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 | 14 |
5 files changed, 21 insertions, 11 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 5d74c847efec..6fac5b8a42c2 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1345,6 +1345,11 @@ struct net_device { unsigned char if_port; /* Selectable AUI, TP,..*/ unsigned char dma; /* DMA channel */ + /* Note : dev->mtu is often read without holding a lock. + * Writers usually hold RTNL. + * It is recommended to use ACCESS_ONCE() to annotate the reads + * and writes. + */ unsigned int mtu; /* interface MTU value */ unsigned short type; /* interface hardware type */ unsigned short hard_header_len; /* hardware hdr length */ diff --git a/include/net/ip.h b/include/net/ip.h index 8ec53320c902..333f1159d0f8 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -522,4 +522,9 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, int ip_misc_proc_init(void); #endif +static inline bool inetdev_valid_mtu(unsigned int mtu) +{ + return likely(mtu >= 68); +} + #endif /* _IP_H */ diff --git a/net/core/dev.c b/net/core/dev.c index 4c821b721713..7e499da4a06f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5680,7 +5680,8 @@ static 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 */ + ACCESS_ONCE(dev->mtu) = new_mtu; return 0; } diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 710fe64fb2f7..026f69106ec2 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1318,11 +1318,6 @@ skip: } } -static bool inetdev_valid_mtu(unsigned int mtu) -{ - return mtu >= 68; -} - 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 2a05dfc9a35e..260e50e77d55 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1106,13 +1106,17 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, rt = *rtp; if (unlikely(!rt)) return -EFAULT; - /* - * 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) : ACCESS_ONCE(rt->dst.dev->mtu); + + if (!inetdev_valid_mtu(cork->fragsize)) + return -ENETUNREACH; + 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; |