diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/dummy.c | 2 | ||||
| -rw-r--r-- | security/keys/key.c | 12 | ||||
| -rw-r--r-- | security/keys/keyring.c | 5 | ||||
| -rw-r--r-- | security/keys/process_keys.c | 57 | ||||
| -rw-r--r-- | security/keys/request_key.c | 6 | ||||
| -rw-r--r-- | security/keys/request_key_auth.c | 47 | ||||
| -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 |
12 files changed, 180 insertions, 34 deletions
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..51f851557389 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; |
| @@ -907,6 +907,10 @@ void key_revoke(struct key *key) | |||
| 907 | * it */ | 907 | * it */ |
| 908 | down_write(&key->sem); | 908 | down_write(&key->sem); |
| 909 | set_bit(KEY_FLAG_REVOKED, &key->flags); | 909 | set_bit(KEY_FLAG_REVOKED, &key->flags); |
| 910 | |||
| 911 | if (key->type->revoke) | ||
| 912 | key->type->revoke(key); | ||
| 913 | |||
| 910 | up_write(&key->sem); | 914 | up_write(&key->sem); |
| 911 | 915 | ||
| 912 | } /* end key_revoke() */ | 916 | } /* end key_revoke() */ |
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..4d9825f9962c 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 | } |
| @@ -390,6 +391,8 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
| 390 | struct request_key_auth *rka; | 391 | struct request_key_auth *rka; |
| 391 | key_ref_t key_ref, ret, err; | 392 | key_ref_t key_ref, ret, err; |
| 392 | 393 | ||
| 394 | might_sleep(); | ||
| 395 | |||
| 393 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were | 396 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were |
| 394 | * searchable, but we failed to find a key or we found a negative key; | 397 | * searchable, but we failed to find a key or we found a negative key; |
| 395 | * otherwise we want to return a sample error (probably -EACCES) if | 398 | * otherwise we want to return a sample error (probably -EACCES) if |
| @@ -495,27 +498,35 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
| 495 | */ | 498 | */ |
| 496 | if (context->request_key_auth && | 499 | if (context->request_key_auth && |
| 497 | context == current && | 500 | context == current && |
| 498 | type != &key_type_request_key_auth && | 501 | type != &key_type_request_key_auth |
| 499 | key_validate(context->request_key_auth) == 0 | ||
| 500 | ) { | 502 | ) { |
| 501 | rka = context->request_key_auth->payload.data; | 503 | /* defend against the auth key being revoked */ |
| 504 | down_read(&context->request_key_auth->sem); | ||
| 502 | 505 | ||
| 503 | key_ref = search_process_keyrings(type, description, match, | 506 | if (key_validate(context->request_key_auth) == 0) { |
| 504 | rka->context); | 507 | rka = context->request_key_auth->payload.data; |
| 505 | 508 | ||
| 506 | if (!IS_ERR(key_ref)) | 509 | key_ref = search_process_keyrings(type, description, |
| 507 | goto found; | 510 | match, rka->context); |
| 508 | 511 | ||
| 509 | switch (PTR_ERR(key_ref)) { | 512 | up_read(&context->request_key_auth->sem); |
| 510 | case -EAGAIN: /* no key */ | 513 | |
| 511 | if (ret) | 514 | if (!IS_ERR(key_ref)) |
| 515 | goto found; | ||
| 516 | |||
| 517 | switch (PTR_ERR(key_ref)) { | ||
| 518 | case -EAGAIN: /* no key */ | ||
| 519 | if (ret) | ||
| 520 | break; | ||
| 521 | case -ENOKEY: /* negative key */ | ||
| 522 | ret = key_ref; | ||
| 512 | break; | 523 | break; |
| 513 | case -ENOKEY: /* negative key */ | 524 | default: |
| 514 | ret = key_ref; | 525 | err = key_ref; |
| 515 | break; | 526 | break; |
| 516 | default: | 527 | } |
| 517 | err = key_ref; | 528 | } else { |
| 518 | break; | 529 | up_read(&context->request_key_auth->sem); |
| 519 | } | 530 | } |
| 520 | } | 531 | } |
| 521 | 532 | ||
| @@ -717,7 +728,7 @@ long join_session_keyring(const char *name) | |||
| 717 | keyring = find_keyring_by_name(name, 0); | 728 | keyring = find_keyring_by_name(name, 0); |
| 718 | if (PTR_ERR(keyring) == -ENOKEY) { | 729 | if (PTR_ERR(keyring) == -ENOKEY) { |
| 719 | /* not found - try and create a new one */ | 730 | /* not found - try and create a new one */ |
| 720 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); | 731 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL); |
| 721 | if (IS_ERR(keyring)) { | 732 | if (IS_ERR(keyring)) { |
| 722 | ret = PTR_ERR(keyring); | 733 | ret = PTR_ERR(keyring); |
| 723 | goto error2; | 734 | 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..cb9817ced3fd 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | static int request_key_auth_instantiate(struct key *, const void *, size_t); | 21 | static int request_key_auth_instantiate(struct key *, const void *, size_t); |
| 22 | static void request_key_auth_describe(const struct key *, struct seq_file *); | 22 | static void request_key_auth_describe(const struct key *, struct seq_file *); |
| 23 | static void request_key_auth_revoke(struct key *); | ||
| 23 | static void request_key_auth_destroy(struct key *); | 24 | static void request_key_auth_destroy(struct key *); |
| 24 | static long request_key_auth_read(const struct key *, char __user *, size_t); | 25 | static long request_key_auth_read(const struct key *, char __user *, size_t); |
| 25 | 26 | ||
| @@ -31,6 +32,7 @@ struct key_type key_type_request_key_auth = { | |||
| 31 | .def_datalen = sizeof(struct request_key_auth), | 32 | .def_datalen = sizeof(struct request_key_auth), |
| 32 | .instantiate = request_key_auth_instantiate, | 33 | .instantiate = request_key_auth_instantiate, |
| 33 | .describe = request_key_auth_describe, | 34 | .describe = request_key_auth_describe, |
| 35 | .revoke = request_key_auth_revoke, | ||
| 34 | .destroy = request_key_auth_destroy, | 36 | .destroy = request_key_auth_destroy, |
| 35 | .read = request_key_auth_read, | 37 | .read = request_key_auth_read, |
| 36 | }; | 38 | }; |
| @@ -93,6 +95,24 @@ static long request_key_auth_read(const struct key *key, | |||
| 93 | 95 | ||
| 94 | /*****************************************************************************/ | 96 | /*****************************************************************************/ |
| 95 | /* | 97 | /* |
| 98 | * handle revocation of an authorisation token key | ||
| 99 | * - called with the key sem write-locked | ||
| 100 | */ | ||
| 101 | static void request_key_auth_revoke(struct key *key) | ||
| 102 | { | ||
| 103 | struct request_key_auth *rka = key->payload.data; | ||
| 104 | |||
| 105 | kenter("{%d}", key->serial); | ||
| 106 | |||
| 107 | if (rka->context) { | ||
| 108 | put_task_struct(rka->context); | ||
| 109 | rka->context = NULL; | ||
| 110 | } | ||
| 111 | |||
| 112 | } /* end request_key_auth_revoke() */ | ||
| 113 | |||
| 114 | /*****************************************************************************/ | ||
| 115 | /* | ||
| 96 | * destroy an instantiation authorisation token key | 116 | * destroy an instantiation authorisation token key |
| 97 | */ | 117 | */ |
| 98 | static void request_key_auth_destroy(struct key *key) | 118 | static void request_key_auth_destroy(struct key *key) |
| @@ -101,6 +121,11 @@ static void request_key_auth_destroy(struct key *key) | |||
| 101 | 121 | ||
| 102 | kenter("{%d}", key->serial); | 122 | kenter("{%d}", key->serial); |
| 103 | 123 | ||
| 124 | if (rka->context) { | ||
| 125 | put_task_struct(rka->context); | ||
| 126 | rka->context = NULL; | ||
| 127 | } | ||
| 128 | |||
| 104 | key_put(rka->target_key); | 129 | key_put(rka->target_key); |
| 105 | kfree(rka); | 130 | kfree(rka); |
| 106 | 131 | ||
| @@ -131,14 +156,26 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
| 131 | * another process */ | 156 | * another process */ |
| 132 | if (current->request_key_auth) { | 157 | if (current->request_key_auth) { |
| 133 | /* it is - use that instantiation context here too */ | 158 | /* it is - use that instantiation context here too */ |
| 159 | down_read(¤t->request_key_auth->sem); | ||
| 160 | |||
| 161 | /* if the auth key has been revoked, then the key we're | ||
| 162 | * servicing is already instantiated */ | ||
| 163 | if (test_bit(KEY_FLAG_REVOKED, | ||
| 164 | ¤t->request_key_auth->flags)) | ||
| 165 | goto auth_key_revoked; | ||
| 166 | |||
| 134 | irka = current->request_key_auth->payload.data; | 167 | irka = current->request_key_auth->payload.data; |
| 135 | rka->context = irka->context; | 168 | rka->context = irka->context; |
| 136 | rka->pid = irka->pid; | 169 | rka->pid = irka->pid; |
| 170 | get_task_struct(rka->context); | ||
| 171 | |||
| 172 | up_read(¤t->request_key_auth->sem); | ||
| 137 | } | 173 | } |
| 138 | else { | 174 | else { |
| 139 | /* it isn't - use this process as the context */ | 175 | /* it isn't - use this process as the context */ |
| 140 | rka->context = current; | 176 | rka->context = current; |
| 141 | rka->pid = current->pid; | 177 | rka->pid = current->pid; |
| 178 | get_task_struct(rka->context); | ||
| 142 | } | 179 | } |
| 143 | 180 | ||
| 144 | rka->target_key = key_get(target); | 181 | rka->target_key = key_get(target); |
| @@ -148,7 +185,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
| 148 | sprintf(desc, "%x", target->serial); | 185 | sprintf(desc, "%x", target->serial); |
| 149 | 186 | ||
| 150 | authkey = key_alloc(&key_type_request_key_auth, desc, | 187 | authkey = key_alloc(&key_type_request_key_auth, desc, |
| 151 | current->fsuid, current->fsgid, | 188 | current->fsuid, current->fsgid, current, |
| 152 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | | 189 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | |
| 153 | KEY_USR_VIEW, 1); | 190 | KEY_USR_VIEW, 1); |
| 154 | if (IS_ERR(authkey)) { | 191 | if (IS_ERR(authkey)) { |
| @@ -161,9 +198,15 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
| 161 | if (ret < 0) | 198 | if (ret < 0) |
| 162 | goto error_inst; | 199 | goto error_inst; |
| 163 | 200 | ||
| 164 | kleave(" = {%d})", authkey->serial); | 201 | kleave(" = {%d}", authkey->serial); |
| 165 | return authkey; | 202 | return authkey; |
| 166 | 203 | ||
| 204 | auth_key_revoked: | ||
| 205 | up_read(¤t->request_key_auth->sem); | ||
| 206 | kfree(rka); | ||
| 207 | kleave("= -EKEYREVOKED"); | ||
| 208 | return ERR_PTR(-EKEYREVOKED); | ||
| 209 | |||
| 167 | error_inst: | 210 | error_inst: |
| 168 | key_revoke(authkey); | 211 | key_revoke(authkey); |
| 169 | key_put(authkey); | 212 | key_put(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_ */ |
