FAILED: patch "[PATCH] selinux: properly handle multiple messages in" failed to apply to 4.19-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From fb73974172ffaaf57a7c42f35424d9aece1a5af6 Mon Sep 17 00:00:00 2001
From: Paul Moore <[email protected]>
Date: Tue, 28 Apr 2020 09:59:02 -0400
Subject: [PATCH] selinux: properly handle multiple messages in
selinux_netlink_send()
Fix the SELinux netlink_send hook to properly handle multiple netlink messages in a single sk_buff; each message is parsed and subject to SELinux access control. Prior to this patch, SELinux only inspected the first message in the sk_buff.
security/selinux/hooks.c +45 -25
@@ -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; + +/* 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 ; - err =selinux_nlmsg_lookup (sksec->sclass, nlh->nlmsg_type, &perm); -if (err) { -if (err == -EINVAL ) { + 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, -task_pid_nr (current), current->comm); -if (!enforcing_enabled (&selinux_state) || -security_get_allow_unknown (&selinux_state)) - err =0 ; +" message: protocol=%hu nlmsg_type=%hu sclass=%s" +" pid=%d comm=%s\n" , + sk->sk_protocol, nlh->nlmsg_type, + secclass_map[sclass -1 ].name, +task_pid_nr (current), current->comm); +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)