Commit 39e16d93 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SELinux fixes from Paul Moore:
 "Two more SELinux patches to fix problems in the v5.7-rcX releases.

  Wei Yongjun's patch fixes a return code in an error path, and my patch
  fixes a problem where we were not correctly applying access controls
  to all of the netlink messages in the netlink_send LSM hook"

* tag 'selinux-pr-20200430' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinux: properly handle multiple messages in selinux_netlink_send()
  selinux: fix error return code in cond_read_list()
parents 0468915b fb739741
Loading
Loading
Loading
Loading
+45 −25
Original line number Diff line number Diff line
@@ -5842,40 +5842,60 @@ static unsigned int selinux_ipv6_postroute(void *priv,

static int selinux_netlink_send(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"
				" 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;
}

static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass)
+1 −1
Original line number Diff line number Diff line
@@ -429,7 +429,7 @@ int cond_read_list(struct policydb *p, void *fp)

	p->cond_list = kcalloc(len, sizeof(*p->cond_list), GFP_KERNEL);
	if (!p->cond_list)
		return rc;
		return -ENOMEM;

	rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
	if (rc)