From: Todd C. Miller Date: Wed, 4 Apr 2018 17:28:53 +0000 (-0600) Subject: Use btime in /proc/stat to determine system start time instead of X-Git-Tag: SUDO_1_8_23^2~44 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=512e0be8344f167b14ebce77c15f45e5671fb265;p=sudo Use btime in /proc/stat to determine system start time instead of /proc/uptime. Fixes the process start time test when run from a container where /proc/uptime is the uptime of the container but the process start time is relative to the host system boot time. Bug #829 --- diff --git a/plugins/sudoers/regress/starttime/check_starttime.c b/plugins/sudoers/regress/starttime/check_starttime.c index 4bcdde891..15dd1f7bf 100644 --- a/plugins/sudoers/regress/starttime/check_starttime.c +++ b/plugins/sudoers/regress/starttime/check_starttime.c @@ -17,8 +17,10 @@ #include #include +#include #include #include +#include #include #include @@ -27,27 +29,45 @@ #include "sudo_fatal.h" #include "check.h" +#ifndef TIME_T_MAX +# if SIZEOF_TIME_T == 8 +# define TIME_T_MAX LLONG_MAX +# else +# define TIME_T_MAX INT_MAX +# endif +#endif + __dso_public int main(int argc, char *argv[]); #ifdef __linux__ static int get_now(struct timespec *now) { - int ret = -1; + const char *errstr; char buf[1024]; + time_t seconds; + int ret = -1; FILE *fp; /* Linux process start time is relative to boot time. */ - fp = fopen("/proc/uptime", "r"); + fp = fopen("/proc/stat", "r"); if (fp != NULL) { - if (fgets(buf, sizeof(buf), fp) != NULL) { - char *ep; - double uptime = strtod(buf, &ep); - if (*ep == ' ') { - now->tv_sec = (time_t)uptime; - now->tv_nsec = (uptime - (time_t)uptime) * 1000000000; - ret = 0; - } + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (strncmp(buf, "btime ", 6) != 0) + continue; + buf[strcspn(buf, "\n")] = '\0'; + + /* Boot time is in seconds since the epoch. */ + seconds = strtonum(buf + 6, 0, TIME_T_MAX, &errstr); + if (errstr != NULL) + return -1; + + /* Instead of the real time, "now" is relative to boot time. */ + if (sudo_gettime_real(now) == -1) + return -1; + now->tv_sec -= seconds; + ret = 0; + break; } fclose(fp); }