Use timespec throughout.

This commit is contained in:
Todd C. Miller
2004-09-08 15:48:23 +00:00
parent 5748664575
commit 0f056c0d5f
6 changed files with 85 additions and 38 deletions

20
check.c
View File

@@ -149,11 +149,9 @@ update_timestamp(timestampdir, timestampfile)
char *timestampdir; char *timestampdir;
char *timestampfile; char *timestampfile;
{ {
time_t now = time(NULL);
if (timestamp_uid != 0) if (timestamp_uid != 0)
set_perms(PERM_TIMESTAMP); set_perms(PERM_TIMESTAMP);
if (touch(-1, timestampfile ? timestampfile : timestampdir, now, 0) == -1) { if (touch(-1, timestampfile ? timestampfile : timestampdir, NULL) == -1) {
if (timestampfile) { if (timestampfile) {
int fd = open(timestampfile, O_WRONLY|O_CREAT|O_TRUNC, 0600); int fd = open(timestampfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
@@ -498,6 +496,7 @@ timestamp_status(timestampdir, timestampfile, user, make_dirs)
if (def_timestamp_timeout < 0 && sb.st_mtime != 0) if (def_timestamp_timeout < 0 && sb.st_mtime != 0)
status = TS_CURRENT; status = TS_CURRENT;
else { else {
/* XXX - should use timespec here */
now = time(NULL); now = time(NULL);
if (def_timestamp_timeout && if (def_timestamp_timeout &&
now - sb.st_mtime < 60 * def_timestamp_timeout) { now - sb.st_mtime < 60 * def_timestamp_timeout) {
@@ -532,15 +531,14 @@ void
remove_timestamp(remove) remove_timestamp(remove)
int remove; int remove;
{ {
char *timestampdir; struct timespec ts;
char *timestampfile; char *timestampdir, *timestampfile, *path;
char *ts;
int status; int status;
build_timestamp(&timestampdir, &timestampfile); build_timestamp(&timestampdir, &timestampfile);
status = timestamp_status(timestampdir, timestampfile, user_name, FALSE); status = timestamp_status(timestampdir, timestampfile, user_name, FALSE);
if (status == TS_OLD || status == TS_CURRENT) { if (status == TS_OLD || status == TS_CURRENT) {
ts = timestampfile ? timestampfile : timestampdir; path = timestampfile ? timestampfile : timestampdir;
if (remove) { if (remove) {
if (timestampfile) if (timestampfile)
status = unlink(timestampfile); status = unlink(timestampfile);
@@ -548,12 +546,14 @@ remove_timestamp(remove)
status = rmdir(timestampdir); status = rmdir(timestampdir);
if (status == -1 && errno != ENOENT) { if (status == -1 && errno != ENOENT) {
log_error(NO_EXIT, "can't remove %s (%s), will reset to Epoch", log_error(NO_EXIT, "can't remove %s (%s), will reset to Epoch",
ts, strerror(errno)); path, strerror(errno));
remove = FALSE; remove = FALSE;
} }
} else {
timespecclear(&ts);
if (touch(-1, path, &ts) == -1)
err(1, "can't reset %s to Epoch", path);
} }
if (!remove && touch(-1, ts, 0, 0) == -1)
err(1, "can't reset %s to Epoch", ts);
} }
free(timestampdir); free(timestampdir);

View File

@@ -239,4 +239,22 @@ struct timespec {
}; };
#endif /* !HAVE_TIMESPEC */ #endif /* !HAVE_TIMESPEC */
#ifndef timespecclear
# define timespecclear(ts) (ts)->tv_sec = (ts)->tv_nsec = 0
#endif
#ifndef timespecisset
# define timespecisset(ts) ((ts)->tv_sec || (ts)->tv_nsec)
#endif
#ifndef timespecsub
# define timespecsub(minuend, subrahend, difference) \
do { \
(difference)->tv_sec = (minuend)->tv_sec - (subrahend)->tv_sec; \
(difference)->tv_nsec = (minuend)->tv_nsec - (subrahend)->tv_nsec; \
if ((difference)->tv_nsec < 0) { \
(difference)->tv_nsec += 1000000000L; \
(difference)->tv_sec--; \
} \
} while (0)
#endif
#endif /* _SUDO_COMPAT_H */ #endif /* _SUDO_COMPAT_H */

View File

@@ -43,24 +43,25 @@ static const char rcsid[] = "$Sudo$";
* Update the access and modify times on an fd or file. * Update the access and modify times on an fd or file.
*/ */
int int
touch(fd, path, sec, nsec) touch(fd, path, tsp)
int fd; int fd;
char *path; char *path;
time_t sec; struct timespec *tsp;
long nsec;
{ {
struct timeval times[2]; struct timeval times[2];
times[0].tv_sec = times[1].tv_sec = sec; if (tsp != NULL) {
times[0].tv_usec = times[1].tv_usec = nsec; times[0].tv_sec = times[1].tv_sec = tsp->tv_sec;
times[0].tv_usec = times[1].tv_usec = tsp->tv_nsec / 1000;
}
#if defined(HAVE_FUTIME) || defined(HAVE_FUTIMES) #if defined(HAVE_FUTIME) || defined(HAVE_FUTIMES)
if (fd != -1) if (fd != -1)
return(futimes(fd, times)); return(futimes(fd, tsp ? times : NULL));
else else
#endif #endif
if (path != NULL) if (path != NULL)
return(utimes(path, times)); return(utimes(path, tsp ? times : NULL));
else else
return(-1); return(-1);
} }

3
sudo.h
View File

@@ -229,13 +229,14 @@ void dump_defaults __P((void));
void dump_auth_methods __P((void)); void dump_auth_methods __P((void));
void init_envtables __P((void)); void init_envtables __P((void));
int lock_file __P((int, int)); int lock_file __P((int, int));
int touch __P((int, char *, time_t, long)); int touch __P((int, char *, struct timespec *));
int user_is_exempt __P((void)); int user_is_exempt __P((void));
void set_fqdn __P((void)); void set_fqdn __P((void));
int set_runaspw __P((char *)); int set_runaspw __P((char *));
char *sudo_getepw __P((const struct passwd *)); char *sudo_getepw __P((const struct passwd *));
int pam_prep_user __P((struct passwd *)); int pam_prep_user __P((struct passwd *));
void zero_bytes __P((volatile VOID *, size_t)); void zero_bytes __P((volatile VOID *, size_t));
int gettime __P((struct timespec *));
YY_DECL; YY_DECL;
/* Only provide extern declarations outside of sudo.c. */ /* Only provide extern declarations outside of sudo.c. */

View File

@@ -76,6 +76,7 @@ int sudo_edit(argc, argv)
int i, ac, ofd, nargc, rval; int i, ac, ofd, nargc, rval;
sigaction_t sa; sigaction_t sa;
struct stat sb; struct stat sb;
struct timespec ts1, ts2;
struct tempfile { struct tempfile {
char *tfile; char *tfile;
char *ofile; char *ofile;
@@ -162,11 +163,12 @@ int sudo_edit(argc, argv)
* file's mtime. It is better than nothing and we only use the info * file's mtime. It is better than nothing and we only use the info
* to determine whether or not a file has been modified. * to determine whether or not a file has been modified.
*/ */
if (touch(tf[i].tfd, NULL, tf[i].ots.tv_sec, tf[i].ots.tv_nsec) == -1) { if (touch(tf[i].tfd, NULL, &tf[i].ots) == -1) {
if (fstat(tf[i].tfd, &sb) == 0) { if (fstat(tf[i].tfd, &sb) == 0) {
tf[i].ots.tv_sec = mtim_getsec(sb); tf[i].ots.tv_sec = mtim_getsec(sb);
tf[i].ots.tv_nsec = mtim_getnsec(sb); tf[i].ots.tv_nsec = mtim_getnsec(sb);
} }
/* XXX - else error? */
} }
#endif #endif
} }
@@ -213,8 +215,10 @@ int sudo_edit(argc, argv)
(void) sigaction(SIGTSTP, &saved_sa_tstp, NULL); (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL);
/* /*
* Fork and exec the editor as with the invoking user's creds. * Fork and exec the editor as with the invoking user's creds,
* keeping track of the time spent in the editor.
*/ */
gettime(&ts1);
kidpid = fork(); kidpid = fork();
if (kidpid == -1) { if (kidpid == -1) {
warn("fork"); warn("fork");
@@ -252,6 +256,7 @@ int sudo_edit(argc, argv)
break; break;
} }
} while (pid != -1 || errno == EINTR); } while (pid != -1 || errno == EINTR);
gettime(&ts2);
if (pid == -1 || !WIFEXITED(i)) if (pid == -1 || !WIFEXITED(i))
rval = 1; rval = 1;
else else
@@ -270,10 +275,17 @@ int sudo_edit(argc, argv)
if (tf[i].osize == sb.st_size && if (tf[i].osize == sb.st_size &&
tf[i].ots.tv_sec == mtim_getsec(sb) && tf[i].ots.tv_sec == mtim_getsec(sb) &&
tf[i].ots.tv_nsec == mtim_getnsec(sb)) { tf[i].ots.tv_nsec == mtim_getnsec(sb)) {
warnx("%s unchanged", tf[i].ofile); /*
unlink(tf[i].tfile); * If mtime and size match but the user spent no measurable
close(tf[i].tfd); * time in the editor we can't tell if the file was changed.
continue; */
timespecsub(&ts1, &ts2, &ts2);
if (timespecisset(&ts2)) {
warnx("%s unchanged", tf[i].ofile);
unlink(tf[i].tfile);
close(tf[i].tfd);
continue;
}
} }
} }
#endif #endif

View File

@@ -33,6 +33,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h>
#ifndef __TANDEM #ifndef __TANDEM
# include <sys/file.h> # include <sys/file.h>
#endif #endif
@@ -130,8 +131,10 @@ main(argc, argv)
int stmp_fd; /* stmp file descriptor */ int stmp_fd; /* stmp file descriptor */
int n; /* length parameter */ int n; /* length parameter */
int ch; /* getopt char */ int ch; /* getopt char */
time_t now; /* time now */ struct timespec ts1, ts2; /* time before and after edit */
struct stat stmp_sb, sudoers_sb; /* to check for changes */ struct timespec sudoers_mtim; /* starting mtime of sudoers file */
off_t sudoers_size; /* starting size of sudoers file */
struct stat sb; /* stat buffer */
/* Warn about aliases that are used before being defined. */ /* Warn about aliases that are used before being defined. */
pedantic = 1; pedantic = 1;
@@ -192,11 +195,14 @@ main(argc, argv)
if (!lock_file(sudoers_fd, SUDO_TLOCK)) if (!lock_file(sudoers_fd, SUDO_TLOCK))
errx(1, "sudoers file busy, try again later"); errx(1, "sudoers file busy, try again later");
#ifdef HAVE_FSTAT #ifdef HAVE_FSTAT
if (fstat(sudoers_fd, &sudoers_sb) == -1) if (fstat(sudoers_fd, &sb) == -1)
#else #else
if (stat(sudoers, &sudoers_sb) == -1) if (stat(sudoers, &sb) == -1)
#endif #endif
err(1, "can't stat %s", sudoers); err(1, "can't stat %s", sudoers);
sudoers_size = sb.st_size;
sudoers_mtim.tv_sec = mtim_getsec(sb);
sudoers_mtim.tv_nsec = mtim_getnsec(sb);
/* /*
* Open sudoers temp file. * Open sudoers temp file.
@@ -209,7 +215,7 @@ main(argc, argv)
setup_signals(); setup_signals();
/* Copy sudoers -> stmp and reset the mtime */ /* Copy sudoers -> stmp and reset the mtime */
if (sudoers_sb.st_size) { if (sudoers_size) {
while ((n = read(sudoers_fd, buf, sizeof(buf))) > 0) while ((n = read(sudoers_fd, buf, sizeof(buf))) > 0)
if (write(stmp_fd, buf, n) != n) if (write(stmp_fd, buf, n) != n)
err(1, "write error"); err(1, "write error");
@@ -220,7 +226,7 @@ main(argc, argv)
write(stmp_fd, buf, 1); write(stmp_fd, buf, 1);
} }
(void) touch(stmp_fd, stmp, sudoers_sb.st_mtime, 0); (void) touch(stmp_fd, stmp, &sudoers_mtim);
(void) close(stmp_fd); (void) close(stmp_fd);
/* Parse sudoers to pull in editor and env_editor conf values. */ /* Parse sudoers to pull in editor and env_editor conf values. */
@@ -354,17 +360,18 @@ main(argc, argv)
* XPG4 specifies that vi's exit value is a function of the * XPG4 specifies that vi's exit value is a function of the
* number of errors during editing (?!?!). * number of errors during editing (?!?!).
*/ */
now = time(NULL); gettime(&ts1);
if (run_command(Editor, av) != -1) { if (run_command(Editor, av) != -1) {
gettime(&ts2);
/* /*
* Sanity checks. * Sanity checks.
*/ */
if (stat(stmp, &stmp_sb) < 0) { if (stat(stmp, &sb) < 0) {
warnx("cannot stat temporary file (%s), %s unchanged", warnx("cannot stat temporary file (%s), %s unchanged",
stmp, sudoers); stmp, sudoers);
Exit(-1); Exit(-1);
} }
if (stmp_sb.st_size == 0) { if (sb.st_size == 0) {
warnx("zero length temporary file (%s), %s unchanged", warnx("zero length temporary file (%s), %s unchanged",
stmp, sudoers); stmp, sudoers);
Exit(-1); Exit(-1);
@@ -412,7 +419,7 @@ main(argc, argv)
switch (whatnow()) { switch (whatnow()) {
case 'Q' : parse_error = FALSE; /* ignore parse error */ case 'Q' : parse_error = FALSE; /* ignore parse error */
break; break;
case 'x' : if (sudoers_sb.st_size == 0) case 'x' : if (sudoers_size == 0)
unlink(sudoers); unlink(sudoers);
Exit(0); Exit(0);
break; break;
@@ -423,10 +430,18 @@ main(argc, argv)
/* /*
* If the user didn't change the temp file, just unlink it. * If the user didn't change the temp file, just unlink it.
*/ */
if (sudoers_sb.st_mtime != now && sudoers_sb.st_mtime == stmp_sb.st_mtime && if (sudoers_size == sb.st_size &&
sudoers_sb.st_size == stmp_sb.st_size) { sudoers_mtim.tv_sec == mtim_getsec(sb) &&
warnx("sudoers file unchanged"); sudoers_mtim.tv_nsec == mtim_getnsec(sb)) {
Exit(0); /*
* If mtime and size match but the user spent no measurable
* time in the editor we can't tell if the file was changed.
*/
timespecsub(&ts1, &ts2, &ts2);
if (timespecisset(&ts2)) {
warnx("sudoers file unchanged");
Exit(0);
}
} }
/* /*