aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/keys/compat.c3
-rw-r--r--security/keys/gc.c21
-rw-r--r--security/keys/internal.h15
-rw-r--r--security/keys/key.c22
-rw-r--r--security/keys/keyctl.c34
-rw-r--r--security/keys/keyring.c25
-rw-r--r--security/keys/permission.c15
-rw-r--r--security/keys/proc.c3
8 files changed, 110 insertions, 28 deletions
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 4c48e13448f8..fab4f8dda6c6 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -135,6 +135,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
135 return compat_keyctl_instantiate_key_iov( 135 return compat_keyctl_instantiate_key_iov(
136 arg2, compat_ptr(arg3), arg4, arg5); 136 arg2, compat_ptr(arg3), arg4, arg5);
137 137
138 case KEYCTL_INVALIDATE:
139 return keyctl_invalidate_key(arg2);
140
138 default: 141 default:
139 return -EOPNOTSUPP; 142 return -EOPNOTSUPP;
140 } 143 }
diff --git a/security/keys/gc.c b/security/keys/gc.c
index adddaa258d50..61ab7c82ebb1 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -72,6 +72,15 @@ void key_schedule_gc(time_t gc_at)
72} 72}
73 73
74/* 74/*
75 * Schedule a dead links collection run.
76 */
77void key_schedule_gc_links(void)
78{
79 set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags);
80 queue_work(system_nrt_wq, &key_gc_work);
81}
82
83/*
75 * Some key's cleanup time was met after it expired, so we need to get the 84 * Some key's cleanup time was met after it expired, so we need to get the
76 * reaper to go through a cycle finding expired keys. 85 * reaper to go through a cycle finding expired keys.
77 */ 86 */
@@ -79,8 +88,7 @@ static void key_gc_timer_func(unsigned long data)
79{ 88{
80 kenter(""); 89 kenter("");
81 key_gc_next_run = LONG_MAX; 90 key_gc_next_run = LONG_MAX;
82 set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags); 91 key_schedule_gc_links();
83 queue_work(system_nrt_wq, &key_gc_work);
84} 92}
85 93
86/* 94/*
@@ -131,12 +139,12 @@ void key_gc_keytype(struct key_type *ktype)
131static void key_gc_keyring(struct key *keyring, time_t limit) 139static void key_gc_keyring(struct key *keyring, time_t limit)
132{ 140{
133 struct keyring_list *klist; 141 struct keyring_list *klist;
134 struct key *key;
135 int loop; 142 int loop;
136 143
137 kenter("%x", key_serial(keyring)); 144 kenter("%x", key_serial(keyring));
138 145
139 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) 146 if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
147 (1 << KEY_FLAG_REVOKED)))
140 goto dont_gc; 148 goto dont_gc;
141 149
142 /* scan the keyring looking for dead keys */ 150 /* scan the keyring looking for dead keys */
@@ -148,9 +156,8 @@ static void key_gc_keyring(struct key *keyring, time_t limit)
148 loop = klist->nkeys; 156 loop = klist->nkeys;
149 smp_rmb(); 157 smp_rmb();
150 for (loop--; loop >= 0; loop--) { 158 for (loop--; loop >= 0; loop--) {
151 key = rcu_dereference(klist->keys[loop]); 159 struct key *key = rcu_dereference(klist->keys[loop]);
152 if (test_bit(KEY_FLAG_DEAD, &key->flags) || 160 if (key_is_dead(key, limit))
153 (key->expiry > 0 && key->expiry <= limit))
154 goto do_gc; 161 goto do_gc;
155 } 162 }
156 163
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 65647f825584..f711b094ed41 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -152,7 +152,8 @@ extern long join_session_keyring(const char *name);
152extern struct work_struct key_gc_work; 152extern struct work_struct key_gc_work;
153extern unsigned key_gc_delay; 153extern unsigned key_gc_delay;
154extern void keyring_gc(struct key *keyring, time_t limit); 154extern void keyring_gc(struct key *keyring, time_t limit);
155extern void key_schedule_gc(time_t expiry_at); 155extern void key_schedule_gc(time_t gc_at);
156extern void key_schedule_gc_links(void);
156extern void key_gc_keytype(struct key_type *ktype); 157extern void key_gc_keytype(struct key_type *ktype);
157 158
158extern int key_task_permission(const key_ref_t key_ref, 159extern int key_task_permission(const key_ref_t key_ref,
@@ -197,6 +198,17 @@ extern struct key *request_key_auth_new(struct key *target,
197extern struct key *key_get_instantiation_authkey(key_serial_t target_id); 198extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
198 199
199/* 200/*
201 * Determine whether a key is dead.
202 */
203static inline bool key_is_dead(struct key *key, time_t limit)
204{
205 return
206 key->flags & ((1 << KEY_FLAG_DEAD) |
207 (1 << KEY_FLAG_INVALIDATED)) ||
208 (key->expiry > 0 && key->expiry <= limit);
209}
210
211/*
200 * keyctl() functions 212 * keyctl() functions
201 */ 213 */
202extern long keyctl_get_keyring_ID(key_serial_t, int); 214extern long keyctl_get_keyring_ID(key_serial_t, int);
@@ -225,6 +237,7 @@ extern long keyctl_reject_key(key_serial_t, unsigned, unsigned, key_serial_t);
225extern long keyctl_instantiate_key_iov(key_serial_t, 237extern long keyctl_instantiate_key_iov(key_serial_t,
226 const struct iovec __user *, 238 const struct iovec __user *,
227 unsigned, key_serial_t); 239 unsigned, key_serial_t);
240extern long keyctl_invalidate_key(key_serial_t);
228 241
229extern long keyctl_instantiate_key_common(key_serial_t, 242extern long keyctl_instantiate_key_common(key_serial_t,
230 const struct iovec __user *, 243 const struct iovec __user *,
diff --git a/security/keys/key.c b/security/keys/key.c
index dc628941ecd3..c9bf66ac36e0 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -955,6 +955,28 @@ void key_revoke(struct key *key)
955EXPORT_SYMBOL(key_revoke); 955EXPORT_SYMBOL(key_revoke);
956 956
957/** 957/**
958 * key_invalidate - Invalidate a key.
959 * @key: The key to be invalidated.
960 *
961 * Mark a key as being invalidated and have it cleaned up immediately. The key
962 * is ignored by all searches and other operations from this point.
963 */
964void key_invalidate(struct key *key)
965{
966 kenter("%d", key_serial(key));
967
968 key_check(key);
969
970 if (!test_bit(KEY_FLAG_INVALIDATED, &key->flags)) {
971 down_write_nested(&key->sem, 1);
972 if (!test_and_set_bit(KEY_FLAG_INVALIDATED, &key->flags))
973 key_schedule_gc_links();
974 up_write(&key->sem);
975 }
976}
977EXPORT_SYMBOL(key_invalidate);
978
979/**
958 * register_key_type - Register a type of key. 980 * register_key_type - Register a type of key.
959 * @ktype: The new key type. 981 * @ktype: The new key type.
960 * 982 *
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index fb767c6cd99f..ddb3e05bc5fc 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -375,6 +375,37 @@ error:
375} 375}
376 376
377/* 377/*
378 * Invalidate a key.
379 *
380 * The key must be grant the caller Invalidate permission for this to work.
381 * The key and any links to the key will be automatically garbage collected
382 * immediately.
383 *
384 * If successful, 0 is returned.
385 */
386long keyctl_invalidate_key(key_serial_t id)
387{
388 key_ref_t key_ref;
389 long ret;
390
391 kenter("%d", id);
392
393 key_ref = lookup_user_key(id, 0, KEY_SEARCH);
394 if (IS_ERR(key_ref)) {
395 ret = PTR_ERR(key_ref);
396 goto error;
397 }
398
399 key_invalidate(key_ref_to_ptr(key_ref));
400 ret = 0;
401
402 key_ref_put(key_ref);
403error:
404 kleave(" = %ld", ret);
405 return ret;
406}
407
408/*
378 * Clear the specified keyring, creating an empty process keyring if one of the 409 * Clear the specified keyring, creating an empty process keyring if one of the
379 * special keyring IDs is used. 410 * special keyring IDs is used.
380 * 411 *
@@ -1622,6 +1653,9 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
1622 (unsigned) arg4, 1653 (unsigned) arg4,
1623 (key_serial_t) arg5); 1654 (key_serial_t) arg5);
1624 1655
1656 case KEYCTL_INVALIDATE:
1657 return keyctl_invalidate_key((key_serial_t) arg2);
1658
1625 default: 1659 default:
1626 return -EOPNOTSUPP; 1660 return -EOPNOTSUPP;
1627 } 1661 }
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 89d02cfb00c2..7445875f6818 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -382,13 +382,17 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
382 /* otherwise, the top keyring must not be revoked, expired, or 382 /* otherwise, the top keyring must not be revoked, expired, or
383 * negatively instantiated if we are to search it */ 383 * negatively instantiated if we are to search it */
384 key_ref = ERR_PTR(-EAGAIN); 384 key_ref = ERR_PTR(-EAGAIN);
385 if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) || 385 if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
386 (1 << KEY_FLAG_REVOKED) |
387 (1 << KEY_FLAG_NEGATIVE)) ||
386 (keyring->expiry && now.tv_sec >= keyring->expiry)) 388 (keyring->expiry && now.tv_sec >= keyring->expiry))
387 goto error_2; 389 goto error_2;
388 390
389 /* start processing a new keyring */ 391 /* start processing a new keyring */
390descend: 392descend:
391 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) 393 kflags = keyring->flags;
394 if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
395 (1 << KEY_FLAG_REVOKED)))
392 goto not_this_keyring; 396 goto not_this_keyring;
393 397
394 keylist = rcu_dereference(keyring->payload.subscriptions); 398 keylist = rcu_dereference(keyring->payload.subscriptions);
@@ -406,9 +410,10 @@ descend:
406 if (key->type != type) 410 if (key->type != type)
407 continue; 411 continue;
408 412
409 /* skip revoked keys and expired keys */ 413 /* skip invalidated, revoked and expired keys */
410 if (!no_state_check) { 414 if (!no_state_check) {
411 if (kflags & (1 << KEY_FLAG_REVOKED)) 415 if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
416 (1 << KEY_FLAG_REVOKED)))
412 continue; 417 continue;
413 418
414 if (key->expiry && now.tv_sec >= key->expiry) 419 if (key->expiry && now.tv_sec >= key->expiry)
@@ -559,7 +564,8 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
559 key->type->match(key, description)) && 564 key->type->match(key, description)) &&
560 key_permission(make_key_ref(key, possessed), 565 key_permission(make_key_ref(key, possessed),
561 perm) == 0 && 566 perm) == 0 &&
562 !test_bit(KEY_FLAG_REVOKED, &key->flags) 567 !(key->flags & ((1 << KEY_FLAG_INVALIDATED) |
568 (1 << KEY_FLAG_REVOKED)))
563 ) 569 )
564 goto found; 570 goto found;
565 } 571 }
@@ -1177,15 +1183,6 @@ static void keyring_revoke(struct key *keyring)
1177} 1183}
1178 1184
1179/* 1185/*
1180 * Determine whether a key is dead.
1181 */
1182static bool key_is_dead(struct key *key, time_t limit)
1183{
1184 return test_bit(KEY_FLAG_DEAD, &key->flags) ||
1185 (key->expiry > 0 && key->expiry <= limit);
1186}
1187
1188/*
1189 * Collect garbage from the contents of a keyring, replacing the old list with 1186 * Collect garbage from the contents of a keyring, replacing the old list with
1190 * a new one with the pointers all shuffled down. 1187 * a new one with the pointers all shuffled down.
1191 * 1188 *
diff --git a/security/keys/permission.c b/security/keys/permission.c
index c35b5229e3cd..5f4c00c0947d 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -87,20 +87,25 @@ EXPORT_SYMBOL(key_task_permission);
87 * key_validate - Validate a key. 87 * key_validate - Validate a key.
88 * @key: The key to be validated. 88 * @key: The key to be validated.
89 * 89 *
90 * Check that a key is valid, returning 0 if the key is okay, -EKEYREVOKED if 90 * Check that a key is valid, returning 0 if the key is okay, -ENOKEY if the
91 * the key's type has been removed or if the key has been revoked or 91 * key is invalidated, -EKEYREVOKED if the key's type has been removed or if
92 * -EKEYEXPIRED if the key has expired. 92 * the key has been revoked or -EKEYEXPIRED if the key has expired.
93 */ 93 */
94int key_validate(struct key *key) 94int key_validate(struct key *key)
95{ 95{
96 struct timespec now; 96 struct timespec now;
97 unsigned long flags = key->flags;
97 int ret = 0; 98 int ret = 0;
98 99
99 if (key) { 100 if (key) {
101 ret = -ENOKEY;
102 if (flags & (1 << KEY_FLAG_INVALIDATED))
103 goto error;
104
100 /* check it's still accessible */ 105 /* check it's still accessible */
101 ret = -EKEYREVOKED; 106 ret = -EKEYREVOKED;
102 if (test_bit(KEY_FLAG_REVOKED, &key->flags) || 107 if (flags & ((1 << KEY_FLAG_REVOKED) |
103 test_bit(KEY_FLAG_DEAD, &key->flags)) 108 (1 << KEY_FLAG_DEAD)))
104 goto error; 109 goto error;
105 110
106 /* check it hasn't expired */ 111 /* check it hasn't expired */
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 49bbc97943ad..30d1ddfd9cef 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -242,7 +242,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
242#define showflag(KEY, LETTER, FLAG) \ 242#define showflag(KEY, LETTER, FLAG) \
243 (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') 243 (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-')
244 244
245 seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", 245 seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
246 key->serial, 246 key->serial,
247 showflag(key, 'I', KEY_FLAG_INSTANTIATED), 247 showflag(key, 'I', KEY_FLAG_INSTANTIATED),
248 showflag(key, 'R', KEY_FLAG_REVOKED), 248 showflag(key, 'R', KEY_FLAG_REVOKED),
@@ -250,6 +250,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
250 showflag(key, 'Q', KEY_FLAG_IN_QUOTA), 250 showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
251 showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), 251 showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
252 showflag(key, 'N', KEY_FLAG_NEGATIVE), 252 showflag(key, 'N', KEY_FLAG_NEGATIVE),
253 showflag(key, 'i', KEY_FLAG_INVALIDATED),
253 atomic_read(&key->usage), 254 atomic_read(&key->usage),
254 xbuf, 255 xbuf,
255 key->perm, 256 key->perm,