mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-23 11:18:54 +00:00
Use time_t for intermediate values to avoid overflow in clock_ts_to_ct
Add additionally safety and overflow checks to clock_ts_to_ct and the BCD routines while we're here. Perform a safety check in sys_clock_settime() first to avoid easy local root panic, without having to propagate an error value back through dozens of APIs currently lacking error returns. PR: 211960, 214300 Submitted by: Justin McOmie <justin.mcomie at gmail.com>, kib@ Reported by: Tim Newsham <tim.newsham at nccgroup.trust> Reviewed by: kib@ Sponsored by: Dell EMC Isilon, FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D9279
This commit is contained in:
parent
86e01d5add
commit
90a79ac576
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=312702
@ -387,6 +387,11 @@ sys_clock_settime(struct thread *td, struct clock_settime_args *uap)
|
||||
return (kern_clock_settime(td, uap->clock_id, &ats));
|
||||
}
|
||||
|
||||
static int allow_insane_settime = 0;
|
||||
SYSCTL_INT(_debug, OID_AUTO, allow_insane_settime, CTLFLAG_RWTUN,
|
||||
&allow_insane_settime, 0,
|
||||
"do not perform possibly restrictive checks on settime(2) args");
|
||||
|
||||
int
|
||||
kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats)
|
||||
{
|
||||
@ -400,6 +405,8 @@ kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats)
|
||||
if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000 ||
|
||||
ats->tv_sec < 0)
|
||||
return (EINVAL);
|
||||
if (!allow_insane_settime && ats->tv_sec > 9999ULL * 366 * 24 * 60 * 60)
|
||||
return (EINVAL);
|
||||
/* XXX Don't convert nsec->usec and back */
|
||||
TIMESPEC_TO_TIMEVAL(&atv, ats);
|
||||
error = settime(td, &atv);
|
||||
|
@ -178,7 +178,7 @@ clock_ct_to_ts(struct clocktime *ct, struct timespec *ts)
|
||||
void
|
||||
clock_ts_to_ct(struct timespec *ts, struct clocktime *ct)
|
||||
{
|
||||
int i, year, days;
|
||||
time_t i, year, days;
|
||||
time_t rsec; /* remainder seconds */
|
||||
time_t secs;
|
||||
|
||||
@ -214,6 +214,20 @@ clock_ts_to_ct(struct timespec *ts, struct clocktime *ct)
|
||||
print_ct(ct);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
KASSERT(ct->year >= 0 && ct->year < 10000,
|
||||
("year %d isn't a 4 digit year", ct->year));
|
||||
KASSERT(ct->mon >= 1 && ct->mon <= 12,
|
||||
("month %d not in 1-12", ct->mon));
|
||||
KASSERT(ct->day >= 1 && ct->day <= 31,
|
||||
("day %d not in 1-31", ct->day));
|
||||
KASSERT(ct->hour >= 0 && ct->hour <= 23,
|
||||
("hour %d not in 0-23", ct->hour));
|
||||
KASSERT(ct->min >= 0 && ct->min <= 59,
|
||||
("minute %d not in 0-59", ct->min));
|
||||
/* Not sure if this interface needs to handle leapseconds or not. */
|
||||
KASSERT(ct->sec >= 0 && ct->sec <= 60,
|
||||
("seconds %d not in 0-60", ct->sec));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/libkern.h>
|
||||
|
||||
u_char const bcd2bin_data[] = {
|
||||
@ -20,6 +21,7 @@ u_char const bcd2bin_data[] = {
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 0, 0, 0, 0, 0,
|
||||
90, 91, 92, 93, 94, 95, 96, 97, 98, 99
|
||||
};
|
||||
CTASSERT(nitems(bcd2bin_data) == LIBKERN_LEN_BCD2BIN);
|
||||
|
||||
u_char const bin2bcd_data[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
@ -33,6 +35,8 @@ u_char const bin2bcd_data[] = {
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99
|
||||
};
|
||||
CTASSERT(nitems(bin2bcd_data) == LIBKERN_LEN_BIN2BCD);
|
||||
|
||||
/* This is actually used with radix [2..36] */
|
||||
char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
CTASSERT(nitems(hex2ascii_data) == LIBKERN_LEN_HEX2ASCII + 1);
|
||||
|
@ -49,9 +49,36 @@ extern u_char const bcd2bin_data[];
|
||||
extern u_char const bin2bcd_data[];
|
||||
extern char const hex2ascii_data[];
|
||||
|
||||
#define bcd2bin(bcd) (bcd2bin_data[bcd])
|
||||
#define bin2bcd(bin) (bin2bcd_data[bin])
|
||||
#define hex2ascii(hex) (hex2ascii_data[hex])
|
||||
#define LIBKERN_LEN_BCD2BIN 154
|
||||
#define LIBKERN_LEN_BIN2BCD 100
|
||||
#define LIBKERN_LEN_HEX2ASCII 36
|
||||
|
||||
static inline u_char
|
||||
bcd2bin(int bcd)
|
||||
{
|
||||
|
||||
KASSERT(bcd >= 0 && bcd < LIBKERN_LEN_BCD2BIN,
|
||||
("invalid bcd %d", bcd));
|
||||
return (bcd2bin_data[bcd]);
|
||||
}
|
||||
|
||||
static inline u_char
|
||||
bin2bcd(int bin)
|
||||
{
|
||||
|
||||
KASSERT(bin >= 0 && bin < LIBKERN_LEN_BIN2BCD,
|
||||
("invalid bin %d", bin));
|
||||
return (bin2bcd_data[bin]);
|
||||
}
|
||||
|
||||
static inline char
|
||||
hex2ascii(int hex)
|
||||
{
|
||||
|
||||
KASSERT(hex >= 0 && hex < LIBKERN_LEN_HEX2ASCII,
|
||||
("invalid hex %d", hex));
|
||||
return (hex2ascii_data[hex]);
|
||||
}
|
||||
|
||||
static __inline int imax(int a, int b) { return (a > b ? a : b); }
|
||||
static __inline int imin(int a, int b) { return (a < b ? a : b); }
|
||||
|
Loading…
Reference in New Issue
Block a user