mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
tipc: raise the minimum bearer MTU to fit tunnel and crypto overhead
A peer can lower the link MTU to TIPC_MIN_BEARER_MTU (100 bytes, plus
the UDP encapsulation header) with the max_pkt field of a RESET or
ACTIVATE message; tipc_link_proto_rcv() only checks the lower bound
returned by tipc_bearer_min_mtu(). The same bound is applied to the
device MTU when a bearer is enabled.
That bound predates two later reductions of the link MSS:
tipc_link_mss() = mtu - INT_H_SIZE (tunnel header)
- EMSG_OVERHEAD (CONFIG_TIPC_CRYPTO)
With CONFIG_TIPC_CRYPTO=y, which is the default, an MTU of 100 gives an
MSS of 28. Once the link comes up, tipc_named_node_up() calls
named_distribute(), which computes
msg_dsz = ((tipc_node_get_mtu() - INT_H_SIZE) / ITEM_SIZE) * ITEM_SIZE;
For an MSS of 28 the subtraction is negative and the result truncates to
0xfffffff0; for an MSS between 40 and 59 it is 0. named_prepare_buf()
then allocates a buffer with no room for any item (the u32 size wraps),
and msg_rem never reaches zero, so every cluster-scope publication on
the node is written with publ_to_item() past the end of that one skb,
over skb_shared_info and into adjacent memory.
Without crypto the MSS is at least 60, which still does not hold the
first fragment built by tipc_msg_build(): INT_H_SIZE fragment header
plus a message header of up to MAX_H_SIZE. With pktmax below that, the
header copies run past the pktmax bytes allocated for the fragment.
Raise TIPC_MIN_BEARER_MTU to MAX_H_SIZE + 2 * INT_H_SIZE so the MSS can
always hold INT_H_SIZE + MAX_H_SIZE, which also leaves room for name
table items, and add tipc_bearer_mtu_floor(), which adds EMSG_OVERHEAD
on top for CONFIG_TIPC_CRYPTO=y. Use it for the device MTU check
(tipc_mtu_bad()), the UDP MTU check, the netlink MTU setting and
tipc_bearer_min_mtu(), which also bounds the max_pkt negotiation.
Found by manual code review and reproduced with KASAN using two network
namespaces joined by a veth pair (see below).
Fixes: fc1b6d6de2 ("tipc: introduce TIPC encryption & authentication")
Fixes: 2320bcdae6 ("tipc: fix changeover issues due to large packet")
Suggested-by: Tung Nguyen <tung.quang.nguyen@est.tech>
Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com>
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
Link: https://patch.msgid.link/179340438471.4412.6707287163192409104@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
6d2cf411ab
commit
0389706606
|
|
@ -579,9 +579,22 @@ int tipc_bearer_mtu(struct net *net, u32 bearer_id)
|
|||
return mtu;
|
||||
}
|
||||
|
||||
/* tipc_bearer_mtu_floor - smallest bearer MTU, excluding the media
|
||||
* encapsulation header, that leaves room for a fragment header plus a
|
||||
* full message header after the link MSS reductions (see tipc_link_mss())
|
||||
*/
|
||||
u32 tipc_bearer_mtu_floor(void)
|
||||
{
|
||||
#ifdef CONFIG_TIPC_CRYPTO
|
||||
return TIPC_MIN_BEARER_MTU + EMSG_OVERHEAD;
|
||||
#else
|
||||
return TIPC_MIN_BEARER_MTU;
|
||||
#endif
|
||||
}
|
||||
|
||||
int tipc_bearer_min_mtu(struct net *net, u32 bearer_id)
|
||||
{
|
||||
int mtu = TIPC_MIN_BEARER_MTU;
|
||||
int mtu = tipc_bearer_mtu_floor();
|
||||
struct tipc_bearer *b;
|
||||
|
||||
rcu_read_lock();
|
||||
|
|
@ -1197,7 +1210,7 @@ int __tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
#ifdef CONFIG_TIPC_MEDIA_UDP
|
||||
if (nla_get_u32(props[TIPC_NLA_PROP_MTU]) <
|
||||
b->encap_hlen + TIPC_MIN_BEARER_MTU) {
|
||||
b->encap_hlen + tipc_bearer_mtu_floor()) {
|
||||
NL_SET_ERR_MSG(info->extack,
|
||||
"MTU value is out-of-range");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -60,8 +60,10 @@
|
|||
#define TIPC_MEDIA_TYPE_IB 2
|
||||
#define TIPC_MEDIA_TYPE_UDP 3
|
||||
|
||||
/* Minimum bearer MTU */
|
||||
#define TIPC_MIN_BEARER_MTU (MAX_H_SIZE + INT_H_SIZE)
|
||||
/* Minimum bearer MTU, not counting the crypto overhead, see
|
||||
* tipc_bearer_mtu_floor()
|
||||
*/
|
||||
#define TIPC_MIN_BEARER_MTU (MAX_H_SIZE + 2 * INT_H_SIZE)
|
||||
|
||||
/* Maximum bearer MTU
|
||||
*
|
||||
|
|
@ -241,6 +243,7 @@ void tipc_bearer_cleanup(void);
|
|||
void tipc_bearer_stop(struct net *net);
|
||||
int tipc_bearer_mtu(struct net *net, u32 bearer_id);
|
||||
int tipc_bearer_min_mtu(struct net *net, u32 bearer_id);
|
||||
u32 tipc_bearer_mtu_floor(void);
|
||||
bool tipc_bearer_bcast_support(struct net *net, u32 bearer_id);
|
||||
void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
|
||||
struct sk_buff *skb,
|
||||
|
|
@ -265,7 +268,7 @@ static inline void tipc_loopback_trace(struct net *net,
|
|||
/* check if device MTU is usable for tipc bearers */
|
||||
static inline bool tipc_mtu_bad(struct net_device *dev)
|
||||
{
|
||||
if (dev->mtu >= TIPC_MIN_BEARER_MTU &&
|
||||
if (dev->mtu >= tipc_bearer_mtu_floor() &&
|
||||
dev->mtu <= TIPC_MAX_BEARER_MTU)
|
||||
return false;
|
||||
netdev_warn(dev, "MTU not usable for tipc bearer\n");
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb);
|
|||
/* check if configured MTU is too low for tipc headers */
|
||||
static inline bool tipc_udp_mtu_bad(u32 mtu)
|
||||
{
|
||||
if (mtu >= (TIPC_MIN_BEARER_MTU + sizeof(struct iphdr) +
|
||||
if (mtu >= (tipc_bearer_mtu_floor() + sizeof(struct iphdr) +
|
||||
sizeof(struct udphdr)))
|
||||
return false;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user