From 1709dc7f77f2d8a3e185c2649fa2a37dc77eaa2d Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 16 Dec 2017 05:53:05 -0700 Subject: [PATCH] In the timestamp record, include the start time of the terminal session leader for tty-based timestamps or the start time of the parent process for ppid-based timestamps. Idea from Duncan Overbruck. --- MANIFEST | 1 + doc/sudoers.cat | 30 ++-- doc/sudoers.man.in | 48 +++--- doc/sudoers.mdoc.in | 48 +++--- plugins/sudoers/Makefile.in | 25 +++- plugins/sudoers/check.h | 5 +- plugins/sudoers/starttime.c | 282 ++++++++++++++++++++++++++++++++++++ plugins/sudoers/timestamp.c | 8 + 8 files changed, 379 insertions(+), 68 deletions(-) create mode 100644 plugins/sudoers/starttime.c diff --git a/MANIFEST b/MANIFEST index 26fb997f7..e8b796dbe 100644 --- a/MANIFEST +++ b/MANIFEST @@ -515,6 +515,7 @@ plugins/sudoers/set_perms.c plugins/sudoers/solaris_audit.c plugins/sudoers/solaris_audit.h plugins/sudoers/sssd.c +plugins/sudoers/starttime.c plugins/sudoers/sudo_nss.c plugins/sudoers/sudo_nss.h plugins/sudoers/sudo_printf.c diff --git a/doc/sudoers.cat b/doc/sudoers.cat index 7761d0e3d..bf3d7c654 100644 --- a/doc/sudoers.cat +++ b/doc/sudoers.cat @@ -2772,19 +2772,21 @@ SSEECCUURRIITTYY NNOOTTEESS with a date greater than current_time + 2 * TIMEOUT will be ignored and ssuuddooeerrss will log and complain. - Since time stamp files live in the file system, they can outlive a user's - login session. As a result, a user may be able to login, run a command - with ssuuddoo after authenticating, logout, login again, and run ssuuddoo without - authenticating so long as the record's time stamp is within 5 minutes (or - whatever value the timeout is set to in the _s_u_d_o_e_r_s file). When the - _t_t_y___t_i_c_k_e_t_s option is enabled, the time stamp record includes the device - number of the terminal the user authenticated with. This provides per- - tty granularity but time stamp records still may outlive the user's - session. The time stamp record also includes the session ID of the - process that last authenticated. This prevents processes in different - terminal sessions from using the same time stamp record. It also helps - reduce the chance that a user will be able to run ssuuddoo without entering a - password when logging out and back in again on the same terminal. + If the _t_i_m_e_s_t_a_m_p___t_y_p_e option is set to "tty", the time stamp record + includes the device number of the terminal the user authenticated with. + This provides per-terminal granularity but time stamp records may still + outlive the user's session. + + Unless the _t_i_m_e_s_t_a_m_p___t_y_p_e option is set to "global", the time stamp + record also includes the session ID of the process that last + authenticated. This prevents processes in different terminal sessions + from using the same time stamp record. On systems where a process's + start time can be queried, the start time of the session leader is + recorded in the time stamp record. If no terminal is present or the + _t_i_m_e_s_t_a_m_p___t_y_p_e option is set to "ppid", the start time of the parent + process is used instead. In most cases this will prevent a time stamp + record from being re-used without the user entering a password when + logging out and back in again. DDEEBBUUGGGGIINNGG Versions 1.8.4 and higher of the ssuuddooeerrss plugin support a flexible @@ -2886,4 +2888,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or https://www.sudo.ws/license.html for complete details. -Sudo 1.8.22 December 11, 2017 Sudo 1.8.22 +Sudo 1.8.22 December 15, 2017 Sudo 1.8.22 diff --git a/doc/sudoers.man.in b/doc/sudoers.man.in index 15c11203d..f0729d290 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" "5" "December 11, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual" +.TH "SUDOERS" "5" "December 15, 2017" "Sudo @PACKAGE_VERSION@" "File Formats Manual" .nh .if n .ad l .SH "NAME" @@ -5497,31 +5497,33 @@ will be ignored and \fBsudoers\fR will log and complain. .PP -Since time stamp files live in the file system, they can outlive a -user's login session. -As a result, a user may be able to login, run a command with -\fBsudo\fR -after authenticating, logout, login again, and run -\fBsudo\fR -without authenticating so long as the record's time stamp is within -\fR@timeout@\fR -minutes (or whatever value the timeout is set to in the -\fIsudoers\fR -file). -When the -\fItty_tickets\fR -option is enabled, the time stamp record includes the device -number of the terminal the user authenticated with. -This provides per-tty granularity but time stamp records still -may outlive the user's session. -The time stamp record also includes the session ID of the process +If the +\fItimestamp_type\fR +option is set to +\(Lqtty\(Rq, +the time stamp record includes the device number of the terminal +the user authenticated with. +This provides per-terminal granularity but time stamp records may still +outlive the user's session. +.PP +Unless the +\fItimestamp_type\fR +option is set to +\(Lqglobal\(Rq, +the time stamp record also includes the session ID of the process that last authenticated. This prevents processes in different terminal sessions from using the same time stamp record. -It also helps reduce the chance that a user will be able to run -\fBsudo\fR -without entering a password when logging out and back in again -on the same terminal. +On systems where a process's start time can be queried, +the start time of the session leader +is recorded in the time stamp record. +If no terminal is present or the +\fItimestamp_type\fR +option is set to +\(Lqppid\(Rq, +the start time of the parent process is used instead. +In most cases this will prevent a time stamp record from being re-used +without the user entering a password when logging out and back in again. .SH "DEBUGGING" Versions 1.8.4 and higher of the \fBsudoers\fR diff --git a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in index 2773d6c2a..b41265423 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 December 11, 2017 +.Dd December 15, 2017 .Dt SUDOERS @mansectform@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -5089,31 +5089,33 @@ will be ignored and .Nm sudoers will log and complain. .Pp -Since time stamp files live in the file system, they can outlive a -user's login session. -As a result, a user may be able to login, run a command with -.Nm sudo -after authenticating, logout, login again, and run -.Nm sudo -without authenticating so long as the record's time stamp is within -.Li @timeout@ -minutes (or whatever value the timeout is set to in the -.Em sudoers -file). -When the -.Em tty_tickets -option is enabled, the time stamp record includes the device -number of the terminal the user authenticated with. -This provides per-tty granularity but time stamp records still -may outlive the user's session. -The time stamp record also includes the session ID of the process +If the +.Em timestamp_type +option is set to +.Dq tty , +the time stamp record includes the device number of the terminal +the user authenticated with. +This provides per-terminal granularity but time stamp records may still +outlive the user's session. +.Pp +Unless the +.Em timestamp_type +option is set to +.Dq global , +the time stamp record also includes the session ID of the process that last authenticated. This prevents processes in different terminal sessions from using the same time stamp record. -It also helps reduce the chance that a user will be able to run -.Nm sudo -without entering a password when logging out and back in again -on the same terminal. +On systems where a process's start time can be queried, +the start time of the session leader +is recorded in the time stamp record. +If no terminal is present or the +.Em timestamp_type +option is set to +.Dq ppid , +the start time of the parent process is used instead. +In most cases this will prevent a time stamp record from being re-used +without the user entering a password when logging out and back in again. .Sh DEBUGGING Versions 1.8.4 and higher of the .Nm diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 0319a9309..2949cc0b7 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -161,7 +161,8 @@ SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo editor.lo env.lo \ env_pattern.lo find_path.lo gc.lo goodpath.lo group_plugin.lo \ interfaces.lo iolog.lo iolog_path.lo locale.lo logging.lo \ logwrap.lo mkdir_parents.lo parse.lo policy.lo prompt.lo \ - set_perms.lo sudo_nss.lo sudoers.lo timestamp.lo @SUDOERS_OBJS@ + set_perms.lo starttime.lo sudo_nss.lo sudoers.lo \ + timestamp.lo @SUDOERS_OBJS@ VISUDO_OBJS = editor.o find_path.o goodpath.o locale.o sudo_printf.o visudo.o \ visudo_json.o @@ -607,12 +608,13 @@ check_addr.o: $(srcdir)/regress/parser/check_addr.c $(devdir)/def_data.h \ $(top_builddir)/pathnames.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/parser/check_addr.c check_base64.o: $(srcdir)/regress/parser/check_base64.c \ - $(incdir)/sudo_compat.h $(top_builddir)/config.h + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_util.h $(top_builddir)/config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/parser/check_base64.c check_digest.o: $(srcdir)/regress/parser/check_digest.c \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_fatal.h $(incdir)/sudo_queue.h \ - $(srcdir)/parse.h $(top_builddir)/config.h + $(incdir)/sudo_util.h $(srcdir)/parse.h $(top_builddir)/config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/parser/check_digest.c check_env_pattern.o: $(srcdir)/regress/env_match/check_env_pattern.c \ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \ @@ -634,11 +636,12 @@ check_fill.o: $(srcdir)/regress/parser/check_fill.c $(devdir)/gram.h \ check_gentime.o: $(srcdir)/regress/parser/check_gentime.c \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \ - $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \ - $(top_builddir)/config.h + $(incdir)/sudo_util.h $(srcdir)/parse.h \ + $(srcdir)/sudoers_debug.h $(top_builddir)/config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/parser/check_gentime.c check_hexchar.o: $(srcdir)/regress/parser/check_hexchar.c \ - $(incdir)/sudo_compat.h $(top_builddir)/config.h + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_util.h $(top_builddir)/config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/parser/check_hexchar.c check_iolog_path.o: $(srcdir)/regress/iolog_path/check_iolog_path.c \ $(devdir)/def_data.c $(devdir)/def_data.h \ @@ -1111,6 +1114,16 @@ sssd.lo: $(srcdir)/sssd.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \ $(top_builddir)/pathnames.h $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/sssd.c +starttime.lo: $(srcdir)/starttime.c $(devdir)/def_data.h \ + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ + $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ + $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \ + $(incdir)/sudo_util.h $(srcdir)/check.h $(srcdir)/defaults.h \ + $(srcdir)/logging.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ + $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \ + $(top_builddir)/pathnames.h + $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/starttime.c sudo_auth.lo: $(authdir)/sudo_auth.c $(devdir)/def_data.h \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ diff --git a/plugins/sudoers/check.h b/plugins/sudoers/check.h index eee1e4cad..15a0dc706 100644 --- a/plugins/sudoers/check.h +++ b/plugins/sudoers/check.h @@ -34,7 +34,7 @@ * records. Each record starts with a 16-bit version number and a 16-bit * record size. Multiple record types can coexist in the same file. */ -#define TS_VERSION 1 +#define TS_VERSION 2 /* Time stamp entry types */ #define TS_GLOBAL 0x01 @@ -46,7 +46,6 @@ #define TS_DISABLED 0x01 /* entry disabled */ #define TS_ANYUID 0x02 /* ignore uid, only valid in the key */ -/* XXX - may also want to store uid/gid of tty device */ struct timestamp_entry { unsigned short version; /* version number */ unsigned short size; /* entry size */ @@ -54,6 +53,7 @@ struct timestamp_entry { unsigned short flags; /* TS_DISABLED, TS_ANYUID */ uid_t auth_uid; /* uid to authenticate as */ pid_t sid; /* session ID associated with tty/ppid */ + struct timespec start_time; /* session/ppid start time */ struct timespec ts; /* timestamp (CLOCK_MONOTONIC) */ union { dev_t ttydev; /* tty device number */ @@ -66,6 +66,7 @@ void timestamp_close(void *vcookie); bool timestamp_lock(void *vcookie, struct passwd *pw); bool timestamp_update(void *vcookie, struct passwd *pw); int timestamp_status(void *vcookie, struct passwd *pw); +int get_starttime(pid_t pid, struct timespec *starttime); bool already_lectured(int status); int set_lectured(void); diff --git a/plugins/sudoers/starttime.c b/plugins/sudoers/starttime.c new file mode 100644 index 000000000..d49359d0e --- /dev/null +++ b/plugins/sudoers/starttime.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2012-2017 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 + +/* Large files not supported by procfs.h on Solaris. */ +#if defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) +# undef _FILE_OFFSET_BITS +# undef _LARGE_FILES +#endif + +#include +#include +#if defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined (HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV) || defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV) +# include +#elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV) +# include +# include +#endif +#if defined(HAVE_PROCFS_H) +# include +#elif defined(HAVE_SYS_PROCFS_H) +# include +#endif +#ifdef HAVE_PSTAT_GETPROC +# include +#endif + +#include +#include +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include +#include +#include +#include +#include + +#include "sudoers.h" +#include "check.h" + +/* + * Arguments for sysctl(2) when reading the process start time. + */ +#if defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV) +# define SUDO_KERN_PROC KERN_PROC2 +# define sudo_kinfo_proc kinfo_proc2 +# define sudo_kp_namelen 6 +#elif defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) +# define SUDO_KERN_PROC KERN_PROC +# define sudo_kinfo_proc kinfo_proc +# define sudo_kp_namelen 6 +#elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV) +# define SUDO_KERN_PROC KERN_PROC +# define sudo_kinfo_proc kinfo_proc +# define sudo_kp_namelen 4 +#endif + +/* + * Store start time of the specified process in starttime. + */ + +#if defined(sudo_kinfo_proc) +int +get_starttime(pid_t pid, struct timespec *starttime) +{ + struct sudo_kinfo_proc *ki_proc = NULL; + size_t size = sizeof(*ki_proc); + int mib[6], rc; + debug_decl(get_starttime, SUDO_DEBUG_UTIL) + + /* + * Lookup start time for pid via sysctl. + */ + mib[0] = CTL_KERN; + mib[1] = SUDO_KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = (int)pid; + mib[4] = sizeof(*ki_proc); + mib[5] = 1; + do { + struct sudo_kinfo_proc *kp; + + size += size / 10; + if ((kp = realloc(ki_proc, size)) == NULL) { + rc = -1; + break; /* really out of memory. */ + } + ki_proc = kp; + rc = sysctl(mib, sudo_kp_namelen, ki_proc, &size, NULL, 0); + } while (rc == -1 && errno == ENOMEM); + if (rc != -1) { +#if defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV) + /* FreeBSD and macOS */ + starttime->tv_sec = ki_proc->ki_start->tv_sec; + starttime->tv_nsec = ki_proc->ki_start->tv_usec / 1000; +#else + /* NetBSD and OpenBSD */ + starttime->tv_sec = ki_proc->p_ustart_sec; + starttime->tv_nsec = ki_proc->p_ustart_usec / 1000; +#endif + } else { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + "unable to get start time for %d via KERN_PROC", (int)pid); + } + free(ki_proc); + + debug_return_int(rc == -1 ? -1 : 0); +} +#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) +int +get_starttime(pid_t pid, struct timespec *starttime) +{ + struct psinfo psinfo; + char path[PATH_MAX]; + ssize_t nread; + int fd, ret = -1; + debug_decl(get_starttime, SUDO_DEBUG_UTIL) + + /* Determine the start time from pr_start in /proc/pid/psinfo. */ + snprintf(path, sizeof(path), "/proc/%u/psinfo", (unsigned int)pid); + if ((fd = open(path, O_RDONLY, 0)) != -1) { + nread = read(fd, &psinfo, sizeof(psinfo)); + close(fd); + if (nread == (ssize_t)sizeof(psinfo)) { + starttime->tv_sec = psinfo.pr_start.tv_sec; + starttime->tv_nsec = psinfo.pr_start.tv_nsec; + ret = 0; + } + } + + if (ret == -1) + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + "unable to get start time for %d via %s", (int)pid, path); + debug_return_int(ret); +} +#elif defined(__linux__) +int +get_starttime(pid_t pid, struct timespec *starttime) +{ + char path[PATH_MAX]; + char *cp, buf[1024]; + ssize_t nread; + int ret = -1; + int fd = -1; + long tps; + debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL) + + /* + * Start time is in ticks per second on Linux. + */ + tps = sysconf(_SC_CLK_TCK); + if (tps == -1) + goto done; + + /* + * Determine the start time from 22nd field in /proc/pid/stat. + * Ignore /proc/self/stat if it contains embedded NUL bytes. + * XXX - refactor common code with ttyname.c? + */ + snprintf(path, sizeof(path), "/proc/%u/stat", (unsigned int)pid); + if ((fd = open(path, O_RDONLY | O_NOFOLLOW)) != -1) { + cp = buf; + while ((nread = read(fd, cp, buf + sizeof(buf) - cp)) != 0) { + if (nread == -1) { + if (errno == EAGAIN || errno == EINTR) + continue; + break; + } + cp += nread; + if (cp >= buf + sizeof(buf)) + break; + } + if (nread == 0 && memchr(buf, '\0', cp - buf) == NULL) { + /* + * Field 22 is the start time (%ull). + * Since the process name at field 2 "(comm)" may include + * whitespace (including newlines), start at the last ')' found. + */ + *cp = '\0'; + cp = strrchr(buf, ')'); + if (cp != NULL) { + char *ep = cp; + int field = 1; + + while (*++ep != '\0') { + if (*ep == ' ') { + *ep = '\0'; + if (++field == 22) { + unsigned long long ullval; + + /* Must start with a digit (not negative). */ + if (!isdigit((unsigned char)*cp)) { + errno = EINVAL; + goto done; + } + + /* starttime is %ul in 2.4 and %ull in >= 2.6 */ + errno = 0; + ullval = strtoull(cp, &ep, 10); + if (ep == cp || *ep != ' ') { + errno = EINVAL; + goto done; + } + if (errno == ERANGE && ullval == ULLONG_MAX) + goto done; + + /* Convert from ticks to timespec */ + starttime->tv_sec = ullval / tps; + starttime->tv_nsec = + (ullval % tps) * (1000000000 / tps); + + ret = 0; + goto done; + } + cp = ep + 1; + } + } + } + } + } + errno = ENOENT; + +done: + if (fd != -1) + close(fd); + if (ret == -1) + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + "unable to get start time for %d via %s", (int)pid, path); + debug_return_int(ret); +} +#elif defined(HAVE_PSTAT_GETPROC) +int +get_starttime(pid_t pid, struct timespec *starttime) +{ + struct pst_status pstat; + int rc; + debug_decl(get_starttime, SUDO_DEBUG_UTIL) + + /* + * Determine the start time from pst_start in struct pst_status. + * We may get EOVERFLOW if the whole thing doesn't fit but that is OK. + */ + rc = pstat_getproc(&pstat, sizeof(pstat), (size_t)0, (int)getpid()); + if (rc != -1 || errno == EOVERFLOW) { + starttime->tv_sec = pstat.pst_start; + starttime->tv_nsec = 0; + debug_return_int(0); + } + + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + "unable to get start time for %d via pstat_getproc", (int)pid); + debug_return_int(-1); +} +#else +int +get_starttime(pid_t pid, struct timespec *starttime) +{ + debug_decl(get_starttime, SUDO_DEBUG_UTIL) + + sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO, + "process start time not supported by sudo on this system"); + debug_return_int(-1); +} +#endif diff --git a/plugins/sudoers/timestamp.c b/plugins/sudoers/timestamp.c index 3b7b8728f..07b045cc6 100644 --- a/plugins/sudoers/timestamp.c +++ b/plugins/sudoers/timestamp.c @@ -90,10 +90,15 @@ ts_match_record(struct timestamp_entry *key, struct timestamp_entry *entry) /* verify parent pid */ if (entry->u.ppid != key->u.ppid) debug_return_bool(false); + if (sudo_timespeccmp(&entry->start_time, &key->start_time, !=)) + debug_return_bool(false); + break; break; case TS_TTY: if (entry->u.ttydev != key->u.ttydev) debug_return_bool(false); + if (sudo_timespeccmp(&entry->start_time, &key->start_time, !=)) + debug_return_bool(false); break; default: /* unknown record type, ignore it */ @@ -334,6 +339,8 @@ ts_init_key(struct timestamp_entry *entry, struct passwd *pw, int flags, /* tty-based time stamp */ entry->type = TS_TTY; entry->u.ttydev = sb.st_rdev; + if (entry->sid != -1) + get_starttime(entry->sid, &entry->start_time); break; } /* FALLTHROUGH */ @@ -341,6 +348,7 @@ ts_init_key(struct timestamp_entry *entry, struct passwd *pw, int flags, /* ppid-based time stamp */ entry->type = TS_PPID; entry->u.ppid = getppid(); + get_starttime(entry->u.ppid, &entry->start_time); break; default: /* global time stamp */ -- 2.40.0