diff options
-rw-r--r-- | include/linux/netdevice.h | 5 | ||||
-rw-r--r-- | include/net/ip.h | 5 | ||||
-rw-r--r-- | net/core/dev.c | 3 | ||||
-rw-r--r-- | net/ipv4/devinet.c | 5 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 13 |
5 files changed, 20 insertions, 11 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index eeacebd7debb..de025c0585ca 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1848,6 +1848,11 @@ struct net_device { unsigned char if_port; unsigned char dma; + /* Note : dev->mtu is often read without holding a lock. + * Writers usually hold RTNL. + * It is recommended to use READ_ONCE() to annotate the reads, + * and to use WRITE_ONCE() to annotate the writes. + */ unsigned int mtu; unsigned int min_mtu; unsigned int max_mtu; diff --git a/include/net/ip.h b/include/net/ip.h index 49c672c8cdae..561ab1755f73 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -721,4 +721,9 @@ int ip_misc_proc_init(void); int rtm_getroute_parse_ip_proto(struct nlattr *attr, u8 *ip_proto, u8 family, struct netlink_ext_ack *extack); +static inline bool inetdev_valid_mtu(unsigned int mtu) +{ + return likely(mtu >= IPV4_MIN_MTU); +} + #endif /* _IP_H */ diff --git a/net/core/dev.c b/net/core/dev.c index 002d5d460495..f9cd0705a392 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7672,7 +7672,8 @@ int __dev_set_mtu(struct net_device *dev, int new_mtu) if (ops->ndo_change_mtu) return ops->ndo_change_mtu(dev, new_mtu); - dev->mtu = new_mtu; + /* Pairs with all the lockless reads of dev->mtu in the stack */ + WRITE_ONCE(dev->mtu, new_mtu); return 0; } EXPORT_SYMBOL(__dev_set_mtu); diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index c5ebfa199794..af0c3ea78c45 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1449,11 +1449,6 @@ skip: } } -static bool inetdev_valid_mtu(unsigned int mtu) -{ - return mtu >= IPV4_MIN_MTU; -} - static void inetdev_send_gratuitous_arp(struct net_device *dev, struct in_device *in_dev) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index b6f3a9f0b8be..c6c761617cce 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1173,15 +1173,18 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, cork->addr = ipc->addr; } - /* - * We steal reference to this route, caller should not release it - */ - *rtp = NULL; cork->fragsize = ip_sk_use_pmtu(sk) ? - dst_mtu(&rt->dst) : rt->dst.dev->mtu; + dst_mtu(&rt->dst) : READ_ONCE(rt->dst.dev->mtu); + + if (!inetdev_valid_mtu(cork->fragsize)) + return -ENETUNREACH; cork->gso_size = ipc->gso_size; + cork->dst = &rt->dst; + /* We stole this route, caller should not release it. */ + *rtp = NULL; + cork->length = 0; cork->ttl = ipc->ttl; cork->tos = ipc->tos; |