mirror of
https://github.com/torvalds/linux.git
synced 2025-08-15 14:11:42 +02:00
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: 86741ec254
("net: core: Add a UID field to struct sock.")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Lorenzo Colitti <lorenzo@google.com>
Reviewed-by: Maciej Żenczykowski <maze@google.com>
Link: https://patch.msgid.link/20250620133001.4090592-2-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
b630c781bc
commit
e84a4927a4
20 changed files with 42 additions and 28 deletions
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -556,7 +556,8 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
|
|||
inet_test_bit(HDRINCL, sk) ?
|
||||
IPPROTO_RAW : sk->sk_protocol,
|
||||
inet_sk_flowi_flags(sk),
|
||||
daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
|
||||
daddr, inet->inet_saddr, 0, 0,
|
||||
sk_uid(sk));
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -454,7 +454,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
|
|||
ip_sock_rt_tos(sk), ip_sock_rt_scope(sk),
|
||||
IPPROTO_TCP, inet_sk_flowi_flags(sk),
|
||||
opt->srr ? opt->faddr : ireq->ir_rmt_addr,
|
||||
ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid);
|
||||
ireq->ir_loc_addr, th->source, th->dest,
|
||||
sk_uid(sk));
|
||||
security_req_classify_flow(req, flowi4_to_flowi_common(&fl4));
|
||||
rt = ip_route_output_key(net, &fl4);
|
||||
if (IS_ERR(rt)) {
|
||||
|
|
|
@ -1445,7 +1445,8 @@ int udp_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, flow_flags, faddr, saddr,
|
||||
dport, inet->inet_sport, sk->sk_uid);
|
||||
dport, inet->inet_sport,
|
||||
sk_uid(sk));
|
||||
|
||||
security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
|
||||
rt = ip_route_output_flow(net, fl4, sk);
|
||||
|
|
|
@ -842,7 +842,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
|
|||
fl6.flowi6_mark = sk->sk_mark;
|
||||
fl6.fl6_dport = inet->inet_dport;
|
||||
fl6.fl6_sport = inet->inet_sport;
|
||||
fl6.flowi6_uid = sk->sk_uid;
|
||||
fl6.flowi6_uid = sk_uid(sk);
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
|
||||
|
||||
rcu_read_lock();
|
||||
|
|
|
@ -53,7 +53,7 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6,
|
|||
fl6->fl6_dport = inet->inet_dport;
|
||||
fl6->fl6_sport = inet->inet_sport;
|
||||
fl6->flowlabel = ip6_make_flowinfo(np->tclass, np->flow_label);
|
||||
fl6->flowi6_uid = sk->sk_uid;
|
||||
fl6->flowi6_uid = sk_uid(sk);
|
||||
|
||||
if (!oif)
|
||||
oif = np->sticky_pktinfo.ipi6_ifindex;
|
||||
|
|
|
@ -45,7 +45,7 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,
|
|||
fl6->flowi6_mark = ireq->ir_mark;
|
||||
fl6->fl6_dport = ireq->ir_rmt_port;
|
||||
fl6->fl6_sport = htons(ireq->ir_num);
|
||||
fl6->flowi6_uid = sk->sk_uid;
|
||||
fl6->flowi6_uid = sk_uid(sk);
|
||||
security_req_classify_flow(req, flowi6_to_flowi_common(fl6));
|
||||
|
||||
dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
|
||||
|
@ -79,7 +79,7 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
|
|||
fl6->flowi6_mark = sk->sk_mark;
|
||||
fl6->fl6_sport = inet->inet_sport;
|
||||
fl6->fl6_dport = inet->inet_dport;
|
||||
fl6->flowi6_uid = sk->sk_uid;
|
||||
fl6->flowi6_uid = sk_uid(sk);
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6));
|
||||
|
||||
rcu_read_lock();
|
||||
|
|
|
@ -142,7 +142,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
fl6.saddr = np->saddr;
|
||||
fl6.daddr = *daddr;
|
||||
fl6.flowi6_mark = ipc6.sockc.mark;
|
||||
fl6.flowi6_uid = sk->sk_uid;
|
||||
fl6.flowi6_uid = sk_uid(sk);
|
||||
fl6.fl6_icmp_type = user_icmph.icmp6_type;
|
||||
fl6.fl6_icmp_code = user_icmph.icmp6_code;
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
|
||||
|
|
|
@ -777,7 +777,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
memset(&fl6, 0, sizeof(fl6));
|
||||
|
||||
fl6.flowi6_mark = ipc6.sockc.mark;
|
||||
fl6.flowi6_uid = sk->sk_uid;
|
||||
fl6.flowi6_uid = sk_uid(sk);
|
||||
|
||||
if (sin6) {
|
||||
if (addr_len < SIN6_LEN_RFC2133)
|
||||
|
|
|
@ -3011,7 +3011,7 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
|
|||
oif = l3mdev_master_ifindex(skb->dev);
|
||||
|
||||
ip6_update_pmtu(skb, sock_net(sk), mtu, oif, READ_ONCE(sk->sk_mark),
|
||||
sk->sk_uid);
|
||||
sk_uid(sk));
|
||||
|
||||
dst = __sk_dst_get(sk);
|
||||
if (!dst || !dst->obsolete ||
|
||||
|
@ -3233,7 +3233,7 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif)
|
|||
void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
|
||||
{
|
||||
ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if,
|
||||
READ_ONCE(sk->sk_mark), sk->sk_uid);
|
||||
READ_ONCE(sk->sk_mark), sk_uid(sk));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip6_sk_redirect);
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
|
|||
fl6.flowi6_mark = ireq->ir_mark;
|
||||
fl6.fl6_dport = ireq->ir_rmt_port;
|
||||
fl6.fl6_sport = inet_sk(sk)->inet_sport;
|
||||
fl6.flowi6_uid = sk->sk_uid;
|
||||
fl6.flowi6_uid = sk_uid(sk);
|
||||
security_req_classify_flow(req, flowi6_to_flowi_common(&fl6));
|
||||
|
||||
dst = ip6_dst_lookup_flow(net, sk, &fl6, final_p);
|
||||
|
|
|
@ -269,7 +269,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
|||
fl6.fl6_sport = inet->inet_sport;
|
||||
if (IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) && !fl6.fl6_sport)
|
||||
fl6.flowi6_flags = FLOWI_FLAG_ANY_SPORT;
|
||||
fl6.flowi6_uid = sk->sk_uid;
|
||||
fl6.flowi6_uid = sk_uid(sk);
|
||||
|
||||
opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
|
||||
final_p = fl6_update_dst(&fl6, opt, &final);
|
||||
|
|
|
@ -750,7 +750,8 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
if (type == NDISC_REDIRECT) {
|
||||
if (tunnel) {
|
||||
ip6_redirect(skb, sock_net(sk), inet6_iif(skb),
|
||||
READ_ONCE(sk->sk_mark), sk->sk_uid);
|
||||
READ_ONCE(sk->sk_mark),
|
||||
sk_uid(sk));
|
||||
} else {
|
||||
ip6_sk_redirect(skb, sk);
|
||||
}
|
||||
|
@ -1620,7 +1621,7 @@ do_udp_sendmsg:
|
|||
if (!fl6->flowi6_oif)
|
||||
fl6->flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
|
||||
|
||||
fl6->flowi6_uid = sk->sk_uid;
|
||||
fl6->flowi6_uid = sk_uid(sk);
|
||||
|
||||
if (msg->msg_controllen) {
|
||||
opt = &opt_space;
|
||||
|
|
|
@ -545,7 +545,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
memset(&fl6, 0, sizeof(fl6));
|
||||
|
||||
fl6.flowi6_mark = READ_ONCE(sk->sk_mark);
|
||||
fl6.flowi6_uid = sk->sk_uid;
|
||||
fl6.flowi6_uid = sk_uid(sk);
|
||||
|
||||
ipcm6_init_sk(&ipc6, sk);
|
||||
|
||||
|
|
|
@ -3503,7 +3503,7 @@ void mptcp_sock_graft(struct sock *sk, struct socket *parent)
|
|||
write_lock_bh(&sk->sk_callback_lock);
|
||||
rcu_assign_pointer(sk->sk_wq, &parent->wq);
|
||||
sk_set_socket(sk, parent);
|
||||
sk->sk_uid = SOCK_INODE(parent)->i_uid;
|
||||
WRITE_ONCE(sk->sk_uid, SOCK_INODE(parent)->i_uid);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -592,11 +592,13 @@ static int sockfs_setattr(struct mnt_idmap *idmap,
|
|||
if (!err && (iattr->ia_valid & ATTR_UID)) {
|
||||
struct socket *sock = SOCKET_I(d_inode(dentry));
|
||||
|
||||
if (sock->sk)
|
||||
sock->sk->sk_uid = iattr->ia_uid;
|
||||
else
|
||||
if (sock->sk) {
|
||||
/* Paired with READ_ONCE() in sk_uid() */
|
||||
WRITE_ONCE(sock->sk->sk_uid, iattr->ia_uid);
|
||||
} else {
|
||||
err = -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue