time: create __getnstimeofday for WARNless calls
The pstore RAM backend can get called during resume, and must be defensive against a suspended time source. Expose getnstimeofday logic that returns an error instead of a WARN. This can be detected and the timestamp can be zeroed out. Reported-by: Doug Anderson <dianders@chromium.org> Cc: John Stultz <johnstul@us.ibm.com> Cc: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: John Stultz <john.stultz@linaro.org>
This commit is contained in:
parent
9c3f9e2816
commit
1e817fb62c
|
@ -168,12 +168,16 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
|
||||||
static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz)
|
static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz)
|
||||||
{
|
{
|
||||||
char *hdr;
|
char *hdr;
|
||||||
struct timeval timestamp;
|
struct timespec timestamp;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
do_gettimeofday(×tamp);
|
/* Report zeroed timestamp if called before timekeeping has resumed. */
|
||||||
|
if (__getnstimeofday(×tamp)) {
|
||||||
|
timestamp.tv_sec = 0;
|
||||||
|
timestamp.tv_nsec = 0;
|
||||||
|
}
|
||||||
hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lu.%lu\n",
|
hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lu.%lu\n",
|
||||||
(long)timestamp.tv_sec, (long)timestamp.tv_usec);
|
(long)timestamp.tv_sec, (long)(timestamp.tv_nsec / 1000));
|
||||||
WARN_ON_ONCE(!hdr);
|
WARN_ON_ONCE(!hdr);
|
||||||
len = hdr ? strlen(hdr) : 0;
|
len = hdr ? strlen(hdr) : 0;
|
||||||
persistent_ram_write(prz, hdr, len);
|
persistent_ram_write(prz, hdr, len);
|
||||||
|
|
|
@ -158,6 +158,7 @@ extern int do_setitimer(int which, struct itimerval *value,
|
||||||
struct itimerval *ovalue);
|
struct itimerval *ovalue);
|
||||||
extern unsigned int alarm_setitimer(unsigned int seconds);
|
extern unsigned int alarm_setitimer(unsigned int seconds);
|
||||||
extern int do_getitimer(int which, struct itimerval *value);
|
extern int do_getitimer(int which, struct itimerval *value);
|
||||||
|
extern int __getnstimeofday(struct timespec *tv);
|
||||||
extern void getnstimeofday(struct timespec *tv);
|
extern void getnstimeofday(struct timespec *tv);
|
||||||
extern void getrawmonotonic(struct timespec *ts);
|
extern void getrawmonotonic(struct timespec *ts);
|
||||||
extern void getnstime_raw_and_real(struct timespec *ts_raw,
|
extern void getnstime_raw_and_real(struct timespec *ts_raw,
|
||||||
|
|
|
@ -214,19 +214,18 @@ static void timekeeping_forward_now(struct timekeeper *tk)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getnstimeofday - Returns the time of day in a timespec
|
* __getnstimeofday - Returns the time of day in a timespec.
|
||||||
* @ts: pointer to the timespec to be set
|
* @ts: pointer to the timespec to be set
|
||||||
*
|
*
|
||||||
* Returns the time of day in a timespec.
|
* Updates the time of day in the timespec.
|
||||||
|
* Returns 0 on success, or -ve when suspended (timespec will be undefined).
|
||||||
*/
|
*/
|
||||||
void getnstimeofday(struct timespec *ts)
|
int __getnstimeofday(struct timespec *ts)
|
||||||
{
|
{
|
||||||
struct timekeeper *tk = &timekeeper;
|
struct timekeeper *tk = &timekeeper;
|
||||||
unsigned long seq;
|
unsigned long seq;
|
||||||
s64 nsecs = 0;
|
s64 nsecs = 0;
|
||||||
|
|
||||||
WARN_ON(timekeeping_suspended);
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
seq = read_seqbegin(&tk->lock);
|
seq = read_seqbegin(&tk->lock);
|
||||||
|
|
||||||
|
@ -237,6 +236,26 @@ void getnstimeofday(struct timespec *ts)
|
||||||
|
|
||||||
ts->tv_nsec = 0;
|
ts->tv_nsec = 0;
|
||||||
timespec_add_ns(ts, nsecs);
|
timespec_add_ns(ts, nsecs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not bail out early, in case there were callers still using
|
||||||
|
* the value, even in the face of the WARN_ON.
|
||||||
|
*/
|
||||||
|
if (unlikely(timekeeping_suspended))
|
||||||
|
return -EAGAIN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__getnstimeofday);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getnstimeofday - Returns the time of day in a timespec.
|
||||||
|
* @ts: pointer to the timespec to be set
|
||||||
|
*
|
||||||
|
* Returns the time of day in a timespec (WARN if suspended).
|
||||||
|
*/
|
||||||
|
void getnstimeofday(struct timespec *ts)
|
||||||
|
{
|
||||||
|
WARN_ON(__getnstimeofday(ts));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(getnstimeofday);
|
EXPORT_SYMBOL(getnstimeofday);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue