[Pkg-cron-devel] [SCM] Git repository for pkg-cron branch, sf3, updated. debian/3.0pl1-109-20-gde88d23
Christian Kastner
debian at kvr.at
Sat Sep 24 22:26:49 UTC 2011
The following commit has been merged in the sf3 branch:
commit c5ac3932fdb55fa678490be31f5ac83c67fb146a
Author: Christian Kastner <debian at kvr.at>
Date: Sun Sep 25 00:04:48 2011 +0200
Recovery from symlink, type, mode, owner, syntax errors
The previous patch for this, features/recover-from-broken-symlinks,
was dropped (the essential parts were integrated into this patch).
diff --git a/debian/patches/features/recover-from-broken-symlinks b/debian/patches/features/recover-from-broken-symlinks
deleted file mode 100644
index 52fb96b..0000000
--- a/debian/patches/features/recover-from-broken-symlinks
+++ /dev/null
@@ -1,65 +0,0 @@
-Subject: Recover from broken symlinks in /etc/cron.d
-Author: Christian Kastner <debian at kvr.at
-Last-Update: 2010-04-19
-
-The way the current power-management-friendly change detection logic notices
-changes to /etc/cron.d, broken symlinks do not get added back once they are
-restored again.
-This is only relevant to /etc/cron.d because SPOOL_DIR does not allow symlinks.
-
-Bug-Debian: http://bugs.debian.org/433609
-Index: patched/database.c
-===================================================================
---- patched.orig/database.c 2010-05-06 18:19:01.607560756 +0200
-+++ patched/database.c 2010-05-06 18:19:02.884526570 +0200
-@@ -126,7 +126,8 @@
- if (stat(syscrond_fname, &syscrond_file_stat) < OK)
- syscrond_file_stat.st_mtime = 0;
-
-- if (syscrond_file_stat.st_mtime != systab->mtime) {
-+ if (syscrond_file_stat.st_mtime != systab->mtime ||
-+ systab->mtime == 0) {
- syscrond_change = 1;
- }
-
-@@ -381,9 +382,38 @@
- }
- if ((crontab_fd = open(tabname, O_RDONLY, 0)) < OK) {
- /* crontab not accessible?
-+
-+ If tabname is a regular file, this error is bad so we skip
-+ it instead of adding it to the new DB. If it's a symlink,
-+ it's most probably just broken, so we emit a warning.
-+ Then we re-add the old crontab to the new DB, but only after
-+ removing all entries and resetting its mtime. Once the link
-+ is fixed, it will get picked up and processed again.
- */
-- log_it(fname, getpid(), "CAN'T OPEN", tabname);
-- goto next_crontab;
-+ if (S_ISREG(statbuf->st_mode)) {
-+ log_it(fname, getpid(), "CAN'T OPEN", tabname);
-+ goto next_crontab;
-+ } else {
-+ log_it(fname, getpid(), "CAN'T OPEN SYMLINK", tabname);
-+
-+ u = find_user(old_db, fname);
-+ if (u != NULL) {
-+ Debug(DLOAD, ("\t%s: [using placeholder]\n", fname))
-+ unlink_user(old_db, u);
-+
-+ if (u->crontab != NULL) {
-+ entry *e, *ne;
-+ for (e = u->crontab; e != NULL; e = ne) {
-+ ne = e->next;
-+ free_entry(e);
-+ }
-+ }
-+ u->crontab = NULL;
-+ u->mtime = 0;
-+ link_user(new_db, u);
-+ goto next_crontab;
-+ }
-+ }
- }
-
- if (fstat(crontab_fd, statbuf) < OK) {
diff --git a/debian/patches/features/recover-from-errors b/debian/patches/features/recover-from-errors
new file mode 100644
index 0000000..f4dd3c5
--- /dev/null
+++ b/debian/patches/features/recover-from-errors
@@ -0,0 +1,188 @@
+Subject: Recover from errors in /etc/cron.d
+Author: Christian Kastner <debian at kvr.at
+
+The way the current power-management-friendly change detection logic notices
+changes to /etc/cron.d, files with mode errors, files with syntax errors and
+broken symlinks do not get added back once the offending issue is resolved.
+This patch amends cron to recover from such errors.
+
+The symlink recovery is only relevant to /etc/cron.d because SPOOL_DIR does
+not allow symlinks.
+
+Bug-Debian: http://bugs.debian.org/433609
+Bug-Debian: http://bugs.debian.org/625495
+Bug-Debian: http://bugs.debian.org/627859
+Last-Update: 2011-09-24
+Index: sf3/database.c
+===================================================================
+--- sf3.orig/database.c 2011-09-24 00:54:05.720004760 +0200
++++ sf3/database.c 2011-09-24 00:54:44.992004765 +0200
+@@ -29,6 +29,7 @@
+ #undef __USE_GNU
+ #include <sys/stat.h>
+ #include <sys/file.h>
++#include <time.h>
+
+ #define TMAX(a,b) ((a)>(b)?(a):(b))
+
+@@ -52,6 +53,9 @@
+ static int valid_name (char *filename);
+ static user *get_next_system_crontab __P((user *));
+ #endif
++
++void force_rescan_user(cron_db *old_db, cron_db *new_db, const char *fname, time_t old_mtime);
++
+ void
+ load_database(old_db)
+ cron_db *old_db;
+@@ -126,7 +130,8 @@
+ if (stat(syscrond_fname, &syscrond_file_stat) < OK)
+ syscrond_file_stat.st_mtime = 0;
+
+- if (syscrond_file_stat.st_mtime != systab->mtime) {
++ if (syscrond_file_stat.st_mtime != systab->mtime ||
++ systab->mtime == 0) {
+ syscrond_change = 1;
+ }
+
+@@ -356,10 +361,9 @@
+ }
+ /* Check to make sure that the crontab is owned by the correct user
+ (or root) */
+-
+- if (statbuf->st_uid != pw->pw_uid &&
+- statbuf->st_uid != ROOT_UID) {
++ if (statbuf->st_uid != pw->pw_uid && statbuf->st_uid != ROOT_UID) {
+ log_it(fname, getpid(), "WRONG FILE OWNER", tabname);
++ force_rescan_user(old_db, new_db, fname, 0);
+ goto next_crontab;
+ }
+
+@@ -372,12 +376,14 @@
+ /* Check to make sure that the crontab's permissions are secure */
+ if ((statbuf->st_mode & 07777) != 0600) {
+ log_it(fname, getpid(), "INSECURE MODE (mode 0600 expected)", tabname);
++ force_rescan_user(old_db, new_db, fname, 0);
+ goto next_crontab;
+ }
+
+ /* Check to make sure that there are no hardlinks to the crontab */
+ if (statbuf->st_nlink != 1) {
+ log_it(fname, getpid(), "NUMBER OF HARD LINKS > 1", tabname);
++ force_rescan_user(old_db, new_db, fname, 0);
+ goto next_crontab;
+ }
+ } else {
+@@ -389,13 +395,25 @@
+ }
+ if (S_ISLNK(statbuf->st_mode) && statbuf->st_uid != ROOT_UID) {
+ log_it(fname, getpid(), "WRONG SYMLINK OWNER", tabname);
++ force_rescan_user(old_db, new_db, fname, 0);
+ goto next_crontab;
+ }
+ if ((crontab_fd = open(tabname, O_RDONLY, 0)) < OK) {
+ /* crontab not accessible?
++
++ If tabname is a symlink, it's most probably just broken, so
++ we force a rescan. Once the link is fixed, it will get picked
++ up and processed again. If tabname is a regular file, this
++ error is bad so we skip it instead.
+ */
+- log_it(fname, getpid(), "CAN'T OPEN", tabname);
+- goto next_crontab;
++ if (S_ISLNK(statbuf->st_mode)) {
++ log_it(fname, getpid(), "CAN'T OPEN SYMLINK", tabname);
++ force_rescan_user(old_db, new_db, fname, 0);
++ goto next_crontab;
++ } else {
++ log_it(fname, getpid(), "CAN'T OPEN", tabname);
++ goto next_crontab;
++ }
+ }
+
+ if (fstat(crontab_fd, statbuf) < OK) {
+@@ -406,6 +424,7 @@
+ /* Check to make sure that the crontab is owned by root */
+ if (statbuf->st_uid != ROOT_UID) {
+ log_it(fname, getpid(), "WRONG FILE OWNER", tabname);
++ force_rescan_user(old_db, new_db, fname, 0);
+ goto next_crontab;
+ }
+
+@@ -421,6 +440,7 @@
+ */
+ if ((statbuf->st_mode & S_IWGRP) || (statbuf->st_mode & S_IWOTH)) {
+ log_it(fname, getpid(), "INSECURE MODE (group/other writable)", tabname);
++ force_rescan_user(old_db, new_db, fname, 0);
+ goto next_crontab;
+ }
+ /* Technically, we should also check whether the parent dir is
+@@ -433,6 +453,7 @@
+ /* Check to make sure that there are no hardlinks to the crontab */
+ if (statbuf->st_nlink != 1) {
+ log_it(fname, getpid(), "NUMBER OF HARD LINKS > 1", tabname);
++ force_rescan_user(old_db, new_db, fname, 0);
+ goto next_crontab;
+ }
+ }
+@@ -471,7 +492,16 @@
+ if (u != NULL) {
+ u->mtime = statbuf->st_mtime;
+ link_user(new_db, u);
+- }
++ } else {
++ /* The crontab we attempted to load contains a syntax error. A
++ * fix won't get picked up by the regular change detection
++ * code, so we force a rescan. statbuf->st_mtime still contains
++ * the file's mtime, so we use it to rescan only when an update
++ * has actually taken place.
++ */
++ force_rescan_user(old_db, new_db, fname, statbuf->st_mtime);
++ }
++
+
+ next_crontab:
+ if (crontab_fd >= OK) {
+@@ -532,3 +562,42 @@
+ }
+
+ #endif
++
++/* Force rescan of a crontab the next time cron wakes up
++ *
++ * cron currently only detects changes caused by an mtime update; it does not
++ * detect other attribute changes such as UID or mode. To allow cron to recover
++ * from errors of that nature as well, this function removes the crontab from
++ * the old DB (if present there) and adds an empty crontab to the new DB with
++ * a given mtime. Specifying mtime as 0 will force a rescan the next time the
++ * daemon wakes up.
++ */
++void
++force_rescan_user(cron_db *old_db, cron_db *new_db, const char *fname, time_t old_mtime)
++{
++ user *u;
++
++ /* Remove from old DB and free resources */
++ u = find_user(old_db, fname);
++ if (u != NULL) {
++ Debug(DLOAD, (" [delete old data]"))
++ unlink_user(old_db, u);
++ free_user(u);
++ }
++
++ /* Allocate an empty crontab with the specified mtime, add it to new DB */
++ if ((u = (user *) malloc(sizeof(user))) == NULL) {
++ errno = ENOMEM;
++ }
++ if ((u->name = strdup(fname)) == NULL) {
++ free(u);
++ errno = ENOMEM;
++ }
++ u->mtime = old_mtime;
++ u->crontab = NULL;
++#ifdef WITH_SELINUX
++ u->scontext = NULL;
++#endif
++ Debug(DLOAD, ("\t%s: [added empty placeholder to force rescan]\n", fname))
++ link_user(new_db, u);
++}
diff --git a/debian/patches/series b/debian/patches/series
index 68101c6..49e5316 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -54,7 +54,7 @@ features/dont-fail-on-missing-MTA
features/no-argument-is-stdin
features/dont-die-on-missing-dirs
features/crontab-refuse-eof-without-nl
-features/recover-from-broken-symlinks
+features/recover-from-errors
features/backport-envparser
other/changes-to-upstream-README
other/changes-to-cron-8
--
Git repository for pkg-cron
More information about the Pkg-cron-devel
mailing list