diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 9b06c380866b53bcb395bf255587279db025d11d..53b35002e0e9850bac27baac8a643923b1d34d70 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -935,6 +935,7 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) int noblock = flags & MSG_DONTWAIT; struct sk_buff *skb = NULL; size_t size = 0; + struct net_device *dev; int rc = -EINVAL, copied = 0, hdrlen; dprintk("%s: sending from %02X to %02X\n", __func__, @@ -955,10 +956,10 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) if (rc) goto out; } - hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr); + dev = llc->dev; + hdrlen = READ_ONCE(dev->hard_header_len) + llc_ui_header_len(sk, addr); size = hdrlen + len; - if (size > llc->dev->mtu) - size = llc->dev->mtu; + size = min_t(size_t, size, READ_ONCE(dev->mtu)); copied = size - hdrlen; rc = -EINVAL; if (copied < 0) @@ -968,7 +969,13 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) lock_sock(sk); if (!skb) goto out; - skb->dev = llc->dev; + if (sock_flag(sk, SOCK_ZAPPED) || + llc->dev != dev || + hdrlen != READ_ONCE(dev->hard_header_len) + + llc_ui_header_len(sk, addr) || + size > READ_ONCE(dev->mtu)) + goto out; + skb->dev = dev; skb->protocol = llc_proto_type(addr->sllc_arphrd); skb_reserve(skb, hdrlen); rc = memcpy_from_msg(skb_put(skb, copied), msg, copied);