diff options
Diffstat (limited to 'security/selinux')
| -rw-r--r-- | security/selinux/avc.c | 31 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 162 | ||||
| -rw-r--r-- | security/selinux/include/initial_sid_to_string.h | 2 | ||||
| -rw-r--r-- | security/selinux/include/netlabel.h | 8 | ||||
| -rw-r--r-- | security/selinux/include/objsec.h | 1 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 13 | ||||
| -rw-r--r-- | security/selinux/netif.c | 1 | ||||
| -rw-r--r-- | security/selinux/netlabel.c | 15 | ||||
| -rw-r--r-- | security/selinux/netlink.c | 2 | ||||
| -rw-r--r-- | security/selinux/netnode.c | 1 | ||||
| -rw-r--r-- | security/selinux/netport.c | 1 | ||||
| -rw-r--r-- | security/selinux/nlmsgtab.c | 1 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 56 | ||||
| -rw-r--r-- | security/selinux/ss/avtab.h | 2 | ||||
| -rw-r--r-- | security/selinux/ss/context.h | 12 | ||||
| -rw-r--r-- | security/selinux/ss/ebitmap.c | 2 | ||||
| -rw-r--r-- | security/selinux/ss/mls.c | 50 | ||||
| -rw-r--r-- | security/selinux/ss/mls.h | 2 | ||||
| -rw-r--r-- | security/selinux/ss/mls_types.h | 7 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.c | 134 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.h | 10 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 322 | ||||
| -rw-r--r-- | security/selinux/ss/symtab.c | 1 | ||||
| -rw-r--r-- | security/selinux/xfrm.c | 1 |
24 files changed, 422 insertions, 415 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index f2dde268165a..7f1a304712a9 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
| @@ -337,7 +337,7 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) | |||
| 337 | * Look up an AVC entry that is valid for the | 337 | * Look up an AVC entry that is valid for the |
| 338 | * (@ssid, @tsid), interpreting the permissions | 338 | * (@ssid, @tsid), interpreting the permissions |
| 339 | * based on @tclass. If a valid AVC entry exists, | 339 | * based on @tclass. If a valid AVC entry exists, |
| 340 | * then this function return the avc_node. | 340 | * then this function returns the avc_node. |
| 341 | * Otherwise, this function returns NULL. | 341 | * Otherwise, this function returns NULL. |
| 342 | */ | 342 | */ |
| 343 | static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) | 343 | static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) |
| @@ -489,21 +489,17 @@ void avc_audit(u32 ssid, u32 tsid, | |||
| 489 | struct common_audit_data stack_data; | 489 | struct common_audit_data stack_data; |
| 490 | u32 denied, audited; | 490 | u32 denied, audited; |
| 491 | denied = requested & ~avd->allowed; | 491 | denied = requested & ~avd->allowed; |
| 492 | if (denied) { | 492 | if (denied) |
| 493 | audited = denied; | 493 | audited = denied & avd->auditdeny; |
| 494 | if (!(audited & avd->auditdeny)) | 494 | else if (result) |
| 495 | return; | ||
| 496 | } else if (result) { | ||
| 497 | audited = denied = requested; | 495 | audited = denied = requested; |
| 498 | } else { | 496 | else |
| 499 | audited = requested; | 497 | audited = requested & avd->auditallow; |
| 500 | if (!(audited & avd->auditallow)) | 498 | if (!audited) |
| 501 | return; | 499 | return; |
| 502 | } | ||
| 503 | if (!a) { | 500 | if (!a) { |
| 504 | a = &stack_data; | 501 | a = &stack_data; |
| 505 | memset(a, 0, sizeof(*a)); | 502 | COMMON_AUDIT_DATA_INIT(a, NONE); |
| 506 | a->type = LSM_AUDIT_NO_AUDIT; | ||
| 507 | } | 503 | } |
| 508 | a->selinux_audit_data.tclass = tclass; | 504 | a->selinux_audit_data.tclass = tclass; |
| 509 | a->selinux_audit_data.requested = requested; | 505 | a->selinux_audit_data.requested = requested; |
| @@ -526,7 +522,7 @@ void avc_audit(u32 ssid, u32 tsid, | |||
| 526 | * @perms: permissions | 522 | * @perms: permissions |
| 527 | * | 523 | * |
| 528 | * Register a callback function for events in the set @events | 524 | * Register a callback function for events in the set @events |
| 529 | * related to the SID pair (@ssid, @tsid) and | 525 | * related to the SID pair (@ssid, @tsid) |
| 530 | * and the permissions @perms, interpreting | 526 | * and the permissions @perms, interpreting |
| 531 | * @perms based on @tclass. Returns %0 on success or | 527 | * @perms based on @tclass. Returns %0 on success or |
| 532 | * -%ENOMEM if insufficient memory exists to add the callback. | 528 | * -%ENOMEM if insufficient memory exists to add the callback. |
| @@ -571,7 +567,7 @@ static inline int avc_sidcmp(u32 x, u32 y) | |||
| 571 | * | 567 | * |
| 572 | * if a valid AVC entry doesn't exist,this function returns -ENOENT. | 568 | * if a valid AVC entry doesn't exist,this function returns -ENOENT. |
| 573 | * if kmalloc() called internal returns NULL, this function returns -ENOMEM. | 569 | * if kmalloc() called internal returns NULL, this function returns -ENOMEM. |
| 574 | * otherwise, this function update the AVC entry. The original AVC-entry object | 570 | * otherwise, this function updates the AVC entry. The original AVC-entry object |
| 575 | * will release later by RCU. | 571 | * will release later by RCU. |
| 576 | */ | 572 | */ |
| 577 | static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, | 573 | static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, |
| @@ -746,9 +742,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
| 746 | else | 742 | else |
| 747 | avd = &avd_entry; | 743 | avd = &avd_entry; |
| 748 | 744 | ||
| 749 | rc = security_compute_av(ssid, tsid, tclass, requested, avd); | 745 | security_compute_av(ssid, tsid, tclass, avd); |
| 750 | if (rc) | ||
| 751 | goto out; | ||
| 752 | rcu_read_lock(); | 746 | rcu_read_lock(); |
| 753 | node = avc_insert(ssid, tsid, tclass, avd); | 747 | node = avc_insert(ssid, tsid, tclass, avd); |
| 754 | } else { | 748 | } else { |
| @@ -770,7 +764,6 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
| 770 | } | 764 | } |
| 771 | 765 | ||
| 772 | rcu_read_unlock(); | 766 | rcu_read_unlock(); |
| 773 | out: | ||
| 774 | return rc; | 767 | return rc; |
| 775 | } | 768 | } |
| 776 | 769 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9a2ee845e9d4..5c9f25ba1c95 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -76,6 +76,7 @@ | |||
| 76 | #include <linux/selinux.h> | 76 | #include <linux/selinux.h> |
| 77 | #include <linux/mutex.h> | 77 | #include <linux/mutex.h> |
| 78 | #include <linux/posix-timers.h> | 78 | #include <linux/posix-timers.h> |
| 79 | #include <linux/syslog.h> | ||
| 79 | 80 | ||
| 80 | #include "avc.h" | 81 | #include "avc.h" |
| 81 | #include "objsec.h" | 82 | #include "objsec.h" |
| @@ -125,18 +126,6 @@ __setup("selinux=", selinux_enabled_setup); | |||
| 125 | int selinux_enabled = 1; | 126 | int selinux_enabled = 1; |
| 126 | #endif | 127 | #endif |
| 127 | 128 | ||
| 128 | |||
| 129 | /* | ||
| 130 | * Minimal support for a secondary security module, | ||
| 131 | * just to allow the use of the capability module. | ||
| 132 | */ | ||
| 133 | static struct security_operations *secondary_ops; | ||
| 134 | |||
| 135 | /* Lists of inode and superblock security structures initialized | ||
| 136 | before the policy was loaded. */ | ||
| 137 | static LIST_HEAD(superblock_security_head); | ||
| 138 | static DEFINE_SPINLOCK(sb_security_lock); | ||
| 139 | |||
| 140 | static struct kmem_cache *sel_inode_cache; | 129 | static struct kmem_cache *sel_inode_cache; |
| 141 | 130 | ||
| 142 | /** | 131 | /** |
| @@ -272,7 +261,6 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 272 | return -ENOMEM; | 261 | return -ENOMEM; |
| 273 | 262 | ||
| 274 | mutex_init(&sbsec->lock); | 263 | mutex_init(&sbsec->lock); |
| 275 | INIT_LIST_HEAD(&sbsec->list); | ||
| 276 | INIT_LIST_HEAD(&sbsec->isec_head); | 264 | INIT_LIST_HEAD(&sbsec->isec_head); |
| 277 | spin_lock_init(&sbsec->isec_lock); | 265 | spin_lock_init(&sbsec->isec_lock); |
| 278 | sbsec->sb = sb; | 266 | sbsec->sb = sb; |
| @@ -287,40 +275,34 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 287 | static void superblock_free_security(struct super_block *sb) | 275 | static void superblock_free_security(struct super_block *sb) |
| 288 | { | 276 | { |
| 289 | struct superblock_security_struct *sbsec = sb->s_security; | 277 | struct superblock_security_struct *sbsec = sb->s_security; |
| 290 | |||
| 291 | spin_lock(&sb_security_lock); | ||
| 292 | if (!list_empty(&sbsec->list)) | ||
| 293 | list_del_init(&sbsec->list); | ||
| 294 | spin_unlock(&sb_security_lock); | ||
| 295 | |||
| 296 | sb->s_security = NULL; | 278 | sb->s_security = NULL; |
| 297 | kfree(sbsec); | 279 | kfree(sbsec); |
| 298 | } | 280 | } |
| 299 | 281 | ||
| 300 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 282 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
| 301 | { | 283 | { |
| 302 | struct sk_security_struct *ssec; | 284 | struct sk_security_struct *sksec; |
| 303 | 285 | ||
| 304 | ssec = kzalloc(sizeof(*ssec), priority); | 286 | sksec = kzalloc(sizeof(*sksec), priority); |
| 305 | if (!ssec) | 287 | if (!sksec) |
| 306 | return -ENOMEM; | 288 | return -ENOMEM; |
| 307 | 289 | ||
| 308 | ssec->peer_sid = SECINITSID_UNLABELED; | 290 | sksec->peer_sid = SECINITSID_UNLABELED; |
| 309 | ssec->sid = SECINITSID_UNLABELED; | 291 | sksec->sid = SECINITSID_UNLABELED; |
| 310 | sk->sk_security = ssec; | 292 | sk->sk_security = sksec; |
| 311 | 293 | ||
| 312 | selinux_netlbl_sk_security_reset(ssec); | 294 | selinux_netlbl_sk_security_reset(sksec); |
| 313 | 295 | ||
| 314 | return 0; | 296 | return 0; |
| 315 | } | 297 | } |
| 316 | 298 | ||
| 317 | static void sk_free_security(struct sock *sk) | 299 | static void sk_free_security(struct sock *sk) |
| 318 | { | 300 | { |
| 319 | struct sk_security_struct *ssec = sk->sk_security; | 301 | struct sk_security_struct *sksec = sk->sk_security; |
| 320 | 302 | ||
| 321 | sk->sk_security = NULL; | 303 | sk->sk_security = NULL; |
| 322 | selinux_netlbl_sk_security_free(ssec); | 304 | selinux_netlbl_sk_security_free(sksec); |
| 323 | kfree(ssec); | 305 | kfree(sksec); |
| 324 | } | 306 | } |
| 325 | 307 | ||
| 326 | /* The security server must be initialized before | 308 | /* The security server must be initialized before |
| @@ -329,7 +311,7 @@ extern int ss_initialized; | |||
| 329 | 311 | ||
| 330 | /* The file system's label must be initialized prior to use. */ | 312 | /* The file system's label must be initialized prior to use. */ |
| 331 | 313 | ||
| 332 | static char *labeling_behaviors[6] = { | 314 | static const char *labeling_behaviors[6] = { |
| 333 | "uses xattr", | 315 | "uses xattr", |
| 334 | "uses transition SIDs", | 316 | "uses transition SIDs", |
| 335 | "uses task SIDs", | 317 | "uses task SIDs", |
| @@ -618,10 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 618 | /* Defer initialization until selinux_complete_init, | 600 | /* Defer initialization until selinux_complete_init, |
| 619 | after the initial policy is loaded and the security | 601 | after the initial policy is loaded and the security |
| 620 | server is ready to handle calls. */ | 602 | server is ready to handle calls. */ |
| 621 | spin_lock(&sb_security_lock); | ||
| 622 | if (list_empty(&sbsec->list)) | ||
| 623 | list_add(&sbsec->list, &superblock_security_head); | ||
| 624 | spin_unlock(&sb_security_lock); | ||
| 625 | goto out; | 603 | goto out; |
| 626 | } | 604 | } |
| 627 | rc = -EINVAL; | 605 | rc = -EINVAL; |
| @@ -812,16 +790,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
| 812 | 790 | ||
| 813 | /* | 791 | /* |
| 814 | * if the parent was able to be mounted it clearly had no special lsm | 792 | * if the parent was able to be mounted it clearly had no special lsm |
| 815 | * mount options. thus we can safely put this sb on the list and deal | 793 | * mount options. thus we can safely deal with this superblock later |
| 816 | * with it later | ||
| 817 | */ | 794 | */ |
| 818 | if (!ss_initialized) { | 795 | if (!ss_initialized) |
| 819 | spin_lock(&sb_security_lock); | ||
| 820 | if (list_empty(&newsbsec->list)) | ||
| 821 | list_add(&newsbsec->list, &superblock_security_head); | ||
| 822 | spin_unlock(&sb_security_lock); | ||
| 823 | return; | 796 | return; |
| 824 | } | ||
| 825 | 797 | ||
| 826 | /* how can we clone if the old one wasn't set up?? */ | 798 | /* how can we clone if the old one wasn't set up?? */ |
| 827 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 799 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
| @@ -2049,29 +2021,30 @@ static int selinux_quota_on(struct dentry *dentry) | |||
| 2049 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); | 2021 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); |
| 2050 | } | 2022 | } |
| 2051 | 2023 | ||
| 2052 | static int selinux_syslog(int type) | 2024 | static int selinux_syslog(int type, bool from_file) |
| 2053 | { | 2025 | { |
| 2054 | int rc; | 2026 | int rc; |
| 2055 | 2027 | ||
| 2056 | rc = cap_syslog(type); | 2028 | rc = cap_syslog(type, from_file); |
| 2057 | if (rc) | 2029 | if (rc) |
| 2058 | return rc; | 2030 | return rc; |
| 2059 | 2031 | ||
| 2060 | switch (type) { | 2032 | switch (type) { |
| 2061 | case 3: /* Read last kernel messages */ | 2033 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
| 2062 | case 10: /* Return size of the log buffer */ | 2034 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
| 2063 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); | 2035 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); |
| 2064 | break; | 2036 | break; |
| 2065 | case 6: /* Disable logging to console */ | 2037 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
| 2066 | case 7: /* Enable logging to console */ | 2038 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
| 2067 | case 8: /* Set level of messages printed to console */ | 2039 | /* Set level of messages printed to console */ |
| 2040 | case SYSLOG_ACTION_CONSOLE_LEVEL: | ||
| 2068 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); | 2041 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); |
| 2069 | break; | 2042 | break; |
| 2070 | case 0: /* Close log */ | 2043 | case SYSLOG_ACTION_CLOSE: /* Close log */ |
| 2071 | case 1: /* Open log */ | 2044 | case SYSLOG_ACTION_OPEN: /* Open log */ |
| 2072 | case 2: /* Read from log */ | 2045 | case SYSLOG_ACTION_READ: /* Read from log */ |
| 2073 | case 4: /* Read/clear last kernel messages */ | 2046 | case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */ |
| 2074 | case 5: /* Clear ring buffer */ | 2047 | case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */ |
| 2075 | default: | 2048 | default: |
| 2076 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); | 2049 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); |
| 2077 | break; | 2050 | break; |
| @@ -3004,13 +2977,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
| 3004 | return file_has_perm(cred, file, av); | 2977 | return file_has_perm(cred, file, av); |
| 3005 | } | 2978 | } |
| 3006 | 2979 | ||
| 2980 | static int default_noexec; | ||
| 2981 | |||
| 3007 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 2982 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
| 3008 | { | 2983 | { |
| 3009 | const struct cred *cred = current_cred(); | 2984 | const struct cred *cred = current_cred(); |
| 3010 | int rc = 0; | 2985 | int rc = 0; |
| 3011 | 2986 | ||
| 3012 | #ifndef CONFIG_PPC32 | 2987 | if (default_noexec && |
| 3013 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 2988 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
| 3014 | /* | 2989 | /* |
| 3015 | * We are making executable an anonymous mapping or a | 2990 | * We are making executable an anonymous mapping or a |
| 3016 | * private file mapping that will also be writable. | 2991 | * private file mapping that will also be writable. |
| @@ -3020,7 +2995,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
| 3020 | if (rc) | 2995 | if (rc) |
| 3021 | goto error; | 2996 | goto error; |
| 3022 | } | 2997 | } |
| 3023 | #endif | ||
| 3024 | 2998 | ||
| 3025 | if (file) { | 2999 | if (file) { |
| 3026 | /* read access is always possible with a mapping */ | 3000 | /* read access is always possible with a mapping */ |
| @@ -3081,8 +3055,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3081 | if (selinux_checkreqprot) | 3055 | if (selinux_checkreqprot) |
| 3082 | prot = reqprot; | 3056 | prot = reqprot; |
| 3083 | 3057 | ||
| 3084 | #ifndef CONFIG_PPC32 | 3058 | if (default_noexec && |
| 3085 | if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { | 3059 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { |
| 3086 | int rc = 0; | 3060 | int rc = 0; |
| 3087 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3061 | if (vma->vm_start >= vma->vm_mm->start_brk && |
| 3088 | vma->vm_end <= vma->vm_mm->brk) { | 3062 | vma->vm_end <= vma->vm_mm->brk) { |
| @@ -3104,7 +3078,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3104 | if (rc) | 3078 | if (rc) |
| 3105 | return rc; | 3079 | return rc; |
| 3106 | } | 3080 | } |
| 3107 | #endif | ||
| 3108 | 3081 | ||
| 3109 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); | 3082 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); |
| 3110 | } | 3083 | } |
| @@ -3334,7 +3307,7 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
| 3334 | 3307 | ||
| 3335 | if (ret == 0) | 3308 | if (ret == 0) |
| 3336 | tsec->create_sid = isec->sid; | 3309 | tsec->create_sid = isec->sid; |
| 3337 | return 0; | 3310 | return ret; |
| 3338 | } | 3311 | } |
| 3339 | 3312 | ||
| 3340 | static int selinux_kernel_module_request(char *kmod_name) | 3313 | static int selinux_kernel_module_request(char *kmod_name) |
| @@ -4007,7 +3980,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
| 4007 | struct socket *other, | 3980 | struct socket *other, |
| 4008 | struct sock *newsk) | 3981 | struct sock *newsk) |
| 4009 | { | 3982 | { |
| 4010 | struct sk_security_struct *ssec; | 3983 | struct sk_security_struct *sksec; |
| 4011 | struct inode_security_struct *isec; | 3984 | struct inode_security_struct *isec; |
| 4012 | struct inode_security_struct *other_isec; | 3985 | struct inode_security_struct *other_isec; |
| 4013 | struct common_audit_data ad; | 3986 | struct common_audit_data ad; |
| @@ -4026,13 +3999,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
| 4026 | return err; | 3999 | return err; |
| 4027 | 4000 | ||
| 4028 | /* connecting socket */ | 4001 | /* connecting socket */ |
| 4029 | ssec = sock->sk->sk_security; | 4002 | sksec = sock->sk->sk_security; |
| 4030 | ssec->peer_sid = other_isec->sid; | 4003 | sksec->peer_sid = other_isec->sid; |
| 4031 | 4004 | ||
| 4032 | /* server child socket */ | 4005 | /* server child socket */ |
| 4033 | ssec = newsk->sk_security; | 4006 | sksec = newsk->sk_security; |
| 4034 | ssec->peer_sid = isec->sid; | 4007 | sksec->peer_sid = isec->sid; |
| 4035 | err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); | 4008 | err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); |
| 4036 | 4009 | ||
| 4037 | return err; | 4010 | return err; |
| 4038 | } | 4011 | } |
| @@ -4195,7 +4168,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 4195 | int err = 0; | 4168 | int err = 0; |
| 4196 | char *scontext; | 4169 | char *scontext; |
| 4197 | u32 scontext_len; | 4170 | u32 scontext_len; |
| 4198 | struct sk_security_struct *ssec; | 4171 | struct sk_security_struct *sksec; |
| 4199 | struct inode_security_struct *isec; | 4172 | struct inode_security_struct *isec; |
| 4200 | u32 peer_sid = SECSID_NULL; | 4173 | u32 peer_sid = SECSID_NULL; |
| 4201 | 4174 | ||
| @@ -4203,8 +4176,8 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 4203 | 4176 | ||
| 4204 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 4177 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
| 4205 | isec->sclass == SECCLASS_TCP_SOCKET) { | 4178 | isec->sclass == SECCLASS_TCP_SOCKET) { |
| 4206 | ssec = sock->sk->sk_security; | 4179 | sksec = sock->sk->sk_security; |
| 4207 | peer_sid = ssec->peer_sid; | 4180 | peer_sid = sksec->peer_sid; |
| 4208 | } | 4181 | } |
| 4209 | if (peer_sid == SECSID_NULL) { | 4182 | if (peer_sid == SECSID_NULL) { |
| 4210 | err = -ENOPROTOOPT; | 4183 | err = -ENOPROTOOPT; |
| @@ -4271,14 +4244,14 @@ static void selinux_sk_free_security(struct sock *sk) | |||
| 4271 | 4244 | ||
| 4272 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4245 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
| 4273 | { | 4246 | { |
| 4274 | struct sk_security_struct *ssec = sk->sk_security; | 4247 | struct sk_security_struct *sksec = sk->sk_security; |
| 4275 | struct sk_security_struct *newssec = newsk->sk_security; | 4248 | struct sk_security_struct *newsksec = newsk->sk_security; |
| 4276 | 4249 | ||
| 4277 | newssec->sid = ssec->sid; | 4250 | newsksec->sid = sksec->sid; |
| 4278 | newssec->peer_sid = ssec->peer_sid; | 4251 | newsksec->peer_sid = sksec->peer_sid; |
| 4279 | newssec->sclass = ssec->sclass; | 4252 | newsksec->sclass = sksec->sclass; |
| 4280 | 4253 | ||
| 4281 | selinux_netlbl_sk_security_reset(newssec); | 4254 | selinux_netlbl_sk_security_reset(newsksec); |
| 4282 | } | 4255 | } |
| 4283 | 4256 | ||
| 4284 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4257 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
| @@ -5667,14 +5640,13 @@ static __init int selinux_init(void) | |||
| 5667 | /* Set the security state for the initial task. */ | 5640 | /* Set the security state for the initial task. */ |
| 5668 | cred_init_security(); | 5641 | cred_init_security(); |
| 5669 | 5642 | ||
| 5643 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | ||
| 5644 | |||
| 5670 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5645 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
| 5671 | sizeof(struct inode_security_struct), | 5646 | sizeof(struct inode_security_struct), |
| 5672 | 0, SLAB_PANIC, NULL); | 5647 | 0, SLAB_PANIC, NULL); |
| 5673 | avc_init(); | 5648 | avc_init(); |
| 5674 | 5649 | ||
| 5675 | secondary_ops = security_ops; | ||
| 5676 | if (!secondary_ops) | ||
| 5677 | panic("SELinux: No initial security operations\n"); | ||
| 5678 | if (register_security(&selinux_ops)) | 5650 | if (register_security(&selinux_ops)) |
| 5679 | panic("SELinux: Unable to register with kernel.\n"); | 5651 | panic("SELinux: Unable to register with kernel.\n"); |
| 5680 | 5652 | ||
| @@ -5686,35 +5658,18 @@ static __init int selinux_init(void) | |||
| 5686 | return 0; | 5658 | return 0; |
| 5687 | } | 5659 | } |
| 5688 | 5660 | ||
| 5661 | static void delayed_superblock_init(struct super_block *sb, void *unused) | ||
| 5662 | { | ||
| 5663 | superblock_doinit(sb, NULL); | ||
| 5664 | } | ||
| 5665 | |||
| 5689 | void selinux_complete_init(void) | 5666 | void selinux_complete_init(void) |
| 5690 | { | 5667 | { |
| 5691 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); | 5668 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); |
| 5692 | 5669 | ||
| 5693 | /* Set up any superblocks initialized prior to the policy load. */ | 5670 | /* Set up any superblocks initialized prior to the policy load. */ |
| 5694 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); | 5671 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); |
| 5695 | spin_lock(&sb_lock); | 5672 | iterate_supers(delayed_superblock_init, NULL); |
| 5696 | spin_lock(&sb_security_lock); | ||
| 5697 | next_sb: | ||
| 5698 | if (!list_empty(&superblock_security_head)) { | ||
| 5699 | struct superblock_security_struct *sbsec = | ||
| 5700 | list_entry(superblock_security_head.next, | ||
| 5701 | struct superblock_security_struct, | ||
| 5702 | list); | ||
| 5703 | struct super_block *sb = sbsec->sb; | ||
| 5704 | sb->s_count++; | ||
| 5705 | spin_unlock(&sb_security_lock); | ||
| 5706 | spin_unlock(&sb_lock); | ||
| 5707 | down_read(&sb->s_umount); | ||
| 5708 | if (sb->s_root) | ||
| 5709 | superblock_doinit(sb, NULL); | ||
| 5710 | drop_super(sb); | ||
| 5711 | spin_lock(&sb_lock); | ||
| 5712 | spin_lock(&sb_security_lock); | ||
| 5713 | list_del_init(&sbsec->list); | ||
| 5714 | goto next_sb; | ||
| 5715 | } | ||
| 5716 | spin_unlock(&sb_security_lock); | ||
| 5717 | spin_unlock(&sb_lock); | ||
| 5718 | } | 5673 | } |
| 5719 | 5674 | ||
| 5720 | /* SELinux requires early initialization in order to label | 5675 | /* SELinux requires early initialization in order to label |
| @@ -5835,8 +5790,7 @@ int selinux_disable(void) | |||
| 5835 | selinux_disabled = 1; | 5790 | selinux_disabled = 1; |
| 5836 | selinux_enabled = 0; | 5791 | selinux_enabled = 0; |
| 5837 | 5792 | ||
| 5838 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5793 | reset_security_ops(); |
| 5839 | security_ops = secondary_ops; | ||
| 5840 | 5794 | ||
| 5841 | /* Try to destroy the avc node cache */ | 5795 | /* Try to destroy the avc node cache */ |
| 5842 | avc_disable(); | 5796 | avc_disable(); |
diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h index d4fac82793ae..a59b64e3fd02 100644 --- a/security/selinux/include/initial_sid_to_string.h +++ b/security/selinux/include/initial_sid_to_string.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* This file is automatically generated. Do not edit. */ | 1 | /* This file is automatically generated. Do not edit. */ |
| 2 | static char *initial_sid_to_string[] = | 2 | static const char *initial_sid_to_string[] = |
| 3 | { | 3 | { |
| 4 | "null", | 4 | "null", |
| 5 | "kernel", | 5 | "kernel", |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 8d7384280a7a..cf2f628e6e28 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h | |||
| @@ -42,8 +42,8 @@ void selinux_netlbl_cache_invalidate(void); | |||
| 42 | 42 | ||
| 43 | void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); | 43 | void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); |
| 44 | 44 | ||
| 45 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); | 45 | void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec); |
| 46 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec); | 46 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec); |
| 47 | 47 | ||
| 48 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | 48 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, |
| 49 | u16 family, | 49 | u16 family, |
| @@ -79,13 +79,13 @@ static inline void selinux_netlbl_err(struct sk_buff *skb, | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static inline void selinux_netlbl_sk_security_free( | 81 | static inline void selinux_netlbl_sk_security_free( |
| 82 | struct sk_security_struct *ssec) | 82 | struct sk_security_struct *sksec) |
| 83 | { | 83 | { |
| 84 | return; | 84 | return; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static inline void selinux_netlbl_sk_security_reset( | 87 | static inline void selinux_netlbl_sk_security_reset( |
| 88 | struct sk_security_struct *ssec) | 88 | struct sk_security_struct *sksec) |
| 89 | { | 89 | { |
| 90 | return; | 90 | return; |
| 91 | } | 91 | } |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index c4e062336ef3..26c7eee1c309 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -55,7 +55,6 @@ struct file_security_struct { | |||
| 55 | 55 | ||
| 56 | struct superblock_security_struct { | 56 | struct superblock_security_struct { |
| 57 | struct super_block *sb; /* back pointer to sb object */ | 57 | struct super_block *sb; /* back pointer to sb object */ |
| 58 | struct list_head list; /* list of superblock_security_struct */ | ||
| 59 | u32 sid; /* SID of file system superblock */ | 58 | u32 sid; /* SID of file system superblock */ |
| 60 | u32 def_sid; /* default SID for labeling */ | 59 | u32 def_sid; /* default SID for labeling */ |
| 61 | u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ | 60 | u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 2553266ad793..1f7c2491d3dc 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
| @@ -57,7 +57,6 @@ | |||
| 57 | struct netlbl_lsm_secattr; | 57 | struct netlbl_lsm_secattr; |
| 58 | 58 | ||
| 59 | extern int selinux_enabled; | 59 | extern int selinux_enabled; |
| 60 | extern int selinux_mls_enabled; | ||
| 61 | 60 | ||
| 62 | /* Policy capabilities */ | 61 | /* Policy capabilities */ |
| 63 | enum { | 62 | enum { |
| @@ -80,6 +79,8 @@ extern int selinux_policycap_openperm; | |||
| 80 | /* limitation of boundary depth */ | 79 | /* limitation of boundary depth */ |
| 81 | #define POLICYDB_BOUNDS_MAXDEPTH 4 | 80 | #define POLICYDB_BOUNDS_MAXDEPTH 4 |
| 82 | 81 | ||
| 82 | int security_mls_enabled(void); | ||
| 83 | |||
| 83 | int security_load_policy(void *data, size_t len); | 84 | int security_load_policy(void *data, size_t len); |
| 84 | 85 | ||
| 85 | int security_policycap_supported(unsigned int req_cap); | 86 | int security_policycap_supported(unsigned int req_cap); |
| @@ -96,13 +97,11 @@ struct av_decision { | |||
| 96 | /* definitions of av_decision.flags */ | 97 | /* definitions of av_decision.flags */ |
| 97 | #define AVD_FLAGS_PERMISSIVE 0x0001 | 98 | #define AVD_FLAGS_PERMISSIVE 0x0001 |
| 98 | 99 | ||
| 99 | int security_compute_av(u32 ssid, u32 tsid, | 100 | void security_compute_av(u32 ssid, u32 tsid, |
| 100 | u16 tclass, u32 requested, | 101 | u16 tclass, struct av_decision *avd); |
| 101 | struct av_decision *avd); | ||
| 102 | 102 | ||
| 103 | int security_compute_av_user(u32 ssid, u32 tsid, | 103 | void security_compute_av_user(u32 ssid, u32 tsid, |
| 104 | u16 tclass, u32 requested, | 104 | u16 tclass, struct av_decision *avd); |
| 105 | struct av_decision *avd); | ||
| 106 | 105 | ||
| 107 | int security_transition_sid(u32 ssid, u32 tsid, | 106 | int security_transition_sid(u32 ssid, u32 tsid, |
| 108 | u16 tclass, u32 *out_sid); | 107 | u16 tclass, u32 *out_sid); |
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index b4e14bc0bf32..d6095d63d831 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | */ | 16 | */ |
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 19 | #include <linux/slab.h> | ||
| 19 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
| 20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 21 | #include <linux/list.h> | 22 | #include <linux/list.h> |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2534400317c5..1c2fc46544bf 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
| 31 | #include <linux/rcupdate.h> | 31 | #include <linux/rcupdate.h> |
| 32 | #include <linux/gfp.h> | ||
| 32 | #include <linux/ip.h> | 33 | #include <linux/ip.h> |
| 33 | #include <linux/ipv6.h> | 34 | #include <linux/ipv6.h> |
| 34 | #include <net/sock.h> | 35 | #include <net/sock.h> |
| @@ -131,21 +132,21 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) | |||
| 131 | 132 | ||
| 132 | /** | 133 | /** |
| 133 | * selinux_netlbl_sk_security_free - Free the NetLabel fields | 134 | * selinux_netlbl_sk_security_free - Free the NetLabel fields |
| 134 | * @sssec: the sk_security_struct | 135 | * @sksec: the sk_security_struct |
| 135 | * | 136 | * |
| 136 | * Description: | 137 | * Description: |
| 137 | * Free all of the memory in the NetLabel fields of a sk_security_struct. | 138 | * Free all of the memory in the NetLabel fields of a sk_security_struct. |
| 138 | * | 139 | * |
| 139 | */ | 140 | */ |
| 140 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | 141 | void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) |
| 141 | { | 142 | { |
| 142 | if (ssec->nlbl_secattr != NULL) | 143 | if (sksec->nlbl_secattr != NULL) |
| 143 | netlbl_secattr_free(ssec->nlbl_secattr); | 144 | netlbl_secattr_free(sksec->nlbl_secattr); |
| 144 | } | 145 | } |
| 145 | 146 | ||
| 146 | /** | 147 | /** |
| 147 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields | 148 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields |
| 148 | * @ssec: the sk_security_struct | 149 | * @sksec: the sk_security_struct |
| 149 | * @family: the socket family | 150 | * @family: the socket family |
| 150 | * | 151 | * |
| 151 | * Description: | 152 | * Description: |
| @@ -153,9 +154,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | |||
| 153 | * The caller is responsibile for all the NetLabel sk_security_struct locking. | 154 | * The caller is responsibile for all the NetLabel sk_security_struct locking. |
| 154 | * | 155 | * |
| 155 | */ | 156 | */ |
| 156 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec) | 157 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) |
| 157 | { | 158 | { |
| 158 | ssec->nlbl_state = NLBL_UNSET; | 159 | sksec->nlbl_state = NLBL_UNSET; |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 161 | /** | 162 | /** |
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 1ae556446e65..36ac257cec9a 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c | |||
| @@ -11,9 +11,9 @@ | |||
| 11 | */ | 11 | */ |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 14 | #include <linux/slab.h> | ||
| 14 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
| 15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
| 18 | #include <linux/netlink.h> | 18 | #include <linux/netlink.h> |
| 19 | #include <linux/selinux_netlink.h> | 19 | #include <linux/selinux_netlink.h> |
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 7100072bb1b0..dc92792271f1 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 32 | #include <linux/rcupdate.h> | 32 | #include <linux/rcupdate.h> |
| 33 | #include <linux/list.h> | 33 | #include <linux/list.h> |
| 34 | #include <linux/slab.h> | ||
| 34 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
| 35 | #include <linux/in.h> | 36 | #include <linux/in.h> |
| 36 | #include <linux/in6.h> | 37 | #include <linux/in6.h> |
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index fe7fba67f19f..cfe2d72d3fb7 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
| 31 | #include <linux/rcupdate.h> | 31 | #include <linux/rcupdate.h> |
| 32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
| 33 | #include <linux/slab.h> | ||
| 33 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
| 34 | #include <linux/in.h> | 35 | #include <linux/in.h> |
| 35 | #include <linux/in6.h> | 36 | #include <linux/in6.h> |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index dd7cc6de77f9..75ec0c6ebacd 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | */ | 11 | */ |
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/skbuff.h> | ||
| 15 | #include <linux/netlink.h> | 14 | #include <linux/netlink.h> |
| 16 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
| 17 | #include <linux/if.h> | 16 | #include <linux/if.h> |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index fab36fdf2769..0293843f7eda 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -282,7 +282,8 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf, | |||
| 282 | char tmpbuf[TMPBUFLEN]; | 282 | char tmpbuf[TMPBUFLEN]; |
| 283 | ssize_t length; | 283 | ssize_t length; |
| 284 | 284 | ||
| 285 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled); | 285 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", |
| 286 | security_mls_enabled()); | ||
| 286 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 287 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
| 287 | } | 288 | } |
| 288 | 289 | ||
| @@ -494,7 +495,6 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
| 494 | char *scon, *tcon; | 495 | char *scon, *tcon; |
| 495 | u32 ssid, tsid; | 496 | u32 ssid, tsid; |
| 496 | u16 tclass; | 497 | u16 tclass; |
| 497 | u32 req; | ||
| 498 | struct av_decision avd; | 498 | struct av_decision avd; |
| 499 | ssize_t length; | 499 | ssize_t length; |
| 500 | 500 | ||
| @@ -503,28 +503,26 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
| 503 | return length; | 503 | return length; |
| 504 | 504 | ||
| 505 | length = -ENOMEM; | 505 | length = -ENOMEM; |
| 506 | scon = kzalloc(size+1, GFP_KERNEL); | 506 | scon = kzalloc(size + 1, GFP_KERNEL); |
| 507 | if (!scon) | 507 | if (!scon) |
| 508 | return length; | 508 | return length; |
| 509 | 509 | ||
| 510 | tcon = kzalloc(size+1, GFP_KERNEL); | 510 | tcon = kzalloc(size + 1, GFP_KERNEL); |
| 511 | if (!tcon) | 511 | if (!tcon) |
| 512 | goto out; | 512 | goto out; |
| 513 | 513 | ||
| 514 | length = -EINVAL; | 514 | length = -EINVAL; |
| 515 | if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4) | 515 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
| 516 | goto out2; | 516 | goto out2; |
| 517 | 517 | ||
| 518 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 518 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
| 519 | if (length < 0) | 519 | if (length < 0) |
| 520 | goto out2; | 520 | goto out2; |
| 521 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 521 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
| 522 | if (length < 0) | 522 | if (length < 0) |
| 523 | goto out2; | 523 | goto out2; |
| 524 | 524 | ||
| 525 | length = security_compute_av_user(ssid, tsid, tclass, req, &avd); | 525 | security_compute_av_user(ssid, tsid, tclass, &avd); |
| 526 | if (length < 0) | ||
| 527 | goto out2; | ||
| 528 | 526 | ||
| 529 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, | 527 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, |
| 530 | "%x %x %x %x %u %x", | 528 | "%x %x %x %x %u %x", |
| @@ -552,11 +550,11 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
| 552 | return length; | 550 | return length; |
| 553 | 551 | ||
| 554 | length = -ENOMEM; | 552 | length = -ENOMEM; |
| 555 | scon = kzalloc(size+1, GFP_KERNEL); | 553 | scon = kzalloc(size + 1, GFP_KERNEL); |
| 556 | if (!scon) | 554 | if (!scon) |
| 557 | return length; | 555 | return length; |
| 558 | 556 | ||
| 559 | tcon = kzalloc(size+1, GFP_KERNEL); | 557 | tcon = kzalloc(size + 1, GFP_KERNEL); |
| 560 | if (!tcon) | 558 | if (!tcon) |
| 561 | goto out; | 559 | goto out; |
| 562 | 560 | ||
| @@ -564,10 +562,10 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
| 564 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 562 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
| 565 | goto out2; | 563 | goto out2; |
| 566 | 564 | ||
| 567 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 565 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
| 568 | if (length < 0) | 566 | if (length < 0) |
| 569 | goto out2; | 567 | goto out2; |
| 570 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 568 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
| 571 | if (length < 0) | 569 | if (length < 0) |
| 572 | goto out2; | 570 | goto out2; |
| 573 | 571 | ||
| @@ -611,11 +609,11 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
| 611 | return length; | 609 | return length; |
| 612 | 610 | ||
| 613 | length = -ENOMEM; | 611 | length = -ENOMEM; |
| 614 | scon = kzalloc(size+1, GFP_KERNEL); | 612 | scon = kzalloc(size + 1, GFP_KERNEL); |
| 615 | if (!scon) | 613 | if (!scon) |
| 616 | return length; | 614 | return length; |
| 617 | 615 | ||
| 618 | tcon = kzalloc(size+1, GFP_KERNEL); | 616 | tcon = kzalloc(size + 1, GFP_KERNEL); |
| 619 | if (!tcon) | 617 | if (!tcon) |
| 620 | goto out; | 618 | goto out; |
| 621 | 619 | ||
| @@ -623,10 +621,10 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
| 623 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 621 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
| 624 | goto out2; | 622 | goto out2; |
| 625 | 623 | ||
| 626 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 624 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
| 627 | if (length < 0) | 625 | if (length < 0) |
| 628 | goto out2; | 626 | goto out2; |
| 629 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 627 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
| 630 | if (length < 0) | 628 | if (length < 0) |
| 631 | goto out2; | 629 | goto out2; |
| 632 | 630 | ||
| @@ -668,11 +666,11 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
| 668 | return length; | 666 | return length; |
| 669 | 667 | ||
| 670 | length = -ENOMEM; | 668 | length = -ENOMEM; |
| 671 | con = kzalloc(size+1, GFP_KERNEL); | 669 | con = kzalloc(size + 1, GFP_KERNEL); |
| 672 | if (!con) | 670 | if (!con) |
| 673 | return length; | 671 | return length; |
| 674 | 672 | ||
| 675 | user = kzalloc(size+1, GFP_KERNEL); | 673 | user = kzalloc(size + 1, GFP_KERNEL); |
| 676 | if (!user) | 674 | if (!user) |
| 677 | goto out; | 675 | goto out; |
| 678 | 676 | ||
| @@ -680,7 +678,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
| 680 | if (sscanf(buf, "%s %s", con, user) != 2) | 678 | if (sscanf(buf, "%s %s", con, user) != 2) |
| 681 | goto out2; | 679 | goto out2; |
| 682 | 680 | ||
| 683 | length = security_context_to_sid(con, strlen(con)+1, &sid); | 681 | length = security_context_to_sid(con, strlen(con) + 1, &sid); |
| 684 | if (length < 0) | 682 | if (length < 0) |
| 685 | goto out2; | 683 | goto out2; |
| 686 | 684 | ||
| @@ -729,11 +727,11 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
| 729 | return length; | 727 | return length; |
| 730 | 728 | ||
| 731 | length = -ENOMEM; | 729 | length = -ENOMEM; |
| 732 | scon = kzalloc(size+1, GFP_KERNEL); | 730 | scon = kzalloc(size + 1, GFP_KERNEL); |
| 733 | if (!scon) | 731 | if (!scon) |
| 734 | return length; | 732 | return length; |
| 735 | 733 | ||
| 736 | tcon = kzalloc(size+1, GFP_KERNEL); | 734 | tcon = kzalloc(size + 1, GFP_KERNEL); |
| 737 | if (!tcon) | 735 | if (!tcon) |
| 738 | goto out; | 736 | goto out; |
| 739 | 737 | ||
| @@ -741,10 +739,10 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
| 741 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 739 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
| 742 | goto out2; | 740 | goto out2; |
| 743 | 741 | ||
| 744 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 742 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
| 745 | if (length < 0) | 743 | if (length < 0) |
| 746 | goto out2; | 744 | goto out2; |
| 747 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 745 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
| 748 | if (length < 0) | 746 | if (length < 0) |
| 749 | goto out2; | 747 | goto out2; |
| 750 | 748 | ||
| @@ -979,6 +977,8 @@ static int sel_make_bools(void) | |||
| 979 | u32 sid; | 977 | u32 sid; |
| 980 | 978 | ||
| 981 | /* remove any existing files */ | 979 | /* remove any existing files */ |
| 980 | for (i = 0; i < bool_num; i++) | ||
| 981 | kfree(bool_pending_names[i]); | ||
| 982 | kfree(bool_pending_names); | 982 | kfree(bool_pending_names); |
| 983 | kfree(bool_pending_values); | 983 | kfree(bool_pending_values); |
| 984 | bool_pending_names = NULL; | 984 | bool_pending_names = NULL; |
| @@ -1401,7 +1401,7 @@ static int sel_make_perm_files(char *objclass, int classvalue, | |||
| 1401 | } | 1401 | } |
| 1402 | inode->i_fop = &sel_perm_ops; | 1402 | inode->i_fop = &sel_perm_ops; |
| 1403 | /* i+1 since perm values are 1-indexed */ | 1403 | /* i+1 since perm values are 1-indexed */ |
| 1404 | inode->i_ino = sel_perm_to_ino(classvalue, i+1); | 1404 | inode->i_ino = sel_perm_to_ino(classvalue, i + 1); |
| 1405 | d_add(dentry, inode); | 1405 | d_add(dentry, inode); |
| 1406 | } | 1406 | } |
| 1407 | 1407 | ||
| @@ -1489,7 +1489,7 @@ static int sel_make_classes(void) | |||
| 1489 | goto out; | 1489 | goto out; |
| 1490 | 1490 | ||
| 1491 | /* +2 since classes are 1-indexed */ | 1491 | /* +2 since classes are 1-indexed */ |
| 1492 | last_class_ino = sel_class_to_ino(nclasses+2); | 1492 | last_class_ino = sel_class_to_ino(nclasses + 2); |
| 1493 | 1493 | ||
| 1494 | for (i = 0; i < nclasses; i++) { | 1494 | for (i = 0; i < nclasses; i++) { |
| 1495 | struct dentry *class_name_dir; | 1495 | struct dentry *class_name_dir; |
| @@ -1506,7 +1506,7 @@ static int sel_make_classes(void) | |||
| 1506 | goto out1; | 1506 | goto out1; |
| 1507 | 1507 | ||
| 1508 | /* i+1 since class values are 1-indexed */ | 1508 | /* i+1 since class values are 1-indexed */ |
| 1509 | rc = sel_make_class_dir_entries(classes[i], i+1, | 1509 | rc = sel_make_class_dir_entries(classes[i], i + 1, |
| 1510 | class_name_dir); | 1510 | class_name_dir); |
| 1511 | if (rc) | 1511 | if (rc) |
| 1512 | goto out1; | 1512 | goto out1; |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 8da6a8428086..cd4f734e2749 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
| @@ -82,7 +82,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified | |||
| 82 | void avtab_cache_init(void); | 82 | void avtab_cache_init(void); |
| 83 | void avtab_cache_destroy(void); | 83 | void avtab_cache_destroy(void); |
| 84 | 84 | ||
| 85 | #define MAX_AVTAB_HASH_BITS 13 | 85 | #define MAX_AVTAB_HASH_BITS 11 |
| 86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) | 86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) |
| 87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) | 87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) |
| 88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS | 88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS |
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index d9dd7a2f6a8a..45e8fb0515f8 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h | |||
| @@ -41,9 +41,6 @@ static inline int mls_context_cpy(struct context *dst, struct context *src) | |||
| 41 | { | 41 | { |
| 42 | int rc; | 42 | int rc; |
| 43 | 43 | ||
| 44 | if (!selinux_mls_enabled) | ||
| 45 | return 0; | ||
| 46 | |||
| 47 | dst->range.level[0].sens = src->range.level[0].sens; | 44 | dst->range.level[0].sens = src->range.level[0].sens; |
| 48 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); | 45 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); |
| 49 | if (rc) | 46 | if (rc) |
| @@ -64,9 +61,6 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src) | |||
| 64 | { | 61 | { |
| 65 | int rc; | 62 | int rc; |
| 66 | 63 | ||
| 67 | if (!selinux_mls_enabled) | ||
| 68 | return 0; | ||
| 69 | |||
| 70 | dst->range.level[0].sens = src->range.level[0].sens; | 64 | dst->range.level[0].sens = src->range.level[0].sens; |
| 71 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); | 65 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); |
| 72 | if (rc) | 66 | if (rc) |
| @@ -82,9 +76,6 @@ out: | |||
| 82 | 76 | ||
| 83 | static inline int mls_context_cmp(struct context *c1, struct context *c2) | 77 | static inline int mls_context_cmp(struct context *c1, struct context *c2) |
| 84 | { | 78 | { |
| 85 | if (!selinux_mls_enabled) | ||
| 86 | return 1; | ||
| 87 | |||
| 88 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && | 79 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && |
| 89 | ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && | 80 | ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && |
| 90 | (c1->range.level[1].sens == c2->range.level[1].sens) && | 81 | (c1->range.level[1].sens == c2->range.level[1].sens) && |
| @@ -93,9 +84,6 @@ static inline int mls_context_cmp(struct context *c1, struct context *c2) | |||
| 93 | 84 | ||
| 94 | static inline void mls_context_destroy(struct context *c) | 85 | static inline void mls_context_destroy(struct context *c) |
| 95 | { | 86 | { |
| 96 | if (!selinux_mls_enabled) | ||
| 97 | return; | ||
| 98 | |||
| 99 | ebitmap_destroy(&c->range.level[0].cat); | 87 | ebitmap_destroy(&c->range.level[0].cat); |
| 100 | ebitmap_destroy(&c->range.level[1].cat); | 88 | ebitmap_destroy(&c->range.level[1].cat); |
| 101 | mls_context_init(c); | 89 | mls_context_init(c); |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 68c7348d1acc..04b6145d767f 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
| @@ -128,7 +128,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, | |||
| 128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; | 128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; |
| 129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; | 129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; |
| 130 | c_iter->bitmap[cmap_idx] | 130 | c_iter->bitmap[cmap_idx] |
| 131 | |= e_iter->maps[cmap_idx] << cmap_sft; | 131 | |= e_iter->maps[i] << cmap_sft; |
| 132 | } | 132 | } |
| 133 | e_iter = e_iter->next; | 133 | e_iter = e_iter->next; |
| 134 | } | 134 | } |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 3f2b2706b5bb..b4eff7a60c50 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
| @@ -39,7 +39,7 @@ int mls_compute_context_len(struct context *context) | |||
| 39 | struct ebitmap *e; | 39 | struct ebitmap *e; |
| 40 | struct ebitmap_node *node; | 40 | struct ebitmap_node *node; |
| 41 | 41 | ||
| 42 | if (!selinux_mls_enabled) | 42 | if (!policydb.mls_enabled) |
| 43 | return 0; | 43 | return 0; |
| 44 | 44 | ||
| 45 | len = 1; /* for the beginning ":" */ | 45 | len = 1; /* for the beginning ":" */ |
| @@ -93,7 +93,7 @@ void mls_sid_to_context(struct context *context, | |||
| 93 | struct ebitmap *e; | 93 | struct ebitmap *e; |
| 94 | struct ebitmap_node *node; | 94 | struct ebitmap_node *node; |
| 95 | 95 | ||
| 96 | if (!selinux_mls_enabled) | 96 | if (!policydb.mls_enabled) |
| 97 | return; | 97 | return; |
| 98 | 98 | ||
| 99 | scontextp = *scontext; | 99 | scontextp = *scontext; |
| @@ -200,7 +200,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
| 200 | { | 200 | { |
| 201 | struct user_datum *usrdatum; | 201 | struct user_datum *usrdatum; |
| 202 | 202 | ||
| 203 | if (!selinux_mls_enabled) | 203 | if (!p->mls_enabled) |
| 204 | return 1; | 204 | return 1; |
| 205 | 205 | ||
| 206 | if (!mls_range_isvalid(p, &c->range)) | 206 | if (!mls_range_isvalid(p, &c->range)) |
| @@ -253,9 +253,9 @@ int mls_context_to_sid(struct policydb *pol, | |||
| 253 | struct cat_datum *catdatum, *rngdatum; | 253 | struct cat_datum *catdatum, *rngdatum; |
| 254 | int l, rc = -EINVAL; | 254 | int l, rc = -EINVAL; |
| 255 | 255 | ||
| 256 | if (!selinux_mls_enabled) { | 256 | if (!pol->mls_enabled) { |
| 257 | if (def_sid != SECSID_NULL && oldc) | 257 | if (def_sid != SECSID_NULL && oldc) |
| 258 | *scontext += strlen(*scontext)+1; | 258 | *scontext += strlen(*scontext) + 1; |
| 259 | return 0; | 259 | return 0; |
| 260 | } | 260 | } |
| 261 | 261 | ||
| @@ -387,7 +387,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
| 387 | char *tmpstr, *freestr; | 387 | char *tmpstr, *freestr; |
| 388 | int rc; | 388 | int rc; |
| 389 | 389 | ||
| 390 | if (!selinux_mls_enabled) | 390 | if (!policydb.mls_enabled) |
| 391 | return -EINVAL; | 391 | return -EINVAL; |
| 392 | 392 | ||
| 393 | /* we need freestr because mls_context_to_sid will change | 393 | /* we need freestr because mls_context_to_sid will change |
| @@ -407,7 +407,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
| 407 | /* | 407 | /* |
| 408 | * Copies the MLS range `range' into `context'. | 408 | * Copies the MLS range `range' into `context'. |
| 409 | */ | 409 | */ |
| 410 | static inline int mls_range_set(struct context *context, | 410 | int mls_range_set(struct context *context, |
| 411 | struct mls_range *range) | 411 | struct mls_range *range) |
| 412 | { | 412 | { |
| 413 | int l, rc = 0; | 413 | int l, rc = 0; |
| @@ -427,7 +427,7 @@ static inline int mls_range_set(struct context *context, | |||
| 427 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, | 427 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, |
| 428 | struct context *usercon) | 428 | struct context *usercon) |
| 429 | { | 429 | { |
| 430 | if (selinux_mls_enabled) { | 430 | if (policydb.mls_enabled) { |
| 431 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); | 431 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); |
| 432 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); | 432 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); |
| 433 | struct mls_level *user_low = &(user->range.level[0]); | 433 | struct mls_level *user_low = &(user->range.level[0]); |
| @@ -477,7 +477,7 @@ int mls_convert_context(struct policydb *oldp, | |||
| 477 | struct ebitmap_node *node; | 477 | struct ebitmap_node *node; |
| 478 | int l, i; | 478 | int l, i; |
| 479 | 479 | ||
| 480 | if (!selinux_mls_enabled) | 480 | if (!policydb.mls_enabled) |
| 481 | return 0; | 481 | return 0; |
| 482 | 482 | ||
| 483 | for (l = 0; l < 2; l++) { | 483 | for (l = 0; l < 2; l++) { |
| @@ -513,23 +513,21 @@ int mls_compute_sid(struct context *scontext, | |||
| 513 | u32 specified, | 513 | u32 specified, |
| 514 | struct context *newcontext) | 514 | struct context *newcontext) |
| 515 | { | 515 | { |
| 516 | struct range_trans *rtr; | 516 | struct range_trans rtr; |
| 517 | struct mls_range *r; | ||
| 517 | 518 | ||
| 518 | if (!selinux_mls_enabled) | 519 | if (!policydb.mls_enabled) |
| 519 | return 0; | 520 | return 0; |
| 520 | 521 | ||
| 521 | switch (specified) { | 522 | switch (specified) { |
| 522 | case AVTAB_TRANSITION: | 523 | case AVTAB_TRANSITION: |
| 523 | /* Look for a range transition rule. */ | 524 | /* Look for a range transition rule. */ |
| 524 | for (rtr = policydb.range_tr; rtr; rtr = rtr->next) { | 525 | rtr.source_type = scontext->type; |
| 525 | if (rtr->source_type == scontext->type && | 526 | rtr.target_type = tcontext->type; |
| 526 | rtr->target_type == tcontext->type && | 527 | rtr.target_class = tclass; |
| 527 | rtr->target_class == tclass) { | 528 | r = hashtab_search(policydb.range_tr, &rtr); |
| 528 | /* Set the range from the rule */ | 529 | if (r) |
| 529 | return mls_range_set(newcontext, | 530 | return mls_range_set(newcontext, r); |
| 530 | &rtr->target_range); | ||
| 531 | } | ||
| 532 | } | ||
| 533 | /* Fallthrough */ | 531 | /* Fallthrough */ |
| 534 | case AVTAB_CHANGE: | 532 | case AVTAB_CHANGE: |
| 535 | if (tclass == policydb.process_class) | 533 | if (tclass == policydb.process_class) |
| @@ -541,8 +539,8 @@ int mls_compute_sid(struct context *scontext, | |||
| 541 | case AVTAB_MEMBER: | 539 | case AVTAB_MEMBER: |
| 542 | /* Use the process effective MLS attributes. */ | 540 | /* Use the process effective MLS attributes. */ |
| 543 | return mls_context_cpy_low(newcontext, scontext); | 541 | return mls_context_cpy_low(newcontext, scontext); |
| 544 | default: | 542 | |
| 545 | return -EINVAL; | 543 | /* fall through */ |
| 546 | } | 544 | } |
| 547 | return -EINVAL; | 545 | return -EINVAL; |
| 548 | } | 546 | } |
| @@ -561,7 +559,7 @@ int mls_compute_sid(struct context *scontext, | |||
| 561 | void mls_export_netlbl_lvl(struct context *context, | 559 | void mls_export_netlbl_lvl(struct context *context, |
| 562 | struct netlbl_lsm_secattr *secattr) | 560 | struct netlbl_lsm_secattr *secattr) |
| 563 | { | 561 | { |
| 564 | if (!selinux_mls_enabled) | 562 | if (!policydb.mls_enabled) |
| 565 | return; | 563 | return; |
| 566 | 564 | ||
| 567 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; | 565 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; |
| @@ -581,7 +579,7 @@ void mls_export_netlbl_lvl(struct context *context, | |||
| 581 | void mls_import_netlbl_lvl(struct context *context, | 579 | void mls_import_netlbl_lvl(struct context *context, |
| 582 | struct netlbl_lsm_secattr *secattr) | 580 | struct netlbl_lsm_secattr *secattr) |
| 583 | { | 581 | { |
| 584 | if (!selinux_mls_enabled) | 582 | if (!policydb.mls_enabled) |
| 585 | return; | 583 | return; |
| 586 | 584 | ||
| 587 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; | 585 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; |
| @@ -603,7 +601,7 @@ int mls_export_netlbl_cat(struct context *context, | |||
| 603 | { | 601 | { |
| 604 | int rc; | 602 | int rc; |
| 605 | 603 | ||
| 606 | if (!selinux_mls_enabled) | 604 | if (!policydb.mls_enabled) |
| 607 | return 0; | 605 | return 0; |
| 608 | 606 | ||
| 609 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, | 607 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, |
| @@ -631,7 +629,7 @@ int mls_import_netlbl_cat(struct context *context, | |||
| 631 | { | 629 | { |
| 632 | int rc; | 630 | int rc; |
| 633 | 631 | ||
| 634 | if (!selinux_mls_enabled) | 632 | if (!policydb.mls_enabled) |
| 635 | return 0; | 633 | return 0; |
| 636 | 634 | ||
| 637 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, | 635 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 1276715aaa8b..cd9152632e54 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
| @@ -39,6 +39,8 @@ int mls_context_to_sid(struct policydb *p, | |||
| 39 | 39 | ||
| 40 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); | 40 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); |
| 41 | 41 | ||
| 42 | int mls_range_set(struct context *context, struct mls_range *range); | ||
| 43 | |||
| 42 | int mls_convert_context(struct policydb *oldp, | 44 | int mls_convert_context(struct policydb *oldp, |
| 43 | struct policydb *newp, | 45 | struct policydb *newp, |
| 44 | struct context *context); | 46 | struct context *context); |
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h index b6e943a21061..03bed52a8052 100644 --- a/security/selinux/ss/mls_types.h +++ b/security/selinux/ss/mls_types.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #define _SS_MLS_TYPES_H_ | 15 | #define _SS_MLS_TYPES_H_ |
| 16 | 16 | ||
| 17 | #include "security.h" | 17 | #include "security.h" |
| 18 | #include "ebitmap.h" | ||
| 18 | 19 | ||
| 19 | struct mls_level { | 20 | struct mls_level { |
| 20 | u32 sens; /* sensitivity */ | 21 | u32 sens; /* sensitivity */ |
| @@ -27,18 +28,12 @@ struct mls_range { | |||
| 27 | 28 | ||
| 28 | static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) | 29 | static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) |
| 29 | { | 30 | { |
| 30 | if (!selinux_mls_enabled) | ||
| 31 | return 1; | ||
| 32 | |||
| 33 | return ((l1->sens == l2->sens) && | 31 | return ((l1->sens == l2->sens) && |
| 34 | ebitmap_cmp(&l1->cat, &l2->cat)); | 32 | ebitmap_cmp(&l1->cat, &l2->cat)); |
| 35 | } | 33 | } |
| 36 | 34 | ||
| 37 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) | 35 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) |
| 38 | { | 36 | { |
| 39 | if (!selinux_mls_enabled) | ||
| 40 | return 1; | ||
| 41 | |||
| 42 | return ((l1->sens >= l2->sens) && | 37 | return ((l1->sens >= l2->sens) && |
| 43 | ebitmap_contains(&l1->cat, &l2->cat)); | 38 | ebitmap_contains(&l1->cat, &l2->cat)); |
| 44 | } | 39 | } |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index f03667213ea8..c57802a164d5 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | #define _DEBUG_HASHES | 40 | #define _DEBUG_HASHES |
| 41 | 41 | ||
| 42 | #ifdef DEBUG_HASHES | 42 | #ifdef DEBUG_HASHES |
| 43 | static char *symtab_name[SYM_NUM] = { | 43 | static const char *symtab_name[SYM_NUM] = { |
| 44 | "common prefixes", | 44 | "common prefixes", |
| 45 | "classes", | 45 | "classes", |
| 46 | "roles", | 46 | "roles", |
| @@ -52,8 +52,6 @@ static char *symtab_name[SYM_NUM] = { | |||
| 52 | }; | 52 | }; |
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | int selinux_mls_enabled; | ||
| 56 | |||
| 57 | static unsigned int symtab_sizes[SYM_NUM] = { | 55 | static unsigned int symtab_sizes[SYM_NUM] = { |
| 58 | 2, | 56 | 2, |
| 59 | 32, | 57 | 32, |
| @@ -158,12 +156,11 @@ static int roles_init(struct policydb *p) | |||
| 158 | rc = -EINVAL; | 156 | rc = -EINVAL; |
| 159 | goto out_free_role; | 157 | goto out_free_role; |
| 160 | } | 158 | } |
| 161 | key = kmalloc(strlen(OBJECT_R)+1, GFP_KERNEL); | 159 | key = kstrdup(OBJECT_R, GFP_KERNEL); |
| 162 | if (!key) { | 160 | if (!key) { |
| 163 | rc = -ENOMEM; | 161 | rc = -ENOMEM; |
| 164 | goto out_free_role; | 162 | goto out_free_role; |
| 165 | } | 163 | } |
| 166 | strcpy(key, OBJECT_R); | ||
| 167 | rc = hashtab_insert(p->p_roles.table, key, role); | 164 | rc = hashtab_insert(p->p_roles.table, key, role); |
| 168 | if (rc) | 165 | if (rc) |
| 169 | goto out_free_key; | 166 | goto out_free_key; |
| @@ -177,6 +174,21 @@ out_free_role: | |||
| 177 | goto out; | 174 | goto out; |
| 178 | } | 175 | } |
| 179 | 176 | ||
| 177 | static u32 rangetr_hash(struct hashtab *h, const void *k) | ||
| 178 | { | ||
| 179 | const struct range_trans *key = k; | ||
| 180 | return (key->source_type + (key->target_type << 3) + | ||
| 181 | (key->target_class << 5)) & (h->size - 1); | ||
| 182 | } | ||
| 183 | |||
| 184 | static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2) | ||
| 185 | { | ||
| 186 | const struct range_trans *key1 = k1, *key2 = k2; | ||
| 187 | return (key1->source_type != key2->source_type || | ||
| 188 | key1->target_type != key2->target_type || | ||
| 189 | key1->target_class != key2->target_class); | ||
| 190 | } | ||
| 191 | |||
| 180 | /* | 192 | /* |
| 181 | * Initialize a policy database structure. | 193 | * Initialize a policy database structure. |
| 182 | */ | 194 | */ |
| @@ -204,6 +216,10 @@ static int policydb_init(struct policydb *p) | |||
| 204 | if (rc) | 216 | if (rc) |
| 205 | goto out_free_symtab; | 217 | goto out_free_symtab; |
| 206 | 218 | ||
| 219 | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); | ||
| 220 | if (!p->range_tr) | ||
| 221 | goto out_free_symtab; | ||
| 222 | |||
| 207 | ebitmap_init(&p->policycaps); | 223 | ebitmap_init(&p->policycaps); |
| 208 | ebitmap_init(&p->permissive_map); | 224 | ebitmap_init(&p->permissive_map); |
| 209 | 225 | ||
| @@ -408,6 +424,20 @@ static void symtab_hash_eval(struct symtab *s) | |||
| 408 | info.slots_used, h->size, info.max_chain_len); | 424 | info.slots_used, h->size, info.max_chain_len); |
| 409 | } | 425 | } |
| 410 | } | 426 | } |
| 427 | |||
| 428 | static void rangetr_hash_eval(struct hashtab *h) | ||
| 429 | { | ||
| 430 | struct hashtab_info info; | ||
| 431 | |||
| 432 | hashtab_stat(h, &info); | ||
| 433 | printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, " | ||
| 434 | "longest chain length %d\n", h->nel, | ||
| 435 | info.slots_used, h->size, info.max_chain_len); | ||
| 436 | } | ||
| 437 | #else | ||
| 438 | static inline void rangetr_hash_eval(struct hashtab *h) | ||
| 439 | { | ||
| 440 | } | ||
| 411 | #endif | 441 | #endif |
| 412 | 442 | ||
| 413 | /* | 443 | /* |
| @@ -422,7 +452,7 @@ static int policydb_index_others(struct policydb *p) | |||
| 422 | 452 | ||
| 423 | printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", | 453 | printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", |
| 424 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); | 454 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); |
| 425 | if (selinux_mls_enabled) | 455 | if (p->mls_enabled) |
| 426 | printk(", %d sens, %d cats", p->p_levels.nprim, | 456 | printk(", %d sens, %d cats", p->p_levels.nprim, |
| 427 | p->p_cats.nprim); | 457 | p->p_cats.nprim); |
| 428 | printk("\n"); | 458 | printk("\n"); |
| @@ -612,6 +642,17 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = | |||
| 612 | cat_destroy, | 642 | cat_destroy, |
| 613 | }; | 643 | }; |
| 614 | 644 | ||
| 645 | static int range_tr_destroy(void *key, void *datum, void *p) | ||
| 646 | { | ||
| 647 | struct mls_range *rt = datum; | ||
| 648 | kfree(key); | ||
| 649 | ebitmap_destroy(&rt->level[0].cat); | ||
| 650 | ebitmap_destroy(&rt->level[1].cat); | ||
| 651 | kfree(datum); | ||
| 652 | cond_resched(); | ||
| 653 | return 0; | ||
| 654 | } | ||
| 655 | |||
| 615 | static void ocontext_destroy(struct ocontext *c, int i) | 656 | static void ocontext_destroy(struct ocontext *c, int i) |
| 616 | { | 657 | { |
| 617 | context_destroy(&c->context[0]); | 658 | context_destroy(&c->context[0]); |
| @@ -632,7 +673,6 @@ void policydb_destroy(struct policydb *p) | |||
| 632 | int i; | 673 | int i; |
| 633 | struct role_allow *ra, *lra = NULL; | 674 | struct role_allow *ra, *lra = NULL; |
| 634 | struct role_trans *tr, *ltr = NULL; | 675 | struct role_trans *tr, *ltr = NULL; |
| 635 | struct range_trans *rt, *lrt = NULL; | ||
| 636 | 676 | ||
| 637 | for (i = 0; i < SYM_NUM; i++) { | 677 | for (i = 0; i < SYM_NUM; i++) { |
| 638 | cond_resched(); | 678 | cond_resched(); |
| @@ -693,20 +733,8 @@ void policydb_destroy(struct policydb *p) | |||
| 693 | } | 733 | } |
| 694 | kfree(lra); | 734 | kfree(lra); |
| 695 | 735 | ||
| 696 | for (rt = p->range_tr; rt; rt = rt->next) { | 736 | hashtab_map(p->range_tr, range_tr_destroy, NULL); |
| 697 | cond_resched(); | 737 | hashtab_destroy(p->range_tr); |
| 698 | if (lrt) { | ||
| 699 | ebitmap_destroy(&lrt->target_range.level[0].cat); | ||
| 700 | ebitmap_destroy(&lrt->target_range.level[1].cat); | ||
| 701 | kfree(lrt); | ||
| 702 | } | ||
| 703 | lrt = rt; | ||
| 704 | } | ||
| 705 | if (lrt) { | ||
| 706 | ebitmap_destroy(&lrt->target_range.level[0].cat); | ||
| 707 | ebitmap_destroy(&lrt->target_range.level[1].cat); | ||
| 708 | kfree(lrt); | ||
| 709 | } | ||
| 710 | 738 | ||
| 711 | if (p->type_attr_map) { | 739 | if (p->type_attr_map) { |
| 712 | for (i = 0; i < p->p_types.nprim; i++) | 740 | for (i = 0; i < p->p_types.nprim; i++) |
| @@ -1686,12 +1714,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1686 | int i, j, rc; | 1714 | int i, j, rc; |
| 1687 | __le32 buf[4]; | 1715 | __le32 buf[4]; |
| 1688 | u32 nodebuf[8]; | 1716 | u32 nodebuf[8]; |
| 1689 | u32 len, len2, config, nprim, nel, nel2; | 1717 | u32 len, len2, nprim, nel, nel2; |
| 1690 | char *policydb_str; | 1718 | char *policydb_str; |
| 1691 | struct policydb_compat_info *info; | 1719 | struct policydb_compat_info *info; |
| 1692 | struct range_trans *rt, *lrt; | 1720 | struct range_trans *rt; |
| 1693 | 1721 | struct mls_range *r; | |
| 1694 | config = 0; | ||
| 1695 | 1722 | ||
| 1696 | rc = policydb_init(p); | 1723 | rc = policydb_init(p); |
| 1697 | if (rc) | 1724 | if (rc) |
| @@ -1740,7 +1767,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1740 | kfree(policydb_str); | 1767 | kfree(policydb_str); |
| 1741 | policydb_str = NULL; | 1768 | policydb_str = NULL; |
| 1742 | 1769 | ||
| 1743 | /* Read the version, config, and table sizes. */ | 1770 | /* Read the version and table sizes. */ |
| 1744 | rc = next_entry(buf, fp, sizeof(u32)*4); | 1771 | rc = next_entry(buf, fp, sizeof(u32)*4); |
| 1745 | if (rc < 0) | 1772 | if (rc < 0) |
| 1746 | goto bad; | 1773 | goto bad; |
| @@ -1755,13 +1782,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1755 | } | 1782 | } |
| 1756 | 1783 | ||
| 1757 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { | 1784 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
| 1758 | if (ss_initialized && !selinux_mls_enabled) { | 1785 | p->mls_enabled = 1; |
| 1759 | printk(KERN_ERR "SELinux: Cannot switch between non-MLS" | ||
| 1760 | " and MLS policies\n"); | ||
| 1761 | goto bad; | ||
| 1762 | } | ||
| 1763 | selinux_mls_enabled = 1; | ||
| 1764 | config |= POLICYDB_CONFIG_MLS; | ||
| 1765 | 1786 | ||
| 1766 | if (p->policyvers < POLICYDB_VERSION_MLS) { | 1787 | if (p->policyvers < POLICYDB_VERSION_MLS) { |
| 1767 | printk(KERN_ERR "SELinux: security policydb version %d " | 1788 | printk(KERN_ERR "SELinux: security policydb version %d " |
| @@ -1769,12 +1790,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1769 | p->policyvers); | 1790 | p->policyvers); |
| 1770 | goto bad; | 1791 | goto bad; |
| 1771 | } | 1792 | } |
| 1772 | } else { | ||
| 1773 | if (ss_initialized && selinux_mls_enabled) { | ||
| 1774 | printk(KERN_ERR "SELinux: Cannot switch between MLS and" | ||
| 1775 | " non-MLS policies\n"); | ||
| 1776 | goto bad; | ||
| 1777 | } | ||
| 1778 | } | 1793 | } |
| 1779 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); | 1794 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); |
| 1780 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); | 1795 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); |
| @@ -2122,47 +2137,64 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 2122 | if (rc < 0) | 2137 | if (rc < 0) |
| 2123 | goto bad; | 2138 | goto bad; |
| 2124 | nel = le32_to_cpu(buf[0]); | 2139 | nel = le32_to_cpu(buf[0]); |
| 2125 | lrt = NULL; | ||
| 2126 | for (i = 0; i < nel; i++) { | 2140 | for (i = 0; i < nel; i++) { |
| 2127 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | 2141 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); |
| 2128 | if (!rt) { | 2142 | if (!rt) { |
| 2129 | rc = -ENOMEM; | 2143 | rc = -ENOMEM; |
| 2130 | goto bad; | 2144 | goto bad; |
| 2131 | } | 2145 | } |
| 2132 | if (lrt) | ||
| 2133 | lrt->next = rt; | ||
| 2134 | else | ||
| 2135 | p->range_tr = rt; | ||
| 2136 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | 2146 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); |
| 2137 | if (rc < 0) | 2147 | if (rc < 0) { |
| 2148 | kfree(rt); | ||
| 2138 | goto bad; | 2149 | goto bad; |
| 2150 | } | ||
| 2139 | rt->source_type = le32_to_cpu(buf[0]); | 2151 | rt->source_type = le32_to_cpu(buf[0]); |
| 2140 | rt->target_type = le32_to_cpu(buf[1]); | 2152 | rt->target_type = le32_to_cpu(buf[1]); |
| 2141 | if (new_rangetr) { | 2153 | if (new_rangetr) { |
| 2142 | rc = next_entry(buf, fp, sizeof(u32)); | 2154 | rc = next_entry(buf, fp, sizeof(u32)); |
| 2143 | if (rc < 0) | 2155 | if (rc < 0) { |
| 2156 | kfree(rt); | ||
| 2144 | goto bad; | 2157 | goto bad; |
| 2158 | } | ||
| 2145 | rt->target_class = le32_to_cpu(buf[0]); | 2159 | rt->target_class = le32_to_cpu(buf[0]); |
| 2146 | } else | 2160 | } else |
| 2147 | rt->target_class = p->process_class; | 2161 | rt->target_class = p->process_class; |
| 2148 | if (!policydb_type_isvalid(p, rt->source_type) || | 2162 | if (!policydb_type_isvalid(p, rt->source_type) || |
| 2149 | !policydb_type_isvalid(p, rt->target_type) || | 2163 | !policydb_type_isvalid(p, rt->target_type) || |
| 2150 | !policydb_class_isvalid(p, rt->target_class)) { | 2164 | !policydb_class_isvalid(p, rt->target_class)) { |
| 2165 | kfree(rt); | ||
| 2151 | rc = -EINVAL; | 2166 | rc = -EINVAL; |
| 2152 | goto bad; | 2167 | goto bad; |
| 2153 | } | 2168 | } |
| 2154 | rc = mls_read_range_helper(&rt->target_range, fp); | 2169 | r = kzalloc(sizeof(*r), GFP_KERNEL); |
| 2155 | if (rc) | 2170 | if (!r) { |
| 2171 | kfree(rt); | ||
| 2172 | rc = -ENOMEM; | ||
| 2156 | goto bad; | 2173 | goto bad; |
| 2157 | if (!mls_range_isvalid(p, &rt->target_range)) { | 2174 | } |
| 2175 | rc = mls_read_range_helper(r, fp); | ||
| 2176 | if (rc) { | ||
| 2177 | kfree(rt); | ||
| 2178 | kfree(r); | ||
| 2179 | goto bad; | ||
| 2180 | } | ||
| 2181 | if (!mls_range_isvalid(p, r)) { | ||
| 2158 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | 2182 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); |
| 2183 | kfree(rt); | ||
| 2184 | kfree(r); | ||
| 2185 | goto bad; | ||
| 2186 | } | ||
| 2187 | rc = hashtab_insert(p->range_tr, rt, r); | ||
| 2188 | if (rc) { | ||
| 2189 | kfree(rt); | ||
| 2190 | kfree(r); | ||
| 2159 | goto bad; | 2191 | goto bad; |
| 2160 | } | 2192 | } |
| 2161 | lrt = rt; | ||
| 2162 | } | 2193 | } |
| 2194 | rangetr_hash_eval(p->range_tr); | ||
| 2163 | } | 2195 | } |
| 2164 | 2196 | ||
| 2165 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | 2197 | p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL); |
| 2166 | if (!p->type_attr_map) | 2198 | if (!p->type_attr_map) |
| 2167 | goto bad; | 2199 | goto bad; |
| 2168 | 2200 | ||
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index cdcc5700946f..26d9adf8542b 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
| @@ -27,6 +27,8 @@ | |||
| 27 | #include "symtab.h" | 27 | #include "symtab.h" |
| 28 | #include "avtab.h" | 28 | #include "avtab.h" |
| 29 | #include "sidtab.h" | 29 | #include "sidtab.h" |
| 30 | #include "ebitmap.h" | ||
| 31 | #include "mls_types.h" | ||
| 30 | #include "context.h" | 32 | #include "context.h" |
| 31 | #include "constraint.h" | 33 | #include "constraint.h" |
| 32 | 34 | ||
| @@ -113,8 +115,6 @@ struct range_trans { | |||
| 113 | u32 source_type; | 115 | u32 source_type; |
| 114 | u32 target_type; | 116 | u32 target_type; |
| 115 | u32 target_class; | 117 | u32 target_class; |
| 116 | struct mls_range target_range; | ||
| 117 | struct range_trans *next; | ||
| 118 | }; | 118 | }; |
| 119 | 119 | ||
| 120 | /* Boolean data type */ | 120 | /* Boolean data type */ |
| @@ -187,6 +187,8 @@ struct genfs { | |||
| 187 | 187 | ||
| 188 | /* The policy database */ | 188 | /* The policy database */ |
| 189 | struct policydb { | 189 | struct policydb { |
| 190 | int mls_enabled; | ||
| 191 | |||
| 190 | /* symbol tables */ | 192 | /* symbol tables */ |
| 191 | struct symtab symtab[SYM_NUM]; | 193 | struct symtab symtab[SYM_NUM]; |
| 192 | #define p_commons symtab[SYM_COMMONS] | 194 | #define p_commons symtab[SYM_COMMONS] |
| @@ -240,8 +242,8 @@ struct policydb { | |||
| 240 | fixed labeling behavior. */ | 242 | fixed labeling behavior. */ |
| 241 | struct genfs *genfs; | 243 | struct genfs *genfs; |
| 242 | 244 | ||
| 243 | /* range transitions */ | 245 | /* range transitions table (range_trans_key -> mls_range) */ |
| 244 | struct range_trans *range_tr; | 246 | struct hashtab *range_tr; |
| 245 | 247 | ||
| 246 | /* type -> attribute reverse mapping */ | 248 | /* type -> attribute reverse mapping */ |
| 247 | struct ebitmap *type_attr_map; | 249 | struct ebitmap *type_attr_map; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b3efae204ac7..1de60ce90d9a 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -26,6 +26,10 @@ | |||
| 26 | * | 26 | * |
| 27 | * Added support for bounds domain and audit messaged on masked permissions | 27 | * Added support for bounds domain and audit messaged on masked permissions |
| 28 | * | 28 | * |
| 29 | * Updated: Guido Trentalancia <guido@trentalancia.com> | ||
| 30 | * | ||
| 31 | * Added support for runtime switching of the policy type | ||
| 32 | * | ||
| 29 | * Copyright (C) 2008, 2009 NEC Corporation | 33 | * Copyright (C) 2008, 2009 NEC Corporation |
| 30 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 34 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. |
| 31 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 35 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
| @@ -87,11 +91,10 @@ static u32 latest_granting; | |||
| 87 | static int context_struct_to_string(struct context *context, char **scontext, | 91 | static int context_struct_to_string(struct context *context, char **scontext, |
| 88 | u32 *scontext_len); | 92 | u32 *scontext_len); |
| 89 | 93 | ||
| 90 | static int context_struct_compute_av(struct context *scontext, | 94 | static void context_struct_compute_av(struct context *scontext, |
| 91 | struct context *tcontext, | 95 | struct context *tcontext, |
| 92 | u16 tclass, | 96 | u16 tclass, |
| 93 | u32 requested, | 97 | struct av_decision *avd); |
| 94 | struct av_decision *avd); | ||
| 95 | 98 | ||
| 96 | struct selinux_mapping { | 99 | struct selinux_mapping { |
| 97 | u16 value; /* policy value */ | 100 | u16 value; /* policy value */ |
| @@ -196,23 +199,6 @@ static u16 unmap_class(u16 tclass) | |||
| 196 | return tclass; | 199 | return tclass; |
| 197 | } | 200 | } |
| 198 | 201 | ||
| 199 | static u32 unmap_perm(u16 tclass, u32 tperm) | ||
| 200 | { | ||
| 201 | if (tclass < current_mapping_size) { | ||
| 202 | unsigned i; | ||
| 203 | u32 kperm = 0; | ||
| 204 | |||
| 205 | for (i = 0; i < current_mapping[tclass].num_perms; i++) | ||
| 206 | if (tperm & (1<<i)) { | ||
| 207 | kperm |= current_mapping[tclass].perms[i]; | ||
| 208 | tperm &= ~(1<<i); | ||
| 209 | } | ||
| 210 | return kperm; | ||
| 211 | } | ||
| 212 | |||
| 213 | return tperm; | ||
| 214 | } | ||
| 215 | |||
| 216 | static void map_decision(u16 tclass, struct av_decision *avd, | 202 | static void map_decision(u16 tclass, struct av_decision *avd, |
| 217 | int allow_unknown) | 203 | int allow_unknown) |
| 218 | { | 204 | { |
| @@ -250,6 +236,10 @@ static void map_decision(u16 tclass, struct av_decision *avd, | |||
| 250 | } | 236 | } |
| 251 | } | 237 | } |
| 252 | 238 | ||
| 239 | int security_mls_enabled(void) | ||
| 240 | { | ||
| 241 | return policydb.mls_enabled; | ||
| 242 | } | ||
| 253 | 243 | ||
| 254 | /* | 244 | /* |
| 255 | * Return the boolean value of a constraint expression | 245 | * Return the boolean value of a constraint expression |
| @@ -284,15 +274,15 @@ static int constraint_expr_eval(struct context *scontext, | |||
| 284 | case CEXPR_AND: | 274 | case CEXPR_AND: |
| 285 | BUG_ON(sp < 1); | 275 | BUG_ON(sp < 1); |
| 286 | sp--; | 276 | sp--; |
| 287 | s[sp] &= s[sp+1]; | 277 | s[sp] &= s[sp + 1]; |
| 288 | break; | 278 | break; |
| 289 | case CEXPR_OR: | 279 | case CEXPR_OR: |
| 290 | BUG_ON(sp < 1); | 280 | BUG_ON(sp < 1); |
| 291 | sp--; | 281 | sp--; |
| 292 | s[sp] |= s[sp+1]; | 282 | s[sp] |= s[sp + 1]; |
| 293 | break; | 283 | break; |
| 294 | case CEXPR_ATTR: | 284 | case CEXPR_ATTR: |
| 295 | if (sp == (CEXPR_MAXDEPTH-1)) | 285 | if (sp == (CEXPR_MAXDEPTH - 1)) |
| 296 | return 0; | 286 | return 0; |
| 297 | switch (e->attr) { | 287 | switch (e->attr) { |
| 298 | case CEXPR_USER: | 288 | case CEXPR_USER: |
| @@ -465,7 +455,8 @@ static void security_dump_masked_av(struct context *scontext, | |||
| 465 | char *scontext_name = NULL; | 455 | char *scontext_name = NULL; |
| 466 | char *tcontext_name = NULL; | 456 | char *tcontext_name = NULL; |
| 467 | char *permission_names[32]; | 457 | char *permission_names[32]; |
| 468 | int index, length; | 458 | int index; |
| 459 | u32 length; | ||
| 469 | bool need_comma = false; | 460 | bool need_comma = false; |
| 470 | 461 | ||
| 471 | if (!permissions) | 462 | if (!permissions) |
| @@ -532,7 +523,6 @@ out: | |||
| 532 | static void type_attribute_bounds_av(struct context *scontext, | 523 | static void type_attribute_bounds_av(struct context *scontext, |
| 533 | struct context *tcontext, | 524 | struct context *tcontext, |
| 534 | u16 tclass, | 525 | u16 tclass, |
| 535 | u32 requested, | ||
| 536 | struct av_decision *avd) | 526 | struct av_decision *avd) |
| 537 | { | 527 | { |
| 538 | struct context lo_scontext; | 528 | struct context lo_scontext; |
| @@ -553,7 +543,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
| 553 | context_struct_compute_av(&lo_scontext, | 543 | context_struct_compute_av(&lo_scontext, |
| 554 | tcontext, | 544 | tcontext, |
| 555 | tclass, | 545 | tclass, |
| 556 | requested, | ||
| 557 | &lo_avd); | 546 | &lo_avd); |
| 558 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 547 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
| 559 | return; /* no masked permission */ | 548 | return; /* no masked permission */ |
| @@ -569,7 +558,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
| 569 | context_struct_compute_av(scontext, | 558 | context_struct_compute_av(scontext, |
| 570 | &lo_tcontext, | 559 | &lo_tcontext, |
| 571 | tclass, | 560 | tclass, |
| 572 | requested, | ||
| 573 | &lo_avd); | 561 | &lo_avd); |
| 574 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 562 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
| 575 | return; /* no masked permission */ | 563 | return; /* no masked permission */ |
| @@ -586,7 +574,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
| 586 | context_struct_compute_av(&lo_scontext, | 574 | context_struct_compute_av(&lo_scontext, |
| 587 | &lo_tcontext, | 575 | &lo_tcontext, |
| 588 | tclass, | 576 | tclass, |
| 589 | requested, | ||
| 590 | &lo_avd); | 577 | &lo_avd); |
| 591 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 578 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
| 592 | return; /* no masked permission */ | 579 | return; /* no masked permission */ |
| @@ -607,11 +594,10 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
| 607 | * Compute access vectors based on a context structure pair for | 594 | * Compute access vectors based on a context structure pair for |
| 608 | * the permissions in a particular class. | 595 | * the permissions in a particular class. |
| 609 | */ | 596 | */ |
| 610 | static int context_struct_compute_av(struct context *scontext, | 597 | static void context_struct_compute_av(struct context *scontext, |
| 611 | struct context *tcontext, | 598 | struct context *tcontext, |
| 612 | u16 tclass, | 599 | u16 tclass, |
| 613 | u32 requested, | 600 | struct av_decision *avd) |
| 614 | struct av_decision *avd) | ||
| 615 | { | 601 | { |
| 616 | struct constraint_node *constraint; | 602 | struct constraint_node *constraint; |
| 617 | struct role_allow *ra; | 603 | struct role_allow *ra; |
| @@ -622,19 +608,14 @@ static int context_struct_compute_av(struct context *scontext, | |||
| 622 | struct ebitmap_node *snode, *tnode; | 608 | struct ebitmap_node *snode, *tnode; |
| 623 | unsigned int i, j; | 609 | unsigned int i, j; |
| 624 | 610 | ||
| 625 | /* | ||
| 626 | * Initialize the access vectors to the default values. | ||
| 627 | */ | ||
| 628 | avd->allowed = 0; | 611 | avd->allowed = 0; |
| 629 | avd->auditallow = 0; | 612 | avd->auditallow = 0; |
| 630 | avd->auditdeny = 0xffffffff; | 613 | avd->auditdeny = 0xffffffff; |
| 631 | avd->seqno = latest_granting; | ||
| 632 | avd->flags = 0; | ||
| 633 | 614 | ||
| 634 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { | 615 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { |
| 635 | if (printk_ratelimit()) | 616 | if (printk_ratelimit()) |
| 636 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); | 617 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); |
| 637 | return -EINVAL; | 618 | return; |
| 638 | } | 619 | } |
| 639 | 620 | ||
| 640 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | 621 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; |
| @@ -705,9 +686,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
| 705 | * permission and notice it to userspace via audit. | 686 | * permission and notice it to userspace via audit. |
| 706 | */ | 687 | */ |
| 707 | type_attribute_bounds_av(scontext, tcontext, | 688 | type_attribute_bounds_av(scontext, tcontext, |
| 708 | tclass, requested, avd); | 689 | tclass, avd); |
| 709 | |||
| 710 | return 0; | ||
| 711 | } | 690 | } |
| 712 | 691 | ||
| 713 | static int security_validtrans_handle_fail(struct context *ocontext, | 692 | static int security_validtrans_handle_fail(struct context *ocontext, |
| @@ -864,7 +843,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
| 864 | if (rc) { | 843 | if (rc) { |
| 865 | char *old_name = NULL; | 844 | char *old_name = NULL; |
| 866 | char *new_name = NULL; | 845 | char *new_name = NULL; |
| 867 | int length; | 846 | u32 length; |
| 868 | 847 | ||
| 869 | if (!context_struct_to_string(old_context, | 848 | if (!context_struct_to_string(old_context, |
| 870 | &old_name, &length) && | 849 | &old_name, &length) && |
| @@ -886,110 +865,116 @@ out: | |||
| 886 | return rc; | 865 | return rc; |
| 887 | } | 866 | } |
| 888 | 867 | ||
| 889 | 868 | static void avd_init(struct av_decision *avd) | |
| 890 | static int security_compute_av_core(u32 ssid, | ||
| 891 | u32 tsid, | ||
| 892 | u16 tclass, | ||
| 893 | u32 requested, | ||
| 894 | struct av_decision *avd) | ||
| 895 | { | 869 | { |
| 896 | struct context *scontext = NULL, *tcontext = NULL; | 870 | avd->allowed = 0; |
| 897 | int rc = 0; | 871 | avd->auditallow = 0; |
| 898 | 872 | avd->auditdeny = 0xffffffff; | |
| 899 | scontext = sidtab_search(&sidtab, ssid); | 873 | avd->seqno = latest_granting; |
| 900 | if (!scontext) { | 874 | avd->flags = 0; |
| 901 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
| 902 | __func__, ssid); | ||
| 903 | return -EINVAL; | ||
| 904 | } | ||
| 905 | tcontext = sidtab_search(&sidtab, tsid); | ||
| 906 | if (!tcontext) { | ||
| 907 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
| 908 | __func__, tsid); | ||
| 909 | return -EINVAL; | ||
| 910 | } | ||
| 911 | |||
| 912 | rc = context_struct_compute_av(scontext, tcontext, tclass, | ||
| 913 | requested, avd); | ||
| 914 | |||
| 915 | /* permissive domain? */ | ||
| 916 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
| 917 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
| 918 | |||
| 919 | return rc; | ||
| 920 | } | 875 | } |
| 921 | 876 | ||
| 877 | |||
| 922 | /** | 878 | /** |
| 923 | * security_compute_av - Compute access vector decisions. | 879 | * security_compute_av - Compute access vector decisions. |
| 924 | * @ssid: source security identifier | 880 | * @ssid: source security identifier |
| 925 | * @tsid: target security identifier | 881 | * @tsid: target security identifier |
| 926 | * @tclass: target security class | 882 | * @tclass: target security class |
| 927 | * @requested: requested permissions | ||
| 928 | * @avd: access vector decisions | 883 | * @avd: access vector decisions |
| 929 | * | 884 | * |
| 930 | * Compute a set of access vector decisions based on the | 885 | * Compute a set of access vector decisions based on the |
| 931 | * SID pair (@ssid, @tsid) for the permissions in @tclass. | 886 | * SID pair (@ssid, @tsid) for the permissions in @tclass. |
| 932 | * Return -%EINVAL if any of the parameters are invalid or %0 | ||
| 933 | * if the access vector decisions were computed successfully. | ||
| 934 | */ | 887 | */ |
| 935 | int security_compute_av(u32 ssid, | 888 | void security_compute_av(u32 ssid, |
| 936 | u32 tsid, | 889 | u32 tsid, |
| 937 | u16 orig_tclass, | 890 | u16 orig_tclass, |
| 938 | u32 orig_requested, | 891 | struct av_decision *avd) |
| 939 | struct av_decision *avd) | ||
| 940 | { | 892 | { |
| 941 | u16 tclass; | 893 | u16 tclass; |
| 942 | u32 requested; | 894 | struct context *scontext = NULL, *tcontext = NULL; |
| 943 | int rc; | ||
| 944 | 895 | ||
| 945 | read_lock(&policy_rwlock); | 896 | read_lock(&policy_rwlock); |
| 946 | 897 | avd_init(avd); | |
| 947 | if (!ss_initialized) | 898 | if (!ss_initialized) |
| 948 | goto allow; | 899 | goto allow; |
| 949 | 900 | ||
| 950 | requested = unmap_perm(orig_tclass, orig_requested); | 901 | scontext = sidtab_search(&sidtab, ssid); |
| 902 | if (!scontext) { | ||
| 903 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
| 904 | __func__, ssid); | ||
| 905 | goto out; | ||
| 906 | } | ||
| 907 | |||
| 908 | /* permissive domain? */ | ||
| 909 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
| 910 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
| 911 | |||
| 912 | tcontext = sidtab_search(&sidtab, tsid); | ||
| 913 | if (!tcontext) { | ||
| 914 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
| 915 | __func__, tsid); | ||
| 916 | goto out; | ||
| 917 | } | ||
| 918 | |||
| 951 | tclass = unmap_class(orig_tclass); | 919 | tclass = unmap_class(orig_tclass); |
| 952 | if (unlikely(orig_tclass && !tclass)) { | 920 | if (unlikely(orig_tclass && !tclass)) { |
| 953 | if (policydb.allow_unknown) | 921 | if (policydb.allow_unknown) |
| 954 | goto allow; | 922 | goto allow; |
| 955 | rc = -EINVAL; | ||
| 956 | goto out; | 923 | goto out; |
| 957 | } | 924 | } |
| 958 | rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); | 925 | context_struct_compute_av(scontext, tcontext, tclass, avd); |
| 959 | map_decision(orig_tclass, avd, policydb.allow_unknown); | 926 | map_decision(orig_tclass, avd, policydb.allow_unknown); |
| 960 | out: | 927 | out: |
| 961 | read_unlock(&policy_rwlock); | 928 | read_unlock(&policy_rwlock); |
| 962 | return rc; | 929 | return; |
| 963 | allow: | 930 | allow: |
| 964 | avd->allowed = 0xffffffff; | 931 | avd->allowed = 0xffffffff; |
| 965 | avd->auditallow = 0; | ||
| 966 | avd->auditdeny = 0xffffffff; | ||
| 967 | avd->seqno = latest_granting; | ||
| 968 | avd->flags = 0; | ||
| 969 | rc = 0; | ||
| 970 | goto out; | 932 | goto out; |
| 971 | } | 933 | } |
| 972 | 934 | ||
| 973 | int security_compute_av_user(u32 ssid, | 935 | void security_compute_av_user(u32 ssid, |
| 974 | u32 tsid, | 936 | u32 tsid, |
| 975 | u16 tclass, | 937 | u16 tclass, |
| 976 | u32 requested, | 938 | struct av_decision *avd) |
| 977 | struct av_decision *avd) | ||
| 978 | { | 939 | { |
| 979 | int rc; | 940 | struct context *scontext = NULL, *tcontext = NULL; |
| 980 | 941 | ||
| 981 | if (!ss_initialized) { | 942 | read_lock(&policy_rwlock); |
| 982 | avd->allowed = 0xffffffff; | 943 | avd_init(avd); |
| 983 | avd->auditallow = 0; | 944 | if (!ss_initialized) |
| 984 | avd->auditdeny = 0xffffffff; | 945 | goto allow; |
| 985 | avd->seqno = latest_granting; | 946 | |
| 986 | return 0; | 947 | scontext = sidtab_search(&sidtab, ssid); |
| 948 | if (!scontext) { | ||
| 949 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
| 950 | __func__, ssid); | ||
| 951 | goto out; | ||
| 987 | } | 952 | } |
| 988 | 953 | ||
| 989 | read_lock(&policy_rwlock); | 954 | /* permissive domain? */ |
| 990 | rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); | 955 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) |
| 956 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
| 957 | |||
| 958 | tcontext = sidtab_search(&sidtab, tsid); | ||
| 959 | if (!tcontext) { | ||
| 960 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
| 961 | __func__, tsid); | ||
| 962 | goto out; | ||
| 963 | } | ||
| 964 | |||
| 965 | if (unlikely(!tclass)) { | ||
| 966 | if (policydb.allow_unknown) | ||
| 967 | goto allow; | ||
| 968 | goto out; | ||
| 969 | } | ||
| 970 | |||
| 971 | context_struct_compute_av(scontext, tcontext, tclass, avd); | ||
| 972 | out: | ||
| 991 | read_unlock(&policy_rwlock); | 973 | read_unlock(&policy_rwlock); |
| 992 | return rc; | 974 | return; |
| 975 | allow: | ||
| 976 | avd->allowed = 0xffffffff; | ||
| 977 | goto out; | ||
| 993 | } | 978 | } |
| 994 | 979 | ||
| 995 | /* | 980 | /* |
| @@ -1231,7 +1216,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
| 1231 | *sid = SECSID_NULL; | 1216 | *sid = SECSID_NULL; |
| 1232 | 1217 | ||
| 1233 | /* Copy the string so that we can modify the copy as we parse it. */ | 1218 | /* Copy the string so that we can modify the copy as we parse it. */ |
| 1234 | scontext2 = kmalloc(scontext_len+1, gfp_flags); | 1219 | scontext2 = kmalloc(scontext_len + 1, gfp_flags); |
| 1235 | if (!scontext2) | 1220 | if (!scontext2) |
| 1236 | return -ENOMEM; | 1221 | return -ENOMEM; |
| 1237 | memcpy(scontext2, scontext, scontext_len); | 1222 | memcpy(scontext2, scontext, scontext_len); |
| @@ -1565,7 +1550,10 @@ static int clone_sid(u32 sid, | |||
| 1565 | { | 1550 | { |
| 1566 | struct sidtab *s = arg; | 1551 | struct sidtab *s = arg; |
| 1567 | 1552 | ||
| 1568 | return sidtab_insert(s, sid, context); | 1553 | if (sid > SECINITSID_NUM) |
| 1554 | return sidtab_insert(s, sid, context); | ||
| 1555 | else | ||
| 1556 | return 0; | ||
| 1569 | } | 1557 | } |
| 1570 | 1558 | ||
| 1571 | static inline int convert_context_handle_invalid_context(struct context *context) | 1559 | static inline int convert_context_handle_invalid_context(struct context *context) |
| @@ -1606,12 +1594,17 @@ static int convert_context(u32 key, | |||
| 1606 | { | 1594 | { |
| 1607 | struct convert_context_args *args; | 1595 | struct convert_context_args *args; |
| 1608 | struct context oldc; | 1596 | struct context oldc; |
| 1597 | struct ocontext *oc; | ||
| 1598 | struct mls_range *range; | ||
| 1609 | struct role_datum *role; | 1599 | struct role_datum *role; |
| 1610 | struct type_datum *typdatum; | 1600 | struct type_datum *typdatum; |
| 1611 | struct user_datum *usrdatum; | 1601 | struct user_datum *usrdatum; |
| 1612 | char *s; | 1602 | char *s; |
| 1613 | u32 len; | 1603 | u32 len; |
| 1614 | int rc; | 1604 | int rc = 0; |
| 1605 | |||
| 1606 | if (key <= SECINITSID_NUM) | ||
| 1607 | goto out; | ||
| 1615 | 1608 | ||
| 1616 | args = p; | 1609 | args = p; |
| 1617 | 1610 | ||
| @@ -1673,9 +1666,39 @@ static int convert_context(u32 key, | |||
| 1673 | goto bad; | 1666 | goto bad; |
| 1674 | c->type = typdatum->value; | 1667 | c->type = typdatum->value; |
| 1675 | 1668 | ||
| 1676 | rc = mls_convert_context(args->oldp, args->newp, c); | 1669 | /* Convert the MLS fields if dealing with MLS policies */ |
| 1677 | if (rc) | 1670 | if (args->oldp->mls_enabled && args->newp->mls_enabled) { |
| 1678 | goto bad; | 1671 | rc = mls_convert_context(args->oldp, args->newp, c); |
| 1672 | if (rc) | ||
| 1673 | goto bad; | ||
| 1674 | } else if (args->oldp->mls_enabled && !args->newp->mls_enabled) { | ||
| 1675 | /* | ||
| 1676 | * Switching between MLS and non-MLS policy: | ||
| 1677 | * free any storage used by the MLS fields in the | ||
| 1678 | * context for all existing entries in the sidtab. | ||
| 1679 | */ | ||
| 1680 | mls_context_destroy(c); | ||
| 1681 | } else if (!args->oldp->mls_enabled && args->newp->mls_enabled) { | ||
| 1682 | /* | ||
| 1683 | * Switching between non-MLS and MLS policy: | ||
| 1684 | * ensure that the MLS fields of the context for all | ||
| 1685 | * existing entries in the sidtab are filled in with a | ||
| 1686 | * suitable default value, likely taken from one of the | ||
| 1687 | * initial SIDs. | ||
| 1688 | */ | ||
| 1689 | oc = args->newp->ocontexts[OCON_ISID]; | ||
| 1690 | while (oc && oc->sid[0] != SECINITSID_UNLABELED) | ||
| 1691 | oc = oc->next; | ||
| 1692 | if (!oc) { | ||
| 1693 | printk(KERN_ERR "SELinux: unable to look up" | ||
| 1694 | " the initial SIDs list\n"); | ||
| 1695 | goto bad; | ||
| 1696 | } | ||
| 1697 | range = &oc->context[0].range; | ||
| 1698 | rc = mls_range_set(c, range); | ||
| 1699 | if (rc) | ||
| 1700 | goto bad; | ||
| 1701 | } | ||
| 1679 | 1702 | ||
| 1680 | /* Check the validity of the new context. */ | 1703 | /* Check the validity of the new context. */ |
| 1681 | if (!policydb_context_isvalid(args->newp, c)) { | 1704 | if (!policydb_context_isvalid(args->newp, c)) { |
| @@ -1737,22 +1760,28 @@ int security_load_policy(void *data, size_t len) | |||
| 1737 | 1760 | ||
| 1738 | if (!ss_initialized) { | 1761 | if (!ss_initialized) { |
| 1739 | avtab_cache_init(); | 1762 | avtab_cache_init(); |
| 1740 | if (policydb_read(&policydb, fp)) { | 1763 | rc = policydb_read(&policydb, fp); |
| 1764 | if (rc) { | ||
| 1741 | avtab_cache_destroy(); | 1765 | avtab_cache_destroy(); |
| 1742 | return -EINVAL; | 1766 | return rc; |
| 1743 | } | 1767 | } |
| 1744 | if (selinux_set_mapping(&policydb, secclass_map, | 1768 | |
| 1745 | ¤t_mapping, | 1769 | rc = selinux_set_mapping(&policydb, secclass_map, |
| 1746 | ¤t_mapping_size)) { | 1770 | ¤t_mapping, |
| 1771 | ¤t_mapping_size); | ||
| 1772 | if (rc) { | ||
| 1747 | policydb_destroy(&policydb); | 1773 | policydb_destroy(&policydb); |
| 1748 | avtab_cache_destroy(); | 1774 | avtab_cache_destroy(); |
| 1749 | return -EINVAL; | 1775 | return rc; |
| 1750 | } | 1776 | } |
| 1751 | if (policydb_load_isids(&policydb, &sidtab)) { | 1777 | |
| 1778 | rc = policydb_load_isids(&policydb, &sidtab); | ||
| 1779 | if (rc) { | ||
| 1752 | policydb_destroy(&policydb); | 1780 | policydb_destroy(&policydb); |
| 1753 | avtab_cache_destroy(); | 1781 | avtab_cache_destroy(); |
| 1754 | return -EINVAL; | 1782 | return rc; |
| 1755 | } | 1783 | } |
| 1784 | |||
| 1756 | security_load_policycaps(); | 1785 | security_load_policycaps(); |
| 1757 | ss_initialized = 1; | 1786 | ss_initialized = 1; |
| 1758 | seqno = ++latest_granting; | 1787 | seqno = ++latest_granting; |
| @@ -1768,16 +1797,25 @@ int security_load_policy(void *data, size_t len) | |||
| 1768 | sidtab_hash_eval(&sidtab, "sids"); | 1797 | sidtab_hash_eval(&sidtab, "sids"); |
| 1769 | #endif | 1798 | #endif |
| 1770 | 1799 | ||
| 1771 | if (policydb_read(&newpolicydb, fp)) | 1800 | rc = policydb_read(&newpolicydb, fp); |
| 1772 | return -EINVAL; | 1801 | if (rc) |
| 1802 | return rc; | ||
| 1803 | |||
| 1804 | /* If switching between different policy types, log MLS status */ | ||
| 1805 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) | ||
| 1806 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); | ||
| 1807 | else if (!policydb.mls_enabled && newpolicydb.mls_enabled) | ||
| 1808 | printk(KERN_INFO "SELinux: Enabling MLS support...\n"); | ||
| 1773 | 1809 | ||
| 1774 | if (sidtab_init(&newsidtab)) { | 1810 | rc = policydb_load_isids(&newpolicydb, &newsidtab); |
| 1811 | if (rc) { | ||
| 1812 | printk(KERN_ERR "SELinux: unable to load the initial SIDs\n"); | ||
| 1775 | policydb_destroy(&newpolicydb); | 1813 | policydb_destroy(&newpolicydb); |
| 1776 | return -ENOMEM; | 1814 | return rc; |
| 1777 | } | 1815 | } |
| 1778 | 1816 | ||
| 1779 | if (selinux_set_mapping(&newpolicydb, secclass_map, | 1817 | rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size); |
| 1780 | &map, &map_size)) | 1818 | if (rc) |
| 1781 | goto err; | 1819 | goto err; |
| 1782 | 1820 | ||
| 1783 | rc = security_preserve_bools(&newpolicydb); | 1821 | rc = security_preserve_bools(&newpolicydb); |
| @@ -1788,10 +1826,10 @@ int security_load_policy(void *data, size_t len) | |||
| 1788 | 1826 | ||
| 1789 | /* Clone the SID table. */ | 1827 | /* Clone the SID table. */ |
| 1790 | sidtab_shutdown(&sidtab); | 1828 | sidtab_shutdown(&sidtab); |
| 1791 | if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { | 1829 | |
| 1792 | rc = -ENOMEM; | 1830 | rc = sidtab_map(&sidtab, clone_sid, &newsidtab); |
| 1831 | if (rc) | ||
| 1793 | goto err; | 1832 | goto err; |
| 1794 | } | ||
| 1795 | 1833 | ||
| 1796 | /* | 1834 | /* |
| 1797 | * Convert the internal representations of contexts | 1835 | * Convert the internal representations of contexts |
| @@ -1800,8 +1838,12 @@ int security_load_policy(void *data, size_t len) | |||
| 1800 | args.oldp = &policydb; | 1838 | args.oldp = &policydb; |
| 1801 | args.newp = &newpolicydb; | 1839 | args.newp = &newpolicydb; |
| 1802 | rc = sidtab_map(&newsidtab, convert_context, &args); | 1840 | rc = sidtab_map(&newsidtab, convert_context, &args); |
| 1803 | if (rc) | 1841 | if (rc) { |
| 1842 | printk(KERN_ERR "SELinux: unable to convert the internal" | ||
| 1843 | " representation of contexts in the new SID" | ||
| 1844 | " table\n"); | ||
| 1804 | goto err; | 1845 | goto err; |
| 1846 | } | ||
| 1805 | 1847 | ||
| 1806 | /* Save the old policydb and SID table to free later. */ | 1848 | /* Save the old policydb and SID table to free later. */ |
| 1807 | memcpy(&oldpolicydb, &policydb, sizeof policydb); | 1849 | memcpy(&oldpolicydb, &policydb, sizeof policydb); |
| @@ -2066,9 +2108,9 @@ int security_get_user_sids(u32 fromsid, | |||
| 2066 | 2108 | ||
| 2067 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { | 2109 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { |
| 2068 | role = policydb.role_val_to_struct[i]; | 2110 | role = policydb.role_val_to_struct[i]; |
| 2069 | usercon.role = i+1; | 2111 | usercon.role = i + 1; |
| 2070 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { | 2112 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { |
| 2071 | usercon.type = j+1; | 2113 | usercon.type = j + 1; |
| 2072 | 2114 | ||
| 2073 | if (mls_setup_user_range(fromcon, user, &usercon)) | 2115 | if (mls_setup_user_range(fromcon, user, &usercon)) |
| 2074 | continue; | 2116 | continue; |
| @@ -2397,7 +2439,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
| 2397 | u32 len; | 2439 | u32 len; |
| 2398 | int rc = 0; | 2440 | int rc = 0; |
| 2399 | 2441 | ||
| 2400 | if (!ss_initialized || !selinux_mls_enabled) { | 2442 | if (!ss_initialized || !policydb.mls_enabled) { |
| 2401 | *new_sid = sid; | 2443 | *new_sid = sid; |
| 2402 | goto out; | 2444 | goto out; |
| 2403 | } | 2445 | } |
| @@ -2498,7 +2540,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
| 2498 | /* we don't need to check ss_initialized here since the only way both | 2540 | /* we don't need to check ss_initialized here since the only way both |
| 2499 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the | 2541 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the |
| 2500 | * security server was initialized and ss_initialized was true */ | 2542 | * security server was initialized and ss_initialized was true */ |
| 2501 | if (!selinux_mls_enabled) { | 2543 | if (!policydb.mls_enabled) { |
| 2502 | *peer_sid = SECSID_NULL; | 2544 | *peer_sid = SECSID_NULL; |
| 2503 | return 0; | 2545 | return 0; |
| 2504 | } | 2546 | } |
| @@ -2555,7 +2597,7 @@ int security_get_classes(char ***classes, int *nclasses) | |||
| 2555 | read_lock(&policy_rwlock); | 2597 | read_lock(&policy_rwlock); |
| 2556 | 2598 | ||
| 2557 | *nclasses = policydb.p_classes.nprim; | 2599 | *nclasses = policydb.p_classes.nprim; |
| 2558 | *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC); | 2600 | *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); |
| 2559 | if (!*classes) | 2601 | if (!*classes) |
| 2560 | goto out; | 2602 | goto out; |
| 2561 | 2603 | ||
| @@ -2602,7 +2644,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms) | |||
| 2602 | } | 2644 | } |
| 2603 | 2645 | ||
| 2604 | *nperms = match->permissions.nprim; | 2646 | *nperms = match->permissions.nprim; |
| 2605 | *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC); | 2647 | *perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC); |
| 2606 | if (!*perms) | 2648 | if (!*perms) |
| 2607 | goto out; | 2649 | goto out; |
| 2608 | 2650 | ||
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 837658a98a54..bcf9f620426e 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> | 4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> |
| 5 | */ | 5 | */ |
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 7 | #include <linux/slab.h> | ||
| 8 | #include <linux/string.h> | 7 | #include <linux/string.h> |
| 9 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
| 10 | #include "symtab.h" | 9 | #include "symtab.h" |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index f3cb9ed731a9..fff78d3b51a2 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/netfilter.h> | 38 | #include <linux/netfilter.h> |
| 39 | #include <linux/netfilter_ipv4.h> | 39 | #include <linux/netfilter_ipv4.h> |
| 40 | #include <linux/netfilter_ipv6.h> | 40 | #include <linux/netfilter_ipv6.h> |
| 41 | #include <linux/slab.h> | ||
| 41 | #include <linux/ip.h> | 42 | #include <linux/ip.h> |
| 42 | #include <linux/tcp.h> | 43 | #include <linux/tcp.h> |
| 43 | #include <linux/skbuff.h> | 44 | #include <linux/skbuff.h> |
