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 <Todd.Miller@sudo.ws>
+ *
+ * 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>
+
+/* 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 <sys/types.h>
+#include <sys/stat.h>
+#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 <sys/sysctl.h>
+#elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
+# include <sys/sysctl.h>
+# include <sys/user.h>
+#endif
+#if defined(HAVE_PROCFS_H)
+# include <procfs.h>
+#elif defined(HAVE_SYS_PROCFS_H)
+# include <sys/procfs.h>
+#endif
+#ifdef HAVE_PSTAT_GETPROC
+# include <sys/pstat.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+
+#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 */
