diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 313 |
1 files changed, 128 insertions, 185 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5c9f25ba1c95..4796ddd4e721 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 | ||
@@ -2219,8 +2170,9 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2219 | 2170 | ||
2220 | tty = get_current_tty(); | 2171 | tty = get_current_tty(); |
2221 | if (tty) { | 2172 | if (tty) { |
2222 | file_list_lock(); | 2173 | spin_lock(&tty_files_lock); |
2223 | if (!list_empty(&tty->tty_files)) { | 2174 | if (!list_empty(&tty->tty_files)) { |
2175 | struct tty_file_private *file_priv; | ||
2224 | struct inode *inode; | 2176 | struct inode *inode; |
2225 | 2177 | ||
2226 | /* Revalidate access to controlling tty. | 2178 | /* Revalidate access to controlling tty. |
@@ -2228,14 +2180,16 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2228 | than using file_has_perm, as this particular open | 2180 | than using file_has_perm, as this particular open |
2229 | file may belong to another process and we are only | 2181 | file may belong to another process and we are only |
2230 | interested in the inode-based check here. */ | 2182 | interested in the inode-based check here. */ |
2231 | file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list); | 2183 | file_priv = list_first_entry(&tty->tty_files, |
2184 | struct tty_file_private, list); | ||
2185 | file = file_priv->file; | ||
2232 | inode = file->f_path.dentry->d_inode; | 2186 | inode = file->f_path.dentry->d_inode; |
2233 | if (inode_has_perm(cred, inode, | 2187 | if (inode_has_perm(cred, inode, |
2234 | FILE__READ | FILE__WRITE, NULL)) { | 2188 | FILE__READ | FILE__WRITE, NULL)) { |
2235 | drop_tty = 1; | 2189 | drop_tty = 1; |
2236 | } | 2190 | } |
2237 | } | 2191 | } |
2238 | file_list_unlock(); | 2192 | spin_unlock(&tty_files_lock); |
2239 | tty_kref_put(tty); | 2193 | tty_kref_put(tty); |
2240 | } | 2194 | } |
2241 | /* Reset controlling tty. */ | 2195 | /* Reset controlling tty. */ |
@@ -2333,12 +2287,15 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
2333 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, | 2287 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, |
2334 | PROCESS__RLIMITINH, NULL); | 2288 | PROCESS__RLIMITINH, NULL); |
2335 | if (rc) { | 2289 | if (rc) { |
2290 | /* protect against do_prlimit() */ | ||
2291 | task_lock(current); | ||
2336 | for (i = 0; i < RLIM_NLIMITS; i++) { | 2292 | for (i = 0; i < RLIM_NLIMITS; i++) { |
2337 | rlim = current->signal->rlim + i; | 2293 | rlim = current->signal->rlim + i; |
2338 | initrlim = init_task.signal->rlim + i; | 2294 | initrlim = init_task.signal->rlim + i; |
2339 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2295 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2340 | } | 2296 | } |
2341 | update_rlimit_cpu(current->signal->rlim[RLIMIT_CPU].rlim_cur); | 2297 | task_unlock(current); |
2298 | update_rlimit_cpu(current, rlimit(RLIMIT_CPU)); | ||
2342 | } | 2299 | } |
2343 | } | 2300 | } |
2344 | 2301 | ||
@@ -2559,8 +2516,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2559 | char **name, void **value, | 2516 | char **name, void **value, |
2560 | size_t *len) | 2517 | size_t *len) |
2561 | { | 2518 | { |
2562 | const struct cred *cred = current_cred(); | 2519 | const struct task_security_struct *tsec = current_security(); |
2563 | const struct task_security_struct *tsec = cred->security; | ||
2564 | struct inode_security_struct *dsec; | 2520 | struct inode_security_struct *dsec; |
2565 | struct superblock_security_struct *sbsec; | 2521 | struct superblock_security_struct *sbsec; |
2566 | u32 sid, newsid, clen; | 2522 | u32 sid, newsid, clen; |
@@ -2676,14 +2632,26 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2676 | static int selinux_inode_permission(struct inode *inode, int mask) | 2632 | static int selinux_inode_permission(struct inode *inode, int mask) |
2677 | { | 2633 | { |
2678 | const struct cred *cred = current_cred(); | 2634 | const struct cred *cred = current_cred(); |
2635 | struct common_audit_data ad; | ||
2636 | u32 perms; | ||
2637 | bool from_access; | ||
2679 | 2638 | ||
2680 | if (!mask) { | 2639 | from_access = mask & MAY_ACCESS; |
2681 | /* No permission to check. Existence test. */ | 2640 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
2641 | |||
2642 | /* No permission to check. Existence test. */ | ||
2643 | if (!mask) | ||
2682 | return 0; | 2644 | return 0; |
2683 | } | ||
2684 | 2645 | ||
2685 | return inode_has_perm(cred, inode, | 2646 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2686 | file_mask_to_av(inode->i_mode, mask), NULL); | 2647 | ad.u.fs.inode = inode; |
2648 | |||
2649 | if (from_access) | ||
2650 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | ||
2651 | |||
2652 | perms = file_mask_to_av(inode->i_mode, mask); | ||
2653 | |||
2654 | return inode_has_perm(cred, inode, perms, &ad); | ||
2687 | } | 2655 | } |
2688 | 2656 | ||
2689 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2657 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
@@ -3371,16 +3339,17 @@ static int selinux_task_getioprio(struct task_struct *p) | |||
3371 | return current_has_perm(p, PROCESS__GETSCHED); | 3339 | return current_has_perm(p, PROCESS__GETSCHED); |
3372 | } | 3340 | } |
3373 | 3341 | ||
3374 | static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) | 3342 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, |
3343 | struct rlimit *new_rlim) | ||
3375 | { | 3344 | { |
3376 | struct rlimit *old_rlim = current->signal->rlim + resource; | 3345 | struct rlimit *old_rlim = p->signal->rlim + resource; |
3377 | 3346 | ||
3378 | /* Control the ability to change the hard limit (whether | 3347 | /* Control the ability to change the hard limit (whether |
3379 | lowering or raising it), so that the hard limit can | 3348 | lowering or raising it), so that the hard limit can |
3380 | later be used as a safe reset point for the soft limit | 3349 | later be used as a safe reset point for the soft limit |
3381 | upon context transitions. See selinux_bprm_committing_creds. */ | 3350 | upon context transitions. See selinux_bprm_committing_creds. */ |
3382 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3351 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3383 | return current_has_perm(current, PROCESS__SETRLIMIT); | 3352 | return current_has_perm(p, PROCESS__SETRLIMIT); |
3384 | 3353 | ||
3385 | return 0; | 3354 | return 0; |
3386 | } | 3355 | } |
@@ -3671,71 +3640,54 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
3671 | } | 3640 | } |
3672 | 3641 | ||
3673 | /* socket security operations */ | 3642 | /* socket security operations */ |
3674 | static int socket_has_perm(struct task_struct *task, struct socket *sock, | 3643 | |
3675 | u32 perms) | 3644 | static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) |
3676 | { | 3645 | { |
3677 | struct inode_security_struct *isec; | 3646 | return tsec->sockcreate_sid ? : tsec->sid; |
3678 | struct common_audit_data ad; | 3647 | } |
3679 | u32 sid; | ||
3680 | int err = 0; | ||
3681 | 3648 | ||
3682 | isec = SOCK_INODE(sock)->i_security; | 3649 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
3650 | { | ||
3651 | struct sk_security_struct *sksec = sk->sk_security; | ||
3652 | struct common_audit_data ad; | ||
3653 | u32 tsid = task_sid(task); | ||
3683 | 3654 | ||
3684 | if (isec->sid == SECINITSID_KERNEL) | 3655 | if (sksec->sid == SECINITSID_KERNEL) |
3685 | goto out; | 3656 | return 0; |
3686 | sid = task_sid(task); | ||
3687 | 3657 | ||
3688 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3658 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3689 | ad.u.net.sk = sock->sk; | 3659 | ad.u.net.sk = sk; |
3690 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | ||
3691 | 3660 | ||
3692 | out: | 3661 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); |
3693 | return err; | ||
3694 | } | 3662 | } |
3695 | 3663 | ||
3696 | static int selinux_socket_create(int family, int type, | 3664 | static int selinux_socket_create(int family, int type, |
3697 | int protocol, int kern) | 3665 | int protocol, int kern) |
3698 | { | 3666 | { |
3699 | const struct cred *cred = current_cred(); | 3667 | const struct task_security_struct *tsec = current_security(); |
3700 | const struct task_security_struct *tsec = cred->security; | 3668 | u32 newsid; |
3701 | u32 sid, newsid; | ||
3702 | u16 secclass; | 3669 | u16 secclass; |
3703 | int err = 0; | ||
3704 | 3670 | ||
3705 | if (kern) | 3671 | if (kern) |
3706 | goto out; | 3672 | return 0; |
3707 | |||
3708 | sid = tsec->sid; | ||
3709 | newsid = tsec->sockcreate_sid ?: sid; | ||
3710 | 3673 | ||
3674 | newsid = socket_sockcreate_sid(tsec); | ||
3711 | secclass = socket_type_to_security_class(family, type, protocol); | 3675 | secclass = socket_type_to_security_class(family, type, protocol); |
3712 | err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); | 3676 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
3713 | |||
3714 | out: | ||
3715 | return err; | ||
3716 | } | 3677 | } |
3717 | 3678 | ||
3718 | static int selinux_socket_post_create(struct socket *sock, int family, | 3679 | static int selinux_socket_post_create(struct socket *sock, int family, |
3719 | int type, int protocol, int kern) | 3680 | int type, int protocol, int kern) |
3720 | { | 3681 | { |
3721 | const struct cred *cred = current_cred(); | 3682 | const struct task_security_struct *tsec = current_security(); |
3722 | const struct task_security_struct *tsec = cred->security; | 3683 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
3723 | struct inode_security_struct *isec; | ||
3724 | struct sk_security_struct *sksec; | 3684 | struct sk_security_struct *sksec; |
3725 | u32 sid, newsid; | ||
3726 | int err = 0; | 3685 | int err = 0; |
3727 | 3686 | ||
3728 | sid = tsec->sid; | ||
3729 | newsid = tsec->sockcreate_sid; | ||
3730 | |||
3731 | isec = SOCK_INODE(sock)->i_security; | ||
3732 | |||
3733 | if (kern) | 3687 | if (kern) |
3734 | isec->sid = SECINITSID_KERNEL; | 3688 | isec->sid = SECINITSID_KERNEL; |
3735 | else if (newsid) | ||
3736 | isec->sid = newsid; | ||
3737 | else | 3689 | else |
3738 | isec->sid = sid; | 3690 | isec->sid = socket_sockcreate_sid(tsec); |
3739 | 3691 | ||
3740 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 3692 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
3741 | isec->initialized = 1; | 3693 | isec->initialized = 1; |
@@ -3756,10 +3708,11 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
3756 | 3708 | ||
3757 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3709 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
3758 | { | 3710 | { |
3711 | struct sock *sk = sock->sk; | ||
3759 | u16 family; | 3712 | u16 family; |
3760 | int err; | 3713 | int err; |
3761 | 3714 | ||
3762 | err = socket_has_perm(current, sock, SOCKET__BIND); | 3715 | err = sock_has_perm(current, sk, SOCKET__BIND); |
3763 | if (err) | 3716 | if (err) |
3764 | goto out; | 3717 | goto out; |
3765 | 3718 | ||
@@ -3768,19 +3721,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3768 | * Multiple address binding for SCTP is not supported yet: we just | 3721 | * Multiple address binding for SCTP is not supported yet: we just |
3769 | * check the first address now. | 3722 | * check the first address now. |
3770 | */ | 3723 | */ |
3771 | family = sock->sk->sk_family; | 3724 | family = sk->sk_family; |
3772 | if (family == PF_INET || family == PF_INET6) { | 3725 | if (family == PF_INET || family == PF_INET6) { |
3773 | char *addrp; | 3726 | char *addrp; |
3774 | struct inode_security_struct *isec; | 3727 | struct sk_security_struct *sksec = sk->sk_security; |
3775 | struct common_audit_data ad; | 3728 | struct common_audit_data ad; |
3776 | struct sockaddr_in *addr4 = NULL; | 3729 | struct sockaddr_in *addr4 = NULL; |
3777 | struct sockaddr_in6 *addr6 = NULL; | 3730 | struct sockaddr_in6 *addr6 = NULL; |
3778 | unsigned short snum; | 3731 | unsigned short snum; |
3779 | struct sock *sk = sock->sk; | ||
3780 | u32 sid, node_perm; | 3732 | u32 sid, node_perm; |
3781 | 3733 | ||
3782 | isec = SOCK_INODE(sock)->i_security; | ||
3783 | |||
3784 | if (family == PF_INET) { | 3734 | if (family == PF_INET) { |
3785 | addr4 = (struct sockaddr_in *)address; | 3735 | addr4 = (struct sockaddr_in *)address; |
3786 | snum = ntohs(addr4->sin_port); | 3736 | snum = ntohs(addr4->sin_port); |
@@ -3804,15 +3754,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3804 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3754 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3805 | ad.u.net.sport = htons(snum); | 3755 | ad.u.net.sport = htons(snum); |
3806 | ad.u.net.family = family; | 3756 | ad.u.net.family = family; |
3807 | err = avc_has_perm(isec->sid, sid, | 3757 | err = avc_has_perm(sksec->sid, sid, |
3808 | isec->sclass, | 3758 | sksec->sclass, |
3809 | SOCKET__NAME_BIND, &ad); | 3759 | SOCKET__NAME_BIND, &ad); |
3810 | if (err) | 3760 | if (err) |
3811 | goto out; | 3761 | goto out; |
3812 | } | 3762 | } |
3813 | } | 3763 | } |
3814 | 3764 | ||
3815 | switch (isec->sclass) { | 3765 | switch (sksec->sclass) { |
3816 | case SECCLASS_TCP_SOCKET: | 3766 | case SECCLASS_TCP_SOCKET: |
3817 | node_perm = TCP_SOCKET__NODE_BIND; | 3767 | node_perm = TCP_SOCKET__NODE_BIND; |
3818 | break; | 3768 | break; |
@@ -3843,8 +3793,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3843 | else | 3793 | else |
3844 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); | 3794 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); |
3845 | 3795 | ||
3846 | err = avc_has_perm(isec->sid, sid, | 3796 | err = avc_has_perm(sksec->sid, sid, |
3847 | isec->sclass, node_perm, &ad); | 3797 | sksec->sclass, node_perm, &ad); |
3848 | if (err) | 3798 | if (err) |
3849 | goto out; | 3799 | goto out; |
3850 | } | 3800 | } |
@@ -3855,19 +3805,18 @@ out: | |||
3855 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3805 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
3856 | { | 3806 | { |
3857 | struct sock *sk = sock->sk; | 3807 | struct sock *sk = sock->sk; |
3858 | struct inode_security_struct *isec; | 3808 | struct sk_security_struct *sksec = sk->sk_security; |
3859 | int err; | 3809 | int err; |
3860 | 3810 | ||
3861 | err = socket_has_perm(current, sock, SOCKET__CONNECT); | 3811 | err = sock_has_perm(current, sk, SOCKET__CONNECT); |
3862 | if (err) | 3812 | if (err) |
3863 | return err; | 3813 | return err; |
3864 | 3814 | ||
3865 | /* | 3815 | /* |
3866 | * If a TCP or DCCP socket, check name_connect permission for the port. | 3816 | * If a TCP or DCCP socket, check name_connect permission for the port. |
3867 | */ | 3817 | */ |
3868 | isec = SOCK_INODE(sock)->i_security; | 3818 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
3869 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3819 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
3870 | isec->sclass == SECCLASS_DCCP_SOCKET) { | ||
3871 | struct common_audit_data ad; | 3820 | struct common_audit_data ad; |
3872 | struct sockaddr_in *addr4 = NULL; | 3821 | struct sockaddr_in *addr4 = NULL; |
3873 | struct sockaddr_in6 *addr6 = NULL; | 3822 | struct sockaddr_in6 *addr6 = NULL; |
@@ -3890,13 +3839,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3890 | if (err) | 3839 | if (err) |
3891 | goto out; | 3840 | goto out; |
3892 | 3841 | ||
3893 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3842 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
3894 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3843 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3895 | 3844 | ||
3896 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3845 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3897 | ad.u.net.dport = htons(snum); | 3846 | ad.u.net.dport = htons(snum); |
3898 | ad.u.net.family = sk->sk_family; | 3847 | ad.u.net.family = sk->sk_family; |
3899 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3848 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); |
3900 | if (err) | 3849 | if (err) |
3901 | goto out; | 3850 | goto out; |
3902 | } | 3851 | } |
@@ -3909,7 +3858,7 @@ out: | |||
3909 | 3858 | ||
3910 | static int selinux_socket_listen(struct socket *sock, int backlog) | 3859 | static int selinux_socket_listen(struct socket *sock, int backlog) |
3911 | { | 3860 | { |
3912 | return socket_has_perm(current, sock, SOCKET__LISTEN); | 3861 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); |
3913 | } | 3862 | } |
3914 | 3863 | ||
3915 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 3864 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
@@ -3918,7 +3867,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3918 | struct inode_security_struct *isec; | 3867 | struct inode_security_struct *isec; |
3919 | struct inode_security_struct *newisec; | 3868 | struct inode_security_struct *newisec; |
3920 | 3869 | ||
3921 | err = socket_has_perm(current, sock, SOCKET__ACCEPT); | 3870 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
3922 | if (err) | 3871 | if (err) |
3923 | return err; | 3872 | return err; |
3924 | 3873 | ||
@@ -3935,30 +3884,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3935 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3884 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
3936 | int size) | 3885 | int size) |
3937 | { | 3886 | { |
3938 | return socket_has_perm(current, sock, SOCKET__WRITE); | 3887 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); |
3939 | } | 3888 | } |
3940 | 3889 | ||
3941 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3890 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
3942 | int size, int flags) | 3891 | int size, int flags) |
3943 | { | 3892 | { |
3944 | return socket_has_perm(current, sock, SOCKET__READ); | 3893 | return sock_has_perm(current, sock->sk, SOCKET__READ); |
3945 | } | 3894 | } |
3946 | 3895 | ||
3947 | static int selinux_socket_getsockname(struct socket *sock) | 3896 | static int selinux_socket_getsockname(struct socket *sock) |
3948 | { | 3897 | { |
3949 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3898 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3950 | } | 3899 | } |
3951 | 3900 | ||
3952 | static int selinux_socket_getpeername(struct socket *sock) | 3901 | static int selinux_socket_getpeername(struct socket *sock) |
3953 | { | 3902 | { |
3954 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3903 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3955 | } | 3904 | } |
3956 | 3905 | ||
3957 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 3906 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
3958 | { | 3907 | { |
3959 | int err; | 3908 | int err; |
3960 | 3909 | ||
3961 | err = socket_has_perm(current, sock, SOCKET__SETOPT); | 3910 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); |
3962 | if (err) | 3911 | if (err) |
3963 | return err; | 3912 | return err; |
3964 | 3913 | ||
@@ -3968,68 +3917,58 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
3968 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3917 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
3969 | int optname) | 3918 | int optname) |
3970 | { | 3919 | { |
3971 | return socket_has_perm(current, sock, SOCKET__GETOPT); | 3920 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); |
3972 | } | 3921 | } |
3973 | 3922 | ||
3974 | static int selinux_socket_shutdown(struct socket *sock, int how) | 3923 | static int selinux_socket_shutdown(struct socket *sock, int how) |
3975 | { | 3924 | { |
3976 | return socket_has_perm(current, sock, SOCKET__SHUTDOWN); | 3925 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
3977 | } | 3926 | } |
3978 | 3927 | ||
3979 | static int selinux_socket_unix_stream_connect(struct socket *sock, | 3928 | static int selinux_socket_unix_stream_connect(struct socket *sock, |
3980 | struct socket *other, | 3929 | struct socket *other, |
3981 | struct sock *newsk) | 3930 | struct sock *newsk) |
3982 | { | 3931 | { |
3983 | struct sk_security_struct *sksec; | 3932 | struct sk_security_struct *sksec_sock = sock->sk->sk_security; |
3984 | struct inode_security_struct *isec; | 3933 | struct sk_security_struct *sksec_other = other->sk->sk_security; |
3985 | struct inode_security_struct *other_isec; | 3934 | struct sk_security_struct *sksec_new = newsk->sk_security; |
3986 | struct common_audit_data ad; | 3935 | struct common_audit_data ad; |
3987 | int err; | 3936 | int err; |
3988 | 3937 | ||
3989 | isec = SOCK_INODE(sock)->i_security; | ||
3990 | other_isec = SOCK_INODE(other)->i_security; | ||
3991 | |||
3992 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3938 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3993 | ad.u.net.sk = other->sk; | 3939 | ad.u.net.sk = other->sk; |
3994 | 3940 | ||
3995 | err = avc_has_perm(isec->sid, other_isec->sid, | 3941 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
3996 | isec->sclass, | 3942 | sksec_other->sclass, |
3997 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 3943 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
3998 | if (err) | 3944 | if (err) |
3999 | return err; | 3945 | return err; |
4000 | 3946 | ||
4001 | /* connecting socket */ | ||
4002 | sksec = sock->sk->sk_security; | ||
4003 | sksec->peer_sid = other_isec->sid; | ||
4004 | |||
4005 | /* server child socket */ | 3947 | /* server child socket */ |
4006 | sksec = newsk->sk_security; | 3948 | sksec_new->peer_sid = sksec_sock->sid; |
4007 | sksec->peer_sid = isec->sid; | 3949 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, |
4008 | err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); | 3950 | &sksec_new->sid); |
3951 | if (err) | ||
3952 | return err; | ||
4009 | 3953 | ||
4010 | return err; | 3954 | /* connecting socket */ |
3955 | sksec_sock->peer_sid = sksec_new->sid; | ||
3956 | |||
3957 | return 0; | ||
4011 | } | 3958 | } |
4012 | 3959 | ||
4013 | static int selinux_socket_unix_may_send(struct socket *sock, | 3960 | static int selinux_socket_unix_may_send(struct socket *sock, |
4014 | struct socket *other) | 3961 | struct socket *other) |
4015 | { | 3962 | { |
4016 | struct inode_security_struct *isec; | 3963 | struct sk_security_struct *ssec = sock->sk->sk_security; |
4017 | struct inode_security_struct *other_isec; | 3964 | struct sk_security_struct *osec = other->sk->sk_security; |
4018 | struct common_audit_data ad; | 3965 | struct common_audit_data ad; |
4019 | int err; | ||
4020 | |||
4021 | isec = SOCK_INODE(sock)->i_security; | ||
4022 | other_isec = SOCK_INODE(other)->i_security; | ||
4023 | 3966 | ||
4024 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3967 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4025 | ad.u.net.sk = other->sk; | 3968 | ad.u.net.sk = other->sk; |
4026 | 3969 | ||
4027 | err = avc_has_perm(isec->sid, other_isec->sid, | 3970 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, |
4028 | isec->sclass, SOCKET__SENDTO, &ad); | 3971 | &ad); |
4029 | if (err) | ||
4030 | return err; | ||
4031 | |||
4032 | return 0; | ||
4033 | } | 3972 | } |
4034 | 3973 | ||
4035 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 3974 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
@@ -4168,26 +4107,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4168 | int err = 0; | 4107 | int err = 0; |
4169 | char *scontext; | 4108 | char *scontext; |
4170 | u32 scontext_len; | 4109 | u32 scontext_len; |
4171 | struct sk_security_struct *sksec; | 4110 | struct sk_security_struct *sksec = sock->sk->sk_security; |
4172 | struct inode_security_struct *isec; | ||
4173 | u32 peer_sid = SECSID_NULL; | 4111 | u32 peer_sid = SECSID_NULL; |
4174 | 4112 | ||
4175 | isec = SOCK_INODE(sock)->i_security; | 4113 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
4176 | 4114 | sksec->sclass == SECCLASS_TCP_SOCKET) | |
4177 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | ||
4178 | isec->sclass == SECCLASS_TCP_SOCKET) { | ||
4179 | sksec = sock->sk->sk_security; | ||
4180 | peer_sid = sksec->peer_sid; | 4115 | peer_sid = sksec->peer_sid; |
4181 | } | 4116 | if (peer_sid == SECSID_NULL) |
4182 | if (peer_sid == SECSID_NULL) { | 4117 | return -ENOPROTOOPT; |
4183 | err = -ENOPROTOOPT; | ||
4184 | goto out; | ||
4185 | } | ||
4186 | 4118 | ||
4187 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 4119 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
4188 | |||
4189 | if (err) | 4120 | if (err) |
4190 | goto out; | 4121 | return err; |
4191 | 4122 | ||
4192 | if (scontext_len > len) { | 4123 | if (scontext_len > len) { |
4193 | err = -ERANGE; | 4124 | err = -ERANGE; |
@@ -4200,9 +4131,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4200 | out_len: | 4131 | out_len: |
4201 | if (put_user(scontext_len, optlen)) | 4132 | if (put_user(scontext_len, optlen)) |
4202 | err = -EFAULT; | 4133 | err = -EFAULT; |
4203 | |||
4204 | kfree(scontext); | 4134 | kfree(scontext); |
4205 | out: | ||
4206 | return err; | 4135 | return err; |
4207 | } | 4136 | } |
4208 | 4137 | ||
@@ -4234,12 +4163,27 @@ out: | |||
4234 | 4163 | ||
4235 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 4164 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
4236 | { | 4165 | { |
4237 | return sk_alloc_security(sk, family, priority); | 4166 | struct sk_security_struct *sksec; |
4167 | |||
4168 | sksec = kzalloc(sizeof(*sksec), priority); | ||
4169 | if (!sksec) | ||
4170 | return -ENOMEM; | ||
4171 | |||
4172 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
4173 | sksec->sid = SECINITSID_UNLABELED; | ||
4174 | selinux_netlbl_sk_security_reset(sksec); | ||
4175 | sk->sk_security = sksec; | ||
4176 | |||
4177 | return 0; | ||
4238 | } | 4178 | } |
4239 | 4179 | ||
4240 | static void selinux_sk_free_security(struct sock *sk) | 4180 | static void selinux_sk_free_security(struct sock *sk) |
4241 | { | 4181 | { |
4242 | sk_free_security(sk); | 4182 | struct sk_security_struct *sksec = sk->sk_security; |
4183 | |||
4184 | sk->sk_security = NULL; | ||
4185 | selinux_netlbl_sk_security_free(sksec); | ||
4186 | kfree(sksec); | ||
4243 | } | 4187 | } |
4244 | 4188 | ||
4245 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4189 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
@@ -4399,8 +4343,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4399 | int err = 0; | 4343 | int err = 0; |
4400 | u32 perm; | 4344 | u32 perm; |
4401 | struct nlmsghdr *nlh; | 4345 | struct nlmsghdr *nlh; |
4402 | struct socket *sock = sk->sk_socket; | 4346 | struct sk_security_struct *sksec = sk->sk_security; |
4403 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
4404 | 4347 | ||
4405 | if (skb->len < NLMSG_SPACE(0)) { | 4348 | if (skb->len < NLMSG_SPACE(0)) { |
4406 | err = -EINVAL; | 4349 | err = -EINVAL; |
@@ -4408,13 +4351,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4408 | } | 4351 | } |
4409 | nlh = nlmsg_hdr(skb); | 4352 | nlh = nlmsg_hdr(skb); |
4410 | 4353 | ||
4411 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); | 4354 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
4412 | if (err) { | 4355 | if (err) { |
4413 | if (err == -EINVAL) { | 4356 | if (err == -EINVAL) { |
4414 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4357 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
4415 | "SELinux: unrecognized netlink message" | 4358 | "SELinux: unrecognized netlink message" |
4416 | " type=%hu for sclass=%hu\n", | 4359 | " type=%hu for sclass=%hu\n", |
4417 | nlh->nlmsg_type, isec->sclass); | 4360 | nlh->nlmsg_type, sksec->sclass); |
4418 | if (!selinux_enforcing || security_get_allow_unknown()) | 4361 | if (!selinux_enforcing || security_get_allow_unknown()) |
4419 | err = 0; | 4362 | err = 0; |
4420 | } | 4363 | } |
@@ -4425,7 +4368,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4425 | goto out; | 4368 | goto out; |
4426 | } | 4369 | } |
4427 | 4370 | ||
4428 | err = socket_has_perm(current, sock, perm); | 4371 | err = sock_has_perm(current, sk, perm); |
4429 | out: | 4372 | out: |
4430 | return err; | 4373 | return err; |
4431 | } | 4374 | } |