Concerned with migrating the key related structs in security/keys to use 64-bit time datatypes; and their corresponding system calls and macros. The patches are highly correlated and should be either accepted or rejected as a series. However, they were generated in such a way that they would be independent. This is for the sake of readability and to avoid the introduction of new warnings while building the kernel.
Aya Mahfouz (2): security: keys: migrate structs key and keyring_search_context security: keys: migrate struct key_preparsed_payload and time_t variables
include/linux/key-type.h | 2 +- include/linux/key.h | 6 +++--- security/keys/gc.c | 20 ++++++++++---------- security/keys/internal.h | 8 ++++---- security/keys/key.c | 20 +++++++------------- security/keys/keyring.c | 16 ++++++++-------- security/keys/permission.c | 3 +-- security/keys/proc.c | 8 ++++---- security/keys/process_keys.c | 2 +- 9 files changed, 39 insertions(+), 46 deletions(-)
Updates the structs key and keyring_search_context to use time64_t instead of time_t and timespec. All the functions that manipulate them have been changed accordingly too. This is to handle the y2038 problem where time_t and timespec will overflow in the year 2038.
Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Aya Mahfouz mahfouz.saif.elyazal@gmail.com --- include/linux/key.h | 6 +++--- security/keys/gc.c | 8 ++++---- security/keys/internal.h | 8 ++++---- security/keys/key.c | 16 +++++----------- security/keys/keyring.c | 16 ++++++++-------- security/keys/permission.c | 3 +-- security/keys/proc.c | 8 ++++---- security/keys/process_keys.c | 2 +- 8 files changed, 30 insertions(+), 37 deletions(-)
diff --git a/include/linux/key.h b/include/linux/key.h index 66f7052..c74c493 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -145,10 +145,10 @@ struct key { struct key_user *user; /* owner of this key */ void *security; /* security data for this key */ union { - time_t expiry; /* time at which key expires (or 0) */ - time_t revoked_at; /* time at which key was revoked */ + time64_t expiry; /* time at which key expires (or 0) */ + time64_t revoked_at; /* time at which key was revoked */ }; - time_t last_used_at; /* last time used for LRU keyring discard */ + time64_t last_used_at; /* last time used for LRU keyring discard */ kuid_t uid; kgid_t gid; key_perm_t perm; /* access permissions */ diff --git a/security/keys/gc.c b/security/keys/gc.c index addf060..fffc097 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -53,12 +53,12 @@ struct key_type key_type_dead = { * Schedule a garbage collection run. * - time precision isn't particularly important */ -void key_schedule_gc(time_t gc_at) +void key_schedule_gc(time64_t gc_at) { unsigned long expires; - time_t now = current_kernel_time().tv_sec; + time64_t now = ktime_get_real_seconds();
- kenter("%ld", gc_at - now); + kenter("%lld", gc_at - now);
if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { kdebug("IMMEDIATE"); @@ -234,7 +234,7 @@ continue_scanning:
if (gc_state & KEY_GC_SET_TIMER) { if (key->expiry > limit && key->expiry < new_timer) { - kdebug("will expire %x in %ld", + kdebug("will expire %x in %lld", key_serial(key), key->expiry - limit); new_timer = key->expiry; } diff --git a/security/keys/internal.h b/security/keys/internal.h index 5105c2c..5f4f007 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -125,7 +125,7 @@ struct keyring_search_context { int skipped_ret; bool possessed; key_ref_t result; - struct timespec now; + time64_t now; };
extern bool key_default_cmp(const struct key *key, @@ -164,8 +164,8 @@ extern void key_change_session_keyring(struct callback_head *twork);
extern struct work_struct key_gc_work; extern unsigned key_gc_delay; -extern void keyring_gc(struct key *keyring, time_t limit); -extern void key_schedule_gc(time_t gc_at); +extern void keyring_gc(struct key *keyring, time64_t limit); +extern void key_schedule_gc(time64_t gc_at); extern void key_schedule_gc_links(void); extern void key_gc_keytype(struct key_type *ktype);
@@ -204,7 +204,7 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id); /* * Determine whether a key is dead. */ -static inline bool key_is_dead(const struct key *key, time_t limit) +static inline bool key_is_dead(const struct key *key, time64_t limit) { return key->flags & ((1 << KEY_FLAG_DEAD) | diff --git a/security/keys/key.c b/security/keys/key.c index ab7997d..a7bc935 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -536,7 +536,6 @@ int key_reject_and_link(struct key *key, struct key *authkey) { struct assoc_array_edit *edit; - struct timespec now; int ret, awaken, link_ret = 0;
key_check(key); @@ -558,8 +557,7 @@ int key_reject_and_link(struct key *key, smp_wmb(); set_bit(KEY_FLAG_NEGATIVE, &key->flags); set_bit(KEY_FLAG_INSTANTIATED, &key->flags); - now = current_kernel_time(); - key->expiry = now.tv_sec + timeout; + key->expiry = ktime_get_real_seconds() + timeout; key_schedule_gc(key->expiry + key_gc_delay);
if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) @@ -678,15 +676,13 @@ found_kernel_type:
void key_set_timeout(struct key *key, unsigned timeout) { - struct timespec now; - time_t expiry = 0; + time64_t expiry = 0;
/* make the changes with the locks held to prevent races */ down_write(&key->sem);
if (timeout > 0) { - now = current_kernel_time(); - expiry = now.tv_sec + timeout; + expiry = ktime_get_real_seconds() + timeout; }
key->expiry = expiry; @@ -979,8 +975,7 @@ EXPORT_SYMBOL(key_update); */ void key_revoke(struct key *key) { - struct timespec now; - time_t time; + time64_t time;
key_check(key);
@@ -995,8 +990,7 @@ void key_revoke(struct key *key) key->type->revoke(key);
/* set the death time to no more than the expiry time */ - now = current_kernel_time(); - time = now.tv_sec; + time = ktime_get_real_seconds(); if (key->revoked_at == 0 || key->revoked_at > time) { key->revoked_at = time; key_schedule_gc(key->revoked_at + key_gc_delay); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index f931ccf..15e62f2 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -545,7 +545,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) goto skipped; }
- if (key->expiry && ctx->now.tv_sec >= key->expiry) { + if (key->expiry && ctx->now >= key->expiry) { if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED)) ctx->result = ERR_PTR(-EKEYEXPIRED); kleave(" = %d [expire]", ctx->skipped_ret); @@ -806,10 +806,10 @@ found: key = key_ref_to_ptr(ctx->result); key_check(key); if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) { - key->last_used_at = ctx->now.tv_sec; - keyring->last_used_at = ctx->now.tv_sec; + key->last_used_at = ctx->now; + keyring->last_used_at = ctx->now; while (sp > 0) - stack[--sp].keyring->last_used_at = ctx->now.tv_sec; + stack[--sp].keyring->last_used_at = ctx->now; } kleave(" = true"); return true; @@ -870,7 +870,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, }
rcu_read_lock(); - ctx->now = current_kernel_time(); + ctx->now = ktime_get_real_seconds(); if (search_nested_keyrings(keyring, ctx)) __key_get(key_ref_to_ptr(ctx->result)); rcu_read_unlock(); @@ -1011,7 +1011,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) * (ie. it has a zero usage count) */ if (!atomic_inc_not_zero(&keyring->usage)) continue; - keyring->last_used_at = current_kernel_time().tv_sec; + keyring->last_used_at = ktime_get_real_seconds(); goto out; } } @@ -1342,7 +1342,7 @@ static void keyring_revoke(struct key *keyring) static bool keyring_gc_select_iterator(void *object, void *iterator_data) { struct key *key = keyring_ptr_to_key(object); - time_t *limit = iterator_data; + time64_t *limit = iterator_data;
if (key_is_dead(key, *limit)) return false; @@ -1365,7 +1365,7 @@ static int keyring_gc_check_iterator(const void *object, void *iterator_data) * Not called with any locks held. The keyring's key struct will not be * deallocated under us as only our caller may deallocate it. */ -void keyring_gc(struct key *keyring, time_t limit) +void keyring_gc(struct key *keyring, time64_t limit) { int result;
diff --git a/security/keys/permission.c b/security/keys/permission.c index 732cc0b..507b1d41 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c @@ -100,8 +100,7 @@ int key_validate(const struct key *key)
/* check it hasn't expired */ if (key->expiry) { - struct timespec now = current_kernel_time(); - if (now.tv_sec >= key->expiry) + if (ktime_get_real_seconds() >= key->expiry) return -EKEYEXPIRED; }
diff --git a/security/keys/proc.c b/security/keys/proc.c index f0611a6..f3c20aa 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -178,7 +178,7 @@ static int proc_keys_show(struct seq_file *m, void *v) { struct rb_node *_p = v; struct key *key = rb_entry(_p, struct key, serial_node); - struct timespec now; + time64_t now; unsigned long timo; key_ref_t key_ref, skey_ref; char xbuf[12]; @@ -216,17 +216,17 @@ static int proc_keys_show(struct seq_file *m, void *v) if (rc < 0) return 0;
- now = current_kernel_time(); + now = ktime_get_real_seconds();
rcu_read_lock();
/* come up with a suitable timeout value */ if (key->expiry == 0) { memcpy(xbuf, "perm", 5); - } else if (now.tv_sec >= key->expiry) { + } else if (now >= key->expiry) { memcpy(xbuf, "expd", 5); } else { - timo = key->expiry - now.tv_sec; + timo = key->expiry - now;
if (timo < 60) sprintf(xbuf, "%lus", timo); diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index a3f85d2..7acede7 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -721,7 +721,7 @@ try_again: if (ret < 0) goto invalid_key;
- key->last_used_at = current_kernel_time().tv_sec; + key->last_used_at = ktime_get_real_seconds();
error: put_cred(ctx.cred);
Updates the struct key_preparsed_payload to use time64_t instead of time_t. In addition, several variables in the security/keys have been converted to time64_t and to use the S64_MAX macro instead of LONG_MAX. This is to handle the y2038 problem where time_t will overflow in 2038.
Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Aya Mahfouz mahfouz.saif.elyazal@gmail.com --- include/linux/key-type.h | 2 +- security/keys/gc.c | 12 ++++++------ security/keys/key.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 7463355..2c844ae 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -44,7 +44,7 @@ struct key_preparsed_payload { const void *data; /* Raw data */ size_t datalen; /* Raw datalen */ size_t quotalen; /* Quota length for proposed payload */ - time_t expiry; /* Expiry time of key */ + time64_t expiry; /* Expiry time of key */ bool trusted; /* True if key is trusted */ };
diff --git a/security/keys/gc.c b/security/keys/gc.c index fffc097..19b0760 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -32,7 +32,7 @@ DECLARE_WORK(key_gc_work, key_garbage_collector); static void key_gc_timer_func(unsigned long); static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0);
-static time_t key_gc_next_run = LONG_MAX; +static time64_t key_gc_next_run = S64_MAX; static struct key_type *key_gc_dead_keytype;
static unsigned long key_gc_flags; @@ -87,7 +87,7 @@ void key_schedule_gc_links(void) static void key_gc_timer_func(unsigned long data) { kenter(""); - key_gc_next_run = LONG_MAX; + key_gc_next_run = S64_MAX; key_schedule_gc_links(); }
@@ -186,11 +186,11 @@ static void key_garbage_collector(struct work_struct *work)
struct rb_node *cursor; struct key *key; - time_t new_timer, limit; + time64_t new_timer, limit;
kenter("[%lx,%x]", key_gc_flags, gc_state);
- limit = current_kernel_time().tv_sec; + limit = ktime_get_real_seconds(); if (limit > key_gc_delay) limit -= key_gc_delay; else @@ -206,7 +206,7 @@ static void key_garbage_collector(struct work_struct *work) gc_state |= KEY_GC_REAPING_DEAD_1; kdebug("new pass %x", gc_state);
- new_timer = LONG_MAX; + new_timer = S64_MAX;
/* As only this function is permitted to remove things from the key * serial tree, if cursor is non-NULL then it will always point to a @@ -275,7 +275,7 @@ maybe_resched: */ kdebug("pass complete");
- if (gc_state & KEY_GC_SET_TIMER && new_timer != (time_t)LONG_MAX) { + if (gc_state & KEY_GC_SET_TIMER && new_timer != (time64_t)S64_MAX) { new_timer += key_gc_delay; key_schedule_gc(new_timer); } diff --git a/security/keys/key.c b/security/keys/key.c index a7bc935..85d3ae7 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -436,7 +436,7 @@ static int __key_instantiate_and_link(struct key *key, if (authkey) key_revoke(authkey);
- if (prep->expiry != TIME_T_MAX) { + if (prep->expiry != S64_MAX) { key->expiry = prep->expiry; key_schedule_gc(prep->expiry + key_gc_delay); } @@ -482,7 +482,7 @@ int key_instantiate_and_link(struct key *key, prep.data = data; prep.datalen = datalen; prep.quotalen = key->type->def_datalen; - prep.expiry = TIME_T_MAX; + prep.expiry = S64_MAX; if (key->type->preparse) { ret = key->type->preparse(&prep); if (ret < 0)