From: Todd C. Miller Date: Mon, 3 Feb 2014 12:45:27 +0000 (-0700) Subject: Bring back boot time checking code and zero out time stamp files X-Git-Tag: SUDO_1_8_10^2~60 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7155fc526fedf7ed509fa7e089edd934aced5011;p=sudo Bring back boot time checking code and zero out time stamp files that predate the boot time. This should help systems w/o /var/run where the admin has setup rc.d to clear the timestamp directory. --- diff --git a/MANIFEST b/MANIFEST index 41170534a..80c25a838 100644 --- a/MANIFEST +++ b/MANIFEST @@ -201,6 +201,7 @@ plugins/sudoers/auth/sia.c plugins/sudoers/auth/sudo_auth.c plugins/sudoers/auth/sudo_auth.h plugins/sudoers/base64.c +plugins/sudoers/boottime.c plugins/sudoers/bsm_audit.c plugins/sudoers/bsm_audit.h plugins/sudoers/check.c diff --git a/doc/sudoers.cat b/doc/sudoers.cat index 7f11b5c34..ab524bd41 100644 --- a/doc/sudoers.cat +++ b/doc/sudoers.cat @@ -2203,6 +2203,11 @@ SSEECCUURRIITTYY NNOOTTEESS themselves on systems that allow unprivileged users to change the ownership of files they create. + While the time stamp directory _s_h_o_u_l_d be cleared at reboot time, not all + systems contain a _/_v_a_r_/_r_u_n directory. To avoid potential problems, + _s_u_d_o_e_r_s will ignore time stamp files that date from before the machine + booted on systems where the boot time is available. + Some systems with graphical desktop environments allow unprivileged users to change the system clock. Since _s_u_d_o_e_r_s relies on the system clock for time stamp validation, it may be possible on such systems for a user to @@ -2317,4 +2322,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or http://www.sudo.ws/sudo/license.html for complete details. -Sudo 1.8.10 February 1, 2014 Sudo 1.8.10 +Sudo 1.8.10 February 3, 2014 Sudo 1.8.10 diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in index 641cab367..841cd1842 100644 --- a/doc/sudoers.man.in +++ b/doc/sudoers.man.in @@ -21,7 +21,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.TH "SUDOERS" "@mansectsu@" "February 1, 2014" "Sudo @PACKAGE_VERSION@" "Programmer's Manual" +.TH "SUDOERS" "@mansectsu@" "February 3, 2014" "Sudo @PACKAGE_VERSION@" "Programmer's Manual" .nh .if n .ad l .SH "NAME" @@ -4488,6 +4488,16 @@ this is no longer recommended as it may be possible for a user to create the time stamp themselves on systems that allow unprivileged users to change the ownership of files they create. .PP +While the time stamp directory +\fIshould\fR +be cleared at reboot time, not all systems contain a +\fI/var/run\fR +directory. +To avoid potential problems, +\fIsudoers\fR +will ignore time stamp files that date from before the machine booted +on systems where the boot time is available. +.PP Some systems with graphical desktop environments allow unprivileged users to change the system clock. Since diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in index b80a589be..e6a24df50 100644 --- a/doc/sudoers.mdoc.in +++ b/doc/sudoers.mdoc.in @@ -19,7 +19,7 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.Dd February 1, 2014 +.Dd February 3, 2014 .Dt SUDOERS @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -4128,6 +4128,16 @@ this is no longer recommended as it may be possible for a user to create the time stamp themselves on systems that allow unprivileged users to change the ownership of files they create. .Pp +While the time stamp directory +.Em should +be cleared at reboot time, not all systems contain a +.Pa /var/run +directory. +To avoid potential problems, +.Em sudoers +will ignore time stamp files that date from before the machine booted +on systems where the boot time is available. +.Pp Some systems with graphical desktop environments allow unprivileged users to change the system clock. Since diff --git a/plugins/sudoers/boottime.c b/plugins/sudoers/boottime.c new file mode 100644 index 000000000..16fb376f0 --- /dev/null +++ b/plugins/sudoers/boottime.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2009-2013 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include +#ifdef TIME_WITH_SYS_TIME +# include +#endif +#ifndef __linux__ +# if defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME) +# include +# elif defined(HAVE_GETUTXID) +# include +# elif defined(HAVE_GETUTID) +# include +# endif +#endif /* !__linux__ */ + +#include "missing.h" +#include "sudo_debug.h" + +/* + * Fill in a struct timeval with the time the system booted. + * Returns 1 on success and 0 on failure. + */ + +#if defined(__linux__) +int +get_boottime(struct timeval *tv) +{ + char *ep, *line = NULL; + size_t linesize = 0; + ssize_t len; + FILE * fp; + debug_decl(get_boottime, SUDO_DEBUG_UTIL) + + /* read btime from /proc/stat */ + fp = fopen("/proc/stat", "r"); + if (fp != NULL) { + while ((len = getline(&line, &linesize, fp)) != -1) { + if (strncmp(line, "btime ", 6) == 0) { + long long llval = strtonum(line + 6, 1, LLONG_MAX, NULL); + if (llval > 0) { + tv->tv_sec = (time_t)llval; + tv->tv_usec = 0; + debug_return_bool(1); + } + } + } + fclose(fp); + free(line); + } + + debug_return_bool(0); +} + +#elif defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME) + +int +get_boottime(struct timeval *tv) +{ + size_t size; + int mib[2]; + debug_decl(get_boottime, SUDO_DEBUG_UTIL) + + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + size = sizeof(*tv); + if (sysctl(mib, 2, tv, &size, NULL, 0) != -1) + debug_return_bool(1); + + debug_return_bool(0); +} + +#elif defined(HAVE_GETUTXID) + +int +get_boottime(struct timeval *tv) +{ + struct utmpx *ut, key; + debug_decl(get_boottime, SUDO_DEBUG_UTIL) + + memset(&key, 0, sizeof(key)); + key.ut_type = BOOT_TIME; + setutxent(); + if ((ut = getutxid(&key)) != NULL) { + tv->tv_sec = ut->ut_tv.tv_sec; + tv->tv_usec = ut->ut_tv.tv_usec; + } + endutxent(); + debug_return_bool(ut != NULL); +} + +#elif defined(HAVE_GETUTID) + +int +get_boottime(struct timeval *tv) +{ + struct utmp *ut, key; + debug_decl(get_boottime, SUDO_DEBUG_UTIL) + + memset(&key, 0, sizeof(key)); + key.ut_type = BOOT_TIME; + setutent(); + if ((ut = getutid(&key)) != NULL) { + tv->tv_sec = ut->ut_time; + tv->tv_usec = 0; + } + endutent(); + debug_return_bool(ut != NULL); +} + +#else + +int +get_boottime(struct timeval *tv) +{ + debug_decl(get_boottime, SUDO_DEBUG_UTIL) + debug_return_bool(0); +} +#endif diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 7ab39f3ab..3479ea6c6 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -325,6 +325,9 @@ void sudo_setspent(void); /* timestr.c */ char *get_timestr(time_t, int); +/* boottime.c */ +int get_boottime(struct timeval *); + /* iolog.c */ int io_set_max_sessid(const char *sessid); void io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7]); diff --git a/plugins/sudoers/timestamp.c b/plugins/sudoers/timestamp.c index 2d643dff8..21f14d567 100644 --- a/plugins/sudoers/timestamp.c +++ b/plugins/sudoers/timestamp.c @@ -359,6 +359,7 @@ timestamp_status(struct passwd *pw) struct timestamp_entry entry; struct timespec diff, timeout; int status = TS_ERROR; /* assume the worst */ + struct stat sb; int fd = -1; debug_decl(timestamp_status, SUDO_DEBUG_AUTH) @@ -395,7 +396,6 @@ timestamp_status(struct passwd *pw) } timestamp_key.sid = user_sid; if (def_timestampdir) { - struct stat sb; if (user_ttypath != NULL && stat(user_ttypath, &sb) == 0) { /* tty-based time stamp */ timestamp_key.type = TS_TTY; @@ -415,16 +415,28 @@ timestamp_status(struct passwd *pw) /* Open time stamp file and lock it for exclusive access. */ if (timestamp_uid != 0) set_perms(PERM_TIMESTAMP); - fd = open(timestamp_file, O_RDONLY); + fd = open(timestamp_file, O_RDWR); if (timestamp_uid != 0) restore_perms(); if (fd == -1) { status = TS_MISSING; goto done; } + lock_file(fd, SUDO_LOCK); + + /* Ignore and clear time stamp file if mtime predates boot time. */ + if (fstat(fd, &sb) == 0) { + struct timeval boottime, mtime; + + mtim_get(&sb, &mtime); + if (get_boottime(&boottime) && sudo_timevalcmp(&mtime, &boottime, <)) { + ignore_result(ftruncate(fd, (off_t)0)); + status = TS_MISSING; + goto done; + } + } /* Read existing record, if any. */ - lock_file(fd, SUDO_LOCK); if (!ts_find_record(fd, ×tamp_key, &entry)) { status = TS_MISSING; goto done;