Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mctp: Use output netdev to allocate skb headroom

Previously the skb was allocated with headroom MCTP_HEADER_MAXLEN,
but that isn't sufficient if we are using devs that are not MCTP
specific.

This also adds a check that the smctp_halen provided to sendmsg for
extended addressing is the correct size for the netdev.

Fixes: 833ef3b91de6 ("mctp: Populate socket implementation")
Reported-by: Matthew Rinaldi <mjrinal@g.clemson.edu>
Signed-off-by: Matt Johnston <matt@codeconstruct.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Matt Johnston and committed by
David S. Miller
4a9dda1c 8ce40a2f

+44 -18
-2
include/net/mctp.h
··· 36 36 #define MCTP_HDR_TAG_SHIFT 0 37 37 #define MCTP_HDR_TAG_MASK GENMASK(2, 0) 38 38 39 - #define MCTP_HEADER_MAXLEN 4 40 - 41 39 #define MCTP_INITIAL_DEFAULT_NET 1 42 40 43 41 static inline bool mctp_address_unicast(mctp_eid_t eid)
+33 -13
net/mctp/af_mctp.c
··· 93 93 static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) 94 94 { 95 95 DECLARE_SOCKADDR(struct sockaddr_mctp *, addr, msg->msg_name); 96 - const int hlen = MCTP_HEADER_MAXLEN + sizeof(struct mctp_hdr); 97 96 int rc, addrlen = msg->msg_namelen; 98 97 struct sock *sk = sock->sk; 99 98 struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); 100 99 struct mctp_skb_cb *cb; 101 100 struct mctp_route *rt; 102 - struct sk_buff *skb; 101 + struct sk_buff *skb = NULL; 102 + int hlen; 103 103 104 104 if (addr) { 105 105 const u8 tagbits = MCTP_TAG_MASK | MCTP_TAG_OWNER | ··· 129 129 if (addr->smctp_network == MCTP_NET_ANY) 130 130 addr->smctp_network = mctp_default_net(sock_net(sk)); 131 131 132 + /* direct addressing */ 133 + if (msk->addr_ext && addrlen >= sizeof(struct sockaddr_mctp_ext)) { 134 + DECLARE_SOCKADDR(struct sockaddr_mctp_ext *, 135 + extaddr, msg->msg_name); 136 + struct net_device *dev; 137 + 138 + rc = -EINVAL; 139 + rcu_read_lock(); 140 + dev = dev_get_by_index_rcu(sock_net(sk), extaddr->smctp_ifindex); 141 + /* check for correct halen */ 142 + if (dev && extaddr->smctp_halen == dev->addr_len) { 143 + hlen = LL_RESERVED_SPACE(dev) + sizeof(struct mctp_hdr); 144 + rc = 0; 145 + } 146 + rcu_read_unlock(); 147 + if (rc) 148 + goto err_free; 149 + rt = NULL; 150 + } else { 151 + rt = mctp_route_lookup(sock_net(sk), addr->smctp_network, 152 + addr->smctp_addr.s_addr); 153 + if (!rt) { 154 + rc = -EHOSTUNREACH; 155 + goto err_free; 156 + } 157 + hlen = LL_RESERVED_SPACE(rt->dev->dev) + sizeof(struct mctp_hdr); 158 + } 159 + 132 160 skb = sock_alloc_send_skb(sk, hlen + 1 + len, 133 161 msg->msg_flags & MSG_DONTWAIT, &rc); 134 162 if (!skb) ··· 175 147 cb = __mctp_cb(skb); 176 148 cb->net = addr->smctp_network; 177 149 178 - /* direct addressing */ 179 - if (msk->addr_ext && addrlen >= sizeof(struct sockaddr_mctp_ext)) { 150 + if (!rt) { 151 + /* fill extended address in cb */ 180 152 DECLARE_SOCKADDR(struct sockaddr_mctp_ext *, 181 153 extaddr, msg->msg_name); 182 154 ··· 187 159 } 188 160 189 161 cb->ifindex = extaddr->smctp_ifindex; 162 + /* smctp_halen is checked above */ 190 163 cb->halen = extaddr->smctp_halen; 191 164 memcpy(cb->haddr, extaddr->smctp_haddr, cb->halen); 192 - 193 - rt = NULL; 194 - } else { 195 - rt = mctp_route_lookup(sock_net(sk), addr->smctp_network, 196 - addr->smctp_addr.s_addr); 197 - if (!rt) { 198 - rc = -EHOSTUNREACH; 199 - goto err_free; 200 - } 201 165 } 202 166 203 167 rc = mctp_local_output(sk, rt, skb, addr->smctp_addr.s_addr,
+11 -3
net/mctp/route.c
··· 503 503 504 504 if (cb->ifindex) { 505 505 /* direct route; use the hwaddr we stashed in sendmsg */ 506 + if (cb->halen != skb->dev->addr_len) { 507 + /* sanity check, sendmsg should have already caught this */ 508 + kfree_skb(skb); 509 + return -EMSGSIZE; 510 + } 506 511 daddr = cb->haddr; 507 512 } else { 508 513 /* If lookup fails let the device handle daddr==NULL */ ··· 761 756 { 762 757 const unsigned int hlen = sizeof(struct mctp_hdr); 763 758 struct mctp_hdr *hdr, *hdr2; 764 - unsigned int pos, size; 759 + unsigned int pos, size, headroom; 765 760 struct sk_buff *skb2; 766 761 int rc; 767 762 u8 seq; ··· 775 770 return -EMSGSIZE; 776 771 } 777 772 773 + /* keep same headroom as the original skb */ 774 + headroom = skb_headroom(skb); 775 + 778 776 /* we've got the header */ 779 777 skb_pull(skb, hlen); 780 778 ··· 785 777 /* size of message payload */ 786 778 size = min(mtu - hlen, skb->len - pos); 787 779 788 - skb2 = alloc_skb(MCTP_HEADER_MAXLEN + hlen + size, GFP_KERNEL); 780 + skb2 = alloc_skb(headroom + hlen + size, GFP_KERNEL); 789 781 if (!skb2) { 790 782 rc = -ENOMEM; 791 783 break; ··· 801 793 skb_set_owner_w(skb2, skb->sk); 802 794 803 795 /* establish packet */ 804 - skb_reserve(skb2, MCTP_HEADER_MAXLEN); 796 + skb_reserve(skb2, headroom); 805 797 skb_reset_network_header(skb2); 806 798 skb_put(skb2, hlen + size); 807 799 skb2->transport_header = skb2->network_header + hlen;