Commit e84a4927 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

net: annotate races around sk->sk_uid



sk->sk_uid can be read while another thread changes its
value in sockfs_setattr().

Add sk_uid(const struct sock *sk) helper to factorize the needed
READ_ONCE() annotations, and add corresponding WRITE_ONCE()
where needed.

Fixes: 86741ec2 ("net: core: Add a UID field to struct sock.")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Lorenzo Colitti <lorenzo@google.com>
Reviewed-by: default avatarMaciej Żenczykowski <maze@google.com>
Link: https://patch.msgid.link/20250620133001.4090592-2-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b630c781
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -153,7 +153,7 @@ static inline void inet_sk_init_flowi4(const struct inet_sock *inet,
			   ip_sock_rt_tos(sk), ip_sock_rt_scope(sk),
			   sk->sk_protocol, inet_sk_flowi_flags(sk), daddr,
			   inet->inet_saddr, inet->inet_dport,
			   inet->inet_sport, sk->sk_uid);
			   inet->inet_sport, sk_uid(sk));
	security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
}

@@ -331,7 +331,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst,

	flowi4_init_output(fl4, oif, READ_ONCE(sk->sk_mark), ip_sock_rt_tos(sk),
			   ip_sock_rt_scope(sk), protocol, flow_flags, dst,
			   src, dport, sport, sk->sk_uid);
			   src, dport, sport, sk_uid(sk));
}

static inline struct rtable *ip_route_connect(struct flowi4 *fl4, __be32 dst,
+10 −2
Original line number Diff line number Diff line
@@ -2076,6 +2076,7 @@ static inline void sock_orphan(struct sock *sk)
	sock_set_flag(sk, SOCK_DEAD);
	sk_set_socket(sk, NULL);
	sk->sk_wq  = NULL;
	/* Note: sk_uid is unchanged. */
	write_unlock_bh(&sk->sk_callback_lock);
}

@@ -2086,18 +2087,25 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
	rcu_assign_pointer(sk->sk_wq, &parent->wq);
	parent->sk = sk;
	sk_set_socket(sk, parent);
	sk->sk_uid = SOCK_INODE(parent)->i_uid;
	WRITE_ONCE(sk->sk_uid, SOCK_INODE(parent)->i_uid);
	security_sock_graft(sk, parent);
	write_unlock_bh(&sk->sk_callback_lock);
}

kuid_t sock_i_uid(struct sock *sk);

static inline kuid_t sk_uid(const struct sock *sk)
{
	/* Paired with WRITE_ONCE() in sockfs_setattr() */
	return READ_ONCE(sk->sk_uid);
}

unsigned long __sock_i_ino(struct sock *sk);
unsigned long sock_i_ino(struct sock *sk);

static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
{
	return sk ? sk->sk_uid : make_kuid(net->user_ns, 0);
	return sk ? sk_uid(sk) : make_kuid(net->user_ns, 0);
}

static inline u32 net_tx_rndhash(void)
+2 −2
Original line number Diff line number Diff line
@@ -812,7 +812,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
			   sk->sk_protocol, inet_sk_flowi_flags(sk),
			   (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
			   ireq->ir_loc_addr, ireq->ir_rmt_port,
			   htons(ireq->ir_num), sk->sk_uid);
			   htons(ireq->ir_num), sk_uid(sk));
	security_req_classify_flow(req, flowi4_to_flowi_common(fl4));
	rt = ip_route_output_flow(net, fl4, sk);
	if (IS_ERR(rt))
@@ -849,7 +849,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
			   sk->sk_protocol, inet_sk_flowi_flags(sk),
			   (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
			   ireq->ir_loc_addr, ireq->ir_rmt_port,
			   htons(ireq->ir_num), sk->sk_uid);
			   htons(ireq->ir_num), sk_uid(sk));
	security_req_classify_flow(req, flowi4_to_flowi_common(fl4));
	rt = ip_route_output_flow(net, fl4, sk);
	if (IS_ERR(rt))
+1 −1
Original line number Diff line number Diff line
@@ -781,7 +781,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
	flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark,
			   ipc.tos & INET_DSCP_MASK, scope,
			   sk->sk_protocol, inet_sk_flowi_flags(sk), faddr,
			   saddr, 0, 0, sk->sk_uid);
			   saddr, 0, 0, sk_uid(sk));

	fl4.fl4_icmp_type = user_icmph.type;
	fl4.fl4_icmp_code = user_icmph.code;
+1 −1
Original line number Diff line number Diff line
@@ -610,7 +610,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
			   hdrincl ? ipc.protocol : sk->sk_protocol,
			   inet_sk_flowi_flags(sk) |
			    (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
			   daddr, saddr, 0, 0, sk->sk_uid);
			   daddr, saddr, 0, 0, sk_uid(sk));

	fl4.fl4_icmp_type = 0;
	fl4.fl4_icmp_code = 0;
Loading