[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