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.
Showing the changes to security (12 of 16 files). Show all
Unified · Split
| @@ -860,7 +860,7 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz · 859 unmodified lines | |||
| 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 | } |
| @@ -247,8 +247,8 @@ static inline void key_alloc_serial(struct key *key) · 246 unmodified lines | |||
| 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, · 63 unmodified lines | |||
| 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, · 497 unmodified lines | |||
| 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; |
| @@ -240,13 +240,14 @@ static long keyring_read(const struct key *keyring, · 239 unmodified lines | |||
| 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 | ||
| @@ -67,7 +67,8 @@ struct key root_session_keyring = { · 66 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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) · 50 unmodified lines | |||
| 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) · 27 unmodified lines | |||
| 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, · 33 unmodified lines | |||
| 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) · 493 unmodified lines | |||
| 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; |
| @@ -48,7 +48,8 @@ static int call_sbin_request_key(struct key *key, · 47 unmodified lines | |||
| 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, · 82 unmodified lines | |||
| 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 | ||
| @@ -148,7 +148,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) · 147 unmodified lines | |||
| 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)) { |
| @@ -4252,6 +4252,57 @@ static int selinux_setprocattr(struct task_struct *p, · 4251 unmodified lines | |||
| 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 = { · 148 unmodified lines | |||
| 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) · 29 unmodified lines | |||
| 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 | ||
| @@ -242,3 +242,9 @@ · 241 unmodified lines | |||
| 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") | ||
| @@ -959,3 +959,11 @@ · 958 unmodified lines | |||
| 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 | |||
| @@ -60,3 +60,4 @@ · 59 unmodified lines | |||
| 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") | ||
| @@ -62,6 +62,7 @@ · 61 unmodified lines | |||
| 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 |
| @@ -99,6 +99,11 @@ struct sk_security_struct { · 98 unmodified lines | |||
| 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_ */ |