diff options
author | Michael LeMay <mdlemay@epoch.ncsc.mil> | 2006-06-22 17:47:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-22 18:05:55 -0400 |
commit | d720024e94de4e8b7f10ee83c532926f3ad5d708 (patch) | |
tree | 8f21613c29a26bfbeb334cb0104b8b998b09fbdc | |
parent | f893afbe1262e27e91234506f72e17716190dd2f (diff) |
[PATCH] selinux: add hooks for key subsystem
Introduce SELinux hooks to support the access key retention subsystem
within the kernel. Incorporate new flask headers from a modified version
of the SELinux reference policy, with support for the new security class
representing retained keys. Extend the "key_alloc" security hook with a
task parameter representing the intended ownership context for the key
being allocated. Attach security information to root's default keyrings
within the SELinux initialization routine.
Has passed David's testsuite.
Signed-off-by: Michael LeMay <mdlemay@epoch.ncsc.mil>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Acked-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | Documentation/keys.txt | 29 | ||||
-rw-r--r-- | include/linux/key.h | 18 | ||||
-rw-r--r-- | include/linux/security.h | 10 | ||||
-rw-r--r-- | kernel/user.c | 2 | ||||
-rw-r--r-- | security/dummy.c | 2 | ||||
-rw-r--r-- | security/keys/key.c | 8 | ||||
-rw-r--r-- | security/keys/keyring.c | 5 | ||||
-rw-r--r-- | security/keys/process_keys.c | 15 | ||||
-rw-r--r-- | security/keys/request_key.c | 6 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 2 | ||||
-rw-r--r-- | security/selinux/hooks.c | 64 | ||||
-rw-r--r-- | security/selinux/include/av_perm_to_string.h | 6 | ||||
-rw-r--r-- | security/selinux/include/av_permissions.h | 8 | ||||
-rw-r--r-- | security/selinux/include/class_to_string.h | 1 | ||||
-rw-r--r-- | security/selinux/include/flask.h | 1 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 5 |
16 files changed, 155 insertions, 27 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt index aaa01b0e3ee9..703020012708 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt | |||
@@ -19,6 +19,7 @@ This document has the following sections: | |||
19 | - Key overview | 19 | - Key overview |
20 | - Key service overview | 20 | - Key service overview |
21 | - Key access permissions | 21 | - Key access permissions |
22 | - SELinux support | ||
22 | - New procfs files | 23 | - New procfs files |
23 | - Userspace system call interface | 24 | - Userspace system call interface |
24 | - Kernel services | 25 | - Kernel services |
@@ -232,6 +233,34 @@ For changing the ownership, group ID or permissions mask, being the owner of | |||
232 | the key or having the sysadmin capability is sufficient. | 233 | the key or having the sysadmin capability is sufficient. |
233 | 234 | ||
234 | 235 | ||
236 | =============== | ||
237 | SELINUX SUPPORT | ||
238 | =============== | ||
239 | |||
240 | The security class "key" has been added to SELinux so that mandatory access | ||
241 | controls can be applied to keys created within various contexts. This support | ||
242 | is preliminary, and is likely to change quite significantly in the near future. | ||
243 | Currently, all of the basic permissions explained above are provided in SELinux | ||
244 | as well; SE Linux is simply invoked after all basic permission checks have been | ||
245 | performed. | ||
246 | |||
247 | Each key is labeled with the same context as the task to which it belongs. | ||
248 | Typically, this is the same task that was running when the key was created. | ||
249 | The default keyrings are handled differently, but in a way that is very | ||
250 | intuitive: | ||
251 | |||
252 | (*) The user and user session keyrings that are created when the user logs in | ||
253 | are currently labeled with the context of the login manager. | ||
254 | |||
255 | (*) The keyrings associated with new threads are each labeled with the context | ||
256 | of their associated thread, and both session and process keyrings are | ||
257 | handled similarly. | ||
258 | |||
259 | Note, however, that the default keyrings associated with the root user are | ||
260 | labeled with the default kernel context, since they are created early in the | ||
261 | boot process, before root has a chance to log in. | ||
262 | |||
263 | |||
235 | ================ | 264 | ================ |
236 | NEW PROCFS FILES | 265 | NEW PROCFS FILES |
237 | ================ | 266 | ================ |
diff --git a/include/linux/key.h b/include/linux/key.h index cbf464ad9589..8c275d12ef63 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -241,8 +241,9 @@ extern void unregister_key_type(struct key_type *ktype); | |||
241 | 241 | ||
242 | extern struct key *key_alloc(struct key_type *type, | 242 | extern struct key *key_alloc(struct key_type *type, |
243 | const char *desc, | 243 | const char *desc, |
244 | uid_t uid, gid_t gid, key_perm_t perm, | 244 | uid_t uid, gid_t gid, |
245 | int not_in_quota); | 245 | struct task_struct *ctx, |
246 | key_perm_t perm, int not_in_quota); | ||
246 | extern int key_payload_reserve(struct key *key, size_t datalen); | 247 | extern int key_payload_reserve(struct key *key, size_t datalen); |
247 | extern int key_instantiate_and_link(struct key *key, | 248 | extern int key_instantiate_and_link(struct key *key, |
248 | const void *data, | 249 | const void *data, |
@@ -292,7 +293,9 @@ extern int key_unlink(struct key *keyring, | |||
292 | struct key *key); | 293 | struct key *key); |
293 | 294 | ||
294 | extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 295 | extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
295 | int not_in_quota, struct key *dest); | 296 | struct task_struct *ctx, |
297 | int not_in_quota, | ||
298 | struct key *dest); | ||
296 | 299 | ||
297 | extern int keyring_clear(struct key *keyring); | 300 | extern int keyring_clear(struct key *keyring); |
298 | 301 | ||
@@ -313,7 +316,8 @@ extern void keyring_replace_payload(struct key *key, void *replacement); | |||
313 | * the userspace interface | 316 | * the userspace interface |
314 | */ | 317 | */ |
315 | extern struct key root_user_keyring, root_session_keyring; | 318 | extern struct key root_user_keyring, root_session_keyring; |
316 | extern int alloc_uid_keyring(struct user_struct *user); | 319 | extern int alloc_uid_keyring(struct user_struct *user, |
320 | struct task_struct *ctx); | ||
317 | extern void switch_uid_keyring(struct user_struct *new_user); | 321 | extern void switch_uid_keyring(struct user_struct *new_user); |
318 | extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk); | 322 | extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk); |
319 | extern int copy_thread_group_keys(struct task_struct *tsk); | 323 | extern int copy_thread_group_keys(struct task_struct *tsk); |
@@ -342,7 +346,7 @@ extern void key_init(void); | |||
342 | #define make_key_ref(k) ({ NULL; }) | 346 | #define make_key_ref(k) ({ NULL; }) |
343 | #define key_ref_to_ptr(k) ({ NULL; }) | 347 | #define key_ref_to_ptr(k) ({ NULL; }) |
344 | #define is_key_possessed(k) 0 | 348 | #define is_key_possessed(k) 0 |
345 | #define alloc_uid_keyring(u) 0 | 349 | #define alloc_uid_keyring(u,c) 0 |
346 | #define switch_uid_keyring(u) do { } while(0) | 350 | #define switch_uid_keyring(u) do { } while(0) |
347 | #define __install_session_keyring(t, k) ({ NULL; }) | 351 | #define __install_session_keyring(t, k) ({ NULL; }) |
348 | #define copy_keys(f,t) 0 | 352 | #define copy_keys(f,t) 0 |
@@ -355,6 +359,10 @@ extern void key_init(void); | |||
355 | #define key_fsgid_changed(t) do { } while(0) | 359 | #define key_fsgid_changed(t) do { } while(0) |
356 | #define key_init() do { } while(0) | 360 | #define key_init() do { } while(0) |
357 | 361 | ||
362 | /* Initial keyrings */ | ||
363 | extern struct key root_user_keyring; | ||
364 | extern struct key root_session_keyring; | ||
365 | |||
358 | #endif /* CONFIG_KEYS */ | 366 | #endif /* CONFIG_KEYS */ |
359 | #endif /* __KERNEL__ */ | 367 | #endif /* __KERNEL__ */ |
360 | #endif /* _LINUX_KEY_H */ | 368 | #endif /* _LINUX_KEY_H */ |
diff --git a/include/linux/security.h b/include/linux/security.h index 4dfb1b84a9b3..47722d355532 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -1313,7 +1313,7 @@ struct security_operations { | |||
1313 | 1313 | ||
1314 | /* key management security hooks */ | 1314 | /* key management security hooks */ |
1315 | #ifdef CONFIG_KEYS | 1315 | #ifdef CONFIG_KEYS |
1316 | int (*key_alloc)(struct key *key); | 1316 | int (*key_alloc)(struct key *key, struct task_struct *tsk); |
1317 | void (*key_free)(struct key *key); | 1317 | void (*key_free)(struct key *key); |
1318 | int (*key_permission)(key_ref_t key_ref, | 1318 | int (*key_permission)(key_ref_t key_ref, |
1319 | struct task_struct *context, | 1319 | struct task_struct *context, |
@@ -3008,9 +3008,10 @@ static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid | |||
3008 | 3008 | ||
3009 | #ifdef CONFIG_KEYS | 3009 | #ifdef CONFIG_KEYS |
3010 | #ifdef CONFIG_SECURITY | 3010 | #ifdef CONFIG_SECURITY |
3011 | static inline int security_key_alloc(struct key *key) | 3011 | static inline int security_key_alloc(struct key *key, |
3012 | struct task_struct *tsk) | ||
3012 | { | 3013 | { |
3013 | return security_ops->key_alloc(key); | 3014 | return security_ops->key_alloc(key, tsk); |
3014 | } | 3015 | } |
3015 | 3016 | ||
3016 | static inline void security_key_free(struct key *key) | 3017 | static inline void security_key_free(struct key *key) |
@@ -3027,7 +3028,8 @@ static inline int security_key_permission(key_ref_t key_ref, | |||
3027 | 3028 | ||
3028 | #else | 3029 | #else |
3029 | 3030 | ||
3030 | static inline int security_key_alloc(struct key *key) | 3031 | static inline int security_key_alloc(struct key *key, |
3032 | struct task_struct *tsk) | ||
3031 | { | 3033 | { |
3032 | return 0; | 3034 | return 0; |
3033 | } | 3035 | } |
diff --git a/kernel/user.c b/kernel/user.c index 4b1eb745afa1..6408c0424291 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
@@ -148,7 +148,7 @@ struct user_struct * alloc_uid(uid_t uid) | |||
148 | new->mq_bytes = 0; | 148 | new->mq_bytes = 0; |
149 | new->locked_shm = 0; | 149 | new->locked_shm = 0; |
150 | 150 | ||
151 | if (alloc_uid_keyring(new) < 0) { | 151 | if (alloc_uid_keyring(new, current) < 0) { |
152 | kmem_cache_free(uid_cachep, new); | 152 | kmem_cache_free(uid_cachep, new); |
153 | return NULL; | 153 | return NULL; |
154 | } | 154 | } |
diff --git a/security/dummy.c b/security/dummy.c index 64f6da0f422e..6de4a4a5eb13 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -860,7 +860,7 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz | |||
860 | } | 860 | } |
861 | 861 | ||
862 | #ifdef CONFIG_KEYS | 862 | #ifdef CONFIG_KEYS |
863 | static inline int dummy_key_alloc(struct key *key) | 863 | static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx) |
864 | { | 864 | { |
865 | return 0; | 865 | return 0; |
866 | } | 866 | } |
diff --git a/security/keys/key.c b/security/keys/key.c index 3fdc49c6a02c..14a15abb7735 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -247,8 +247,8 @@ static inline void key_alloc_serial(struct key *key) | |||
247 | * instantiate the key or discard it before returning | 247 | * instantiate the key or discard it before returning |
248 | */ | 248 | */ |
249 | struct key *key_alloc(struct key_type *type, const char *desc, | 249 | struct key *key_alloc(struct key_type *type, const char *desc, |
250 | uid_t uid, gid_t gid, key_perm_t perm, | 250 | uid_t uid, gid_t gid, struct task_struct *ctx, |
251 | int not_in_quota) | 251 | key_perm_t perm, int not_in_quota) |
252 | { | 252 | { |
253 | struct key_user *user = NULL; | 253 | struct key_user *user = NULL; |
254 | struct key *key; | 254 | struct key *key; |
@@ -318,7 +318,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
318 | #endif | 318 | #endif |
319 | 319 | ||
320 | /* let the security module know about the key */ | 320 | /* let the security module know about the key */ |
321 | ret = security_key_alloc(key); | 321 | ret = security_key_alloc(key, ctx); |
322 | if (ret < 0) | 322 | if (ret < 0) |
323 | goto security_error; | 323 | goto security_error; |
324 | 324 | ||
@@ -822,7 +822,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
822 | 822 | ||
823 | /* allocate a new key */ | 823 | /* allocate a new key */ |
824 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, | 824 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, |
825 | perm, not_in_quota); | 825 | current, perm, not_in_quota); |
826 | if (IS_ERR(key)) { | 826 | if (IS_ERR(key)) { |
827 | key_ref = ERR_PTR(PTR_ERR(key)); | 827 | key_ref = ERR_PTR(PTR_ERR(key)); |
828 | goto error_3; | 828 | goto error_3; |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index bffa924c1f88..1357207fc9df 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -240,13 +240,14 @@ static long keyring_read(const struct key *keyring, | |||
240 | * allocate a keyring and link into the destination keyring | 240 | * allocate a keyring and link into the destination keyring |
241 | */ | 241 | */ |
242 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 242 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
243 | int not_in_quota, struct key *dest) | 243 | struct task_struct *ctx, int not_in_quota, |
244 | struct key *dest) | ||
244 | { | 245 | { |
245 | struct key *keyring; | 246 | struct key *keyring; |
246 | int ret; | 247 | int ret; |
247 | 248 | ||
248 | keyring = key_alloc(&key_type_keyring, description, | 249 | keyring = key_alloc(&key_type_keyring, description, |
249 | uid, gid, | 250 | uid, gid, ctx, |
250 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | 251 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, |
251 | not_in_quota); | 252 | not_in_quota); |
252 | 253 | ||
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 217a0bef3c82..a50a91332fe1 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -67,7 +67,8 @@ struct key root_session_keyring = { | |||
67 | /* | 67 | /* |
68 | * allocate the keyrings to be associated with a UID | 68 | * allocate the keyrings to be associated with a UID |
69 | */ | 69 | */ |
70 | int alloc_uid_keyring(struct user_struct *user) | 70 | int alloc_uid_keyring(struct user_struct *user, |
71 | struct task_struct *ctx) | ||
71 | { | 72 | { |
72 | struct key *uid_keyring, *session_keyring; | 73 | struct key *uid_keyring, *session_keyring; |
73 | char buf[20]; | 74 | char buf[20]; |
@@ -76,7 +77,7 @@ int alloc_uid_keyring(struct user_struct *user) | |||
76 | /* concoct a default session keyring */ | 77 | /* concoct a default session keyring */ |
77 | sprintf(buf, "_uid_ses.%u", user->uid); | 78 | sprintf(buf, "_uid_ses.%u", user->uid); |
78 | 79 | ||
79 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, NULL); | 80 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL); |
80 | if (IS_ERR(session_keyring)) { | 81 | if (IS_ERR(session_keyring)) { |
81 | ret = PTR_ERR(session_keyring); | 82 | ret = PTR_ERR(session_keyring); |
82 | goto error; | 83 | goto error; |
@@ -86,7 +87,7 @@ int alloc_uid_keyring(struct user_struct *user) | |||
86 | * keyring */ | 87 | * keyring */ |
87 | sprintf(buf, "_uid.%u", user->uid); | 88 | sprintf(buf, "_uid.%u", user->uid); |
88 | 89 | ||
89 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, | 90 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, |
90 | session_keyring); | 91 | session_keyring); |
91 | if (IS_ERR(uid_keyring)) { | 92 | if (IS_ERR(uid_keyring)) { |
92 | key_put(session_keyring); | 93 | key_put(session_keyring); |
@@ -143,7 +144,7 @@ int install_thread_keyring(struct task_struct *tsk) | |||
143 | 144 | ||
144 | sprintf(buf, "_tid.%u", tsk->pid); | 145 | sprintf(buf, "_tid.%u", tsk->pid); |
145 | 146 | ||
146 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 147 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
147 | if (IS_ERR(keyring)) { | 148 | if (IS_ERR(keyring)) { |
148 | ret = PTR_ERR(keyring); | 149 | ret = PTR_ERR(keyring); |
149 | goto error; | 150 | goto error; |
@@ -177,7 +178,7 @@ int install_process_keyring(struct task_struct *tsk) | |||
177 | if (!tsk->signal->process_keyring) { | 178 | if (!tsk->signal->process_keyring) { |
178 | sprintf(buf, "_pid.%u", tsk->tgid); | 179 | sprintf(buf, "_pid.%u", tsk->tgid); |
179 | 180 | ||
180 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 181 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
181 | if (IS_ERR(keyring)) { | 182 | if (IS_ERR(keyring)) { |
182 | ret = PTR_ERR(keyring); | 183 | ret = PTR_ERR(keyring); |
183 | goto error; | 184 | goto error; |
@@ -217,7 +218,7 @@ static int install_session_keyring(struct task_struct *tsk, | |||
217 | if (!keyring) { | 218 | if (!keyring) { |
218 | sprintf(buf, "_ses.%u", tsk->tgid); | 219 | sprintf(buf, "_ses.%u", tsk->tgid); |
219 | 220 | ||
220 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 221 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
221 | if (IS_ERR(keyring)) | 222 | if (IS_ERR(keyring)) |
222 | return PTR_ERR(keyring); | 223 | return PTR_ERR(keyring); |
223 | } | 224 | } |
@@ -717,7 +718,7 @@ long join_session_keyring(const char *name) | |||
717 | keyring = find_keyring_by_name(name, 0); | 718 | keyring = find_keyring_by_name(name, 0); |
718 | if (PTR_ERR(keyring) == -ENOKEY) { | 719 | if (PTR_ERR(keyring) == -ENOKEY) { |
719 | /* not found - try and create a new one */ | 720 | /* not found - try and create a new one */ |
720 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); | 721 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL); |
721 | if (IS_ERR(keyring)) { | 722 | if (IS_ERR(keyring)) { |
722 | ret = PTR_ERR(keyring); | 723 | ret = PTR_ERR(keyring); |
723 | goto error2; | 724 | goto error2; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index f030a0ccbb93..eab66a06ca53 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -48,7 +48,8 @@ static int call_sbin_request_key(struct key *key, | |||
48 | /* allocate a new session keyring */ | 48 | /* allocate a new session keyring */ |
49 | sprintf(desc, "_req.%u", key->serial); | 49 | sprintf(desc, "_req.%u", key->serial); |
50 | 50 | ||
51 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); | 51 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, |
52 | current, 1, NULL); | ||
52 | if (IS_ERR(keyring)) { | 53 | if (IS_ERR(keyring)) { |
53 | ret = PTR_ERR(keyring); | 54 | ret = PTR_ERR(keyring); |
54 | goto error_alloc; | 55 | goto error_alloc; |
@@ -137,7 +138,8 @@ static struct key *__request_key_construction(struct key_type *type, | |||
137 | 138 | ||
138 | /* create a key and add it to the queue */ | 139 | /* create a key and add it to the queue */ |
139 | key = key_alloc(type, description, | 140 | key = key_alloc(type, description, |
140 | current->fsuid, current->fsgid, KEY_POS_ALL, 0); | 141 | current->fsuid, current->fsgid, |
142 | current, KEY_POS_ALL, 0); | ||
141 | if (IS_ERR(key)) | 143 | if (IS_ERR(key)) |
142 | goto alloc_failed; | 144 | goto alloc_failed; |
143 | 145 | ||
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index cce6ba6b0323..0ecc2e8d2bd0 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -148,7 +148,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
148 | sprintf(desc, "%x", target->serial); | 148 | sprintf(desc, "%x", target->serial); |
149 | 149 | ||
150 | authkey = key_alloc(&key_type_request_key_auth, desc, | 150 | authkey = key_alloc(&key_type_request_key_auth, desc, |
151 | current->fsuid, current->fsgid, | 151 | current->fsuid, current->fsgid, current, |
152 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | | 152 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | |
153 | KEY_USR_VIEW, 1); | 153 | KEY_USR_VIEW, 1); |
154 | if (IS_ERR(authkey)) { | 154 | if (IS_ERR(authkey)) { |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 54adc9d31e92..524915dfda64 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -4252,6 +4252,57 @@ static int selinux_setprocattr(struct task_struct *p, | |||
4252 | return size; | 4252 | return size; |
4253 | } | 4253 | } |
4254 | 4254 | ||
4255 | #ifdef CONFIG_KEYS | ||
4256 | |||
4257 | static int selinux_key_alloc(struct key *k, struct task_struct *tsk) | ||
4258 | { | ||
4259 | struct task_security_struct *tsec = tsk->security; | ||
4260 | struct key_security_struct *ksec; | ||
4261 | |||
4262 | ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); | ||
4263 | if (!ksec) | ||
4264 | return -ENOMEM; | ||
4265 | |||
4266 | ksec->obj = k; | ||
4267 | ksec->sid = tsec->sid; | ||
4268 | k->security = ksec; | ||
4269 | |||
4270 | return 0; | ||
4271 | } | ||
4272 | |||
4273 | static void selinux_key_free(struct key *k) | ||
4274 | { | ||
4275 | struct key_security_struct *ksec = k->security; | ||
4276 | |||
4277 | k->security = NULL; | ||
4278 | kfree(ksec); | ||
4279 | } | ||
4280 | |||
4281 | static int selinux_key_permission(key_ref_t key_ref, | ||
4282 | struct task_struct *ctx, | ||
4283 | key_perm_t perm) | ||
4284 | { | ||
4285 | struct key *key; | ||
4286 | struct task_security_struct *tsec; | ||
4287 | struct key_security_struct *ksec; | ||
4288 | |||
4289 | key = key_ref_to_ptr(key_ref); | ||
4290 | |||
4291 | tsec = ctx->security; | ||
4292 | ksec = key->security; | ||
4293 | |||
4294 | /* if no specific permissions are requested, we skip the | ||
4295 | permission check. No serious, additional covert channels | ||
4296 | appear to be created. */ | ||
4297 | if (perm == 0) | ||
4298 | return 0; | ||
4299 | |||
4300 | return avc_has_perm(tsec->sid, ksec->sid, | ||
4301 | SECCLASS_KEY, perm, NULL); | ||
4302 | } | ||
4303 | |||
4304 | #endif | ||
4305 | |||
4255 | static struct security_operations selinux_ops = { | 4306 | static struct security_operations selinux_ops = { |
4256 | .ptrace = selinux_ptrace, | 4307 | .ptrace = selinux_ptrace, |
4257 | .capget = selinux_capget, | 4308 | .capget = selinux_capget, |
@@ -4406,6 +4457,12 @@ static struct security_operations selinux_ops = { | |||
4406 | .xfrm_state_delete_security = selinux_xfrm_state_delete, | 4457 | .xfrm_state_delete_security = selinux_xfrm_state_delete, |
4407 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, | 4458 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, |
4408 | #endif | 4459 | #endif |
4460 | |||
4461 | #ifdef CONFIG_KEYS | ||
4462 | .key_alloc = selinux_key_alloc, | ||
4463 | .key_free = selinux_key_free, | ||
4464 | .key_permission = selinux_key_permission, | ||
4465 | #endif | ||
4409 | }; | 4466 | }; |
4410 | 4467 | ||
4411 | static __init int selinux_init(void) | 4468 | static __init int selinux_init(void) |
@@ -4441,6 +4498,13 @@ static __init int selinux_init(void) | |||
4441 | } else { | 4498 | } else { |
4442 | printk(KERN_INFO "SELinux: Starting in permissive mode\n"); | 4499 | printk(KERN_INFO "SELinux: Starting in permissive mode\n"); |
4443 | } | 4500 | } |
4501 | |||
4502 | #ifdef CONFIG_KEYS | ||
4503 | /* Add security information to initial keyrings */ | ||
4504 | security_key_alloc(&root_user_keyring, current); | ||
4505 | security_key_alloc(&root_session_keyring, current); | ||
4506 | #endif | ||
4507 | |||
4444 | return 0; | 4508 | return 0; |
4445 | } | 4509 | } |
4446 | 4510 | ||
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 70ee65a58817..bc020bde6c86 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h | |||
@@ -242,3 +242,9 @@ | |||
242 | S_(SECCLASS_PACKET, PACKET__SEND, "send") | 242 | S_(SECCLASS_PACKET, PACKET__SEND, "send") |
243 | S_(SECCLASS_PACKET, PACKET__RECV, "recv") | 243 | S_(SECCLASS_PACKET, PACKET__RECV, "recv") |
244 | S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") | 244 | S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") |
245 | S_(SECCLASS_KEY, KEY__VIEW, "view") | ||
246 | S_(SECCLASS_KEY, KEY__READ, "read") | ||
247 | S_(SECCLASS_KEY, KEY__WRITE, "write") | ||
248 | S_(SECCLASS_KEY, KEY__SEARCH, "search") | ||
249 | S_(SECCLASS_KEY, KEY__LINK, "link") | ||
250 | S_(SECCLASS_KEY, KEY__SETATTR, "setattr") | ||
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 1d9cf3d306bc..1205227a3a33 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h | |||
@@ -959,3 +959,11 @@ | |||
959 | #define PACKET__SEND 0x00000001UL | 959 | #define PACKET__SEND 0x00000001UL |
960 | #define PACKET__RECV 0x00000002UL | 960 | #define PACKET__RECV 0x00000002UL |
961 | #define PACKET__RELABELTO 0x00000004UL | 961 | #define PACKET__RELABELTO 0x00000004UL |
962 | |||
963 | #define KEY__VIEW 0x00000001UL | ||
964 | #define KEY__READ 0x00000002UL | ||
965 | #define KEY__WRITE 0x00000004UL | ||
966 | #define KEY__SEARCH 0x00000008UL | ||
967 | #define KEY__LINK 0x00000010UL | ||
968 | #define KEY__SETATTR 0x00000020UL | ||
969 | |||
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index 3aec75fee4f7..24303b61309f 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h | |||
@@ -60,3 +60,4 @@ | |||
60 | S_("netlink_kobject_uevent_socket") | 60 | S_("netlink_kobject_uevent_socket") |
61 | S_("appletalk_socket") | 61 | S_("appletalk_socket") |
62 | S_("packet") | 62 | S_("packet") |
63 | S_("key") | ||
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index a0eb9e281d18..95887aed2a68 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h | |||
@@ -62,6 +62,7 @@ | |||
62 | #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 | 62 | #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 |
63 | #define SECCLASS_APPLETALK_SOCKET 56 | 63 | #define SECCLASS_APPLETALK_SOCKET 56 |
64 | #define SECCLASS_PACKET 57 | 64 | #define SECCLASS_PACKET 57 |
65 | #define SECCLASS_KEY 58 | ||
65 | 66 | ||
66 | /* | 67 | /* |
67 | * Security identifier indices for initial entities | 68 | * Security identifier indices for initial entities |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 54c030778882..8f5547ad1856 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
@@ -99,6 +99,11 @@ struct sk_security_struct { | |||
99 | u32 peer_sid; /* SID of peer */ | 99 | u32 peer_sid; /* SID of peer */ |
100 | }; | 100 | }; |
101 | 101 | ||
102 | struct key_security_struct { | ||
103 | struct key *obj; /* back pointer */ | ||
104 | u32 sid; /* SID of key */ | ||
105 | }; | ||
106 | |||
102 | extern unsigned int selinux_checkreqprot; | 107 | extern unsigned int selinux_checkreqprot; |
103 | 108 | ||
104 | #endif /* _SELINUX_OBJSEC_H_ */ | 109 | #endif /* _SELINUX_OBJSEC_H_ */ |