diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 19de675d4504..81fb4c1631e9 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -28,6 +28,7 @@ #include <linux/tcp.h> #include <linux/udp.h> #include <linux/dccp.h> +#include <linux/icmpv6.h> #include <linux/slab.h> #include <linux/mutex.h> #include <linux/pipe_fs_i.h> @@ -420,6 +421,7 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, struct smk_audit_info ad, *saip = NULL; struct task_smack *tsp; struct smack_known *tracer_known; + const struct cred *tracercred; if ((mode & PTRACE_MODE_NOAUDIT) == 0) { smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); @@ -428,7 +430,8 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, } rcu_read_lock(); - tsp = __task_cred(tracer)->security; + tracercred = __task_cred(tracer); + tsp = tracercred->security; tracer_known = smk_of_task(tsp); if ((mode & PTRACE_MODE_ATTACH) && @@ -438,7 +441,7 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, rc = 0; else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) rc = -EACCES; - else if (capable(CAP_SYS_PTRACE)) + else if (smack_privileged_cred(CAP_SYS_PTRACE, tracercred)) rc = 0; else rc = -EACCES; @@ -1840,6 +1843,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, { struct smack_known *skp; struct smack_known *tkp = smk_of_task(tsk->cred->security); + const struct cred *tcred; struct file *file; int rc; struct smk_audit_info ad; @@ -1853,8 +1857,12 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, skp = file->f_security; rc = smk_access(skp, tkp, MAY_DELIVER, NULL); rc = smk_bu_note("sigiotask", skp, tkp, MAY_DELIVER, rc); - if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) + + rcu_read_lock(); + tcred = __task_cred(tsk); + if (rc != 0 && smack_privileged_cred(CAP_MAC_OVERRIDE, tcred)) rc = 0; + rcu_read_unlock(); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, tsk); @@ -1927,9 +1935,9 @@ static int smack_file_receive(struct file *file) * * Returns 0 */ -static int smack_file_open(struct file *file, const struct cred *cred) +static int smack_file_open(struct file *file) { - struct task_smack *tsp = cred->security; + struct task_smack *tsp = file->f_cred->security; struct inode *inode = file_inode(file); struct smk_audit_info ad; int rc; @@ -1937,7 +1945,7 @@ static int smack_file_open(struct file *file, const struct cred *cred) smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); smk_ad_setfield_u_fs_path(&ad, file->f_path); rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad); - rc = smk_bu_credfile(cred, file, MAY_READ, rc); + rc = smk_bu_credfile(file->f_cred, file, MAY_READ, rc); return rc; } @@ -2250,7 +2258,7 @@ static int smack_task_movememory(struct task_struct *p) * Return 0 if write access is permitted * */ -static int smack_task_kill(struct task_struct *p, struct siginfo *info, +static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { struct smk_audit_info ad; @@ -3466,7 +3474,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) */ final = &smack_known_star; /* - * No break. + * Fall through. * * If a smack value has been set we want to use it, * but since tmpfs isn't giving us the opportunity @@ -3896,6 +3904,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) sip->sin6_port = th->source; break; case IPPROTO_UDP: + case IPPROTO_UDPLITE: uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); if (uh != NULL) sip->sin6_port = uh->source; @@ -3924,15 +3933,19 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) struct smack_known *skp = NULL; int rc = 0; struct smk_audit_info ad; + u16 family = sk->sk_family; #ifdef CONFIG_AUDIT struct lsm_network_audit net; #endif #if IS_ENABLED(CONFIG_IPV6) struct sockaddr_in6 sadd; int proto; + + if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) + family = PF_INET; #endif /* CONFIG_IPV6 */ - switch (sk->sk_family) { + switch (family) { case PF_INET: #ifdef CONFIG_SECURITY_SMACK_NETFILTER /* @@ -3950,7 +3963,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) */ netlbl_secattr_init(&secattr); - rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); + rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0) skp = smack_from_secattr(&secattr, ssp); else @@ -3963,7 +3976,7 @@ access_check: #endif #ifdef CONFIG_AUDIT smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); - ad.a.u.net->family = sk->sk_family; + ad.a.u.net->family = family; ad.a.u.net->netif = skb->skb_iif; ipv4_skb_to_auditdata(skb, &ad.a, NULL); #endif @@ -3977,12 +3990,13 @@ access_check: rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in, MAY_WRITE, rc); if (rc != 0) - netlbl_skbuff_err(skb, sk->sk_family, rc, 0); + netlbl_skbuff_err(skb, family, rc, 0); break; #if IS_ENABLED(CONFIG_IPV6) case PF_INET6: proto = smk_skb_to_addr_ipv6(skb, &sadd); - if (proto != IPPROTO_UDP && proto != IPPROTO_TCP) + if (proto != IPPROTO_UDP && proto != IPPROTO_UDPLITE && + proto != IPPROTO_TCP && proto != IPPROTO_DCCP) break; #ifdef SMACK_IPV6_SECMARK_LABELING if (skb && skb->secmark != 0) @@ -3993,7 +4007,7 @@ access_check: skp = smack_net_ambient; #ifdef CONFIG_AUDIT smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); - ad.a.u.net->family = sk->sk_family; + ad.a.u.net->family = family; ad.a.u.net->netif = skb->skb_iif; ipv6_skb_to_auditdata(skb, &ad.a, NULL); #endif /* CONFIG_AUDIT */ @@ -4004,6 +4018,9 @@ access_check: #ifdef SMACK_IPV6_PORT_LABELING rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); #endif /* SMACK_IPV6_PORT_LABELING */ + if (rc != 0) + icmpv6_send(skb, ICMPV6_DEST_UNREACH, + ICMPV6_ADM_PROHIBITED, 0); break; #endif /* CONFIG_IPV6 */ } @@ -4872,4 +4889,7 @@ static __init int smack_init(void) * Smack requires early initialization in order to label * all processes and objects when they are created. */ -security_initcall(smack_init); +DEFINE_LSM(smack) = { + .name = "smack", + .init = smack_init, +}; |