diff options
Diffstat (limited to 'security/selinux')
| -rw-r--r-- | security/selinux/avc.c | 28 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 377 | ||||
| -rw-r--r-- | security/selinux/include/classmap.h | 16 | ||||
| -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/netlabel.c | 14 | ||||
| -rw-r--r-- | security/selinux/netlink.c | 1 | ||||
| -rw-r--r-- | security/selinux/netnode.c | 2 | ||||
| -rw-r--r-- | security/selinux/nlmsgtab.c | 1 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 60 | ||||
| -rw-r--r-- | security/selinux/ss/avtab.c | 39 | ||||
| -rw-r--r-- | security/selinux/ss/conditional.c | 65 | ||||
| -rw-r--r-- | security/selinux/ss/mls.c | 2 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.c | 663 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.h | 4 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 56 | ||||
| -rw-r--r-- | security/selinux/ss/symtab.c | 2 |
18 files changed, 688 insertions, 653 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 989fef82563a..9da6420e2056 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
| @@ -288,7 +288,6 @@ static struct avc_node *avc_alloc_node(void) | |||
| 288 | if (!node) | 288 | if (!node) |
| 289 | goto out; | 289 | goto out; |
| 290 | 290 | ||
| 291 | INIT_RCU_HEAD(&node->rhead); | ||
| 292 | INIT_HLIST_NODE(&node->list); | 291 | INIT_HLIST_NODE(&node->list); |
| 293 | avc_cache_stats_incr(allocations); | 292 | avc_cache_stats_incr(allocations); |
| 294 | 293 | ||
| @@ -489,9 +488,29 @@ void avc_audit(u32 ssid, u32 tsid, | |||
| 489 | struct common_audit_data stack_data; | 488 | struct common_audit_data stack_data; |
| 490 | u32 denied, audited; | 489 | u32 denied, audited; |
| 491 | denied = requested & ~avd->allowed; | 490 | denied = requested & ~avd->allowed; |
| 492 | if (denied) | 491 | if (denied) { |
| 493 | audited = denied & avd->auditdeny; | 492 | audited = denied & avd->auditdeny; |
| 494 | else if (result) | 493 | /* |
| 494 | * a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in | ||
| 495 | * this field means that ANY denials should NOT be audited if | ||
| 496 | * the policy contains an explicit dontaudit rule for that | ||
| 497 | * permission. Take notice that this is unrelated to the | ||
| 498 | * actual permissions that were denied. As an example lets | ||
| 499 | * assume: | ||
| 500 | * | ||
| 501 | * denied == READ | ||
| 502 | * avd.auditdeny & ACCESS == 0 (not set means explicit rule) | ||
| 503 | * selinux_audit_data.auditdeny & ACCESS == 1 | ||
| 504 | * | ||
| 505 | * We will NOT audit the denial even though the denied | ||
| 506 | * permission was READ and the auditdeny checks were for | ||
| 507 | * ACCESS | ||
| 508 | */ | ||
| 509 | if (a && | ||
| 510 | a->selinux_audit_data.auditdeny && | ||
| 511 | !(a->selinux_audit_data.auditdeny & avd->auditdeny)) | ||
| 512 | audited = 0; | ||
| 513 | } else if (result) | ||
| 495 | audited = denied = requested; | 514 | audited = denied = requested; |
| 496 | else | 515 | else |
| 497 | audited = requested & avd->auditallow; | 516 | audited = requested & avd->auditallow; |
| @@ -499,8 +518,7 @@ void avc_audit(u32 ssid, u32 tsid, | |||
| 499 | return; | 518 | return; |
| 500 | if (!a) { | 519 | if (!a) { |
| 501 | a = &stack_data; | 520 | a = &stack_data; |
| 502 | memset(a, 0, sizeof(*a)); | 521 | COMMON_AUDIT_DATA_INIT(a, NONE); |
| 503 | a->type = LSM_AUDIT_NO_AUDIT; | ||
| 504 | } | 522 | } |
| 505 | a->selinux_audit_data.tclass = tclass; | 523 | a->selinux_audit_data.tclass = tclass; |
| 506 | a->selinux_audit_data.requested = requested; | 524 | a->selinux_audit_data.requested = requested; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5feecb41009d..9b40f4c0ac70 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -87,9 +87,6 @@ | |||
| 87 | #include "netlabel.h" | 87 | #include "netlabel.h" |
| 88 | #include "audit.h" | 88 | #include "audit.h" |
| 89 | 89 | ||
| 90 | #define XATTR_SELINUX_SUFFIX "selinux" | ||
| 91 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX | ||
| 92 | |||
| 93 | #define NUM_SEL_MNT_OPTS 5 | 90 | #define NUM_SEL_MNT_OPTS 5 |
| 94 | 91 | ||
| 95 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 92 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
| @@ -126,11 +123,6 @@ __setup("selinux=", selinux_enabled_setup); | |||
| 126 | int selinux_enabled = 1; | 123 | int selinux_enabled = 1; |
| 127 | #endif | 124 | #endif |
| 128 | 125 | ||
| 129 | /* Lists of inode and superblock security structures initialized | ||
| 130 | before the policy was loaded. */ | ||
| 131 | static LIST_HEAD(superblock_security_head); | ||
| 132 | static DEFINE_SPINLOCK(sb_security_lock); | ||
| 133 | |||
| 134 | static struct kmem_cache *sel_inode_cache; | 126 | static struct kmem_cache *sel_inode_cache; |
| 135 | 127 | ||
| 136 | /** | 128 | /** |
| @@ -193,7 +185,7 @@ static inline u32 task_sid(const struct task_struct *task) | |||
| 193 | */ | 185 | */ |
| 194 | static inline u32 current_sid(void) | 186 | static inline u32 current_sid(void) |
| 195 | { | 187 | { |
| 196 | const struct task_security_struct *tsec = current_cred()->security; | 188 | const struct task_security_struct *tsec = current_security(); |
| 197 | 189 | ||
| 198 | return tsec->sid; | 190 | return tsec->sid; |
| 199 | } | 191 | } |
| @@ -266,7 +258,6 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 266 | return -ENOMEM; | 258 | return -ENOMEM; |
| 267 | 259 | ||
| 268 | mutex_init(&sbsec->lock); | 260 | mutex_init(&sbsec->lock); |
| 269 | INIT_LIST_HEAD(&sbsec->list); | ||
| 270 | INIT_LIST_HEAD(&sbsec->isec_head); | 261 | INIT_LIST_HEAD(&sbsec->isec_head); |
| 271 | spin_lock_init(&sbsec->isec_lock); | 262 | spin_lock_init(&sbsec->isec_lock); |
| 272 | sbsec->sb = sb; | 263 | sbsec->sb = sb; |
| @@ -281,49 +272,17 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 281 | static void superblock_free_security(struct super_block *sb) | 272 | static void superblock_free_security(struct super_block *sb) |
| 282 | { | 273 | { |
| 283 | struct superblock_security_struct *sbsec = sb->s_security; | 274 | struct superblock_security_struct *sbsec = sb->s_security; |
| 284 | |||
| 285 | spin_lock(&sb_security_lock); | ||
| 286 | if (!list_empty(&sbsec->list)) | ||
| 287 | list_del_init(&sbsec->list); | ||
| 288 | spin_unlock(&sb_security_lock); | ||
| 289 | |||
| 290 | sb->s_security = NULL; | 275 | sb->s_security = NULL; |
| 291 | kfree(sbsec); | 276 | kfree(sbsec); |
| 292 | } | 277 | } |
| 293 | 278 | ||
| 294 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | ||
| 295 | { | ||
| 296 | struct sk_security_struct *ssec; | ||
| 297 | |||
| 298 | ssec = kzalloc(sizeof(*ssec), priority); | ||
| 299 | if (!ssec) | ||
| 300 | return -ENOMEM; | ||
| 301 | |||
| 302 | ssec->peer_sid = SECINITSID_UNLABELED; | ||
| 303 | ssec->sid = SECINITSID_UNLABELED; | ||
| 304 | sk->sk_security = ssec; | ||
| 305 | |||
| 306 | selinux_netlbl_sk_security_reset(ssec); | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static void sk_free_security(struct sock *sk) | ||
| 312 | { | ||
| 313 | struct sk_security_struct *ssec = sk->sk_security; | ||
| 314 | |||
| 315 | sk->sk_security = NULL; | ||
| 316 | selinux_netlbl_sk_security_free(ssec); | ||
| 317 | kfree(ssec); | ||
| 318 | } | ||
| 319 | |||
| 320 | /* The security server must be initialized before | 279 | /* The security server must be initialized before |
| 321 | any labeling or access decisions can be provided. */ | 280 | any labeling or access decisions can be provided. */ |
| 322 | extern int ss_initialized; | 281 | extern int ss_initialized; |
| 323 | 282 | ||
| 324 | /* The file system's label must be initialized prior to use. */ | 283 | /* The file system's label must be initialized prior to use. */ |
| 325 | 284 | ||
| 326 | static char *labeling_behaviors[6] = { | 285 | static const char *labeling_behaviors[6] = { |
| 327 | "uses xattr", | 286 | "uses xattr", |
| 328 | "uses transition SIDs", | 287 | "uses transition SIDs", |
| 329 | "uses task SIDs", | 288 | "uses task SIDs", |
| @@ -612,10 +571,6 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
| 612 | /* Defer initialization until selinux_complete_init, | 571 | /* Defer initialization until selinux_complete_init, |
| 613 | after the initial policy is loaded and the security | 572 | after the initial policy is loaded and the security |
| 614 | server is ready to handle calls. */ | 573 | server is ready to handle calls. */ |
| 615 | spin_lock(&sb_security_lock); | ||
| 616 | if (list_empty(&sbsec->list)) | ||
| 617 | list_add(&sbsec->list, &superblock_security_head); | ||
| 618 | spin_unlock(&sb_security_lock); | ||
| 619 | goto out; | 574 | goto out; |
| 620 | } | 575 | } |
| 621 | rc = -EINVAL; | 576 | rc = -EINVAL; |
| @@ -806,16 +761,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
| 806 | 761 | ||
| 807 | /* | 762 | /* |
| 808 | * if the parent was able to be mounted it clearly had no special lsm | 763 | * if the parent was able to be mounted it clearly had no special lsm |
| 809 | * mount options. thus we can safely put this sb on the list and deal | 764 | * mount options. thus we can safely deal with this superblock later |
| 810 | * with it later | ||
| 811 | */ | 765 | */ |
| 812 | if (!ss_initialized) { | 766 | if (!ss_initialized) |
| 813 | spin_lock(&sb_security_lock); | ||
| 814 | if (list_empty(&newsbsec->list)) | ||
| 815 | list_add(&newsbsec->list, &superblock_security_head); | ||
| 816 | spin_unlock(&sb_security_lock); | ||
| 817 | return; | 767 | return; |
| 818 | } | ||
| 819 | 768 | ||
| 820 | /* how can we clone if the old one wasn't set up?? */ | 769 | /* how can we clone if the old one wasn't set up?? */ |
| 821 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 770 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
| @@ -1606,8 +1555,7 @@ static int may_create(struct inode *dir, | |||
| 1606 | struct dentry *dentry, | 1555 | struct dentry *dentry, |
| 1607 | u16 tclass) | 1556 | u16 tclass) |
| 1608 | { | 1557 | { |
| 1609 | const struct cred *cred = current_cred(); | 1558 | const struct task_security_struct *tsec = current_security(); |
| 1610 | const struct task_security_struct *tsec = cred->security; | ||
| 1611 | struct inode_security_struct *dsec; | 1559 | struct inode_security_struct *dsec; |
| 1612 | struct superblock_security_struct *sbsec; | 1560 | struct superblock_security_struct *sbsec; |
| 1613 | u32 sid, newsid; | 1561 | u32 sid, newsid; |
| @@ -1828,27 +1776,9 @@ static inline u32 open_file_to_av(struct file *file) | |||
| 1828 | { | 1776 | { |
| 1829 | u32 av = file_to_av(file); | 1777 | u32 av = file_to_av(file); |
| 1830 | 1778 | ||
| 1831 | if (selinux_policycap_openperm) { | 1779 | if (selinux_policycap_openperm) |
| 1832 | mode_t mode = file->f_path.dentry->d_inode->i_mode; | 1780 | av |= FILE__OPEN; |
| 1833 | /* | 1781 | |
| 1834 | * lnk files and socks do not really have an 'open' | ||
| 1835 | */ | ||
| 1836 | if (S_ISREG(mode)) | ||
| 1837 | av |= FILE__OPEN; | ||
| 1838 | else if (S_ISCHR(mode)) | ||
| 1839 | av |= CHR_FILE__OPEN; | ||
| 1840 | else if (S_ISBLK(mode)) | ||
| 1841 | av |= BLK_FILE__OPEN; | ||
| 1842 | else if (S_ISFIFO(mode)) | ||
| 1843 | av |= FIFO_FILE__OPEN; | ||
| 1844 | else if (S_ISDIR(mode)) | ||
| 1845 | av |= DIR__OPEN; | ||
| 1846 | else if (S_ISSOCK(mode)) | ||
| 1847 | av |= SOCK_FILE__OPEN; | ||
| 1848 | else | ||
| 1849 | printk(KERN_ERR "SELinux: WARNING: inside %s with " | ||
| 1850 | "unknown mode:%o\n", __func__, mode); | ||
| 1851 | } | ||
| 1852 | return av; | 1782 | return av; |
| 1853 | } | 1783 | } |
| 1854 | 1784 | ||
| @@ -2205,8 +2135,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
| 2205 | 2135 | ||
| 2206 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) | 2136 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) |
| 2207 | { | 2137 | { |
| 2208 | const struct cred *cred = current_cred(); | 2138 | const struct task_security_struct *tsec = current_security(); |
| 2209 | const struct task_security_struct *tsec = cred->security; | ||
| 2210 | u32 sid, osid; | 2139 | u32 sid, osid; |
| 2211 | int atsecure = 0; | 2140 | int atsecure = 0; |
| 2212 | 2141 | ||
| @@ -2581,8 +2510,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 2581 | char **name, void **value, | 2510 | char **name, void **value, |
| 2582 | size_t *len) | 2511 | size_t *len) |
| 2583 | { | 2512 | { |
| 2584 | const struct cred *cred = current_cred(); | 2513 | const struct task_security_struct *tsec = current_security(); |
| 2585 | const struct task_security_struct *tsec = cred->security; | ||
| 2586 | struct inode_security_struct *dsec; | 2514 | struct inode_security_struct *dsec; |
| 2587 | struct superblock_security_struct *sbsec; | 2515 | struct superblock_security_struct *sbsec; |
| 2588 | u32 sid, newsid, clen; | 2516 | u32 sid, newsid, clen; |
| @@ -2698,14 +2626,26 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
| 2698 | static int selinux_inode_permission(struct inode *inode, int mask) | 2626 | static int selinux_inode_permission(struct inode *inode, int mask) |
| 2699 | { | 2627 | { |
| 2700 | const struct cred *cred = current_cred(); | 2628 | const struct cred *cred = current_cred(); |
| 2629 | struct common_audit_data ad; | ||
| 2630 | u32 perms; | ||
| 2631 | bool from_access; | ||
| 2701 | 2632 | ||
| 2702 | if (!mask) { | 2633 | from_access = mask & MAY_ACCESS; |
| 2703 | /* No permission to check. Existence test. */ | 2634 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
| 2635 | |||
| 2636 | /* No permission to check. Existence test. */ | ||
| 2637 | if (!mask) | ||
| 2704 | return 0; | 2638 | return 0; |
| 2705 | } | ||
| 2706 | 2639 | ||
| 2707 | return inode_has_perm(cred, inode, | 2640 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 2708 | file_mask_to_av(inode->i_mode, mask), NULL); | 2641 | ad.u.fs.inode = inode; |
| 2642 | |||
| 2643 | if (from_access) | ||
| 2644 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | ||
| 2645 | |||
| 2646 | perms = file_mask_to_av(inode->i_mode, mask); | ||
| 2647 | |||
| 2648 | return inode_has_perm(cred, inode, perms, &ad); | ||
| 2709 | } | 2649 | } |
| 2710 | 2650 | ||
| 2711 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2651 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
| @@ -2999,13 +2939,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
| 2999 | return file_has_perm(cred, file, av); | 2939 | return file_has_perm(cred, file, av); |
| 3000 | } | 2940 | } |
| 3001 | 2941 | ||
| 2942 | static int default_noexec; | ||
| 2943 | |||
| 3002 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 2944 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
| 3003 | { | 2945 | { |
| 3004 | const struct cred *cred = current_cred(); | 2946 | const struct cred *cred = current_cred(); |
| 3005 | int rc = 0; | 2947 | int rc = 0; |
| 3006 | 2948 | ||
| 3007 | #ifndef CONFIG_PPC32 | 2949 | if (default_noexec && |
| 3008 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 2950 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
| 3009 | /* | 2951 | /* |
| 3010 | * We are making executable an anonymous mapping or a | 2952 | * We are making executable an anonymous mapping or a |
| 3011 | * private file mapping that will also be writable. | 2953 | * private file mapping that will also be writable. |
| @@ -3015,7 +2957,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
| 3015 | if (rc) | 2957 | if (rc) |
| 3016 | goto error; | 2958 | goto error; |
| 3017 | } | 2959 | } |
| 3018 | #endif | ||
| 3019 | 2960 | ||
| 3020 | if (file) { | 2961 | if (file) { |
| 3021 | /* read access is always possible with a mapping */ | 2962 | /* read access is always possible with a mapping */ |
| @@ -3076,8 +3017,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3076 | if (selinux_checkreqprot) | 3017 | if (selinux_checkreqprot) |
| 3077 | prot = reqprot; | 3018 | prot = reqprot; |
| 3078 | 3019 | ||
| 3079 | #ifndef CONFIG_PPC32 | 3020 | if (default_noexec && |
| 3080 | if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { | 3021 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { |
| 3081 | int rc = 0; | 3022 | int rc = 0; |
| 3082 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3023 | if (vma->vm_start >= vma->vm_mm->start_brk && |
| 3083 | vma->vm_end <= vma->vm_mm->brk) { | 3024 | vma->vm_end <= vma->vm_mm->brk) { |
| @@ -3099,7 +3040,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
| 3099 | if (rc) | 3040 | if (rc) |
| 3100 | return rc; | 3041 | return rc; |
| 3101 | } | 3042 | } |
| 3102 | #endif | ||
| 3103 | 3043 | ||
| 3104 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); | 3044 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); |
| 3105 | } | 3045 | } |
| @@ -3693,71 +3633,54 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
| 3693 | } | 3633 | } |
| 3694 | 3634 | ||
| 3695 | /* socket security operations */ | 3635 | /* socket security operations */ |
| 3696 | static int socket_has_perm(struct task_struct *task, struct socket *sock, | 3636 | |
| 3697 | u32 perms) | 3637 | static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) |
| 3698 | { | 3638 | { |
| 3699 | struct inode_security_struct *isec; | 3639 | return tsec->sockcreate_sid ? : tsec->sid; |
| 3700 | struct common_audit_data ad; | 3640 | } |
| 3701 | u32 sid; | ||
| 3702 | int err = 0; | ||
| 3703 | 3641 | ||
| 3704 | isec = SOCK_INODE(sock)->i_security; | 3642 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
| 3643 | { | ||
| 3644 | struct sk_security_struct *sksec = sk->sk_security; | ||
| 3645 | struct common_audit_data ad; | ||
| 3646 | u32 tsid = task_sid(task); | ||
| 3705 | 3647 | ||
| 3706 | if (isec->sid == SECINITSID_KERNEL) | 3648 | if (sksec->sid == SECINITSID_KERNEL) |
| 3707 | goto out; | 3649 | return 0; |
| 3708 | sid = task_sid(task); | ||
| 3709 | 3650 | ||
| 3710 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3651 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3711 | ad.u.net.sk = sock->sk; | 3652 | ad.u.net.sk = sk; |
| 3712 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | ||
| 3713 | 3653 | ||
| 3714 | out: | 3654 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); |
| 3715 | return err; | ||
| 3716 | } | 3655 | } |
| 3717 | 3656 | ||
| 3718 | static int selinux_socket_create(int family, int type, | 3657 | static int selinux_socket_create(int family, int type, |
| 3719 | int protocol, int kern) | 3658 | int protocol, int kern) |
| 3720 | { | 3659 | { |
| 3721 | const struct cred *cred = current_cred(); | 3660 | const struct task_security_struct *tsec = current_security(); |
| 3722 | const struct task_security_struct *tsec = cred->security; | 3661 | u32 newsid; |
| 3723 | u32 sid, newsid; | ||
| 3724 | u16 secclass; | 3662 | u16 secclass; |
| 3725 | int err = 0; | ||
| 3726 | 3663 | ||
| 3727 | if (kern) | 3664 | if (kern) |
| 3728 | goto out; | 3665 | return 0; |
| 3729 | |||
| 3730 | sid = tsec->sid; | ||
| 3731 | newsid = tsec->sockcreate_sid ?: sid; | ||
| 3732 | 3666 | ||
| 3667 | newsid = socket_sockcreate_sid(tsec); | ||
| 3733 | secclass = socket_type_to_security_class(family, type, protocol); | 3668 | secclass = socket_type_to_security_class(family, type, protocol); |
| 3734 | err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); | 3669 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
| 3735 | |||
| 3736 | out: | ||
| 3737 | return err; | ||
| 3738 | } | 3670 | } |
| 3739 | 3671 | ||
| 3740 | static int selinux_socket_post_create(struct socket *sock, int family, | 3672 | static int selinux_socket_post_create(struct socket *sock, int family, |
| 3741 | int type, int protocol, int kern) | 3673 | int type, int protocol, int kern) |
| 3742 | { | 3674 | { |
| 3743 | const struct cred *cred = current_cred(); | 3675 | const struct task_security_struct *tsec = current_security(); |
| 3744 | const struct task_security_struct *tsec = cred->security; | 3676 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
| 3745 | struct inode_security_struct *isec; | ||
| 3746 | struct sk_security_struct *sksec; | 3677 | struct sk_security_struct *sksec; |
| 3747 | u32 sid, newsid; | ||
| 3748 | int err = 0; | 3678 | int err = 0; |
| 3749 | 3679 | ||
| 3750 | sid = tsec->sid; | ||
| 3751 | newsid = tsec->sockcreate_sid; | ||
| 3752 | |||
| 3753 | isec = SOCK_INODE(sock)->i_security; | ||
| 3754 | |||
| 3755 | if (kern) | 3680 | if (kern) |
| 3756 | isec->sid = SECINITSID_KERNEL; | 3681 | isec->sid = SECINITSID_KERNEL; |
| 3757 | else if (newsid) | ||
| 3758 | isec->sid = newsid; | ||
| 3759 | else | 3682 | else |
| 3760 | isec->sid = sid; | 3683 | isec->sid = socket_sockcreate_sid(tsec); |
| 3761 | 3684 | ||
| 3762 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 3685 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
| 3763 | isec->initialized = 1; | 3686 | isec->initialized = 1; |
| @@ -3778,10 +3701,11 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
| 3778 | 3701 | ||
| 3779 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3702 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
| 3780 | { | 3703 | { |
| 3704 | struct sock *sk = sock->sk; | ||
| 3781 | u16 family; | 3705 | u16 family; |
| 3782 | int err; | 3706 | int err; |
| 3783 | 3707 | ||
| 3784 | err = socket_has_perm(current, sock, SOCKET__BIND); | 3708 | err = sock_has_perm(current, sk, SOCKET__BIND); |
| 3785 | if (err) | 3709 | if (err) |
| 3786 | goto out; | 3710 | goto out; |
| 3787 | 3711 | ||
| @@ -3790,19 +3714,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3790 | * Multiple address binding for SCTP is not supported yet: we just | 3714 | * Multiple address binding for SCTP is not supported yet: we just |
| 3791 | * check the first address now. | 3715 | * check the first address now. |
| 3792 | */ | 3716 | */ |
| 3793 | family = sock->sk->sk_family; | 3717 | family = sk->sk_family; |
| 3794 | if (family == PF_INET || family == PF_INET6) { | 3718 | if (family == PF_INET || family == PF_INET6) { |
| 3795 | char *addrp; | 3719 | char *addrp; |
| 3796 | struct inode_security_struct *isec; | 3720 | struct sk_security_struct *sksec = sk->sk_security; |
| 3797 | struct common_audit_data ad; | 3721 | struct common_audit_data ad; |
| 3798 | struct sockaddr_in *addr4 = NULL; | 3722 | struct sockaddr_in *addr4 = NULL; |
| 3799 | struct sockaddr_in6 *addr6 = NULL; | 3723 | struct sockaddr_in6 *addr6 = NULL; |
| 3800 | unsigned short snum; | 3724 | unsigned short snum; |
| 3801 | struct sock *sk = sock->sk; | ||
| 3802 | u32 sid, node_perm; | 3725 | u32 sid, node_perm; |
| 3803 | 3726 | ||
| 3804 | isec = SOCK_INODE(sock)->i_security; | ||
| 3805 | |||
| 3806 | if (family == PF_INET) { | 3727 | if (family == PF_INET) { |
| 3807 | addr4 = (struct sockaddr_in *)address; | 3728 | addr4 = (struct sockaddr_in *)address; |
| 3808 | snum = ntohs(addr4->sin_port); | 3729 | snum = ntohs(addr4->sin_port); |
| @@ -3826,15 +3747,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3826 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3747 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3827 | ad.u.net.sport = htons(snum); | 3748 | ad.u.net.sport = htons(snum); |
| 3828 | ad.u.net.family = family; | 3749 | ad.u.net.family = family; |
| 3829 | err = avc_has_perm(isec->sid, sid, | 3750 | err = avc_has_perm(sksec->sid, sid, |
| 3830 | isec->sclass, | 3751 | sksec->sclass, |
| 3831 | SOCKET__NAME_BIND, &ad); | 3752 | SOCKET__NAME_BIND, &ad); |
| 3832 | if (err) | 3753 | if (err) |
| 3833 | goto out; | 3754 | goto out; |
| 3834 | } | 3755 | } |
| 3835 | } | 3756 | } |
| 3836 | 3757 | ||
| 3837 | switch (isec->sclass) { | 3758 | switch (sksec->sclass) { |
| 3838 | case SECCLASS_TCP_SOCKET: | 3759 | case SECCLASS_TCP_SOCKET: |
| 3839 | node_perm = TCP_SOCKET__NODE_BIND; | 3760 | node_perm = TCP_SOCKET__NODE_BIND; |
| 3840 | break; | 3761 | break; |
| @@ -3865,8 +3786,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3865 | else | 3786 | else |
| 3866 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); | 3787 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); |
| 3867 | 3788 | ||
| 3868 | err = avc_has_perm(isec->sid, sid, | 3789 | err = avc_has_perm(sksec->sid, sid, |
| 3869 | isec->sclass, node_perm, &ad); | 3790 | sksec->sclass, node_perm, &ad); |
| 3870 | if (err) | 3791 | if (err) |
| 3871 | goto out; | 3792 | goto out; |
| 3872 | } | 3793 | } |
| @@ -3877,19 +3798,18 @@ out: | |||
| 3877 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3798 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
| 3878 | { | 3799 | { |
| 3879 | struct sock *sk = sock->sk; | 3800 | struct sock *sk = sock->sk; |
| 3880 | struct inode_security_struct *isec; | 3801 | struct sk_security_struct *sksec = sk->sk_security; |
| 3881 | int err; | 3802 | int err; |
| 3882 | 3803 | ||
| 3883 | err = socket_has_perm(current, sock, SOCKET__CONNECT); | 3804 | err = sock_has_perm(current, sk, SOCKET__CONNECT); |
| 3884 | if (err) | 3805 | if (err) |
| 3885 | return err; | 3806 | return err; |
| 3886 | 3807 | ||
| 3887 | /* | 3808 | /* |
| 3888 | * If a TCP or DCCP socket, check name_connect permission for the port. | 3809 | * If a TCP or DCCP socket, check name_connect permission for the port. |
| 3889 | */ | 3810 | */ |
| 3890 | isec = SOCK_INODE(sock)->i_security; | 3811 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
| 3891 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3812 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
| 3892 | isec->sclass == SECCLASS_DCCP_SOCKET) { | ||
| 3893 | struct common_audit_data ad; | 3813 | struct common_audit_data ad; |
| 3894 | struct sockaddr_in *addr4 = NULL; | 3814 | struct sockaddr_in *addr4 = NULL; |
| 3895 | struct sockaddr_in6 *addr6 = NULL; | 3815 | struct sockaddr_in6 *addr6 = NULL; |
| @@ -3912,13 +3832,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
| 3912 | if (err) | 3832 | if (err) |
| 3913 | goto out; | 3833 | goto out; |
| 3914 | 3834 | ||
| 3915 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3835 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
| 3916 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3836 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
| 3917 | 3837 | ||
| 3918 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3838 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3919 | ad.u.net.dport = htons(snum); | 3839 | ad.u.net.dport = htons(snum); |
| 3920 | ad.u.net.family = sk->sk_family; | 3840 | ad.u.net.family = sk->sk_family; |
| 3921 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3841 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); |
| 3922 | if (err) | 3842 | if (err) |
| 3923 | goto out; | 3843 | goto out; |
| 3924 | } | 3844 | } |
| @@ -3931,7 +3851,7 @@ out: | |||
| 3931 | 3851 | ||
| 3932 | static int selinux_socket_listen(struct socket *sock, int backlog) | 3852 | static int selinux_socket_listen(struct socket *sock, int backlog) |
| 3933 | { | 3853 | { |
| 3934 | return socket_has_perm(current, sock, SOCKET__LISTEN); | 3854 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); |
| 3935 | } | 3855 | } |
| 3936 | 3856 | ||
| 3937 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 3857 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
| @@ -3940,7 +3860,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
| 3940 | struct inode_security_struct *isec; | 3860 | struct inode_security_struct *isec; |
| 3941 | struct inode_security_struct *newisec; | 3861 | struct inode_security_struct *newisec; |
| 3942 | 3862 | ||
| 3943 | err = socket_has_perm(current, sock, SOCKET__ACCEPT); | 3863 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
| 3944 | if (err) | 3864 | if (err) |
| 3945 | return err; | 3865 | return err; |
| 3946 | 3866 | ||
| @@ -3957,30 +3877,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
| 3957 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3877 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
| 3958 | int size) | 3878 | int size) |
| 3959 | { | 3879 | { |
| 3960 | return socket_has_perm(current, sock, SOCKET__WRITE); | 3880 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); |
| 3961 | } | 3881 | } |
| 3962 | 3882 | ||
| 3963 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3883 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
| 3964 | int size, int flags) | 3884 | int size, int flags) |
| 3965 | { | 3885 | { |
| 3966 | return socket_has_perm(current, sock, SOCKET__READ); | 3886 | return sock_has_perm(current, sock->sk, SOCKET__READ); |
| 3967 | } | 3887 | } |
| 3968 | 3888 | ||
| 3969 | static int selinux_socket_getsockname(struct socket *sock) | 3889 | static int selinux_socket_getsockname(struct socket *sock) |
| 3970 | { | 3890 | { |
| 3971 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3891 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
| 3972 | } | 3892 | } |
| 3973 | 3893 | ||
| 3974 | static int selinux_socket_getpeername(struct socket *sock) | 3894 | static int selinux_socket_getpeername(struct socket *sock) |
| 3975 | { | 3895 | { |
| 3976 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3896 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
| 3977 | } | 3897 | } |
| 3978 | 3898 | ||
| 3979 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 3899 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
| 3980 | { | 3900 | { |
| 3981 | int err; | 3901 | int err; |
| 3982 | 3902 | ||
| 3983 | err = socket_has_perm(current, sock, SOCKET__SETOPT); | 3903 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); |
| 3984 | if (err) | 3904 | if (err) |
| 3985 | return err; | 3905 | return err; |
| 3986 | 3906 | ||
| @@ -3990,68 +3910,58 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
| 3990 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3910 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
| 3991 | int optname) | 3911 | int optname) |
| 3992 | { | 3912 | { |
| 3993 | return socket_has_perm(current, sock, SOCKET__GETOPT); | 3913 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); |
| 3994 | } | 3914 | } |
| 3995 | 3915 | ||
| 3996 | static int selinux_socket_shutdown(struct socket *sock, int how) | 3916 | static int selinux_socket_shutdown(struct socket *sock, int how) |
| 3997 | { | 3917 | { |
| 3998 | return socket_has_perm(current, sock, SOCKET__SHUTDOWN); | 3918 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
| 3999 | } | 3919 | } |
| 4000 | 3920 | ||
| 4001 | static int selinux_socket_unix_stream_connect(struct socket *sock, | 3921 | static int selinux_socket_unix_stream_connect(struct socket *sock, |
| 4002 | struct socket *other, | 3922 | struct socket *other, |
| 4003 | struct sock *newsk) | 3923 | struct sock *newsk) |
| 4004 | { | 3924 | { |
| 4005 | struct sk_security_struct *ssec; | 3925 | struct sk_security_struct *sksec_sock = sock->sk->sk_security; |
| 4006 | struct inode_security_struct *isec; | 3926 | struct sk_security_struct *sksec_other = other->sk->sk_security; |
| 4007 | struct inode_security_struct *other_isec; | 3927 | struct sk_security_struct *sksec_new = newsk->sk_security; |
| 4008 | struct common_audit_data ad; | 3928 | struct common_audit_data ad; |
| 4009 | int err; | 3929 | int err; |
| 4010 | 3930 | ||
| 4011 | isec = SOCK_INODE(sock)->i_security; | ||
| 4012 | other_isec = SOCK_INODE(other)->i_security; | ||
| 4013 | |||
| 4014 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3931 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4015 | ad.u.net.sk = other->sk; | 3932 | ad.u.net.sk = other->sk; |
| 4016 | 3933 | ||
| 4017 | err = avc_has_perm(isec->sid, other_isec->sid, | 3934 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
| 4018 | isec->sclass, | 3935 | sksec_other->sclass, |
| 4019 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 3936 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
| 4020 | if (err) | 3937 | if (err) |
| 4021 | return err; | 3938 | return err; |
| 4022 | 3939 | ||
| 4023 | /* connecting socket */ | ||
| 4024 | ssec = sock->sk->sk_security; | ||
| 4025 | ssec->peer_sid = other_isec->sid; | ||
| 4026 | |||
| 4027 | /* server child socket */ | 3940 | /* server child socket */ |
| 4028 | ssec = newsk->sk_security; | 3941 | sksec_new->peer_sid = sksec_sock->sid; |
| 4029 | ssec->peer_sid = isec->sid; | 3942 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, |
| 4030 | err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); | 3943 | &sksec_new->sid); |
| 3944 | if (err) | ||
| 3945 | return err; | ||
| 4031 | 3946 | ||
| 4032 | return err; | 3947 | /* connecting socket */ |
| 3948 | sksec_sock->peer_sid = sksec_new->sid; | ||
| 3949 | |||
| 3950 | return 0; | ||
| 4033 | } | 3951 | } |
| 4034 | 3952 | ||
| 4035 | static int selinux_socket_unix_may_send(struct socket *sock, | 3953 | static int selinux_socket_unix_may_send(struct socket *sock, |
| 4036 | struct socket *other) | 3954 | struct socket *other) |
| 4037 | { | 3955 | { |
| 4038 | struct inode_security_struct *isec; | 3956 | struct sk_security_struct *ssec = sock->sk->sk_security; |
| 4039 | struct inode_security_struct *other_isec; | 3957 | struct sk_security_struct *osec = other->sk->sk_security; |
| 4040 | struct common_audit_data ad; | 3958 | struct common_audit_data ad; |
| 4041 | int err; | ||
| 4042 | |||
| 4043 | isec = SOCK_INODE(sock)->i_security; | ||
| 4044 | other_isec = SOCK_INODE(other)->i_security; | ||
| 4045 | 3959 | ||
| 4046 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3960 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4047 | ad.u.net.sk = other->sk; | 3961 | ad.u.net.sk = other->sk; |
| 4048 | 3962 | ||
| 4049 | err = avc_has_perm(isec->sid, other_isec->sid, | 3963 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, |
| 4050 | isec->sclass, SOCKET__SENDTO, &ad); | 3964 | &ad); |
| 4051 | if (err) | ||
| 4052 | return err; | ||
| 4053 | |||
| 4054 | return 0; | ||
| 4055 | } | 3965 | } |
| 4056 | 3966 | ||
| 4057 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 3967 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
| @@ -4190,26 +4100,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 4190 | int err = 0; | 4100 | int err = 0; |
| 4191 | char *scontext; | 4101 | char *scontext; |
| 4192 | u32 scontext_len; | 4102 | u32 scontext_len; |
| 4193 | struct sk_security_struct *ssec; | 4103 | struct sk_security_struct *sksec = sock->sk->sk_security; |
| 4194 | struct inode_security_struct *isec; | ||
| 4195 | u32 peer_sid = SECSID_NULL; | 4104 | u32 peer_sid = SECSID_NULL; |
| 4196 | 4105 | ||
| 4197 | isec = SOCK_INODE(sock)->i_security; | 4106 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
| 4198 | 4107 | sksec->sclass == SECCLASS_TCP_SOCKET) | |
| 4199 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 4108 | peer_sid = sksec->peer_sid; |
| 4200 | isec->sclass == SECCLASS_TCP_SOCKET) { | 4109 | if (peer_sid == SECSID_NULL) |
| 4201 | ssec = sock->sk->sk_security; | 4110 | return -ENOPROTOOPT; |
| 4202 | peer_sid = ssec->peer_sid; | ||
| 4203 | } | ||
| 4204 | if (peer_sid == SECSID_NULL) { | ||
| 4205 | err = -ENOPROTOOPT; | ||
| 4206 | goto out; | ||
| 4207 | } | ||
| 4208 | 4111 | ||
| 4209 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 4112 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
| 4210 | |||
| 4211 | if (err) | 4113 | if (err) |
| 4212 | goto out; | 4114 | return err; |
| 4213 | 4115 | ||
| 4214 | if (scontext_len > len) { | 4116 | if (scontext_len > len) { |
| 4215 | err = -ERANGE; | 4117 | err = -ERANGE; |
| @@ -4222,9 +4124,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 4222 | out_len: | 4124 | out_len: |
| 4223 | if (put_user(scontext_len, optlen)) | 4125 | if (put_user(scontext_len, optlen)) |
| 4224 | err = -EFAULT; | 4126 | err = -EFAULT; |
| 4225 | |||
| 4226 | kfree(scontext); | 4127 | kfree(scontext); |
| 4227 | out: | ||
| 4228 | return err; | 4128 | return err; |
| 4229 | } | 4129 | } |
| 4230 | 4130 | ||
| @@ -4256,24 +4156,39 @@ out: | |||
| 4256 | 4156 | ||
| 4257 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 4157 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
| 4258 | { | 4158 | { |
| 4259 | return sk_alloc_security(sk, family, priority); | 4159 | struct sk_security_struct *sksec; |
| 4160 | |||
| 4161 | sksec = kzalloc(sizeof(*sksec), priority); | ||
| 4162 | if (!sksec) | ||
| 4163 | return -ENOMEM; | ||
| 4164 | |||
| 4165 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
| 4166 | sksec->sid = SECINITSID_UNLABELED; | ||
| 4167 | selinux_netlbl_sk_security_reset(sksec); | ||
| 4168 | sk->sk_security = sksec; | ||
| 4169 | |||
| 4170 | return 0; | ||
| 4260 | } | 4171 | } |
| 4261 | 4172 | ||
| 4262 | static void selinux_sk_free_security(struct sock *sk) | 4173 | static void selinux_sk_free_security(struct sock *sk) |
| 4263 | { | 4174 | { |
| 4264 | sk_free_security(sk); | 4175 | struct sk_security_struct *sksec = sk->sk_security; |
| 4176 | |||
| 4177 | sk->sk_security = NULL; | ||
| 4178 | selinux_netlbl_sk_security_free(sksec); | ||
| 4179 | kfree(sksec); | ||
| 4265 | } | 4180 | } |
| 4266 | 4181 | ||
| 4267 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4182 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
| 4268 | { | 4183 | { |
| 4269 | struct sk_security_struct *ssec = sk->sk_security; | 4184 | struct sk_security_struct *sksec = sk->sk_security; |
| 4270 | struct sk_security_struct *newssec = newsk->sk_security; | 4185 | struct sk_security_struct *newsksec = newsk->sk_security; |
| 4271 | 4186 | ||
| 4272 | newssec->sid = ssec->sid; | 4187 | newsksec->sid = sksec->sid; |
| 4273 | newssec->peer_sid = ssec->peer_sid; | 4188 | newsksec->peer_sid = sksec->peer_sid; |
| 4274 | newssec->sclass = ssec->sclass; | 4189 | newsksec->sclass = sksec->sclass; |
| 4275 | 4190 | ||
| 4276 | selinux_netlbl_sk_security_reset(newssec); | 4191 | selinux_netlbl_sk_security_reset(newsksec); |
| 4277 | } | 4192 | } |
| 4278 | 4193 | ||
| 4279 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4194 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
| @@ -4421,8 +4336,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
| 4421 | int err = 0; | 4336 | int err = 0; |
| 4422 | u32 perm; | 4337 | u32 perm; |
| 4423 | struct nlmsghdr *nlh; | 4338 | struct nlmsghdr *nlh; |
| 4424 | struct socket *sock = sk->sk_socket; | 4339 | struct sk_security_struct *sksec = sk->sk_security; |
| 4425 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
| 4426 | 4340 | ||
| 4427 | if (skb->len < NLMSG_SPACE(0)) { | 4341 | if (skb->len < NLMSG_SPACE(0)) { |
| 4428 | err = -EINVAL; | 4342 | err = -EINVAL; |
| @@ -4430,13 +4344,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
| 4430 | } | 4344 | } |
| 4431 | nlh = nlmsg_hdr(skb); | 4345 | nlh = nlmsg_hdr(skb); |
| 4432 | 4346 | ||
| 4433 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); | 4347 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
| 4434 | if (err) { | 4348 | if (err) { |
| 4435 | if (err == -EINVAL) { | 4349 | if (err == -EINVAL) { |
| 4436 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4350 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
| 4437 | "SELinux: unrecognized netlink message" | 4351 | "SELinux: unrecognized netlink message" |
| 4438 | " type=%hu for sclass=%hu\n", | 4352 | " type=%hu for sclass=%hu\n", |
| 4439 | nlh->nlmsg_type, isec->sclass); | 4353 | nlh->nlmsg_type, sksec->sclass); |
| 4440 | if (!selinux_enforcing || security_get_allow_unknown()) | 4354 | if (!selinux_enforcing || security_get_allow_unknown()) |
| 4441 | err = 0; | 4355 | err = 0; |
| 4442 | } | 4356 | } |
| @@ -4447,7 +4361,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
| 4447 | goto out; | 4361 | goto out; |
| 4448 | } | 4362 | } |
| 4449 | 4363 | ||
| 4450 | err = socket_has_perm(current, sock, perm); | 4364 | err = sock_has_perm(current, sk, perm); |
| 4451 | out: | 4365 | out: |
| 4452 | return err; | 4366 | return err; |
| 4453 | } | 4367 | } |
| @@ -5662,6 +5576,8 @@ static __init int selinux_init(void) | |||
| 5662 | /* Set the security state for the initial task. */ | 5576 | /* Set the security state for the initial task. */ |
| 5663 | cred_init_security(); | 5577 | cred_init_security(); |
| 5664 | 5578 | ||
| 5579 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | ||
| 5580 | |||
| 5665 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5581 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
| 5666 | sizeof(struct inode_security_struct), | 5582 | sizeof(struct inode_security_struct), |
| 5667 | 0, SLAB_PANIC, NULL); | 5583 | 0, SLAB_PANIC, NULL); |
| @@ -5678,35 +5594,18 @@ static __init int selinux_init(void) | |||
| 5678 | return 0; | 5594 | return 0; |
| 5679 | } | 5595 | } |
| 5680 | 5596 | ||
| 5597 | static void delayed_superblock_init(struct super_block *sb, void *unused) | ||
| 5598 | { | ||
| 5599 | superblock_doinit(sb, NULL); | ||
| 5600 | } | ||
| 5601 | |||
| 5681 | void selinux_complete_init(void) | 5602 | void selinux_complete_init(void) |
| 5682 | { | 5603 | { |
| 5683 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); | 5604 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); |
| 5684 | 5605 | ||
| 5685 | /* Set up any superblocks initialized prior to the policy load. */ | 5606 | /* Set up any superblocks initialized prior to the policy load. */ |
| 5686 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); | 5607 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); |
| 5687 | spin_lock(&sb_lock); | 5608 | iterate_supers(delayed_superblock_init, NULL); |
| 5688 | spin_lock(&sb_security_lock); | ||
| 5689 | next_sb: | ||
| 5690 | if (!list_empty(&superblock_security_head)) { | ||
| 5691 | struct superblock_security_struct *sbsec = | ||
| 5692 | list_entry(superblock_security_head.next, | ||
| 5693 | struct superblock_security_struct, | ||
| 5694 | list); | ||
| 5695 | struct super_block *sb = sbsec->sb; | ||
| 5696 | sb->s_count++; | ||
| 5697 | spin_unlock(&sb_security_lock); | ||
| 5698 | spin_unlock(&sb_lock); | ||
| 5699 | down_read(&sb->s_umount); | ||
| 5700 | if (sb->s_root) | ||
| 5701 | superblock_doinit(sb, NULL); | ||
| 5702 | drop_super(sb); | ||
| 5703 | spin_lock(&sb_lock); | ||
| 5704 | spin_lock(&sb_security_lock); | ||
| 5705 | list_del_init(&sbsec->list); | ||
| 5706 | goto next_sb; | ||
| 5707 | } | ||
| 5708 | spin_unlock(&sb_security_lock); | ||
| 5709 | spin_unlock(&sb_lock); | ||
| 5710 | } | 5609 | } |
| 5711 | 5610 | ||
| 5712 | /* SELinux requires early initialization in order to label | 5611 | /* SELinux requires early initialization in order to label |
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 8b32e959bb2e..b4c9eb4bd6f9 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" | 2 | "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" |
| 3 | 3 | ||
| 4 | #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ | 4 | #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ |
| 5 | "rename", "execute", "swapon", "quotaon", "mounton" | 5 | "rename", "execute", "swapon", "quotaon", "mounton", "audit_access", \ |
| 6 | "open", "execmod" | ||
| 6 | 7 | ||
| 7 | #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ | 8 | #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ |
| 8 | "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ | 9 | "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ |
| @@ -43,22 +44,21 @@ struct security_class_mapping secclass_map[] = { | |||
| 43 | "quotaget", NULL } }, | 44 | "quotaget", NULL } }, |
| 44 | { "file", | 45 | { "file", |
| 45 | { COMMON_FILE_PERMS, | 46 | { COMMON_FILE_PERMS, |
| 46 | "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, | 47 | "execute_no_trans", "entrypoint", NULL } }, |
| 47 | { "dir", | 48 | { "dir", |
| 48 | { COMMON_FILE_PERMS, "add_name", "remove_name", | 49 | { COMMON_FILE_PERMS, "add_name", "remove_name", |
| 49 | "reparent", "search", "rmdir", "open", NULL } }, | 50 | "reparent", "search", "rmdir", NULL } }, |
| 50 | { "fd", { "use", NULL } }, | 51 | { "fd", { "use", NULL } }, |
| 51 | { "lnk_file", | 52 | { "lnk_file", |
| 52 | { COMMON_FILE_PERMS, NULL } }, | 53 | { COMMON_FILE_PERMS, NULL } }, |
| 53 | { "chr_file", | 54 | { "chr_file", |
| 54 | { COMMON_FILE_PERMS, | 55 | { COMMON_FILE_PERMS, NULL } }, |
| 55 | "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, | ||
| 56 | { "blk_file", | 56 | { "blk_file", |
| 57 | { COMMON_FILE_PERMS, "open", NULL } }, | 57 | { COMMON_FILE_PERMS, NULL } }, |
| 58 | { "sock_file", | 58 | { "sock_file", |
| 59 | { COMMON_FILE_PERMS, "open", NULL } }, | 59 | { COMMON_FILE_PERMS, NULL } }, |
| 60 | { "fifo_file", | 60 | { "fifo_file", |
| 61 | { COMMON_FILE_PERMS, "open", NULL } }, | 61 | { COMMON_FILE_PERMS, NULL } }, |
| 62 | { "socket", | 62 | { "socket", |
| 63 | { COMMON_SOCK_PERMS, NULL } }, | 63 | { COMMON_SOCK_PERMS, NULL } }, |
| 64 | { "tcp_socket", | 64 | { "tcp_socket", |
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/netlabel.c b/security/selinux/netlabel.c index 628da72ee763..1c2fc46544bf 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
| @@ -132,21 +132,21 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) | |||
| 132 | 132 | ||
| 133 | /** | 133 | /** |
| 134 | * selinux_netlbl_sk_security_free - Free the NetLabel fields | 134 | * selinux_netlbl_sk_security_free - Free the NetLabel fields |
| 135 | * @sssec: the sk_security_struct | 135 | * @sksec: the sk_security_struct |
| 136 | * | 136 | * |
| 137 | * Description: | 137 | * Description: |
| 138 | * 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. |
| 139 | * | 139 | * |
| 140 | */ | 140 | */ |
| 141 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | 141 | void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) |
| 142 | { | 142 | { |
| 143 | if (ssec->nlbl_secattr != NULL) | 143 | if (sksec->nlbl_secattr != NULL) |
| 144 | netlbl_secattr_free(ssec->nlbl_secattr); | 144 | netlbl_secattr_free(sksec->nlbl_secattr); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | /** | 147 | /** |
| 148 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields | 148 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields |
| 149 | * @ssec: the sk_security_struct | 149 | * @sksec: the sk_security_struct |
| 150 | * @family: the socket family | 150 | * @family: the socket family |
| 151 | * | 151 | * |
| 152 | * Description: | 152 | * Description: |
| @@ -154,9 +154,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | |||
| 154 | * 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. |
| 155 | * | 155 | * |
| 156 | */ | 156 | */ |
| 157 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec) | 157 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) |
| 158 | { | 158 | { |
| 159 | ssec->nlbl_state = NLBL_UNSET; | 159 | sksec->nlbl_state = NLBL_UNSET; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | /** | 162 | /** |
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 0e147b6914ad..36ac257cec9a 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/list.h> | ||
| 18 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
| 19 | #include <linux/netlink.h> | 18 | #include <linux/netlink.h> |
| 20 | #include <linux/selinux_netlink.h> | 19 | #include <linux/selinux_netlink.h> |
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index dc92792271f1..65ebfe954f85 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
| @@ -183,8 +183,6 @@ static void sel_netnode_insert(struct sel_netnode *node) | |||
| 183 | BUG(); | 183 | BUG(); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | INIT_RCU_HEAD(&node->rcu); | ||
| 187 | |||
| 188 | /* we need to impose a limit on the growth of the hash table so check | 186 | /* we need to impose a limit on the growth of the hash table so check |
| 189 | * this bucket to make sure it is within the specified bounds */ | 187 | * this bucket to make sure it is within the specified bounds */ |
| 190 | list_add_rcu(&node->list, &sel_netnode_hash[idx].list); | 188 | list_add_rcu(&node->list, &sel_netnode_hash[idx].list); |
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 cd191bbec03c..79a1bb635662 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -184,6 +184,7 @@ out: | |||
| 184 | static const struct file_operations sel_enforce_ops = { | 184 | static const struct file_operations sel_enforce_ops = { |
| 185 | .read = sel_read_enforce, | 185 | .read = sel_read_enforce, |
| 186 | .write = sel_write_enforce, | 186 | .write = sel_write_enforce, |
| 187 | .llseek = generic_file_llseek, | ||
| 187 | }; | 188 | }; |
| 188 | 189 | ||
| 189 | static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, | 190 | static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, |
| @@ -201,6 +202,7 @@ static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, | |||
| 201 | 202 | ||
| 202 | static const struct file_operations sel_handle_unknown_ops = { | 203 | static const struct file_operations sel_handle_unknown_ops = { |
| 203 | .read = sel_read_handle_unknown, | 204 | .read = sel_read_handle_unknown, |
| 205 | .llseek = generic_file_llseek, | ||
| 204 | }; | 206 | }; |
| 205 | 207 | ||
| 206 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 208 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
| @@ -251,6 +253,7 @@ out: | |||
| 251 | 253 | ||
| 252 | static const struct file_operations sel_disable_ops = { | 254 | static const struct file_operations sel_disable_ops = { |
| 253 | .write = sel_write_disable, | 255 | .write = sel_write_disable, |
| 256 | .llseek = generic_file_llseek, | ||
| 254 | }; | 257 | }; |
| 255 | 258 | ||
| 256 | static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, | 259 | static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, |
| @@ -265,6 +268,7 @@ static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, | |||
| 265 | 268 | ||
| 266 | static const struct file_operations sel_policyvers_ops = { | 269 | static const struct file_operations sel_policyvers_ops = { |
| 267 | .read = sel_read_policyvers, | 270 | .read = sel_read_policyvers, |
| 271 | .llseek = generic_file_llseek, | ||
| 268 | }; | 272 | }; |
| 269 | 273 | ||
| 270 | /* declaration for sel_write_load */ | 274 | /* declaration for sel_write_load */ |
| @@ -289,6 +293,7 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf, | |||
| 289 | 293 | ||
| 290 | static const struct file_operations sel_mls_ops = { | 294 | static const struct file_operations sel_mls_ops = { |
| 291 | .read = sel_read_mls, | 295 | .read = sel_read_mls, |
| 296 | .llseek = generic_file_llseek, | ||
| 292 | }; | 297 | }; |
| 293 | 298 | ||
| 294 | static ssize_t sel_write_load(struct file *file, const char __user *buf, | 299 | static ssize_t sel_write_load(struct file *file, const char __user *buf, |
| @@ -356,6 +361,7 @@ out: | |||
| 356 | 361 | ||
| 357 | static const struct file_operations sel_load_ops = { | 362 | static const struct file_operations sel_load_ops = { |
| 358 | .write = sel_write_load, | 363 | .write = sel_write_load, |
| 364 | .llseek = generic_file_llseek, | ||
| 359 | }; | 365 | }; |
| 360 | 366 | ||
| 361 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) | 367 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) |
| @@ -437,6 +443,7 @@ out: | |||
| 437 | static const struct file_operations sel_checkreqprot_ops = { | 443 | static const struct file_operations sel_checkreqprot_ops = { |
| 438 | .read = sel_read_checkreqprot, | 444 | .read = sel_read_checkreqprot, |
| 439 | .write = sel_write_checkreqprot, | 445 | .write = sel_write_checkreqprot, |
| 446 | .llseek = generic_file_llseek, | ||
| 440 | }; | 447 | }; |
| 441 | 448 | ||
| 442 | /* | 449 | /* |
| @@ -482,6 +489,7 @@ static const struct file_operations transaction_ops = { | |||
| 482 | .write = selinux_transaction_write, | 489 | .write = selinux_transaction_write, |
| 483 | .read = simple_transaction_read, | 490 | .read = simple_transaction_read, |
| 484 | .release = simple_transaction_release, | 491 | .release = simple_transaction_release, |
| 492 | .llseek = generic_file_llseek, | ||
| 485 | }; | 493 | }; |
| 486 | 494 | ||
| 487 | /* | 495 | /* |
| @@ -503,11 +511,11 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
| 503 | return length; | 511 | return length; |
| 504 | 512 | ||
| 505 | length = -ENOMEM; | 513 | length = -ENOMEM; |
| 506 | scon = kzalloc(size+1, GFP_KERNEL); | 514 | scon = kzalloc(size + 1, GFP_KERNEL); |
| 507 | if (!scon) | 515 | if (!scon) |
| 508 | return length; | 516 | return length; |
| 509 | 517 | ||
| 510 | tcon = kzalloc(size+1, GFP_KERNEL); | 518 | tcon = kzalloc(size + 1, GFP_KERNEL); |
| 511 | if (!tcon) | 519 | if (!tcon) |
| 512 | goto out; | 520 | goto out; |
| 513 | 521 | ||
| @@ -515,10 +523,10 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
| 515 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 523 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
| 516 | goto out2; | 524 | goto out2; |
| 517 | 525 | ||
| 518 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 526 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
| 519 | if (length < 0) | 527 | if (length < 0) |
| 520 | goto out2; | 528 | goto out2; |
| 521 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 529 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
| 522 | if (length < 0) | 530 | if (length < 0) |
| 523 | goto out2; | 531 | goto out2; |
| 524 | 532 | ||
| @@ -550,11 +558,11 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
| 550 | return length; | 558 | return length; |
| 551 | 559 | ||
| 552 | length = -ENOMEM; | 560 | length = -ENOMEM; |
| 553 | scon = kzalloc(size+1, GFP_KERNEL); | 561 | scon = kzalloc(size + 1, GFP_KERNEL); |
| 554 | if (!scon) | 562 | if (!scon) |
| 555 | return length; | 563 | return length; |
| 556 | 564 | ||
| 557 | tcon = kzalloc(size+1, GFP_KERNEL); | 565 | tcon = kzalloc(size + 1, GFP_KERNEL); |
| 558 | if (!tcon) | 566 | if (!tcon) |
| 559 | goto out; | 567 | goto out; |
| 560 | 568 | ||
| @@ -562,10 +570,10 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
| 562 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 570 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
| 563 | goto out2; | 571 | goto out2; |
| 564 | 572 | ||
| 565 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 573 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
| 566 | if (length < 0) | 574 | if (length < 0) |
| 567 | goto out2; | 575 | goto out2; |
| 568 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 576 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
| 569 | if (length < 0) | 577 | if (length < 0) |
| 570 | goto out2; | 578 | goto out2; |
| 571 | 579 | ||
| @@ -609,11 +617,11 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
| 609 | return length; | 617 | return length; |
| 610 | 618 | ||
| 611 | length = -ENOMEM; | 619 | length = -ENOMEM; |
| 612 | scon = kzalloc(size+1, GFP_KERNEL); | 620 | scon = kzalloc(size + 1, GFP_KERNEL); |
| 613 | if (!scon) | 621 | if (!scon) |
| 614 | return length; | 622 | return length; |
| 615 | 623 | ||
| 616 | tcon = kzalloc(size+1, GFP_KERNEL); | 624 | tcon = kzalloc(size + 1, GFP_KERNEL); |
| 617 | if (!tcon) | 625 | if (!tcon) |
| 618 | goto out; | 626 | goto out; |
| 619 | 627 | ||
| @@ -621,10 +629,10 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
| 621 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 629 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
| 622 | goto out2; | 630 | goto out2; |
| 623 | 631 | ||
| 624 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 632 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
| 625 | if (length < 0) | 633 | if (length < 0) |
| 626 | goto out2; | 634 | goto out2; |
| 627 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 635 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
| 628 | if (length < 0) | 636 | if (length < 0) |
| 629 | goto out2; | 637 | goto out2; |
| 630 | 638 | ||
| @@ -666,11 +674,11 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
| 666 | return length; | 674 | return length; |
| 667 | 675 | ||
| 668 | length = -ENOMEM; | 676 | length = -ENOMEM; |
| 669 | con = kzalloc(size+1, GFP_KERNEL); | 677 | con = kzalloc(size + 1, GFP_KERNEL); |
| 670 | if (!con) | 678 | if (!con) |
| 671 | return length; | 679 | return length; |
| 672 | 680 | ||
| 673 | user = kzalloc(size+1, GFP_KERNEL); | 681 | user = kzalloc(size + 1, GFP_KERNEL); |
| 674 | if (!user) | 682 | if (!user) |
| 675 | goto out; | 683 | goto out; |
| 676 | 684 | ||
| @@ -678,7 +686,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
| 678 | if (sscanf(buf, "%s %s", con, user) != 2) | 686 | if (sscanf(buf, "%s %s", con, user) != 2) |
| 679 | goto out2; | 687 | goto out2; |
| 680 | 688 | ||
| 681 | length = security_context_to_sid(con, strlen(con)+1, &sid); | 689 | length = security_context_to_sid(con, strlen(con) + 1, &sid); |
| 682 | if (length < 0) | 690 | if (length < 0) |
| 683 | goto out2; | 691 | goto out2; |
| 684 | 692 | ||
| @@ -727,11 +735,11 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
| 727 | return length; | 735 | return length; |
| 728 | 736 | ||
| 729 | length = -ENOMEM; | 737 | length = -ENOMEM; |
| 730 | scon = kzalloc(size+1, GFP_KERNEL); | 738 | scon = kzalloc(size + 1, GFP_KERNEL); |
| 731 | if (!scon) | 739 | if (!scon) |
| 732 | return length; | 740 | return length; |
| 733 | 741 | ||
| 734 | tcon = kzalloc(size+1, GFP_KERNEL); | 742 | tcon = kzalloc(size + 1, GFP_KERNEL); |
| 735 | if (!tcon) | 743 | if (!tcon) |
| 736 | goto out; | 744 | goto out; |
| 737 | 745 | ||
| @@ -739,10 +747,10 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
| 739 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 747 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
| 740 | goto out2; | 748 | goto out2; |
| 741 | 749 | ||
| 742 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 750 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
| 743 | if (length < 0) | 751 | if (length < 0) |
| 744 | goto out2; | 752 | goto out2; |
| 745 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 753 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
| 746 | if (length < 0) | 754 | if (length < 0) |
| 747 | goto out2; | 755 | goto out2; |
| 748 | 756 | ||
| @@ -883,6 +891,7 @@ out: | |||
| 883 | static const struct file_operations sel_bool_ops = { | 891 | static const struct file_operations sel_bool_ops = { |
| 884 | .read = sel_read_bool, | 892 | .read = sel_read_bool, |
| 885 | .write = sel_write_bool, | 893 | .write = sel_write_bool, |
| 894 | .llseek = generic_file_llseek, | ||
| 886 | }; | 895 | }; |
| 887 | 896 | ||
| 888 | static ssize_t sel_commit_bools_write(struct file *filep, | 897 | static ssize_t sel_commit_bools_write(struct file *filep, |
| @@ -935,6 +944,7 @@ out: | |||
| 935 | 944 | ||
| 936 | static const struct file_operations sel_commit_bools_ops = { | 945 | static const struct file_operations sel_commit_bools_ops = { |
| 937 | .write = sel_commit_bools_write, | 946 | .write = sel_commit_bools_write, |
| 947 | .llseek = generic_file_llseek, | ||
| 938 | }; | 948 | }; |
| 939 | 949 | ||
| 940 | static void sel_remove_entries(struct dentry *de) | 950 | static void sel_remove_entries(struct dentry *de) |
| @@ -1127,10 +1137,12 @@ out: | |||
| 1127 | static const struct file_operations sel_avc_cache_threshold_ops = { | 1137 | static const struct file_operations sel_avc_cache_threshold_ops = { |
| 1128 | .read = sel_read_avc_cache_threshold, | 1138 | .read = sel_read_avc_cache_threshold, |
| 1129 | .write = sel_write_avc_cache_threshold, | 1139 | .write = sel_write_avc_cache_threshold, |
| 1140 | .llseek = generic_file_llseek, | ||
| 1130 | }; | 1141 | }; |
| 1131 | 1142 | ||
| 1132 | static const struct file_operations sel_avc_hash_stats_ops = { | 1143 | static const struct file_operations sel_avc_hash_stats_ops = { |
| 1133 | .read = sel_read_avc_hash_stats, | 1144 | .read = sel_read_avc_hash_stats, |
| 1145 | .llseek = generic_file_llseek, | ||
| 1134 | }; | 1146 | }; |
| 1135 | 1147 | ||
| 1136 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS | 1148 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS |
| @@ -1255,6 +1267,7 @@ static ssize_t sel_read_initcon(struct file *file, char __user *buf, | |||
| 1255 | 1267 | ||
| 1256 | static const struct file_operations sel_initcon_ops = { | 1268 | static const struct file_operations sel_initcon_ops = { |
| 1257 | .read = sel_read_initcon, | 1269 | .read = sel_read_initcon, |
| 1270 | .llseek = generic_file_llseek, | ||
| 1258 | }; | 1271 | }; |
| 1259 | 1272 | ||
| 1260 | static int sel_make_initcon_files(struct dentry *dir) | 1273 | static int sel_make_initcon_files(struct dentry *dir) |
| @@ -1330,6 +1343,7 @@ out: | |||
| 1330 | 1343 | ||
| 1331 | static const struct file_operations sel_class_ops = { | 1344 | static const struct file_operations sel_class_ops = { |
| 1332 | .read = sel_read_class, | 1345 | .read = sel_read_class, |
| 1346 | .llseek = generic_file_llseek, | ||
| 1333 | }; | 1347 | }; |
| 1334 | 1348 | ||
| 1335 | static ssize_t sel_read_perm(struct file *file, char __user *buf, | 1349 | static ssize_t sel_read_perm(struct file *file, char __user *buf, |
| @@ -1354,6 +1368,7 @@ out: | |||
| 1354 | 1368 | ||
| 1355 | static const struct file_operations sel_perm_ops = { | 1369 | static const struct file_operations sel_perm_ops = { |
| 1356 | .read = sel_read_perm, | 1370 | .read = sel_read_perm, |
| 1371 | .llseek = generic_file_llseek, | ||
| 1357 | }; | 1372 | }; |
| 1358 | 1373 | ||
| 1359 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, | 1374 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, |
| @@ -1372,6 +1387,7 @@ static ssize_t sel_read_policycap(struct file *file, char __user *buf, | |||
| 1372 | 1387 | ||
| 1373 | static const struct file_operations sel_policycap_ops = { | 1388 | static const struct file_operations sel_policycap_ops = { |
| 1374 | .read = sel_read_policycap, | 1389 | .read = sel_read_policycap, |
| 1390 | .llseek = generic_file_llseek, | ||
| 1375 | }; | 1391 | }; |
| 1376 | 1392 | ||
| 1377 | static int sel_make_perm_files(char *objclass, int classvalue, | 1393 | static int sel_make_perm_files(char *objclass, int classvalue, |
| @@ -1401,7 +1417,7 @@ static int sel_make_perm_files(char *objclass, int classvalue, | |||
| 1401 | } | 1417 | } |
| 1402 | inode->i_fop = &sel_perm_ops; | 1418 | inode->i_fop = &sel_perm_ops; |
| 1403 | /* i+1 since perm values are 1-indexed */ | 1419 | /* i+1 since perm values are 1-indexed */ |
| 1404 | inode->i_ino = sel_perm_to_ino(classvalue, i+1); | 1420 | inode->i_ino = sel_perm_to_ino(classvalue, i + 1); |
| 1405 | d_add(dentry, inode); | 1421 | d_add(dentry, inode); |
| 1406 | } | 1422 | } |
| 1407 | 1423 | ||
| @@ -1489,7 +1505,7 @@ static int sel_make_classes(void) | |||
| 1489 | goto out; | 1505 | goto out; |
| 1490 | 1506 | ||
| 1491 | /* +2 since classes are 1-indexed */ | 1507 | /* +2 since classes are 1-indexed */ |
| 1492 | last_class_ino = sel_class_to_ino(nclasses+2); | 1508 | last_class_ino = sel_class_to_ino(nclasses + 2); |
| 1493 | 1509 | ||
| 1494 | for (i = 0; i < nclasses; i++) { | 1510 | for (i = 0; i < nclasses; i++) { |
| 1495 | struct dentry *class_name_dir; | 1511 | struct dentry *class_name_dir; |
| @@ -1506,7 +1522,7 @@ static int sel_make_classes(void) | |||
| 1506 | goto out1; | 1522 | goto out1; |
| 1507 | 1523 | ||
| 1508 | /* i+1 since class values are 1-indexed */ | 1524 | /* i+1 since class values are 1-indexed */ |
| 1509 | rc = sel_make_class_dir_entries(classes[i], i+1, | 1525 | rc = sel_make_class_dir_entries(classes[i], i + 1, |
| 1510 | class_name_dir); | 1526 | class_name_dir); |
| 1511 | if (rc) | 1527 | if (rc) |
| 1512 | goto out1; | 1528 | goto out1; |
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 1215b8e47dba..929480c6c430 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c | |||
| @@ -342,20 +342,20 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
| 342 | 342 | ||
| 343 | if (vers < POLICYDB_VERSION_AVTAB) { | 343 | if (vers < POLICYDB_VERSION_AVTAB) { |
| 344 | rc = next_entry(buf32, fp, sizeof(u32)); | 344 | rc = next_entry(buf32, fp, sizeof(u32)); |
| 345 | if (rc < 0) { | 345 | if (rc) { |
| 346 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); | 346 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); |
| 347 | return -1; | 347 | return rc; |
| 348 | } | 348 | } |
| 349 | items2 = le32_to_cpu(buf32[0]); | 349 | items2 = le32_to_cpu(buf32[0]); |
| 350 | if (items2 > ARRAY_SIZE(buf32)) { | 350 | if (items2 > ARRAY_SIZE(buf32)) { |
| 351 | printk(KERN_ERR "SELinux: avtab: entry overflow\n"); | 351 | printk(KERN_ERR "SELinux: avtab: entry overflow\n"); |
| 352 | return -1; | 352 | return -EINVAL; |
| 353 | 353 | ||
| 354 | } | 354 | } |
| 355 | rc = next_entry(buf32, fp, sizeof(u32)*items2); | 355 | rc = next_entry(buf32, fp, sizeof(u32)*items2); |
| 356 | if (rc < 0) { | 356 | if (rc) { |
| 357 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); | 357 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); |
| 358 | return -1; | 358 | return rc; |
| 359 | } | 359 | } |
| 360 | items = 0; | 360 | items = 0; |
| 361 | 361 | ||
| @@ -363,19 +363,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
| 363 | key.source_type = (u16)val; | 363 | key.source_type = (u16)val; |
| 364 | if (key.source_type != val) { | 364 | if (key.source_type != val) { |
| 365 | printk(KERN_ERR "SELinux: avtab: truncated source type\n"); | 365 | printk(KERN_ERR "SELinux: avtab: truncated source type\n"); |
| 366 | return -1; | 366 | return -EINVAL; |
| 367 | } | 367 | } |
| 368 | val = le32_to_cpu(buf32[items++]); | 368 | val = le32_to_cpu(buf32[items++]); |
| 369 | key.target_type = (u16)val; | 369 | key.target_type = (u16)val; |
| 370 | if (key.target_type != val) { | 370 | if (key.target_type != val) { |
| 371 | printk(KERN_ERR "SELinux: avtab: truncated target type\n"); | 371 | printk(KERN_ERR "SELinux: avtab: truncated target type\n"); |
| 372 | return -1; | 372 | return -EINVAL; |
| 373 | } | 373 | } |
| 374 | val = le32_to_cpu(buf32[items++]); | 374 | val = le32_to_cpu(buf32[items++]); |
| 375 | key.target_class = (u16)val; | 375 | key.target_class = (u16)val; |
| 376 | if (key.target_class != val) { | 376 | if (key.target_class != val) { |
| 377 | printk(KERN_ERR "SELinux: avtab: truncated target class\n"); | 377 | printk(KERN_ERR "SELinux: avtab: truncated target class\n"); |
| 378 | return -1; | 378 | return -EINVAL; |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | val = le32_to_cpu(buf32[items++]); | 381 | val = le32_to_cpu(buf32[items++]); |
| @@ -383,12 +383,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
| 383 | 383 | ||
| 384 | if (!(val & (AVTAB_AV | AVTAB_TYPE))) { | 384 | if (!(val & (AVTAB_AV | AVTAB_TYPE))) { |
| 385 | printk(KERN_ERR "SELinux: avtab: null entry\n"); | 385 | printk(KERN_ERR "SELinux: avtab: null entry\n"); |
| 386 | return -1; | 386 | return -EINVAL; |
| 387 | } | 387 | } |
| 388 | if ((val & AVTAB_AV) && | 388 | if ((val & AVTAB_AV) && |
| 389 | (val & AVTAB_TYPE)) { | 389 | (val & AVTAB_TYPE)) { |
| 390 | printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); | 390 | printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); |
| 391 | return -1; | 391 | return -EINVAL; |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | for (i = 0; i < ARRAY_SIZE(spec_order); i++) { | 394 | for (i = 0; i < ARRAY_SIZE(spec_order); i++) { |
| @@ -403,15 +403,15 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
| 403 | 403 | ||
| 404 | if (items != items2) { | 404 | if (items != items2) { |
| 405 | printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items); | 405 | printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items); |
| 406 | return -1; | 406 | return -EINVAL; |
| 407 | } | 407 | } |
| 408 | return 0; | 408 | return 0; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | rc = next_entry(buf16, fp, sizeof(u16)*4); | 411 | rc = next_entry(buf16, fp, sizeof(u16)*4); |
| 412 | if (rc < 0) { | 412 | if (rc) { |
| 413 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); | 413 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); |
| 414 | return -1; | 414 | return rc; |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | items = 0; | 417 | items = 0; |
| @@ -424,7 +424,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
| 424 | !policydb_type_isvalid(pol, key.target_type) || | 424 | !policydb_type_isvalid(pol, key.target_type) || |
| 425 | !policydb_class_isvalid(pol, key.target_class)) { | 425 | !policydb_class_isvalid(pol, key.target_class)) { |
| 426 | printk(KERN_ERR "SELinux: avtab: invalid type or class\n"); | 426 | printk(KERN_ERR "SELinux: avtab: invalid type or class\n"); |
| 427 | return -1; | 427 | return -EINVAL; |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | set = 0; | 430 | set = 0; |
| @@ -434,19 +434,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
| 434 | } | 434 | } |
| 435 | if (!set || set > 1) { | 435 | if (!set || set > 1) { |
| 436 | printk(KERN_ERR "SELinux: avtab: more than one specifier\n"); | 436 | printk(KERN_ERR "SELinux: avtab: more than one specifier\n"); |
| 437 | return -1; | 437 | return -EINVAL; |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | rc = next_entry(buf32, fp, sizeof(u32)); | 440 | rc = next_entry(buf32, fp, sizeof(u32)); |
| 441 | if (rc < 0) { | 441 | if (rc) { |
| 442 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); | 442 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); |
| 443 | return -1; | 443 | return rc; |
| 444 | } | 444 | } |
| 445 | datum.data = le32_to_cpu(*buf32); | 445 | datum.data = le32_to_cpu(*buf32); |
| 446 | if ((key.specified & AVTAB_TYPE) && | 446 | if ((key.specified & AVTAB_TYPE) && |
| 447 | !policydb_type_isvalid(pol, datum.data)) { | 447 | !policydb_type_isvalid(pol, datum.data)) { |
| 448 | printk(KERN_ERR "SELinux: avtab: invalid type\n"); | 448 | printk(KERN_ERR "SELinux: avtab: invalid type\n"); |
| 449 | return -1; | 449 | return -EINVAL; |
| 450 | } | 450 | } |
| 451 | return insertf(a, &key, &datum, p); | 451 | return insertf(a, &key, &datum, p); |
| 452 | } | 452 | } |
| @@ -487,8 +487,7 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) | |||
| 487 | printk(KERN_ERR "SELinux: avtab: out of memory\n"); | 487 | printk(KERN_ERR "SELinux: avtab: out of memory\n"); |
| 488 | else if (rc == -EEXIST) | 488 | else if (rc == -EEXIST) |
| 489 | printk(KERN_ERR "SELinux: avtab: duplicate entry\n"); | 489 | printk(KERN_ERR "SELinux: avtab: duplicate entry\n"); |
| 490 | else | 490 | |
| 491 | rc = -EINVAL; | ||
| 492 | goto bad; | 491 | goto bad; |
| 493 | } | 492 | } |
| 494 | } | 493 | } |
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 4a4e35cac22b..c91e150c3087 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c | |||
| @@ -117,10 +117,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) | |||
| 117 | 117 | ||
| 118 | int cond_policydb_init(struct policydb *p) | 118 | int cond_policydb_init(struct policydb *p) |
| 119 | { | 119 | { |
| 120 | int rc; | ||
| 121 | |||
| 120 | p->bool_val_to_struct = NULL; | 122 | p->bool_val_to_struct = NULL; |
| 121 | p->cond_list = NULL; | 123 | p->cond_list = NULL; |
| 122 | if (avtab_init(&p->te_cond_avtab)) | 124 | |
| 123 | return -1; | 125 | rc = avtab_init(&p->te_cond_avtab); |
| 126 | if (rc) | ||
| 127 | return rc; | ||
| 124 | 128 | ||
| 125 | return 0; | 129 | return 0; |
| 126 | } | 130 | } |
| @@ -219,34 +223,37 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) | |||
| 219 | 223 | ||
| 220 | booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); | 224 | booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); |
| 221 | if (!booldatum) | 225 | if (!booldatum) |
| 222 | return -1; | 226 | return -ENOMEM; |
| 223 | 227 | ||
| 224 | rc = next_entry(buf, fp, sizeof buf); | 228 | rc = next_entry(buf, fp, sizeof buf); |
| 225 | if (rc < 0) | 229 | if (rc) |
| 226 | goto err; | 230 | goto err; |
| 227 | 231 | ||
| 228 | booldatum->value = le32_to_cpu(buf[0]); | 232 | booldatum->value = le32_to_cpu(buf[0]); |
| 229 | booldatum->state = le32_to_cpu(buf[1]); | 233 | booldatum->state = le32_to_cpu(buf[1]); |
| 230 | 234 | ||
| 235 | rc = -EINVAL; | ||
| 231 | if (!bool_isvalid(booldatum)) | 236 | if (!bool_isvalid(booldatum)) |
| 232 | goto err; | 237 | goto err; |
| 233 | 238 | ||
| 234 | len = le32_to_cpu(buf[2]); | 239 | len = le32_to_cpu(buf[2]); |
| 235 | 240 | ||
| 241 | rc = -ENOMEM; | ||
| 236 | key = kmalloc(len + 1, GFP_KERNEL); | 242 | key = kmalloc(len + 1, GFP_KERNEL); |
| 237 | if (!key) | 243 | if (!key) |
| 238 | goto err; | 244 | goto err; |
| 239 | rc = next_entry(key, fp, len); | 245 | rc = next_entry(key, fp, len); |
| 240 | if (rc < 0) | 246 | if (rc) |
| 241 | goto err; | 247 | goto err; |
| 242 | key[len] = '\0'; | 248 | key[len] = '\0'; |
| 243 | if (hashtab_insert(h, key, booldatum)) | 249 | rc = hashtab_insert(h, key, booldatum); |
| 250 | if (rc) | ||
| 244 | goto err; | 251 | goto err; |
| 245 | 252 | ||
| 246 | return 0; | 253 | return 0; |
| 247 | err: | 254 | err: |
| 248 | cond_destroy_bool(key, booldatum, NULL); | 255 | cond_destroy_bool(key, booldatum, NULL); |
| 249 | return -1; | 256 | return rc; |
| 250 | } | 257 | } |
| 251 | 258 | ||
| 252 | struct cond_insertf_data { | 259 | struct cond_insertf_data { |
| @@ -263,7 +270,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum | |||
| 263 | struct cond_av_list *other = data->other, *list, *cur; | 270 | struct cond_av_list *other = data->other, *list, *cur; |
| 264 | struct avtab_node *node_ptr; | 271 | struct avtab_node *node_ptr; |
| 265 | u8 found; | 272 | u8 found; |
| 266 | 273 | int rc = -EINVAL; | |
| 267 | 274 | ||
| 268 | /* | 275 | /* |
| 269 | * For type rules we have to make certain there aren't any | 276 | * For type rules we have to make certain there aren't any |
| @@ -313,12 +320,15 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum | |||
| 313 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); | 320 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); |
| 314 | if (!node_ptr) { | 321 | if (!node_ptr) { |
| 315 | printk(KERN_ERR "SELinux: could not insert rule.\n"); | 322 | printk(KERN_ERR "SELinux: could not insert rule.\n"); |
| 323 | rc = -ENOMEM; | ||
| 316 | goto err; | 324 | goto err; |
| 317 | } | 325 | } |
| 318 | 326 | ||
| 319 | list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); | 327 | list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); |
| 320 | if (!list) | 328 | if (!list) { |
| 329 | rc = -ENOMEM; | ||
| 321 | goto err; | 330 | goto err; |
| 331 | } | ||
| 322 | 332 | ||
| 323 | list->node = node_ptr; | 333 | list->node = node_ptr; |
| 324 | if (!data->head) | 334 | if (!data->head) |
| @@ -331,7 +341,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum | |||
| 331 | err: | 341 | err: |
| 332 | cond_av_list_destroy(data->head); | 342 | cond_av_list_destroy(data->head); |
| 333 | data->head = NULL; | 343 | data->head = NULL; |
| 334 | return -1; | 344 | return rc; |
| 335 | } | 345 | } |
| 336 | 346 | ||
| 337 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) | 347 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) |
| @@ -345,8 +355,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * | |||
| 345 | 355 | ||
| 346 | len = 0; | 356 | len = 0; |
| 347 | rc = next_entry(buf, fp, sizeof(u32)); | 357 | rc = next_entry(buf, fp, sizeof(u32)); |
| 348 | if (rc < 0) | 358 | if (rc) |
| 349 | return -1; | 359 | return rc; |
| 350 | 360 | ||
| 351 | len = le32_to_cpu(buf[0]); | 361 | len = le32_to_cpu(buf[0]); |
| 352 | if (len == 0) | 362 | if (len == 0) |
| @@ -361,7 +371,6 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * | |||
| 361 | &data); | 371 | &data); |
| 362 | if (rc) | 372 | if (rc) |
| 363 | return rc; | 373 | return rc; |
| 364 | |||
| 365 | } | 374 | } |
| 366 | 375 | ||
| 367 | *ret_list = data.head; | 376 | *ret_list = data.head; |
| @@ -390,24 +399,25 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | |||
| 390 | struct cond_expr *expr = NULL, *last = NULL; | 399 | struct cond_expr *expr = NULL, *last = NULL; |
| 391 | 400 | ||
| 392 | rc = next_entry(buf, fp, sizeof(u32)); | 401 | rc = next_entry(buf, fp, sizeof(u32)); |
| 393 | if (rc < 0) | 402 | if (rc) |
| 394 | return -1; | 403 | return rc; |
| 395 | 404 | ||
| 396 | node->cur_state = le32_to_cpu(buf[0]); | 405 | node->cur_state = le32_to_cpu(buf[0]); |
| 397 | 406 | ||
| 398 | len = 0; | 407 | len = 0; |
| 399 | rc = next_entry(buf, fp, sizeof(u32)); | 408 | rc = next_entry(buf, fp, sizeof(u32)); |
| 400 | if (rc < 0) | 409 | if (rc) |
| 401 | return -1; | 410 | return rc; |
| 402 | 411 | ||
| 403 | /* expr */ | 412 | /* expr */ |
| 404 | len = le32_to_cpu(buf[0]); | 413 | len = le32_to_cpu(buf[0]); |
| 405 | 414 | ||
| 406 | for (i = 0; i < len; i++) { | 415 | for (i = 0; i < len; i++) { |
| 407 | rc = next_entry(buf, fp, sizeof(u32) * 2); | 416 | rc = next_entry(buf, fp, sizeof(u32) * 2); |
| 408 | if (rc < 0) | 417 | if (rc) |
| 409 | goto err; | 418 | goto err; |
| 410 | 419 | ||
| 420 | rc = -ENOMEM; | ||
| 411 | expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); | 421 | expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); |
| 412 | if (!expr) | 422 | if (!expr) |
| 413 | goto err; | 423 | goto err; |
| @@ -416,6 +426,7 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | |||
| 416 | expr->bool = le32_to_cpu(buf[1]); | 426 | expr->bool = le32_to_cpu(buf[1]); |
| 417 | 427 | ||
| 418 | if (!expr_isvalid(p, expr)) { | 428 | if (!expr_isvalid(p, expr)) { |
| 429 | rc = -EINVAL; | ||
| 419 | kfree(expr); | 430 | kfree(expr); |
| 420 | goto err; | 431 | goto err; |
| 421 | } | 432 | } |
| @@ -427,14 +438,16 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | |||
| 427 | last = expr; | 438 | last = expr; |
| 428 | } | 439 | } |
| 429 | 440 | ||
| 430 | if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) | 441 | rc = cond_read_av_list(p, fp, &node->true_list, NULL); |
| 442 | if (rc) | ||
| 431 | goto err; | 443 | goto err; |
| 432 | if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0) | 444 | rc = cond_read_av_list(p, fp, &node->false_list, node->true_list); |
| 445 | if (rc) | ||
| 433 | goto err; | 446 | goto err; |
| 434 | return 0; | 447 | return 0; |
| 435 | err: | 448 | err: |
| 436 | cond_node_destroy(node); | 449 | cond_node_destroy(node); |
| 437 | return -1; | 450 | return rc; |
| 438 | } | 451 | } |
| 439 | 452 | ||
| 440 | int cond_read_list(struct policydb *p, void *fp) | 453 | int cond_read_list(struct policydb *p, void *fp) |
| @@ -445,8 +458,8 @@ int cond_read_list(struct policydb *p, void *fp) | |||
| 445 | int rc; | 458 | int rc; |
| 446 | 459 | ||
| 447 | rc = next_entry(buf, fp, sizeof buf); | 460 | rc = next_entry(buf, fp, sizeof buf); |
| 448 | if (rc < 0) | 461 | if (rc) |
| 449 | return -1; | 462 | return rc; |
| 450 | 463 | ||
| 451 | len = le32_to_cpu(buf[0]); | 464 | len = le32_to_cpu(buf[0]); |
| 452 | 465 | ||
| @@ -455,11 +468,13 @@ int cond_read_list(struct policydb *p, void *fp) | |||
| 455 | goto err; | 468 | goto err; |
| 456 | 469 | ||
| 457 | for (i = 0; i < len; i++) { | 470 | for (i = 0; i < len; i++) { |
| 471 | rc = -ENOMEM; | ||
| 458 | node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); | 472 | node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); |
| 459 | if (!node) | 473 | if (!node) |
| 460 | goto err; | 474 | goto err; |
| 461 | 475 | ||
| 462 | if (cond_read_node(p, node, fp) != 0) | 476 | rc = cond_read_node(p, node, fp); |
| 477 | if (rc) | ||
| 463 | goto err; | 478 | goto err; |
| 464 | 479 | ||
| 465 | if (i == 0) | 480 | if (i == 0) |
| @@ -472,7 +487,7 @@ int cond_read_list(struct policydb *p, void *fp) | |||
| 472 | err: | 487 | err: |
| 473 | cond_list_destroy(p->cond_list); | 488 | cond_list_destroy(p->cond_list); |
| 474 | p->cond_list = NULL; | 489 | p->cond_list = NULL; |
| 475 | return -1; | 490 | return rc; |
| 476 | } | 491 | } |
| 477 | 492 | ||
| 478 | /* Determine whether additional permissions are granted by the conditional | 493 | /* Determine whether additional permissions are granted by the conditional |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 372b773f8210..b4eff7a60c50 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
| @@ -255,7 +255,7 @@ int mls_context_to_sid(struct policydb *pol, | |||
| 255 | 255 | ||
| 256 | if (!pol->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 | ||
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 23c6e53c102c..3a29704be8ce 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
| 32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
| 33 | #include <linux/audit.h> | 33 | #include <linux/audit.h> |
| 34 | #include <linux/flex_array.h> | ||
| 34 | #include "security.h" | 35 | #include "security.h" |
| 35 | 36 | ||
| 36 | #include "policydb.h" | 37 | #include "policydb.h" |
| @@ -40,7 +41,7 @@ | |||
| 40 | #define _DEBUG_HASHES | 41 | #define _DEBUG_HASHES |
| 41 | 42 | ||
| 42 | #ifdef DEBUG_HASHES | 43 | #ifdef DEBUG_HASHES |
| 43 | static char *symtab_name[SYM_NUM] = { | 44 | static const char *symtab_name[SYM_NUM] = { |
| 44 | "common prefixes", | 45 | "common prefixes", |
| 45 | "classes", | 46 | "classes", |
| 46 | "roles", | 47 | "roles", |
| @@ -156,12 +157,11 @@ static int roles_init(struct policydb *p) | |||
| 156 | rc = -EINVAL; | 157 | rc = -EINVAL; |
| 157 | goto out_free_role; | 158 | goto out_free_role; |
| 158 | } | 159 | } |
| 159 | key = kmalloc(strlen(OBJECT_R)+1, GFP_KERNEL); | 160 | key = kstrdup(OBJECT_R, GFP_KERNEL); |
| 160 | if (!key) { | 161 | if (!key) { |
| 161 | rc = -ENOMEM; | 162 | rc = -ENOMEM; |
| 162 | goto out_free_role; | 163 | goto out_free_role; |
| 163 | } | 164 | } |
| 164 | strcpy(key, OBJECT_R); | ||
| 165 | rc = hashtab_insert(p->p_roles.table, key, role); | 165 | rc = hashtab_insert(p->p_roles.table, key, role); |
| 166 | if (rc) | 166 | if (rc) |
| 167 | goto out_free_key; | 167 | goto out_free_key; |
| @@ -656,6 +656,9 @@ static int range_tr_destroy(void *key, void *datum, void *p) | |||
| 656 | 656 | ||
| 657 | static void ocontext_destroy(struct ocontext *c, int i) | 657 | static void ocontext_destroy(struct ocontext *c, int i) |
| 658 | { | 658 | { |
| 659 | if (!c) | ||
| 660 | return; | ||
| 661 | |||
| 659 | context_destroy(&c->context[0]); | 662 | context_destroy(&c->context[0]); |
| 660 | context_destroy(&c->context[1]); | 663 | context_destroy(&c->context[1]); |
| 661 | if (i == OCON_ISID || i == OCON_FS || | 664 | if (i == OCON_ISID || i == OCON_FS || |
| @@ -737,11 +740,17 @@ void policydb_destroy(struct policydb *p) | |||
| 737 | hashtab_map(p->range_tr, range_tr_destroy, NULL); | 740 | hashtab_map(p->range_tr, range_tr_destroy, NULL); |
| 738 | hashtab_destroy(p->range_tr); | 741 | hashtab_destroy(p->range_tr); |
| 739 | 742 | ||
| 740 | if (p->type_attr_map) { | 743 | if (p->type_attr_map_array) { |
| 741 | for (i = 0; i < p->p_types.nprim; i++) | 744 | for (i = 0; i < p->p_types.nprim; i++) { |
| 742 | ebitmap_destroy(&p->type_attr_map[i]); | 745 | struct ebitmap *e; |
| 746 | |||
| 747 | e = flex_array_get(p->type_attr_map_array, i); | ||
| 748 | if (!e) | ||
| 749 | continue; | ||
| 750 | ebitmap_destroy(e); | ||
| 751 | } | ||
| 752 | flex_array_free(p->type_attr_map_array); | ||
| 743 | } | 753 | } |
| 744 | kfree(p->type_attr_map); | ||
| 745 | ebitmap_destroy(&p->policycaps); | 754 | ebitmap_destroy(&p->policycaps); |
| 746 | ebitmap_destroy(&p->permissive_map); | 755 | ebitmap_destroy(&p->permissive_map); |
| 747 | 756 | ||
| @@ -1702,6 +1711,333 @@ u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) | |||
| 1702 | return 1U << (perdatum->value-1); | 1711 | return 1U << (perdatum->value-1); |
| 1703 | } | 1712 | } |
| 1704 | 1713 | ||
| 1714 | static int range_read(struct policydb *p, void *fp) | ||
| 1715 | { | ||
| 1716 | struct range_trans *rt = NULL; | ||
| 1717 | struct mls_range *r = NULL; | ||
| 1718 | int i, rc; | ||
| 1719 | __le32 buf[2]; | ||
| 1720 | u32 nel; | ||
| 1721 | |||
| 1722 | if (p->policyvers < POLICYDB_VERSION_MLS) | ||
| 1723 | return 0; | ||
| 1724 | |||
| 1725 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1726 | if (rc) | ||
| 1727 | goto out; | ||
| 1728 | |||
| 1729 | nel = le32_to_cpu(buf[0]); | ||
| 1730 | for (i = 0; i < nel; i++) { | ||
| 1731 | rc = -ENOMEM; | ||
| 1732 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | ||
| 1733 | if (!rt) | ||
| 1734 | goto out; | ||
| 1735 | |||
| 1736 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | ||
| 1737 | if (rc) | ||
| 1738 | goto out; | ||
| 1739 | |||
| 1740 | rt->source_type = le32_to_cpu(buf[0]); | ||
| 1741 | rt->target_type = le32_to_cpu(buf[1]); | ||
| 1742 | if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) { | ||
| 1743 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1744 | if (rc) | ||
| 1745 | goto out; | ||
| 1746 | rt->target_class = le32_to_cpu(buf[0]); | ||
| 1747 | } else | ||
| 1748 | rt->target_class = p->process_class; | ||
| 1749 | |||
| 1750 | rc = -EINVAL; | ||
| 1751 | if (!policydb_type_isvalid(p, rt->source_type) || | ||
| 1752 | !policydb_type_isvalid(p, rt->target_type) || | ||
| 1753 | !policydb_class_isvalid(p, rt->target_class)) | ||
| 1754 | goto out; | ||
| 1755 | |||
| 1756 | rc = -ENOMEM; | ||
| 1757 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
| 1758 | if (!r) | ||
| 1759 | goto out; | ||
| 1760 | |||
| 1761 | rc = mls_read_range_helper(r, fp); | ||
| 1762 | if (rc) | ||
| 1763 | goto out; | ||
| 1764 | |||
| 1765 | rc = -EINVAL; | ||
| 1766 | if (!mls_range_isvalid(p, r)) { | ||
| 1767 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | ||
| 1768 | goto out; | ||
| 1769 | } | ||
| 1770 | |||
| 1771 | rc = hashtab_insert(p->range_tr, rt, r); | ||
| 1772 | if (rc) | ||
| 1773 | goto out; | ||
| 1774 | |||
| 1775 | rt = NULL; | ||
| 1776 | r = NULL; | ||
| 1777 | } | ||
| 1778 | rangetr_hash_eval(p->range_tr); | ||
| 1779 | rc = 0; | ||
| 1780 | out: | ||
| 1781 | kfree(rt); | ||
| 1782 | kfree(r); | ||
| 1783 | return rc; | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | static int genfs_read(struct policydb *p, void *fp) | ||
| 1787 | { | ||
| 1788 | int i, j, rc; | ||
| 1789 | u32 nel, nel2, len, len2; | ||
| 1790 | __le32 buf[1]; | ||
| 1791 | struct ocontext *l, *c; | ||
| 1792 | struct ocontext *newc = NULL; | ||
| 1793 | struct genfs *genfs_p, *genfs; | ||
| 1794 | struct genfs *newgenfs = NULL; | ||
| 1795 | |||
| 1796 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1797 | if (rc) | ||
| 1798 | goto out; | ||
| 1799 | nel = le32_to_cpu(buf[0]); | ||
| 1800 | |||
| 1801 | for (i = 0; i < nel; i++) { | ||
| 1802 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1803 | if (rc) | ||
| 1804 | goto out; | ||
| 1805 | len = le32_to_cpu(buf[0]); | ||
| 1806 | |||
| 1807 | rc = -ENOMEM; | ||
| 1808 | newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); | ||
| 1809 | if (!newgenfs) | ||
| 1810 | goto out; | ||
| 1811 | |||
| 1812 | rc = -ENOMEM; | ||
| 1813 | newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); | ||
| 1814 | if (!newgenfs->fstype) | ||
| 1815 | goto out; | ||
| 1816 | |||
| 1817 | rc = next_entry(newgenfs->fstype, fp, len); | ||
| 1818 | if (rc) | ||
| 1819 | goto out; | ||
| 1820 | |||
| 1821 | newgenfs->fstype[len] = 0; | ||
| 1822 | |||
| 1823 | for (genfs_p = NULL, genfs = p->genfs; genfs; | ||
| 1824 | genfs_p = genfs, genfs = genfs->next) { | ||
| 1825 | rc = -EINVAL; | ||
| 1826 | if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { | ||
| 1827 | printk(KERN_ERR "SELinux: dup genfs fstype %s\n", | ||
| 1828 | newgenfs->fstype); | ||
| 1829 | goto out; | ||
| 1830 | } | ||
| 1831 | if (strcmp(newgenfs->fstype, genfs->fstype) < 0) | ||
| 1832 | break; | ||
| 1833 | } | ||
| 1834 | newgenfs->next = genfs; | ||
| 1835 | if (genfs_p) | ||
| 1836 | genfs_p->next = newgenfs; | ||
| 1837 | else | ||
| 1838 | p->genfs = newgenfs; | ||
| 1839 | genfs = newgenfs; | ||
| 1840 | newgenfs = NULL; | ||
| 1841 | |||
| 1842 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1843 | if (rc) | ||
| 1844 | goto out; | ||
| 1845 | |||
| 1846 | nel2 = le32_to_cpu(buf[0]); | ||
| 1847 | for (j = 0; j < nel2; j++) { | ||
| 1848 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1849 | if (rc) | ||
| 1850 | goto out; | ||
| 1851 | len = le32_to_cpu(buf[0]); | ||
| 1852 | |||
| 1853 | rc = -ENOMEM; | ||
| 1854 | newc = kzalloc(sizeof(*newc), GFP_KERNEL); | ||
| 1855 | if (!newc) | ||
| 1856 | goto out; | ||
| 1857 | |||
| 1858 | rc = -ENOMEM; | ||
| 1859 | newc->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
| 1860 | if (!newc->u.name) | ||
| 1861 | goto out; | ||
| 1862 | |||
| 1863 | rc = next_entry(newc->u.name, fp, len); | ||
| 1864 | if (rc) | ||
| 1865 | goto out; | ||
| 1866 | newc->u.name[len] = 0; | ||
| 1867 | |||
| 1868 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1869 | if (rc) | ||
| 1870 | goto out; | ||
| 1871 | |||
| 1872 | newc->v.sclass = le32_to_cpu(buf[0]); | ||
| 1873 | rc = context_read_and_validate(&newc->context[0], p, fp); | ||
| 1874 | if (rc) | ||
| 1875 | goto out; | ||
| 1876 | |||
| 1877 | for (l = NULL, c = genfs->head; c; | ||
| 1878 | l = c, c = c->next) { | ||
| 1879 | rc = -EINVAL; | ||
| 1880 | if (!strcmp(newc->u.name, c->u.name) && | ||
| 1881 | (!c->v.sclass || !newc->v.sclass || | ||
| 1882 | newc->v.sclass == c->v.sclass)) { | ||
| 1883 | printk(KERN_ERR "SELinux: dup genfs entry (%s,%s)\n", | ||
| 1884 | genfs->fstype, c->u.name); | ||
| 1885 | goto out; | ||
| 1886 | } | ||
| 1887 | len = strlen(newc->u.name); | ||
| 1888 | len2 = strlen(c->u.name); | ||
| 1889 | if (len > len2) | ||
| 1890 | break; | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | newc->next = c; | ||
| 1894 | if (l) | ||
| 1895 | l->next = newc; | ||
| 1896 | else | ||
| 1897 | genfs->head = newc; | ||
| 1898 | newc = NULL; | ||
| 1899 | } | ||
| 1900 | } | ||
| 1901 | rc = 0; | ||
| 1902 | out: | ||
| 1903 | if (newgenfs) | ||
| 1904 | kfree(newgenfs->fstype); | ||
| 1905 | kfree(newgenfs); | ||
| 1906 | ocontext_destroy(newc, OCON_FSUSE); | ||
| 1907 | |||
| 1908 | return rc; | ||
| 1909 | } | ||
| 1910 | |||
| 1911 | static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | ||
| 1912 | void *fp) | ||
| 1913 | { | ||
| 1914 | int i, j, rc; | ||
| 1915 | u32 nel, len; | ||
| 1916 | __le32 buf[3]; | ||
| 1917 | struct ocontext *l, *c; | ||
| 1918 | u32 nodebuf[8]; | ||
| 1919 | |||
| 1920 | for (i = 0; i < info->ocon_num; i++) { | ||
| 1921 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1922 | if (rc) | ||
| 1923 | goto out; | ||
| 1924 | nel = le32_to_cpu(buf[0]); | ||
| 1925 | |||
| 1926 | l = NULL; | ||
| 1927 | for (j = 0; j < nel; j++) { | ||
| 1928 | rc = -ENOMEM; | ||
| 1929 | c = kzalloc(sizeof(*c), GFP_KERNEL); | ||
| 1930 | if (!c) | ||
| 1931 | goto out; | ||
| 1932 | if (l) | ||
| 1933 | l->next = c; | ||
| 1934 | else | ||
| 1935 | p->ocontexts[i] = c; | ||
| 1936 | l = c; | ||
| 1937 | |||
| 1938 | switch (i) { | ||
| 1939 | case OCON_ISID: | ||
| 1940 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1941 | if (rc) | ||
| 1942 | goto out; | ||
| 1943 | |||
| 1944 | c->sid[0] = le32_to_cpu(buf[0]); | ||
| 1945 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 1946 | if (rc) | ||
| 1947 | goto out; | ||
| 1948 | break; | ||
| 1949 | case OCON_FS: | ||
| 1950 | case OCON_NETIF: | ||
| 1951 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1952 | if (rc) | ||
| 1953 | goto out; | ||
| 1954 | len = le32_to_cpu(buf[0]); | ||
| 1955 | |||
| 1956 | rc = -ENOMEM; | ||
| 1957 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
| 1958 | if (!c->u.name) | ||
| 1959 | goto out; | ||
| 1960 | |||
| 1961 | rc = next_entry(c->u.name, fp, len); | ||
| 1962 | if (rc) | ||
| 1963 | goto out; | ||
| 1964 | |||
| 1965 | c->u.name[len] = 0; | ||
| 1966 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 1967 | if (rc) | ||
| 1968 | goto out; | ||
| 1969 | rc = context_read_and_validate(&c->context[1], p, fp); | ||
| 1970 | if (rc) | ||
| 1971 | goto out; | ||
| 1972 | break; | ||
| 1973 | case OCON_PORT: | ||
| 1974 | rc = next_entry(buf, fp, sizeof(u32)*3); | ||
| 1975 | if (rc) | ||
| 1976 | goto out; | ||
| 1977 | c->u.port.protocol = le32_to_cpu(buf[0]); | ||
| 1978 | c->u.port.low_port = le32_to_cpu(buf[1]); | ||
| 1979 | c->u.port.high_port = le32_to_cpu(buf[2]); | ||
| 1980 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 1981 | if (rc) | ||
| 1982 | goto out; | ||
| 1983 | break; | ||
| 1984 | case OCON_NODE: | ||
| 1985 | rc = next_entry(nodebuf, fp, sizeof(u32) * 2); | ||
| 1986 | if (rc) | ||
| 1987 | goto out; | ||
| 1988 | c->u.node.addr = nodebuf[0]; /* network order */ | ||
| 1989 | c->u.node.mask = nodebuf[1]; /* network order */ | ||
| 1990 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 1991 | if (rc) | ||
| 1992 | goto out; | ||
| 1993 | break; | ||
| 1994 | case OCON_FSUSE: | ||
| 1995 | rc = next_entry(buf, fp, sizeof(u32)*2); | ||
| 1996 | if (rc) | ||
| 1997 | goto out; | ||
| 1998 | |||
| 1999 | rc = -EINVAL; | ||
| 2000 | c->v.behavior = le32_to_cpu(buf[0]); | ||
| 2001 | if (c->v.behavior > SECURITY_FS_USE_NONE) | ||
| 2002 | goto out; | ||
| 2003 | |||
| 2004 | rc = -ENOMEM; | ||
| 2005 | len = le32_to_cpu(buf[1]); | ||
| 2006 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
| 2007 | if (!c->u.name) | ||
| 2008 | goto out; | ||
| 2009 | |||
| 2010 | rc = next_entry(c->u.name, fp, len); | ||
| 2011 | if (rc) | ||
| 2012 | goto out; | ||
| 2013 | c->u.name[len] = 0; | ||
| 2014 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 2015 | if (rc) | ||
| 2016 | goto out; | ||
| 2017 | break; | ||
| 2018 | case OCON_NODE6: { | ||
| 2019 | int k; | ||
| 2020 | |||
| 2021 | rc = next_entry(nodebuf, fp, sizeof(u32) * 8); | ||
| 2022 | if (rc) | ||
| 2023 | goto out; | ||
| 2024 | for (k = 0; k < 4; k++) | ||
| 2025 | c->u.node6.addr[k] = nodebuf[k]; | ||
| 2026 | for (k = 0; k < 4; k++) | ||
| 2027 | c->u.node6.mask[k] = nodebuf[k+4]; | ||
| 2028 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 2029 | if (rc) | ||
| 2030 | goto out; | ||
| 2031 | break; | ||
| 2032 | } | ||
| 2033 | } | ||
| 2034 | } | ||
| 2035 | } | ||
| 2036 | rc = 0; | ||
| 2037 | out: | ||
| 2038 | return rc; | ||
| 2039 | } | ||
| 2040 | |||
| 1705 | /* | 2041 | /* |
| 1706 | * Read the configuration data from a policy database binary | 2042 | * Read the configuration data from a policy database binary |
| 1707 | * representation file into a policy database structure. | 2043 | * representation file into a policy database structure. |
| @@ -1710,16 +2046,12 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1710 | { | 2046 | { |
| 1711 | struct role_allow *ra, *lra; | 2047 | struct role_allow *ra, *lra; |
| 1712 | struct role_trans *tr, *ltr; | 2048 | struct role_trans *tr, *ltr; |
| 1713 | struct ocontext *l, *c, *newc; | ||
| 1714 | struct genfs *genfs_p, *genfs, *newgenfs; | ||
| 1715 | int i, j, rc; | 2049 | int i, j, rc; |
| 1716 | __le32 buf[4]; | 2050 | __le32 buf[4]; |
| 1717 | u32 nodebuf[8]; | 2051 | u32 len, nprim, nel; |
| 1718 | u32 len, len2, nprim, nel, nel2; | 2052 | |
| 1719 | char *policydb_str; | 2053 | char *policydb_str; |
| 1720 | struct policydb_compat_info *info; | 2054 | struct policydb_compat_info *info; |
| 1721 | struct range_trans *rt; | ||
| 1722 | struct mls_range *r; | ||
| 1723 | 2055 | ||
| 1724 | rc = policydb_init(p); | 2056 | rc = policydb_init(p); |
| 1725 | if (rc) | 2057 | if (rc) |
| @@ -1920,294 +2252,45 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1920 | if (!p->process_trans_perms) | 2252 | if (!p->process_trans_perms) |
| 1921 | goto bad; | 2253 | goto bad; |
| 1922 | 2254 | ||
| 1923 | for (i = 0; i < info->ocon_num; i++) { | 2255 | rc = ocontext_read(p, info, fp); |
| 1924 | rc = next_entry(buf, fp, sizeof(u32)); | 2256 | if (rc) |
| 1925 | if (rc < 0) | ||
| 1926 | goto bad; | ||
| 1927 | nel = le32_to_cpu(buf[0]); | ||
| 1928 | l = NULL; | ||
| 1929 | for (j = 0; j < nel; j++) { | ||
| 1930 | c = kzalloc(sizeof(*c), GFP_KERNEL); | ||
| 1931 | if (!c) { | ||
| 1932 | rc = -ENOMEM; | ||
| 1933 | goto bad; | ||
| 1934 | } | ||
| 1935 | if (l) | ||
| 1936 | l->next = c; | ||
| 1937 | else | ||
| 1938 | p->ocontexts[i] = c; | ||
| 1939 | l = c; | ||
| 1940 | rc = -EINVAL; | ||
| 1941 | switch (i) { | ||
| 1942 | case OCON_ISID: | ||
| 1943 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1944 | if (rc < 0) | ||
| 1945 | goto bad; | ||
| 1946 | c->sid[0] = le32_to_cpu(buf[0]); | ||
| 1947 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 1948 | if (rc) | ||
| 1949 | goto bad; | ||
| 1950 | break; | ||
| 1951 | case OCON_FS: | ||
| 1952 | case OCON_NETIF: | ||
| 1953 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1954 | if (rc < 0) | ||
| 1955 | goto bad; | ||
| 1956 | len = le32_to_cpu(buf[0]); | ||
| 1957 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
| 1958 | if (!c->u.name) { | ||
| 1959 | rc = -ENOMEM; | ||
| 1960 | goto bad; | ||
| 1961 | } | ||
| 1962 | rc = next_entry(c->u.name, fp, len); | ||
| 1963 | if (rc < 0) | ||
| 1964 | goto bad; | ||
| 1965 | c->u.name[len] = 0; | ||
| 1966 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 1967 | if (rc) | ||
| 1968 | goto bad; | ||
| 1969 | rc = context_read_and_validate(&c->context[1], p, fp); | ||
| 1970 | if (rc) | ||
| 1971 | goto bad; | ||
| 1972 | break; | ||
| 1973 | case OCON_PORT: | ||
| 1974 | rc = next_entry(buf, fp, sizeof(u32)*3); | ||
| 1975 | if (rc < 0) | ||
| 1976 | goto bad; | ||
| 1977 | c->u.port.protocol = le32_to_cpu(buf[0]); | ||
| 1978 | c->u.port.low_port = le32_to_cpu(buf[1]); | ||
| 1979 | c->u.port.high_port = le32_to_cpu(buf[2]); | ||
| 1980 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 1981 | if (rc) | ||
| 1982 | goto bad; | ||
| 1983 | break; | ||
| 1984 | case OCON_NODE: | ||
| 1985 | rc = next_entry(nodebuf, fp, sizeof(u32) * 2); | ||
| 1986 | if (rc < 0) | ||
| 1987 | goto bad; | ||
| 1988 | c->u.node.addr = nodebuf[0]; /* network order */ | ||
| 1989 | c->u.node.mask = nodebuf[1]; /* network order */ | ||
| 1990 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 1991 | if (rc) | ||
| 1992 | goto bad; | ||
| 1993 | break; | ||
| 1994 | case OCON_FSUSE: | ||
| 1995 | rc = next_entry(buf, fp, sizeof(u32)*2); | ||
| 1996 | if (rc < 0) | ||
| 1997 | goto bad; | ||
| 1998 | c->v.behavior = le32_to_cpu(buf[0]); | ||
| 1999 | if (c->v.behavior > SECURITY_FS_USE_NONE) | ||
| 2000 | goto bad; | ||
| 2001 | len = le32_to_cpu(buf[1]); | ||
| 2002 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
| 2003 | if (!c->u.name) { | ||
| 2004 | rc = -ENOMEM; | ||
| 2005 | goto bad; | ||
| 2006 | } | ||
| 2007 | rc = next_entry(c->u.name, fp, len); | ||
| 2008 | if (rc < 0) | ||
| 2009 | goto bad; | ||
| 2010 | c->u.name[len] = 0; | ||
| 2011 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
| 2012 | if (rc) | ||
| 2013 | goto bad; | ||
| 2014 | break; | ||
| 2015 | case OCON_NODE6: { | ||
| 2016 | int k; | ||
| 2017 | |||
| 2018 | rc = next_entry(nodebuf, fp, sizeof(u32) * 8); | ||
| 2019 | if (rc < 0) | ||
| 2020 | goto bad; | ||
| 2021 | for (k = 0; k < 4; k++) | ||
| 2022 | c->u.node6.addr[k] = nodebuf[k]; | ||
| 2023 | for (k = 0; k < 4; k++) | ||
| 2024 | c->u.node6.mask[k] = nodebuf[k+4]; | ||
| 2025 | if (context_read_and_validate(&c->context[0], p, fp)) | ||
| 2026 | goto bad; | ||
| 2027 | break; | ||
| 2028 | } | ||
| 2029 | } | ||
| 2030 | } | ||
| 2031 | } | ||
| 2032 | |||
| 2033 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 2034 | if (rc < 0) | ||
| 2035 | goto bad; | 2257 | goto bad; |
| 2036 | nel = le32_to_cpu(buf[0]); | ||
| 2037 | genfs_p = NULL; | ||
| 2038 | rc = -EINVAL; | ||
| 2039 | for (i = 0; i < nel; i++) { | ||
| 2040 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 2041 | if (rc < 0) | ||
| 2042 | goto bad; | ||
| 2043 | len = le32_to_cpu(buf[0]); | ||
| 2044 | newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); | ||
| 2045 | if (!newgenfs) { | ||
| 2046 | rc = -ENOMEM; | ||
| 2047 | goto bad; | ||
| 2048 | } | ||
| 2049 | 2258 | ||
| 2050 | newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); | 2259 | rc = genfs_read(p, fp); |
| 2051 | if (!newgenfs->fstype) { | 2260 | if (rc) |
| 2052 | rc = -ENOMEM; | 2261 | goto bad; |
| 2053 | kfree(newgenfs); | ||
| 2054 | goto bad; | ||
| 2055 | } | ||
| 2056 | rc = next_entry(newgenfs->fstype, fp, len); | ||
| 2057 | if (rc < 0) { | ||
| 2058 | kfree(newgenfs->fstype); | ||
| 2059 | kfree(newgenfs); | ||
| 2060 | goto bad; | ||
| 2061 | } | ||
| 2062 | newgenfs->fstype[len] = 0; | ||
| 2063 | for (genfs_p = NULL, genfs = p->genfs; genfs; | ||
| 2064 | genfs_p = genfs, genfs = genfs->next) { | ||
| 2065 | if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { | ||
| 2066 | printk(KERN_ERR "SELinux: dup genfs " | ||
| 2067 | "fstype %s\n", newgenfs->fstype); | ||
| 2068 | kfree(newgenfs->fstype); | ||
| 2069 | kfree(newgenfs); | ||
| 2070 | goto bad; | ||
| 2071 | } | ||
| 2072 | if (strcmp(newgenfs->fstype, genfs->fstype) < 0) | ||
| 2073 | break; | ||
| 2074 | } | ||
| 2075 | newgenfs->next = genfs; | ||
| 2076 | if (genfs_p) | ||
| 2077 | genfs_p->next = newgenfs; | ||
| 2078 | else | ||
| 2079 | p->genfs = newgenfs; | ||
| 2080 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 2081 | if (rc < 0) | ||
| 2082 | goto bad; | ||
| 2083 | nel2 = le32_to_cpu(buf[0]); | ||
| 2084 | for (j = 0; j < nel2; j++) { | ||
| 2085 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 2086 | if (rc < 0) | ||
| 2087 | goto bad; | ||
| 2088 | len = le32_to_cpu(buf[0]); | ||
| 2089 | |||
| 2090 | newc = kzalloc(sizeof(*newc), GFP_KERNEL); | ||
| 2091 | if (!newc) { | ||
| 2092 | rc = -ENOMEM; | ||
| 2093 | goto bad; | ||
| 2094 | } | ||
| 2095 | |||
| 2096 | newc->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
| 2097 | if (!newc->u.name) { | ||
| 2098 | rc = -ENOMEM; | ||
| 2099 | goto bad_newc; | ||
| 2100 | } | ||
| 2101 | rc = next_entry(newc->u.name, fp, len); | ||
| 2102 | if (rc < 0) | ||
| 2103 | goto bad_newc; | ||
| 2104 | newc->u.name[len] = 0; | ||
| 2105 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 2106 | if (rc < 0) | ||
| 2107 | goto bad_newc; | ||
| 2108 | newc->v.sclass = le32_to_cpu(buf[0]); | ||
| 2109 | if (context_read_and_validate(&newc->context[0], p, fp)) | ||
| 2110 | goto bad_newc; | ||
| 2111 | for (l = NULL, c = newgenfs->head; c; | ||
| 2112 | l = c, c = c->next) { | ||
| 2113 | if (!strcmp(newc->u.name, c->u.name) && | ||
| 2114 | (!c->v.sclass || !newc->v.sclass || | ||
| 2115 | newc->v.sclass == c->v.sclass)) { | ||
| 2116 | printk(KERN_ERR "SELinux: dup genfs " | ||
| 2117 | "entry (%s,%s)\n", | ||
| 2118 | newgenfs->fstype, c->u.name); | ||
| 2119 | goto bad_newc; | ||
| 2120 | } | ||
| 2121 | len = strlen(newc->u.name); | ||
| 2122 | len2 = strlen(c->u.name); | ||
| 2123 | if (len > len2) | ||
| 2124 | break; | ||
| 2125 | } | ||
| 2126 | 2262 | ||
| 2127 | newc->next = c; | 2263 | rc = range_read(p, fp); |
| 2128 | if (l) | 2264 | if (rc) |
| 2129 | l->next = newc; | 2265 | goto bad; |
| 2130 | else | ||
| 2131 | newgenfs->head = newc; | ||
| 2132 | } | ||
| 2133 | } | ||
| 2134 | 2266 | ||
| 2135 | if (p->policyvers >= POLICYDB_VERSION_MLS) { | 2267 | rc = -ENOMEM; |
| 2136 | int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS; | 2268 | p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap), |
| 2137 | rc = next_entry(buf, fp, sizeof(u32)); | 2269 | p->p_types.nprim, |
| 2138 | if (rc < 0) | 2270 | GFP_KERNEL | __GFP_ZERO); |
| 2139 | goto bad; | 2271 | if (!p->type_attr_map_array) |
| 2140 | nel = le32_to_cpu(buf[0]); | 2272 | goto bad; |
| 2141 | for (i = 0; i < nel; i++) { | ||
| 2142 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | ||
| 2143 | if (!rt) { | ||
| 2144 | rc = -ENOMEM; | ||
| 2145 | goto bad; | ||
| 2146 | } | ||
| 2147 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | ||
| 2148 | if (rc < 0) { | ||
| 2149 | kfree(rt); | ||
| 2150 | goto bad; | ||
| 2151 | } | ||
| 2152 | rt->source_type = le32_to_cpu(buf[0]); | ||
| 2153 | rt->target_type = le32_to_cpu(buf[1]); | ||
| 2154 | if (new_rangetr) { | ||
| 2155 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 2156 | if (rc < 0) { | ||
| 2157 | kfree(rt); | ||
| 2158 | goto bad; | ||
| 2159 | } | ||
| 2160 | rt->target_class = le32_to_cpu(buf[0]); | ||
| 2161 | } else | ||
| 2162 | rt->target_class = p->process_class; | ||
| 2163 | if (!policydb_type_isvalid(p, rt->source_type) || | ||
| 2164 | !policydb_type_isvalid(p, rt->target_type) || | ||
| 2165 | !policydb_class_isvalid(p, rt->target_class)) { | ||
| 2166 | kfree(rt); | ||
| 2167 | rc = -EINVAL; | ||
| 2168 | goto bad; | ||
| 2169 | } | ||
| 2170 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
| 2171 | if (!r) { | ||
| 2172 | kfree(rt); | ||
| 2173 | rc = -ENOMEM; | ||
| 2174 | goto bad; | ||
| 2175 | } | ||
| 2176 | rc = mls_read_range_helper(r, fp); | ||
| 2177 | if (rc) { | ||
| 2178 | kfree(rt); | ||
| 2179 | kfree(r); | ||
| 2180 | goto bad; | ||
| 2181 | } | ||
| 2182 | if (!mls_range_isvalid(p, r)) { | ||
| 2183 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | ||
| 2184 | kfree(rt); | ||
| 2185 | kfree(r); | ||
| 2186 | goto bad; | ||
| 2187 | } | ||
| 2188 | rc = hashtab_insert(p->range_tr, rt, r); | ||
| 2189 | if (rc) { | ||
| 2190 | kfree(rt); | ||
| 2191 | kfree(r); | ||
| 2192 | goto bad; | ||
| 2193 | } | ||
| 2194 | } | ||
| 2195 | rangetr_hash_eval(p->range_tr); | ||
| 2196 | } | ||
| 2197 | 2273 | ||
| 2198 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | 2274 | /* preallocate so we don't have to worry about the put ever failing */ |
| 2199 | if (!p->type_attr_map) | 2275 | rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1, |
| 2276 | GFP_KERNEL | __GFP_ZERO); | ||
| 2277 | if (rc) | ||
| 2200 | goto bad; | 2278 | goto bad; |
| 2201 | 2279 | ||
| 2202 | for (i = 0; i < p->p_types.nprim; i++) { | 2280 | for (i = 0; i < p->p_types.nprim; i++) { |
| 2203 | ebitmap_init(&p->type_attr_map[i]); | 2281 | struct ebitmap *e = flex_array_get(p->type_attr_map_array, i); |
| 2282 | |||
| 2283 | BUG_ON(!e); | ||
| 2284 | ebitmap_init(e); | ||
| 2204 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { | 2285 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { |
| 2205 | if (ebitmap_read(&p->type_attr_map[i], fp)) | 2286 | rc = ebitmap_read(e, fp); |
| 2287 | if (rc) | ||
| 2206 | goto bad; | 2288 | goto bad; |
| 2207 | } | 2289 | } |
| 2208 | /* add the type itself as the degenerate case */ | 2290 | /* add the type itself as the degenerate case */ |
| 2209 | if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) | 2291 | rc = ebitmap_set_bit(e, i, 1); |
| 2210 | goto bad; | 2292 | if (rc) |
| 2293 | goto bad; | ||
| 2211 | } | 2294 | } |
| 2212 | 2295 | ||
| 2213 | rc = policydb_bounds_sanity_check(p); | 2296 | rc = policydb_bounds_sanity_check(p); |
| @@ -2217,8 +2300,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 2217 | rc = 0; | 2300 | rc = 0; |
| 2218 | out: | 2301 | out: |
| 2219 | return rc; | 2302 | return rc; |
| 2220 | bad_newc: | ||
| 2221 | ocontext_destroy(newc, OCON_FSUSE); | ||
| 2222 | bad: | 2303 | bad: |
| 2223 | if (!rc) | 2304 | if (!rc) |
| 2224 | rc = -EINVAL; | 2305 | rc = -EINVAL; |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 26d9adf8542b..310e94442cb8 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | #ifndef _SS_POLICYDB_H_ | 24 | #ifndef _SS_POLICYDB_H_ |
| 25 | #define _SS_POLICYDB_H_ | 25 | #define _SS_POLICYDB_H_ |
| 26 | 26 | ||
| 27 | #include <linux/flex_array.h> | ||
| 28 | |||
| 27 | #include "symtab.h" | 29 | #include "symtab.h" |
| 28 | #include "avtab.h" | 30 | #include "avtab.h" |
| 29 | #include "sidtab.h" | 31 | #include "sidtab.h" |
| @@ -246,7 +248,7 @@ struct policydb { | |||
| 246 | struct hashtab *range_tr; | 248 | struct hashtab *range_tr; |
| 247 | 249 | ||
| 248 | /* type -> attribute reverse mapping */ | 250 | /* type -> attribute reverse mapping */ |
| 249 | struct ebitmap *type_attr_map; | 251 | struct flex_array *type_attr_map_array; |
| 250 | 252 | ||
| 251 | struct ebitmap policycaps; | 253 | struct ebitmap policycaps; |
| 252 | 254 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index cf27b3ee1a95..9ea2feca3cd4 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | #include <linux/audit.h> | 50 | #include <linux/audit.h> |
| 51 | #include <linux/mutex.h> | 51 | #include <linux/mutex.h> |
| 52 | #include <linux/selinux.h> | 52 | #include <linux/selinux.h> |
| 53 | #include <linux/flex_array.h> | ||
| 53 | #include <net/netlabel.h> | 54 | #include <net/netlabel.h> |
| 54 | 55 | ||
| 55 | #include "flask.h" | 56 | #include "flask.h" |
| @@ -274,15 +275,15 @@ static int constraint_expr_eval(struct context *scontext, | |||
| 274 | case CEXPR_AND: | 275 | case CEXPR_AND: |
| 275 | BUG_ON(sp < 1); | 276 | BUG_ON(sp < 1); |
| 276 | sp--; | 277 | sp--; |
| 277 | s[sp] &= s[sp+1]; | 278 | s[sp] &= s[sp + 1]; |
| 278 | break; | 279 | break; |
| 279 | case CEXPR_OR: | 280 | case CEXPR_OR: |
| 280 | BUG_ON(sp < 1); | 281 | BUG_ON(sp < 1); |
| 281 | sp--; | 282 | sp--; |
| 282 | s[sp] |= s[sp+1]; | 283 | s[sp] |= s[sp + 1]; |
| 283 | break; | 284 | break; |
| 284 | case CEXPR_ATTR: | 285 | case CEXPR_ATTR: |
| 285 | if (sp == (CEXPR_MAXDEPTH-1)) | 286 | if (sp == (CEXPR_MAXDEPTH - 1)) |
| 286 | return 0; | 287 | return 0; |
| 287 | switch (e->attr) { | 288 | switch (e->attr) { |
| 288 | case CEXPR_USER: | 289 | case CEXPR_USER: |
| @@ -626,8 +627,10 @@ static void context_struct_compute_av(struct context *scontext, | |||
| 626 | */ | 627 | */ |
| 627 | avkey.target_class = tclass; | 628 | avkey.target_class = tclass; |
| 628 | avkey.specified = AVTAB_AV; | 629 | avkey.specified = AVTAB_AV; |
| 629 | sattr = &policydb.type_attr_map[scontext->type - 1]; | 630 | sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1); |
| 630 | tattr = &policydb.type_attr_map[tcontext->type - 1]; | 631 | BUG_ON(!sattr); |
| 632 | tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1); | ||
| 633 | BUG_ON(!tattr); | ||
| 631 | ebitmap_for_each_positive_bit(sattr, snode, i) { | 634 | ebitmap_for_each_positive_bit(sattr, snode, i) { |
| 632 | ebitmap_for_each_positive_bit(tattr, tnode, j) { | 635 | ebitmap_for_each_positive_bit(tattr, tnode, j) { |
| 633 | avkey.source_type = i + 1; | 636 | avkey.source_type = i + 1; |
| @@ -1216,7 +1219,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
| 1216 | *sid = SECSID_NULL; | 1219 | *sid = SECSID_NULL; |
| 1217 | 1220 | ||
| 1218 | /* Copy the string so that we can modify the copy as we parse it. */ | 1221 | /* Copy the string so that we can modify the copy as we parse it. */ |
| 1219 | scontext2 = kmalloc(scontext_len+1, gfp_flags); | 1222 | scontext2 = kmalloc(scontext_len + 1, gfp_flags); |
| 1220 | if (!scontext2) | 1223 | if (!scontext2) |
| 1221 | return -ENOMEM; | 1224 | return -ENOMEM; |
| 1222 | memcpy(scontext2, scontext, scontext_len); | 1225 | memcpy(scontext2, scontext, scontext_len); |
| @@ -1760,22 +1763,28 @@ int security_load_policy(void *data, size_t len) | |||
| 1760 | 1763 | ||
| 1761 | if (!ss_initialized) { | 1764 | if (!ss_initialized) { |
| 1762 | avtab_cache_init(); | 1765 | avtab_cache_init(); |
| 1763 | if (policydb_read(&policydb, fp)) { | 1766 | rc = policydb_read(&policydb, fp); |
| 1767 | if (rc) { | ||
| 1764 | avtab_cache_destroy(); | 1768 | avtab_cache_destroy(); |
| 1765 | return -EINVAL; | 1769 | return rc; |
| 1766 | } | 1770 | } |
| 1767 | if (selinux_set_mapping(&policydb, secclass_map, | 1771 | |
| 1768 | ¤t_mapping, | 1772 | rc = selinux_set_mapping(&policydb, secclass_map, |
| 1769 | ¤t_mapping_size)) { | 1773 | ¤t_mapping, |
| 1774 | ¤t_mapping_size); | ||
| 1775 | if (rc) { | ||
| 1770 | policydb_destroy(&policydb); | 1776 | policydb_destroy(&policydb); |
| 1771 | avtab_cache_destroy(); | 1777 | avtab_cache_destroy(); |
| 1772 | return -EINVAL; | 1778 | return rc; |
| 1773 | } | 1779 | } |
| 1774 | if (policydb_load_isids(&policydb, &sidtab)) { | 1780 | |
| 1781 | rc = policydb_load_isids(&policydb, &sidtab); | ||
| 1782 | if (rc) { | ||
| 1775 | policydb_destroy(&policydb); | 1783 | policydb_destroy(&policydb); |
| 1776 | avtab_cache_destroy(); | 1784 | avtab_cache_destroy(); |
| 1777 | return -EINVAL; | 1785 | return rc; |
| 1778 | } | 1786 | } |
| 1787 | |||
| 1779 | security_load_policycaps(); | 1788 | security_load_policycaps(); |
| 1780 | ss_initialized = 1; | 1789 | ss_initialized = 1; |
| 1781 | seqno = ++latest_granting; | 1790 | seqno = ++latest_granting; |
| @@ -1791,8 +1800,9 @@ int security_load_policy(void *data, size_t len) | |||
| 1791 | sidtab_hash_eval(&sidtab, "sids"); | 1800 | sidtab_hash_eval(&sidtab, "sids"); |
| 1792 | #endif | 1801 | #endif |
| 1793 | 1802 | ||
| 1794 | if (policydb_read(&newpolicydb, fp)) | 1803 | rc = policydb_read(&newpolicydb, fp); |
| 1795 | return -EINVAL; | 1804 | if (rc) |
| 1805 | return rc; | ||
| 1796 | 1806 | ||
| 1797 | /* If switching between different policy types, log MLS status */ | 1807 | /* If switching between different policy types, log MLS status */ |
| 1798 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) | 1808 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) |
| @@ -1807,8 +1817,8 @@ int security_load_policy(void *data, size_t len) | |||
| 1807 | return rc; | 1817 | return rc; |
| 1808 | } | 1818 | } |
| 1809 | 1819 | ||
| 1810 | if (selinux_set_mapping(&newpolicydb, secclass_map, | 1820 | rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size); |
| 1811 | &map, &map_size)) | 1821 | if (rc) |
| 1812 | goto err; | 1822 | goto err; |
| 1813 | 1823 | ||
| 1814 | rc = security_preserve_bools(&newpolicydb); | 1824 | rc = security_preserve_bools(&newpolicydb); |
| @@ -1819,10 +1829,10 @@ int security_load_policy(void *data, size_t len) | |||
| 1819 | 1829 | ||
| 1820 | /* Clone the SID table. */ | 1830 | /* Clone the SID table. */ |
| 1821 | sidtab_shutdown(&sidtab); | 1831 | sidtab_shutdown(&sidtab); |
| 1822 | if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { | 1832 | |
| 1823 | rc = -ENOMEM; | 1833 | rc = sidtab_map(&sidtab, clone_sid, &newsidtab); |
| 1834 | if (rc) | ||
| 1824 | goto err; | 1835 | goto err; |
| 1825 | } | ||
| 1826 | 1836 | ||
| 1827 | /* | 1837 | /* |
| 1828 | * Convert the internal representations of contexts | 1838 | * Convert the internal representations of contexts |
| @@ -2101,9 +2111,9 @@ int security_get_user_sids(u32 fromsid, | |||
| 2101 | 2111 | ||
| 2102 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { | 2112 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { |
| 2103 | role = policydb.role_val_to_struct[i]; | 2113 | role = policydb.role_val_to_struct[i]; |
| 2104 | usercon.role = i+1; | 2114 | usercon.role = i + 1; |
| 2105 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { | 2115 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { |
| 2106 | usercon.type = j+1; | 2116 | usercon.type = j + 1; |
| 2107 | 2117 | ||
| 2108 | if (mls_setup_user_range(fromcon, user, &usercon)) | 2118 | if (mls_setup_user_range(fromcon, user, &usercon)) |
| 2109 | continue; | 2119 | continue; |
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index bcf9f620426e..160326ee99e5 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c | |||
| @@ -36,7 +36,7 @@ int symtab_init(struct symtab *s, unsigned int size) | |||
| 36 | { | 36 | { |
| 37 | s->table = hashtab_create(symhash, symcmp, size); | 37 | s->table = hashtab_create(symhash, symcmp, size); |
| 38 | if (!s->table) | 38 | if (!s->table) |
| 39 | return -1; | 39 | return -ENOMEM; |
| 40 | s->nprim = 0; | 40 | s->nprim = 0; |
| 41 | return 0; | 41 | return 0; |
| 42 | } | 42 | } |
