diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4796ddd4e72..c8d69927068 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1973,14 +1973,10 @@ static int selinux_quota_on(struct dentry *dentry) | |||
1973 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); | 1973 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); |
1974 | } | 1974 | } |
1975 | 1975 | ||
1976 | static int selinux_syslog(int type, bool from_file) | 1976 | static int selinux_syslog(int type) |
1977 | { | 1977 | { |
1978 | int rc; | 1978 | int rc; |
1979 | 1979 | ||
1980 | rc = cap_syslog(type, from_file); | ||
1981 | if (rc) | ||
1982 | return rc; | ||
1983 | |||
1984 | switch (type) { | 1980 | switch (type) { |
1985 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ | 1981 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
1986 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ | 1982 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
@@ -2529,7 +2525,10 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2529 | sid = tsec->sid; | 2525 | sid = tsec->sid; |
2530 | newsid = tsec->create_sid; | 2526 | newsid = tsec->create_sid; |
2531 | 2527 | ||
2532 | if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | 2528 | if ((sbsec->flags & SE_SBINITIALIZED) && |
2529 | (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) | ||
2530 | newsid = sbsec->mntpoint_sid; | ||
2531 | else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | ||
2533 | rc = security_transition_sid(sid, dsec->sid, | 2532 | rc = security_transition_sid(sid, dsec->sid, |
2534 | inode_mode_to_security_class(inode->i_mode), | 2533 | inode_mode_to_security_class(inode->i_mode), |
2535 | &newsid); | 2534 | &newsid); |
@@ -3199,7 +3198,11 @@ static void selinux_cred_free(struct cred *cred) | |||
3199 | { | 3198 | { |
3200 | struct task_security_struct *tsec = cred->security; | 3199 | struct task_security_struct *tsec = cred->security; |
3201 | 3200 | ||
3202 | BUG_ON((unsigned long) cred->security < PAGE_SIZE); | 3201 | /* |
3202 | * cred->security == NULL if security_cred_alloc_blank() or | ||
3203 | * security_prepare_creds() returned an error. | ||
3204 | */ | ||
3205 | BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE); | ||
3203 | cred->security = (void *) 0x7UL; | 3206 | cred->security = (void *) 0x7UL; |
3204 | kfree(tsec); | 3207 | kfree(tsec); |
3205 | } | 3208 | } |
@@ -3354,11 +3357,11 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, | |||
3354 | return 0; | 3357 | return 0; |
3355 | } | 3358 | } |
3356 | 3359 | ||
3357 | static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp) | 3360 | static int selinux_task_setscheduler(struct task_struct *p) |
3358 | { | 3361 | { |
3359 | int rc; | 3362 | int rc; |
3360 | 3363 | ||
3361 | rc = cap_task_setscheduler(p, policy, lp); | 3364 | rc = cap_task_setscheduler(p); |
3362 | if (rc) | 3365 | if (rc) |
3363 | return rc; | 3366 | return rc; |
3364 | 3367 | ||
@@ -3925,18 +3928,18 @@ static int selinux_socket_shutdown(struct socket *sock, int how) | |||
3925 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); | 3928 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
3926 | } | 3929 | } |
3927 | 3930 | ||
3928 | static int selinux_socket_unix_stream_connect(struct socket *sock, | 3931 | static int selinux_socket_unix_stream_connect(struct sock *sock, |
3929 | struct socket *other, | 3932 | struct sock *other, |
3930 | struct sock *newsk) | 3933 | struct sock *newsk) |
3931 | { | 3934 | { |
3932 | struct sk_security_struct *sksec_sock = sock->sk->sk_security; | 3935 | struct sk_security_struct *sksec_sock = sock->sk_security; |
3933 | struct sk_security_struct *sksec_other = other->sk->sk_security; | 3936 | struct sk_security_struct *sksec_other = other->sk_security; |
3934 | struct sk_security_struct *sksec_new = newsk->sk_security; | 3937 | struct sk_security_struct *sksec_new = newsk->sk_security; |
3935 | struct common_audit_data ad; | 3938 | struct common_audit_data ad; |
3936 | int err; | 3939 | int err; |
3937 | 3940 | ||
3938 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3941 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3939 | ad.u.net.sk = other->sk; | 3942 | ad.u.net.sk = other; |
3940 | 3943 | ||
3941 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, | 3944 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
3942 | sksec_other->sclass, | 3945 | sksec_other->sclass, |
@@ -4279,6 +4282,27 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) | |||
4279 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); | 4282 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); |
4280 | } | 4283 | } |
4281 | 4284 | ||
4285 | static int selinux_secmark_relabel_packet(u32 sid) | ||
4286 | { | ||
4287 | const struct task_security_struct *__tsec; | ||
4288 | u32 tsid; | ||
4289 | |||
4290 | __tsec = current_security(); | ||
4291 | tsid = __tsec->sid; | ||
4292 | |||
4293 | return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); | ||
4294 | } | ||
4295 | |||
4296 | static void selinux_secmark_refcount_inc(void) | ||
4297 | { | ||
4298 | atomic_inc(&selinux_secmark_refcount); | ||
4299 | } | ||
4300 | |||
4301 | static void selinux_secmark_refcount_dec(void) | ||
4302 | { | ||
4303 | atomic_dec(&selinux_secmark_refcount); | ||
4304 | } | ||
4305 | |||
4282 | static void selinux_req_classify_flow(const struct request_sock *req, | 4306 | static void selinux_req_classify_flow(const struct request_sock *req, |
4283 | struct flowi *fl) | 4307 | struct flowi *fl) |
4284 | { | 4308 | { |
@@ -4503,11 +4527,11 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4503 | if (selinux_secmark_enabled()) | 4527 | if (selinux_secmark_enabled()) |
4504 | if (avc_has_perm(sksec->sid, skb->secmark, | 4528 | if (avc_has_perm(sksec->sid, skb->secmark, |
4505 | SECCLASS_PACKET, PACKET__SEND, &ad)) | 4529 | SECCLASS_PACKET, PACKET__SEND, &ad)) |
4506 | return NF_DROP; | 4530 | return NF_DROP_ERR(-ECONNREFUSED); |
4507 | 4531 | ||
4508 | if (selinux_policycap_netpeer) | 4532 | if (selinux_policycap_netpeer) |
4509 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) | 4533 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) |
4510 | return NF_DROP; | 4534 | return NF_DROP_ERR(-ECONNREFUSED); |
4511 | 4535 | ||
4512 | return NF_ACCEPT; | 4536 | return NF_ACCEPT; |
4513 | } | 4537 | } |
@@ -4564,7 +4588,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4564 | secmark_perm = PACKET__SEND; | 4588 | secmark_perm = PACKET__SEND; |
4565 | break; | 4589 | break; |
4566 | default: | 4590 | default: |
4567 | return NF_DROP; | 4591 | return NF_DROP_ERR(-ECONNREFUSED); |
4568 | } | 4592 | } |
4569 | if (secmark_perm == PACKET__FORWARD_OUT) { | 4593 | if (secmark_perm == PACKET__FORWARD_OUT) { |
4570 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | 4594 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) |
@@ -4586,7 +4610,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4586 | if (secmark_active) | 4610 | if (secmark_active) |
4587 | if (avc_has_perm(peer_sid, skb->secmark, | 4611 | if (avc_has_perm(peer_sid, skb->secmark, |
4588 | SECCLASS_PACKET, secmark_perm, &ad)) | 4612 | SECCLASS_PACKET, secmark_perm, &ad)) |
4589 | return NF_DROP; | 4613 | return NF_DROP_ERR(-ECONNREFUSED); |
4590 | 4614 | ||
4591 | if (peerlbl_active) { | 4615 | if (peerlbl_active) { |
4592 | u32 if_sid; | 4616 | u32 if_sid; |
@@ -4596,13 +4620,13 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4596 | return NF_DROP; | 4620 | return NF_DROP; |
4597 | if (avc_has_perm(peer_sid, if_sid, | 4621 | if (avc_has_perm(peer_sid, if_sid, |
4598 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) | 4622 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) |
4599 | return NF_DROP; | 4623 | return NF_DROP_ERR(-ECONNREFUSED); |
4600 | 4624 | ||
4601 | if (sel_netnode_sid(addrp, family, &node_sid)) | 4625 | if (sel_netnode_sid(addrp, family, &node_sid)) |
4602 | return NF_DROP; | 4626 | return NF_DROP; |
4603 | if (avc_has_perm(peer_sid, node_sid, | 4627 | if (avc_has_perm(peer_sid, node_sid, |
4604 | SECCLASS_NODE, NODE__SENDTO, &ad)) | 4628 | SECCLASS_NODE, NODE__SENDTO, &ad)) |
4605 | return NF_DROP; | 4629 | return NF_DROP_ERR(-ECONNREFUSED); |
4606 | } | 4630 | } |
4607 | 4631 | ||
4608 | return NF_ACCEPT; | 4632 | return NF_ACCEPT; |
@@ -5533,6 +5557,9 @@ static struct security_operations selinux_ops = { | |||
5533 | .inet_conn_request = selinux_inet_conn_request, | 5557 | .inet_conn_request = selinux_inet_conn_request, |
5534 | .inet_csk_clone = selinux_inet_csk_clone, | 5558 | .inet_csk_clone = selinux_inet_csk_clone, |
5535 | .inet_conn_established = selinux_inet_conn_established, | 5559 | .inet_conn_established = selinux_inet_conn_established, |
5560 | .secmark_relabel_packet = selinux_secmark_relabel_packet, | ||
5561 | .secmark_refcount_inc = selinux_secmark_refcount_inc, | ||
5562 | .secmark_refcount_dec = selinux_secmark_refcount_dec, | ||
5536 | .req_classify_flow = selinux_req_classify_flow, | 5563 | .req_classify_flow = selinux_req_classify_flow, |
5537 | .tun_dev_create = selinux_tun_dev_create, | 5564 | .tun_dev_create = selinux_tun_dev_create, |
5538 | .tun_dev_post_create = selinux_tun_dev_post_create, | 5565 | .tun_dev_post_create = selinux_tun_dev_post_create, |