diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/Makefile | 2 | ||||
-rw-r--r-- | security/selinux/avc.c | 25 | ||||
-rw-r--r-- | security/selinux/hooks.c | 292 | ||||
-rw-r--r-- | security/selinux/include/classmap.h | 16 | ||||
-rw-r--r-- | security/selinux/netnode.c | 2 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 16 | ||||
-rw-r--r-- | security/selinux/ss/avtab.c | 39 | ||||
-rw-r--r-- | security/selinux/ss/conditional.c | 65 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 658 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 4 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 7 | ||||
-rw-r--r-- | security/selinux/ss/symtab.c | 2 |
12 files changed, 599 insertions, 529 deletions
diff --git a/security/selinux/Makefile b/security/selinux/Makefile index f013982df417..58d80f3bd6f6 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile | |||
@@ -25,6 +25,6 @@ $(obj)/avc.o: $(obj)/flask.h | |||
25 | quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h | 25 | quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h |
26 | cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h | 26 | cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h |
27 | 27 | ||
28 | targets += flask.h | 28 | targets += flask.h av_permissions.h |
29 | $(obj)/flask.h: $(src)/include/classmap.h FORCE | 29 | $(obj)/flask.h: $(src)/include/classmap.h FORCE |
30 | $(call if_changed,flask) | 30 | $(call if_changed,flask) |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 7f1a304712a9..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; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2a8a0a915ff3..42043f96e54f 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); |
@@ -188,7 +185,7 @@ static inline u32 task_sid(const struct task_struct *task) | |||
188 | */ | 185 | */ |
189 | static inline u32 current_sid(void) | 186 | static inline u32 current_sid(void) |
190 | { | 187 | { |
191 | const struct task_security_struct *tsec = current_cred()->security; | 188 | const struct task_security_struct *tsec = current_security(); |
192 | 189 | ||
193 | return tsec->sid; | 190 | return tsec->sid; |
194 | } | 191 | } |
@@ -279,32 +276,6 @@ static void superblock_free_security(struct super_block *sb) | |||
279 | kfree(sbsec); | 276 | kfree(sbsec); |
280 | } | 277 | } |
281 | 278 | ||
282 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | ||
283 | { | ||
284 | struct sk_security_struct *sksec; | ||
285 | |||
286 | sksec = kzalloc(sizeof(*sksec), priority); | ||
287 | if (!sksec) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
291 | sksec->sid = SECINITSID_UNLABELED; | ||
292 | sk->sk_security = sksec; | ||
293 | |||
294 | selinux_netlbl_sk_security_reset(sksec); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static void sk_free_security(struct sock *sk) | ||
300 | { | ||
301 | struct sk_security_struct *sksec = sk->sk_security; | ||
302 | |||
303 | sk->sk_security = NULL; | ||
304 | selinux_netlbl_sk_security_free(sksec); | ||
305 | kfree(sksec); | ||
306 | } | ||
307 | |||
308 | /* The security server must be initialized before | 279 | /* The security server must be initialized before |
309 | any labeling or access decisions can be provided. */ | 280 | any labeling or access decisions can be provided. */ |
310 | extern int ss_initialized; | 281 | extern int ss_initialized; |
@@ -1584,8 +1555,7 @@ static int may_create(struct inode *dir, | |||
1584 | struct dentry *dentry, | 1555 | struct dentry *dentry, |
1585 | u16 tclass) | 1556 | u16 tclass) |
1586 | { | 1557 | { |
1587 | const struct cred *cred = current_cred(); | 1558 | const struct task_security_struct *tsec = current_security(); |
1588 | const struct task_security_struct *tsec = cred->security; | ||
1589 | struct inode_security_struct *dsec; | 1559 | struct inode_security_struct *dsec; |
1590 | struct superblock_security_struct *sbsec; | 1560 | struct superblock_security_struct *sbsec; |
1591 | u32 sid, newsid; | 1561 | u32 sid, newsid; |
@@ -1806,27 +1776,9 @@ static inline u32 open_file_to_av(struct file *file) | |||
1806 | { | 1776 | { |
1807 | u32 av = file_to_av(file); | 1777 | u32 av = file_to_av(file); |
1808 | 1778 | ||
1809 | if (selinux_policycap_openperm) { | 1779 | if (selinux_policycap_openperm) |
1810 | mode_t mode = file->f_path.dentry->d_inode->i_mode; | 1780 | av |= FILE__OPEN; |
1811 | /* | 1781 | |
1812 | * lnk files and socks do not really have an 'open' | ||
1813 | */ | ||
1814 | if (S_ISREG(mode)) | ||
1815 | av |= FILE__OPEN; | ||
1816 | else if (S_ISCHR(mode)) | ||
1817 | av |= CHR_FILE__OPEN; | ||
1818 | else if (S_ISBLK(mode)) | ||
1819 | av |= BLK_FILE__OPEN; | ||
1820 | else if (S_ISFIFO(mode)) | ||
1821 | av |= FIFO_FILE__OPEN; | ||
1822 | else if (S_ISDIR(mode)) | ||
1823 | av |= DIR__OPEN; | ||
1824 | else if (S_ISSOCK(mode)) | ||
1825 | av |= SOCK_FILE__OPEN; | ||
1826 | else | ||
1827 | printk(KERN_ERR "SELinux: WARNING: inside %s with " | ||
1828 | "unknown mode:%o\n", __func__, mode); | ||
1829 | } | ||
1830 | return av; | 1782 | return av; |
1831 | } | 1783 | } |
1832 | 1784 | ||
@@ -2183,8 +2135,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2183 | 2135 | ||
2184 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) | 2136 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) |
2185 | { | 2137 | { |
2186 | const struct cred *cred = current_cred(); | 2138 | const struct task_security_struct *tsec = current_security(); |
2187 | const struct task_security_struct *tsec = cred->security; | ||
2188 | u32 sid, osid; | 2139 | u32 sid, osid; |
2189 | int atsecure = 0; | 2140 | int atsecure = 0; |
2190 | 2141 | ||
@@ -2562,8 +2513,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2562 | char **name, void **value, | 2513 | char **name, void **value, |
2563 | size_t *len) | 2514 | size_t *len) |
2564 | { | 2515 | { |
2565 | const struct cred *cred = current_cred(); | 2516 | const struct task_security_struct *tsec = current_security(); |
2566 | const struct task_security_struct *tsec = cred->security; | ||
2567 | struct inode_security_struct *dsec; | 2517 | struct inode_security_struct *dsec; |
2568 | struct superblock_security_struct *sbsec; | 2518 | struct superblock_security_struct *sbsec; |
2569 | u32 sid, newsid, clen; | 2519 | u32 sid, newsid, clen; |
@@ -2679,14 +2629,26 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2679 | static int selinux_inode_permission(struct inode *inode, int mask) | 2629 | static int selinux_inode_permission(struct inode *inode, int mask) |
2680 | { | 2630 | { |
2681 | const struct cred *cred = current_cred(); | 2631 | const struct cred *cred = current_cred(); |
2632 | struct common_audit_data ad; | ||
2633 | u32 perms; | ||
2634 | bool from_access; | ||
2682 | 2635 | ||
2683 | if (!mask) { | 2636 | from_access = mask & MAY_ACCESS; |
2684 | /* No permission to check. Existence test. */ | 2637 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
2638 | |||
2639 | /* No permission to check. Existence test. */ | ||
2640 | if (!mask) | ||
2685 | return 0; | 2641 | return 0; |
2686 | } | ||
2687 | 2642 | ||
2688 | return inode_has_perm(cred, inode, | 2643 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2689 | file_mask_to_av(inode->i_mode, mask), NULL); | 2644 | ad.u.fs.inode = inode; |
2645 | |||
2646 | if (from_access) | ||
2647 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | ||
2648 | |||
2649 | perms = file_mask_to_av(inode->i_mode, mask); | ||
2650 | |||
2651 | return inode_has_perm(cred, inode, perms, &ad); | ||
2690 | } | 2652 | } |
2691 | 2653 | ||
2692 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2654 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
@@ -3675,71 +3637,54 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
3675 | } | 3637 | } |
3676 | 3638 | ||
3677 | /* socket security operations */ | 3639 | /* socket security operations */ |
3678 | static int socket_has_perm(struct task_struct *task, struct socket *sock, | 3640 | |
3679 | u32 perms) | 3641 | static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) |
3680 | { | 3642 | { |
3681 | struct inode_security_struct *isec; | 3643 | return tsec->sockcreate_sid ? : tsec->sid; |
3682 | struct common_audit_data ad; | 3644 | } |
3683 | u32 sid; | ||
3684 | int err = 0; | ||
3685 | 3645 | ||
3686 | isec = SOCK_INODE(sock)->i_security; | 3646 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
3647 | { | ||
3648 | struct sk_security_struct *sksec = sk->sk_security; | ||
3649 | struct common_audit_data ad; | ||
3650 | u32 tsid = task_sid(task); | ||
3687 | 3651 | ||
3688 | if (isec->sid == SECINITSID_KERNEL) | 3652 | if (sksec->sid == SECINITSID_KERNEL) |
3689 | goto out; | 3653 | return 0; |
3690 | sid = task_sid(task); | ||
3691 | 3654 | ||
3692 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3655 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3693 | ad.u.net.sk = sock->sk; | 3656 | ad.u.net.sk = sk; |
3694 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | ||
3695 | 3657 | ||
3696 | out: | 3658 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); |
3697 | return err; | ||
3698 | } | 3659 | } |
3699 | 3660 | ||
3700 | static int selinux_socket_create(int family, int type, | 3661 | static int selinux_socket_create(int family, int type, |
3701 | int protocol, int kern) | 3662 | int protocol, int kern) |
3702 | { | 3663 | { |
3703 | const struct cred *cred = current_cred(); | 3664 | const struct task_security_struct *tsec = current_security(); |
3704 | const struct task_security_struct *tsec = cred->security; | 3665 | u32 newsid; |
3705 | u32 sid, newsid; | ||
3706 | u16 secclass; | 3666 | u16 secclass; |
3707 | int err = 0; | ||
3708 | 3667 | ||
3709 | if (kern) | 3668 | if (kern) |
3710 | goto out; | 3669 | return 0; |
3711 | |||
3712 | sid = tsec->sid; | ||
3713 | newsid = tsec->sockcreate_sid ?: sid; | ||
3714 | 3670 | ||
3671 | newsid = socket_sockcreate_sid(tsec); | ||
3715 | secclass = socket_type_to_security_class(family, type, protocol); | 3672 | secclass = socket_type_to_security_class(family, type, protocol); |
3716 | err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); | 3673 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
3717 | |||
3718 | out: | ||
3719 | return err; | ||
3720 | } | 3674 | } |
3721 | 3675 | ||
3722 | static int selinux_socket_post_create(struct socket *sock, int family, | 3676 | static int selinux_socket_post_create(struct socket *sock, int family, |
3723 | int type, int protocol, int kern) | 3677 | int type, int protocol, int kern) |
3724 | { | 3678 | { |
3725 | const struct cred *cred = current_cred(); | 3679 | const struct task_security_struct *tsec = current_security(); |
3726 | const struct task_security_struct *tsec = cred->security; | 3680 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
3727 | struct inode_security_struct *isec; | ||
3728 | struct sk_security_struct *sksec; | 3681 | struct sk_security_struct *sksec; |
3729 | u32 sid, newsid; | ||
3730 | int err = 0; | 3682 | int err = 0; |
3731 | 3683 | ||
3732 | sid = tsec->sid; | ||
3733 | newsid = tsec->sockcreate_sid; | ||
3734 | |||
3735 | isec = SOCK_INODE(sock)->i_security; | ||
3736 | |||
3737 | if (kern) | 3684 | if (kern) |
3738 | isec->sid = SECINITSID_KERNEL; | 3685 | isec->sid = SECINITSID_KERNEL; |
3739 | else if (newsid) | ||
3740 | isec->sid = newsid; | ||
3741 | else | 3686 | else |
3742 | isec->sid = sid; | 3687 | isec->sid = socket_sockcreate_sid(tsec); |
3743 | 3688 | ||
3744 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 3689 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
3745 | isec->initialized = 1; | 3690 | isec->initialized = 1; |
@@ -3760,10 +3705,11 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
3760 | 3705 | ||
3761 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3706 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
3762 | { | 3707 | { |
3708 | struct sock *sk = sock->sk; | ||
3763 | u16 family; | 3709 | u16 family; |
3764 | int err; | 3710 | int err; |
3765 | 3711 | ||
3766 | err = socket_has_perm(current, sock, SOCKET__BIND); | 3712 | err = sock_has_perm(current, sk, SOCKET__BIND); |
3767 | if (err) | 3713 | if (err) |
3768 | goto out; | 3714 | goto out; |
3769 | 3715 | ||
@@ -3772,19 +3718,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3772 | * Multiple address binding for SCTP is not supported yet: we just | 3718 | * Multiple address binding for SCTP is not supported yet: we just |
3773 | * check the first address now. | 3719 | * check the first address now. |
3774 | */ | 3720 | */ |
3775 | family = sock->sk->sk_family; | 3721 | family = sk->sk_family; |
3776 | if (family == PF_INET || family == PF_INET6) { | 3722 | if (family == PF_INET || family == PF_INET6) { |
3777 | char *addrp; | 3723 | char *addrp; |
3778 | struct inode_security_struct *isec; | 3724 | struct sk_security_struct *sksec = sk->sk_security; |
3779 | struct common_audit_data ad; | 3725 | struct common_audit_data ad; |
3780 | struct sockaddr_in *addr4 = NULL; | 3726 | struct sockaddr_in *addr4 = NULL; |
3781 | struct sockaddr_in6 *addr6 = NULL; | 3727 | struct sockaddr_in6 *addr6 = NULL; |
3782 | unsigned short snum; | 3728 | unsigned short snum; |
3783 | struct sock *sk = sock->sk; | ||
3784 | u32 sid, node_perm; | 3729 | u32 sid, node_perm; |
3785 | 3730 | ||
3786 | isec = SOCK_INODE(sock)->i_security; | ||
3787 | |||
3788 | if (family == PF_INET) { | 3731 | if (family == PF_INET) { |
3789 | addr4 = (struct sockaddr_in *)address; | 3732 | addr4 = (struct sockaddr_in *)address; |
3790 | snum = ntohs(addr4->sin_port); | 3733 | snum = ntohs(addr4->sin_port); |
@@ -3808,15 +3751,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3808 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3751 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3809 | ad.u.net.sport = htons(snum); | 3752 | ad.u.net.sport = htons(snum); |
3810 | ad.u.net.family = family; | 3753 | ad.u.net.family = family; |
3811 | err = avc_has_perm(isec->sid, sid, | 3754 | err = avc_has_perm(sksec->sid, sid, |
3812 | isec->sclass, | 3755 | sksec->sclass, |
3813 | SOCKET__NAME_BIND, &ad); | 3756 | SOCKET__NAME_BIND, &ad); |
3814 | if (err) | 3757 | if (err) |
3815 | goto out; | 3758 | goto out; |
3816 | } | 3759 | } |
3817 | } | 3760 | } |
3818 | 3761 | ||
3819 | switch (isec->sclass) { | 3762 | switch (sksec->sclass) { |
3820 | case SECCLASS_TCP_SOCKET: | 3763 | case SECCLASS_TCP_SOCKET: |
3821 | node_perm = TCP_SOCKET__NODE_BIND; | 3764 | node_perm = TCP_SOCKET__NODE_BIND; |
3822 | break; | 3765 | break; |
@@ -3847,8 +3790,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3847 | else | 3790 | else |
3848 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); | 3791 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); |
3849 | 3792 | ||
3850 | err = avc_has_perm(isec->sid, sid, | 3793 | err = avc_has_perm(sksec->sid, sid, |
3851 | isec->sclass, node_perm, &ad); | 3794 | sksec->sclass, node_perm, &ad); |
3852 | if (err) | 3795 | if (err) |
3853 | goto out; | 3796 | goto out; |
3854 | } | 3797 | } |
@@ -3859,19 +3802,18 @@ out: | |||
3859 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3802 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
3860 | { | 3803 | { |
3861 | struct sock *sk = sock->sk; | 3804 | struct sock *sk = sock->sk; |
3862 | struct inode_security_struct *isec; | 3805 | struct sk_security_struct *sksec = sk->sk_security; |
3863 | int err; | 3806 | int err; |
3864 | 3807 | ||
3865 | err = socket_has_perm(current, sock, SOCKET__CONNECT); | 3808 | err = sock_has_perm(current, sk, SOCKET__CONNECT); |
3866 | if (err) | 3809 | if (err) |
3867 | return err; | 3810 | return err; |
3868 | 3811 | ||
3869 | /* | 3812 | /* |
3870 | * If a TCP or DCCP socket, check name_connect permission for the port. | 3813 | * If a TCP or DCCP socket, check name_connect permission for the port. |
3871 | */ | 3814 | */ |
3872 | isec = SOCK_INODE(sock)->i_security; | 3815 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
3873 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3816 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
3874 | isec->sclass == SECCLASS_DCCP_SOCKET) { | ||
3875 | struct common_audit_data ad; | 3817 | struct common_audit_data ad; |
3876 | struct sockaddr_in *addr4 = NULL; | 3818 | struct sockaddr_in *addr4 = NULL; |
3877 | struct sockaddr_in6 *addr6 = NULL; | 3819 | struct sockaddr_in6 *addr6 = NULL; |
@@ -3894,13 +3836,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3894 | if (err) | 3836 | if (err) |
3895 | goto out; | 3837 | goto out; |
3896 | 3838 | ||
3897 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3839 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
3898 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3840 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3899 | 3841 | ||
3900 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3842 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3901 | ad.u.net.dport = htons(snum); | 3843 | ad.u.net.dport = htons(snum); |
3902 | ad.u.net.family = sk->sk_family; | 3844 | ad.u.net.family = sk->sk_family; |
3903 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3845 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); |
3904 | if (err) | 3846 | if (err) |
3905 | goto out; | 3847 | goto out; |
3906 | } | 3848 | } |
@@ -3913,7 +3855,7 @@ out: | |||
3913 | 3855 | ||
3914 | static int selinux_socket_listen(struct socket *sock, int backlog) | 3856 | static int selinux_socket_listen(struct socket *sock, int backlog) |
3915 | { | 3857 | { |
3916 | return socket_has_perm(current, sock, SOCKET__LISTEN); | 3858 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); |
3917 | } | 3859 | } |
3918 | 3860 | ||
3919 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 3861 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
@@ -3922,7 +3864,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3922 | struct inode_security_struct *isec; | 3864 | struct inode_security_struct *isec; |
3923 | struct inode_security_struct *newisec; | 3865 | struct inode_security_struct *newisec; |
3924 | 3866 | ||
3925 | err = socket_has_perm(current, sock, SOCKET__ACCEPT); | 3867 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
3926 | if (err) | 3868 | if (err) |
3927 | return err; | 3869 | return err; |
3928 | 3870 | ||
@@ -3939,30 +3881,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3939 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3881 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
3940 | int size) | 3882 | int size) |
3941 | { | 3883 | { |
3942 | return socket_has_perm(current, sock, SOCKET__WRITE); | 3884 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); |
3943 | } | 3885 | } |
3944 | 3886 | ||
3945 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3887 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
3946 | int size, int flags) | 3888 | int size, int flags) |
3947 | { | 3889 | { |
3948 | return socket_has_perm(current, sock, SOCKET__READ); | 3890 | return sock_has_perm(current, sock->sk, SOCKET__READ); |
3949 | } | 3891 | } |
3950 | 3892 | ||
3951 | static int selinux_socket_getsockname(struct socket *sock) | 3893 | static int selinux_socket_getsockname(struct socket *sock) |
3952 | { | 3894 | { |
3953 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3895 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3954 | } | 3896 | } |
3955 | 3897 | ||
3956 | static int selinux_socket_getpeername(struct socket *sock) | 3898 | static int selinux_socket_getpeername(struct socket *sock) |
3957 | { | 3899 | { |
3958 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3900 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3959 | } | 3901 | } |
3960 | 3902 | ||
3961 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 3903 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
3962 | { | 3904 | { |
3963 | int err; | 3905 | int err; |
3964 | 3906 | ||
3965 | err = socket_has_perm(current, sock, SOCKET__SETOPT); | 3907 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); |
3966 | if (err) | 3908 | if (err) |
3967 | return err; | 3909 | return err; |
3968 | 3910 | ||
@@ -3972,68 +3914,58 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
3972 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3914 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
3973 | int optname) | 3915 | int optname) |
3974 | { | 3916 | { |
3975 | return socket_has_perm(current, sock, SOCKET__GETOPT); | 3917 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); |
3976 | } | 3918 | } |
3977 | 3919 | ||
3978 | static int selinux_socket_shutdown(struct socket *sock, int how) | 3920 | static int selinux_socket_shutdown(struct socket *sock, int how) |
3979 | { | 3921 | { |
3980 | return socket_has_perm(current, sock, SOCKET__SHUTDOWN); | 3922 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
3981 | } | 3923 | } |
3982 | 3924 | ||
3983 | static int selinux_socket_unix_stream_connect(struct socket *sock, | 3925 | static int selinux_socket_unix_stream_connect(struct socket *sock, |
3984 | struct socket *other, | 3926 | struct socket *other, |
3985 | struct sock *newsk) | 3927 | struct sock *newsk) |
3986 | { | 3928 | { |
3987 | struct sk_security_struct *sksec; | 3929 | struct sk_security_struct *sksec_sock = sock->sk->sk_security; |
3988 | struct inode_security_struct *isec; | 3930 | struct sk_security_struct *sksec_other = other->sk->sk_security; |
3989 | struct inode_security_struct *other_isec; | 3931 | struct sk_security_struct *sksec_new = newsk->sk_security; |
3990 | struct common_audit_data ad; | 3932 | struct common_audit_data ad; |
3991 | int err; | 3933 | int err; |
3992 | 3934 | ||
3993 | isec = SOCK_INODE(sock)->i_security; | ||
3994 | other_isec = SOCK_INODE(other)->i_security; | ||
3995 | |||
3996 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3935 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3997 | ad.u.net.sk = other->sk; | 3936 | ad.u.net.sk = other->sk; |
3998 | 3937 | ||
3999 | err = avc_has_perm(isec->sid, other_isec->sid, | 3938 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
4000 | isec->sclass, | 3939 | sksec_other->sclass, |
4001 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 3940 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
4002 | if (err) | 3941 | if (err) |
4003 | return err; | 3942 | return err; |
4004 | 3943 | ||
4005 | /* connecting socket */ | ||
4006 | sksec = sock->sk->sk_security; | ||
4007 | sksec->peer_sid = other_isec->sid; | ||
4008 | |||
4009 | /* server child socket */ | 3944 | /* server child socket */ |
4010 | sksec = newsk->sk_security; | 3945 | sksec_new->peer_sid = sksec_sock->sid; |
4011 | sksec->peer_sid = isec->sid; | 3946 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, |
4012 | err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); | 3947 | &sksec_new->sid); |
3948 | if (err) | ||
3949 | return err; | ||
4013 | 3950 | ||
4014 | return err; | 3951 | /* connecting socket */ |
3952 | sksec_sock->peer_sid = sksec_new->sid; | ||
3953 | |||
3954 | return 0; | ||
4015 | } | 3955 | } |
4016 | 3956 | ||
4017 | static int selinux_socket_unix_may_send(struct socket *sock, | 3957 | static int selinux_socket_unix_may_send(struct socket *sock, |
4018 | struct socket *other) | 3958 | struct socket *other) |
4019 | { | 3959 | { |
4020 | struct inode_security_struct *isec; | 3960 | struct sk_security_struct *ssec = sock->sk->sk_security; |
4021 | struct inode_security_struct *other_isec; | 3961 | struct sk_security_struct *osec = other->sk->sk_security; |
4022 | struct common_audit_data ad; | 3962 | struct common_audit_data ad; |
4023 | int err; | ||
4024 | |||
4025 | isec = SOCK_INODE(sock)->i_security; | ||
4026 | other_isec = SOCK_INODE(other)->i_security; | ||
4027 | 3963 | ||
4028 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3964 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4029 | ad.u.net.sk = other->sk; | 3965 | ad.u.net.sk = other->sk; |
4030 | 3966 | ||
4031 | err = avc_has_perm(isec->sid, other_isec->sid, | 3967 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, |
4032 | isec->sclass, SOCKET__SENDTO, &ad); | 3968 | &ad); |
4033 | if (err) | ||
4034 | return err; | ||
4035 | |||
4036 | return 0; | ||
4037 | } | 3969 | } |
4038 | 3970 | ||
4039 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 3971 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
@@ -4172,26 +4104,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4172 | int err = 0; | 4104 | int err = 0; |
4173 | char *scontext; | 4105 | char *scontext; |
4174 | u32 scontext_len; | 4106 | u32 scontext_len; |
4175 | struct sk_security_struct *sksec; | 4107 | struct sk_security_struct *sksec = sock->sk->sk_security; |
4176 | struct inode_security_struct *isec; | ||
4177 | u32 peer_sid = SECSID_NULL; | 4108 | u32 peer_sid = SECSID_NULL; |
4178 | 4109 | ||
4179 | isec = SOCK_INODE(sock)->i_security; | 4110 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
4180 | 4111 | sksec->sclass == SECCLASS_TCP_SOCKET) | |
4181 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | ||
4182 | isec->sclass == SECCLASS_TCP_SOCKET) { | ||
4183 | sksec = sock->sk->sk_security; | ||
4184 | peer_sid = sksec->peer_sid; | 4112 | peer_sid = sksec->peer_sid; |
4185 | } | 4113 | if (peer_sid == SECSID_NULL) |
4186 | if (peer_sid == SECSID_NULL) { | 4114 | return -ENOPROTOOPT; |
4187 | err = -ENOPROTOOPT; | ||
4188 | goto out; | ||
4189 | } | ||
4190 | 4115 | ||
4191 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 4116 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
4192 | |||
4193 | if (err) | 4117 | if (err) |
4194 | goto out; | 4118 | return err; |
4195 | 4119 | ||
4196 | if (scontext_len > len) { | 4120 | if (scontext_len > len) { |
4197 | err = -ERANGE; | 4121 | err = -ERANGE; |
@@ -4204,9 +4128,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4204 | out_len: | 4128 | out_len: |
4205 | if (put_user(scontext_len, optlen)) | 4129 | if (put_user(scontext_len, optlen)) |
4206 | err = -EFAULT; | 4130 | err = -EFAULT; |
4207 | |||
4208 | kfree(scontext); | 4131 | kfree(scontext); |
4209 | out: | ||
4210 | return err; | 4132 | return err; |
4211 | } | 4133 | } |
4212 | 4134 | ||
@@ -4238,12 +4160,27 @@ out: | |||
4238 | 4160 | ||
4239 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 4161 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
4240 | { | 4162 | { |
4241 | return sk_alloc_security(sk, family, priority); | 4163 | struct sk_security_struct *sksec; |
4164 | |||
4165 | sksec = kzalloc(sizeof(*sksec), priority); | ||
4166 | if (!sksec) | ||
4167 | return -ENOMEM; | ||
4168 | |||
4169 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
4170 | sksec->sid = SECINITSID_UNLABELED; | ||
4171 | selinux_netlbl_sk_security_reset(sksec); | ||
4172 | sk->sk_security = sksec; | ||
4173 | |||
4174 | return 0; | ||
4242 | } | 4175 | } |
4243 | 4176 | ||
4244 | static void selinux_sk_free_security(struct sock *sk) | 4177 | static void selinux_sk_free_security(struct sock *sk) |
4245 | { | 4178 | { |
4246 | sk_free_security(sk); | 4179 | struct sk_security_struct *sksec = sk->sk_security; |
4180 | |||
4181 | sk->sk_security = NULL; | ||
4182 | selinux_netlbl_sk_security_free(sksec); | ||
4183 | kfree(sksec); | ||
4247 | } | 4184 | } |
4248 | 4185 | ||
4249 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4186 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
@@ -4403,8 +4340,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4403 | int err = 0; | 4340 | int err = 0; |
4404 | u32 perm; | 4341 | u32 perm; |
4405 | struct nlmsghdr *nlh; | 4342 | struct nlmsghdr *nlh; |
4406 | struct socket *sock = sk->sk_socket; | 4343 | struct sk_security_struct *sksec = sk->sk_security; |
4407 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
4408 | 4344 | ||
4409 | if (skb->len < NLMSG_SPACE(0)) { | 4345 | if (skb->len < NLMSG_SPACE(0)) { |
4410 | err = -EINVAL; | 4346 | err = -EINVAL; |
@@ -4412,13 +4348,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4412 | } | 4348 | } |
4413 | nlh = nlmsg_hdr(skb); | 4349 | nlh = nlmsg_hdr(skb); |
4414 | 4350 | ||
4415 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); | 4351 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
4416 | if (err) { | 4352 | if (err) { |
4417 | if (err == -EINVAL) { | 4353 | if (err == -EINVAL) { |
4418 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4354 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
4419 | "SELinux: unrecognized netlink message" | 4355 | "SELinux: unrecognized netlink message" |
4420 | " type=%hu for sclass=%hu\n", | 4356 | " type=%hu for sclass=%hu\n", |
4421 | nlh->nlmsg_type, isec->sclass); | 4357 | nlh->nlmsg_type, sksec->sclass); |
4422 | if (!selinux_enforcing || security_get_allow_unknown()) | 4358 | if (!selinux_enforcing || security_get_allow_unknown()) |
4423 | err = 0; | 4359 | err = 0; |
4424 | } | 4360 | } |
@@ -4429,7 +4365,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4429 | goto out; | 4365 | goto out; |
4430 | } | 4366 | } |
4431 | 4367 | ||
4432 | err = socket_has_perm(current, sock, perm); | 4368 | err = sock_has_perm(current, sk, perm); |
4433 | out: | 4369 | out: |
4434 | return err; | 4370 | return err; |
4435 | } | 4371 | } |
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/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/selinuxfs.c b/security/selinux/selinuxfs.c index 0293843f7eda..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 | /* |
@@ -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, |
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/policydb.c b/security/selinux/ss/policydb.c index c57802a164d5..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" |
@@ -655,6 +656,9 @@ static int range_tr_destroy(void *key, void *datum, void *p) | |||
655 | 656 | ||
656 | static void ocontext_destroy(struct ocontext *c, int i) | 657 | static void ocontext_destroy(struct ocontext *c, int i) |
657 | { | 658 | { |
659 | if (!c) | ||
660 | return; | ||
661 | |||
658 | context_destroy(&c->context[0]); | 662 | context_destroy(&c->context[0]); |
659 | context_destroy(&c->context[1]); | 663 | context_destroy(&c->context[1]); |
660 | if (i == OCON_ISID || i == OCON_FS || | 664 | if (i == OCON_ISID || i == OCON_FS || |
@@ -736,11 +740,17 @@ void policydb_destroy(struct policydb *p) | |||
736 | hashtab_map(p->range_tr, range_tr_destroy, NULL); | 740 | hashtab_map(p->range_tr, range_tr_destroy, NULL); |
737 | hashtab_destroy(p->range_tr); | 741 | hashtab_destroy(p->range_tr); |
738 | 742 | ||
739 | if (p->type_attr_map) { | 743 | if (p->type_attr_map_array) { |
740 | for (i = 0; i < p->p_types.nprim; i++) | 744 | for (i = 0; i < p->p_types.nprim; i++) { |
741 | 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); | ||
742 | } | 753 | } |
743 | kfree(p->type_attr_map); | ||
744 | ebitmap_destroy(&p->policycaps); | 754 | ebitmap_destroy(&p->policycaps); |
745 | ebitmap_destroy(&p->permissive_map); | 755 | ebitmap_destroy(&p->permissive_map); |
746 | 756 | ||
@@ -1701,6 +1711,333 @@ u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) | |||
1701 | return 1U << (perdatum->value-1); | 1711 | return 1U << (perdatum->value-1); |
1702 | } | 1712 | } |
1703 | 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 | |||
1704 | /* | 2041 | /* |
1705 | * Read the configuration data from a policy database binary | 2042 | * Read the configuration data from a policy database binary |
1706 | * representation file into a policy database structure. | 2043 | * representation file into a policy database structure. |
@@ -1709,16 +2046,12 @@ int policydb_read(struct policydb *p, void *fp) | |||
1709 | { | 2046 | { |
1710 | struct role_allow *ra, *lra; | 2047 | struct role_allow *ra, *lra; |
1711 | struct role_trans *tr, *ltr; | 2048 | struct role_trans *tr, *ltr; |
1712 | struct ocontext *l, *c, *newc; | ||
1713 | struct genfs *genfs_p, *genfs, *newgenfs; | ||
1714 | int i, j, rc; | 2049 | int i, j, rc; |
1715 | __le32 buf[4]; | 2050 | __le32 buf[4]; |
1716 | u32 nodebuf[8]; | 2051 | u32 len, nprim, nel; |
1717 | u32 len, len2, nprim, nel, nel2; | 2052 | |
1718 | char *policydb_str; | 2053 | char *policydb_str; |
1719 | struct policydb_compat_info *info; | 2054 | struct policydb_compat_info *info; |
1720 | struct range_trans *rt; | ||
1721 | struct mls_range *r; | ||
1722 | 2055 | ||
1723 | rc = policydb_init(p); | 2056 | rc = policydb_init(p); |
1724 | if (rc) | 2057 | if (rc) |
@@ -1919,294 +2252,45 @@ int policydb_read(struct policydb *p, void *fp) | |||
1919 | if (!p->process_trans_perms) | 2252 | if (!p->process_trans_perms) |
1920 | goto bad; | 2253 | goto bad; |
1921 | 2254 | ||
1922 | for (i = 0; i < info->ocon_num; i++) { | 2255 | rc = ocontext_read(p, info, fp); |
1923 | rc = next_entry(buf, fp, sizeof(u32)); | 2256 | if (rc) |
1924 | if (rc < 0) | ||
1925 | goto bad; | ||
1926 | nel = le32_to_cpu(buf[0]); | ||
1927 | l = NULL; | ||
1928 | for (j = 0; j < nel; j++) { | ||
1929 | c = kzalloc(sizeof(*c), GFP_KERNEL); | ||
1930 | if (!c) { | ||
1931 | rc = -ENOMEM; | ||
1932 | goto bad; | ||
1933 | } | ||
1934 | if (l) | ||
1935 | l->next = c; | ||
1936 | else | ||
1937 | p->ocontexts[i] = c; | ||
1938 | l = c; | ||
1939 | rc = -EINVAL; | ||
1940 | switch (i) { | ||
1941 | case OCON_ISID: | ||
1942 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1943 | if (rc < 0) | ||
1944 | goto bad; | ||
1945 | c->sid[0] = le32_to_cpu(buf[0]); | ||
1946 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1947 | if (rc) | ||
1948 | goto bad; | ||
1949 | break; | ||
1950 | case OCON_FS: | ||
1951 | case OCON_NETIF: | ||
1952 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1953 | if (rc < 0) | ||
1954 | goto bad; | ||
1955 | len = le32_to_cpu(buf[0]); | ||
1956 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
1957 | if (!c->u.name) { | ||
1958 | rc = -ENOMEM; | ||
1959 | goto bad; | ||
1960 | } | ||
1961 | rc = next_entry(c->u.name, fp, len); | ||
1962 | if (rc < 0) | ||
1963 | goto bad; | ||
1964 | c->u.name[len] = 0; | ||
1965 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1966 | if (rc) | ||
1967 | goto bad; | ||
1968 | rc = context_read_and_validate(&c->context[1], p, fp); | ||
1969 | if (rc) | ||
1970 | goto bad; | ||
1971 | break; | ||
1972 | case OCON_PORT: | ||
1973 | rc = next_entry(buf, fp, sizeof(u32)*3); | ||
1974 | if (rc < 0) | ||
1975 | goto bad; | ||
1976 | c->u.port.protocol = le32_to_cpu(buf[0]); | ||
1977 | c->u.port.low_port = le32_to_cpu(buf[1]); | ||
1978 | c->u.port.high_port = le32_to_cpu(buf[2]); | ||
1979 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1980 | if (rc) | ||
1981 | goto bad; | ||
1982 | break; | ||
1983 | case OCON_NODE: | ||
1984 | rc = next_entry(nodebuf, fp, sizeof(u32) * 2); | ||
1985 | if (rc < 0) | ||
1986 | goto bad; | ||
1987 | c->u.node.addr = nodebuf[0]; /* network order */ | ||
1988 | c->u.node.mask = nodebuf[1]; /* network order */ | ||
1989 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1990 | if (rc) | ||
1991 | goto bad; | ||
1992 | break; | ||
1993 | case OCON_FSUSE: | ||
1994 | rc = next_entry(buf, fp, sizeof(u32)*2); | ||
1995 | if (rc < 0) | ||
1996 | goto bad; | ||
1997 | c->v.behavior = le32_to_cpu(buf[0]); | ||
1998 | if (c->v.behavior > SECURITY_FS_USE_NONE) | ||
1999 | goto bad; | ||
2000 | len = le32_to_cpu(buf[1]); | ||
2001 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
2002 | if (!c->u.name) { | ||
2003 | rc = -ENOMEM; | ||
2004 | goto bad; | ||
2005 | } | ||
2006 | rc = next_entry(c->u.name, fp, len); | ||
2007 | if (rc < 0) | ||
2008 | goto bad; | ||
2009 | c->u.name[len] = 0; | ||
2010 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
2011 | if (rc) | ||
2012 | goto bad; | ||
2013 | break; | ||
2014 | case OCON_NODE6: { | ||
2015 | int k; | ||
2016 | |||
2017 | rc = next_entry(nodebuf, fp, sizeof(u32) * 8); | ||
2018 | if (rc < 0) | ||
2019 | goto bad; | ||
2020 | for (k = 0; k < 4; k++) | ||
2021 | c->u.node6.addr[k] = nodebuf[k]; | ||
2022 | for (k = 0; k < 4; k++) | ||
2023 | c->u.node6.mask[k] = nodebuf[k+4]; | ||
2024 | if (context_read_and_validate(&c->context[0], p, fp)) | ||
2025 | goto bad; | ||
2026 | break; | ||
2027 | } | ||
2028 | } | ||
2029 | } | ||
2030 | } | ||
2031 | |||
2032 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2033 | if (rc < 0) | ||
2034 | goto bad; | 2257 | goto bad; |
2035 | nel = le32_to_cpu(buf[0]); | ||
2036 | genfs_p = NULL; | ||
2037 | rc = -EINVAL; | ||
2038 | for (i = 0; i < nel; i++) { | ||
2039 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2040 | if (rc < 0) | ||
2041 | goto bad; | ||
2042 | len = le32_to_cpu(buf[0]); | ||
2043 | newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); | ||
2044 | if (!newgenfs) { | ||
2045 | rc = -ENOMEM; | ||
2046 | goto bad; | ||
2047 | } | ||
2048 | 2258 | ||
2049 | newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); | 2259 | rc = genfs_read(p, fp); |
2050 | if (!newgenfs->fstype) { | 2260 | if (rc) |
2051 | rc = -ENOMEM; | 2261 | goto bad; |
2052 | kfree(newgenfs); | ||
2053 | goto bad; | ||
2054 | } | ||
2055 | rc = next_entry(newgenfs->fstype, fp, len); | ||
2056 | if (rc < 0) { | ||
2057 | kfree(newgenfs->fstype); | ||
2058 | kfree(newgenfs); | ||
2059 | goto bad; | ||
2060 | } | ||
2061 | newgenfs->fstype[len] = 0; | ||
2062 | for (genfs_p = NULL, genfs = p->genfs; genfs; | ||
2063 | genfs_p = genfs, genfs = genfs->next) { | ||
2064 | if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { | ||
2065 | printk(KERN_ERR "SELinux: dup genfs " | ||
2066 | "fstype %s\n", newgenfs->fstype); | ||
2067 | kfree(newgenfs->fstype); | ||
2068 | kfree(newgenfs); | ||
2069 | goto bad; | ||
2070 | } | ||
2071 | if (strcmp(newgenfs->fstype, genfs->fstype) < 0) | ||
2072 | break; | ||
2073 | } | ||
2074 | newgenfs->next = genfs; | ||
2075 | if (genfs_p) | ||
2076 | genfs_p->next = newgenfs; | ||
2077 | else | ||
2078 | p->genfs = newgenfs; | ||
2079 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2080 | if (rc < 0) | ||
2081 | goto bad; | ||
2082 | nel2 = le32_to_cpu(buf[0]); | ||
2083 | for (j = 0; j < nel2; j++) { | ||
2084 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2085 | if (rc < 0) | ||
2086 | goto bad; | ||
2087 | len = le32_to_cpu(buf[0]); | ||
2088 | |||
2089 | newc = kzalloc(sizeof(*newc), GFP_KERNEL); | ||
2090 | if (!newc) { | ||
2091 | rc = -ENOMEM; | ||
2092 | goto bad; | ||
2093 | } | ||
2094 | |||
2095 | newc->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
2096 | if (!newc->u.name) { | ||
2097 | rc = -ENOMEM; | ||
2098 | goto bad_newc; | ||
2099 | } | ||
2100 | rc = next_entry(newc->u.name, fp, len); | ||
2101 | if (rc < 0) | ||
2102 | goto bad_newc; | ||
2103 | newc->u.name[len] = 0; | ||
2104 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2105 | if (rc < 0) | ||
2106 | goto bad_newc; | ||
2107 | newc->v.sclass = le32_to_cpu(buf[0]); | ||
2108 | if (context_read_and_validate(&newc->context[0], p, fp)) | ||
2109 | goto bad_newc; | ||
2110 | for (l = NULL, c = newgenfs->head; c; | ||
2111 | l = c, c = c->next) { | ||
2112 | if (!strcmp(newc->u.name, c->u.name) && | ||
2113 | (!c->v.sclass || !newc->v.sclass || | ||
2114 | newc->v.sclass == c->v.sclass)) { | ||
2115 | printk(KERN_ERR "SELinux: dup genfs " | ||
2116 | "entry (%s,%s)\n", | ||
2117 | newgenfs->fstype, c->u.name); | ||
2118 | goto bad_newc; | ||
2119 | } | ||
2120 | len = strlen(newc->u.name); | ||
2121 | len2 = strlen(c->u.name); | ||
2122 | if (len > len2) | ||
2123 | break; | ||
2124 | } | ||
2125 | 2262 | ||
2126 | newc->next = c; | 2263 | rc = range_read(p, fp); |
2127 | if (l) | 2264 | if (rc) |
2128 | l->next = newc; | 2265 | goto bad; |
2129 | else | ||
2130 | newgenfs->head = newc; | ||
2131 | } | ||
2132 | } | ||
2133 | 2266 | ||
2134 | if (p->policyvers >= POLICYDB_VERSION_MLS) { | 2267 | rc = -ENOMEM; |
2135 | int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS; | 2268 | p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap), |
2136 | rc = next_entry(buf, fp, sizeof(u32)); | 2269 | p->p_types.nprim, |
2137 | if (rc < 0) | 2270 | GFP_KERNEL | __GFP_ZERO); |
2138 | goto bad; | 2271 | if (!p->type_attr_map_array) |
2139 | nel = le32_to_cpu(buf[0]); | 2272 | goto bad; |
2140 | for (i = 0; i < nel; i++) { | ||
2141 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | ||
2142 | if (!rt) { | ||
2143 | rc = -ENOMEM; | ||
2144 | goto bad; | ||
2145 | } | ||
2146 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | ||
2147 | if (rc < 0) { | ||
2148 | kfree(rt); | ||
2149 | goto bad; | ||
2150 | } | ||
2151 | rt->source_type = le32_to_cpu(buf[0]); | ||
2152 | rt->target_type = le32_to_cpu(buf[1]); | ||
2153 | if (new_rangetr) { | ||
2154 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2155 | if (rc < 0) { | ||
2156 | kfree(rt); | ||
2157 | goto bad; | ||
2158 | } | ||
2159 | rt->target_class = le32_to_cpu(buf[0]); | ||
2160 | } else | ||
2161 | rt->target_class = p->process_class; | ||
2162 | if (!policydb_type_isvalid(p, rt->source_type) || | ||
2163 | !policydb_type_isvalid(p, rt->target_type) || | ||
2164 | !policydb_class_isvalid(p, rt->target_class)) { | ||
2165 | kfree(rt); | ||
2166 | rc = -EINVAL; | ||
2167 | goto bad; | ||
2168 | } | ||
2169 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
2170 | if (!r) { | ||
2171 | kfree(rt); | ||
2172 | rc = -ENOMEM; | ||
2173 | goto bad; | ||
2174 | } | ||
2175 | rc = mls_read_range_helper(r, fp); | ||
2176 | if (rc) { | ||
2177 | kfree(rt); | ||
2178 | kfree(r); | ||
2179 | goto bad; | ||
2180 | } | ||
2181 | if (!mls_range_isvalid(p, r)) { | ||
2182 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | ||
2183 | kfree(rt); | ||
2184 | kfree(r); | ||
2185 | goto bad; | ||
2186 | } | ||
2187 | rc = hashtab_insert(p->range_tr, rt, r); | ||
2188 | if (rc) { | ||
2189 | kfree(rt); | ||
2190 | kfree(r); | ||
2191 | goto bad; | ||
2192 | } | ||
2193 | } | ||
2194 | rangetr_hash_eval(p->range_tr); | ||
2195 | } | ||
2196 | 2273 | ||
2197 | 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 */ |
2198 | 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) | ||
2199 | goto bad; | 2278 | goto bad; |
2200 | 2279 | ||
2201 | for (i = 0; i < p->p_types.nprim; i++) { | 2280 | for (i = 0; i < p->p_types.nprim; i++) { |
2202 | 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); | ||
2203 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { | 2285 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { |
2204 | if (ebitmap_read(&p->type_attr_map[i], fp)) | 2286 | rc = ebitmap_read(e, fp); |
2287 | if (rc) | ||
2205 | goto bad; | 2288 | goto bad; |
2206 | } | 2289 | } |
2207 | /* add the type itself as the degenerate case */ | 2290 | /* add the type itself as the degenerate case */ |
2208 | if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) | 2291 | rc = ebitmap_set_bit(e, i, 1); |
2209 | goto bad; | 2292 | if (rc) |
2293 | goto bad; | ||
2210 | } | 2294 | } |
2211 | 2295 | ||
2212 | rc = policydb_bounds_sanity_check(p); | 2296 | rc = policydb_bounds_sanity_check(p); |
@@ -2216,8 +2300,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
2216 | rc = 0; | 2300 | rc = 0; |
2217 | out: | 2301 | out: |
2218 | return rc; | 2302 | return rc; |
2219 | bad_newc: | ||
2220 | ocontext_destroy(newc, OCON_FSUSE); | ||
2221 | bad: | 2303 | bad: |
2222 | if (!rc) | 2304 | if (!rc) |
2223 | 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 1de60ce90d9a..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" |
@@ -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; |
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 | } |