Commit 074d5898 authored by Baolin Wang's avatar Baolin Wang Committed by David Howells

security: keys: Replace time_t/timespec with time64_t

The 'struct key' will use 'time_t' which we try to remove in the
kernel, since 'time_t' is not year 2038 safe on 32bit systems.
Also the 'struct keyring_search_context' will use 'timespec' type
to record current time, which is also not year 2038 safe on 32bit
systems.

Thus this patch replaces 'time_t' with 'time64_t' which is year 2038
safe for 'struct key', and replace 'timespec' with 'time64_t' for the
'struct keyring_search_context', since we only look at the the seconds
part of 'timespec' variable. Moreover we also change the codes where
using the 'time_t' and 'timespec', and we can get current time by
ktime_get_real_seconds() instead of current_kernel_time(), and use
'TIME64_MAX' macro to initialize the 'time64_t' type variable.

Especially in proc.c file, we have replaced 'unsigned long' and 'timespec'
type with 'u64' and 'time64_t' type to save the timeout value, which means
user will get one 'u64' type timeout value by issuing proc_keys_show()
function.
Signed-off-by: default avatarBaolin Wang <baolin.wang@linaro.org>
Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Reviewed-by: default avatarJames Morris <james.l.morris@oracle.com>
parent be543dd6
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/assoc_array.h> #include <linux/assoc_array.h>
#include <linux/refcount.h> #include <linux/refcount.h>
#include <linux/time64.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/uidgid.h> #include <linux/uidgid.h>
...@@ -162,10 +163,10 @@ struct key { ...@@ -162,10 +163,10 @@ struct key {
struct key_user *user; /* owner of this key */ struct key_user *user; /* owner of this key */
void *security; /* security data for this key */ void *security; /* security data for this key */
union { union {
time_t expiry; /* time at which key expires (or 0) */ time64_t expiry; /* time at which key expires (or 0) */
time_t revoked_at; /* time at which key was revoked */ 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; kuid_t uid;
kgid_t gid; kgid_t gid;
key_perm_t perm; /* access permissions */ key_perm_t perm; /* access permissions */
......
...@@ -32,7 +32,7 @@ DECLARE_WORK(key_gc_work, key_garbage_collector); ...@@ -32,7 +32,7 @@ DECLARE_WORK(key_gc_work, key_garbage_collector);
static void key_gc_timer_func(unsigned long); static void key_gc_timer_func(unsigned long);
static DEFINE_TIMER(key_gc_timer, key_gc_timer_func); static DEFINE_TIMER(key_gc_timer, key_gc_timer_func);
static time_t key_gc_next_run = LONG_MAX; static time64_t key_gc_next_run = TIME64_MAX;
static struct key_type *key_gc_dead_keytype; static struct key_type *key_gc_dead_keytype;
static unsigned long key_gc_flags; static unsigned long key_gc_flags;
...@@ -53,12 +53,12 @@ struct key_type key_type_dead = { ...@@ -53,12 +53,12 @@ struct key_type key_type_dead = {
* Schedule a garbage collection run. * Schedule a garbage collection run.
* - time precision isn't particularly important * - 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; 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)) { if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) {
kdebug("IMMEDIATE"); kdebug("IMMEDIATE");
...@@ -87,7 +87,7 @@ void key_schedule_gc_links(void) ...@@ -87,7 +87,7 @@ void key_schedule_gc_links(void)
static void key_gc_timer_func(unsigned long data) static void key_gc_timer_func(unsigned long data)
{ {
kenter(""); kenter("");
key_gc_next_run = LONG_MAX; key_gc_next_run = TIME64_MAX;
key_schedule_gc_links(); key_schedule_gc_links();
} }
...@@ -184,11 +184,11 @@ static void key_garbage_collector(struct work_struct *work) ...@@ -184,11 +184,11 @@ static void key_garbage_collector(struct work_struct *work)
struct rb_node *cursor; struct rb_node *cursor;
struct key *key; struct key *key;
time_t new_timer, limit; time64_t new_timer, limit;
kenter("[%lx,%x]", key_gc_flags, gc_state); kenter("[%lx,%x]", key_gc_flags, gc_state);
limit = current_kernel_time().tv_sec; limit = ktime_get_real_seconds();
if (limit > key_gc_delay) if (limit > key_gc_delay)
limit -= key_gc_delay; limit -= key_gc_delay;
else else
...@@ -204,7 +204,7 @@ static void key_garbage_collector(struct work_struct *work) ...@@ -204,7 +204,7 @@ static void key_garbage_collector(struct work_struct *work)
gc_state |= KEY_GC_REAPING_DEAD_1; gc_state |= KEY_GC_REAPING_DEAD_1;
kdebug("new pass %x", gc_state); kdebug("new pass %x", gc_state);
new_timer = LONG_MAX; new_timer = TIME64_MAX;
/* As only this function is permitted to remove things from the key /* 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 * serial tree, if cursor is non-NULL then it will always point to a
...@@ -235,7 +235,7 @@ static void key_garbage_collector(struct work_struct *work) ...@@ -235,7 +235,7 @@ static void key_garbage_collector(struct work_struct *work)
if (gc_state & KEY_GC_SET_TIMER) { if (gc_state & KEY_GC_SET_TIMER) {
if (key->expiry > limit && key->expiry < new_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); key_serial(key), key->expiry - limit);
new_timer = key->expiry; new_timer = key->expiry;
} }
...@@ -276,7 +276,7 @@ static void key_garbage_collector(struct work_struct *work) ...@@ -276,7 +276,7 @@ static void key_garbage_collector(struct work_struct *work)
*/ */
kdebug("pass complete"); 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)TIME64_MAX) {
new_timer += key_gc_delay; new_timer += key_gc_delay;
key_schedule_gc(new_timer); key_schedule_gc(new_timer);
} }
......
...@@ -130,7 +130,7 @@ struct keyring_search_context { ...@@ -130,7 +130,7 @@ struct keyring_search_context {
int skipped_ret; int skipped_ret;
bool possessed; bool possessed;
key_ref_t result; key_ref_t result;
struct timespec now; time64_t now;
}; };
extern bool key_default_cmp(const struct key *key, extern bool key_default_cmp(const struct key *key,
...@@ -169,10 +169,10 @@ extern void key_change_session_keyring(struct callback_head *twork); ...@@ -169,10 +169,10 @@ extern void key_change_session_keyring(struct callback_head *twork);
extern struct work_struct key_gc_work; extern struct work_struct key_gc_work;
extern unsigned key_gc_delay; extern unsigned key_gc_delay;
extern void keyring_gc(struct key *keyring, time_t limit); extern void keyring_gc(struct key *keyring, time64_t limit);
extern void keyring_restriction_gc(struct key *keyring, extern void keyring_restriction_gc(struct key *keyring,
struct key_type *dead_type); struct key_type *dead_type);
extern void key_schedule_gc(time_t gc_at); extern void key_schedule_gc(time64_t gc_at);
extern void key_schedule_gc_links(void); extern void key_schedule_gc_links(void);
extern void key_gc_keytype(struct key_type *ktype); extern void key_gc_keytype(struct key_type *ktype);
...@@ -211,7 +211,7 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id); ...@@ -211,7 +211,7 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
/* /*
* Determine whether a key is dead. * 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 return
key->flags & ((1 << KEY_FLAG_DEAD) | key->flags & ((1 << KEY_FLAG_DEAD) |
......
...@@ -570,7 +570,6 @@ int key_reject_and_link(struct key *key, ...@@ -570,7 +570,6 @@ int key_reject_and_link(struct key *key,
struct key *authkey) struct key *authkey)
{ {
struct assoc_array_edit *edit; struct assoc_array_edit *edit;
struct timespec now;
int ret, awaken, link_ret = 0; int ret, awaken, link_ret = 0;
key_check(key); key_check(key);
...@@ -593,8 +592,7 @@ int key_reject_and_link(struct key *key, ...@@ -593,8 +592,7 @@ int key_reject_and_link(struct key *key,
/* mark the key as being negatively instantiated */ /* mark the key as being negatively instantiated */
atomic_inc(&key->user->nikeys); atomic_inc(&key->user->nikeys);
mark_key_instantiated(key, -error); mark_key_instantiated(key, -error);
now = current_kernel_time(); key->expiry = ktime_get_real_seconds() + timeout;
key->expiry = now.tv_sec + timeout;
key_schedule_gc(key->expiry + key_gc_delay); key_schedule_gc(key->expiry + key_gc_delay);
if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
...@@ -710,16 +708,13 @@ struct key_type *key_type_lookup(const char *type) ...@@ -710,16 +708,13 @@ struct key_type *key_type_lookup(const char *type)
void key_set_timeout(struct key *key, unsigned timeout) void key_set_timeout(struct key *key, unsigned timeout)
{ {
struct timespec now; time64_t expiry = 0;
time_t expiry = 0;
/* make the changes with the locks held to prevent races */ /* make the changes with the locks held to prevent races */
down_write(&key->sem); down_write(&key->sem);
if (timeout > 0) { if (timeout > 0)
now = current_kernel_time(); expiry = ktime_get_real_seconds() + timeout;
expiry = now.tv_sec + timeout;
}
key->expiry = expiry; key->expiry = expiry;
key_schedule_gc(key->expiry + key_gc_delay); key_schedule_gc(key->expiry + key_gc_delay);
...@@ -1028,8 +1023,7 @@ EXPORT_SYMBOL(key_update); ...@@ -1028,8 +1023,7 @@ EXPORT_SYMBOL(key_update);
*/ */
void key_revoke(struct key *key) void key_revoke(struct key *key)
{ {
struct timespec now; time64_t time;
time_t time;
key_check(key); key_check(key);
...@@ -1044,8 +1038,7 @@ void key_revoke(struct key *key) ...@@ -1044,8 +1038,7 @@ void key_revoke(struct key *key)
key->type->revoke(key); key->type->revoke(key);
/* set the death time to no more than the expiry time */ /* set the death time to no more than the expiry time */
now = current_kernel_time(); time = ktime_get_real_seconds();
time = now.tv_sec;
if (key->revoked_at == 0 || key->revoked_at > time) { if (key->revoked_at == 0 || key->revoked_at > time) {
key->revoked_at = time; key->revoked_at = time;
key_schedule_gc(key->revoked_at + key_gc_delay); key_schedule_gc(key->revoked_at + key_gc_delay);
......
...@@ -565,7 +565,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) ...@@ -565,7 +565,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
/* skip invalidated, revoked and expired keys */ /* skip invalidated, revoked and expired keys */
if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) {
time_t expiry = READ_ONCE(key->expiry); time64_t expiry = READ_ONCE(key->expiry);
if (kflags & ((1 << KEY_FLAG_INVALIDATED) | if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED))) { (1 << KEY_FLAG_REVOKED))) {
...@@ -574,7 +574,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) ...@@ -574,7 +574,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
goto skipped; goto skipped;
} }
if (expiry && ctx->now.tv_sec >= expiry) { if (expiry && ctx->now >= expiry) {
if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED)) if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED))
ctx->result = ERR_PTR(-EKEYEXPIRED); ctx->result = ERR_PTR(-EKEYEXPIRED);
kleave(" = %d [expire]", ctx->skipped_ret); kleave(" = %d [expire]", ctx->skipped_ret);
...@@ -834,10 +834,10 @@ static bool search_nested_keyrings(struct key *keyring, ...@@ -834,10 +834,10 @@ static bool search_nested_keyrings(struct key *keyring,
key = key_ref_to_ptr(ctx->result); key = key_ref_to_ptr(ctx->result);
key_check(key); key_check(key);
if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) { if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) {
key->last_used_at = ctx->now.tv_sec; key->last_used_at = ctx->now;
keyring->last_used_at = ctx->now.tv_sec; keyring->last_used_at = ctx->now;
while (sp > 0) while (sp > 0)
stack[--sp].keyring->last_used_at = ctx->now.tv_sec; stack[--sp].keyring->last_used_at = ctx->now;
} }
kleave(" = true"); kleave(" = true");
return true; return true;
...@@ -898,7 +898,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, ...@@ -898,7 +898,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
} }
rcu_read_lock(); rcu_read_lock();
ctx->now = current_kernel_time(); ctx->now = ktime_get_real_seconds();
if (search_nested_keyrings(keyring, ctx)) if (search_nested_keyrings(keyring, ctx))
__key_get(key_ref_to_ptr(ctx->result)); __key_get(key_ref_to_ptr(ctx->result));
rcu_read_unlock(); rcu_read_unlock();
...@@ -1149,7 +1149,7 @@ struct key *find_keyring_by_name(const char *name, bool uid_keyring) ...@@ -1149,7 +1149,7 @@ struct key *find_keyring_by_name(const char *name, bool uid_keyring)
* (ie. it has a zero usage count) */ * (ie. it has a zero usage count) */
if (!refcount_inc_not_zero(&keyring->usage)) if (!refcount_inc_not_zero(&keyring->usage))
continue; continue;
keyring->last_used_at = current_kernel_time().tv_sec; keyring->last_used_at = ktime_get_real_seconds();
goto out; goto out;
} }
} }
...@@ -1489,7 +1489,7 @@ static void keyring_revoke(struct key *keyring) ...@@ -1489,7 +1489,7 @@ static void keyring_revoke(struct key *keyring)
static bool keyring_gc_select_iterator(void *object, void *iterator_data) static bool keyring_gc_select_iterator(void *object, void *iterator_data)
{ {
struct key *key = keyring_ptr_to_key(object); struct key *key = keyring_ptr_to_key(object);
time_t *limit = iterator_data; time64_t *limit = iterator_data;
if (key_is_dead(key, *limit)) if (key_is_dead(key, *limit))
return false; return false;
...@@ -1500,7 +1500,7 @@ static bool keyring_gc_select_iterator(void *object, void *iterator_data) ...@@ -1500,7 +1500,7 @@ static bool keyring_gc_select_iterator(void *object, void *iterator_data)
static int keyring_gc_check_iterator(const void *object, void *iterator_data) static int keyring_gc_check_iterator(const void *object, void *iterator_data)
{ {
const struct key *key = keyring_ptr_to_key(object); const struct key *key = keyring_ptr_to_key(object);
time_t *limit = iterator_data; time64_t *limit = iterator_data;
key_check(key); key_check(key);
return key_is_dead(key, *limit); return key_is_dead(key, *limit);
...@@ -1512,7 +1512,7 @@ static int keyring_gc_check_iterator(const void *object, void *iterator_data) ...@@ -1512,7 +1512,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 * Not called with any locks held. The keyring's key struct will not be
* deallocated under us as only our caller may deallocate it. * 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; int result;
......
...@@ -89,7 +89,7 @@ EXPORT_SYMBOL(key_task_permission); ...@@ -89,7 +89,7 @@ EXPORT_SYMBOL(key_task_permission);
int key_validate(const struct key *key) int key_validate(const struct key *key)
{ {
unsigned long flags = READ_ONCE(key->flags); unsigned long flags = READ_ONCE(key->flags);
time_t expiry = READ_ONCE(key->expiry); time64_t expiry = READ_ONCE(key->expiry);
if (flags & (1 << KEY_FLAG_INVALIDATED)) if (flags & (1 << KEY_FLAG_INVALIDATED))
return -ENOKEY; return -ENOKEY;
...@@ -101,8 +101,7 @@ int key_validate(const struct key *key) ...@@ -101,8 +101,7 @@ int key_validate(const struct key *key)
/* check it hasn't expired */ /* check it hasn't expired */
if (expiry) { if (expiry) {
struct timespec now = current_kernel_time(); if (ktime_get_real_seconds() >= expiry)
if (now.tv_sec >= expiry)
return -EKEYEXPIRED; return -EKEYEXPIRED;
} }
......
...@@ -178,13 +178,12 @@ static int proc_keys_show(struct seq_file *m, void *v) ...@@ -178,13 +178,12 @@ static int proc_keys_show(struct seq_file *m, void *v)
{ {
struct rb_node *_p = v; struct rb_node *_p = v;
struct key *key = rb_entry(_p, struct key, serial_node); struct key *key = rb_entry(_p, struct key, serial_node);
struct timespec now;
time_t expiry;
unsigned long timo;
unsigned long flags; unsigned long flags;
key_ref_t key_ref, skey_ref; key_ref_t key_ref, skey_ref;
time64_t now, expiry;
char xbuf[16]; char xbuf[16];
short state; short state;
u64 timo;
int rc; int rc;
struct keyring_search_context ctx = { struct keyring_search_context ctx = {
...@@ -215,7 +214,7 @@ static int proc_keys_show(struct seq_file *m, void *v) ...@@ -215,7 +214,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
if (rc < 0) if (rc < 0)
return 0; return 0;
now = current_kernel_time(); now = ktime_get_real_seconds();
rcu_read_lock(); rcu_read_lock();
...@@ -223,21 +222,21 @@ static int proc_keys_show(struct seq_file *m, void *v) ...@@ -223,21 +222,21 @@ static int proc_keys_show(struct seq_file *m, void *v)
expiry = READ_ONCE(key->expiry); expiry = READ_ONCE(key->expiry);
if (expiry == 0) { if (expiry == 0) {
memcpy(xbuf, "perm", 5); memcpy(xbuf, "perm", 5);
} else if (now.tv_sec >= expiry) { } else if (now >= expiry) {
memcpy(xbuf, "expd", 5); memcpy(xbuf, "expd", 5);
} else { } else {
timo = expiry - now.tv_sec; timo = expiry - now;
if (timo < 60) if (timo < 60)
sprintf(xbuf, "%lus", timo); sprintf(xbuf, "%llus", timo);
else if (timo < 60*60) else if (timo < 60*60)
sprintf(xbuf, "%lum", timo / 60); sprintf(xbuf, "%llum", div_u64(timo, 60));
else if (timo < 60*60*24) else if (timo < 60*60*24)
sprintf(xbuf, "%luh", timo / (60*60)); sprintf(xbuf, "%lluh", div_u64(timo, 60 * 60));
else if (timo < 60*60*24*7) else if (timo < 60*60*24*7)
sprintf(xbuf, "%lud", timo / (60*60*24)); sprintf(xbuf, "%llud", div_u64(timo, 60 * 60 * 24));
else else
sprintf(xbuf, "%luw", timo / (60*60*24*7)); sprintf(xbuf, "%lluw", div_u64(timo, 60 * 60 * 24 * 7));
} }
state = key_read_state(key); state = key_read_state(key);
......
...@@ -738,7 +738,7 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, ...@@ -738,7 +738,7 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
if (ret < 0) if (ret < 0)
goto invalid_key; goto invalid_key;
key->last_used_at = current_kernel_time().tv_sec; key->last_used_at = ktime_get_real_seconds();
error: error:
put_cred(ctx.cred); put_cred(ctx.cred);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment