diff --git a/sys/amd64/vmm/io/vrtc.c b/sys/amd64/vmm/io/vrtc.c --- a/sys/amd64/vmm/io/vrtc.c +++ b/sys/amd64/vmm/io/vrtc.c @@ -184,7 +184,7 @@ struct clocktime ct; struct timespec ts; struct rtcdev *rtc; - int hour; + int hour, r; KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); @@ -204,7 +204,10 @@ ts.tv_sec = rtctime; ts.tv_nsec = 0; - clock_ts_to_ct(&ts, &ct); + r = clock_ts_to_ct(&ts, &ct); + if (r) + panic("invalid RTC time %ld seconds %ld nanoseconds", + ts.tv_sec, ts.tv_nsec); KASSERT(ct.sec >= 0 && ct.sec <= 59, ("invalid clocktime sec %d", ct.sec)); diff --git a/sys/dev/dialog/da9063/da9063_rtc.c b/sys/dev/dialog/da9063/da9063_rtc.c --- a/sys/dev/dialog/da9063/da9063_rtc.c +++ b/sys/dev/dialog/da9063/da9063_rtc.c @@ -198,7 +198,9 @@ * disables utc adjustment, so apply that ourselves. */ ts->tv_sec -= utc_offset(); - clock_ts_to_ct(ts, &ct); + error = clock_ts_to_ct(ts, &ct); + if (error) + return (error); DA9063_RTC_LOCK(sc); error = da9063_rtc_write_ct(sc, &ct); diff --git a/sys/dev/efidev/efirtc.c b/sys/dev/efidev/efirtc.c --- a/sys/dev/efidev/efirtc.c +++ b/sys/dev/efidev/efirtc.c @@ -156,6 +156,7 @@ { struct clocktime ct; struct efi_tm tm; + int err; /* * We request a timespec with no resolution-adjustment so that we can @@ -166,7 +167,9 @@ if (!efirtc_zeroes_subseconds) timespecadd(ts, &efirtc_resadj, ts); - clock_ts_to_ct(ts, &ct); + err = clock_ts_to_ct(ts, &ct); + if (err) + return (err); clock_dbgprint_ct(dev, CLOCK_DBG_WRITE, &ct); bzero(&tm, sizeof(tm)); diff --git a/sys/dev/iicbus/ds1307.c b/sys/dev/iicbus/ds1307.c --- a/sys/dev/iicbus/ds1307.c +++ b/sys/dev/iicbus/ds1307.c @@ -516,7 +516,9 @@ * disables utc adjustment, so apply that ourselves. */ ts->tv_sec -= utc_offset(); - clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm); + error = clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm); + if (error) + return (error); clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct); /* diff --git a/sys/dev/iicbus/ds13rtc.c b/sys/dev/iicbus/ds13rtc.c --- a/sys/dev/iicbus/ds13rtc.c +++ b/sys/dev/iicbus/ds13rtc.c @@ -423,7 +423,9 @@ if (sc->is_binary_counter) return (write_timeword(sc, ts->tv_sec)); - clock_ts_to_bcd(ts, &bct, sc->use_ampm); + err = clock_ts_to_bcd(ts, &bct, sc->use_ampm); + if (err) + return (err); clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); /* If the chip is in AMPM mode deal with the PM flag. */ diff --git a/sys/dev/iicbus/ds3231.c b/sys/dev/iicbus/ds3231.c --- a/sys/dev/iicbus/ds3231.c +++ b/sys/dev/iicbus/ds3231.c @@ -552,7 +552,9 @@ * disables utc adjustment, so apply that ourselves. */ ts->tv_sec -= utc_offset(); - clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm); + error = clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm); + if (error) + return (error); clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct); /* If the chip is in AM/PM mode, adjust hour and set flags as needed. */ diff --git a/sys/dev/iicbus/isl12xx.c b/sys/dev/iicbus/isl12xx.c --- a/sys/dev/iicbus/isl12xx.c +++ b/sys/dev/iicbus/isl12xx.c @@ -293,7 +293,9 @@ */ ts->tv_sec -= utc_offset(); ts->tv_nsec = 0; - clock_ts_to_bcd(ts, &bct, sc->use_ampm); + err = clock_ts_to_bcd(ts, &bct, sc->use_ampm); + if (err) + return (err); clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); /* If the chip is in AM/PM mode, set flags as needed. */ diff --git a/sys/dev/iicbus/nxprtc.c b/sys/dev/iicbus/nxprtc.c --- a/sys/dev/iicbus/nxprtc.c +++ b/sys/dev/iicbus/nxprtc.c @@ -837,7 +837,9 @@ getnanotime(ts); ts->tv_sec -= utc_offset(); ts->tv_nsec = 0; - clock_ts_to_bcd(ts, &bct, sc->use_ampm); + err = clock_ts_to_bcd(ts, &bct, sc->use_ampm); + if (err) + return (err); clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); /* On 8563 set the century based on the polarity seen when reading. */ diff --git a/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c b/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c --- a/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c +++ b/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c @@ -116,7 +116,9 @@ sc = device_get_softc(dev); - clock_ts_to_bcd(ts, &bct, false); + error = clock_ts_to_bcd(ts, &bct, false); + if (error) + return (error); /* This works as long as RK805_RTC_SECS = 0 */ if (sc->type == RK809 || sc->type == RK817) { diff --git a/sys/dev/iicbus/rtc/hym8563.c b/sys/dev/iicbus/rtc/hym8563.c --- a/sys/dev/iicbus/rtc/hym8563.c +++ b/sys/dev/iicbus/rtc/hym8563.c @@ -170,7 +170,9 @@ sc = device_get_softc(dev); ts->tv_sec -= utc_offset(); - clock_ts_to_bcd(ts, &bct, false); + rv = clock_ts_to_bcd(ts, &bct, false); + if (rv) + return (rv); clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); buf[0] = bct.sec; /* Also clear VL flag */ diff --git a/sys/dev/iicbus/rtc/pcf85063.c b/sys/dev/iicbus/rtc/pcf85063.c --- a/sys/dev/iicbus/rtc/pcf85063.c +++ b/sys/dev/iicbus/rtc/pcf85063.c @@ -183,7 +183,9 @@ sizeof(uint8_t), IIC_WAIT); ts->tv_sec -= utc_offset(); - clock_ts_to_bcd(ts, &bcd, false); + error = clock_ts_to_bcd(ts, &bcd, false); + if (error) + return (error); clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bcd); data.sec = bcd.sec; diff --git a/sys/dev/iicbus/rtc/rx8803.c b/sys/dev/iicbus/rtc/rx8803.c --- a/sys/dev/iicbus/rtc/rx8803.c +++ b/sys/dev/iicbus/rtc/rx8803.c @@ -138,7 +138,9 @@ int rc; ts->tv_sec -= utc_offset(); - clock_ts_to_bcd(ts, &bcd, false); + rc = clock_ts_to_bcd(ts, &bcd, false); + if (rc) + return (rc); clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bcd); data.sec = bcd.sec; diff --git a/sys/dev/iicbus/rtc8583.c b/sys/dev/iicbus/rtc8583.c --- a/sys/dev/iicbus/rtc8583.c +++ b/sys/dev/iicbus/rtc8583.c @@ -256,7 +256,9 @@ sc = device_get_softc(dev); ts->tv_sec -= utc_offset(); - clock_ts_to_bcd(ts, &bct, false); + err = clock_ts_to_bcd(ts, &bct, false); + if (err) + return (err); clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); /* The 'msec' reg is actually 1/100ths, in bcd. */ diff --git a/sys/dev/iicbus/s35390a.c b/sys/dev/iicbus/s35390a.c --- a/sys/dev/iicbus/s35390a.c +++ b/sys/dev/iicbus/s35390a.c @@ -328,8 +328,11 @@ { uint8_t bcd[S390_RT1_NBYTES]; struct bcd_clocktime bct; + int err; - clock_ts_to_bcd(ts, &bct, false); + err = clock_ts_to_bcd(ts, &bct, false); + if (err) + return (err); clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bct); /* diff --git a/sys/dev/smartpqi/smartpqi_discovery.c b/sys/dev/smartpqi/smartpqi_discovery.c --- a/sys/dev/smartpqi/smartpqi_discovery.c +++ b/sys/dev/smartpqi/smartpqi_discovery.c @@ -1751,7 +1751,8 @@ host_wellness_time->time_length = LE_16(offsetof(struct bmic_host_wellness_time, time_length) - offsetof(struct bmic_host_wellness_time, century)); - os_get_time(host_wellness_time); + if (os_get_time(host_wellness_time)) + return PQI_STATUS_FAILURE; host_wellness_time->dont_write_tag[0] = 'D'; host_wellness_time->dont_write_tag[1] = 'W'; diff --git a/sys/dev/smartpqi/smartpqi_misc.c b/sys/dev/smartpqi/smartpqi_misc.c --- a/sys/dev/smartpqi/smartpqi_misc.c +++ b/sys/dev/smartpqi/smartpqi_misc.c @@ -30,14 +30,17 @@ /* * Populate hostwellness time variables in bcd format from FreeBSD format */ -void +int os_get_time(struct bmic_host_wellness_time *host_wellness_time) { struct timespec ts; struct clocktime ct; + int err; getnanotime(&ts); - clock_ts_to_ct(&ts, &ct); + err = clock_ts_to_ct(&ts, &ct); + if (err) + return (err); /* Fill the time In BCD Format */ host_wellness_time->hour= (uint8_t)bin2bcd(ct.hour); @@ -49,6 +52,7 @@ host_wellness_time->century = (uint8_t)bin2bcd(ct.year / 100); host_wellness_time->year = (uint8_t)bin2bcd(ct.year % 100); + return (0); } /* diff --git a/sys/dev/smartpqi/smartpqi_prototypes.h b/sys/dev/smartpqi/smartpqi_prototypes.h --- a/sys/dev/smartpqi/smartpqi_prototypes.h +++ b/sys/dev/smartpqi/smartpqi_prototypes.h @@ -287,7 +287,7 @@ int register_msix_intr(pqisrc_softstate_t *); void deregister_pqi_intx(pqisrc_softstate_t *); void deregister_pqi_msix(pqisrc_softstate_t *); -void os_get_time(struct bmic_host_wellness_time *); +int os_get_time(struct bmic_host_wellness_time *); void os_eventtaskqueue_enqueue(pqisrc_softstate_t *); void pqisrc_save_controller_info(struct pqisrc_softstate *); diff --git a/sys/geom/raid/md_ddf.c b/sys/geom/raid/md_ddf.c --- a/sys/geom/raid/md_ddf.c +++ b/sys/geom/raid/md_ddf.c @@ -589,7 +589,6 @@ meta->sectorsize = ss; meta->bigendian = sample ? sample->bigendian : mdi->mdio_bigendian; getnanotime(&ts); - clock_ts_to_ct(&ts, &ct); /* Header */ meta->hdr = malloc(ss, M_MD_DDF, M_WAITOK); @@ -711,10 +710,17 @@ error = g_io_getattr("GEOM::ident", disk->d_consumer, &len, serial_buffer); if (error == 0 && (len = strlen (serial_buffer)) >= 6 && len <= 20) snprintf(pde->PD_GUID, 25, "DISK%20s", serial_buffer); - else - snprintf(pde->PD_GUID, 25, "DISK%04d%02d%02d%08x%04x", - ct.year, ct.mon, ct.day, - arc4random(), arc4random() & 0xffff); + else { + error = clock_ts_to_ct(&ts, &ct); + if (error) { + snprintf(pde->PD_GUID, 25, "DISK%08x%04x", + arc4random(), arc4random() & 0xffff); + } else { + snprintf(pde->PD_GUID, 25, "DISK%04d%02d%02d%08x%04x", + ct.year, ct.mon, ct.day, + arc4random(), arc4random() & 0xffff); + } + } SET32D(meta, pde->PD_Reference, arc4random()); SET16D(meta, pde->PD_Type, DDF_PDE_GUID_FORCE); SET16D(meta, pde->PD_State, 0); @@ -847,6 +853,7 @@ struct timespec ts; struct clocktime ct; u_int ss, size; + int error; meta->bigendian = sample->bigendian; ss = meta->sectorsize = sample->sectorsize; @@ -857,10 +864,15 @@ meta->vde = malloc(sizeof(struct ddf_vd_entry), M_MD_DDF, M_WAITOK); memset(meta->vde, 0xff, sizeof(struct ddf_vd_entry)); getnanotime(&ts); - clock_ts_to_ct(&ts, &ct); - snprintf(meta->vde->VD_GUID, 25, "FreeBSD%04d%02d%02d%08x%01x", - ct.year, ct.mon, ct.day, - arc4random(), arc4random() & 0xf); + error = clock_ts_to_ct(&ts, &ct); + if (error) { + snprintf(meta->vde->VD_GUID, 25, "FreeBSD%08x%01x", + arc4random(), arc4random() & 0xf); + } else { + snprintf(meta->vde->VD_GUID, 25, "FreeBSD%04d%02d%02d%08x%01x", + ct.year, ct.mon, ct.day, + arc4random(), arc4random() & 0xf); + } size = GET16(sample, hdr->Configuration_Record_Length) * ss; meta->vdc = malloc(size, M_MD_DDF, M_WAITOK); memset(meta->vdc, 0xff, size); diff --git a/sys/kern/subr_clock.c b/sys/kern/subr_clock.c --- a/sys/kern/subr_clock.c +++ b/sys/kern/subr_clock.c @@ -244,12 +244,13 @@ return (clock_ct_to_ts(&ct, ts)); } -void +int clock_ts_to_ct(const struct timespec *ts, struct clocktime *ct) { - time_t i, year, days; + time_t mon, year, days; time_t rsec; /* remainder seconds */ time_t secs; + int hour, day, min; secs = ts->tv_sec; days = secs / SECDAY; @@ -266,20 +267,25 @@ } for (; days >= days_in_year(year); year++) days -= days_in_year(year); + if (year < 0 || year >= 10000) + return (EINVAL); ct->year = year; - /* Subtract out whole months, counting them in i. */ - for (i = 1; days >= days_in_month(year, i); i++) - days -= days_in_month(year, i); - ct->mon = i; + /* Subtract out whole months, counting them in mon. */ + for (mon = 1; days >= days_in_month(year, mon); mon++) + days -= days_in_month(year, mon); + ct->mon = mon; /* Days are what is left over (+1) from all that. */ - ct->day = days + 1; + day = days + 1; + ct->day = day; /* Hours, minutes, seconds are easy */ - ct->hour = rsec / 3600; + hour = rsec / 3600; + ct->hour = hour; rsec = rsec % 3600; - ct->min = rsec / 60; + min = rsec / 60; + ct->min = min; rsec = rsec % 60; ct->sec = rsec; ct->nsec = ts->tv_nsec; @@ -300,17 +306,21 @@ ("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)); + KASSERT(ct->sec >= 0 && ct->sec <= 59, + ("seconds %d not in 0-59", ct->sec)); + + return (0); } -void +int clock_ts_to_bcd(const struct timespec *ts, struct bcd_clocktime *bct, bool ampm) { struct clocktime ct; + int r; - clock_ts_to_ct(ts, &ct); + r = clock_ts_to_ct(ts, &ct); + if (r) + return (r); /* If asked to handle am/pm, convert from 24hr to 12hr+pmflag. */ bct->ispm = false; @@ -331,6 +341,8 @@ bct->sec = TOBCD(ct.sec); bct->dow = ct.dow; bct->nsec = ct.nsec; + + return (0); } void diff --git a/sys/kern/subr_rtc.c b/sys/kern/subr_rtc.c --- a/sys/kern/subr_rtc.c +++ b/sys/kern/subr_rtc.c @@ -152,7 +152,7 @@ ts.tv_nsec = 0; } error = CLOCK_SETTIME(rtc->clockdev, &ts); - if (error != 0 && bootverbose) + if (error != 0) device_printf(rtc->clockdev, "CLOCK_SETTIME error %d\n", error); } diff --git a/sys/sys/clock.h b/sys/sys/clock.h --- a/sys/sys/clock.h +++ b/sys/sys/clock.h @@ -83,7 +83,7 @@ }; int clock_ct_to_ts(const struct clocktime *, struct timespec *); -void clock_ts_to_ct(const struct timespec *, struct clocktime *); +int clock_ts_to_ct(const struct timespec *, struct clocktime *); /* * Structure to hold the values typically reported by time-of-day clocks, @@ -120,7 +120,7 @@ }; int clock_bcd_to_ts(const struct bcd_clocktime *, struct timespec *, bool ampm); -void clock_ts_to_bcd(const struct timespec *, struct bcd_clocktime *, bool ampm); +int clock_ts_to_bcd(const struct timespec *, struct bcd_clocktime *, bool ampm); /* * Time-of-day clock functions and flags. These functions might sleep. diff --git a/sys/x86/isa/atrtc.c b/sys/x86/isa/atrtc.c --- a/sys/x86/isa/atrtc.c +++ b/sys/x86/isa/atrtc.c @@ -560,8 +560,11 @@ atrtc_settime(device_t dev __unused, struct timespec *ts) { struct bcd_clocktime bct; + int r; - clock_ts_to_bcd(ts, &bct, false); + r = clock_ts_to_bcd(ts, &bct, false); + if (r) + return (EINVAL); clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bct); mtx_lock(&atrtc_time_lock);