Commit f2e977f3 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-data-race-annotations'



Eric Dumazet says:

====================
net: another round of data-race annotations

Series inspired by some syzbot reports, taking care
of 4 socket fields that can be read locklessly.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 82ba0ff7 251cd405
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
	ipcm_init(ipcm);

	ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark);
	ipcm->sockc.tsflags = inet->sk.sk_tsflags;
	ipcm->sockc.tsflags = READ_ONCE(inet->sk.sk_tsflags);
	ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
	ipcm->addr = inet->inet_saddr;
	ipcm->protocol = inet->inet_num;
+19 −10
Original line number Diff line number Diff line
@@ -1053,6 +1053,12 @@ static inline void sk_wmem_queued_add(struct sock *sk, int val)
	WRITE_ONCE(sk->sk_wmem_queued, sk->sk_wmem_queued + val);
}

static inline void sk_forward_alloc_add(struct sock *sk, int val)
{
	/* Paired with lockless reads of sk->sk_forward_alloc */
	WRITE_ONCE(sk->sk_forward_alloc, sk->sk_forward_alloc + val);
}

void sk_stream_write_space(struct sock *sk);

/* OOB backlog add */
@@ -1377,7 +1383,7 @@ static inline int sk_forward_alloc_get(const struct sock *sk)
	if (sk->sk_prot->forward_alloc_get)
		return sk->sk_prot->forward_alloc_get(sk);
#endif
	return sk->sk_forward_alloc;
	return READ_ONCE(sk->sk_forward_alloc);
}

static inline bool __sk_stream_memory_free(const struct sock *sk, int wake)
@@ -1673,14 +1679,14 @@ static inline void sk_mem_charge(struct sock *sk, int size)
{
	if (!sk_has_account(sk))
		return;
	sk->sk_forward_alloc -= size;
	sk_forward_alloc_add(sk, -size);
}

static inline void sk_mem_uncharge(struct sock *sk, int size)
{
	if (!sk_has_account(sk))
		return;
	sk->sk_forward_alloc += size;
	sk_forward_alloc_add(sk, size);
	sk_mem_reclaim(sk);
}

@@ -1900,7 +1906,9 @@ struct sockcm_cookie {
static inline void sockcm_init(struct sockcm_cookie *sockc,
			       const struct sock *sk)
{
	*sockc = (struct sockcm_cookie) { .tsflags = sk->sk_tsflags };
	*sockc = (struct sockcm_cookie) {
		.tsflags = READ_ONCE(sk->sk_tsflags)
	};
}

int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
@@ -2695,9 +2703,9 @@ void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
static inline void
sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
{
	ktime_t kt = skb->tstamp;
	struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);

	u32 tsflags = READ_ONCE(sk->sk_tsflags);
	ktime_t kt = skb->tstamp;
	/*
	 * generate control messages if
	 * - receive time stamping in software requested
@@ -2705,10 +2713,10 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
	 * - hardware time stamps available and wanted
	 */
	if (sock_flag(sk, SOCK_RCVTSTAMP) ||
	    (sk->sk_tsflags & SOF_TIMESTAMPING_RX_SOFTWARE) ||
	    (kt && sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) ||
	    (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE) ||
	    (kt && tsflags & SOF_TIMESTAMPING_SOFTWARE) ||
	    (hwtstamps->hwtstamp &&
	     (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)))
	     (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)))
		__sock_recv_timestamp(msg, sk, skb);
	else
		sock_write_timestamp(sk, kt);
@@ -2730,7 +2738,8 @@ static inline void sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
#define TSFLAGS_ANY	  (SOF_TIMESTAMPING_SOFTWARE			| \
			   SOF_TIMESTAMPING_RAW_HARDWARE)

	if (sk->sk_flags & FLAGS_RECV_CMSGS || sk->sk_tsflags & TSFLAGS_ANY)
	if (sk->sk_flags & FLAGS_RECV_CMSGS ||
	    READ_ONCE(sk->sk_tsflags) & TSFLAGS_ANY)
		__sock_recv_cmsgs(msg, sk, skb);
	else if (unlikely(sock_flag(sk, SOCK_TIMESTAMP)))
		sock_write_timestamp(sk, skb->tstamp);
+6 −4
Original line number Diff line number Diff line
@@ -974,6 +974,7 @@ static void __j1939_sk_errqueue(struct j1939_session *session, struct sock *sk,
	struct sock_exterr_skb *serr;
	struct sk_buff *skb;
	char *state = "UNK";
	u32 tsflags;
	int err;

	jsk = j1939_sk(sk);
@@ -981,13 +982,14 @@ static void __j1939_sk_errqueue(struct j1939_session *session, struct sock *sk,
	if (!(jsk->state & J1939_SOCK_ERRQUEUE))
		return;

	tsflags = READ_ONCE(sk->sk_tsflags);
	switch (type) {
	case J1939_ERRQUEUE_TX_ACK:
		if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK))
		if (!(tsflags & SOF_TIMESTAMPING_TX_ACK))
			return;
		break;
	case J1939_ERRQUEUE_TX_SCHED:
		if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED))
		if (!(tsflags & SOF_TIMESTAMPING_TX_SCHED))
			return;
		break;
	case J1939_ERRQUEUE_TX_ABORT:
@@ -997,7 +999,7 @@ static void __j1939_sk_errqueue(struct j1939_session *session, struct sock *sk,
	case J1939_ERRQUEUE_RX_DPO:
		fallthrough;
	case J1939_ERRQUEUE_RX_ABORT:
		if (!(sk->sk_tsflags & SOF_TIMESTAMPING_RX_SOFTWARE))
		if (!(tsflags & SOF_TIMESTAMPING_RX_SOFTWARE))
			return;
		break;
	default:
@@ -1054,7 +1056,7 @@ static void __j1939_sk_errqueue(struct j1939_session *session, struct sock *sk,
	}

	serr->opt_stats = true;
	if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)
	if (tsflags & SOF_TIMESTAMPING_OPT_ID)
		serr->ee.ee_data = session->tskey;

	netdev_dbg(session->priv->ndev, "%s: 0x%p tskey: %i, state: %s\n",
+6 −4
Original line number Diff line number Diff line
@@ -5207,7 +5207,7 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
	serr->ee.ee_info = tstype;
	serr->opt_stats = opt_stats;
	serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0;
	if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
	if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID) {
		serr->ee.ee_data = skb_shinfo(skb)->tskey;
		if (sk_is_tcp(sk))
			serr->ee.ee_data -= atomic_read(&sk->sk_tskey);
@@ -5263,21 +5263,23 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
{
	struct sk_buff *skb;
	bool tsonly, opt_stats = false;
	u32 tsflags;

	if (!sk)
		return;

	if (!hwtstamps && !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TX_SWHW) &&
	tsflags = READ_ONCE(sk->sk_tsflags);
	if (!hwtstamps && !(tsflags & SOF_TIMESTAMPING_OPT_TX_SWHW) &&
	    skb_shinfo(orig_skb)->tx_flags & SKBTX_IN_PROGRESS)
		return;

	tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
	tsonly = tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
	if (!skb_may_tx_timestamp(sk, tsonly))
		return;

	if (tsonly) {
#ifdef CONFIG_INET
		if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
		if ((tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
		    sk_is_tcp(sk)) {
			skb = tcp_get_timestamping_opt_stats(sk, orig_skb,
							     ack_skb);
+9 −9
Original line number Diff line number Diff line
@@ -894,7 +894,7 @@ static int sock_timestamping_bind_phc(struct sock *sk, int phc_index)
	if (!match)
		return -EINVAL;

	sk->sk_bind_phc = phc_index;
	WRITE_ONCE(sk->sk_bind_phc, phc_index);

	return 0;
}
@@ -937,7 +937,7 @@ int sock_set_timestamping(struct sock *sk, int optname,
			return ret;
	}

	sk->sk_tsflags = val;
	WRITE_ONCE(sk->sk_tsflags, val);
	sock_valbool_flag(sk, SOCK_TSTAMP_NEW, optname == SO_TIMESTAMPING_NEW);

	if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
@@ -1045,7 +1045,7 @@ static int sock_reserve_memory(struct sock *sk, int bytes)
		mem_cgroup_uncharge_skmem(sk->sk_memcg, pages);
		return -ENOMEM;
	}
	sk->sk_forward_alloc += pages << PAGE_SHIFT;
	sk_forward_alloc_add(sk, pages << PAGE_SHIFT);

	WRITE_ONCE(sk->sk_reserved_mem,
		   sk->sk_reserved_mem + (pages << PAGE_SHIFT));
@@ -1719,8 +1719,8 @@ int sk_getsockopt(struct sock *sk, int level, int optname,

	case SO_TIMESTAMPING_OLD:
		lv = sizeof(v.timestamping);
		v.timestamping.flags = sk->sk_tsflags;
		v.timestamping.bind_phc = sk->sk_bind_phc;
		v.timestamping.flags = READ_ONCE(sk->sk_tsflags);
		v.timestamping.bind_phc = READ_ONCE(sk->sk_bind_phc);
		break;

	case SO_RCVTIMEO_OLD:
@@ -3139,10 +3139,10 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind)
{
	int ret, amt = sk_mem_pages(size);

	sk->sk_forward_alloc += amt << PAGE_SHIFT;
	sk_forward_alloc_add(sk, amt << PAGE_SHIFT);
	ret = __sk_mem_raise_allocated(sk, size, amt, kind);
	if (!ret)
		sk->sk_forward_alloc -= amt << PAGE_SHIFT;
		sk_forward_alloc_add(sk, -(amt << PAGE_SHIFT));
	return ret;
}
EXPORT_SYMBOL(__sk_mem_schedule);
@@ -3174,7 +3174,7 @@ void __sk_mem_reduce_allocated(struct sock *sk, int amount)
void __sk_mem_reclaim(struct sock *sk, int amount)
{
	amount >>= PAGE_SHIFT;
	sk->sk_forward_alloc -= amount << PAGE_SHIFT;
	sk_forward_alloc_add(sk, -(amount << PAGE_SHIFT));
	__sk_mem_reduce_allocated(sk, amount);
}
EXPORT_SYMBOL(__sk_mem_reclaim);
@@ -3743,7 +3743,7 @@ void sk_get_meminfo(const struct sock *sk, u32 *mem)
	mem[SK_MEMINFO_RCVBUF] = READ_ONCE(sk->sk_rcvbuf);
	mem[SK_MEMINFO_WMEM_ALLOC] = sk_wmem_alloc_get(sk);
	mem[SK_MEMINFO_SNDBUF] = READ_ONCE(sk->sk_sndbuf);
	mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc;
	mem[SK_MEMINFO_FWD_ALLOC] = sk_forward_alloc_get(sk);
	mem[SK_MEMINFO_WMEM_QUEUED] = READ_ONCE(sk->sk_wmem_queued);
	mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc);
	mem[SK_MEMINFO_BACKLOG] = READ_ONCE(sk->sk_backlog.len);
Loading