diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/dummy.c | 52 | ||||
-rw-r--r-- | security/keys/keyctl.c | 11 | ||||
-rw-r--r-- | security/keys/keyring.c | 21 | ||||
-rw-r--r-- | security/keys/process_keys.c | 2 | ||||
-rw-r--r-- | security/keys/request_key.c | 2 | ||||
-rw-r--r-- | security/seclvl.c | 2 | ||||
-rw-r--r-- | security/selinux/avc.c | 8 | ||||
-rw-r--r-- | security/selinux/hooks.c | 189 | ||||
-rw-r--r-- | security/selinux/include/security.h | 5 | ||||
-rw-r--r-- | security/selinux/netlink.c | 6 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 3 | ||||
-rw-r--r-- | security/selinux/ss/avtab.c | 196 | ||||
-rw-r--r-- | security/selinux/ss/avtab.h | 37 | ||||
-rw-r--r-- | security/selinux/ss/conditional.c | 215 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.c | 5 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.h | 30 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 113 | ||||
-rw-r--r-- | security/selinux/ss/mls.h | 4 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 107 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 3 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 135 |
21 files changed, 650 insertions, 496 deletions
diff --git a/security/dummy.c b/security/dummy.c index 6ff887586479..9623a61dfc76 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -258,16 +258,16 @@ static void dummy_inode_free_security (struct inode *inode) | |||
258 | return; | 258 | return; |
259 | } | 259 | } |
260 | 260 | ||
261 | static int dummy_inode_create (struct inode *inode, struct dentry *dentry, | 261 | static int dummy_inode_init_security (struct inode *inode, struct inode *dir, |
262 | int mask) | 262 | char **name, void **value, size_t *len) |
263 | { | 263 | { |
264 | return 0; | 264 | return -EOPNOTSUPP; |
265 | } | 265 | } |
266 | 266 | ||
267 | static void dummy_inode_post_create (struct inode *inode, struct dentry *dentry, | 267 | static int dummy_inode_create (struct inode *inode, struct dentry *dentry, |
268 | int mask) | 268 | int mask) |
269 | { | 269 | { |
270 | return; | 270 | return 0; |
271 | } | 271 | } |
272 | 272 | ||
273 | static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode, | 273 | static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode, |
@@ -276,13 +276,6 @@ static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode, | |||
276 | return 0; | 276 | return 0; |
277 | } | 277 | } |
278 | 278 | ||
279 | static void dummy_inode_post_link (struct dentry *old_dentry, | ||
280 | struct inode *inode, | ||
281 | struct dentry *new_dentry) | ||
282 | { | ||
283 | return; | ||
284 | } | ||
285 | |||
286 | static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry) | 279 | static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry) |
287 | { | 280 | { |
288 | return 0; | 281 | return 0; |
@@ -294,24 +287,12 @@ static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry, | |||
294 | return 0; | 287 | return 0; |
295 | } | 288 | } |
296 | 289 | ||
297 | static void dummy_inode_post_symlink (struct inode *inode, | ||
298 | struct dentry *dentry, const char *name) | ||
299 | { | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry, | 290 | static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry, |
304 | int mask) | 291 | int mask) |
305 | { | 292 | { |
306 | return 0; | 293 | return 0; |
307 | } | 294 | } |
308 | 295 | ||
309 | static void dummy_inode_post_mkdir (struct inode *inode, struct dentry *dentry, | ||
310 | int mask) | ||
311 | { | ||
312 | return; | ||
313 | } | ||
314 | |||
315 | static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry) | 296 | static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry) |
316 | { | 297 | { |
317 | return 0; | 298 | return 0; |
@@ -323,12 +304,6 @@ static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry, | |||
323 | return 0; | 304 | return 0; |
324 | } | 305 | } |
325 | 306 | ||
326 | static void dummy_inode_post_mknod (struct inode *inode, struct dentry *dentry, | ||
327 | int mode, dev_t dev) | ||
328 | { | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | static int dummy_inode_rename (struct inode *old_inode, | 307 | static int dummy_inode_rename (struct inode *old_inode, |
333 | struct dentry *old_dentry, | 308 | struct dentry *old_dentry, |
334 | struct inode *new_inode, | 309 | struct inode *new_inode, |
@@ -337,14 +312,6 @@ static int dummy_inode_rename (struct inode *old_inode, | |||
337 | return 0; | 312 | return 0; |
338 | } | 313 | } |
339 | 314 | ||
340 | static void dummy_inode_post_rename (struct inode *old_inode, | ||
341 | struct dentry *old_dentry, | ||
342 | struct inode *new_inode, | ||
343 | struct dentry *new_dentry) | ||
344 | { | ||
345 | return; | ||
346 | } | ||
347 | |||
348 | static int dummy_inode_readlink (struct dentry *dentry) | 315 | static int dummy_inode_readlink (struct dentry *dentry) |
349 | { | 316 | { |
350 | return 0; | 317 | return 0; |
@@ -886,20 +853,15 @@ void security_fixup_ops (struct security_operations *ops) | |||
886 | set_to_dummy_if_null(ops, sb_post_pivotroot); | 853 | set_to_dummy_if_null(ops, sb_post_pivotroot); |
887 | set_to_dummy_if_null(ops, inode_alloc_security); | 854 | set_to_dummy_if_null(ops, inode_alloc_security); |
888 | set_to_dummy_if_null(ops, inode_free_security); | 855 | set_to_dummy_if_null(ops, inode_free_security); |
856 | set_to_dummy_if_null(ops, inode_init_security); | ||
889 | set_to_dummy_if_null(ops, inode_create); | 857 | set_to_dummy_if_null(ops, inode_create); |
890 | set_to_dummy_if_null(ops, inode_post_create); | ||
891 | set_to_dummy_if_null(ops, inode_link); | 858 | set_to_dummy_if_null(ops, inode_link); |
892 | set_to_dummy_if_null(ops, inode_post_link); | ||
893 | set_to_dummy_if_null(ops, inode_unlink); | 859 | set_to_dummy_if_null(ops, inode_unlink); |
894 | set_to_dummy_if_null(ops, inode_symlink); | 860 | set_to_dummy_if_null(ops, inode_symlink); |
895 | set_to_dummy_if_null(ops, inode_post_symlink); | ||
896 | set_to_dummy_if_null(ops, inode_mkdir); | 861 | set_to_dummy_if_null(ops, inode_mkdir); |
897 | set_to_dummy_if_null(ops, inode_post_mkdir); | ||
898 | set_to_dummy_if_null(ops, inode_rmdir); | 862 | set_to_dummy_if_null(ops, inode_rmdir); |
899 | set_to_dummy_if_null(ops, inode_mknod); | 863 | set_to_dummy_if_null(ops, inode_mknod); |
900 | set_to_dummy_if_null(ops, inode_post_mknod); | ||
901 | set_to_dummy_if_null(ops, inode_rename); | 864 | set_to_dummy_if_null(ops, inode_rename); |
902 | set_to_dummy_if_null(ops, inode_post_rename); | ||
903 | set_to_dummy_if_null(ops, inode_readlink); | 865 | set_to_dummy_if_null(ops, inode_readlink); |
904 | set_to_dummy_if_null(ops, inode_follow_link); | 866 | set_to_dummy_if_null(ops, inode_follow_link); |
905 | set_to_dummy_if_null(ops, inode_permission); | 867 | set_to_dummy_if_null(ops, inode_permission); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index fea262860ea0..a6516a64b297 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -49,9 +49,6 @@ 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; | 52 | ret = -EPERM; |
56 | if (type[0] == '.') | 53 | if (type[0] == '.') |
57 | goto error; | 54 | goto error; |
@@ -144,6 +141,10 @@ asmlinkage long sys_request_key(const char __user *_type, | |||
144 | goto error; | 141 | goto error; |
145 | type[31] = '\0'; | 142 | type[31] = '\0'; |
146 | 143 | ||
144 | ret = -EPERM; | ||
145 | if (type[0] == '.') | ||
146 | goto error; | ||
147 | |||
147 | /* pull the description into kernel space */ | 148 | /* pull the description into kernel space */ |
148 | ret = -EFAULT; | 149 | ret = -EFAULT; |
149 | dlen = strnlen_user(_description, PAGE_SIZE - 1); | 150 | dlen = strnlen_user(_description, PAGE_SIZE - 1); |
@@ -362,7 +363,7 @@ long keyctl_revoke_key(key_serial_t id) | |||
362 | 363 | ||
363 | key_put(key); | 364 | key_put(key); |
364 | error: | 365 | error: |
365 | return 0; | 366 | return ret; |
366 | 367 | ||
367 | } /* end keyctl_revoke_key() */ | 368 | } /* end keyctl_revoke_key() */ |
368 | 369 | ||
@@ -685,6 +686,8 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
685 | goto can_read_key2; | 686 | goto can_read_key2; |
686 | 687 | ||
687 | ret = PTR_ERR(skey); | 688 | ret = PTR_ERR(skey); |
689 | if (ret == -EAGAIN) | ||
690 | ret = -EACCES; | ||
688 | goto error2; | 691 | goto error2; |
689 | } | 692 | } |
690 | 693 | ||
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 90a551e4da66..9c208c756df8 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -129,7 +129,7 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
129 | int loop, ret; | 129 | int loop, ret; |
130 | 130 | ||
131 | const unsigned limit = | 131 | const unsigned limit = |
132 | (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key); | 132 | (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key *); |
133 | 133 | ||
134 | ret = 0; | 134 | ret = 0; |
135 | 135 | ||
@@ -150,7 +150,7 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
150 | max = limit; | 150 | max = limit; |
151 | 151 | ||
152 | ret = -ENOMEM; | 152 | ret = -ENOMEM; |
153 | size = sizeof(*klist) + sizeof(struct key) * max; | 153 | size = sizeof(*klist) + sizeof(struct key *) * max; |
154 | klist = kmalloc(size, GFP_KERNEL); | 154 | klist = kmalloc(size, GFP_KERNEL); |
155 | if (!klist) | 155 | if (!klist) |
156 | goto error; | 156 | goto error; |
@@ -163,7 +163,7 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
163 | klist->nkeys = sklist->nkeys; | 163 | klist->nkeys = sklist->nkeys; |
164 | memcpy(klist->keys, | 164 | memcpy(klist->keys, |
165 | sklist->keys, | 165 | sklist->keys, |
166 | sklist->nkeys * sizeof(struct key)); | 166 | sklist->nkeys * sizeof(struct key *)); |
167 | 167 | ||
168 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 168 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
169 | atomic_inc(&klist->keys[loop]->usage); | 169 | atomic_inc(&klist->keys[loop]->usage); |
@@ -201,7 +201,11 @@ static void keyring_destroy(struct key *keyring) | |||
201 | 201 | ||
202 | if (keyring->description) { | 202 | if (keyring->description) { |
203 | write_lock(&keyring_name_lock); | 203 | write_lock(&keyring_name_lock); |
204 | list_del(&keyring->type_data.link); | 204 | |
205 | if (keyring->type_data.link.next != NULL && | ||
206 | !list_empty(&keyring->type_data.link)) | ||
207 | list_del(&keyring->type_data.link); | ||
208 | |||
205 | write_unlock(&keyring_name_lock); | 209 | write_unlock(&keyring_name_lock); |
206 | } | 210 | } |
207 | 211 | ||
@@ -783,7 +787,7 @@ int __key_link(struct key *keyring, struct key *key) | |||
783 | ret = -ENFILE; | 787 | ret = -ENFILE; |
784 | if (max > 65535) | 788 | if (max > 65535) |
785 | goto error3; | 789 | goto error3; |
786 | size = sizeof(*klist) + sizeof(*key) * max; | 790 | size = sizeof(*klist) + sizeof(struct key *) * max; |
787 | if (size > PAGE_SIZE) | 791 | if (size > PAGE_SIZE) |
788 | goto error3; | 792 | goto error3; |
789 | 793 | ||
@@ -895,7 +899,8 @@ int key_unlink(struct key *keyring, struct key *key) | |||
895 | 899 | ||
896 | key_is_present: | 900 | key_is_present: |
897 | /* we need to copy the key list for RCU purposes */ | 901 | /* we need to copy the key list for RCU purposes */ |
898 | nklist = kmalloc(sizeof(*klist) + sizeof(*key) * klist->maxkeys, | 902 | nklist = kmalloc(sizeof(*klist) + |
903 | sizeof(struct key *) * klist->maxkeys, | ||
899 | GFP_KERNEL); | 904 | GFP_KERNEL); |
900 | if (!nklist) | 905 | if (!nklist) |
901 | goto nomem; | 906 | goto nomem; |
@@ -905,12 +910,12 @@ key_is_present: | |||
905 | if (loop > 0) | 910 | if (loop > 0) |
906 | memcpy(&nklist->keys[0], | 911 | memcpy(&nklist->keys[0], |
907 | &klist->keys[0], | 912 | &klist->keys[0], |
908 | loop * sizeof(klist->keys[0])); | 913 | loop * sizeof(struct key *)); |
909 | 914 | ||
910 | if (loop < nklist->nkeys) | 915 | if (loop < nklist->nkeys) |
911 | memcpy(&nklist->keys[loop], | 916 | memcpy(&nklist->keys[loop], |
912 | &klist->keys[loop + 1], | 917 | &klist->keys[loop + 1], |
913 | (nklist->nkeys - loop) * sizeof(klist->keys[0])); | 918 | (nklist->nkeys - loop) * sizeof(struct key *)); |
914 | 919 | ||
915 | /* adjust the user's quota */ | 920 | /* adjust the user's quota */ |
916 | key_payload_reserve(keyring, | 921 | key_payload_reserve(keyring, |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 9b0369c5a223..c089f78fb94e 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -678,7 +678,7 @@ long join_session_keyring(const char *name) | |||
678 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); | 678 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); |
679 | if (IS_ERR(keyring)) { | 679 | if (IS_ERR(keyring)) { |
680 | ret = PTR_ERR(keyring); | 680 | ret = PTR_ERR(keyring); |
681 | goto error; | 681 | goto error2; |
682 | } | 682 | } |
683 | } | 683 | } |
684 | else if (IS_ERR(keyring)) { | 684 | else if (IS_ERR(keyring)) { |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index dfcd983af1fd..90c1506d007c 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -405,7 +405,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
405 | key_user_put(user); | 405 | key_user_put(user); |
406 | 406 | ||
407 | /* link the new key into the appropriate keyring */ | 407 | /* link the new key into the appropriate keyring */ |
408 | if (!PTR_ERR(key)) | 408 | if (!IS_ERR(key)) |
409 | request_key_link(key, dest_keyring); | 409 | request_key_link(key, dest_keyring); |
410 | } | 410 | } |
411 | 411 | ||
diff --git a/security/seclvl.c b/security/seclvl.c index f8700e935b33..dc4e17b6eaf6 100644 --- a/security/seclvl.c +++ b/security/seclvl.c | |||
@@ -205,7 +205,7 @@ plaintext_to_sha1(unsigned char *hash, const char *plaintext, int len) | |||
205 | "bytes.\n", len, PAGE_SIZE); | 205 | "bytes.\n", len, PAGE_SIZE); |
206 | return -ENOMEM; | 206 | return -ENOMEM; |
207 | } | 207 | } |
208 | tfm = crypto_alloc_tfm("sha1", 0); | 208 | tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP); |
209 | if (tfm == NULL) { | 209 | if (tfm == NULL) { |
210 | seclvl_printk(0, KERN_ERR, | 210 | seclvl_printk(0, KERN_ERR, |
211 | "Failed to load transform for SHA1\n"); | 211 | "Failed to load transform for SHA1\n"); |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 451502467a9b..12e4fb72bf0f 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -242,7 +242,7 @@ void __init avc_init(void) | |||
242 | avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node), | 242 | avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node), |
243 | 0, SLAB_PANIC, NULL, NULL); | 243 | 0, SLAB_PANIC, NULL, NULL); |
244 | 244 | ||
245 | audit_log(current->audit_context, AUDIT_KERNEL, "AVC INITIALIZED\n"); | 245 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n"); |
246 | } | 246 | } |
247 | 247 | ||
248 | int avc_get_hash_stats(char *page) | 248 | int avc_get_hash_stats(char *page) |
@@ -490,7 +490,7 @@ out: | |||
490 | } | 490 | } |
491 | 491 | ||
492 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | 492 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, |
493 | struct in6_addr *addr, u16 port, | 493 | struct in6_addr *addr, __be16 port, |
494 | char *name1, char *name2) | 494 | char *name1, char *name2) |
495 | { | 495 | { |
496 | if (!ipv6_addr_any(addr)) | 496 | if (!ipv6_addr_any(addr)) |
@@ -501,7 +501,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | |||
501 | } | 501 | } |
502 | 502 | ||
503 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, | 503 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, |
504 | u16 port, char *name1, char *name2) | 504 | __be16 port, char *name1, char *name2) |
505 | { | 505 | { |
506 | if (addr) | 506 | if (addr) |
507 | audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); | 507 | audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); |
@@ -550,7 +550,7 @@ void avc_audit(u32 ssid, u32 tsid, | |||
550 | return; | 550 | return; |
551 | } | 551 | } |
552 | 552 | ||
553 | ab = audit_log_start(current->audit_context, AUDIT_AVC); | 553 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); |
554 | if (!ab) | 554 | if (!ab) |
555 | return; /* audit_panic has been called */ | 555 | return; /* audit_panic has been called */ |
556 | audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); | 556 | audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6be273851144..6e4937fe062b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -659,7 +659,7 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
659 | return SECCLASS_NETLINK_ROUTE_SOCKET; | 659 | return SECCLASS_NETLINK_ROUTE_SOCKET; |
660 | case NETLINK_FIREWALL: | 660 | case NETLINK_FIREWALL: |
661 | return SECCLASS_NETLINK_FIREWALL_SOCKET; | 661 | return SECCLASS_NETLINK_FIREWALL_SOCKET; |
662 | case NETLINK_TCPDIAG: | 662 | case NETLINK_INET_DIAG: |
663 | return SECCLASS_NETLINK_TCPDIAG_SOCKET; | 663 | return SECCLASS_NETLINK_TCPDIAG_SOCKET; |
664 | case NETLINK_NFLOG: | 664 | case NETLINK_NFLOG: |
665 | return SECCLASS_NETLINK_NFLOG_SOCKET; | 665 | return SECCLASS_NETLINK_NFLOG_SOCKET; |
@@ -826,7 +826,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
826 | sid = sbsec->def_sid; | 826 | sid = sbsec->def_sid; |
827 | rc = 0; | 827 | rc = 0; |
828 | } else { | 828 | } else { |
829 | rc = security_context_to_sid(context, rc, &sid); | 829 | rc = security_context_to_sid_default(context, rc, &sid, |
830 | sbsec->def_sid); | ||
830 | if (rc) { | 831 | if (rc) { |
831 | printk(KERN_WARNING "%s: context_to_sid(%s) " | 832 | printk(KERN_WARNING "%s: context_to_sid(%s) " |
832 | "returned %d for dev=%s ino=%ld\n", | 833 | "returned %d for dev=%s ino=%ld\n", |
@@ -1264,85 +1265,6 @@ static int inode_security_set_sid(struct inode *inode, u32 sid) | |||
1264 | return 0; | 1265 | return 0; |
1265 | } | 1266 | } |
1266 | 1267 | ||
1267 | /* Set the security attributes on a newly created file. */ | ||
1268 | static int post_create(struct inode *dir, | ||
1269 | struct dentry *dentry) | ||
1270 | { | ||
1271 | |||
1272 | struct task_security_struct *tsec; | ||
1273 | struct inode *inode; | ||
1274 | struct inode_security_struct *dsec; | ||
1275 | struct superblock_security_struct *sbsec; | ||
1276 | u32 newsid; | ||
1277 | char *context; | ||
1278 | unsigned int len; | ||
1279 | int rc; | ||
1280 | |||
1281 | tsec = current->security; | ||
1282 | dsec = dir->i_security; | ||
1283 | sbsec = dir->i_sb->s_security; | ||
1284 | |||
1285 | inode = dentry->d_inode; | ||
1286 | if (!inode) { | ||
1287 | /* Some file system types (e.g. NFS) may not instantiate | ||
1288 | a dentry for all create operations (e.g. symlink), | ||
1289 | so we have to check to see if the inode is non-NULL. */ | ||
1290 | printk(KERN_WARNING "post_create: no inode, dir (dev=%s, " | ||
1291 | "ino=%ld)\n", dir->i_sb->s_id, dir->i_ino); | ||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1295 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
1296 | newsid = tsec->create_sid; | ||
1297 | } else { | ||
1298 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
1299 | inode_mode_to_security_class(inode->i_mode), | ||
1300 | &newsid); | ||
1301 | if (rc) { | ||
1302 | printk(KERN_WARNING "post_create: " | ||
1303 | "security_transition_sid failed, rc=%d (dev=%s " | ||
1304 | "ino=%ld)\n", | ||
1305 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1306 | return rc; | ||
1307 | } | ||
1308 | } | ||
1309 | |||
1310 | rc = inode_security_set_sid(inode, newsid); | ||
1311 | if (rc) { | ||
1312 | printk(KERN_WARNING "post_create: inode_security_set_sid " | ||
1313 | "failed, rc=%d (dev=%s ino=%ld)\n", | ||
1314 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1315 | return rc; | ||
1316 | } | ||
1317 | |||
1318 | if (sbsec->behavior == SECURITY_FS_USE_XATTR && | ||
1319 | inode->i_op->setxattr) { | ||
1320 | /* Use extended attributes. */ | ||
1321 | rc = security_sid_to_context(newsid, &context, &len); | ||
1322 | if (rc) { | ||
1323 | printk(KERN_WARNING "post_create: sid_to_context " | ||
1324 | "failed, rc=%d (dev=%s ino=%ld)\n", | ||
1325 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1326 | return rc; | ||
1327 | } | ||
1328 | down(&inode->i_sem); | ||
1329 | rc = inode->i_op->setxattr(dentry, | ||
1330 | XATTR_NAME_SELINUX, | ||
1331 | context, len, 0); | ||
1332 | up(&inode->i_sem); | ||
1333 | kfree(context); | ||
1334 | if (rc < 0) { | ||
1335 | printk(KERN_WARNING "post_create: setxattr failed, " | ||
1336 | "rc=%d (dev=%s ino=%ld)\n", | ||
1337 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1338 | return rc; | ||
1339 | } | ||
1340 | } | ||
1341 | |||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | |||
1346 | /* Hook functions begin here. */ | 1268 | /* Hook functions begin here. */ |
1347 | 1269 | ||
1348 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) | 1270 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) |
@@ -1672,6 +1594,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1672 | struct avc_audit_data ad; | 1594 | struct avc_audit_data ad; |
1673 | struct file *file, *devnull = NULL; | 1595 | struct file *file, *devnull = NULL; |
1674 | struct tty_struct *tty = current->signal->tty; | 1596 | struct tty_struct *tty = current->signal->tty; |
1597 | struct fdtable *fdt; | ||
1675 | long j = -1; | 1598 | long j = -1; |
1676 | 1599 | ||
1677 | if (tty) { | 1600 | if (tty) { |
@@ -1705,9 +1628,10 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1705 | 1628 | ||
1706 | j++; | 1629 | j++; |
1707 | i = j * __NFDBITS; | 1630 | i = j * __NFDBITS; |
1708 | if (i >= files->max_fds || i >= files->max_fdset) | 1631 | fdt = files_fdtable(files); |
1632 | if (i >= fdt->max_fds || i >= fdt->max_fdset) | ||
1709 | break; | 1633 | break; |
1710 | set = files->open_fds->fds_bits[j]; | 1634 | set = fdt->open_fds->fds_bits[j]; |
1711 | if (!set) | 1635 | if (!set) |
1712 | continue; | 1636 | continue; |
1713 | spin_unlock(&files->file_lock); | 1637 | spin_unlock(&files->file_lock); |
@@ -1728,7 +1652,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1728 | continue; | 1652 | continue; |
1729 | } | 1653 | } |
1730 | if (devnull) { | 1654 | if (devnull) { |
1731 | atomic_inc(&devnull->f_count); | 1655 | rcuref_inc(&devnull->f_count); |
1732 | } else { | 1656 | } else { |
1733 | devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); | 1657 | devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); |
1734 | if (!devnull) { | 1658 | if (!devnull) { |
@@ -2017,14 +1941,64 @@ static void selinux_inode_free_security(struct inode *inode) | |||
2017 | inode_free_security(inode); | 1941 | inode_free_security(inode); |
2018 | } | 1942 | } |
2019 | 1943 | ||
2020 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) | 1944 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
1945 | char **name, void **value, | ||
1946 | size_t *len) | ||
2021 | { | 1947 | { |
2022 | return may_create(dir, dentry, SECCLASS_FILE); | 1948 | struct task_security_struct *tsec; |
1949 | struct inode_security_struct *dsec; | ||
1950 | struct superblock_security_struct *sbsec; | ||
1951 | struct inode_security_struct *isec; | ||
1952 | u32 newsid, clen; | ||
1953 | int rc; | ||
1954 | char *namep = NULL, *context; | ||
1955 | |||
1956 | tsec = current->security; | ||
1957 | dsec = dir->i_security; | ||
1958 | sbsec = dir->i_sb->s_security; | ||
1959 | isec = inode->i_security; | ||
1960 | |||
1961 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
1962 | newsid = tsec->create_sid; | ||
1963 | } else { | ||
1964 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
1965 | inode_mode_to_security_class(inode->i_mode), | ||
1966 | &newsid); | ||
1967 | if (rc) { | ||
1968 | printk(KERN_WARNING "%s: " | ||
1969 | "security_transition_sid failed, rc=%d (dev=%s " | ||
1970 | "ino=%ld)\n", | ||
1971 | __FUNCTION__, | ||
1972 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1973 | return rc; | ||
1974 | } | ||
1975 | } | ||
1976 | |||
1977 | inode_security_set_sid(inode, newsid); | ||
1978 | |||
1979 | if (name) { | ||
1980 | namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); | ||
1981 | if (!namep) | ||
1982 | return -ENOMEM; | ||
1983 | *name = namep; | ||
1984 | } | ||
1985 | |||
1986 | if (value && len) { | ||
1987 | rc = security_sid_to_context(newsid, &context, &clen); | ||
1988 | if (rc) { | ||
1989 | kfree(namep); | ||
1990 | return rc; | ||
1991 | } | ||
1992 | *value = context; | ||
1993 | *len = clen; | ||
1994 | } | ||
1995 | |||
1996 | return 0; | ||
2023 | } | 1997 | } |
2024 | 1998 | ||
2025 | static void selinux_inode_post_create(struct inode *dir, struct dentry *dentry, int mask) | 1999 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) |
2026 | { | 2000 | { |
2027 | post_create(dir, dentry); | 2001 | return may_create(dir, dentry, SECCLASS_FILE); |
2028 | } | 2002 | } |
2029 | 2003 | ||
2030 | static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) | 2004 | static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) |
@@ -2037,11 +2011,6 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru | |||
2037 | return may_link(dir, old_dentry, MAY_LINK); | 2011 | return may_link(dir, old_dentry, MAY_LINK); |
2038 | } | 2012 | } |
2039 | 2013 | ||
2040 | static void selinux_inode_post_link(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) | ||
2041 | { | ||
2042 | return; | ||
2043 | } | ||
2044 | |||
2045 | static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) | 2014 | static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) |
2046 | { | 2015 | { |
2047 | int rc; | 2016 | int rc; |
@@ -2057,21 +2026,11 @@ static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const | |||
2057 | return may_create(dir, dentry, SECCLASS_LNK_FILE); | 2026 | return may_create(dir, dentry, SECCLASS_LNK_FILE); |
2058 | } | 2027 | } |
2059 | 2028 | ||
2060 | static void selinux_inode_post_symlink(struct inode *dir, struct dentry *dentry, const char *name) | ||
2061 | { | ||
2062 | post_create(dir, dentry); | ||
2063 | } | ||
2064 | |||
2065 | static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) | 2029 | static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) |
2066 | { | 2030 | { |
2067 | return may_create(dir, dentry, SECCLASS_DIR); | 2031 | return may_create(dir, dentry, SECCLASS_DIR); |
2068 | } | 2032 | } |
2069 | 2033 | ||
2070 | static void selinux_inode_post_mkdir(struct inode *dir, struct dentry *dentry, int mask) | ||
2071 | { | ||
2072 | post_create(dir, dentry); | ||
2073 | } | ||
2074 | |||
2075 | static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) | 2034 | static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) |
2076 | { | 2035 | { |
2077 | return may_link(dir, dentry, MAY_RMDIR); | 2036 | return may_link(dir, dentry, MAY_RMDIR); |
@@ -2088,23 +2047,12 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod | |||
2088 | return may_create(dir, dentry, inode_mode_to_security_class(mode)); | 2047 | return may_create(dir, dentry, inode_mode_to_security_class(mode)); |
2089 | } | 2048 | } |
2090 | 2049 | ||
2091 | static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | ||
2092 | { | ||
2093 | post_create(dir, dentry); | ||
2094 | } | ||
2095 | |||
2096 | static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, | 2050 | static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, |
2097 | struct inode *new_inode, struct dentry *new_dentry) | 2051 | struct inode *new_inode, struct dentry *new_dentry) |
2098 | { | 2052 | { |
2099 | return may_rename(old_inode, old_dentry, new_inode, new_dentry); | 2053 | return may_rename(old_inode, old_dentry, new_inode, new_dentry); |
2100 | } | 2054 | } |
2101 | 2055 | ||
2102 | static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry, | ||
2103 | struct inode *new_inode, struct dentry *new_dentry) | ||
2104 | { | ||
2105 | return; | ||
2106 | } | ||
2107 | |||
2108 | static int selinux_inode_readlink(struct dentry *dentry) | 2056 | static int selinux_inode_readlink(struct dentry *dentry) |
2109 | { | 2057 | { |
2110 | return dentry_has_perm(current, NULL, dentry, FILE__READ); | 2058 | return dentry_has_perm(current, NULL, dentry, FILE__READ); |
@@ -3125,12 +3073,12 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3125 | 3073 | ||
3126 | if (sk->sk_family == PF_INET) { | 3074 | if (sk->sk_family == PF_INET) { |
3127 | addr4 = (struct sockaddr_in *)address; | 3075 | addr4 = (struct sockaddr_in *)address; |
3128 | if (addrlen != sizeof(struct sockaddr_in)) | 3076 | if (addrlen < sizeof(struct sockaddr_in)) |
3129 | return -EINVAL; | 3077 | return -EINVAL; |
3130 | snum = ntohs(addr4->sin_port); | 3078 | snum = ntohs(addr4->sin_port); |
3131 | } else { | 3079 | } else { |
3132 | addr6 = (struct sockaddr_in6 *)address; | 3080 | addr6 = (struct sockaddr_in6 *)address; |
3133 | if (addrlen != sizeof(struct sockaddr_in6)) | 3081 | if (addrlen < SIN6_LEN_RFC2133) |
3134 | return -EINVAL; | 3082 | return -EINVAL; |
3135 | snum = ntohs(addr6->sin6_port); | 3083 | snum = ntohs(addr6->sin6_port); |
3136 | } | 3084 | } |
@@ -3441,7 +3389,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
3441 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); | 3389 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); |
3442 | if (err) { | 3390 | if (err) { |
3443 | if (err == -EINVAL) { | 3391 | if (err == -EINVAL) { |
3444 | audit_log(current->audit_context, AUDIT_SELINUX_ERR, | 3392 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
3445 | "SELinux: unrecognized netlink message" | 3393 | "SELinux: unrecognized netlink message" |
3446 | " type=%hu for sclass=%hu\n", | 3394 | " type=%hu for sclass=%hu\n", |
3447 | nlh->nlmsg_type, isec->sclass); | 3395 | nlh->nlmsg_type, isec->sclass); |
@@ -4297,20 +4245,15 @@ static struct security_operations selinux_ops = { | |||
4297 | 4245 | ||
4298 | .inode_alloc_security = selinux_inode_alloc_security, | 4246 | .inode_alloc_security = selinux_inode_alloc_security, |
4299 | .inode_free_security = selinux_inode_free_security, | 4247 | .inode_free_security = selinux_inode_free_security, |
4248 | .inode_init_security = selinux_inode_init_security, | ||
4300 | .inode_create = selinux_inode_create, | 4249 | .inode_create = selinux_inode_create, |
4301 | .inode_post_create = selinux_inode_post_create, | ||
4302 | .inode_link = selinux_inode_link, | 4250 | .inode_link = selinux_inode_link, |
4303 | .inode_post_link = selinux_inode_post_link, | ||
4304 | .inode_unlink = selinux_inode_unlink, | 4251 | .inode_unlink = selinux_inode_unlink, |
4305 | .inode_symlink = selinux_inode_symlink, | 4252 | .inode_symlink = selinux_inode_symlink, |
4306 | .inode_post_symlink = selinux_inode_post_symlink, | ||
4307 | .inode_mkdir = selinux_inode_mkdir, | 4253 | .inode_mkdir = selinux_inode_mkdir, |
4308 | .inode_post_mkdir = selinux_inode_post_mkdir, | ||
4309 | .inode_rmdir = selinux_inode_rmdir, | 4254 | .inode_rmdir = selinux_inode_rmdir, |
4310 | .inode_mknod = selinux_inode_mknod, | 4255 | .inode_mknod = selinux_inode_mknod, |
4311 | .inode_post_mknod = selinux_inode_post_mknod, | ||
4312 | .inode_rename = selinux_inode_rename, | 4256 | .inode_rename = selinux_inode_rename, |
4313 | .inode_post_rename = selinux_inode_post_rename, | ||
4314 | .inode_readlink = selinux_inode_readlink, | 4257 | .inode_readlink = selinux_inode_readlink, |
4315 | .inode_follow_link = selinux_inode_follow_link, | 4258 | .inode_follow_link = selinux_inode_follow_link, |
4316 | .inode_permission = selinux_inode_permission, | 4259 | .inode_permission = selinux_inode_permission, |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index fa187c9a351d..5f016c98056f 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -23,10 +23,11 @@ | |||
23 | #define POLICYDB_VERSION_NLCLASS 18 | 23 | #define POLICYDB_VERSION_NLCLASS 18 |
24 | #define POLICYDB_VERSION_VALIDATETRANS 19 | 24 | #define POLICYDB_VERSION_VALIDATETRANS 19 |
25 | #define POLICYDB_VERSION_MLS 19 | 25 | #define POLICYDB_VERSION_MLS 19 |
26 | #define POLICYDB_VERSION_AVTAB 20 | ||
26 | 27 | ||
27 | /* Range of policy versions we understand*/ | 28 | /* Range of policy versions we understand*/ |
28 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 29 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
29 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS | 30 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB |
30 | 31 | ||
31 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM | 32 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM |
32 | extern int selinux_enabled; | 33 | extern int selinux_enabled; |
@@ -65,6 +66,8 @@ int security_sid_to_context(u32 sid, char **scontext, | |||
65 | int security_context_to_sid(char *scontext, u32 scontext_len, | 66 | int security_context_to_sid(char *scontext, u32 scontext_len, |
66 | u32 *out_sid); | 67 | u32 *out_sid); |
67 | 68 | ||
69 | int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *out_sid, u32 def_sid); | ||
70 | |||
68 | int security_get_user_sids(u32 callsid, char *username, | 71 | int security_get_user_sids(u32 callsid, char *username, |
69 | u32 **sids, u32 *nel); | 72 | u32 **sids, u32 *nel); |
70 | 73 | ||
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 18d08acafa78..e203883406dd 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c | |||
@@ -80,7 +80,8 @@ static void selnl_notify(int msgtype, void *data) | |||
80 | nlh = NLMSG_PUT(skb, 0, 0, msgtype, len); | 80 | nlh = NLMSG_PUT(skb, 0, 0, msgtype, len); |
81 | selnl_add_payload(nlh, len, msgtype, data); | 81 | selnl_add_payload(nlh, len, msgtype, data); |
82 | nlh->nlmsg_len = skb->tail - tmp; | 82 | nlh->nlmsg_len = skb->tail - tmp; |
83 | netlink_broadcast(selnl, skb, 0, SELNL_GRP_AVC, GFP_USER); | 83 | NETLINK_CB(skb).dst_group = SELNLGRP_AVC; |
84 | netlink_broadcast(selnl, skb, 0, SELNLGRP_AVC, GFP_USER); | ||
84 | out: | 85 | out: |
85 | return; | 86 | return; |
86 | 87 | ||
@@ -103,7 +104,8 @@ void selnl_notify_policyload(u32 seqno) | |||
103 | 104 | ||
104 | static int __init selnl_init(void) | 105 | static int __init selnl_init(void) |
105 | { | 106 | { |
106 | selnl = netlink_kernel_create(NETLINK_SELINUX, NULL); | 107 | selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL, |
108 | THIS_MODULE); | ||
107 | if (selnl == NULL) | 109 | if (selnl == NULL) |
108 | panic("SELinux: Cannot create netlink socket."); | 110 | panic("SELinux: Cannot create netlink socket."); |
109 | netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV); | 111 | netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV); |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 92b057becb4b..69b9329b2054 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <linux/if.h> | 17 | #include <linux/if.h> |
18 | #include <linux/netfilter_ipv4/ip_queue.h> | 18 | #include <linux/netfilter_ipv4/ip_queue.h> |
19 | #include <linux/tcp_diag.h> | 19 | #include <linux/inet_diag.h> |
20 | #include <linux/xfrm.h> | 20 | #include <linux/xfrm.h> |
21 | #include <linux/audit.h> | 21 | #include <linux/audit.h> |
22 | 22 | ||
@@ -76,6 +76,7 @@ static struct nlmsg_perm nlmsg_firewall_perms[] = | |||
76 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = | 76 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = |
77 | { | 77 | { |
78 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | 78 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, |
79 | { DCCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | static struct nlmsg_perm nlmsg_xfrm_perms[] = | 82 | static struct nlmsg_perm nlmsg_xfrm_perms[] = |
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index f238c034c44e..dde094feb20d 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c | |||
@@ -58,6 +58,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat | |||
58 | { | 58 | { |
59 | int hvalue; | 59 | int hvalue; |
60 | struct avtab_node *prev, *cur, *newnode; | 60 | struct avtab_node *prev, *cur, *newnode; |
61 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
61 | 62 | ||
62 | if (!h) | 63 | if (!h) |
63 | return -EINVAL; | 64 | return -EINVAL; |
@@ -69,7 +70,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat | |||
69 | if (key->source_type == cur->key.source_type && | 70 | if (key->source_type == cur->key.source_type && |
70 | key->target_type == cur->key.target_type && | 71 | key->target_type == cur->key.target_type && |
71 | key->target_class == cur->key.target_class && | 72 | key->target_class == cur->key.target_class && |
72 | (datum->specified & cur->datum.specified)) | 73 | (specified & cur->key.specified)) |
73 | return -EEXIST; | 74 | return -EEXIST; |
74 | if (key->source_type < cur->key.source_type) | 75 | if (key->source_type < cur->key.source_type) |
75 | break; | 76 | break; |
@@ -98,6 +99,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da | |||
98 | { | 99 | { |
99 | int hvalue; | 100 | int hvalue; |
100 | struct avtab_node *prev, *cur, *newnode; | 101 | struct avtab_node *prev, *cur, *newnode; |
102 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
101 | 103 | ||
102 | if (!h) | 104 | if (!h) |
103 | return NULL; | 105 | return NULL; |
@@ -108,7 +110,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da | |||
108 | if (key->source_type == cur->key.source_type && | 110 | if (key->source_type == cur->key.source_type && |
109 | key->target_type == cur->key.target_type && | 111 | key->target_type == cur->key.target_type && |
110 | key->target_class == cur->key.target_class && | 112 | key->target_class == cur->key.target_class && |
111 | (datum->specified & cur->datum.specified)) | 113 | (specified & cur->key.specified)) |
112 | break; | 114 | break; |
113 | if (key->source_type < cur->key.source_type) | 115 | if (key->source_type < cur->key.source_type) |
114 | break; | 116 | break; |
@@ -125,10 +127,11 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da | |||
125 | return newnode; | 127 | return newnode; |
126 | } | 128 | } |
127 | 129 | ||
128 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified) | 130 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) |
129 | { | 131 | { |
130 | int hvalue; | 132 | int hvalue; |
131 | struct avtab_node *cur; | 133 | struct avtab_node *cur; |
134 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
132 | 135 | ||
133 | if (!h) | 136 | if (!h) |
134 | return NULL; | 137 | return NULL; |
@@ -138,7 +141,7 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe | |||
138 | if (key->source_type == cur->key.source_type && | 141 | if (key->source_type == cur->key.source_type && |
139 | key->target_type == cur->key.target_type && | 142 | key->target_type == cur->key.target_type && |
140 | key->target_class == cur->key.target_class && | 143 | key->target_class == cur->key.target_class && |
141 | (specified & cur->datum.specified)) | 144 | (specified & cur->key.specified)) |
142 | return &cur->datum; | 145 | return &cur->datum; |
143 | 146 | ||
144 | if (key->source_type < cur->key.source_type) | 147 | if (key->source_type < cur->key.source_type) |
@@ -159,10 +162,11 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe | |||
159 | * conjunction with avtab_search_next_node() | 162 | * conjunction with avtab_search_next_node() |
160 | */ | 163 | */ |
161 | struct avtab_node* | 164 | struct avtab_node* |
162 | avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) | 165 | avtab_search_node(struct avtab *h, struct avtab_key *key) |
163 | { | 166 | { |
164 | int hvalue; | 167 | int hvalue; |
165 | struct avtab_node *cur; | 168 | struct avtab_node *cur; |
169 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
166 | 170 | ||
167 | if (!h) | 171 | if (!h) |
168 | return NULL; | 172 | return NULL; |
@@ -172,7 +176,7 @@ avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) | |||
172 | if (key->source_type == cur->key.source_type && | 176 | if (key->source_type == cur->key.source_type && |
173 | key->target_type == cur->key.target_type && | 177 | key->target_type == cur->key.target_type && |
174 | key->target_class == cur->key.target_class && | 178 | key->target_class == cur->key.target_class && |
175 | (specified & cur->datum.specified)) | 179 | (specified & cur->key.specified)) |
176 | return cur; | 180 | return cur; |
177 | 181 | ||
178 | if (key->source_type < cur->key.source_type) | 182 | if (key->source_type < cur->key.source_type) |
@@ -196,11 +200,12 @@ avtab_search_node_next(struct avtab_node *node, int specified) | |||
196 | if (!node) | 200 | if (!node) |
197 | return NULL; | 201 | return NULL; |
198 | 202 | ||
203 | specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
199 | for (cur = node->next; cur; cur = cur->next) { | 204 | for (cur = node->next; cur; cur = cur->next) { |
200 | if (node->key.source_type == cur->key.source_type && | 205 | if (node->key.source_type == cur->key.source_type && |
201 | node->key.target_type == cur->key.target_type && | 206 | node->key.target_type == cur->key.target_type && |
202 | node->key.target_class == cur->key.target_class && | 207 | node->key.target_class == cur->key.target_class && |
203 | (specified & cur->datum.specified)) | 208 | (specified & cur->key.specified)) |
204 | return cur; | 209 | return cur; |
205 | 210 | ||
206 | if (node->key.source_type < cur->key.source_type) | 211 | if (node->key.source_type < cur->key.source_type) |
@@ -278,76 +283,129 @@ void avtab_hash_eval(struct avtab *h, char *tag) | |||
278 | max_chain_len); | 283 | max_chain_len); |
279 | } | 284 | } |
280 | 285 | ||
281 | int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) | 286 | static uint16_t spec_order[] = { |
287 | AVTAB_ALLOWED, | ||
288 | AVTAB_AUDITDENY, | ||
289 | AVTAB_AUDITALLOW, | ||
290 | AVTAB_TRANSITION, | ||
291 | AVTAB_CHANGE, | ||
292 | AVTAB_MEMBER | ||
293 | }; | ||
294 | |||
295 | int avtab_read_item(void *fp, u32 vers, struct avtab *a, | ||
296 | int (*insertf)(struct avtab *a, struct avtab_key *k, | ||
297 | struct avtab_datum *d, void *p), | ||
298 | void *p) | ||
282 | { | 299 | { |
283 | u32 buf[7]; | 300 | __le16 buf16[4]; |
284 | u32 items, items2; | 301 | u16 enabled; |
285 | int rc; | 302 | __le32 buf32[7]; |
303 | u32 items, items2, val; | ||
304 | struct avtab_key key; | ||
305 | struct avtab_datum datum; | ||
306 | int i, rc; | ||
307 | |||
308 | memset(&key, 0, sizeof(struct avtab_key)); | ||
309 | memset(&datum, 0, sizeof(struct avtab_datum)); | ||
310 | |||
311 | if (vers < POLICYDB_VERSION_AVTAB) { | ||
312 | rc = next_entry(buf32, fp, sizeof(u32)); | ||
313 | if (rc < 0) { | ||
314 | printk(KERN_ERR "security: avtab: truncated entry\n"); | ||
315 | return -1; | ||
316 | } | ||
317 | items2 = le32_to_cpu(buf32[0]); | ||
318 | if (items2 > ARRAY_SIZE(buf32)) { | ||
319 | printk(KERN_ERR "security: avtab: entry overflow\n"); | ||
320 | return -1; | ||
286 | 321 | ||
287 | memset(avkey, 0, sizeof(struct avtab_key)); | 322 | } |
288 | memset(avdatum, 0, sizeof(struct avtab_datum)); | 323 | rc = next_entry(buf32, fp, sizeof(u32)*items2); |
324 | if (rc < 0) { | ||
325 | printk(KERN_ERR "security: avtab: truncated entry\n"); | ||
326 | return -1; | ||
327 | } | ||
328 | items = 0; | ||
289 | 329 | ||
290 | rc = next_entry(buf, fp, sizeof(u32)); | 330 | val = le32_to_cpu(buf32[items++]); |
291 | if (rc < 0) { | 331 | key.source_type = (u16)val; |
292 | printk(KERN_ERR "security: avtab: truncated entry\n"); | 332 | if (key.source_type != val) { |
293 | goto bad; | 333 | printk("security: avtab: truncated source type\n"); |
294 | } | 334 | return -1; |
295 | items2 = le32_to_cpu(buf[0]); | 335 | } |
296 | if (items2 > ARRAY_SIZE(buf)) { | 336 | val = le32_to_cpu(buf32[items++]); |
297 | printk(KERN_ERR "security: avtab: entry overflow\n"); | 337 | key.target_type = (u16)val; |
298 | goto bad; | 338 | if (key.target_type != val) { |
339 | printk("security: avtab: truncated target type\n"); | ||
340 | return -1; | ||
341 | } | ||
342 | val = le32_to_cpu(buf32[items++]); | ||
343 | key.target_class = (u16)val; | ||
344 | if (key.target_class != val) { | ||
345 | printk("security: avtab: truncated target class\n"); | ||
346 | return -1; | ||
347 | } | ||
348 | |||
349 | val = le32_to_cpu(buf32[items++]); | ||
350 | enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; | ||
351 | |||
352 | if (!(val & (AVTAB_AV | AVTAB_TYPE))) { | ||
353 | printk("security: avtab: null entry\n"); | ||
354 | return -1; | ||
355 | } | ||
356 | if ((val & AVTAB_AV) && | ||
357 | (val & AVTAB_TYPE)) { | ||
358 | printk("security: avtab: entry has both access vectors and types\n"); | ||
359 | return -1; | ||
360 | } | ||
361 | |||
362 | for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) { | ||
363 | if (val & spec_order[i]) { | ||
364 | key.specified = spec_order[i] | enabled; | ||
365 | datum.data = le32_to_cpu(buf32[items++]); | ||
366 | rc = insertf(a, &key, &datum, p); | ||
367 | if (rc) return rc; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | if (items != items2) { | ||
372 | printk("security: avtab: entry only had %d items, expected %d\n", items2, items); | ||
373 | return -1; | ||
374 | } | ||
375 | return 0; | ||
299 | } | 376 | } |
300 | rc = next_entry(buf, fp, sizeof(u32)*items2); | 377 | |
378 | rc = next_entry(buf16, fp, sizeof(u16)*4); | ||
301 | if (rc < 0) { | 379 | if (rc < 0) { |
302 | printk(KERN_ERR "security: avtab: truncated entry\n"); | 380 | printk("security: avtab: truncated entry\n"); |
303 | goto bad; | 381 | return -1; |
304 | } | 382 | } |
383 | |||
305 | items = 0; | 384 | items = 0; |
306 | avkey->source_type = le32_to_cpu(buf[items++]); | 385 | key.source_type = le16_to_cpu(buf16[items++]); |
307 | avkey->target_type = le32_to_cpu(buf[items++]); | 386 | key.target_type = le16_to_cpu(buf16[items++]); |
308 | avkey->target_class = le32_to_cpu(buf[items++]); | 387 | key.target_class = le16_to_cpu(buf16[items++]); |
309 | avdatum->specified = le32_to_cpu(buf[items++]); | 388 | key.specified = le16_to_cpu(buf16[items++]); |
310 | if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) { | 389 | |
311 | printk(KERN_ERR "security: avtab: null entry\n"); | 390 | rc = next_entry(buf32, fp, sizeof(u32)); |
312 | goto bad; | 391 | if (rc < 0) { |
313 | } | 392 | printk("security: avtab: truncated entry\n"); |
314 | if ((avdatum->specified & AVTAB_AV) && | 393 | return -1; |
315 | (avdatum->specified & AVTAB_TYPE)) { | ||
316 | printk(KERN_ERR "security: avtab: entry has both access vectors and types\n"); | ||
317 | goto bad; | ||
318 | } | ||
319 | if (avdatum->specified & AVTAB_AV) { | ||
320 | if (avdatum->specified & AVTAB_ALLOWED) | ||
321 | avtab_allowed(avdatum) = le32_to_cpu(buf[items++]); | ||
322 | if (avdatum->specified & AVTAB_AUDITDENY) | ||
323 | avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]); | ||
324 | if (avdatum->specified & AVTAB_AUDITALLOW) | ||
325 | avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]); | ||
326 | } else { | ||
327 | if (avdatum->specified & AVTAB_TRANSITION) | ||
328 | avtab_transition(avdatum) = le32_to_cpu(buf[items++]); | ||
329 | if (avdatum->specified & AVTAB_CHANGE) | ||
330 | avtab_change(avdatum) = le32_to_cpu(buf[items++]); | ||
331 | if (avdatum->specified & AVTAB_MEMBER) | ||
332 | avtab_member(avdatum) = le32_to_cpu(buf[items++]); | ||
333 | } | ||
334 | if (items != items2) { | ||
335 | printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n", | ||
336 | items2, items); | ||
337 | goto bad; | ||
338 | } | 394 | } |
395 | datum.data = le32_to_cpu(*buf32); | ||
396 | return insertf(a, &key, &datum, p); | ||
397 | } | ||
339 | 398 | ||
340 | return 0; | 399 | static int avtab_insertf(struct avtab *a, struct avtab_key *k, |
341 | bad: | 400 | struct avtab_datum *d, void *p) |
342 | return -1; | 401 | { |
402 | return avtab_insert(a, k, d); | ||
343 | } | 403 | } |
344 | 404 | ||
345 | int avtab_read(struct avtab *a, void *fp, u32 config) | 405 | int avtab_read(struct avtab *a, void *fp, u32 vers) |
346 | { | 406 | { |
347 | int rc; | 407 | int rc; |
348 | struct avtab_key avkey; | 408 | __le32 buf[1]; |
349 | struct avtab_datum avdatum; | ||
350 | u32 buf[1]; | ||
351 | u32 nel, i; | 409 | u32 nel, i; |
352 | 410 | ||
353 | 411 | ||
@@ -363,16 +421,14 @@ int avtab_read(struct avtab *a, void *fp, u32 config) | |||
363 | goto bad; | 421 | goto bad; |
364 | } | 422 | } |
365 | for (i = 0; i < nel; i++) { | 423 | for (i = 0; i < nel; i++) { |
366 | if (avtab_read_item(fp, &avdatum, &avkey)) { | 424 | rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL); |
367 | rc = -EINVAL; | ||
368 | goto bad; | ||
369 | } | ||
370 | rc = avtab_insert(a, &avkey, &avdatum); | ||
371 | if (rc) { | 425 | if (rc) { |
372 | if (rc == -ENOMEM) | 426 | if (rc == -ENOMEM) |
373 | printk(KERN_ERR "security: avtab: out of memory\n"); | 427 | printk(KERN_ERR "security: avtab: out of memory\n"); |
374 | if (rc == -EEXIST) | 428 | else if (rc == -EEXIST) |
375 | printk(KERN_ERR "security: avtab: duplicate entry\n"); | 429 | printk(KERN_ERR "security: avtab: duplicate entry\n"); |
430 | else | ||
431 | rc = -EINVAL; | ||
376 | goto bad; | 432 | goto bad; |
377 | } | 433 | } |
378 | } | 434 | } |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 519d4f6dc655..0a90d939af93 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
@@ -21,12 +21,9 @@ | |||
21 | #define _SS_AVTAB_H_ | 21 | #define _SS_AVTAB_H_ |
22 | 22 | ||
23 | struct avtab_key { | 23 | struct avtab_key { |
24 | u32 source_type; /* source type */ | 24 | u16 source_type; /* source type */ |
25 | u32 target_type; /* target type */ | 25 | u16 target_type; /* target type */ |
26 | u32 target_class; /* target object class */ | 26 | u16 target_class; /* target object class */ |
27 | }; | ||
28 | |||
29 | struct avtab_datum { | ||
30 | #define AVTAB_ALLOWED 1 | 27 | #define AVTAB_ALLOWED 1 |
31 | #define AVTAB_AUDITALLOW 2 | 28 | #define AVTAB_AUDITALLOW 2 |
32 | #define AVTAB_AUDITDENY 4 | 29 | #define AVTAB_AUDITDENY 4 |
@@ -35,15 +32,13 @@ struct avtab_datum { | |||
35 | #define AVTAB_MEMBER 32 | 32 | #define AVTAB_MEMBER 32 |
36 | #define AVTAB_CHANGE 64 | 33 | #define AVTAB_CHANGE 64 |
37 | #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) | 34 | #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) |
38 | #define AVTAB_ENABLED 0x80000000 /* reserved for used in cond_avtab */ | 35 | #define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ |
39 | u32 specified; /* what fields are specified */ | 36 | #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ |
40 | u32 data[3]; /* access vectors or types */ | 37 | u16 specified; /* what field is specified */ |
41 | #define avtab_allowed(x) (x)->data[0] | 38 | }; |
42 | #define avtab_auditdeny(x) (x)->data[1] | 39 | |
43 | #define avtab_auditallow(x) (x)->data[2] | 40 | struct avtab_datum { |
44 | #define avtab_transition(x) (x)->data[0] | 41 | u32 data; /* access vector or type value */ |
45 | #define avtab_change(x) (x)->data[1] | ||
46 | #define avtab_member(x) (x)->data[2] | ||
47 | }; | 42 | }; |
48 | 43 | ||
49 | struct avtab_node { | 44 | struct avtab_node { |
@@ -58,17 +53,21 @@ struct avtab { | |||
58 | }; | 53 | }; |
59 | 54 | ||
60 | int avtab_init(struct avtab *); | 55 | int avtab_init(struct avtab *); |
61 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified); | 56 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k); |
62 | void avtab_destroy(struct avtab *h); | 57 | void avtab_destroy(struct avtab *h); |
63 | void avtab_hash_eval(struct avtab *h, char *tag); | 58 | void avtab_hash_eval(struct avtab *h, char *tag); |
64 | 59 | ||
65 | int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey); | 60 | int avtab_read_item(void *fp, uint32_t vers, struct avtab *a, |
66 | int avtab_read(struct avtab *a, void *fp, u32 config); | 61 | int (*insert)(struct avtab *a, struct avtab_key *k, |
62 | struct avtab_datum *d, void *p), | ||
63 | void *p); | ||
64 | |||
65 | int avtab_read(struct avtab *a, void *fp, u32 vers); | ||
67 | 66 | ||
68 | struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, | 67 | struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, |
69 | struct avtab_datum *datum); | 68 | struct avtab_datum *datum); |
70 | 69 | ||
71 | struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified); | 70 | struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key); |
72 | 71 | ||
73 | struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); | 72 | struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); |
74 | 73 | ||
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index e2057f5a411a..daf288007460 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c | |||
@@ -100,18 +100,18 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) | |||
100 | /* turn the rules on or off */ | 100 | /* turn the rules on or off */ |
101 | for (cur = node->true_list; cur != NULL; cur = cur->next) { | 101 | for (cur = node->true_list; cur != NULL; cur = cur->next) { |
102 | if (new_state <= 0) { | 102 | if (new_state <= 0) { |
103 | cur->node->datum.specified &= ~AVTAB_ENABLED; | 103 | cur->node->key.specified &= ~AVTAB_ENABLED; |
104 | } else { | 104 | } else { |
105 | cur->node->datum.specified |= AVTAB_ENABLED; | 105 | cur->node->key.specified |= AVTAB_ENABLED; |
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | for (cur = node->false_list; cur != NULL; cur = cur->next) { | 109 | for (cur = node->false_list; cur != NULL; cur = cur->next) { |
110 | /* -1 or 1 */ | 110 | /* -1 or 1 */ |
111 | if (new_state) { | 111 | if (new_state) { |
112 | cur->node->datum.specified &= ~AVTAB_ENABLED; | 112 | cur->node->key.specified &= ~AVTAB_ENABLED; |
113 | } else { | 113 | } else { |
114 | cur->node->datum.specified |= AVTAB_ENABLED; | 114 | cur->node->key.specified |= AVTAB_ENABLED; |
115 | } | 115 | } |
116 | } | 116 | } |
117 | } | 117 | } |
@@ -216,7 +216,8 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) | |||
216 | { | 216 | { |
217 | char *key = NULL; | 217 | char *key = NULL; |
218 | struct cond_bool_datum *booldatum; | 218 | struct cond_bool_datum *booldatum; |
219 | u32 buf[3], len; | 219 | __le32 buf[3]; |
220 | u32 len; | ||
220 | int rc; | 221 | int rc; |
221 | 222 | ||
222 | booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); | 223 | booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); |
@@ -252,104 +253,127 @@ err: | |||
252 | return -1; | 253 | return -1; |
253 | } | 254 | } |
254 | 255 | ||
255 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, | 256 | struct cond_insertf_data |
256 | struct cond_av_list *other) | ||
257 | { | 257 | { |
258 | struct cond_av_list *list, *last = NULL, *cur; | 258 | struct policydb *p; |
259 | struct avtab_key key; | 259 | struct cond_av_list *other; |
260 | struct avtab_datum datum; | 260 | struct cond_av_list *head; |
261 | struct cond_av_list *tail; | ||
262 | }; | ||
263 | |||
264 | static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr) | ||
265 | { | ||
266 | struct cond_insertf_data *data = ptr; | ||
267 | struct policydb *p = data->p; | ||
268 | struct cond_av_list *other = data->other, *list, *cur; | ||
261 | struct avtab_node *node_ptr; | 269 | struct avtab_node *node_ptr; |
262 | int rc; | ||
263 | u32 buf[1], i, len; | ||
264 | u8 found; | 270 | u8 found; |
265 | 271 | ||
266 | *ret_list = NULL; | ||
267 | |||
268 | len = 0; | ||
269 | rc = next_entry(buf, fp, sizeof buf); | ||
270 | if (rc < 0) | ||
271 | return -1; | ||
272 | |||
273 | len = le32_to_cpu(buf[0]); | ||
274 | if (len == 0) { | ||
275 | return 0; | ||
276 | } | ||
277 | 272 | ||
278 | for (i = 0; i < len; i++) { | 273 | /* |
279 | if (avtab_read_item(fp, &datum, &key)) | 274 | * For type rules we have to make certain there aren't any |
275 | * conflicting rules by searching the te_avtab and the | ||
276 | * cond_te_avtab. | ||
277 | */ | ||
278 | if (k->specified & AVTAB_TYPE) { | ||
279 | if (avtab_search(&p->te_avtab, k)) { | ||
280 | printk("security: type rule already exists outside of a conditional."); | ||
280 | goto err; | 281 | goto err; |
281 | 282 | } | |
282 | /* | 283 | /* |
283 | * For type rules we have to make certain there aren't any | 284 | * If we are reading the false list other will be a pointer to |
284 | * conflicting rules by searching the te_avtab and the | 285 | * the true list. We can have duplicate entries if there is only |
285 | * cond_te_avtab. | 286 | * 1 other entry and it is in our true list. |
287 | * | ||
288 | * If we are reading the true list (other == NULL) there shouldn't | ||
289 | * be any other entries. | ||
286 | */ | 290 | */ |
287 | if (datum.specified & AVTAB_TYPE) { | 291 | if (other) { |
288 | if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) { | 292 | node_ptr = avtab_search_node(&p->te_cond_avtab, k); |
289 | printk("security: type rule already exists outside of a conditional."); | 293 | if (node_ptr) { |
290 | goto err; | 294 | if (avtab_search_node_next(node_ptr, k->specified)) { |
291 | } | 295 | printk("security: too many conflicting type rules."); |
292 | /* | 296 | goto err; |
293 | * If we are reading the false list other will be a pointer to | 297 | } |
294 | * the true list. We can have duplicate entries if there is only | 298 | found = 0; |
295 | * 1 other entry and it is in our true list. | 299 | for (cur = other; cur != NULL; cur = cur->next) { |
296 | * | 300 | if (cur->node == node_ptr) { |
297 | * If we are reading the true list (other == NULL) there shouldn't | 301 | found = 1; |
298 | * be any other entries. | 302 | break; |
299 | */ | ||
300 | if (other) { | ||
301 | node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE); | ||
302 | if (node_ptr) { | ||
303 | if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) { | ||
304 | printk("security: too many conflicting type rules."); | ||
305 | goto err; | ||
306 | } | ||
307 | found = 0; | ||
308 | for (cur = other; cur != NULL; cur = cur->next) { | ||
309 | if (cur->node == node_ptr) { | ||
310 | found = 1; | ||
311 | break; | ||
312 | } | ||
313 | } | ||
314 | if (!found) { | ||
315 | printk("security: conflicting type rules."); | ||
316 | goto err; | ||
317 | } | 303 | } |
318 | } | 304 | } |
319 | } else { | 305 | if (!found) { |
320 | if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) { | 306 | printk("security: conflicting type rules.\n"); |
321 | printk("security: conflicting type rules when adding type rule for true."); | ||
322 | goto err; | 307 | goto err; |
323 | } | 308 | } |
324 | } | 309 | } |
310 | } else { | ||
311 | if (avtab_search(&p->te_cond_avtab, k)) { | ||
312 | printk("security: conflicting type rules when adding type rule for true.\n"); | ||
313 | goto err; | ||
314 | } | ||
325 | } | 315 | } |
326 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum); | 316 | } |
327 | if (!node_ptr) { | ||
328 | printk("security: could not insert rule."); | ||
329 | goto err; | ||
330 | } | ||
331 | |||
332 | list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); | ||
333 | if (!list) | ||
334 | goto err; | ||
335 | memset(list, 0, sizeof(struct cond_av_list)); | ||
336 | |||
337 | list->node = node_ptr; | ||
338 | if (i == 0) | ||
339 | *ret_list = list; | ||
340 | else | ||
341 | last->next = list; | ||
342 | last = list; | ||
343 | 317 | ||
318 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); | ||
319 | if (!node_ptr) { | ||
320 | printk("security: could not insert rule."); | ||
321 | goto err; | ||
344 | } | 322 | } |
345 | 323 | ||
324 | list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); | ||
325 | if (!list) | ||
326 | goto err; | ||
327 | memset(list, 0, sizeof(*list)); | ||
328 | |||
329 | list->node = node_ptr; | ||
330 | if (!data->head) | ||
331 | data->head = list; | ||
332 | else | ||
333 | data->tail->next = list; | ||
334 | data->tail = list; | ||
346 | return 0; | 335 | return 0; |
336 | |||
347 | err: | 337 | err: |
348 | cond_av_list_destroy(*ret_list); | 338 | cond_av_list_destroy(data->head); |
349 | *ret_list = NULL; | 339 | data->head = NULL; |
350 | return -1; | 340 | return -1; |
351 | } | 341 | } |
352 | 342 | ||
343 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) | ||
344 | { | ||
345 | int i, rc; | ||
346 | __le32 buf[1]; | ||
347 | u32 len; | ||
348 | struct cond_insertf_data data; | ||
349 | |||
350 | *ret_list = NULL; | ||
351 | |||
352 | len = 0; | ||
353 | rc = next_entry(buf, fp, sizeof(u32)); | ||
354 | if (rc < 0) | ||
355 | return -1; | ||
356 | |||
357 | len = le32_to_cpu(buf[0]); | ||
358 | if (len == 0) { | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | data.p = p; | ||
363 | data.other = other; | ||
364 | data.head = NULL; | ||
365 | data.tail = NULL; | ||
366 | for (i = 0; i < len; i++) { | ||
367 | rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); | ||
368 | if (rc) | ||
369 | return rc; | ||
370 | |||
371 | } | ||
372 | |||
373 | *ret_list = data.head; | ||
374 | return 0; | ||
375 | } | ||
376 | |||
353 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | 377 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) |
354 | { | 378 | { |
355 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { | 379 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { |
@@ -366,7 +390,8 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | |||
366 | 390 | ||
367 | static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | 391 | static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) |
368 | { | 392 | { |
369 | u32 buf[2], len, i; | 393 | __le32 buf[2]; |
394 | u32 len, i; | ||
370 | int rc; | 395 | int rc; |
371 | struct cond_expr *expr = NULL, *last = NULL; | 396 | struct cond_expr *expr = NULL, *last = NULL; |
372 | 397 | ||
@@ -424,7 +449,8 @@ err: | |||
424 | int cond_read_list(struct policydb *p, void *fp) | 449 | int cond_read_list(struct policydb *p, void *fp) |
425 | { | 450 | { |
426 | struct cond_node *node, *last = NULL; | 451 | struct cond_node *node, *last = NULL; |
427 | u32 buf[1], i, len; | 452 | __le32 buf[1]; |
453 | u32 i, len; | ||
428 | int rc; | 454 | int rc; |
429 | 455 | ||
430 | rc = next_entry(buf, fp, sizeof buf); | 456 | rc = next_entry(buf, fp, sizeof buf); |
@@ -452,6 +478,7 @@ int cond_read_list(struct policydb *p, void *fp) | |||
452 | return 0; | 478 | return 0; |
453 | err: | 479 | err: |
454 | cond_list_destroy(p->cond_list); | 480 | cond_list_destroy(p->cond_list); |
481 | p->cond_list = NULL; | ||
455 | return -1; | 482 | return -1; |
456 | } | 483 | } |
457 | 484 | ||
@@ -465,22 +492,22 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi | |||
465 | if(!ctab || !key || !avd) | 492 | if(!ctab || !key || !avd) |
466 | return; | 493 | return; |
467 | 494 | ||
468 | for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL; | 495 | for(node = avtab_search_node(ctab, key); node != NULL; |
469 | node = avtab_search_node_next(node, AVTAB_AV)) { | 496 | node = avtab_search_node_next(node, key->specified)) { |
470 | if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) == | 497 | if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) == |
471 | (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) | 498 | (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) |
472 | avd->allowed |= avtab_allowed(&node->datum); | 499 | avd->allowed |= node->datum.data; |
473 | if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) == | 500 | if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) == |
474 | (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) | 501 | (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) |
475 | /* Since a '0' in an auditdeny mask represents a | 502 | /* Since a '0' in an auditdeny mask represents a |
476 | * permission we do NOT want to audit (dontaudit), we use | 503 | * permission we do NOT want to audit (dontaudit), we use |
477 | * the '&' operand to ensure that all '0's in the mask | 504 | * the '&' operand to ensure that all '0's in the mask |
478 | * are retained (much unlike the allow and auditallow cases). | 505 | * are retained (much unlike the allow and auditallow cases). |
479 | */ | 506 | */ |
480 | avd->auditdeny &= avtab_auditdeny(&node->datum); | 507 | avd->auditdeny &= node->datum.data; |
481 | if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == | 508 | if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == |
482 | (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) | 509 | (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) |
483 | avd->auditallow |= avtab_auditallow(&node->datum); | 510 | avd->auditallow |= node->datum.data; |
484 | } | 511 | } |
485 | return; | 512 | return; |
486 | } | 513 | } |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index d8ce9cc0b9f1..d515154128cc 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -196,8 +196,9 @@ int ebitmap_read(struct ebitmap *e, void *fp) | |||
196 | { | 196 | { |
197 | int rc; | 197 | int rc; |
198 | struct ebitmap_node *n, *l; | 198 | struct ebitmap_node *n, *l; |
199 | u32 buf[3], mapsize, count, i; | 199 | __le32 buf[3]; |
200 | u64 map; | 200 | u32 mapsize, count, i; |
201 | __le64 map; | ||
201 | 202 | ||
202 | ebitmap_init(e); | 203 | ebitmap_init(e); |
203 | 204 | ||
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index 471370233fd9..8bf41055a6cb 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h | |||
@@ -32,11 +32,41 @@ struct ebitmap { | |||
32 | #define ebitmap_length(e) ((e)->highbit) | 32 | #define ebitmap_length(e) ((e)->highbit) |
33 | #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) | 33 | #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) |
34 | 34 | ||
35 | static inline unsigned int ebitmap_start(struct ebitmap *e, | ||
36 | struct ebitmap_node **n) | ||
37 | { | ||
38 | *n = e->node; | ||
39 | return ebitmap_startbit(e); | ||
40 | } | ||
41 | |||
35 | static inline void ebitmap_init(struct ebitmap *e) | 42 | static inline void ebitmap_init(struct ebitmap *e) |
36 | { | 43 | { |
37 | memset(e, 0, sizeof(*e)); | 44 | memset(e, 0, sizeof(*e)); |
38 | } | 45 | } |
39 | 46 | ||
47 | static inline unsigned int ebitmap_next(struct ebitmap_node **n, | ||
48 | unsigned int bit) | ||
49 | { | ||
50 | if ((bit == ((*n)->startbit + MAPSIZE - 1)) && | ||
51 | (*n)->next) { | ||
52 | *n = (*n)->next; | ||
53 | return (*n)->startbit; | ||
54 | } | ||
55 | |||
56 | return (bit+1); | ||
57 | } | ||
58 | |||
59 | static inline int ebitmap_node_get_bit(struct ebitmap_node * n, | ||
60 | unsigned int bit) | ||
61 | { | ||
62 | if (n->map & (MAPBIT << (bit - n->startbit))) | ||
63 | return 1; | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | #define ebitmap_for_each_bit(e, n, bit) \ | ||
68 | for (bit = ebitmap_start(e, &n); bit < ebitmap_length(e); bit = ebitmap_next(&n, bit)) \ | ||
69 | |||
40 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); | 70 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); |
41 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); | 71 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); |
42 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); | 72 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 756036bcc243..aaefac2921f1 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include "sidtab.h" | ||
18 | #include "mls.h" | 19 | #include "mls.h" |
19 | #include "policydb.h" | 20 | #include "policydb.h" |
20 | #include "services.h" | 21 | #include "services.h" |
@@ -26,6 +27,7 @@ | |||
26 | int mls_compute_context_len(struct context * context) | 27 | int mls_compute_context_len(struct context * context) |
27 | { | 28 | { |
28 | int i, l, len, range; | 29 | int i, l, len, range; |
30 | struct ebitmap_node *node; | ||
29 | 31 | ||
30 | if (!selinux_mls_enabled) | 32 | if (!selinux_mls_enabled) |
31 | return 0; | 33 | return 0; |
@@ -35,24 +37,24 @@ int mls_compute_context_len(struct context * context) | |||
35 | range = 0; | 37 | range = 0; |
36 | len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); | 38 | len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); |
37 | 39 | ||
38 | for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { | 40 | ebitmap_for_each_bit(&context->range.level[l].cat, node, i) { |
39 | if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { | 41 | if (ebitmap_node_get_bit(node, i)) { |
40 | if (range) { | 42 | if (range) { |
41 | range++; | 43 | range++; |
42 | continue; | 44 | continue; |
43 | } | 45 | } |
44 | 46 | ||
45 | len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; | 47 | len += strlen(policydb.p_cat_val_to_name[i]) + 1; |
46 | range++; | 48 | range++; |
47 | } else { | 49 | } else { |
48 | if (range > 1) | 50 | if (range > 1) |
49 | len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; | 51 | len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; |
50 | range = 0; | 52 | range = 0; |
51 | } | 53 | } |
52 | } | 54 | } |
53 | /* Handle case where last category is the end of range */ | 55 | /* Handle case where last category is the end of range */ |
54 | if (range > 1) | 56 | if (range > 1) |
55 | len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; | 57 | len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; |
56 | 58 | ||
57 | if (l == 0) { | 59 | if (l == 0) { |
58 | if (mls_level_eq(&context->range.level[0], | 60 | if (mls_level_eq(&context->range.level[0], |
@@ -76,6 +78,7 @@ void mls_sid_to_context(struct context *context, | |||
76 | { | 78 | { |
77 | char *scontextp; | 79 | char *scontextp; |
78 | int i, l, range, wrote_sep; | 80 | int i, l, range, wrote_sep; |
81 | struct ebitmap_node *node; | ||
79 | 82 | ||
80 | if (!selinux_mls_enabled) | 83 | if (!selinux_mls_enabled) |
81 | return; | 84 | return; |
@@ -93,8 +96,8 @@ void mls_sid_to_context(struct context *context, | |||
93 | scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); | 96 | scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); |
94 | 97 | ||
95 | /* categories */ | 98 | /* categories */ |
96 | for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { | 99 | ebitmap_for_each_bit(&context->range.level[l].cat, node, i) { |
97 | if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { | 100 | if (ebitmap_node_get_bit(node, i)) { |
98 | if (range) { | 101 | if (range) { |
99 | range++; | 102 | range++; |
100 | continue; | 103 | continue; |
@@ -105,8 +108,8 @@ void mls_sid_to_context(struct context *context, | |||
105 | wrote_sep = 1; | 108 | wrote_sep = 1; |
106 | } else | 109 | } else |
107 | *scontextp++ = ','; | 110 | *scontextp++ = ','; |
108 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); | 111 | strcpy(scontextp, policydb.p_cat_val_to_name[i]); |
109 | scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); | 112 | scontextp += strlen(policydb.p_cat_val_to_name[i]); |
110 | range++; | 113 | range++; |
111 | } else { | 114 | } else { |
112 | if (range > 1) { | 115 | if (range > 1) { |
@@ -115,8 +118,8 @@ void mls_sid_to_context(struct context *context, | |||
115 | else | 118 | else |
116 | *scontextp++ = ','; | 119 | *scontextp++ = ','; |
117 | 120 | ||
118 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); | 121 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); |
119 | scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); | 122 | scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); |
120 | } | 123 | } |
121 | range = 0; | 124 | range = 0; |
122 | } | 125 | } |
@@ -129,8 +132,8 @@ void mls_sid_to_context(struct context *context, | |||
129 | else | 132 | else |
130 | *scontextp++ = ','; | 133 | *scontextp++ = ','; |
131 | 134 | ||
132 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); | 135 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); |
133 | scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); | 136 | scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); |
134 | } | 137 | } |
135 | 138 | ||
136 | if (l == 0) { | 139 | if (l == 0) { |
@@ -156,6 +159,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
156 | { | 159 | { |
157 | struct level_datum *levdatum; | 160 | struct level_datum *levdatum; |
158 | struct user_datum *usrdatum; | 161 | struct user_datum *usrdatum; |
162 | struct ebitmap_node *node; | ||
159 | int i, l; | 163 | int i, l; |
160 | 164 | ||
161 | if (!selinux_mls_enabled) | 165 | if (!selinux_mls_enabled) |
@@ -178,11 +182,11 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
178 | if (!levdatum) | 182 | if (!levdatum) |
179 | return 0; | 183 | return 0; |
180 | 184 | ||
181 | for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { | 185 | ebitmap_for_each_bit(&c->range.level[l].cat, node, i) { |
182 | if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { | 186 | if (ebitmap_node_get_bit(node, i)) { |
183 | if (i > p->p_cats.nprim) | 187 | if (i > p->p_cats.nprim) |
184 | return 0; | 188 | return 0; |
185 | if (!ebitmap_get_bit(&levdatum->level->cat, i - 1)) | 189 | if (!ebitmap_get_bit(&levdatum->level->cat, i)) |
186 | /* | 190 | /* |
187 | * Category may not be associated with | 191 | * Category may not be associated with |
188 | * sensitivity in low level. | 192 | * sensitivity in low level. |
@@ -208,6 +212,26 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
208 | } | 212 | } |
209 | 213 | ||
210 | /* | 214 | /* |
215 | * Copies the MLS range from `src' into `dst'. | ||
216 | */ | ||
217 | static inline int mls_copy_context(struct context *dst, | ||
218 | struct context *src) | ||
219 | { | ||
220 | int l, rc = 0; | ||
221 | |||
222 | /* Copy the MLS range from the source context */ | ||
223 | for (l = 0; l < 2; l++) { | ||
224 | dst->range.level[l].sens = src->range.level[l].sens; | ||
225 | rc = ebitmap_cpy(&dst->range.level[l].cat, | ||
226 | &src->range.level[l].cat); | ||
227 | if (rc) | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | return rc; | ||
232 | } | ||
233 | |||
234 | /* | ||
211 | * Set the MLS fields in the security context structure | 235 | * Set the MLS fields in the security context structure |
212 | * `context' based on the string representation in | 236 | * `context' based on the string representation in |
213 | * the string `*scontext'. Update `*scontext' to | 237 | * the string `*scontext'. Update `*scontext' to |
@@ -216,10 +240,20 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
216 | * | 240 | * |
217 | * This function modifies the string in place, inserting | 241 | * This function modifies the string in place, inserting |
218 | * NULL characters to terminate the MLS fields. | 242 | * NULL characters to terminate the MLS fields. |
243 | * | ||
244 | * If a def_sid is provided and no MLS field is present, | ||
245 | * copy the MLS field of the associated default context. | ||
246 | * Used for upgraded to MLS systems where objects may lack | ||
247 | * MLS fields. | ||
248 | * | ||
249 | * Policy read-lock must be held for sidtab lookup. | ||
250 | * | ||
219 | */ | 251 | */ |
220 | int mls_context_to_sid(char oldc, | 252 | int mls_context_to_sid(char oldc, |
221 | char **scontext, | 253 | char **scontext, |
222 | struct context *context) | 254 | struct context *context, |
255 | struct sidtab *s, | ||
256 | u32 def_sid) | ||
223 | { | 257 | { |
224 | 258 | ||
225 | char delim; | 259 | char delim; |
@@ -231,9 +265,23 @@ int mls_context_to_sid(char oldc, | |||
231 | if (!selinux_mls_enabled) | 265 | if (!selinux_mls_enabled) |
232 | return 0; | 266 | return 0; |
233 | 267 | ||
234 | /* No MLS component to the security context. */ | 268 | /* |
235 | if (!oldc) | 269 | * No MLS component to the security context, try and map to |
270 | * default if provided. | ||
271 | */ | ||
272 | if (!oldc) { | ||
273 | struct context *defcon; | ||
274 | |||
275 | if (def_sid == SECSID_NULL) | ||
276 | goto out; | ||
277 | |||
278 | defcon = sidtab_search(s, def_sid); | ||
279 | if (!defcon) | ||
280 | goto out; | ||
281 | |||
282 | rc = mls_copy_context(context, defcon); | ||
236 | goto out; | 283 | goto out; |
284 | } | ||
237 | 285 | ||
238 | /* Extract low sensitivity. */ | 286 | /* Extract low sensitivity. */ |
239 | scontextp = p = *scontext; | 287 | scontextp = p = *scontext; |
@@ -334,26 +382,6 @@ out: | |||
334 | } | 382 | } |
335 | 383 | ||
336 | /* | 384 | /* |
337 | * Copies the MLS range from `src' into `dst'. | ||
338 | */ | ||
339 | static inline int mls_copy_context(struct context *dst, | ||
340 | struct context *src) | ||
341 | { | ||
342 | int l, rc = 0; | ||
343 | |||
344 | /* Copy the MLS range from the source context */ | ||
345 | for (l = 0; l < 2; l++) { | ||
346 | dst->range.level[l].sens = src->range.level[l].sens; | ||
347 | rc = ebitmap_cpy(&dst->range.level[l].cat, | ||
348 | &src->range.level[l].cat); | ||
349 | if (rc) | ||
350 | break; | ||
351 | } | ||
352 | |||
353 | return rc; | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * Copies the effective MLS range from `src' into `dst'. | 385 | * Copies the effective MLS range from `src' into `dst'. |
358 | */ | 386 | */ |
359 | static inline int mls_scopy_context(struct context *dst, | 387 | static inline int mls_scopy_context(struct context *dst, |
@@ -443,6 +471,7 @@ int mls_convert_context(struct policydb *oldp, | |||
443 | struct level_datum *levdatum; | 471 | struct level_datum *levdatum; |
444 | struct cat_datum *catdatum; | 472 | struct cat_datum *catdatum; |
445 | struct ebitmap bitmap; | 473 | struct ebitmap bitmap; |
474 | struct ebitmap_node *node; | ||
446 | int l, i; | 475 | int l, i; |
447 | 476 | ||
448 | if (!selinux_mls_enabled) | 477 | if (!selinux_mls_enabled) |
@@ -457,12 +486,12 @@ int mls_convert_context(struct policydb *oldp, | |||
457 | c->range.level[l].sens = levdatum->level->sens; | 486 | c->range.level[l].sens = levdatum->level->sens; |
458 | 487 | ||
459 | ebitmap_init(&bitmap); | 488 | ebitmap_init(&bitmap); |
460 | for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { | 489 | ebitmap_for_each_bit(&c->range.level[l].cat, node, i) { |
461 | if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { | 490 | if (ebitmap_node_get_bit(node, i)) { |
462 | int rc; | 491 | int rc; |
463 | 492 | ||
464 | catdatum = hashtab_search(newp->p_cats.table, | 493 | catdatum = hashtab_search(newp->p_cats.table, |
465 | oldp->p_cat_val_to_name[i - 1]); | 494 | oldp->p_cat_val_to_name[i]); |
466 | if (!catdatum) | 495 | if (!catdatum) |
467 | return -EINVAL; | 496 | return -EINVAL; |
468 | rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); | 497 | rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 0d37beaa85e2..03de697c8058 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
@@ -23,7 +23,9 @@ int mls_context_isvalid(struct policydb *p, struct context *c); | |||
23 | 23 | ||
24 | int mls_context_to_sid(char oldc, | 24 | int mls_context_to_sid(char oldc, |
25 | char **scontext, | 25 | char **scontext, |
26 | struct context *context); | 26 | struct context *context, |
27 | struct sidtab *s, | ||
28 | u32 def_sid); | ||
27 | 29 | ||
28 | int mls_convert_context(struct policydb *oldp, | 30 | int mls_convert_context(struct policydb *oldp, |
29 | struct policydb *newp, | 31 | struct policydb *newp, |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 785c33cf4864..0a758323a9cf 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -91,6 +91,11 @@ static struct policydb_compat_info policydb_compat[] = { | |||
91 | .sym_num = SYM_NUM, | 91 | .sym_num = SYM_NUM, |
92 | .ocon_num = OCON_NUM, | 92 | .ocon_num = OCON_NUM, |
93 | }, | 93 | }, |
94 | { | ||
95 | .version = POLICYDB_VERSION_AVTAB, | ||
96 | .sym_num = SYM_NUM, | ||
97 | .ocon_num = OCON_NUM, | ||
98 | }, | ||
94 | }; | 99 | }; |
95 | 100 | ||
96 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 101 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
@@ -584,6 +589,9 @@ void policydb_destroy(struct policydb *p) | |||
584 | struct ocontext *c, *ctmp; | 589 | struct ocontext *c, *ctmp; |
585 | struct genfs *g, *gtmp; | 590 | struct genfs *g, *gtmp; |
586 | int i; | 591 | int i; |
592 | struct role_allow *ra, *lra = NULL; | ||
593 | struct role_trans *tr, *ltr = NULL; | ||
594 | struct range_trans *rt, *lrt = NULL; | ||
587 | 595 | ||
588 | for (i = 0; i < SYM_NUM; i++) { | 596 | for (i = 0; i < SYM_NUM; i++) { |
589 | hashtab_map(p->symtab[i].table, destroy_f[i], NULL); | 597 | hashtab_map(p->symtab[i].table, destroy_f[i], NULL); |
@@ -624,6 +632,28 @@ void policydb_destroy(struct policydb *p) | |||
624 | 632 | ||
625 | cond_policydb_destroy(p); | 633 | cond_policydb_destroy(p); |
626 | 634 | ||
635 | for (tr = p->role_tr; tr; tr = tr->next) { | ||
636 | if (ltr) kfree(ltr); | ||
637 | ltr = tr; | ||
638 | } | ||
639 | if (ltr) kfree(ltr); | ||
640 | |||
641 | for (ra = p->role_allow; ra; ra = ra -> next) { | ||
642 | if (lra) kfree(lra); | ||
643 | lra = ra; | ||
644 | } | ||
645 | if (lra) kfree(lra); | ||
646 | |||
647 | for (rt = p->range_tr; rt; rt = rt -> next) { | ||
648 | if (lrt) kfree(lrt); | ||
649 | lrt = rt; | ||
650 | } | ||
651 | if (lrt) kfree(lrt); | ||
652 | |||
653 | for (i = 0; i < p->p_types.nprim; i++) | ||
654 | ebitmap_destroy(&p->type_attr_map[i]); | ||
655 | kfree(p->type_attr_map); | ||
656 | |||
627 | return; | 657 | return; |
628 | } | 658 | } |
629 | 659 | ||
@@ -714,7 +744,8 @@ int policydb_context_isvalid(struct policydb *p, struct context *c) | |||
714 | */ | 744 | */ |
715 | static int mls_read_range_helper(struct mls_range *r, void *fp) | 745 | static int mls_read_range_helper(struct mls_range *r, void *fp) |
716 | { | 746 | { |
717 | u32 buf[2], items; | 747 | __le32 buf[2]; |
748 | u32 items; | ||
718 | int rc; | 749 | int rc; |
719 | 750 | ||
720 | rc = next_entry(buf, fp, sizeof(u32)); | 751 | rc = next_entry(buf, fp, sizeof(u32)); |
@@ -775,7 +806,7 @@ static int context_read_and_validate(struct context *c, | |||
775 | struct policydb *p, | 806 | struct policydb *p, |
776 | void *fp) | 807 | void *fp) |
777 | { | 808 | { |
778 | u32 buf[3]; | 809 | __le32 buf[3]; |
779 | int rc; | 810 | int rc; |
780 | 811 | ||
781 | rc = next_entry(buf, fp, sizeof buf); | 812 | rc = next_entry(buf, fp, sizeof buf); |
@@ -815,7 +846,8 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) | |||
815 | char *key = NULL; | 846 | char *key = NULL; |
816 | struct perm_datum *perdatum; | 847 | struct perm_datum *perdatum; |
817 | int rc; | 848 | int rc; |
818 | u32 buf[2], len; | 849 | __le32 buf[2]; |
850 | u32 len; | ||
819 | 851 | ||
820 | perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); | 852 | perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); |
821 | if (!perdatum) { | 853 | if (!perdatum) { |
@@ -855,7 +887,8 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) | |||
855 | { | 887 | { |
856 | char *key = NULL; | 888 | char *key = NULL; |
857 | struct common_datum *comdatum; | 889 | struct common_datum *comdatum; |
858 | u32 buf[4], len, nel; | 890 | __le32 buf[4]; |
891 | u32 len, nel; | ||
859 | int i, rc; | 892 | int i, rc; |
860 | 893 | ||
861 | comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); | 894 | comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); |
@@ -909,7 +942,8 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons, | |||
909 | { | 942 | { |
910 | struct constraint_node *c, *lc; | 943 | struct constraint_node *c, *lc; |
911 | struct constraint_expr *e, *le; | 944 | struct constraint_expr *e, *le; |
912 | u32 buf[3], nexpr; | 945 | __le32 buf[3]; |
946 | u32 nexpr; | ||
913 | int rc, i, j, depth; | 947 | int rc, i, j, depth; |
914 | 948 | ||
915 | lc = NULL; | 949 | lc = NULL; |
@@ -993,7 +1027,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
993 | { | 1027 | { |
994 | char *key = NULL; | 1028 | char *key = NULL; |
995 | struct class_datum *cladatum; | 1029 | struct class_datum *cladatum; |
996 | u32 buf[6], len, len2, ncons, nel; | 1030 | __le32 buf[6]; |
1031 | u32 len, len2, ncons, nel; | ||
997 | int i, rc; | 1032 | int i, rc; |
998 | 1033 | ||
999 | cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); | 1034 | cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); |
@@ -1087,7 +1122,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1087 | char *key = NULL; | 1122 | char *key = NULL; |
1088 | struct role_datum *role; | 1123 | struct role_datum *role; |
1089 | int rc; | 1124 | int rc; |
1090 | u32 buf[2], len; | 1125 | __le32 buf[2]; |
1126 | u32 len; | ||
1091 | 1127 | ||
1092 | role = kmalloc(sizeof(*role), GFP_KERNEL); | 1128 | role = kmalloc(sizeof(*role), GFP_KERNEL); |
1093 | if (!role) { | 1129 | if (!role) { |
@@ -1147,7 +1183,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1147 | char *key = NULL; | 1183 | char *key = NULL; |
1148 | struct type_datum *typdatum; | 1184 | struct type_datum *typdatum; |
1149 | int rc; | 1185 | int rc; |
1150 | u32 buf[3], len; | 1186 | __le32 buf[3]; |
1187 | u32 len; | ||
1151 | 1188 | ||
1152 | typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); | 1189 | typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); |
1153 | if (!typdatum) { | 1190 | if (!typdatum) { |
@@ -1191,7 +1228,7 @@ bad: | |||
1191 | */ | 1228 | */ |
1192 | static int mls_read_level(struct mls_level *lp, void *fp) | 1229 | static int mls_read_level(struct mls_level *lp, void *fp) |
1193 | { | 1230 | { |
1194 | u32 buf[1]; | 1231 | __le32 buf[1]; |
1195 | int rc; | 1232 | int rc; |
1196 | 1233 | ||
1197 | memset(lp, 0, sizeof(*lp)); | 1234 | memset(lp, 0, sizeof(*lp)); |
@@ -1219,7 +1256,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1219 | char *key = NULL; | 1256 | char *key = NULL; |
1220 | struct user_datum *usrdatum; | 1257 | struct user_datum *usrdatum; |
1221 | int rc; | 1258 | int rc; |
1222 | u32 buf[2], len; | 1259 | __le32 buf[2]; |
1260 | u32 len; | ||
1223 | 1261 | ||
1224 | usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); | 1262 | usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); |
1225 | if (!usrdatum) { | 1263 | if (!usrdatum) { |
@@ -1273,7 +1311,8 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1273 | char *key = NULL; | 1311 | char *key = NULL; |
1274 | struct level_datum *levdatum; | 1312 | struct level_datum *levdatum; |
1275 | int rc; | 1313 | int rc; |
1276 | u32 buf[2], len; | 1314 | __le32 buf[2]; |
1315 | u32 len; | ||
1277 | 1316 | ||
1278 | levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); | 1317 | levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); |
1279 | if (!levdatum) { | 1318 | if (!levdatum) { |
@@ -1324,7 +1363,8 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1324 | char *key = NULL; | 1363 | char *key = NULL; |
1325 | struct cat_datum *catdatum; | 1364 | struct cat_datum *catdatum; |
1326 | int rc; | 1365 | int rc; |
1327 | u32 buf[3], len; | 1366 | __le32 buf[3]; |
1367 | u32 len; | ||
1328 | 1368 | ||
1329 | catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); | 1369 | catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); |
1330 | if (!catdatum) { | 1370 | if (!catdatum) { |
@@ -1387,7 +1427,8 @@ int policydb_read(struct policydb *p, void *fp) | |||
1387 | struct ocontext *l, *c, *newc; | 1427 | struct ocontext *l, *c, *newc; |
1388 | struct genfs *genfs_p, *genfs, *newgenfs; | 1428 | struct genfs *genfs_p, *genfs, *newgenfs; |
1389 | int i, j, rc; | 1429 | int i, j, rc; |
1390 | u32 buf[8], len, len2, config, nprim, nel, nel2; | 1430 | __le32 buf[8]; |
1431 | u32 len, len2, config, nprim, nel, nel2; | ||
1391 | char *policydb_str; | 1432 | char *policydb_str; |
1392 | struct policydb_compat_info *info; | 1433 | struct policydb_compat_info *info; |
1393 | struct range_trans *rt, *lrt; | 1434 | struct range_trans *rt, *lrt; |
@@ -1403,17 +1444,14 @@ int policydb_read(struct policydb *p, void *fp) | |||
1403 | if (rc < 0) | 1444 | if (rc < 0) |
1404 | goto bad; | 1445 | goto bad; |
1405 | 1446 | ||
1406 | for (i = 0; i < 2; i++) | 1447 | if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { |
1407 | buf[i] = le32_to_cpu(buf[i]); | ||
1408 | |||
1409 | if (buf[0] != POLICYDB_MAGIC) { | ||
1410 | printk(KERN_ERR "security: policydb magic number 0x%x does " | 1448 | printk(KERN_ERR "security: policydb magic number 0x%x does " |
1411 | "not match expected magic number 0x%x\n", | 1449 | "not match expected magic number 0x%x\n", |
1412 | buf[0], POLICYDB_MAGIC); | 1450 | le32_to_cpu(buf[0]), POLICYDB_MAGIC); |
1413 | goto bad; | 1451 | goto bad; |
1414 | } | 1452 | } |
1415 | 1453 | ||
1416 | len = buf[1]; | 1454 | len = le32_to_cpu(buf[1]); |
1417 | if (len != strlen(POLICYDB_STRING)) { | 1455 | if (len != strlen(POLICYDB_STRING)) { |
1418 | printk(KERN_ERR "security: policydb string length %d does not " | 1456 | printk(KERN_ERR "security: policydb string length %d does not " |
1419 | "match expected length %Zu\n", | 1457 | "match expected length %Zu\n", |
@@ -1448,19 +1486,17 @@ int policydb_read(struct policydb *p, void *fp) | |||
1448 | rc = next_entry(buf, fp, sizeof(u32)*4); | 1486 | rc = next_entry(buf, fp, sizeof(u32)*4); |
1449 | if (rc < 0) | 1487 | if (rc < 0) |
1450 | goto bad; | 1488 | goto bad; |
1451 | for (i = 0; i < 4; i++) | ||
1452 | buf[i] = le32_to_cpu(buf[i]); | ||
1453 | 1489 | ||
1454 | p->policyvers = buf[0]; | 1490 | p->policyvers = le32_to_cpu(buf[0]); |
1455 | if (p->policyvers < POLICYDB_VERSION_MIN || | 1491 | if (p->policyvers < POLICYDB_VERSION_MIN || |
1456 | p->policyvers > POLICYDB_VERSION_MAX) { | 1492 | p->policyvers > POLICYDB_VERSION_MAX) { |
1457 | printk(KERN_ERR "security: policydb version %d does not match " | 1493 | printk(KERN_ERR "security: policydb version %d does not match " |
1458 | "my version range %d-%d\n", | 1494 | "my version range %d-%d\n", |
1459 | buf[0], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); | 1495 | le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); |
1460 | goto bad; | 1496 | goto bad; |
1461 | } | 1497 | } |
1462 | 1498 | ||
1463 | if ((buf[1] & POLICYDB_CONFIG_MLS)) { | 1499 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
1464 | if (ss_initialized && !selinux_mls_enabled) { | 1500 | if (ss_initialized && !selinux_mls_enabled) { |
1465 | printk(KERN_ERR "Cannot switch between non-MLS and MLS " | 1501 | printk(KERN_ERR "Cannot switch between non-MLS and MLS " |
1466 | "policies\n"); | 1502 | "policies\n"); |
@@ -1489,9 +1525,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
1489 | goto bad; | 1525 | goto bad; |
1490 | } | 1526 | } |
1491 | 1527 | ||
1492 | if (buf[2] != info->sym_num || buf[3] != info->ocon_num) { | 1528 | if (le32_to_cpu(buf[2]) != info->sym_num || |
1529 | le32_to_cpu(buf[3]) != info->ocon_num) { | ||
1493 | printk(KERN_ERR "security: policydb table sizes (%d,%d) do " | 1530 | printk(KERN_ERR "security: policydb table sizes (%d,%d) do " |
1494 | "not match mine (%d,%d)\n", buf[2], buf[3], | 1531 | "not match mine (%d,%d)\n", le32_to_cpu(buf[2]), |
1532 | le32_to_cpu(buf[3]), | ||
1495 | info->sym_num, info->ocon_num); | 1533 | info->sym_num, info->ocon_num); |
1496 | goto bad; | 1534 | goto bad; |
1497 | } | 1535 | } |
@@ -1511,7 +1549,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1511 | p->symtab[i].nprim = nprim; | 1549 | p->symtab[i].nprim = nprim; |
1512 | } | 1550 | } |
1513 | 1551 | ||
1514 | rc = avtab_read(&p->te_avtab, fp, config); | 1552 | rc = avtab_read(&p->te_avtab, fp, p->policyvers); |
1515 | if (rc) | 1553 | if (rc) |
1516 | goto bad; | 1554 | goto bad; |
1517 | 1555 | ||
@@ -1825,6 +1863,21 @@ int policydb_read(struct policydb *p, void *fp) | |||
1825 | } | 1863 | } |
1826 | } | 1864 | } |
1827 | 1865 | ||
1866 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | ||
1867 | if (!p->type_attr_map) | ||
1868 | goto bad; | ||
1869 | |||
1870 | for (i = 0; i < p->p_types.nprim; i++) { | ||
1871 | ebitmap_init(&p->type_attr_map[i]); | ||
1872 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { | ||
1873 | if (ebitmap_read(&p->type_attr_map[i], fp)) | ||
1874 | goto bad; | ||
1875 | } | ||
1876 | /* add the type itself as the degenerate case */ | ||
1877 | if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) | ||
1878 | goto bad; | ||
1879 | } | ||
1880 | |||
1828 | rc = 0; | 1881 | rc = 0; |
1829 | out: | 1882 | out: |
1830 | return rc; | 1883 | return rc; |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 2470e2a1a1c3..b1340711f721 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -237,6 +237,9 @@ struct policydb { | |||
237 | /* range transitions */ | 237 | /* range transitions */ |
238 | struct range_trans *range_tr; | 238 | struct range_trans *range_tr; |
239 | 239 | ||
240 | /* type -> attribute reverse mapping */ | ||
241 | struct ebitmap *type_attr_map; | ||
242 | |||
240 | unsigned int policyvers; | 243 | unsigned int policyvers; |
241 | }; | 244 | }; |
242 | 245 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 922bb45054aa..aecdded55e74 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -266,8 +266,11 @@ static int context_struct_compute_av(struct context *scontext, | |||
266 | struct constraint_node *constraint; | 266 | struct constraint_node *constraint; |
267 | struct role_allow *ra; | 267 | struct role_allow *ra; |
268 | struct avtab_key avkey; | 268 | struct avtab_key avkey; |
269 | struct avtab_datum *avdatum; | 269 | struct avtab_node *node; |
270 | struct class_datum *tclass_datum; | 270 | struct class_datum *tclass_datum; |
271 | struct ebitmap *sattr, *tattr; | ||
272 | struct ebitmap_node *snode, *tnode; | ||
273 | unsigned int i, j; | ||
271 | 274 | ||
272 | /* | 275 | /* |
273 | * Remap extended Netlink classes for old policy versions. | 276 | * Remap extended Netlink classes for old policy versions. |
@@ -300,21 +303,34 @@ static int context_struct_compute_av(struct context *scontext, | |||
300 | * If a specific type enforcement rule was defined for | 303 | * If a specific type enforcement rule was defined for |
301 | * this permission check, then use it. | 304 | * this permission check, then use it. |
302 | */ | 305 | */ |
303 | avkey.source_type = scontext->type; | ||
304 | avkey.target_type = tcontext->type; | ||
305 | avkey.target_class = tclass; | 306 | avkey.target_class = tclass; |
306 | avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV); | 307 | avkey.specified = AVTAB_AV; |
307 | if (avdatum) { | 308 | sattr = &policydb.type_attr_map[scontext->type - 1]; |
308 | if (avdatum->specified & AVTAB_ALLOWED) | 309 | tattr = &policydb.type_attr_map[tcontext->type - 1]; |
309 | avd->allowed = avtab_allowed(avdatum); | 310 | ebitmap_for_each_bit(sattr, snode, i) { |
310 | if (avdatum->specified & AVTAB_AUDITDENY) | 311 | if (!ebitmap_node_get_bit(snode, i)) |
311 | avd->auditdeny = avtab_auditdeny(avdatum); | 312 | continue; |
312 | if (avdatum->specified & AVTAB_AUDITALLOW) | 313 | ebitmap_for_each_bit(tattr, tnode, j) { |
313 | avd->auditallow = avtab_auditallow(avdatum); | 314 | if (!ebitmap_node_get_bit(tnode, j)) |
314 | } | 315 | continue; |
316 | avkey.source_type = i + 1; | ||
317 | avkey.target_type = j + 1; | ||
318 | for (node = avtab_search_node(&policydb.te_avtab, &avkey); | ||
319 | node != NULL; | ||
320 | node = avtab_search_node_next(node, avkey.specified)) { | ||
321 | if (node->key.specified == AVTAB_ALLOWED) | ||
322 | avd->allowed |= node->datum.data; | ||
323 | else if (node->key.specified == AVTAB_AUDITALLOW) | ||
324 | avd->auditallow |= node->datum.data; | ||
325 | else if (node->key.specified == AVTAB_AUDITDENY) | ||
326 | avd->auditdeny &= node->datum.data; | ||
327 | } | ||
328 | |||
329 | /* Check conditional av table for additional permissions */ | ||
330 | cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); | ||
315 | 331 | ||
316 | /* Check conditional av table for additional permissions */ | 332 | } |
317 | cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); | 333 | } |
318 | 334 | ||
319 | /* | 335 | /* |
320 | * Remove any permissions prohibited by a constraint (this includes | 336 | * Remove any permissions prohibited by a constraint (this includes |
@@ -365,7 +381,7 @@ static int security_validtrans_handle_fail(struct context *ocontext, | |||
365 | goto out; | 381 | goto out; |
366 | if (context_struct_to_string(tcontext, &t, &tlen) < 0) | 382 | if (context_struct_to_string(tcontext, &t, &tlen) < 0) |
367 | goto out; | 383 | goto out; |
368 | audit_log(current->audit_context, AUDIT_SELINUX_ERR, | 384 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
369 | "security_validate_transition: denied for" | 385 | "security_validate_transition: denied for" |
370 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", | 386 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", |
371 | o, n, t, policydb.p_class_val_to_name[tclass-1]); | 387 | o, n, t, policydb.p_class_val_to_name[tclass-1]); |
@@ -601,18 +617,7 @@ out: | |||
601 | 617 | ||
602 | } | 618 | } |
603 | 619 | ||
604 | /** | 620 | static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid) |
605 | * security_context_to_sid - Obtain a SID for a given security context. | ||
606 | * @scontext: security context | ||
607 | * @scontext_len: length in bytes | ||
608 | * @sid: security identifier, SID | ||
609 | * | ||
610 | * Obtains a SID associated with the security context that | ||
611 | * has the string representation specified by @scontext. | ||
612 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient | ||
613 | * memory is available, or 0 on success. | ||
614 | */ | ||
615 | int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid) | ||
616 | { | 621 | { |
617 | char *scontext2; | 622 | char *scontext2; |
618 | struct context context; | 623 | struct context context; |
@@ -703,7 +708,7 @@ int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid) | |||
703 | 708 | ||
704 | context.type = typdatum->value; | 709 | context.type = typdatum->value; |
705 | 710 | ||
706 | rc = mls_context_to_sid(oldc, &p, &context); | 711 | rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid); |
707 | if (rc) | 712 | if (rc) |
708 | goto out_unlock; | 713 | goto out_unlock; |
709 | 714 | ||
@@ -727,6 +732,46 @@ out: | |||
727 | return rc; | 732 | return rc; |
728 | } | 733 | } |
729 | 734 | ||
735 | /** | ||
736 | * security_context_to_sid - Obtain a SID for a given security context. | ||
737 | * @scontext: security context | ||
738 | * @scontext_len: length in bytes | ||
739 | * @sid: security identifier, SID | ||
740 | * | ||
741 | * Obtains a SID associated with the security context that | ||
742 | * has the string representation specified by @scontext. | ||
743 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient | ||
744 | * memory is available, or 0 on success. | ||
745 | */ | ||
746 | int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid) | ||
747 | { | ||
748 | return security_context_to_sid_core(scontext, scontext_len, | ||
749 | sid, SECSID_NULL); | ||
750 | } | ||
751 | |||
752 | /** | ||
753 | * security_context_to_sid_default - Obtain a SID for a given security context, | ||
754 | * falling back to specified default if needed. | ||
755 | * | ||
756 | * @scontext: security context | ||
757 | * @scontext_len: length in bytes | ||
758 | * @sid: security identifier, SID | ||
759 | * @def_sid: default SID to assign on errror | ||
760 | * | ||
761 | * Obtains a SID associated with the security context that | ||
762 | * has the string representation specified by @scontext. | ||
763 | * The default SID is passed to the MLS layer to be used to allow | ||
764 | * kernel labeling of the MLS field if the MLS field is not present | ||
765 | * (for upgrading to MLS without full relabel). | ||
766 | * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient | ||
767 | * memory is available, or 0 on success. | ||
768 | */ | ||
769 | int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid) | ||
770 | { | ||
771 | return security_context_to_sid_core(scontext, scontext_len, | ||
772 | sid, def_sid); | ||
773 | } | ||
774 | |||
730 | static int compute_sid_handle_invalid_context( | 775 | static int compute_sid_handle_invalid_context( |
731 | struct context *scontext, | 776 | struct context *scontext, |
732 | struct context *tcontext, | 777 | struct context *tcontext, |
@@ -742,7 +787,7 @@ static int compute_sid_handle_invalid_context( | |||
742 | goto out; | 787 | goto out; |
743 | if (context_struct_to_string(newcontext, &n, &nlen) < 0) | 788 | if (context_struct_to_string(newcontext, &n, &nlen) < 0) |
744 | goto out; | 789 | goto out; |
745 | audit_log(current->audit_context, AUDIT_SELINUX_ERR, | 790 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
746 | "security_compute_sid: invalid context %s" | 791 | "security_compute_sid: invalid context %s" |
747 | " for scontext=%s" | 792 | " for scontext=%s" |
748 | " tcontext=%s" | 793 | " tcontext=%s" |
@@ -768,7 +813,6 @@ static int security_compute_sid(u32 ssid, | |||
768 | struct avtab_key avkey; | 813 | struct avtab_key avkey; |
769 | struct avtab_datum *avdatum; | 814 | struct avtab_datum *avdatum; |
770 | struct avtab_node *node; | 815 | struct avtab_node *node; |
771 | unsigned int type_change = 0; | ||
772 | int rc = 0; | 816 | int rc = 0; |
773 | 817 | ||
774 | if (!ss_initialized) { | 818 | if (!ss_initialized) { |
@@ -833,33 +877,23 @@ static int security_compute_sid(u32 ssid, | |||
833 | avkey.source_type = scontext->type; | 877 | avkey.source_type = scontext->type; |
834 | avkey.target_type = tcontext->type; | 878 | avkey.target_type = tcontext->type; |
835 | avkey.target_class = tclass; | 879 | avkey.target_class = tclass; |
836 | avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE); | 880 | avkey.specified = specified; |
881 | avdatum = avtab_search(&policydb.te_avtab, &avkey); | ||
837 | 882 | ||
838 | /* If no permanent rule, also check for enabled conditional rules */ | 883 | /* If no permanent rule, also check for enabled conditional rules */ |
839 | if(!avdatum) { | 884 | if(!avdatum) { |
840 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified); | 885 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey); |
841 | for (; node != NULL; node = avtab_search_node_next(node, specified)) { | 886 | for (; node != NULL; node = avtab_search_node_next(node, specified)) { |
842 | if (node->datum.specified & AVTAB_ENABLED) { | 887 | if (node->key.specified & AVTAB_ENABLED) { |
843 | avdatum = &node->datum; | 888 | avdatum = &node->datum; |
844 | break; | 889 | break; |
845 | } | 890 | } |
846 | } | 891 | } |
847 | } | 892 | } |
848 | 893 | ||
849 | type_change = (avdatum && (avdatum->specified & specified)); | 894 | if (avdatum) { |
850 | if (type_change) { | ||
851 | /* Use the type from the type transition/member/change rule. */ | 895 | /* Use the type from the type transition/member/change rule. */ |
852 | switch (specified) { | 896 | newcontext.type = avdatum->data; |
853 | case AVTAB_TRANSITION: | ||
854 | newcontext.type = avtab_transition(avdatum); | ||
855 | break; | ||
856 | case AVTAB_MEMBER: | ||
857 | newcontext.type = avtab_member(avdatum); | ||
858 | break; | ||
859 | case AVTAB_CHANGE: | ||
860 | newcontext.type = avtab_change(avdatum); | ||
861 | break; | ||
862 | } | ||
863 | } | 897 | } |
864 | 898 | ||
865 | /* Check for class-specific changes. */ | 899 | /* Check for class-specific changes. */ |
@@ -1473,6 +1507,7 @@ int security_get_user_sids(u32 fromsid, | |||
1473 | struct user_datum *user; | 1507 | struct user_datum *user; |
1474 | struct role_datum *role; | 1508 | struct role_datum *role; |
1475 | struct av_decision avd; | 1509 | struct av_decision avd; |
1510 | struct ebitmap_node *rnode, *tnode; | ||
1476 | int rc = 0, i, j; | 1511 | int rc = 0, i, j; |
1477 | 1512 | ||
1478 | if (!ss_initialized) { | 1513 | if (!ss_initialized) { |
@@ -1503,13 +1538,13 @@ int security_get_user_sids(u32 fromsid, | |||
1503 | } | 1538 | } |
1504 | memset(mysids, 0, maxnel*sizeof(*mysids)); | 1539 | memset(mysids, 0, maxnel*sizeof(*mysids)); |
1505 | 1540 | ||
1506 | for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) { | 1541 | ebitmap_for_each_bit(&user->roles, rnode, i) { |
1507 | if (!ebitmap_get_bit(&user->roles, i)) | 1542 | if (!ebitmap_node_get_bit(rnode, i)) |
1508 | continue; | 1543 | continue; |
1509 | role = policydb.role_val_to_struct[i]; | 1544 | role = policydb.role_val_to_struct[i]; |
1510 | usercon.role = i+1; | 1545 | usercon.role = i+1; |
1511 | for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) { | 1546 | ebitmap_for_each_bit(&role->types, tnode, j) { |
1512 | if (!ebitmap_get_bit(&role->types, j)) | 1547 | if (!ebitmap_node_get_bit(tnode, j)) |
1513 | continue; | 1548 | continue; |
1514 | usercon.type = j+1; | 1549 | usercon.type = j+1; |
1515 | 1550 | ||