]> granicus.if.org Git - sudo/commitdiff
Bring back boot time checking code and zero out time stamp files
authorTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 3 Feb 2014 12:45:27 +0000 (05:45 -0700)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 3 Feb 2014 12:45:27 +0000 (05:45 -0700)
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.

MANIFEST
doc/sudoers.cat
doc/sudoers.man.in
doc/sudoers.mdoc.in
plugins/sudoers/boottime.c [new file with mode: 0644]
plugins/sudoers/sudoers.h
plugins/sudoers/timestamp.c

index 41170534a7e9bebb7194aa0bee4e4efc4d36a284..80c25a8389e31818d3591a288fec9ccff1231948 100644 (file)
--- 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
index 7f11b5c34a9408db36cd6f246c78984ea114d05a..ab524bd41f0457b66de2723a32672783e0da8c59 100644 (file)
@@ -2203,6 +2203,11 @@ S\bSE\bEC\bCU\bUR\bRI\bIT\bTY\bY N\bNO\bOT\bTE\bES\bS
      themselves on systems that allow unprivileged users to change the
      ownership of files they create.
 
+     While the time stamp directory _\bs_\bh_\bo_\bu_\bl_\bd be cleared at reboot time, not all
+     systems contain a _\b/_\bv_\ba_\br_\b/_\br_\bu_\bn directory.  To avoid potential problems,
+     _\bs_\bu_\bd_\bo_\be_\br_\bs 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 _\bs_\bu_\bd_\bo_\be_\br_\bs relies on the system clock for
      time stamp validation, it may be possible on such systems for a user to
@@ -2317,4 +2322,4 @@ D\bDI\bIS\bSC\bCL\bLA\bAI\bIM\bME\bER\bR
      file distributed with s\bsu\bud\bdo\bo 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
index 641cab3678bfb101ec3ce17b60bfd6fed20414c8..841cd18427908f6153d628278c0c88c702193ac1 100644 (file)
@@ -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
index b80a589be591961df619e12da13d7a1b4c35d87f..e6a24df503be5f58fe122cdd56442deb11a92b8c 100644 (file)
@@ -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 (file)
index 0000000..16fb376
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2009-2013 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 <config.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <limits.h>
+#ifdef TIME_WITH_SYS_TIME
+# include <time.h>
+#endif
+#ifndef __linux__
+# if defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME)
+#  include <sys/sysctl.h>
+# elif defined(HAVE_GETUTXID)
+#  include <utmpx.h>
+# elif defined(HAVE_GETUTID)
+#  include <utmp.h>
+# 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
index 7ab39f3ab3bc6971f889eaec7b67bef36b9662b0..3479ea6c64a2e17255182d686ddfe2ea7bb183ec 100644 (file)
@@ -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]);
index 2d643dff83676a4cb8daf8a56d223ea07c671750..21f14d567fbb495bbb312b828bf827c3f61a3425 100644 (file)
@@ -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, &timestamp_key, &entry)) {
        status = TS_MISSING;
        goto done;