Skip to content

Commit 6e27831

Browse files
committed
Merge tag 'net-6.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Paolo Abeni: "Including fixes from netfilter. Current release - regressions: - mtk_eth_soc: fix NULL pointer dereference Previous releases - regressions: - core: - skb_partial_csum_set() fix against transport header magic value - fix load-tearing on sk->sk_stamp in sock_recv_cmsgs(). - annotate sk->sk_err write from do_recvmmsg() - add vlan_get_protocol_and_depth() helper - netlink: annotate accesses to nlk->cb_running - netfilter: always release netdev hooks from notifier Previous releases - always broken: - core: deal with most data-races in sk_wait_event() - netfilter: fix possible bug_on with enable_hooks=1 - eth: bonding: fix send_peer_notif overflow - eth: xpcs: fix incorrect number of interfaces - eth: ipvlan: fix out-of-bounds caused by unclear skb->cb - eth: stmmac: Initialize MAC_ONEUS_TIC_COUNTER register" * tag 'net-6.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (31 commits) af_unix: Fix data races around sk->sk_shutdown. af_unix: Fix a data race of sk->sk_receive_queue->qlen. net: datagram: fix data-races in datagram_poll() net: mscc: ocelot: fix stat counter register values ipvlan:Fix out-of-bounds caused by unclear skb->cb docs: networking: fix x25-iface.rst heading & index order gve: Remove the code of clearing PBA bit tcp: add annotations around sk->sk_shutdown accesses net: add vlan_get_protocol_and_depth() helper net: pcs: xpcs: fix incorrect number of interfaces net: deal with most data-races in sk_wait_event() net: annotate sk->sk_err write from do_recvmmsg() netlink: annotate accesses to nlk->cb_running kselftest: bonding: add num_grat_arp test selftests: forwarding: lib: add netns support for tc rule handle stats get Documentation: bonding: fix the doc of peer_notif_delay bonding: fix send_peer_notif overflow net: ethernet: mtk_eth_soc: fix NULL pointer dereference selftests: nft_flowtable.sh: check ingress/egress chain too selftests: nft_flowtable.sh: monitor result file sizes ...
2 parents 691e1ee + cceac92 commit 6e27831

File tree

49 files changed

+361
-112
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+361
-112
lines changed

Documentation/networking/bonding.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -776,10 +776,11 @@ peer_notif_delay
776776
Specify the delay, in milliseconds, between each peer
777777
notification (gratuitous ARP and unsolicited IPv6 Neighbor
778778
Advertisement) when they are issued after a failover event.
779-
This delay should be a multiple of the link monitor interval
780-
(arp_interval or miimon, whichever is active). The default
781-
value is 0 which means to match the value of the link monitor
782-
interval.
779+
This delay should be a multiple of the MII link monitor interval
780+
(miimon).
781+
782+
The valid range is 0 - 300000. The default value is 0, which means
783+
to match the value of the MII link monitor interval.
783784

784785
prio
785786
Slave priority. A higher number means higher priority.

Documentation/networking/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ Contents:
116116
udplite
117117
vrf
118118
vxlan
119-
x25-iface
120119
x25
120+
x25-iface
121121
xfrm_device
122122
xfrm_proc
123123
xfrm_sync

Documentation/networking/x25-iface.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
.. SPDX-License-Identifier: GPL-2.0
22
3-
============================-
43
X.25 Device Driver Interface
5-
============================-
4+
============================
65

76
Version 1.1
87

drivers/net/bonding/bond_netlink.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ static int bond_fill_slave_info(struct sk_buff *skb,
8484
return -EMSGSIZE;
8585
}
8686

87+
/* Limit the max delay range to 300s */
88+
static struct netlink_range_validation delay_range = {
89+
.max = 300000,
90+
};
91+
8792
static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
8893
[IFLA_BOND_MODE] = { .type = NLA_U8 },
8994
[IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 },
@@ -114,7 +119,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
114119
[IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NLA_BINARY,
115120
.len = ETH_ALEN },
116121
[IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NLA_U8 },
117-
[IFLA_BOND_PEER_NOTIF_DELAY] = { .type = NLA_U32 },
122+
[IFLA_BOND_PEER_NOTIF_DELAY] = NLA_POLICY_FULL_RANGE(NLA_U32, &delay_range),
118123
[IFLA_BOND_MISSED_MAX] = { .type = NLA_U8 },
119124
[IFLA_BOND_NS_IP6_TARGET] = { .type = NLA_NESTED },
120125
};

drivers/net/bonding/bond_options.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ static const struct bond_opt_value bond_num_peer_notif_tbl[] = {
169169
{ NULL, -1, 0}
170170
};
171171

172+
static const struct bond_opt_value bond_peer_notif_delay_tbl[] = {
173+
{ "off", 0, 0},
174+
{ "maxval", 300000, BOND_VALFLAG_MAX},
175+
{ NULL, -1, 0}
176+
};
177+
172178
static const struct bond_opt_value bond_primary_reselect_tbl[] = {
173179
{ "always", BOND_PRI_RESELECT_ALWAYS, BOND_VALFLAG_DEFAULT},
174180
{ "better", BOND_PRI_RESELECT_BETTER, 0},
@@ -488,7 +494,7 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
488494
.id = BOND_OPT_PEER_NOTIF_DELAY,
489495
.name = "peer_notif_delay",
490496
.desc = "Delay between each peer notification on failover event, in milliseconds",
491-
.values = bond_intmax_tbl,
497+
.values = bond_peer_notif_delay_tbl,
492498
.set = bond_option_peer_notif_delay_set
493499
}
494500
};

drivers/net/ethernet/google/gve/gve_main.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -294,19 +294,6 @@ static int gve_napi_poll_dqo(struct napi_struct *napi, int budget)
294294
bool reschedule = false;
295295
int work_done = 0;
296296

297-
/* Clear PCI MSI-X Pending Bit Array (PBA)
298-
*
299-
* This bit is set if an interrupt event occurs while the vector is
300-
* masked. If this bit is set and we reenable the interrupt, it will
301-
* fire again. Since we're just about to poll the queue state, we don't
302-
* need it to fire again.
303-
*
304-
* Under high softirq load, it's possible that the interrupt condition
305-
* is triggered twice before we got the chance to process it.
306-
*/
307-
gve_write_irq_doorbell_dqo(priv, block,
308-
GVE_ITR_NO_UPDATE_DQO | GVE_ITR_CLEAR_PBA_BIT_DQO);
309-
310297
if (block->tx)
311298
reschedule |= gve_tx_poll_dqo(block, /*do_clean=*/true);
312299

drivers/net/ethernet/mediatek/mtk_wed.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ __mtk_wed_detach(struct mtk_wed_device *dev)
654654
BIT(hw->index), BIT(hw->index));
655655
}
656656

657-
if (!hw_list[!hw->index]->wed_dev &&
657+
if ((!hw_list[!hw->index] || !hw_list[!hw->index]->wed_dev) &&
658658
hw->eth->dma_dev != hw->eth->dev)
659659
mtk_eth_set_dma_device(hw->eth, hw->eth->dev);
660660

drivers/net/ethernet/mscc/vsc7514_regs.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -307,15 +307,15 @@ static const u32 vsc7514_sys_regmap[] = {
307307
REG(SYS_COUNT_DROP_YELLOW_PRIO_4, 0x000218),
308308
REG(SYS_COUNT_DROP_YELLOW_PRIO_5, 0x00021c),
309309
REG(SYS_COUNT_DROP_YELLOW_PRIO_6, 0x000220),
310-
REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000214),
311-
REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000218),
312-
REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00021c),
313-
REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000220),
314-
REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000224),
315-
REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000228),
316-
REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00022c),
317-
REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000230),
318-
REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000234),
310+
REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000224),
311+
REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000228),
312+
REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00022c),
313+
REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000230),
314+
REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000234),
315+
REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000238),
316+
REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00023c),
317+
REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000240),
318+
REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000244),
319319
REG(SYS_RESET_CFG, 0x000508),
320320
REG(SYS_CMID, 0x00050c),
321321
REG(SYS_VLAN_ETYPE_CFG, 0x000510),

drivers/net/ethernet/stmicro/stmmac/dwmac4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ enum power_event {
181181
#define GMAC4_LPI_CTRL_STATUS 0xd0
182182
#define GMAC4_LPI_TIMER_CTRL 0xd4
183183
#define GMAC4_LPI_ENTRY_TIMER 0xd8
184+
#define GMAC4_MAC_ONEUS_TIC_COUNTER 0xdc
184185

185186
/* LPI control and status defines */
186187
#define GMAC4_LPI_CTRL_STATUS_LPITCSE BIT(21) /* LPI Tx Clock Stop Enable */

drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ static void dwmac4_core_init(struct mac_device_info *hw,
2525
struct stmmac_priv *priv = netdev_priv(dev);
2626
void __iomem *ioaddr = hw->pcsr;
2727
u32 value = readl(ioaddr + GMAC_CONFIG);
28+
u32 clk_rate;
2829

2930
value |= GMAC_CORE_INIT;
3031

@@ -47,6 +48,10 @@ static void dwmac4_core_init(struct mac_device_info *hw,
4748

4849
writel(value, ioaddr + GMAC_CONFIG);
4950

51+
/* Configure LPI 1us counter to number of CSR clock ticks in 1us - 1 */
52+
clk_rate = clk_get_rate(priv->plat->stmmac_clk);
53+
writel((clk_rate / 1000000) - 1, ioaddr + GMAC4_MAC_ONEUS_TIC_COUNTER);
54+
5055
/* Enable GMAC interrupts */
5156
value = GMAC_INT_DEFAULT_ENABLE;
5257

drivers/net/ipvlan/ipvlan_core.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
436436
goto err;
437437
}
438438
skb_dst_set(skb, &rt->dst);
439+
440+
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
441+
439442
err = ip_local_out(net, skb->sk, skb);
440443
if (unlikely(net_xmit_eval(err)))
441444
dev->stats.tx_errors++;
@@ -474,6 +477,9 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
474477
goto err;
475478
}
476479
skb_dst_set(skb, dst);
480+
481+
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
482+
477483
err = ip6_local_out(net, skb->sk, skb);
478484
if (unlikely(net_xmit_eval(err)))
479485
dev->stats.tx_errors++;

drivers/net/mdio/mdio-mvusb.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static int mvusb_mdio_probe(struct usb_interface *interface,
6767
struct device *dev = &interface->dev;
6868
struct mvusb_mdio *mvusb;
6969
struct mii_bus *mdio;
70+
int ret;
7071

7172
mdio = devm_mdiobus_alloc_size(dev, sizeof(*mvusb));
7273
if (!mdio)
@@ -87,7 +88,15 @@ static int mvusb_mdio_probe(struct usb_interface *interface,
8788
mdio->write = mvusb_mdio_write;
8889

8990
usb_set_intfdata(interface, mvusb);
90-
return of_mdiobus_register(mdio, dev->of_node);
91+
ret = of_mdiobus_register(mdio, dev->of_node);
92+
if (ret)
93+
goto put_dev;
94+
95+
return 0;
96+
97+
put_dev:
98+
usb_put_dev(mvusb->udev);
99+
return ret;
91100
}
92101

93102
static void mvusb_mdio_disconnect(struct usb_interface *interface)

drivers/net/pcs/pcs-xpcs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1203,7 +1203,7 @@ static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
12031203
[DW_XPCS_2500BASEX] = {
12041204
.supported = xpcs_2500basex_features,
12051205
.interface = xpcs_2500basex_interfaces,
1206-
.num_interfaces = ARRAY_SIZE(xpcs_2500basex_features),
1206+
.num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
12071207
.an_mode = DW_2500BASEX,
12081208
},
12091209
};

drivers/net/phy/bcm-phy-lib.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ static inline int bcm_phy_write_exp_sel(struct phy_device *phydev,
4040
return bcm_phy_write_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER, val);
4141
}
4242

43+
static inline int bcm_phy_read_exp_sel(struct phy_device *phydev, u16 reg)
44+
{
45+
return bcm_phy_read_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER);
46+
}
47+
4348
int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val);
4449
int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum);
4550

drivers/net/phy/bcm7xxx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ static int bcm7xxx_16nm_ephy_afe_config(struct phy_device *phydev)
486486
bcm_phy_write_misc(phydev, 0x0038, 0x0002, 0xede0);
487487

488488
/* Read CORE_EXPA9 */
489-
tmp = bcm_phy_read_exp(phydev, 0x00a9);
489+
tmp = bcm_phy_read_exp_sel(phydev, 0x00a9);
490490
/* CORE_EXPA9[6:1] is rcalcode[5:0] */
491491
rcalcode = (tmp & 0x7e) / 2;
492492
/* Correct RCAL code + 1 is -1% rprogr, LP: +16 */

drivers/net/tap.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control,
742742

743743
/* Move network header to the right position for VLAN tagged packets */
744744
if (eth_type_vlan(skb->protocol) &&
745-
__vlan_get_protocol(skb, skb->protocol, &depth) != 0)
745+
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
746746
skb_set_network_header(skb, depth);
747747

748748
/* copy skb_ubuf_info for callback when skb has no error */
@@ -1197,7 +1197,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
11971197

11981198
/* Move network header to the right position for VLAN tagged packets */
11991199
if (eth_type_vlan(skb->protocol) &&
1200-
__vlan_get_protocol(skb, skb->protocol, &depth) != 0)
1200+
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
12011201
skb_set_network_header(skb, depth);
12021202

12031203
rcu_read_lock();

include/linux/dim.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,9 @@ void dim_park_tired(struct dim *dim);
236236
*
237237
* Calculate the delta between two samples (in data rates).
238238
* Takes into consideration counter wrap-around.
239+
* Returned boolean indicates whether curr_stats are reliable.
239240
*/
240-
void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
241+
bool dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
241242
struct dim_stats *curr_stats);
242243

243244
/**

include/linux/if_vlan.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,23 @@ static inline __be16 vlan_get_protocol(const struct sk_buff *skb)
637637
return __vlan_get_protocol(skb, skb->protocol, NULL);
638638
}
639639

640+
/* This version of __vlan_get_protocol() also pulls mac header in skb->head */
641+
static inline __be16 vlan_get_protocol_and_depth(struct sk_buff *skb,
642+
__be16 type, int *depth)
643+
{
644+
int maclen;
645+
646+
type = __vlan_get_protocol(skb, type, &maclen);
647+
648+
if (type) {
649+
if (!pskb_may_pull(skb, maclen))
650+
type = 0;
651+
else if (depth)
652+
*depth = maclen;
653+
}
654+
return type;
655+
}
656+
640657
/* A getter for the SKB protocol field which will handle VLAN tags consistently
641658
* whether VLAN acceleration is enabled or not.
642659
*/

include/net/bonding.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ struct bonding {
233233
*/
234234
spinlock_t mode_lock;
235235
spinlock_t stats_lock;
236-
u8 send_peer_notif;
236+
u32 send_peer_notif;
237237
u8 igmp_retrans;
238238
#ifdef CONFIG_PROC_FS
239239
struct proc_dir_entry *proc_entry;

include/net/sock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2718,7 +2718,7 @@ static inline void sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
27182718
__sock_recv_cmsgs(msg, sk, skb);
27192719
else if (unlikely(sock_flag(sk, SOCK_TIMESTAMP)))
27202720
sock_write_timestamp(sk, skb->tstamp);
2721-
else if (unlikely(sk->sk_stamp == SK_DEFAULT_STAMP))
2721+
else if (unlikely(sock_read_timestamp(sk) == SK_DEFAULT_STAMP))
27222722
sock_write_timestamp(sk, 0);
27232723
}
27242724

lib/dim/dim.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void dim_park_tired(struct dim *dim)
5454
}
5555
EXPORT_SYMBOL(dim_park_tired);
5656

57-
void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
57+
bool dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
5858
struct dim_stats *curr_stats)
5959
{
6060
/* u32 holds up to 71 minutes, should be enough */
@@ -66,7 +66,7 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
6666
start->comp_ctr);
6767

6868
if (!delta_us)
69-
return;
69+
return false;
7070

7171
curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
7272
curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
@@ -79,5 +79,6 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
7979
else
8080
curr_stats->cpe_ratio = 0;
8181

82+
return true;
8283
}
8384
EXPORT_SYMBOL(dim_calc_stats);

lib/dim/net_dim.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ void net_dim(struct dim *dim, struct dim_sample end_sample)
227227
dim->start_sample.event_ctr);
228228
if (nevents < DIM_NEVENTS)
229229
break;
230-
dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats);
230+
if (!dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats))
231+
break;
231232
if (net_dim_decision(&curr_stats, dim)) {
232233
dim->state = DIM_APPLY_NEW_PROFILE;
233234
schedule_work(&dim->work);

lib/dim/rdma_dim.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ void rdma_dim(struct dim *dim, u64 completions)
8888
nevents = curr_sample->event_ctr - dim->start_sample.event_ctr;
8989
if (nevents < DIM_NEVENTS)
9090
break;
91-
dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats);
91+
if (!dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats))
92+
break;
9293
if (rdma_dim_decision(&curr_stats, dim)) {
9394
dim->state = DIM_APPLY_NEW_PROFILE;
9495
schedule_work(&dim->work);

net/bridge/br_forward.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb
4242
eth_type_vlan(skb->protocol)) {
4343
int depth;
4444

45-
if (!__vlan_get_protocol(skb, skb->protocol, &depth))
45+
if (!vlan_get_protocol_and_depth(skb, skb->protocol, &depth))
4646
goto drop;
4747

4848
skb_set_network_header(skb, depth);

net/core/datagram.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -807,18 +807,21 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
807807
{
808808
struct sock *sk = sock->sk;
809809
__poll_t mask;
810+
u8 shutdown;
810811

811812
sock_poll_wait(file, sock, wait);
812813
mask = 0;
813814

814815
/* exceptional events? */
815-
if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
816+
if (READ_ONCE(sk->sk_err) ||
817+
!skb_queue_empty_lockless(&sk->sk_error_queue))
816818
mask |= EPOLLERR |
817819
(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
818820

819-
if (sk->sk_shutdown & RCV_SHUTDOWN)
821+
shutdown = READ_ONCE(sk->sk_shutdown);
822+
if (shutdown & RCV_SHUTDOWN)
820823
mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
821-
if (sk->sk_shutdown == SHUTDOWN_MASK)
824+
if (shutdown == SHUTDOWN_MASK)
822825
mask |= EPOLLHUP;
823826

824827
/* readable? */
@@ -827,10 +830,12 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
827830

828831
/* Connection-based need to check for termination and startup */
829832
if (connection_based(sk)) {
830-
if (sk->sk_state == TCP_CLOSE)
833+
int state = READ_ONCE(sk->sk_state);
834+
835+
if (state == TCP_CLOSE)
831836
mask |= EPOLLHUP;
832837
/* connection hasn't started yet? */
833-
if (sk->sk_state == TCP_SYN_SENT)
838+
if (state == TCP_SYN_SENT)
834839
return mask;
835840
}
836841

0 commit comments

Comments
 (0)