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

Merge branch 'tipc-fixes'

Xin Long says:

====================
tipc: fix the mtu update in link mtu negotiation

This patchset fixes a crash caused by a too small MTU carried in the
activate msg. Note that as such malicious packet does not exist in
the normal env, the fix won't break any application

The 1st patch introduces a function to calculate the minimum MTU for
the bearer, and the 2nd patch fixes the crash with this helper. While
at it, the 3rd patch fixes the udp bearer mtu update by netlink with
this helper.
====================

Reviewed-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

+27 -7
+15 -2
net/tipc/bearer.c
··· 541 541 return mtu; 542 542 } 543 543 544 + int tipc_bearer_min_mtu(struct net *net, u32 bearer_id) 545 + { 546 + int mtu = TIPC_MIN_BEARER_MTU; 547 + struct tipc_bearer *b; 548 + 549 + rcu_read_lock(); 550 + b = bearer_get(net, bearer_id); 551 + if (b) 552 + mtu += b->encap_hlen; 553 + rcu_read_unlock(); 554 + return mtu; 555 + } 556 + 544 557 /* tipc_bearer_xmit_skb - sends buffer to destination over bearer 545 558 */ 546 559 void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, ··· 1151 1138 return -EINVAL; 1152 1139 } 1153 1140 #ifdef CONFIG_TIPC_MEDIA_UDP 1154 - if (tipc_udp_mtu_bad(nla_get_u32 1155 - (props[TIPC_NLA_PROP_MTU]))) { 1141 + if (nla_get_u32(props[TIPC_NLA_PROP_MTU]) < 1142 + b->encap_hlen + TIPC_MIN_BEARER_MTU) { 1156 1143 NL_SET_ERR_MSG(info->extack, 1157 1144 "MTU value is out-of-range"); 1158 1145 return -EINVAL;
+3
net/tipc/bearer.h
··· 146 146 * @identity: array index of this bearer within TIPC bearer array 147 147 * @disc: ptr to link setup request 148 148 * @net_plane: network plane ('A' through 'H') currently associated with bearer 149 + * @encap_hlen: encap headers length 149 150 * @up: bearer up flag (bit 0) 150 151 * @refcnt: tipc_bearer reference counter 151 152 * ··· 171 170 u32 identity; 172 171 struct tipc_discoverer *disc; 173 172 char net_plane; 173 + u16 encap_hlen; 174 174 unsigned long up; 175 175 refcount_t refcnt; 176 176 }; ··· 234 232 void tipc_bearer_cleanup(void); 235 233 void tipc_bearer_stop(struct net *net); 236 234 int tipc_bearer_mtu(struct net *net, u32 bearer_id); 235 + int tipc_bearer_min_mtu(struct net *net, u32 bearer_id); 237 236 bool tipc_bearer_bcast_support(struct net *net, u32 bearer_id); 238 237 void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, 239 238 struct sk_buff *skb,
+6 -3
net/tipc/link.c
··· 2200 2200 struct tipc_msg *hdr = buf_msg(skb); 2201 2201 struct tipc_gap_ack_blks *ga = NULL; 2202 2202 bool reply = msg_probe(hdr), retransmitted = false; 2203 - u32 dlen = msg_data_sz(hdr), glen = 0; 2203 + u32 dlen = msg_data_sz(hdr), glen = 0, msg_max; 2204 2204 u16 peers_snd_nxt = msg_next_sent(hdr); 2205 2205 u16 peers_tol = msg_link_tolerance(hdr); 2206 2206 u16 peers_prio = msg_linkprio(hdr); ··· 2239 2239 switch (mtyp) { 2240 2240 case RESET_MSG: 2241 2241 case ACTIVATE_MSG: 2242 + msg_max = msg_max_pkt(hdr); 2243 + if (msg_max < tipc_bearer_min_mtu(l->net, l->bearer_id)) 2244 + break; 2242 2245 /* Complete own link name with peer's interface name */ 2243 2246 if_name = strrchr(l->name, ':') + 1; 2244 2247 if (sizeof(l->name) - (if_name - l->name) <= TIPC_MAX_IF_NAME) ··· 2286 2283 l->peer_session = msg_session(hdr); 2287 2284 l->in_session = true; 2288 2285 l->peer_bearer_id = msg_bearer_id(hdr); 2289 - if (l->mtu > msg_max_pkt(hdr)) 2290 - l->mtu = msg_max_pkt(hdr); 2286 + if (l->mtu > msg_max) 2287 + l->mtu = msg_max; 2291 2288 break; 2292 2289 2293 2290 case STATE_MSG:
+3 -2
net/tipc/udp_media.c
··· 738 738 udp_conf.local_ip.s_addr = local.ipv4.s_addr; 739 739 udp_conf.use_udp_checksums = false; 740 740 ub->ifindex = dev->ifindex; 741 - if (tipc_mtu_bad(dev, sizeof(struct iphdr) + 742 - sizeof(struct udphdr))) { 741 + b->encap_hlen = sizeof(struct iphdr) + sizeof(struct udphdr); 742 + if (tipc_mtu_bad(dev, b->encap_hlen)) { 743 743 err = -EINVAL; 744 744 goto err; 745 745 } ··· 760 760 else 761 761 udp_conf.local_ip6 = local.ipv6; 762 762 ub->ifindex = dev->ifindex; 763 + b->encap_hlen = sizeof(struct ipv6hdr) + sizeof(struct udphdr); 763 764 b->mtu = 1280; 764 765 #endif 765 766 } else {