diff -uprk.orig stmpclean-0.3.orig/FAQ stmpclean-0.3/FAQ --- stmpclean-0.3.orig/FAQ 2000-10-17 21:53:58 +0400 +++ stmpclean-0.3/FAQ 2003-10-26 17:13:52 +0300 @@ -10,8 +10,7 @@ $Id: FAQ,v 1.3 2000/10/17 17:53:58 shalu > stmpclean[24030]: RACE?: unlink("tcal") in /var/spool/mail: > Permission denied, exiting -Stmpclean has not been designed to be run over mail spools or home -directories! +Stmpclean has not been designed to be run over mail spools! You should *not* run stmpclean on /var/spool/mail. You are risking deleting precious mail files. You're going to delete *all* mail in diff -uprk.orig stmpclean-0.3.orig/Makefile stmpclean-0.3/Makefile --- stmpclean-0.3.orig/Makefile 2003-10-26 17:13:06 +0300 +++ stmpclean-0.3/Makefile 2003-10-26 17:15:44 +0300 @@ -4,8 +4,8 @@ CC = gcc LD = gcc -CFLAGS = -O2 -fomit-frame-pointer -Wall -W -pedantic -LDFLAGS = -s +CFLAGS = $(RPM_OPT_FLAGS) -W -Werror -D_FILE_OFFSET_BITS=64 +LDFLAGS = DESTDIR = PREFIX = /usr/local @@ -16,9 +16,9 @@ all: stmpclean stmpclean.0 install: stmpclean mkdir -p -m 755 $(DESTDIR)$(SBINDIR) $(DESTDIR)$(MANDIR)/man8 - install -m 700 stmpclean $(DESTDIR)$(SBINDIR)/ + install -m 755 stmpclean $(DESTDIR)$(SBINDIR)/ ln -s stmpclean $(DESTDIR)$(SBINDIR)/tmpwatch - install -m 644 stmpclean.8 tmpwatch.8 $(DESTDIR)$(MANDIR)/man8/ + install -p -m 644 stmpclean.8 tmpwatch.8 $(DESTDIR)$(MANDIR)/man8/ stmpclean.o: stmpclean.c $(CC) $(CFLAGS) -c stmpclean.c diff -uprk.orig stmpclean-0.3.orig/stmpclean.c stmpclean-0.3/stmpclean.c --- stmpclean-0.3.orig/stmpclean.c 2003-10-26 17:13:06 +0300 +++ stmpclean-0.3/stmpclean.c 2003-10-26 17:13:23 +0300 @@ -82,6 +82,9 @@ static const char rcsid[] = #define GETCWD {if (getcwd(cwd, sizeof(cwd)) == NULL) \ strcpy(cwd, "/FULL/PATH/TOO/LONG");} +/* Start uid/gid values. */ +static gid_t start_gid = -1; +static uid_t start_uid = -1; /* Are we emulating tmpwatch? */ static int am_tmpwatch; /* Time at the start of the program, in seconds since beginning of epoch. */ @@ -182,29 +185,37 @@ parse_time(timespec) } /* Set euid to UID, egid to GID. Exit unsuccessfully on error. */ -void -setecreds(uid, gid) - uid_t uid; - gid_t gid; +static void +setecreds(uid_t uid, id_t gid, const char *dname, const char *fname) { - gid_t groups[2]; + if (start_uid == 0 && setegid(gid)) { + syslog(LOG_ERR, + "processing \"%s/%s\": cannot set EGID to %u: %m, exiting", + dname, fname, gid); + exit(1); + } + if (seteuid(uid)) { + syslog(LOG_ERR, + "processing \"%s/%s\": cannot set EUID to %u: %m, exiting", + dname, fname, uid); + exit(1); + } +} - groups[0] = groups[1] = gid; - if (geteuid()) { - if (seteuid(uid) || setegid(gid) || - (uid == 0 && setgroups(1, groups))) { - syslog(LOG_ERR, "cannot set EUID/EGID to %d/%d, exiting", - uid, gid); - exit(1); - } - } else { - if (setgroups(1, groups) || setegid(gid) || seteuid(uid)) { - syslog(LOG_ERR, "cannot set EUID/EGID to %d/%d, exiting", - uid, gid); - exit(1); - } +/* Set euid/egid to start values. Exit unsuccessfully on error. */ +static void +recover_creds(void) +{ + if (setegid(start_gid)) { + syslog(LOG_ERR, "cannot set EGID to %u: %m, exiting", + start_gid); + exit(1); + } + if (seteuid(start_uid)) { + syslog(LOG_ERR, "cannot set EUID to %u: %m, exiting", + start_uid); + exit(1); } - return; } /* @@ -345,16 +356,17 @@ clean_dir(dir, depth, specified) /* Looking at an empty directory. */ if (now - st.st_atime > minage && st.st_uid) { /* An old non-root owned directory. */ - setecreds(st.st_uid, st.st_gid); + setecreds(st.st_uid, st.st_gid, dir, + dp->d_name); if (rmdir(dp->d_name) == -1 && errno != ENOENT && errno != EACCES && errno != EPERM) { if (errno == ENOTEMPTY) { - setecreds(0, 0); + recover_creds(); goto notempty; } - setecreds(0, 0); + recover_creds(); GETCWD; syslog(LOG_ERR, "RACE?: rmdir" "(\"%s\") in %s: %m, " @@ -367,7 +379,7 @@ clean_dir(dir, depth, specified) "removed dir %s/%s", cwd, dp->d_name); } - setecreds(0, 0); + recover_creds(); } } else { notempty: @@ -388,12 +400,13 @@ notempty: * Old non-root owned regular file or * symlink. */ - setecreds(st.st_uid, st.st_gid); + setecreds(st.st_uid, st.st_gid, dir, + dp->d_name); if (unlink(dp->d_name) == -1 && errno != ENOENT && errno != EACCES && errno != EPERM) { - setecreds(0, 0); + recover_creds(); GETCWD; syslog(LOG_ERR, "RACE?: unlink(\"%s\")" "in %s: %m, exiting", @@ -405,7 +418,7 @@ notempty: syslog(LOG_INFO, "removed file %s/%s", cwd, dp->d_name); } - setecreds(0, 0); + recover_creds(); } } } @@ -483,6 +496,12 @@ main(argc, argv) "cannot disable core dumps: setrlimit: %m, exiting"); exit(1); } + start_gid = getegid(); + start_uid = geteuid(); + if (start_uid == 0 && setgroups(0, NULL)) { + syslog(LOG_ERR, "setgroups failed: %m, exiting"); + exit(1); + } for (i = 0; i < argc; i++) if (argv[i][0] != '/') { syslog(LOG_ERR, "directories to clean must be"