Loading security/selinux/hooks.c +45 −25 Original line number Diff line number Diff line Loading @@ -5592,40 +5592,60 @@ static int selinux_tun_dev_open(void *security) static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) { int err = 0; u32 perm; int rc = 0; unsigned int msg_len; unsigned int data_len = skb->len; unsigned char *data = skb->data; struct nlmsghdr *nlh; struct sk_security_struct *sksec = sk->sk_security; u16 sclass = sksec->sclass; u32 perm; if (skb->len < NLMSG_HDRLEN) { err = -EINVAL; goto out; } nlh = nlmsg_hdr(skb); while (data_len >= nlmsg_total_size(0)) { nlh = (struct nlmsghdr *)data; err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); if (err) { if (err == -EINVAL) { /* NOTE: the nlmsg_len field isn't reliably set by some netlink * users which means we can't reject skb's with bogus * length fields; our solution is to follow what * netlink_rcv_skb() does and simply skip processing at * messages with length fields that are clearly junk */ if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len) return 0; rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm); if (rc == 0) { rc = sock_has_perm(sk, perm); if (rc) return rc; } else if (rc == -EINVAL) { /* -EINVAL is a missing msg/perm mapping */ pr_warn_ratelimited("SELinux: unrecognized netlink" " message: protocol=%hu nlmsg_type=%hu sclass=%s" " pig=%d comm=%s\n", " pid=%d comm=%s\n", sk->sk_protocol, nlh->nlmsg_type, secclass_map[sksec->sclass - 1].name, secclass_map[sclass - 1].name, task_pid_nr(current), current->comm); if (!enforcing_enabled(&selinux_state) || security_get_allow_unknown(&selinux_state)) err = 0; if (enforcing_enabled(&selinux_state) && !security_get_allow_unknown(&selinux_state)) return rc; rc = 0; } else if (rc == -ENOENT) { /* -ENOENT is a missing socket/class mapping, ignore */ rc = 0; } else { return rc; } /* Ignore */ if (err == -ENOENT) err = 0; goto out; /* move to the next message after applying netlink padding */ msg_len = NLMSG_ALIGN(nlh->nlmsg_len); if (msg_len >= data_len) return 0; data_len -= msg_len; data += msg_len; } err = sock_has_perm(sk, perm); out: return err; return rc; } #ifdef CONFIG_NETFILTER Loading Loading
security/selinux/hooks.c +45 −25 Original line number Diff line number Diff line Loading @@ -5592,40 +5592,60 @@ static int selinux_tun_dev_open(void *security) static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) { int err = 0; u32 perm; int rc = 0; unsigned int msg_len; unsigned int data_len = skb->len; unsigned char *data = skb->data; struct nlmsghdr *nlh; struct sk_security_struct *sksec = sk->sk_security; u16 sclass = sksec->sclass; u32 perm; if (skb->len < NLMSG_HDRLEN) { err = -EINVAL; goto out; } nlh = nlmsg_hdr(skb); while (data_len >= nlmsg_total_size(0)) { nlh = (struct nlmsghdr *)data; err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); if (err) { if (err == -EINVAL) { /* NOTE: the nlmsg_len field isn't reliably set by some netlink * users which means we can't reject skb's with bogus * length fields; our solution is to follow what * netlink_rcv_skb() does and simply skip processing at * messages with length fields that are clearly junk */ if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len) return 0; rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm); if (rc == 0) { rc = sock_has_perm(sk, perm); if (rc) return rc; } else if (rc == -EINVAL) { /* -EINVAL is a missing msg/perm mapping */ pr_warn_ratelimited("SELinux: unrecognized netlink" " message: protocol=%hu nlmsg_type=%hu sclass=%s" " pig=%d comm=%s\n", " pid=%d comm=%s\n", sk->sk_protocol, nlh->nlmsg_type, secclass_map[sksec->sclass - 1].name, secclass_map[sclass - 1].name, task_pid_nr(current), current->comm); if (!enforcing_enabled(&selinux_state) || security_get_allow_unknown(&selinux_state)) err = 0; if (enforcing_enabled(&selinux_state) && !security_get_allow_unknown(&selinux_state)) return rc; rc = 0; } else if (rc == -ENOENT) { /* -ENOENT is a missing socket/class mapping, ignore */ rc = 0; } else { return rc; } /* Ignore */ if (err == -ENOENT) err = 0; goto out; /* move to the next message after applying netlink padding */ msg_len = NLMSG_ALIGN(nlh->nlmsg_len); if (msg_len >= data_len) return 0; data_len -= msg_len; data += msg_len; } err = sock_has_perm(sk, perm); out: return err; return rc; } #ifdef CONFIG_NETFILTER Loading