diff options
-rw-r--r-- | Documentation/keys.txt | 34 | ||||
-rw-r--r-- | include/linux/key-ui.h | 41 | ||||
-rw-r--r-- | include/linux/key.h | 9 | ||||
-rw-r--r-- | include/linux/keyctl.h | 11 | ||||
-rw-r--r-- | include/linux/sched.h | 8 | ||||
-rw-r--r-- | kernel/sys.c | 2 | ||||
-rw-r--r-- | security/keys/Makefile | 5 | ||||
-rw-r--r-- | security/keys/compat.c | 7 | ||||
-rw-r--r-- | security/keys/internal.h | 45 | ||||
-rw-r--r-- | security/keys/key.c | 24 | ||||
-rw-r--r-- | security/keys/keyctl.c | 176 | ||||
-rw-r--r-- | security/keys/keyring.c | 67 | ||||
-rw-r--r-- | security/keys/process_keys.c | 179 | ||||
-rw-r--r-- | security/keys/request_key.c | 182 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 180 |
15 files changed, 779 insertions, 191 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt index 3df40c1fe15a..0321ded4b9ae 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt | |||
@@ -591,6 +591,37 @@ The keyctl syscall functions are: | |||
591 | this case too. | 591 | this case too. |
592 | 592 | ||
593 | 593 | ||
594 | (*) Set the default request-key destination keyring. | ||
595 | |||
596 | long keyctl(KEYCTL_SET_REQKEY_KEYRING, int reqkey_defl); | ||
597 | |||
598 | This sets the default keyring to which implicitly requested keys will be | ||
599 | attached for this thread. reqkey_defl should be one of these constants: | ||
600 | |||
601 | CONSTANT VALUE NEW DEFAULT KEYRING | ||
602 | ====================================== ====== ======================= | ||
603 | KEY_REQKEY_DEFL_NO_CHANGE -1 No change | ||
604 | KEY_REQKEY_DEFL_DEFAULT 0 Default[1] | ||
605 | KEY_REQKEY_DEFL_THREAD_KEYRING 1 Thread keyring | ||
606 | KEY_REQKEY_DEFL_PROCESS_KEYRING 2 Process keyring | ||
607 | KEY_REQKEY_DEFL_SESSION_KEYRING 3 Session keyring | ||
608 | KEY_REQKEY_DEFL_USER_KEYRING 4 User keyring | ||
609 | KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5 User session keyring | ||
610 | KEY_REQKEY_DEFL_GROUP_KEYRING 6 Group keyring | ||
611 | |||
612 | The old default will be returned if successful and error EINVAL will be | ||
613 | returned if reqkey_defl is not one of the above values. | ||
614 | |||
615 | The default keyring can be overridden by the keyring indicated to the | ||
616 | request_key() system call. | ||
617 | |||
618 | Note that this setting is inherited across fork/exec. | ||
619 | |||
620 | [1] The default default is: the thread keyring if there is one, otherwise | ||
621 | the process keyring if there is one, otherwise the session keyring if | ||
622 | there is one, otherwise the user default session keyring. | ||
623 | |||
624 | |||
594 | =============== | 625 | =============== |
595 | KERNEL SERVICES | 626 | KERNEL SERVICES |
596 | =============== | 627 | =============== |
@@ -626,6 +657,9 @@ payload contents" for more information. | |||
626 | Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be | 657 | Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be |
627 | returned. | 658 | returned. |
628 | 659 | ||
660 | If successful, the key will have been attached to the default keyring for | ||
661 | implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING. | ||
662 | |||
629 | 663 | ||
630 | (*) When it is no longer required, the key should be released using: | 664 | (*) When it is no longer required, the key should be released using: |
631 | 665 | ||
diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h index 159ca8d54e9a..cc326174a808 100644 --- a/include/linux/key-ui.h +++ b/include/linux/key-ui.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* key-ui.h: key userspace interface stuff for use by keyfs | 1 | /* key-ui.h: key userspace interface stuff |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
@@ -84,8 +84,45 @@ static inline int key_any_permission(const struct key *key, key_perm_t perm) | |||
84 | return kperm != 0; | 84 | return kperm != 0; |
85 | } | 85 | } |
86 | 86 | ||
87 | static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid) | ||
88 | { | ||
89 | int ret; | ||
90 | |||
91 | task_lock(tsk); | ||
92 | ret = groups_search(tsk->group_info, gid); | ||
93 | task_unlock(tsk); | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static inline int key_task_permission(const struct key *key, | ||
98 | struct task_struct *context, | ||
99 | key_perm_t perm) | ||
100 | { | ||
101 | key_perm_t kperm; | ||
102 | |||
103 | if (key->uid == context->fsuid) { | ||
104 | kperm = key->perm >> 16; | ||
105 | } | ||
106 | else if (key->gid != -1 && | ||
107 | key->perm & KEY_GRP_ALL && ( | ||
108 | key->gid == context->fsgid || | ||
109 | key_task_groups_search(context, key->gid) | ||
110 | ) | ||
111 | ) { | ||
112 | kperm = key->perm >> 8; | ||
113 | } | ||
114 | else { | ||
115 | kperm = key->perm; | ||
116 | } | ||
117 | |||
118 | kperm = kperm & perm & KEY_ALL; | ||
119 | |||
120 | return kperm == perm; | ||
121 | |||
122 | } | ||
87 | 123 | ||
88 | extern struct key *lookup_user_key(key_serial_t id, int create, int part, | 124 | extern struct key *lookup_user_key(struct task_struct *context, |
125 | key_serial_t id, int create, int partial, | ||
89 | key_perm_t perm); | 126 | key_perm_t perm); |
90 | 127 | ||
91 | extern long join_session_keyring(const char *name); | 128 | extern long join_session_keyring(const char *name); |
diff --git a/include/linux/key.h b/include/linux/key.h index 2bfbf88d2740..970bbd916cf4 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -199,10 +199,12 @@ extern int key_payload_reserve(struct key *key, size_t datalen); | |||
199 | extern int key_instantiate_and_link(struct key *key, | 199 | extern int key_instantiate_and_link(struct key *key, |
200 | const void *data, | 200 | const void *data, |
201 | size_t datalen, | 201 | size_t datalen, |
202 | struct key *keyring); | 202 | struct key *keyring, |
203 | struct key *instkey); | ||
203 | extern int key_negate_and_link(struct key *key, | 204 | extern int key_negate_and_link(struct key *key, |
204 | unsigned timeout, | 205 | unsigned timeout, |
205 | struct key *keyring); | 206 | struct key *keyring, |
207 | struct key *instkey); | ||
206 | extern void key_revoke(struct key *key); | 208 | extern void key_revoke(struct key *key); |
207 | extern void key_put(struct key *key); | 209 | extern void key_put(struct key *key); |
208 | 210 | ||
@@ -245,9 +247,6 @@ extern struct key *keyring_search(struct key *keyring, | |||
245 | struct key_type *type, | 247 | struct key_type *type, |
246 | const char *description); | 248 | const char *description); |
247 | 249 | ||
248 | extern struct key *search_process_keyrings(struct key_type *type, | ||
249 | const char *description); | ||
250 | |||
251 | extern int keyring_add_key(struct key *keyring, | 250 | extern int keyring_add_key(struct key *keyring, |
252 | struct key *key); | 251 | struct key *key); |
253 | 252 | ||
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h index 381dedc370a3..8d7c59a29e09 100644 --- a/include/linux/keyctl.h +++ b/include/linux/keyctl.h | |||
@@ -20,6 +20,16 @@ | |||
20 | #define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */ | 20 | #define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */ |
21 | #define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */ | 21 | #define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */ |
22 | 22 | ||
23 | /* request-key default keyrings */ | ||
24 | #define KEY_REQKEY_DEFL_NO_CHANGE -1 | ||
25 | #define KEY_REQKEY_DEFL_DEFAULT 0 | ||
26 | #define KEY_REQKEY_DEFL_THREAD_KEYRING 1 | ||
27 | #define KEY_REQKEY_DEFL_PROCESS_KEYRING 2 | ||
28 | #define KEY_REQKEY_DEFL_SESSION_KEYRING 3 | ||
29 | #define KEY_REQKEY_DEFL_USER_KEYRING 4 | ||
30 | #define KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5 | ||
31 | #define KEY_REQKEY_DEFL_GROUP_KEYRING 6 | ||
32 | |||
23 | /* keyctl commands */ | 33 | /* keyctl commands */ |
24 | #define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */ | 34 | #define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */ |
25 | #define KEYCTL_JOIN_SESSION_KEYRING 1 /* join or start named session keyring */ | 35 | #define KEYCTL_JOIN_SESSION_KEYRING 1 /* join or start named session keyring */ |
@@ -35,5 +45,6 @@ | |||
35 | #define KEYCTL_READ 11 /* read a key or keyring's contents */ | 45 | #define KEYCTL_READ 11 /* read a key or keyring's contents */ |
36 | #define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */ | 46 | #define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */ |
37 | #define KEYCTL_NEGATE 13 /* negate a partially constructed key */ | 47 | #define KEYCTL_NEGATE 13 /* negate a partially constructed key */ |
48 | #define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */ | ||
38 | 49 | ||
39 | #endif /* _LINUX_KEYCTL_H */ | 50 | #endif /* _LINUX_KEYCTL_H */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 901742f92389..2c69682b0444 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -561,9 +561,10 @@ struct group_info { | |||
561 | groups_free(group_info); \ | 561 | groups_free(group_info); \ |
562 | } while (0) | 562 | } while (0) |
563 | 563 | ||
564 | struct group_info *groups_alloc(int gidsetsize); | 564 | extern struct group_info *groups_alloc(int gidsetsize); |
565 | void groups_free(struct group_info *group_info); | 565 | extern void groups_free(struct group_info *group_info); |
566 | int set_current_groups(struct group_info *group_info); | 566 | extern int set_current_groups(struct group_info *group_info); |
567 | extern int groups_search(struct group_info *group_info, gid_t grp); | ||
567 | /* access the groups "array" with this macro */ | 568 | /* access the groups "array" with this macro */ |
568 | #define GROUP_AT(gi, i) \ | 569 | #define GROUP_AT(gi, i) \ |
569 | ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK]) | 570 | ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK]) |
@@ -660,6 +661,7 @@ struct task_struct { | |||
660 | struct user_struct *user; | 661 | struct user_struct *user; |
661 | #ifdef CONFIG_KEYS | 662 | #ifdef CONFIG_KEYS |
662 | struct key *thread_keyring; /* keyring private to this thread */ | 663 | struct key *thread_keyring; /* keyring private to this thread */ |
664 | unsigned char jit_keyring; /* default keyring to attach requested keys to */ | ||
663 | #endif | 665 | #endif |
664 | int oomkilladj; /* OOM kill score adjustment (bit shift). */ | 666 | int oomkilladj; /* OOM kill score adjustment (bit shift). */ |
665 | char comm[TASK_COMM_LEN]; /* executable name excluding path | 667 | char comm[TASK_COMM_LEN]; /* executable name excluding path |
diff --git a/kernel/sys.c b/kernel/sys.c index 5a9d6b075016..da24bc1292db 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1259,7 +1259,7 @@ static void groups_sort(struct group_info *group_info) | |||
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | /* a simple bsearch */ | 1261 | /* a simple bsearch */ |
1262 | static int groups_search(struct group_info *group_info, gid_t grp) | 1262 | int groups_search(struct group_info *group_info, gid_t grp) |
1263 | { | 1263 | { |
1264 | int left, right; | 1264 | int left, right; |
1265 | 1265 | ||
diff --git a/security/keys/Makefile b/security/keys/Makefile index ddb495d65062..c392d750b208 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile | |||
@@ -7,8 +7,9 @@ obj-y := \ | |||
7 | keyring.o \ | 7 | keyring.o \ |
8 | keyctl.o \ | 8 | keyctl.o \ |
9 | process_keys.o \ | 9 | process_keys.o \ |
10 | user_defined.o \ | 10 | request_key.o \ |
11 | request_key.o | 11 | request_key_auth.o \ |
12 | user_defined.o | ||
12 | 13 | ||
13 | obj-$(CONFIG_KEYS_COMPAT) += compat.o | 14 | obj-$(CONFIG_KEYS_COMPAT) += compat.o |
14 | obj-$(CONFIG_PROC_FS) += proc.o | 15 | obj-$(CONFIG_PROC_FS) += proc.o |
diff --git a/security/keys/compat.c b/security/keys/compat.c index aff8b22dcb5c..3303673c636e 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* compat.c: 32-bit compatibility syscall for 64-bit systems | 1 | /* compat.c: 32-bit compatibility syscall for 64-bit systems |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -24,7 +24,7 @@ | |||
24 | * - if you can, you should call sys_keyctl directly | 24 | * - if you can, you should call sys_keyctl directly |
25 | */ | 25 | */ |
26 | asmlinkage long compat_sys_keyctl(u32 option, | 26 | asmlinkage long compat_sys_keyctl(u32 option, |
27 | u32 arg2, u32 arg3, u32 arg4, u32 arg5) | 27 | u32 arg2, u32 arg3, u32 arg4, u32 arg5) |
28 | { | 28 | { |
29 | switch (option) { | 29 | switch (option) { |
30 | case KEYCTL_GET_KEYRING_ID: | 30 | case KEYCTL_GET_KEYRING_ID: |
@@ -71,6 +71,9 @@ asmlinkage long compat_sys_keyctl(u32 option, | |||
71 | case KEYCTL_NEGATE: | 71 | case KEYCTL_NEGATE: |
72 | return keyctl_negate_key(arg2, arg3, arg4); | 72 | return keyctl_negate_key(arg2, arg3, arg4); |
73 | 73 | ||
74 | case KEYCTL_SET_REQKEY_KEYRING: | ||
75 | return keyctl_set_reqkey_keyring(arg2); | ||
76 | |||
74 | default: | 77 | default: |
75 | return -EOPNOTSUPP; | 78 | return -EOPNOTSUPP; |
76 | } | 79 | } |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 67b2b93a7489..46c8602661c9 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* internal.h: authentication token and access key management internal defs | 1 | /* internal.h: authentication token and access key management internal defs |
2 | * | 2 | * |
3 | * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -15,6 +15,16 @@ | |||
15 | #include <linux/key.h> | 15 | #include <linux/key.h> |
16 | #include <linux/key-ui.h> | 16 | #include <linux/key-ui.h> |
17 | 17 | ||
18 | #if 0 | ||
19 | #define kenter(FMT, a...) printk("==> %s("FMT")\n",__FUNCTION__ , ## a) | ||
20 | #define kleave(FMT, a...) printk("<== %s()"FMT"\n",__FUNCTION__ , ## a) | ||
21 | #define kdebug(FMT, a...) printk(FMT"\n" , ## a) | ||
22 | #else | ||
23 | #define kenter(FMT, a...) do {} while(0) | ||
24 | #define kleave(FMT, a...) do {} while(0) | ||
25 | #define kdebug(FMT, a...) do {} while(0) | ||
26 | #endif | ||
27 | |||
18 | extern struct key_type key_type_dead; | 28 | extern struct key_type key_type_dead; |
19 | extern struct key_type key_type_user; | 29 | extern struct key_type key_type_user; |
20 | 30 | ||
@@ -66,20 +76,46 @@ extern struct key *__keyring_search_one(struct key *keyring, | |||
66 | const char *description, | 76 | const char *description, |
67 | key_perm_t perm); | 77 | key_perm_t perm); |
68 | 78 | ||
79 | extern struct key *keyring_search_instkey(struct key *keyring, | ||
80 | key_serial_t target_id); | ||
81 | |||
69 | typedef int (*key_match_func_t)(const struct key *, const void *); | 82 | typedef int (*key_match_func_t)(const struct key *, const void *); |
70 | 83 | ||
71 | extern struct key *keyring_search_aux(struct key *keyring, | 84 | extern struct key *keyring_search_aux(struct key *keyring, |
85 | struct task_struct *tsk, | ||
72 | struct key_type *type, | 86 | struct key_type *type, |
73 | const void *description, | 87 | const void *description, |
74 | key_match_func_t match); | 88 | key_match_func_t match); |
75 | 89 | ||
76 | extern struct key *search_process_keyrings_aux(struct key_type *type, | 90 | extern struct key *search_process_keyrings(struct key_type *type, |
77 | const void *description, | 91 | const void *description, |
78 | key_match_func_t match); | 92 | key_match_func_t match, |
93 | struct task_struct *tsk); | ||
79 | 94 | ||
80 | extern struct key *find_keyring_by_name(const char *name, key_serial_t bound); | 95 | extern struct key *find_keyring_by_name(const char *name, key_serial_t bound); |
81 | 96 | ||
82 | extern int install_thread_keyring(struct task_struct *tsk); | 97 | extern int install_thread_keyring(struct task_struct *tsk); |
98 | extern int install_process_keyring(struct task_struct *tsk); | ||
99 | |||
100 | extern struct key *request_key_and_link(struct key_type *type, | ||
101 | const char *description, | ||
102 | const char *callout_info, | ||
103 | struct key *dest_keyring); | ||
104 | |||
105 | /* | ||
106 | * request_key authorisation | ||
107 | */ | ||
108 | struct request_key_auth { | ||
109 | struct key *target_key; | ||
110 | struct task_struct *context; | ||
111 | pid_t pid; | ||
112 | }; | ||
113 | |||
114 | extern struct key_type key_type_request_key_auth; | ||
115 | extern struct key *request_key_auth_new(struct key *target, | ||
116 | struct key **_rkakey); | ||
117 | |||
118 | extern struct key *key_get_instantiation_authkey(key_serial_t target_id); | ||
83 | 119 | ||
84 | /* | 120 | /* |
85 | * keyctl functions | 121 | * keyctl functions |
@@ -100,6 +136,7 @@ extern long keyctl_setperm_key(key_serial_t, key_perm_t); | |||
100 | extern long keyctl_instantiate_key(key_serial_t, const void __user *, | 136 | extern long keyctl_instantiate_key(key_serial_t, const void __user *, |
101 | size_t, key_serial_t); | 137 | size_t, key_serial_t); |
102 | extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t); | 138 | extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t); |
139 | extern long keyctl_set_reqkey_keyring(int); | ||
103 | 140 | ||
104 | 141 | ||
105 | /* | 142 | /* |
diff --git a/security/keys/key.c b/security/keys/key.c index 1fdfccb3fe43..3304d37bb379 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* key.c: basic authentication token and access key management | 1 | /* key.c: basic authentication token and access key management |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -391,7 +391,8 @@ EXPORT_SYMBOL(key_payload_reserve); | |||
391 | static int __key_instantiate_and_link(struct key *key, | 391 | static int __key_instantiate_and_link(struct key *key, |
392 | const void *data, | 392 | const void *data, |
393 | size_t datalen, | 393 | size_t datalen, |
394 | struct key *keyring) | 394 | struct key *keyring, |
395 | struct key *instkey) | ||
395 | { | 396 | { |
396 | int ret, awaken; | 397 | int ret, awaken; |
397 | 398 | ||
@@ -419,6 +420,10 @@ static int __key_instantiate_and_link(struct key *key, | |||
419 | /* and link it into the destination keyring */ | 420 | /* and link it into the destination keyring */ |
420 | if (keyring) | 421 | if (keyring) |
421 | ret = __key_link(keyring, key); | 422 | ret = __key_link(keyring, key); |
423 | |||
424 | /* disable the authorisation key */ | ||
425 | if (instkey) | ||
426 | key_revoke(instkey); | ||
422 | } | 427 | } |
423 | } | 428 | } |
424 | 429 | ||
@@ -439,19 +444,21 @@ static int __key_instantiate_and_link(struct key *key, | |||
439 | int key_instantiate_and_link(struct key *key, | 444 | int key_instantiate_and_link(struct key *key, |
440 | const void *data, | 445 | const void *data, |
441 | size_t datalen, | 446 | size_t datalen, |
442 | struct key *keyring) | 447 | struct key *keyring, |
448 | struct key *instkey) | ||
443 | { | 449 | { |
444 | int ret; | 450 | int ret; |
445 | 451 | ||
446 | if (keyring) | 452 | if (keyring) |
447 | down_write(&keyring->sem); | 453 | down_write(&keyring->sem); |
448 | 454 | ||
449 | ret = __key_instantiate_and_link(key, data, datalen, keyring); | 455 | ret = __key_instantiate_and_link(key, data, datalen, keyring, instkey); |
450 | 456 | ||
451 | if (keyring) | 457 | if (keyring) |
452 | up_write(&keyring->sem); | 458 | up_write(&keyring->sem); |
453 | 459 | ||
454 | return ret; | 460 | return ret; |
461 | |||
455 | } /* end key_instantiate_and_link() */ | 462 | } /* end key_instantiate_and_link() */ |
456 | 463 | ||
457 | EXPORT_SYMBOL(key_instantiate_and_link); | 464 | EXPORT_SYMBOL(key_instantiate_and_link); |
@@ -462,7 +469,8 @@ EXPORT_SYMBOL(key_instantiate_and_link); | |||
462 | */ | 469 | */ |
463 | int key_negate_and_link(struct key *key, | 470 | int key_negate_and_link(struct key *key, |
464 | unsigned timeout, | 471 | unsigned timeout, |
465 | struct key *keyring) | 472 | struct key *keyring, |
473 | struct key *instkey) | ||
466 | { | 474 | { |
467 | struct timespec now; | 475 | struct timespec now; |
468 | int ret, awaken; | 476 | int ret, awaken; |
@@ -495,6 +503,10 @@ int key_negate_and_link(struct key *key, | |||
495 | /* and link it into the destination keyring */ | 503 | /* and link it into the destination keyring */ |
496 | if (keyring) | 504 | if (keyring) |
497 | ret = __key_link(keyring, key); | 505 | ret = __key_link(keyring, key); |
506 | |||
507 | /* disable the authorisation key */ | ||
508 | if (instkey) | ||
509 | key_revoke(instkey); | ||
498 | } | 510 | } |
499 | 511 | ||
500 | up_write(&key_construction_sem); | 512 | up_write(&key_construction_sem); |
@@ -781,7 +793,7 @@ struct key *key_create_or_update(struct key *keyring, | |||
781 | } | 793 | } |
782 | 794 | ||
783 | /* instantiate it and link it into the target keyring */ | 795 | /* instantiate it and link it into the target keyring */ |
784 | ret = __key_instantiate_and_link(key, payload, plen, keyring); | 796 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); |
785 | if (ret < 0) { | 797 | if (ret < 0) { |
786 | key_put(key); | 798 | key_put(key); |
787 | key = ERR_PTR(ret); | 799 | key = ERR_PTR(ret); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index cedb7326de29..fea262860ea0 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* keyctl.c: userspace keyctl operations | 1 | /* keyctl.c: userspace keyctl operations |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -49,6 +49,13 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
49 | goto error; | 49 | goto error; |
50 | type[31] = '\0'; | 50 | type[31] = '\0'; |
51 | 51 | ||
52 | if (!type[0]) | ||
53 | goto error; | ||
54 | |||
55 | ret = -EPERM; | ||
56 | if (type[0] == '.') | ||
57 | goto error; | ||
58 | |||
52 | ret = -EFAULT; | 59 | ret = -EFAULT; |
53 | dlen = strnlen_user(_description, PAGE_SIZE - 1); | 60 | dlen = strnlen_user(_description, PAGE_SIZE - 1); |
54 | if (dlen <= 0) | 61 | if (dlen <= 0) |
@@ -82,7 +89,7 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
82 | } | 89 | } |
83 | 90 | ||
84 | /* find the target keyring (which must be writable) */ | 91 | /* find the target keyring (which must be writable) */ |
85 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 92 | keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
86 | if (IS_ERR(keyring)) { | 93 | if (IS_ERR(keyring)) { |
87 | ret = PTR_ERR(keyring); | 94 | ret = PTR_ERR(keyring); |
88 | goto error3; | 95 | goto error3; |
@@ -181,7 +188,7 @@ asmlinkage long sys_request_key(const char __user *_type, | |||
181 | /* get the destination keyring if specified */ | 188 | /* get the destination keyring if specified */ |
182 | dest = NULL; | 189 | dest = NULL; |
183 | if (destringid) { | 190 | if (destringid) { |
184 | dest = lookup_user_key(destringid, 1, 0, KEY_WRITE); | 191 | dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); |
185 | if (IS_ERR(dest)) { | 192 | if (IS_ERR(dest)) { |
186 | ret = PTR_ERR(dest); | 193 | ret = PTR_ERR(dest); |
187 | goto error3; | 194 | goto error3; |
@@ -196,23 +203,15 @@ asmlinkage long sys_request_key(const char __user *_type, | |||
196 | } | 203 | } |
197 | 204 | ||
198 | /* do the search */ | 205 | /* do the search */ |
199 | key = request_key(ktype, description, callout_info); | 206 | key = request_key_and_link(ktype, description, callout_info, dest); |
200 | if (IS_ERR(key)) { | 207 | if (IS_ERR(key)) { |
201 | ret = PTR_ERR(key); | 208 | ret = PTR_ERR(key); |
202 | goto error5; | 209 | goto error5; |
203 | } | 210 | } |
204 | 211 | ||
205 | /* link the resulting key to the destination keyring */ | ||
206 | if (dest) { | ||
207 | ret = key_link(dest, key); | ||
208 | if (ret < 0) | ||
209 | goto error6; | ||
210 | } | ||
211 | |||
212 | ret = key->serial; | 212 | ret = key->serial; |
213 | 213 | ||
214 | error6: | 214 | key_put(key); |
215 | key_put(key); | ||
216 | error5: | 215 | error5: |
217 | key_type_put(ktype); | 216 | key_type_put(ktype); |
218 | error4: | 217 | error4: |
@@ -237,7 +236,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create) | |||
237 | struct key *key; | 236 | struct key *key; |
238 | long ret; | 237 | long ret; |
239 | 238 | ||
240 | key = lookup_user_key(id, create, 0, KEY_SEARCH); | 239 | key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH); |
241 | if (IS_ERR(key)) { | 240 | if (IS_ERR(key)) { |
242 | ret = PTR_ERR(key); | 241 | ret = PTR_ERR(key); |
243 | goto error; | 242 | goto error; |
@@ -324,7 +323,7 @@ long keyctl_update_key(key_serial_t id, | |||
324 | } | 323 | } |
325 | 324 | ||
326 | /* find the target key (which must be writable) */ | 325 | /* find the target key (which must be writable) */ |
327 | key = lookup_user_key(id, 0, 0, KEY_WRITE); | 326 | key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); |
328 | if (IS_ERR(key)) { | 327 | if (IS_ERR(key)) { |
329 | ret = PTR_ERR(key); | 328 | ret = PTR_ERR(key); |
330 | goto error2; | 329 | goto error2; |
@@ -352,7 +351,7 @@ long keyctl_revoke_key(key_serial_t id) | |||
352 | struct key *key; | 351 | struct key *key; |
353 | long ret; | 352 | long ret; |
354 | 353 | ||
355 | key = lookup_user_key(id, 0, 0, KEY_WRITE); | 354 | key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); |
356 | if (IS_ERR(key)) { | 355 | if (IS_ERR(key)) { |
357 | ret = PTR_ERR(key); | 356 | ret = PTR_ERR(key); |
358 | goto error; | 357 | goto error; |
@@ -378,7 +377,7 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
378 | struct key *keyring; | 377 | struct key *keyring; |
379 | long ret; | 378 | long ret; |
380 | 379 | ||
381 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 380 | keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
382 | if (IS_ERR(keyring)) { | 381 | if (IS_ERR(keyring)) { |
383 | ret = PTR_ERR(keyring); | 382 | ret = PTR_ERR(keyring); |
384 | goto error; | 383 | goto error; |
@@ -404,13 +403,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) | |||
404 | struct key *keyring, *key; | 403 | struct key *keyring, *key; |
405 | long ret; | 404 | long ret; |
406 | 405 | ||
407 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 406 | keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
408 | if (IS_ERR(keyring)) { | 407 | if (IS_ERR(keyring)) { |
409 | ret = PTR_ERR(keyring); | 408 | ret = PTR_ERR(keyring); |
410 | goto error; | 409 | goto error; |
411 | } | 410 | } |
412 | 411 | ||
413 | key = lookup_user_key(id, 1, 0, KEY_LINK); | 412 | key = lookup_user_key(NULL, id, 1, 0, KEY_LINK); |
414 | if (IS_ERR(key)) { | 413 | if (IS_ERR(key)) { |
415 | ret = PTR_ERR(key); | 414 | ret = PTR_ERR(key); |
416 | goto error2; | 415 | goto error2; |
@@ -438,13 +437,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) | |||
438 | struct key *keyring, *key; | 437 | struct key *keyring, *key; |
439 | long ret; | 438 | long ret; |
440 | 439 | ||
441 | keyring = lookup_user_key(ringid, 0, 0, KEY_WRITE); | 440 | keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE); |
442 | if (IS_ERR(keyring)) { | 441 | if (IS_ERR(keyring)) { |
443 | ret = PTR_ERR(keyring); | 442 | ret = PTR_ERR(keyring); |
444 | goto error; | 443 | goto error; |
445 | } | 444 | } |
446 | 445 | ||
447 | key = lookup_user_key(id, 0, 0, 0); | 446 | key = lookup_user_key(NULL, id, 0, 0, 0); |
448 | if (IS_ERR(key)) { | 447 | if (IS_ERR(key)) { |
449 | ret = PTR_ERR(key); | 448 | ret = PTR_ERR(key); |
450 | goto error2; | 449 | goto error2; |
@@ -475,16 +474,29 @@ long keyctl_describe_key(key_serial_t keyid, | |||
475 | char __user *buffer, | 474 | char __user *buffer, |
476 | size_t buflen) | 475 | size_t buflen) |
477 | { | 476 | { |
478 | struct key *key; | 477 | struct key *key, *instkey; |
479 | char *tmpbuf; | 478 | char *tmpbuf; |
480 | long ret; | 479 | long ret; |
481 | 480 | ||
482 | key = lookup_user_key(keyid, 0, 1, KEY_VIEW); | 481 | key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); |
483 | if (IS_ERR(key)) { | 482 | if (IS_ERR(key)) { |
483 | /* viewing a key under construction is permitted if we have the | ||
484 | * authorisation token handy */ | ||
485 | if (PTR_ERR(key) == -EACCES) { | ||
486 | instkey = key_get_instantiation_authkey(keyid); | ||
487 | if (!IS_ERR(instkey)) { | ||
488 | key_put(instkey); | ||
489 | key = lookup_user_key(NULL, keyid, 0, 1, 0); | ||
490 | if (!IS_ERR(key)) | ||
491 | goto okay; | ||
492 | } | ||
493 | } | ||
494 | |||
484 | ret = PTR_ERR(key); | 495 | ret = PTR_ERR(key); |
485 | goto error; | 496 | goto error; |
486 | } | 497 | } |
487 | 498 | ||
499 | okay: | ||
488 | /* calculate how much description we're going to return */ | 500 | /* calculate how much description we're going to return */ |
489 | ret = -ENOMEM; | 501 | ret = -ENOMEM; |
490 | tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 502 | tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
@@ -568,7 +580,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
568 | goto error2; | 580 | goto error2; |
569 | 581 | ||
570 | /* get the keyring at which to begin the search */ | 582 | /* get the keyring at which to begin the search */ |
571 | keyring = lookup_user_key(ringid, 0, 0, KEY_SEARCH); | 583 | keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); |
572 | if (IS_ERR(keyring)) { | 584 | if (IS_ERR(keyring)) { |
573 | ret = PTR_ERR(keyring); | 585 | ret = PTR_ERR(keyring); |
574 | goto error2; | 586 | goto error2; |
@@ -577,7 +589,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
577 | /* get the destination keyring if specified */ | 589 | /* get the destination keyring if specified */ |
578 | dest = NULL; | 590 | dest = NULL; |
579 | if (destringid) { | 591 | if (destringid) { |
580 | dest = lookup_user_key(destringid, 1, 0, KEY_WRITE); | 592 | dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); |
581 | if (IS_ERR(dest)) { | 593 | if (IS_ERR(dest)) { |
582 | ret = PTR_ERR(dest); | 594 | ret = PTR_ERR(dest); |
583 | goto error3; | 595 | goto error3; |
@@ -656,24 +668,23 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
656 | long ret; | 668 | long ret; |
657 | 669 | ||
658 | /* find the key first */ | 670 | /* find the key first */ |
659 | key = lookup_user_key(keyid, 0, 0, 0); | 671 | key = lookup_user_key(NULL, keyid, 0, 0, 0); |
660 | if (!IS_ERR(key)) { | 672 | if (!IS_ERR(key)) { |
661 | /* see if we can read it directly */ | 673 | /* see if we can read it directly */ |
662 | if (key_permission(key, KEY_READ)) | 674 | if (key_permission(key, KEY_READ)) |
663 | goto can_read_key; | 675 | goto can_read_key; |
664 | 676 | ||
665 | /* can't; see if it's searchable from this process's | 677 | /* we can't; see if it's searchable from this process's |
666 | * keyrings */ | 678 | * keyrings |
667 | ret = -ENOKEY; | 679 | * - we automatically take account of the fact that it may be |
668 | if (key_permission(key, KEY_SEARCH)) { | 680 | * dangling off an instantiation key |
669 | /* okay - we do have search permission on the key | 681 | */ |
670 | * itself, but do we have the key? */ | 682 | skey = search_process_keyrings(key->type, key, |
671 | skey = search_process_keyrings_aux(key->type, key, | 683 | keyctl_read_key_same, current); |
672 | keyctl_read_key_same); | 684 | if (!IS_ERR(skey)) |
673 | if (!IS_ERR(skey)) | 685 | goto can_read_key2; |
674 | goto can_read_key2; | 686 | |
675 | } | 687 | ret = PTR_ERR(skey); |
676 | |||
677 | goto error2; | 688 | goto error2; |
678 | } | 689 | } |
679 | 690 | ||
@@ -719,7 +730,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
719 | if (uid == (uid_t) -1 && gid == (gid_t) -1) | 730 | if (uid == (uid_t) -1 && gid == (gid_t) -1) |
720 | goto error; | 731 | goto error; |
721 | 732 | ||
722 | key = lookup_user_key(id, 1, 1, 0); | 733 | key = lookup_user_key(NULL, id, 1, 1, 0); |
723 | if (IS_ERR(key)) { | 734 | if (IS_ERR(key)) { |
724 | ret = PTR_ERR(key); | 735 | ret = PTR_ERR(key); |
725 | goto error; | 736 | goto error; |
@@ -776,7 +787,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
776 | if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) | 787 | if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) |
777 | goto error; | 788 | goto error; |
778 | 789 | ||
779 | key = lookup_user_key(id, 1, 1, 0); | 790 | key = lookup_user_key(NULL, id, 1, 1, 0); |
780 | if (IS_ERR(key)) { | 791 | if (IS_ERR(key)) { |
781 | ret = PTR_ERR(key); | 792 | ret = PTR_ERR(key); |
782 | goto error; | 793 | goto error; |
@@ -809,7 +820,8 @@ long keyctl_instantiate_key(key_serial_t id, | |||
809 | size_t plen, | 820 | size_t plen, |
810 | key_serial_t ringid) | 821 | key_serial_t ringid) |
811 | { | 822 | { |
812 | struct key *key, *keyring; | 823 | struct request_key_auth *rka; |
824 | struct key *instkey, *keyring; | ||
813 | void *payload; | 825 | void *payload; |
814 | long ret; | 826 | long ret; |
815 | 827 | ||
@@ -831,18 +843,21 @@ long keyctl_instantiate_key(key_serial_t id, | |||
831 | goto error2; | 843 | goto error2; |
832 | } | 844 | } |
833 | 845 | ||
834 | /* find the target key (which must be writable) */ | 846 | /* find the instantiation authorisation key */ |
835 | key = lookup_user_key(id, 0, 1, KEY_WRITE); | 847 | instkey = key_get_instantiation_authkey(id); |
836 | if (IS_ERR(key)) { | 848 | if (IS_ERR(instkey)) { |
837 | ret = PTR_ERR(key); | 849 | ret = PTR_ERR(instkey); |
838 | goto error2; | 850 | goto error2; |
839 | } | 851 | } |
840 | 852 | ||
841 | /* find the destination keyring if present (which must also be | 853 | rka = instkey->payload.data; |
842 | * writable) */ | 854 | |
855 | /* find the destination keyring amongst those belonging to the | ||
856 | * requesting task */ | ||
843 | keyring = NULL; | 857 | keyring = NULL; |
844 | if (ringid) { | 858 | if (ringid) { |
845 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 859 | keyring = lookup_user_key(rka->context, ringid, 1, 0, |
860 | KEY_WRITE); | ||
846 | if (IS_ERR(keyring)) { | 861 | if (IS_ERR(keyring)) { |
847 | ret = PTR_ERR(keyring); | 862 | ret = PTR_ERR(keyring); |
848 | goto error3; | 863 | goto error3; |
@@ -850,11 +865,12 @@ long keyctl_instantiate_key(key_serial_t id, | |||
850 | } | 865 | } |
851 | 866 | ||
852 | /* instantiate the key and link it into a keyring */ | 867 | /* instantiate the key and link it into a keyring */ |
853 | ret = key_instantiate_and_link(key, payload, plen, keyring); | 868 | ret = key_instantiate_and_link(rka->target_key, payload, plen, |
869 | keyring, instkey); | ||
854 | 870 | ||
855 | key_put(keyring); | 871 | key_put(keyring); |
856 | error3: | 872 | error3: |
857 | key_put(key); | 873 | key_put(instkey); |
858 | error2: | 874 | error2: |
859 | kfree(payload); | 875 | kfree(payload); |
860 | error: | 876 | error: |
@@ -869,21 +885,24 @@ long keyctl_instantiate_key(key_serial_t id, | |||
869 | */ | 885 | */ |
870 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | 886 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
871 | { | 887 | { |
872 | struct key *key, *keyring; | 888 | struct request_key_auth *rka; |
889 | struct key *instkey, *keyring; | ||
873 | long ret; | 890 | long ret; |
874 | 891 | ||
875 | /* find the target key (which must be writable) */ | 892 | /* find the instantiation authorisation key */ |
876 | key = lookup_user_key(id, 0, 1, KEY_WRITE); | 893 | instkey = key_get_instantiation_authkey(id); |
877 | if (IS_ERR(key)) { | 894 | if (IS_ERR(instkey)) { |
878 | ret = PTR_ERR(key); | 895 | ret = PTR_ERR(instkey); |
879 | goto error; | 896 | goto error; |
880 | } | 897 | } |
881 | 898 | ||
899 | rka = instkey->payload.data; | ||
900 | |||
882 | /* find the destination keyring if present (which must also be | 901 | /* find the destination keyring if present (which must also be |
883 | * writable) */ | 902 | * writable) */ |
884 | keyring = NULL; | 903 | keyring = NULL; |
885 | if (ringid) { | 904 | if (ringid) { |
886 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 905 | keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
887 | if (IS_ERR(keyring)) { | 906 | if (IS_ERR(keyring)) { |
888 | ret = PTR_ERR(keyring); | 907 | ret = PTR_ERR(keyring); |
889 | goto error2; | 908 | goto error2; |
@@ -891,11 +910,11 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
891 | } | 910 | } |
892 | 911 | ||
893 | /* instantiate the key and link it into a keyring */ | 912 | /* instantiate the key and link it into a keyring */ |
894 | ret = key_negate_and_link(key, timeout, keyring); | 913 | ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey); |
895 | 914 | ||
896 | key_put(keyring); | 915 | key_put(keyring); |
897 | error2: | 916 | error2: |
898 | key_put(key); | 917 | key_put(instkey); |
899 | error: | 918 | error: |
900 | return ret; | 919 | return ret; |
901 | 920 | ||
@@ -903,6 +922,44 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
903 | 922 | ||
904 | /*****************************************************************************/ | 923 | /*****************************************************************************/ |
905 | /* | 924 | /* |
925 | * set the default keyring in which request_key() will cache keys | ||
926 | * - return the old setting | ||
927 | */ | ||
928 | long keyctl_set_reqkey_keyring(int reqkey_defl) | ||
929 | { | ||
930 | int ret; | ||
931 | |||
932 | switch (reqkey_defl) { | ||
933 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | ||
934 | ret = install_thread_keyring(current); | ||
935 | if (ret < 0) | ||
936 | return ret; | ||
937 | goto set; | ||
938 | |||
939 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | ||
940 | ret = install_process_keyring(current); | ||
941 | if (ret < 0) | ||
942 | return ret; | ||
943 | |||
944 | case KEY_REQKEY_DEFL_DEFAULT: | ||
945 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | ||
946 | case KEY_REQKEY_DEFL_USER_KEYRING: | ||
947 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | ||
948 | set: | ||
949 | current->jit_keyring = reqkey_defl; | ||
950 | |||
951 | case KEY_REQKEY_DEFL_NO_CHANGE: | ||
952 | return current->jit_keyring; | ||
953 | |||
954 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | ||
955 | default: | ||
956 | return -EINVAL; | ||
957 | } | ||
958 | |||
959 | } /* end keyctl_set_reqkey_keyring() */ | ||
960 | |||
961 | /*****************************************************************************/ | ||
962 | /* | ||
906 | * the key control system call | 963 | * the key control system call |
907 | */ | 964 | */ |
908 | asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | 965 | asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, |
@@ -971,6 +1028,9 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | |||
971 | (unsigned) arg3, | 1028 | (unsigned) arg3, |
972 | (key_serial_t) arg4); | 1029 | (key_serial_t) arg4); |
973 | 1030 | ||
1031 | case KEYCTL_SET_REQKEY_KEYRING: | ||
1032 | return keyctl_set_reqkey_keyring(arg2); | ||
1033 | |||
974 | default: | 1034 | default: |
975 | return -EOPNOTSUPP; | 1035 | return -EOPNOTSUPP; |
976 | } | 1036 | } |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index c9a5de197487..90a551e4da66 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* keyring.c: keyring handling | 1 | /* keyring.c: keyring handling |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -308,7 +308,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
308 | uid, gid, KEY_USR_ALL, not_in_quota); | 308 | uid, gid, KEY_USR_ALL, not_in_quota); |
309 | 309 | ||
310 | if (!IS_ERR(keyring)) { | 310 | if (!IS_ERR(keyring)) { |
311 | ret = key_instantiate_and_link(keyring, NULL, 0, dest); | 311 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); |
312 | if (ret < 0) { | 312 | if (ret < 0) { |
313 | key_put(keyring); | 313 | key_put(keyring); |
314 | keyring = ERR_PTR(ret); | 314 | keyring = ERR_PTR(ret); |
@@ -326,11 +326,12 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
326 | * - we only find keys on which we have search permission | 326 | * - we only find keys on which we have search permission |
327 | * - we use the supplied match function to see if the description (or other | 327 | * - we use the supplied match function to see if the description (or other |
328 | * feature of interest) matches | 328 | * feature of interest) matches |
329 | * - we readlock the keyrings as we search down the tree | 329 | * - we rely on RCU to prevent the keyring lists from disappearing on us |
330 | * - we return -EAGAIN if we didn't find any matching key | 330 | * - we return -EAGAIN if we didn't find any matching key |
331 | * - we return -ENOKEY if we only found negative matching keys | 331 | * - we return -ENOKEY if we only found negative matching keys |
332 | */ | 332 | */ |
333 | struct key *keyring_search_aux(struct key *keyring, | 333 | struct key *keyring_search_aux(struct key *keyring, |
334 | struct task_struct *context, | ||
334 | struct key_type *type, | 335 | struct key_type *type, |
335 | const void *description, | 336 | const void *description, |
336 | key_match_func_t match) | 337 | key_match_func_t match) |
@@ -352,7 +353,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
352 | 353 | ||
353 | /* top keyring must have search permission to begin the search */ | 354 | /* top keyring must have search permission to begin the search */ |
354 | key = ERR_PTR(-EACCES); | 355 | key = ERR_PTR(-EACCES); |
355 | if (!key_permission(keyring, KEY_SEARCH)) | 356 | if (!key_task_permission(keyring, context, KEY_SEARCH)) |
356 | goto error; | 357 | goto error; |
357 | 358 | ||
358 | key = ERR_PTR(-ENOTDIR); | 359 | key = ERR_PTR(-ENOTDIR); |
@@ -392,7 +393,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
392 | continue; | 393 | continue; |
393 | 394 | ||
394 | /* key must have search permissions */ | 395 | /* key must have search permissions */ |
395 | if (!key_permission(key, KEY_SEARCH)) | 396 | if (!key_task_permission(key, context, KEY_SEARCH)) |
396 | continue; | 397 | continue; |
397 | 398 | ||
398 | /* we set a different error code if we find a negative key */ | 399 | /* we set a different error code if we find a negative key */ |
@@ -418,7 +419,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
418 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) | 419 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) |
419 | continue; | 420 | continue; |
420 | 421 | ||
421 | if (!key_permission(key, KEY_SEARCH)) | 422 | if (!key_task_permission(key, context, KEY_SEARCH)) |
422 | continue; | 423 | continue; |
423 | 424 | ||
424 | /* stack the current position */ | 425 | /* stack the current position */ |
@@ -468,7 +469,11 @@ struct key *keyring_search(struct key *keyring, | |||
468 | struct key_type *type, | 469 | struct key_type *type, |
469 | const char *description) | 470 | const char *description) |
470 | { | 471 | { |
471 | return keyring_search_aux(keyring, type, description, type->match); | 472 | if (!type->match) |
473 | return ERR_PTR(-ENOKEY); | ||
474 | |||
475 | return keyring_search_aux(keyring, current, | ||
476 | type, description, type->match); | ||
472 | 477 | ||
473 | } /* end keyring_search() */ | 478 | } /* end keyring_search() */ |
474 | 479 | ||
@@ -496,7 +501,8 @@ struct key *__keyring_search_one(struct key *keyring, | |||
496 | key = klist->keys[loop]; | 501 | key = klist->keys[loop]; |
497 | 502 | ||
498 | if (key->type == ktype && | 503 | if (key->type == ktype && |
499 | key->type->match(key, description) && | 504 | (!key->type->match || |
505 | key->type->match(key, description)) && | ||
500 | key_permission(key, perm) && | 506 | key_permission(key, perm) && |
501 | !test_bit(KEY_FLAG_REVOKED, &key->flags) | 507 | !test_bit(KEY_FLAG_REVOKED, &key->flags) |
502 | ) | 508 | ) |
@@ -517,6 +523,51 @@ struct key *__keyring_search_one(struct key *keyring, | |||
517 | 523 | ||
518 | /*****************************************************************************/ | 524 | /*****************************************************************************/ |
519 | /* | 525 | /* |
526 | * search for an instantiation authorisation key matching a target key | ||
527 | * - the RCU read lock must be held by the caller | ||
528 | * - a target_id of zero specifies any valid token | ||
529 | */ | ||
530 | struct key *keyring_search_instkey(struct key *keyring, | ||
531 | key_serial_t target_id) | ||
532 | { | ||
533 | struct request_key_auth *rka; | ||
534 | struct keyring_list *klist; | ||
535 | struct key *instkey; | ||
536 | int loop; | ||
537 | |||
538 | klist = rcu_dereference(keyring->payload.subscriptions); | ||
539 | if (klist) { | ||
540 | for (loop = 0; loop < klist->nkeys; loop++) { | ||
541 | instkey = klist->keys[loop]; | ||
542 | |||
543 | if (instkey->type != &key_type_request_key_auth) | ||
544 | continue; | ||
545 | |||
546 | rka = instkey->payload.data; | ||
547 | if (target_id && rka->target_key->serial != target_id) | ||
548 | continue; | ||
549 | |||
550 | /* the auth key is revoked during instantiation */ | ||
551 | if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags)) | ||
552 | goto found; | ||
553 | |||
554 | instkey = ERR_PTR(-EKEYREVOKED); | ||
555 | goto error; | ||
556 | } | ||
557 | } | ||
558 | |||
559 | instkey = ERR_PTR(-EACCES); | ||
560 | goto error; | ||
561 | |||
562 | found: | ||
563 | atomic_inc(&instkey->usage); | ||
564 | error: | ||
565 | return instkey; | ||
566 | |||
567 | } /* end keyring_search_instkey() */ | ||
568 | |||
569 | /*****************************************************************************/ | ||
570 | /* | ||
520 | * find a keyring with the specified name | 571 | * find a keyring with the specified name |
521 | * - all named keyrings are searched | 572 | * - all named keyrings are searched |
522 | * - only find keyrings with search permission for the process | 573 | * - only find keyrings with search permission for the process |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 972e30172687..34db087bbcc7 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -165,7 +165,7 @@ int install_thread_keyring(struct task_struct *tsk) | |||
165 | /* | 165 | /* |
166 | * make sure a process keyring is installed | 166 | * make sure a process keyring is installed |
167 | */ | 167 | */ |
168 | static int install_process_keyring(struct task_struct *tsk) | 168 | int install_process_keyring(struct task_struct *tsk) |
169 | { | 169 | { |
170 | unsigned long flags; | 170 | unsigned long flags; |
171 | struct key *keyring; | 171 | struct key *keyring; |
@@ -376,12 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
376 | * - we return -EAGAIN if we didn't find any matching key | 376 | * - we return -EAGAIN if we didn't find any matching key |
377 | * - we return -ENOKEY if we found only negative matching keys | 377 | * - we return -ENOKEY if we found only negative matching keys |
378 | */ | 378 | */ |
379 | struct key *search_process_keyrings_aux(struct key_type *type, | 379 | struct key *search_process_keyrings(struct key_type *type, |
380 | const void *description, | 380 | const void *description, |
381 | key_match_func_t match) | 381 | key_match_func_t match, |
382 | struct task_struct *context) | ||
382 | { | 383 | { |
383 | struct task_struct *tsk = current; | 384 | struct request_key_auth *rka; |
384 | struct key *key, *ret, *err; | 385 | struct key *key, *ret, *err, *instkey; |
385 | 386 | ||
386 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were | 387 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were |
387 | * searchable, but we failed to find a key or we found a negative key; | 388 | * searchable, but we failed to find a key or we found a negative key; |
@@ -395,9 +396,9 @@ struct key *search_process_keyrings_aux(struct key_type *type, | |||
395 | err = ERR_PTR(-EAGAIN); | 396 | err = ERR_PTR(-EAGAIN); |
396 | 397 | ||
397 | /* search the thread keyring first */ | 398 | /* search the thread keyring first */ |
398 | if (tsk->thread_keyring) { | 399 | if (context->thread_keyring) { |
399 | key = keyring_search_aux(tsk->thread_keyring, type, | 400 | key = keyring_search_aux(context->thread_keyring, |
400 | description, match); | 401 | context, type, description, match); |
401 | if (!IS_ERR(key)) | 402 | if (!IS_ERR(key)) |
402 | goto found; | 403 | goto found; |
403 | 404 | ||
@@ -415,9 +416,9 @@ struct key *search_process_keyrings_aux(struct key_type *type, | |||
415 | } | 416 | } |
416 | 417 | ||
417 | /* search the process keyring second */ | 418 | /* search the process keyring second */ |
418 | if (tsk->signal->process_keyring) { | 419 | if (context->signal->process_keyring) { |
419 | key = keyring_search_aux(tsk->signal->process_keyring, | 420 | key = keyring_search_aux(context->signal->process_keyring, |
420 | type, description, match); | 421 | context, type, description, match); |
421 | if (!IS_ERR(key)) | 422 | if (!IS_ERR(key)) |
422 | goto found; | 423 | goto found; |
423 | 424 | ||
@@ -434,53 +435,93 @@ struct key *search_process_keyrings_aux(struct key_type *type, | |||
434 | } | 435 | } |
435 | } | 436 | } |
436 | 437 | ||
437 | /* search the session keyring last */ | 438 | /* search the session keyring */ |
438 | if (tsk->signal->session_keyring) { | 439 | if (context->signal->session_keyring) { |
439 | rcu_read_lock(); | 440 | rcu_read_lock(); |
440 | key = keyring_search_aux( | 441 | key = keyring_search_aux( |
441 | rcu_dereference(tsk->signal->session_keyring), | 442 | rcu_dereference(context->signal->session_keyring), |
442 | type, description, match); | 443 | context, type, description, match); |
443 | rcu_read_unlock(); | 444 | rcu_read_unlock(); |
445 | |||
446 | if (!IS_ERR(key)) | ||
447 | goto found; | ||
448 | |||
449 | switch (PTR_ERR(key)) { | ||
450 | case -EAGAIN: /* no key */ | ||
451 | if (ret) | ||
452 | break; | ||
453 | case -ENOKEY: /* negative key */ | ||
454 | ret = key; | ||
455 | break; | ||
456 | default: | ||
457 | err = key; | ||
458 | break; | ||
459 | } | ||
460 | |||
461 | /* if this process has a session keyring and that has an | ||
462 | * instantiation authorisation key in the bottom level, then we | ||
463 | * also search the keyrings of the process mentioned there */ | ||
464 | if (context != current) | ||
465 | goto no_key; | ||
466 | |||
467 | rcu_read_lock(); | ||
468 | instkey = __keyring_search_one( | ||
469 | rcu_dereference(context->signal->session_keyring), | ||
470 | &key_type_request_key_auth, NULL, 0); | ||
471 | rcu_read_unlock(); | ||
472 | |||
473 | if (IS_ERR(instkey)) | ||
474 | goto no_key; | ||
475 | |||
476 | rka = instkey->payload.data; | ||
477 | |||
478 | key = search_process_keyrings(type, description, match, | ||
479 | rka->context); | ||
480 | key_put(instkey); | ||
481 | |||
482 | if (!IS_ERR(key)) | ||
483 | goto found; | ||
484 | |||
485 | switch (PTR_ERR(key)) { | ||
486 | case -EAGAIN: /* no key */ | ||
487 | if (ret) | ||
488 | break; | ||
489 | case -ENOKEY: /* negative key */ | ||
490 | ret = key; | ||
491 | break; | ||
492 | default: | ||
493 | err = key; | ||
494 | break; | ||
495 | } | ||
444 | } | 496 | } |
497 | /* or search the user-session keyring */ | ||
445 | else { | 498 | else { |
446 | key = keyring_search_aux(tsk->user->session_keyring, | 499 | key = keyring_search_aux(context->user->session_keyring, |
447 | type, description, match); | 500 | context, type, description, match); |
448 | } | 501 | if (!IS_ERR(key)) |
449 | 502 | goto found; | |
450 | if (!IS_ERR(key)) | ||
451 | goto found; | ||
452 | 503 | ||
453 | switch (PTR_ERR(key)) { | 504 | switch (PTR_ERR(key)) { |
454 | case -EAGAIN: /* no key */ | 505 | case -EAGAIN: /* no key */ |
455 | if (ret) | 506 | if (ret) |
507 | break; | ||
508 | case -ENOKEY: /* negative key */ | ||
509 | ret = key; | ||
456 | break; | 510 | break; |
457 | case -ENOKEY: /* negative key */ | 511 | default: |
458 | ret = key; | 512 | err = key; |
459 | break; | 513 | break; |
460 | default: | 514 | } |
461 | err = key; | ||
462 | break; | ||
463 | } | 515 | } |
464 | 516 | ||
517 | |||
518 | no_key: | ||
465 | /* no key - decide on the error we're going to go for */ | 519 | /* no key - decide on the error we're going to go for */ |
466 | key = ret ? ret : err; | 520 | key = ret ? ret : err; |
467 | 521 | ||
468 | found: | 522 | found: |
469 | return key; | 523 | return key; |
470 | 524 | ||
471 | } /* end search_process_keyrings_aux() */ | ||
472 | |||
473 | /*****************************************************************************/ | ||
474 | /* | ||
475 | * search the process keyrings for the first matching key | ||
476 | * - we return -EAGAIN if we didn't find any matching key | ||
477 | * - we return -ENOKEY if we found only negative matching keys | ||
478 | */ | ||
479 | struct key *search_process_keyrings(struct key_type *type, | ||
480 | const char *description) | ||
481 | { | ||
482 | return search_process_keyrings_aux(type, description, type->match); | ||
483 | |||
484 | } /* end search_process_keyrings() */ | 525 | } /* end search_process_keyrings() */ |
485 | 526 | ||
486 | /*****************************************************************************/ | 527 | /*****************************************************************************/ |
@@ -489,72 +530,73 @@ struct key *search_process_keyrings(struct key_type *type, | |||
489 | * - don't create special keyrings unless so requested | 530 | * - don't create special keyrings unless so requested |
490 | * - partially constructed keys aren't found unless requested | 531 | * - partially constructed keys aren't found unless requested |
491 | */ | 532 | */ |
492 | struct key *lookup_user_key(key_serial_t id, int create, int partial, | 533 | struct key *lookup_user_key(struct task_struct *context, key_serial_t id, |
493 | key_perm_t perm) | 534 | int create, int partial, key_perm_t perm) |
494 | { | 535 | { |
495 | struct task_struct *tsk = current; | ||
496 | unsigned long flags; | ||
497 | struct key *key; | 536 | struct key *key; |
498 | int ret; | 537 | int ret; |
499 | 538 | ||
539 | if (!context) | ||
540 | context = current; | ||
541 | |||
500 | key = ERR_PTR(-ENOKEY); | 542 | key = ERR_PTR(-ENOKEY); |
501 | 543 | ||
502 | switch (id) { | 544 | switch (id) { |
503 | case KEY_SPEC_THREAD_KEYRING: | 545 | case KEY_SPEC_THREAD_KEYRING: |
504 | if (!tsk->thread_keyring) { | 546 | if (!context->thread_keyring) { |
505 | if (!create) | 547 | if (!create) |
506 | goto error; | 548 | goto error; |
507 | 549 | ||
508 | ret = install_thread_keyring(tsk); | 550 | ret = install_thread_keyring(context); |
509 | if (ret < 0) { | 551 | if (ret < 0) { |
510 | key = ERR_PTR(ret); | 552 | key = ERR_PTR(ret); |
511 | goto error; | 553 | goto error; |
512 | } | 554 | } |
513 | } | 555 | } |
514 | 556 | ||
515 | key = tsk->thread_keyring; | 557 | key = context->thread_keyring; |
516 | atomic_inc(&key->usage); | 558 | atomic_inc(&key->usage); |
517 | break; | 559 | break; |
518 | 560 | ||
519 | case KEY_SPEC_PROCESS_KEYRING: | 561 | case KEY_SPEC_PROCESS_KEYRING: |
520 | if (!tsk->signal->process_keyring) { | 562 | if (!context->signal->process_keyring) { |
521 | if (!create) | 563 | if (!create) |
522 | goto error; | 564 | goto error; |
523 | 565 | ||
524 | ret = install_process_keyring(tsk); | 566 | ret = install_process_keyring(context); |
525 | if (ret < 0) { | 567 | if (ret < 0) { |
526 | key = ERR_PTR(ret); | 568 | key = ERR_PTR(ret); |
527 | goto error; | 569 | goto error; |
528 | } | 570 | } |
529 | } | 571 | } |
530 | 572 | ||
531 | key = tsk->signal->process_keyring; | 573 | key = context->signal->process_keyring; |
532 | atomic_inc(&key->usage); | 574 | atomic_inc(&key->usage); |
533 | break; | 575 | break; |
534 | 576 | ||
535 | case KEY_SPEC_SESSION_KEYRING: | 577 | case KEY_SPEC_SESSION_KEYRING: |
536 | if (!tsk->signal->session_keyring) { | 578 | if (!context->signal->session_keyring) { |
537 | /* always install a session keyring upon access if one | 579 | /* always install a session keyring upon access if one |
538 | * doesn't exist yet */ | 580 | * doesn't exist yet */ |
539 | ret = install_session_keyring( | 581 | ret = install_session_keyring( |
540 | tsk, tsk->user->session_keyring); | 582 | context, context->user->session_keyring); |
541 | if (ret < 0) | 583 | if (ret < 0) |
542 | goto error; | 584 | goto error; |
543 | } | 585 | } |
544 | 586 | ||
545 | spin_lock_irqsave(&tsk->sighand->siglock, flags); | 587 | rcu_read_lock(); |
546 | key = tsk->signal->session_keyring; | 588 | key = rcu_dereference(context->signal->session_keyring); |
547 | atomic_inc(&key->usage); | 589 | atomic_inc(&key->usage); |
548 | spin_unlock_irqrestore(&tsk->sighand->siglock, flags); | 590 | rcu_read_unlock(); |
549 | break; | 591 | break; |
550 | 592 | ||
551 | case KEY_SPEC_USER_KEYRING: | 593 | case KEY_SPEC_USER_KEYRING: |
552 | key = tsk->user->uid_keyring; | 594 | key = context->user->uid_keyring; |
553 | atomic_inc(&key->usage); | 595 | atomic_inc(&key->usage); |
554 | break; | 596 | break; |
555 | 597 | ||
556 | case KEY_SPEC_USER_SESSION_KEYRING: | 598 | case KEY_SPEC_USER_SESSION_KEYRING: |
557 | key = tsk->user->session_keyring; | 599 | key = context->user->session_keyring; |
558 | atomic_inc(&key->usage); | 600 | atomic_inc(&key->usage); |
559 | break; | 601 | break; |
560 | 602 | ||
@@ -574,7 +616,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial, | |||
574 | break; | 616 | break; |
575 | } | 617 | } |
576 | 618 | ||
577 | /* check the status and permissions */ | 619 | /* check the status */ |
578 | if (perm) { | 620 | if (perm) { |
579 | ret = key_validate(key); | 621 | ret = key_validate(key); |
580 | if (ret < 0) | 622 | if (ret < 0) |
@@ -585,8 +627,10 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial, | |||
585 | if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | 627 | if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) |
586 | goto invalid_key; | 628 | goto invalid_key; |
587 | 629 | ||
630 | /* check the permissions */ | ||
588 | ret = -EACCES; | 631 | ret = -EACCES; |
589 | if (!key_permission(key, perm)) | 632 | |
633 | if (!key_task_permission(key, context, perm)) | ||
590 | goto invalid_key; | 634 | goto invalid_key; |
591 | 635 | ||
592 | error: | 636 | error: |
@@ -609,7 +653,6 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial, | |||
609 | long join_session_keyring(const char *name) | 653 | long join_session_keyring(const char *name) |
610 | { | 654 | { |
611 | struct task_struct *tsk = current; | 655 | struct task_struct *tsk = current; |
612 | unsigned long flags; | ||
613 | struct key *keyring; | 656 | struct key *keyring; |
614 | long ret; | 657 | long ret; |
615 | 658 | ||
@@ -619,9 +662,9 @@ long join_session_keyring(const char *name) | |||
619 | if (ret < 0) | 662 | if (ret < 0) |
620 | goto error; | 663 | goto error; |
621 | 664 | ||
622 | spin_lock_irqsave(&tsk->sighand->siglock, flags); | 665 | rcu_read_lock(); |
623 | ret = tsk->signal->session_keyring->serial; | 666 | ret = rcu_dereference(tsk->signal->session_keyring)->serial; |
624 | spin_unlock_irqrestore(&tsk->sighand->siglock, flags); | 667 | rcu_read_unlock(); |
625 | goto error; | 668 | goto error; |
626 | } | 669 | } |
627 | 670 | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 54aa7b70e63b..dfcd983af1fd 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* request_key.c: request a key from userspace | 1 | /* request_key.c: request a key from userspace |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/kmod.h> | 14 | #include <linux/kmod.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/keyctl.h> | ||
16 | #include "internal.h" | 17 | #include "internal.h" |
17 | 18 | ||
18 | struct key_construction { | 19 | struct key_construction { |
@@ -27,18 +28,26 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq); | |||
27 | /* | 28 | /* |
28 | * request userspace finish the construction of a key | 29 | * request userspace finish the construction of a key |
29 | * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>" | 30 | * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>" |
30 | * - if callout_info is an empty string, it'll be rendered as a "-" instead | ||
31 | */ | 31 | */ |
32 | static int call_request_key(struct key *key, | 32 | static int call_request_key(struct key *key, |
33 | const char *op, | 33 | const char *op, |
34 | const char *callout_info) | 34 | const char *callout_info) |
35 | { | 35 | { |
36 | struct task_struct *tsk = current; | 36 | struct task_struct *tsk = current; |
37 | unsigned long flags; | ||
38 | key_serial_t prkey, sskey; | 37 | key_serial_t prkey, sskey; |
38 | struct key *session_keyring, *rkakey; | ||
39 | char *argv[10], *envp[3], uid_str[12], gid_str[12]; | 39 | char *argv[10], *envp[3], uid_str[12], gid_str[12]; |
40 | char key_str[12], keyring_str[3][12]; | 40 | char key_str[12], keyring_str[3][12]; |
41 | int i; | 41 | int ret, i; |
42 | |||
43 | kenter("{%d},%s,%s", key->serial, op, callout_info); | ||
44 | |||
45 | /* generate a new session keyring with an auth key in it */ | ||
46 | session_keyring = request_key_auth_new(key, &rkakey); | ||
47 | if (IS_ERR(session_keyring)) { | ||
48 | ret = PTR_ERR(session_keyring); | ||
49 | goto error; | ||
50 | } | ||
42 | 51 | ||
43 | /* record the UID and GID */ | 52 | /* record the UID and GID */ |
44 | sprintf(uid_str, "%d", current->fsuid); | 53 | sprintf(uid_str, "%d", current->fsuid); |
@@ -55,17 +64,17 @@ static int call_request_key(struct key *key, | |||
55 | if (tsk->signal->process_keyring) | 64 | if (tsk->signal->process_keyring) |
56 | prkey = tsk->signal->process_keyring->serial; | 65 | prkey = tsk->signal->process_keyring->serial; |
57 | 66 | ||
58 | sskey = 0; | 67 | sprintf(keyring_str[1], "%d", prkey); |
59 | spin_lock_irqsave(&tsk->sighand->siglock, flags); | ||
60 | if (tsk->signal->session_keyring) | ||
61 | sskey = tsk->signal->session_keyring->serial; | ||
62 | spin_unlock_irqrestore(&tsk->sighand->siglock, flags); | ||
63 | |||
64 | 68 | ||
65 | if (!sskey) | 69 | if (tsk->signal->session_keyring) { |
70 | rcu_read_lock(); | ||
71 | sskey = rcu_dereference(tsk->signal->session_keyring)->serial; | ||
72 | rcu_read_unlock(); | ||
73 | } | ||
74 | else { | ||
66 | sskey = tsk->user->session_keyring->serial; | 75 | sskey = tsk->user->session_keyring->serial; |
76 | } | ||
67 | 77 | ||
68 | sprintf(keyring_str[1], "%d", prkey); | ||
69 | sprintf(keyring_str[2], "%d", sskey); | 78 | sprintf(keyring_str[2], "%d", sskey); |
70 | 79 | ||
71 | /* set up a minimal environment */ | 80 | /* set up a minimal environment */ |
@@ -84,11 +93,20 @@ static int call_request_key(struct key *key, | |||
84 | argv[i++] = keyring_str[0]; | 93 | argv[i++] = keyring_str[0]; |
85 | argv[i++] = keyring_str[1]; | 94 | argv[i++] = keyring_str[1]; |
86 | argv[i++] = keyring_str[2]; | 95 | argv[i++] = keyring_str[2]; |
87 | argv[i++] = callout_info[0] ? (char *) callout_info : "-"; | 96 | argv[i++] = (char *) callout_info; |
88 | argv[i] = NULL; | 97 | argv[i] = NULL; |
89 | 98 | ||
90 | /* do it */ | 99 | /* do it */ |
91 | return call_usermodehelper_keys(argv[0], argv, envp, NULL, 1); | 100 | ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1); |
101 | |||
102 | /* dispose of the special keys */ | ||
103 | key_revoke(rkakey); | ||
104 | key_put(rkakey); | ||
105 | key_put(session_keyring); | ||
106 | |||
107 | error: | ||
108 | kleave(" = %d", ret); | ||
109 | return ret; | ||
92 | 110 | ||
93 | } /* end call_request_key() */ | 111 | } /* end call_request_key() */ |
94 | 112 | ||
@@ -107,6 +125,8 @@ static struct key *__request_key_construction(struct key_type *type, | |||
107 | struct key *key; | 125 | struct key *key; |
108 | int ret, negated; | 126 | int ret, negated; |
109 | 127 | ||
128 | kenter("%s,%s,%s", type->name, description, callout_info); | ||
129 | |||
110 | /* create a key and add it to the queue */ | 130 | /* create a key and add it to the queue */ |
111 | key = key_alloc(type, description, | 131 | key = key_alloc(type, description, |
112 | current->fsuid, current->fsgid, KEY_USR_ALL, 0); | 132 | current->fsuid, current->fsgid, KEY_USR_ALL, 0); |
@@ -143,6 +163,7 @@ static struct key *__request_key_construction(struct key_type *type, | |||
143 | } | 163 | } |
144 | 164 | ||
145 | out: | 165 | out: |
166 | kleave(" = %p", key); | ||
146 | return key; | 167 | return key; |
147 | 168 | ||
148 | request_failed: | 169 | request_failed: |
@@ -216,6 +237,9 @@ static struct key *request_key_construction(struct key_type *type, | |||
216 | 237 | ||
217 | DECLARE_WAITQUEUE(myself, current); | 238 | DECLARE_WAITQUEUE(myself, current); |
218 | 239 | ||
240 | kenter("%s,%s,{%d},%s", | ||
241 | type->name, description, user->uid, callout_info); | ||
242 | |||
219 | /* see if there's such a key under construction already */ | 243 | /* see if there's such a key under construction already */ |
220 | down_write(&key_construction_sem); | 244 | down_write(&key_construction_sem); |
221 | 245 | ||
@@ -232,6 +256,7 @@ static struct key *request_key_construction(struct key_type *type, | |||
232 | /* see about getting userspace to construct the key */ | 256 | /* see about getting userspace to construct the key */ |
233 | key = __request_key_construction(type, description, callout_info); | 257 | key = __request_key_construction(type, description, callout_info); |
234 | error: | 258 | error: |
259 | kleave(" = %p", key); | ||
235 | return key; | 260 | return key; |
236 | 261 | ||
237 | /* someone else has the same key under construction | 262 | /* someone else has the same key under construction |
@@ -245,9 +270,11 @@ static struct key *request_key_construction(struct key_type *type, | |||
245 | add_wait_queue(&request_key_conswq, &myself); | 270 | add_wait_queue(&request_key_conswq, &myself); |
246 | 271 | ||
247 | for (;;) { | 272 | for (;;) { |
248 | set_current_state(TASK_UNINTERRUPTIBLE); | 273 | set_current_state(TASK_INTERRUPTIBLE); |
249 | if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags)) | 274 | if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags)) |
250 | break; | 275 | break; |
276 | if (signal_pending(current)) | ||
277 | break; | ||
251 | schedule(); | 278 | schedule(); |
252 | } | 279 | } |
253 | 280 | ||
@@ -267,21 +294,83 @@ static struct key *request_key_construction(struct key_type *type, | |||
267 | 294 | ||
268 | /*****************************************************************************/ | 295 | /*****************************************************************************/ |
269 | /* | 296 | /* |
297 | * link a freshly minted key to an appropriate destination keyring | ||
298 | */ | ||
299 | static void request_key_link(struct key *key, struct key *dest_keyring) | ||
300 | { | ||
301 | struct task_struct *tsk = current; | ||
302 | struct key *drop = NULL; | ||
303 | |||
304 | kenter("{%d},%p", key->serial, dest_keyring); | ||
305 | |||
306 | /* find the appropriate keyring */ | ||
307 | if (!dest_keyring) { | ||
308 | switch (tsk->jit_keyring) { | ||
309 | case KEY_REQKEY_DEFL_DEFAULT: | ||
310 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | ||
311 | dest_keyring = tsk->thread_keyring; | ||
312 | if (dest_keyring) | ||
313 | break; | ||
314 | |||
315 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | ||
316 | dest_keyring = tsk->signal->process_keyring; | ||
317 | if (dest_keyring) | ||
318 | break; | ||
319 | |||
320 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | ||
321 | rcu_read_lock(); | ||
322 | dest_keyring = key_get( | ||
323 | rcu_dereference(tsk->signal->session_keyring)); | ||
324 | rcu_read_unlock(); | ||
325 | drop = dest_keyring; | ||
326 | |||
327 | if (dest_keyring) | ||
328 | break; | ||
329 | |||
330 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | ||
331 | dest_keyring = current->user->session_keyring; | ||
332 | break; | ||
333 | |||
334 | case KEY_REQKEY_DEFL_USER_KEYRING: | ||
335 | dest_keyring = current->user->uid_keyring; | ||
336 | break; | ||
337 | |||
338 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | ||
339 | default: | ||
340 | BUG(); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /* and attach the key to it */ | ||
345 | key_link(dest_keyring, key); | ||
346 | |||
347 | key_put(drop); | ||
348 | |||
349 | kleave(""); | ||
350 | |||
351 | } /* end request_key_link() */ | ||
352 | |||
353 | /*****************************************************************************/ | ||
354 | /* | ||
270 | * request a key | 355 | * request a key |
271 | * - search the process's keyrings | 356 | * - search the process's keyrings |
272 | * - check the list of keys being created or updated | 357 | * - check the list of keys being created or updated |
273 | * - call out to userspace for a key if requested (supplementary info can be | 358 | * - call out to userspace for a key if supplementary info was provided |
274 | * passed) | 359 | * - cache the key in an appropriate keyring |
275 | */ | 360 | */ |
276 | struct key *request_key(struct key_type *type, | 361 | struct key *request_key_and_link(struct key_type *type, |
277 | const char *description, | 362 | const char *description, |
278 | const char *callout_info) | 363 | const char *callout_info, |
364 | struct key *dest_keyring) | ||
279 | { | 365 | { |
280 | struct key_user *user; | 366 | struct key_user *user; |
281 | struct key *key; | 367 | struct key *key; |
282 | 368 | ||
369 | kenter("%s,%s,%s,%p", | ||
370 | type->name, description, callout_info, dest_keyring); | ||
371 | |||
283 | /* search all the process keyrings for a key */ | 372 | /* search all the process keyrings for a key */ |
284 | key = search_process_keyrings_aux(type, description, type->match); | 373 | key = search_process_keyrings(type, description, type->match, current); |
285 | 374 | ||
286 | if (PTR_ERR(key) == -EAGAIN) { | 375 | if (PTR_ERR(key) == -EAGAIN) { |
287 | /* the search failed, but the keyrings were searchable, so we | 376 | /* the search failed, but the keyrings were searchable, so we |
@@ -292,12 +381,13 @@ struct key *request_key(struct key_type *type, | |||
292 | 381 | ||
293 | /* - get hold of the user's construction queue */ | 382 | /* - get hold of the user's construction queue */ |
294 | user = key_user_lookup(current->fsuid); | 383 | user = key_user_lookup(current->fsuid); |
295 | if (!user) { | 384 | if (!user) |
296 | key = ERR_PTR(-ENOMEM); | 385 | goto nomem; |
297 | goto error; | 386 | |
298 | } | 387 | do { |
388 | if (signal_pending(current)) | ||
389 | goto interrupted; | ||
299 | 390 | ||
300 | for (;;) { | ||
301 | /* ask userspace (returns NULL if it waited on a key | 391 | /* ask userspace (returns NULL if it waited on a key |
302 | * being constructed) */ | 392 | * being constructed) */ |
303 | key = request_key_construction(type, description, | 393 | key = request_key_construction(type, description, |
@@ -307,18 +397,46 @@ struct key *request_key(struct key_type *type, | |||
307 | 397 | ||
308 | /* someone else made the key we want, so we need to | 398 | /* someone else made the key we want, so we need to |
309 | * search again as it might now be available to us */ | 399 | * search again as it might now be available to us */ |
310 | key = search_process_keyrings_aux(type, description, | 400 | key = search_process_keyrings(type, description, |
311 | type->match); | 401 | type->match, current); |
312 | if (PTR_ERR(key) != -EAGAIN) | 402 | |
313 | break; | 403 | } while (PTR_ERR(key) == -EAGAIN); |
314 | } | ||
315 | 404 | ||
316 | key_user_put(user); | 405 | key_user_put(user); |
406 | |||
407 | /* link the new key into the appropriate keyring */ | ||
408 | if (!PTR_ERR(key)) | ||
409 | request_key_link(key, dest_keyring); | ||
317 | } | 410 | } |
318 | 411 | ||
319 | error: | 412 | error: |
413 | kleave(" = %p", key); | ||
320 | return key; | 414 | return key; |
321 | 415 | ||
416 | nomem: | ||
417 | key = ERR_PTR(-ENOMEM); | ||
418 | goto error; | ||
419 | |||
420 | interrupted: | ||
421 | key_user_put(user); | ||
422 | key = ERR_PTR(-EINTR); | ||
423 | goto error; | ||
424 | |||
425 | } /* end request_key_and_link() */ | ||
426 | |||
427 | /*****************************************************************************/ | ||
428 | /* | ||
429 | * request a key | ||
430 | * - search the process's keyrings | ||
431 | * - check the list of keys being created or updated | ||
432 | * - call out to userspace for a key if supplementary info was provided | ||
433 | */ | ||
434 | struct key *request_key(struct key_type *type, | ||
435 | const char *description, | ||
436 | const char *callout_info) | ||
437 | { | ||
438 | return request_key_and_link(type, description, callout_info, NULL); | ||
439 | |||
322 | } /* end request_key() */ | 440 | } /* end request_key() */ |
323 | 441 | ||
324 | EXPORT_SYMBOL(request_key); | 442 | EXPORT_SYMBOL(request_key); |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c new file mode 100644 index 000000000000..f22264632229 --- /dev/null +++ b/security/keys/request_key_auth.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* request_key_auth.c: request key authorisation controlling key def | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/seq_file.h> | ||
16 | #include "internal.h" | ||
17 | |||
18 | static int request_key_auth_instantiate(struct key *, const void *, size_t); | ||
19 | static void request_key_auth_describe(const struct key *, struct seq_file *); | ||
20 | static void request_key_auth_destroy(struct key *); | ||
21 | |||
22 | /* | ||
23 | * the request-key authorisation key type definition | ||
24 | */ | ||
25 | struct key_type key_type_request_key_auth = { | ||
26 | .name = ".request_key_auth", | ||
27 | .def_datalen = sizeof(struct request_key_auth), | ||
28 | .instantiate = request_key_auth_instantiate, | ||
29 | .describe = request_key_auth_describe, | ||
30 | .destroy = request_key_auth_destroy, | ||
31 | }; | ||
32 | |||
33 | /*****************************************************************************/ | ||
34 | /* | ||
35 | * instantiate a request-key authorisation record | ||
36 | */ | ||
37 | static int request_key_auth_instantiate(struct key *key, | ||
38 | const void *data, | ||
39 | size_t datalen) | ||
40 | { | ||
41 | struct request_key_auth *rka, *irka; | ||
42 | struct key *instkey; | ||
43 | int ret; | ||
44 | |||
45 | ret = -ENOMEM; | ||
46 | rka = kmalloc(sizeof(*rka), GFP_KERNEL); | ||
47 | if (rka) { | ||
48 | /* see if the calling process is already servicing the key | ||
49 | * request of another process */ | ||
50 | instkey = key_get_instantiation_authkey(0); | ||
51 | if (!IS_ERR(instkey)) { | ||
52 | /* it is - use that instantiation context here too */ | ||
53 | irka = instkey->payload.data; | ||
54 | rka->context = irka->context; | ||
55 | rka->pid = irka->pid; | ||
56 | key_put(instkey); | ||
57 | } | ||
58 | else { | ||
59 | /* it isn't - use this process as the context */ | ||
60 | rka->context = current; | ||
61 | rka->pid = current->pid; | ||
62 | } | ||
63 | |||
64 | rka->target_key = key_get((struct key *) data); | ||
65 | key->payload.data = rka; | ||
66 | ret = 0; | ||
67 | } | ||
68 | |||
69 | return ret; | ||
70 | |||
71 | } /* end request_key_auth_instantiate() */ | ||
72 | |||
73 | /*****************************************************************************/ | ||
74 | /* | ||
75 | * | ||
76 | */ | ||
77 | static void request_key_auth_describe(const struct key *key, | ||
78 | struct seq_file *m) | ||
79 | { | ||
80 | struct request_key_auth *rka = key->payload.data; | ||
81 | |||
82 | seq_puts(m, "key:"); | ||
83 | seq_puts(m, key->description); | ||
84 | seq_printf(m, " pid:%d", rka->pid); | ||
85 | |||
86 | } /* end request_key_auth_describe() */ | ||
87 | |||
88 | /*****************************************************************************/ | ||
89 | /* | ||
90 | * destroy an instantiation authorisation token key | ||
91 | */ | ||
92 | static void request_key_auth_destroy(struct key *key) | ||
93 | { | ||
94 | struct request_key_auth *rka = key->payload.data; | ||
95 | |||
96 | kenter("{%d}", key->serial); | ||
97 | |||
98 | key_put(rka->target_key); | ||
99 | |||
100 | } /* end request_key_auth_destroy() */ | ||
101 | |||
102 | /*****************************************************************************/ | ||
103 | /* | ||
104 | * create a session keyring to be for the invokation of /sbin/request-key and | ||
105 | * stick an authorisation token in it | ||
106 | */ | ||
107 | struct key *request_key_auth_new(struct key *target, struct key **_rkakey) | ||
108 | { | ||
109 | struct key *keyring, *rkakey = NULL; | ||
110 | char desc[20]; | ||
111 | int ret; | ||
112 | |||
113 | kenter("%d,", target->serial); | ||
114 | |||
115 | /* allocate a new session keyring */ | ||
116 | sprintf(desc, "_req.%u", target->serial); | ||
117 | |||
118 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); | ||
119 | if (IS_ERR(keyring)) { | ||
120 | kleave("= %ld", PTR_ERR(keyring)); | ||
121 | return keyring; | ||
122 | } | ||
123 | |||
124 | /* allocate the auth key */ | ||
125 | sprintf(desc, "%x", target->serial); | ||
126 | |||
127 | rkakey = key_alloc(&key_type_request_key_auth, desc, | ||
128 | current->fsuid, current->fsgid, | ||
129 | KEY_USR_VIEW, 1); | ||
130 | if (IS_ERR(rkakey)) { | ||
131 | key_put(keyring); | ||
132 | kleave("= %ld", PTR_ERR(rkakey)); | ||
133 | return rkakey; | ||
134 | } | ||
135 | |||
136 | /* construct and attach to the keyring */ | ||
137 | ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL); | ||
138 | if (ret < 0) { | ||
139 | key_revoke(rkakey); | ||
140 | key_put(rkakey); | ||
141 | key_put(keyring); | ||
142 | kleave("= %d", ret); | ||
143 | return ERR_PTR(ret); | ||
144 | } | ||
145 | |||
146 | *_rkakey = rkakey; | ||
147 | kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial); | ||
148 | return keyring; | ||
149 | |||
150 | } /* end request_key_auth_new() */ | ||
151 | |||
152 | /*****************************************************************************/ | ||
153 | /* | ||
154 | * get the authorisation key for instantiation of a specific key if attached to | ||
155 | * the current process's keyrings | ||
156 | * - this key is inserted into a keyring and that is set as /sbin/request-key's | ||
157 | * session keyring | ||
158 | * - a target_id of zero specifies any valid token | ||
159 | */ | ||
160 | struct key *key_get_instantiation_authkey(key_serial_t target_id) | ||
161 | { | ||
162 | struct task_struct *tsk = current; | ||
163 | struct key *instkey; | ||
164 | |||
165 | /* we must have our own personal session keyring */ | ||
166 | if (!tsk->signal->session_keyring) | ||
167 | return ERR_PTR(-EACCES); | ||
168 | |||
169 | /* and it must contain a suitable request authorisation key | ||
170 | * - lock RCU against session keyring changing | ||
171 | */ | ||
172 | rcu_read_lock(); | ||
173 | |||
174 | instkey = keyring_search_instkey( | ||
175 | rcu_dereference(tsk->signal->session_keyring), target_id); | ||
176 | |||
177 | rcu_read_unlock(); | ||
178 | return instkey; | ||
179 | |||
180 | } /* end key_get_instantiation_authkey() */ | ||