aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBaolin Wang <baolin.wang@linaro.org>2017-11-15 11:38:45 -0500
committerDavid Howells <dhowells@redhat.com>2017-11-15 11:38:45 -0500
commit074d58989569b39f04294c90ef36dd82b8c2cc1a (patch)
tree81aeddd29a2fbc619ebb1c43fa25134e7c6ebeb8
parentbe543dd626c0a23829e9cc1a28e1e3af4cd9ced6 (diff)
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: Baolin Wang <baolin.wang@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: James Morris <james.l.morris@oracle.com>
-rw-r--r--include/linux/key.h7
-rw-r--r--security/keys/gc.c20
-rw-r--r--security/keys/internal.h8
-rw-r--r--security/keys/key.c19
-rw-r--r--security/keys/keyring.c20
-rw-r--r--security/keys/permission.c5
-rw-r--r--security/keys/proc.c21
-rw-r--r--security/keys/process_keys.c2
8 files changed, 47 insertions, 55 deletions
diff --git a/include/linux/key.h b/include/linux/key.h
index 8a15cabe928d..e58ee10f6e58 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -24,6 +24,7 @@
24#include <linux/atomic.h> 24#include <linux/atomic.h>
25#include <linux/assoc_array.h> 25#include <linux/assoc_array.h>
26#include <linux/refcount.h> 26#include <linux/refcount.h>
27#include <linux/time64.h>
27 28
28#ifdef __KERNEL__ 29#ifdef __KERNEL__
29#include <linux/uidgid.h> 30#include <linux/uidgid.h>
@@ -162,10 +163,10 @@ struct key {
162 struct key_user *user; /* owner of this key */ 163 struct key_user *user; /* owner of this key */
163 void *security; /* security data for this key */ 164 void *security; /* security data for this key */
164 union { 165 union {
165 time_t expiry; /* time at which key expires (or 0) */ 166 time64_t expiry; /* time at which key expires (or 0) */
166 time_t revoked_at; /* time at which key was revoked */ 167 time64_t revoked_at; /* time at which key was revoked */
167 }; 168 };
168 time_t last_used_at; /* last time used for LRU keyring discard */ 169 time64_t last_used_at; /* last time used for LRU keyring discard */
169 kuid_t uid; 170 kuid_t uid;
170 kgid_t gid; 171 kgid_t gid;
171 key_perm_t perm; /* access permissions */ 172 key_perm_t perm; /* access permissions */
diff --git a/security/keys/gc.c b/security/keys/gc.c
index afb3a9175d76..6713fee893fb 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -32,7 +32,7 @@ DECLARE_WORK(key_gc_work, key_garbage_collector);
32static void key_gc_timer_func(unsigned long); 32static void key_gc_timer_func(unsigned long);
33static DEFINE_TIMER(key_gc_timer, key_gc_timer_func); 33static DEFINE_TIMER(key_gc_timer, key_gc_timer_func);
34 34
35static time_t key_gc_next_run = LONG_MAX; 35static time64_t key_gc_next_run = TIME64_MAX;
36static struct key_type *key_gc_dead_keytype; 36static struct key_type *key_gc_dead_keytype;
37 37
38static unsigned long key_gc_flags; 38static unsigned long key_gc_flags;
@@ -53,12 +53,12 @@ struct key_type key_type_dead = {
53 * Schedule a garbage collection run. 53 * Schedule a garbage collection run.
54 * - time precision isn't particularly important 54 * - time precision isn't particularly important
55 */ 55 */
56void key_schedule_gc(time_t gc_at) 56void key_schedule_gc(time64_t gc_at)
57{ 57{
58 unsigned long expires; 58 unsigned long expires;
59 time_t now = current_kernel_time().tv_sec; 59 time64_t now = ktime_get_real_seconds();
60 60
61 kenter("%ld", gc_at - now); 61 kenter("%lld", gc_at - now);
62 62
63 if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { 63 if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) {
64 kdebug("IMMEDIATE"); 64 kdebug("IMMEDIATE");
@@ -87,7 +87,7 @@ void key_schedule_gc_links(void)
87static void key_gc_timer_func(unsigned long data) 87static void key_gc_timer_func(unsigned long data)
88{ 88{
89 kenter(""); 89 kenter("");
90 key_gc_next_run = LONG_MAX; 90 key_gc_next_run = TIME64_MAX;
91 key_schedule_gc_links(); 91 key_schedule_gc_links();
92} 92}
93 93
@@ -184,11 +184,11 @@ static void key_garbage_collector(struct work_struct *work)
184 184
185 struct rb_node *cursor; 185 struct rb_node *cursor;
186 struct key *key; 186 struct key *key;
187 time_t new_timer, limit; 187 time64_t new_timer, limit;
188 188
189 kenter("[%lx,%x]", key_gc_flags, gc_state); 189 kenter("[%lx,%x]", key_gc_flags, gc_state);
190 190
191 limit = current_kernel_time().tv_sec; 191 limit = ktime_get_real_seconds();
192 if (limit > key_gc_delay) 192 if (limit > key_gc_delay)
193 limit -= key_gc_delay; 193 limit -= key_gc_delay;
194 else 194 else
@@ -204,7 +204,7 @@ static void key_garbage_collector(struct work_struct *work)
204 gc_state |= KEY_GC_REAPING_DEAD_1; 204 gc_state |= KEY_GC_REAPING_DEAD_1;
205 kdebug("new pass %x", gc_state); 205 kdebug("new pass %x", gc_state);
206 206
207 new_timer = LONG_MAX; 207 new_timer = TIME64_MAX;
208 208
209 /* As only this function is permitted to remove things from the key 209 /* As only this function is permitted to remove things from the key
210 * serial tree, if cursor is non-NULL then it will always point to a 210 * serial tree, if cursor is non-NULL then it will always point to a
@@ -235,7 +235,7 @@ continue_scanning:
235 235
236 if (gc_state & KEY_GC_SET_TIMER) { 236 if (gc_state & KEY_GC_SET_TIMER) {
237 if (key->expiry > limit && key->expiry < new_timer) { 237 if (key->expiry > limit && key->expiry < new_timer) {
238 kdebug("will expire %x in %ld", 238 kdebug("will expire %x in %lld",
239 key_serial(key), key->expiry - limit); 239 key_serial(key), key->expiry - limit);
240 new_timer = key->expiry; 240 new_timer = key->expiry;
241 } 241 }
@@ -276,7 +276,7 @@ maybe_resched:
276 */ 276 */
277 kdebug("pass complete"); 277 kdebug("pass complete");
278 278
279 if (gc_state & KEY_GC_SET_TIMER && new_timer != (time_t)LONG_MAX) { 279 if (gc_state & KEY_GC_SET_TIMER && new_timer != (time64_t)TIME64_MAX) {
280 new_timer += key_gc_delay; 280 new_timer += key_gc_delay;
281 key_schedule_gc(new_timer); 281 key_schedule_gc(new_timer);
282 } 282 }
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 503adbae7b0d..9f8208dc0e55 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -130,7 +130,7 @@ struct keyring_search_context {
130 int skipped_ret; 130 int skipped_ret;
131 bool possessed; 131 bool possessed;
132 key_ref_t result; 132 key_ref_t result;
133 struct timespec now; 133 time64_t now;
134}; 134};
135 135
136extern bool key_default_cmp(const struct key *key, 136extern bool key_default_cmp(const struct key *key,
@@ -169,10 +169,10 @@ extern void key_change_session_keyring(struct callback_head *twork);
169 169
170extern struct work_struct key_gc_work; 170extern struct work_struct key_gc_work;
171extern unsigned key_gc_delay; 171extern unsigned key_gc_delay;
172extern void keyring_gc(struct key *keyring, time_t limit); 172extern void keyring_gc(struct key *keyring, time64_t limit);
173extern void keyring_restriction_gc(struct key *keyring, 173extern void keyring_restriction_gc(struct key *keyring,
174 struct key_type *dead_type); 174 struct key_type *dead_type);
175extern void key_schedule_gc(time_t gc_at); 175extern void key_schedule_gc(time64_t gc_at);
176extern void key_schedule_gc_links(void); 176extern void key_schedule_gc_links(void);
177extern void key_gc_keytype(struct key_type *ktype); 177extern void key_gc_keytype(struct key_type *ktype);
178 178
@@ -211,7 +211,7 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
211/* 211/*
212 * Determine whether a key is dead. 212 * Determine whether a key is dead.
213 */ 213 */
214static inline bool key_is_dead(const struct key *key, time_t limit) 214static inline bool key_is_dead(const struct key *key, time64_t limit)
215{ 215{
216 return 216 return
217 key->flags & ((1 << KEY_FLAG_DEAD) | 217 key->flags & ((1 << KEY_FLAG_DEAD) |
diff --git a/security/keys/key.c b/security/keys/key.c
index 83bf4b4afd49..32fd33d45959 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -570,7 +570,6 @@ int key_reject_and_link(struct key *key,
570 struct key *authkey) 570 struct key *authkey)
571{ 571{
572 struct assoc_array_edit *edit; 572 struct assoc_array_edit *edit;
573 struct timespec now;
574 int ret, awaken, link_ret = 0; 573 int ret, awaken, link_ret = 0;
575 574
576 key_check(key); 575 key_check(key);
@@ -593,8 +592,7 @@ int key_reject_and_link(struct key *key,
593 /* mark the key as being negatively instantiated */ 592 /* mark the key as being negatively instantiated */
594 atomic_inc(&key->user->nikeys); 593 atomic_inc(&key->user->nikeys);
595 mark_key_instantiated(key, -error); 594 mark_key_instantiated(key, -error);
596 now = current_kernel_time(); 595 key->expiry = ktime_get_real_seconds() + timeout;
597 key->expiry = now.tv_sec + timeout;
598 key_schedule_gc(key->expiry + key_gc_delay); 596 key_schedule_gc(key->expiry + key_gc_delay);
599 597
600 if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) 598 if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
@@ -710,16 +708,13 @@ found_kernel_type:
710 708
711void key_set_timeout(struct key *key, unsigned timeout) 709void key_set_timeout(struct key *key, unsigned timeout)
712{ 710{
713 struct timespec now; 711 time64_t expiry = 0;
714 time_t expiry = 0;
715 712
716 /* make the changes with the locks held to prevent races */ 713 /* make the changes with the locks held to prevent races */
717 down_write(&key->sem); 714 down_write(&key->sem);
718 715
719 if (timeout > 0) { 716 if (timeout > 0)
720 now = current_kernel_time(); 717 expiry = ktime_get_real_seconds() + timeout;
721 expiry = now.tv_sec + timeout;
722 }
723 718
724 key->expiry = expiry; 719 key->expiry = expiry;
725 key_schedule_gc(key->expiry + key_gc_delay); 720 key_schedule_gc(key->expiry + key_gc_delay);
@@ -1028,8 +1023,7 @@ EXPORT_SYMBOL(key_update);
1028 */ 1023 */
1029void key_revoke(struct key *key) 1024void key_revoke(struct key *key)
1030{ 1025{
1031 struct timespec now; 1026 time64_t time;
1032 time_t time;
1033 1027
1034 key_check(key); 1028 key_check(key);
1035 1029
@@ -1044,8 +1038,7 @@ void key_revoke(struct key *key)
1044 key->type->revoke(key); 1038 key->type->revoke(key);
1045 1039
1046 /* set the death time to no more than the expiry time */ 1040 /* set the death time to no more than the expiry time */
1047 now = current_kernel_time(); 1041 time = ktime_get_real_seconds();
1048 time = now.tv_sec;
1049 if (key->revoked_at == 0 || key->revoked_at > time) { 1042 if (key->revoked_at == 0 || key->revoked_at > time) {
1050 key->revoked_at = time; 1043 key->revoked_at = time;
1051 key_schedule_gc(key->revoked_at + key_gc_delay); 1044 key_schedule_gc(key->revoked_at + key_gc_delay);
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 36f842ec87f0..d0bccebbd3b5 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -565,7 +565,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
565 565
566 /* skip invalidated, revoked and expired keys */ 566 /* skip invalidated, revoked and expired keys */
567 if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { 567 if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) {
568 time_t expiry = READ_ONCE(key->expiry); 568 time64_t expiry = READ_ONCE(key->expiry);
569 569
570 if (kflags & ((1 << KEY_FLAG_INVALIDATED) | 570 if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
571 (1 << KEY_FLAG_REVOKED))) { 571 (1 << KEY_FLAG_REVOKED))) {
@@ -574,7 +574,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
574 goto skipped; 574 goto skipped;
575 } 575 }
576 576
577 if (expiry && ctx->now.tv_sec >= expiry) { 577 if (expiry && ctx->now >= expiry) {
578 if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED)) 578 if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED))
579 ctx->result = ERR_PTR(-EKEYEXPIRED); 579 ctx->result = ERR_PTR(-EKEYEXPIRED);
580 kleave(" = %d [expire]", ctx->skipped_ret); 580 kleave(" = %d [expire]", ctx->skipped_ret);
@@ -834,10 +834,10 @@ found:
834 key = key_ref_to_ptr(ctx->result); 834 key = key_ref_to_ptr(ctx->result);
835 key_check(key); 835 key_check(key);
836 if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) { 836 if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) {
837 key->last_used_at = ctx->now.tv_sec; 837 key->last_used_at = ctx->now;
838 keyring->last_used_at = ctx->now.tv_sec; 838 keyring->last_used_at = ctx->now;
839 while (sp > 0) 839 while (sp > 0)
840 stack[--sp].keyring->last_used_at = ctx->now.tv_sec; 840 stack[--sp].keyring->last_used_at = ctx->now;
841 } 841 }
842 kleave(" = true"); 842 kleave(" = true");
843 return true; 843 return true;
@@ -898,7 +898,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
898 } 898 }
899 899
900 rcu_read_lock(); 900 rcu_read_lock();
901 ctx->now = current_kernel_time(); 901 ctx->now = ktime_get_real_seconds();
902 if (search_nested_keyrings(keyring, ctx)) 902 if (search_nested_keyrings(keyring, ctx))
903 __key_get(key_ref_to_ptr(ctx->result)); 903 __key_get(key_ref_to_ptr(ctx->result));
904 rcu_read_unlock(); 904 rcu_read_unlock();
@@ -1149,7 +1149,7 @@ struct key *find_keyring_by_name(const char *name, bool uid_keyring)
1149 * (ie. it has a zero usage count) */ 1149 * (ie. it has a zero usage count) */
1150 if (!refcount_inc_not_zero(&keyring->usage)) 1150 if (!refcount_inc_not_zero(&keyring->usage))
1151 continue; 1151 continue;
1152 keyring->last_used_at = current_kernel_time().tv_sec; 1152 keyring->last_used_at = ktime_get_real_seconds();
1153 goto out; 1153 goto out;
1154 } 1154 }
1155 } 1155 }
@@ -1489,7 +1489,7 @@ static void keyring_revoke(struct key *keyring)
1489static bool keyring_gc_select_iterator(void *object, void *iterator_data) 1489static bool keyring_gc_select_iterator(void *object, void *iterator_data)
1490{ 1490{
1491 struct key *key = keyring_ptr_to_key(object); 1491 struct key *key = keyring_ptr_to_key(object);
1492 time_t *limit = iterator_data; 1492 time64_t *limit = iterator_data;
1493 1493
1494 if (key_is_dead(key, *limit)) 1494 if (key_is_dead(key, *limit))
1495 return false; 1495 return false;
@@ -1500,7 +1500,7 @@ static bool keyring_gc_select_iterator(void *object, void *iterator_data)
1500static int keyring_gc_check_iterator(const void *object, void *iterator_data) 1500static int keyring_gc_check_iterator(const void *object, void *iterator_data)
1501{ 1501{
1502 const struct key *key = keyring_ptr_to_key(object); 1502 const struct key *key = keyring_ptr_to_key(object);
1503 time_t *limit = iterator_data; 1503 time64_t *limit = iterator_data;
1504 1504
1505 key_check(key); 1505 key_check(key);
1506 return key_is_dead(key, *limit); 1506 return key_is_dead(key, *limit);
@@ -1512,7 +1512,7 @@ static int keyring_gc_check_iterator(const void *object, void *iterator_data)
1512 * Not called with any locks held. The keyring's key struct will not be 1512 * Not called with any locks held. The keyring's key struct will not be
1513 * deallocated under us as only our caller may deallocate it. 1513 * deallocated under us as only our caller may deallocate it.
1514 */ 1514 */
1515void keyring_gc(struct key *keyring, time_t limit) 1515void keyring_gc(struct key *keyring, time64_t limit)
1516{ 1516{
1517 int result; 1517 int result;
1518 1518
diff --git a/security/keys/permission.c b/security/keys/permission.c
index a72b4dd70c8a..f68dc04d614e 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -89,7 +89,7 @@ EXPORT_SYMBOL(key_task_permission);
89int key_validate(const struct key *key) 89int key_validate(const struct key *key)
90{ 90{
91 unsigned long flags = READ_ONCE(key->flags); 91 unsigned long flags = READ_ONCE(key->flags);
92 time_t expiry = READ_ONCE(key->expiry); 92 time64_t expiry = READ_ONCE(key->expiry);
93 93
94 if (flags & (1 << KEY_FLAG_INVALIDATED)) 94 if (flags & (1 << KEY_FLAG_INVALIDATED))
95 return -ENOKEY; 95 return -ENOKEY;
@@ -101,8 +101,7 @@ int key_validate(const struct key *key)
101 101
102 /* check it hasn't expired */ 102 /* check it hasn't expired */
103 if (expiry) { 103 if (expiry) {
104 struct timespec now = current_kernel_time(); 104 if (ktime_get_real_seconds() >= expiry)
105 if (now.tv_sec >= expiry)
106 return -EKEYEXPIRED; 105 return -EKEYEXPIRED;
107 } 106 }
108 107
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 6d1fcbba1e09..fbc4af5c6c9f 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -178,13 +178,12 @@ static int proc_keys_show(struct seq_file *m, void *v)
178{ 178{
179 struct rb_node *_p = v; 179 struct rb_node *_p = v;
180 struct key *key = rb_entry(_p, struct key, serial_node); 180 struct key *key = rb_entry(_p, struct key, serial_node);
181 struct timespec now;
182 time_t expiry;
183 unsigned long timo;
184 unsigned long flags; 181 unsigned long flags;
185 key_ref_t key_ref, skey_ref; 182 key_ref_t key_ref, skey_ref;
183 time64_t now, expiry;
186 char xbuf[16]; 184 char xbuf[16];
187 short state; 185 short state;
186 u64 timo;
188 int rc; 187 int rc;
189 188
190 struct keyring_search_context ctx = { 189 struct keyring_search_context ctx = {
@@ -215,7 +214,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
215 if (rc < 0) 214 if (rc < 0)
216 return 0; 215 return 0;
217 216
218 now = current_kernel_time(); 217 now = ktime_get_real_seconds();
219 218
220 rcu_read_lock(); 219 rcu_read_lock();
221 220
@@ -223,21 +222,21 @@ static int proc_keys_show(struct seq_file *m, void *v)
223 expiry = READ_ONCE(key->expiry); 222 expiry = READ_ONCE(key->expiry);
224 if (expiry == 0) { 223 if (expiry == 0) {
225 memcpy(xbuf, "perm", 5); 224 memcpy(xbuf, "perm", 5);
226 } else if (now.tv_sec >= expiry) { 225 } else if (now >= expiry) {
227 memcpy(xbuf, "expd", 5); 226 memcpy(xbuf, "expd", 5);
228 } else { 227 } else {
229 timo = expiry - now.tv_sec; 228 timo = expiry - now;
230 229
231 if (timo < 60) 230 if (timo < 60)
232 sprintf(xbuf, "%lus", timo); 231 sprintf(xbuf, "%llus", timo);
233 else if (timo < 60*60) 232 else if (timo < 60*60)
234 sprintf(xbuf, "%lum", timo / 60); 233 sprintf(xbuf, "%llum", div_u64(timo, 60));
235 else if (timo < 60*60*24) 234 else if (timo < 60*60*24)
236 sprintf(xbuf, "%luh", timo / (60*60)); 235 sprintf(xbuf, "%lluh", div_u64(timo, 60 * 60));
237 else if (timo < 60*60*24*7) 236 else if (timo < 60*60*24*7)
238 sprintf(xbuf, "%lud", timo / (60*60*24)); 237 sprintf(xbuf, "%llud", div_u64(timo, 60 * 60 * 24));
239 else 238 else
240 sprintf(xbuf, "%luw", timo / (60*60*24*7)); 239 sprintf(xbuf, "%lluw", div_u64(timo, 60 * 60 * 24 * 7));
241 } 240 }
242 241
243 state = key_read_state(key); 242 state = key_read_state(key);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 740affd65ee9..d5b25e535d3a 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -738,7 +738,7 @@ try_again:
738 if (ret < 0) 738 if (ret < 0)
739 goto invalid_key; 739 goto invalid_key;
740 740
741 key->last_used_at = current_kernel_time().tv_sec; 741 key->last_used_at = ktime_get_real_seconds();
742 742
743error: 743error:
744 put_cred(ctx.cred); 744 put_cred(ctx.cred);