ALT Linux repos
S: | 4.1.20060426-alt10.3 |
5.0: | 4.1.20060426-alt6 |
4.1: | 4.1.20060426-alt4 |
4.0: | 4.1.20060426-alt4 |
3.0: | 4.1.20040916-alt2 |
Group :: System/Servers
RPM: vixie-cron
Main Changelog Spec Patches Sources Download Gear Bugs and FR Repocop
Patch: vixie-cron-4.1.20040916-owl-crond.patch
Download
Download
diff -uprk.orig vixie-cron-4.1.20040916.orig/usr.sbin/cron/cron.8 vixie-cron-4.1.20040916/usr.sbin/cron/cron.8
--- vixie-cron-4.1.20040916.orig/usr.sbin/cron/cron.8 2004-12-18 19:06:54 +0300
+++ vixie-cron-4.1.20040916/usr.sbin/cron/cron.8 2004-12-18 19:07:55 +0300
@@ -181,6 +181,8 @@ logs via
.Bl -tag -width "/var/spool/cron/.sock" -compact
.It Pa /etc/crontab
system crontab file
+.It Pa /etc/cron.d
+directory containing system crontab files
.It Pa /var/spool/at
directory containing
.Xr at 1
diff -uprk.orig vixie-cron-4.1.20040916.orig/usr.sbin/cron/database.c vixie-cron-4.1.20040916/usr.sbin/cron/database.c
--- vixie-cron-4.1.20040916.orig/usr.sbin/cron/database.c 2004-06-22 07:15:33 +0400
+++ vixie-cron-4.1.20040916/usr.sbin/cron/database.c 2004-12-18 19:12:53 +0300
@@ -32,6 +32,18 @@ static char const rcsid[] = "$OpenBSD: d
#define HASH(a,b) ((a)+(b))
+struct spooldir {
+ char *path;
+ char *uname;
+ char *fname;
+};
+
+static struct spooldir spools[] = {
+ {SPOOL_DIR, NULL, NULL},
+ {"/etc/cron.d", "root", "*system*"},
+ {NULL, NULL, NULL}
+};
+
static void process_crontab(const char *, const char *,
const char *, struct stat *,
cron_db *, cron_db *);
@@ -44,22 +56,27 @@ load_database(cron_db *old_db) {
DIR *dir;
user *u, *nu;
- Debug(DLOAD, ("[%ld] load_database()\n", (long)getpid()))
+ struct spooldir *p = spools;
+ time_t maxtime;
- /* before we start loading any data, do a stat on SPOOL_DIR
- * so that if anything changes as of this moment (i.e., before we've
- * cached any of the database), we'll see the changes next time.
- */
- if (stat(SPOOL_DIR, &statbuf) < OK) {
- log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);
- (void) exit(ERROR_EXIT);
- }
+ Debug(DLOAD, ("[%ld] load_database()\n", (long)getpid()))
/* track system crontab file
*/
if (stat(SYSCRONTAB, &syscron_stat) < OK)
syscron_stat.st_mtime = 0;
+ maxtime = syscron_stat.st_mtime;
+ while (p->path) {
+ if (stat(p->path, &statbuf) < OK) {
+ log_it("CRON", getpid(), "STAT FAILED", p->path);
+ (void) exit(ERROR_EXIT);
+ }
+ if (statbuf.st_mtime > maxtime)
+ maxtime = statbuf.st_mtime;
+ p++;
+ }
+
/* if spooldir's mtime has not changed, we don't need to fiddle with
* the database.
*
@@ -67,7 +84,7 @@ load_database(cron_db *old_db) {
* so is guaranteed to be different than the stat() mtime the first
* time this function is called.
*/
- if (old_db->mtime == HASH(statbuf.st_mtime, syscron_stat.st_mtime)) {
+ if (old_db->mtime == maxtime) {
Debug(DLOAD, ("[%ld] spool dir mtime unch, no load needed.\n",
(long)getpid()))
return;
@@ -78,46 +95,56 @@ load_database(cron_db *old_db) {
* actually changed. Whatever is left in the old database when
* we're done is chaff -- crontabs that disappeared.
*/
- new_db.mtime = HASH(statbuf.st_mtime, syscron_stat.st_mtime);
+ new_db.mtime = maxtime;
new_db.head = new_db.tail = NULL;
if (syscron_stat.st_mtime) {
- process_crontab(ROOT_USER, NULL, SYSCRONTAB, &syscron_stat,
+ process_crontab(ROOT_USER, "*system*", SYSCRONTAB, &syscron_stat,
&new_db, old_db);
}
- /* we used to keep this dir open all the time, for the sake of
- * efficiency. however, we need to close it in every fork, and
- * we fork a lot more often than the mtime of the dir changes.
- */
- if (!(dir = opendir(SPOOL_DIR))) {
- log_it("CRON", getpid(), "OPENDIR FAILED", SPOOL_DIR);
- (void) exit(ERROR_EXIT);
- }
-
- while (NULL != (dp = readdir(dir))) {
- char fname[MAXNAMLEN+1], tabname[MAXNAMLEN];
-
- /* avoid file names beginning with ".". this is good
- * because we would otherwise waste two guaranteed calls
- * to getpwnam() for . and .., and also because user names
- * starting with a period are just too nasty to consider.
- */
- if (dp->d_name[0] == '.')
- continue;
-
- if (strlcpy(fname, dp->d_name, sizeof fname) >= sizeof fname)
- continue; /* XXX log? */
-
- if (snprintf(tabname, sizeof tabname, "%s/%s", SPOOL_DIR, fname) >=
- sizeof(tabname))
- continue; /* XXX log? */
-
- process_crontab(fname, fname, tabname,
- &statbuf, &new_db, old_db);
- }
- closedir(dir);
-
+ p = spools;
+ while (p->path) {
+ if (!(dir = opendir(p->path))) {
+ log_it("CRON", getpid(), "OPENDIR FAILED", p->path);
+ (void) exit(ERROR_EXIT);
+ }
+
+ while (NULL != (dp = readdir(dir))) {
+ char fname[MAXNAMLEN+1], tabname[MAXPATHLEN];
+
+ /* Don't try to parse any files containing a dot ('.')
+ * or ending with a tilde ('~'). This catches the case
+ * of '.' and '..', as well as preventing the parsing
+ * of many editor files, temporary files and those
+ * saved by RPM package upgrades.
+ */
+ if ( !dp->d_name[0] /* Shouldn't happen */ ||
+ strchr(dp->d_name, '.') ||
+ dp->d_name[strlen(dp->d_name)-1] == '~')
+ continue;
+
+ if (strlcpy(fname, dp->d_name, sizeof fname) >= sizeof fname)
+ continue; /* XXX log? */
+
+ if (snprintf(tabname, sizeof tabname, "%s/%s", p->path, fname) >=
+ sizeof(tabname))
+ continue; /* XXX log? */
+
+ process_crontab(p->uname ? p->uname : fname,
+ p->fname ? p->fname : fname,
+ tabname,
+ &statbuf, &new_db, old_db);
+ }
+ closedir(dir);
+ /* we used to keep this dir open all the time, for the sake of
+ * efficiency. however, we need to close it in every fork, and
+ * we fork a lot more often than the mtime of the dir changes.
+ */
+
+ p++;
+ }
+
/* if we don't do this, then when our children eventually call
* getpwnam() in do_command.c's child_process to verify MAILTO=,
* they will screw us up (and v-v).
@@ -180,19 +207,34 @@ process_crontab(const char *uname, const
{
struct passwd *pw = NULL;
int crontab_fd = OK - 1;
+ struct stat lstatbuf;
user *u;
- if (fname == NULL) {
- /* must be set to something for logging purposes.
- */
- fname = "*system*";
- } else if ((pw = getpwnam(uname)) == NULL) {
+ if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) {
/* file doesn't have a user in passwd file.
- */
+ * */
log_it(fname, getpid(), "ORPHAN", "no passwd entry");
goto next_crontab;
}
+ if (lstat(tabname, &lstatbuf) < OK) {
+ log_it(fname, getpid(), "CAN'T LSTAT", tabname);
+ goto next_crontab;
+ }
+ if (!S_ISREG(lstatbuf.st_mode)) {
+ log_it(fname, getpid(), "NOT REGULAR", tabname);
+ goto next_crontab;
+ }
+ if ((!pw && (lstatbuf.st_mode & 07533) != 0400) ||
+ (pw && (lstatbuf.st_mode & 07577) != 0400)) {
+ log_it(fname, getpid(), "BAD FILE MODE", tabname);
+ goto next_crontab;
+ }
+ if (lstatbuf.st_nlink != 1) {
+ log_it(fname, getpid(), "BAD LINK COUNT", tabname);
+ goto next_crontab;
+ }
+
if ((crontab_fd = open(tabname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < OK) {
/* crontab not accessible?
*/
@@ -208,7 +250,8 @@ process_crontab(const char *uname, const
log_it(fname, getpid(), "NOT REGULAR", tabname);
goto next_crontab;
}
- if ((statbuf->st_mode & 07577) != 0400) {
+ if ((!pw && (statbuf->st_mode & 07533) != 0400) ||
+ (pw && (statbuf->st_mode & 07577) != 0400)) {
log_it(fname, getpid(), "BAD FILE MODE", tabname);
goto next_crontab;
}
@@ -221,6 +264,11 @@ process_crontab(const char *uname, const
log_it(fname, getpid(), "BAD LINK COUNT", tabname);
goto next_crontab;
}
+ if (lstatbuf.st_dev != statbuf->st_dev ||
+ lstatbuf.st_ino != statbuf->st_ino) {
+ log_it(fname, getpid(), "FILE CHANGED DURING OPEN", tabname);
+ goto next_crontab;
+ }
Debug(DLOAD, ("\t%s:", fname))
u = find_user(old_db, fname);