mirror of
https://git.sr.ht/~cismonx/bookmarkfs
synced 2025-06-07 19:58:50 +00:00
backend: prevent timestamp overflow
When updating timestamps, make sure that the corresponding microsecond value fits in a single signed 64-bit integer, so that it won't result in an integer overflow, which is UB. Also forbid timestamps before the Unix epoch, since working with negative time_t is problematic. This check does not apply to current timestamp, however, add a check on backend startup to ensure sane system time. There's no need to validate `tv_nsec`, since the kernel already does that for us.
This commit is contained in:
parent
09e186b348
commit
750c16077c
3 changed files with 38 additions and 11 deletions
|
@ -772,13 +772,8 @@ build_tsnode (
|
|||
ts = &now;
|
||||
}
|
||||
|
||||
// XXX: May overflow if system time is badly wrong,
|
||||
// but don't bother to check.
|
||||
time_t secs = ts->tv_sec + EPOCH_DIFF;
|
||||
int64_t microsecs = secs * 1000000 + ts->tv_nsec / 1000;
|
||||
if (microsecs < 0) {
|
||||
microsecs = 0;
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
int nbytes = snprintf(buf, sizeof(buf), "%" PRIi64, microsecs);
|
||||
|
@ -1713,6 +1708,13 @@ static int
|
|||
backend_init (
|
||||
uint32_t flags
|
||||
) {
|
||||
struct timespec now;
|
||||
xgetrealtime(&now);
|
||||
if (!valid_ts_sec(now.tv_sec)) {
|
||||
log_puts("bad system time");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(flags & BOOKMARKFS_BACKEND_LIB_READY)) {
|
||||
if (0 != bookmarkfs_lib_init()) {
|
||||
return -1;
|
||||
|
@ -2517,10 +2519,16 @@ bookmark_set (
|
|||
struct timespec const *times = val;
|
||||
json_t *ts_node;
|
||||
if (flags & BOOKMARK_FLAG(SET_ATIME)) {
|
||||
if (!valid_ts_sec(times[0].tv_sec)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
build_tsnode(×[0], &ts_node);
|
||||
json_object_sset_new(node, "date_last_used", ts_node);
|
||||
}
|
||||
if (flags & BOOKMARK_FLAG(SET_MTIME)) {
|
||||
if (!valid_ts_sec(times[1].tv_sec)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
build_tsnode(×[1], &ts_node);
|
||||
json_object_sset_new(node, "date_modified", ts_node);
|
||||
}
|
||||
|
|
|
@ -2038,12 +2038,7 @@ static int64_t
|
|||
timespec_to_usecs (
|
||||
struct timespec const *ts
|
||||
) {
|
||||
int64_t microsecs = ts->tv_sec * 1000000 + ts->tv_nsec / 1000;
|
||||
|
||||
if (microsecs < 0) {
|
||||
microsecs = 0;
|
||||
}
|
||||
return microsecs;
|
||||
return ts->tv_sec * 1000000 + ts->tv_nsec / 1000;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -3003,6 +2998,13 @@ static int
|
|||
backend_init (
|
||||
uint32_t flags
|
||||
) {
|
||||
struct timespec now;
|
||||
xgetrealtime(&now);
|
||||
if (!valid_ts_sec(now.tv_sec)) {
|
||||
log_puts("bad system time");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(flags & BOOKMARKFS_BACKEND_LIB_READY)
|
||||
&& !(flags & BOOKMARKFS_FRONTEND_MKFS)
|
||||
) {
|
||||
|
@ -3675,10 +3677,16 @@ bookmark_set (
|
|||
if (flags & BOOKMARK_FLAG(SET_ATIME, SET_MTIME)) {
|
||||
struct timespec const *times = val;
|
||||
if (flags & BOOKMARK_FLAG(SET_ATIME)) {
|
||||
if (!valid_ts_sec(times[0].tv_sec)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
place_cols.last_visit_date = timespec_to_usecs(×[0]);
|
||||
--xattr_id;
|
||||
}
|
||||
if (flags & BOOKMARK_FLAG(SET_MTIME)) {
|
||||
if (!valid_ts_sec(times[1].tv_sec)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
bm_cols.last_modified = timespec_to_usecs(×[1]);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -57,6 +57,17 @@
|
|||
#define FILENAME_BADLEN -2
|
||||
#define FILENAME_DOTDOT -3
|
||||
|
||||
/**
|
||||
* The maximum valid seconds that a signed 64-bit integer can hold
|
||||
* when converted to microseconds.
|
||||
*
|
||||
* Equals to `INT64_MAX / 1000000 - EPOCH_DIFF - 1`:
|
||||
* - See the Chromium backend for `EPOCH_DIFF`.
|
||||
* - Considering `tv_nsec`, subtract another second.
|
||||
*/
|
||||
#define TIMESPEC_SEC_MAX INT64_C(9211727563253)
|
||||
#define valid_ts_sec(sec) ((sec) >= 0 && (sec) <= TIMESPEC_SEC_MAX)
|
||||
|
||||
/**
|
||||
* Opens the parent directory of a file, and stores its basename
|
||||
* to `basename_ptr`.
|
||||
|
|
Loading…
Add table
Reference in a new issue