From: Todd C. Miller Subject: Re: localtime(3) / gmtime(3) error checking for bin / libexec / sbin To: Florian Obser Cc: tech Date: Sun, 28 Apr 2024 08:48:45 -0600 On Sun, 28 Apr 2024 12:03:04 +0200, Florian Obser wrote: > Mostly compile tested only. Most of these probably can't happen. At > least I don't expect the kernel to work well if the time is so far in > the future that the year can't be represented by a struct tm. But I > suppose just adding the error check is easier than arguing why it's not > needed. This looks good to me. I think it is worth adding the checks even if failure should be impossible. Some comments inline. - todd > diff --git sbin/isakmpd/x509.c sbin/isakmpd/x509.c > index 989553897e2..9a83d5d743e 100644 > --- sbin/isakmpd/x509.c > +++ sbin/isakmpd/x509.c > @@ -222,8 +222,15 @@ x509_generate_kn(int id, X509 *cert) > if (((tm = X509_get_notBefore(cert)) == NULL) || > (tm->type != V_ASN1_UTCTIME && > tm->type != V_ASN1_GENERALIZEDTIME)) { > - tt = time(0); > - strftime(before, 14, "%Y%m%d%H%M%S", localtime(&tt)); > + struct tm *ltm; > + > + tt = time(NULL); > + if ((ltm = localtime(&tt)) == NULL) { > + LOG_DBG((LOG_POLICY, 30, > + "x509_generate_kn: invalid local time")); > + goto fail; > + } > + strftime(before, 14, "%Y%m%d%H%M%S", ltm); > timecomp = "LocalTimeOfDay"; > } else { > if (tm->data[tm->length - 1] == 'Z') { > @@ -312,7 +319,14 @@ x509_generate_kn(int id, X509 *cert) > if (tm == NULL || > (tm->type != V_ASN1_UTCTIME && > tm->type != V_ASN1_GENERALIZEDTIME)) { > + struct tm *ltm; > + > tt = time(0); > + if ((ltm = localtime(&tt)) == NULL) { > + LOG_DBG((LOG_POLICY, 30, > + "x509_generate_kn: invalid local time")); > + goto fail; > + } > strftime(after, 14, "%Y%m%d%H%M%S", localtime(&tt)); In the strftime() call this should now be ltm. > timecomp2 = "LocalTimeOfDay"; > } else { > diff --git sbin/shutdown/shutdown.c sbin/shutdown/shutdown.c > index 2c74ae3d25a..84f26575b26 100644 > --- sbin/shutdown/shutdown.c > +++ sbin/shutdown/shutdown.c > @@ -345,8 +345,11 @@ timewarn(time_t timeleft) > if (timeleft > 10 * 60) { > shuttime = time(NULL) + timeleft; > lt = localtime(&shuttime); > - strftime(when, sizeof(when), "%H:%M %Z", lt); > - dprintf(fd[1], "System going down at %s\n\n", when); > + if (lt != NULL) { > + strftime(when, sizeof(when), "%H:%M %Z", lt); > + dprintf(fd[1], "System going down at %s\n\n", when); > + } else > + dprintf(fd[1], "System going down soon\n\n"); Maybe just use the timeleft > 59 case if localtime() fails? > } else if (timeleft > 59) { > dprintf(fd[1], "System going down in %lld minute%s\n\n", > (long long)(timeleft / 60), (timeleft > 60) ? "s" : ""); > @@ -525,6 +528,9 @@ getoffset(char *timearg) > time(&now); > lt = localtime(&now); /* current time val */ > > + if (lt == NULL) > + badtime(); > + > switch (strlen(timearg)) { > case 10: > this_year = lt->tm_year; > @@ -597,8 +603,13 @@ nolog(time_t timeleft) > tm = localtime(&shuttime); > if (tm && (logfd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT|O_TRUNC, > 0664)) >= 0) { > - strftime(when, sizeof(when), "at %H:%M %Z", tm); > - dprintf(logfd, "\n\nNO LOGINS: System going down %s\n\n", when) > ; > + if (tm) { > + strftime(when, sizeof(when), "at %H:%M %Z", tm); > + dprintf(logfd, > + "\n\nNO LOGINS: System going down %s\n\n", when); > + } else > + dprintf(logfd, > + "\n\nNO LOGINS: System going down soon\n\n"); How about this instead? dprintf(logfd, "\n\nNO LOGINS: System going down in %lld minute%s\n\n", (long long)(timeleft / 60), (timeleft > 60) ? "s" : ""); > close(logfd); > } > }