Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: core: Add a UID field to struct sock.

Protocol sockets (struct sock) don't have UIDs, but most of the
time, they map 1:1 to userspace sockets (struct socket) which do.

Various operations such as the iptables xt_owner match need
access to the "UID of a socket", and do so by following the
backpointer to the struct socket. This involves taking
sk_callback_lock and doesn't work when there is no socket
because userspace has already called close().

Simplify this by adding a sk_uid field to struct sock whose value
matches the UID of the corresponding struct socket. The semantics
are as follows:

1. Whenever sk_socket is non-null: sk_uid is the same as the UID
in sk_socket, i.e., matches the return value of sock_i_uid.
Specifically, the UID is set when userspace calls socket(),
fchown(), or accept().
2. When sk_socket is NULL, sk_uid is defined as follows:
- For a socket that no longer has a sk_socket because
userspace has called close(): the previous UID.
- For a cloned socket (e.g., an incoming connection that is
established but on which userspace has not yet called
accept): the UID of the socket it was cloned from.
- For a socket that has never had an sk_socket: UID 0 inside
the user namespace corresponding to the network namespace
the socket belongs to.

Kernel sockets created by sock_create_kern are a special case
of #1 and sk_uid is the user that created them. For kernel
sockets created at network namespace creation time, such as the
per-processor ICMP and TCP sockets, this is the user that created
the network namespace.

Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Lorenzo Colitti and committed by
David S. Miller
86741ec2 0d53072a

+25 -1
+7
include/net/sock.h
··· 419 419 u32 sk_max_ack_backlog; 420 420 __u32 sk_priority; 421 421 __u32 sk_mark; 422 + kuid_t sk_uid; 422 423 struct pid *sk_peer_pid; 423 424 const struct cred *sk_peer_cred; 424 425 long sk_rcvtimeo; ··· 1665 1664 sk->sk_wq = parent->wq; 1666 1665 parent->sk = sk; 1667 1666 sk_set_socket(sk, parent); 1667 + sk->sk_uid = SOCK_INODE(parent)->i_uid; 1668 1668 security_sock_graft(sk, parent); 1669 1669 write_unlock_bh(&sk->sk_callback_lock); 1670 1670 } 1671 1671 1672 1672 kuid_t sock_i_uid(struct sock *sk); 1673 1673 unsigned long sock_i_ino(struct sock *sk); 1674 + 1675 + static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk) 1676 + { 1677 + return sk ? sk->sk_uid : make_kuid(net->user_ns, 0); 1678 + } 1674 1679 1675 1680 static inline u32 net_tx_rndhash(void) 1676 1681 {
+4 -1
net/core/sock.c
··· 2460 2460 sk->sk_type = sock->type; 2461 2461 sk->sk_wq = sock->wq; 2462 2462 sock->sk = sk; 2463 - } else 2463 + sk->sk_uid = SOCK_INODE(sock)->i_uid; 2464 + } else { 2464 2465 sk->sk_wq = NULL; 2466 + sk->sk_uid = make_kuid(sock_net(sk)->user_ns, 0); 2467 + } 2465 2468 2466 2469 rwlock_init(&sk->sk_callback_lock); 2467 2470 lockdep_set_class_and_name(&sk->sk_callback_lock,
+14
net/socket.c
··· 518 518 return used; 519 519 } 520 520 521 + int sockfs_setattr(struct dentry *dentry, struct iattr *iattr) 522 + { 523 + int err = simple_setattr(dentry, iattr); 524 + 525 + if (!err) { 526 + struct socket *sock = SOCKET_I(d_inode(dentry)); 527 + 528 + sock->sk->sk_uid = iattr->ia_uid; 529 + } 530 + 531 + return err; 532 + } 533 + 521 534 static const struct inode_operations sockfs_inode_ops = { 522 535 .listxattr = sockfs_listxattr, 536 + .setattr = sockfs_setattr, 523 537 }; 524 538 525 539 /**