Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 356fb77c authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Amit Pundir
Browse files

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.

Bug: 16355602
Change-Id: Idbc3e9a0cec91c4c6e01916b967b6237645ebe59
Signed-off-by: default avatarLorenzo Colitti <lorenzo@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 782469bf
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -423,6 +423,7 @@ struct sock {
	void			*sk_security;
#endif
	__u32			sk_mark;
	kuid_t			sk_uid;
	u32			sk_classid;
	struct cg_proto		*sk_cgrp;
	void			(*sk_state_change)(struct sock *sk);
@@ -1737,6 +1738,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
	sk->sk_wq = parent->wq;
	parent->sk = sk;
	sk_set_socket(sk, parent);
	sk->sk_uid = SOCK_INODE(parent)->i_uid;
	security_sock_graft(sk, parent);
	write_unlock_bh(&sk->sk_callback_lock);
}
@@ -1744,6 +1746,11 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
kuid_t sock_i_uid(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);
}

static inline struct dst_entry *
__sk_dst_get(struct sock *sk)
{
+4 −1
Original line number Diff line number Diff line
@@ -2292,8 +2292,11 @@ void sock_init_data(struct socket *sock, struct sock *sk)
		sk->sk_type	=	sock->type;
		sk->sk_wq	=	sock->wq;
		sock->sk	=	sk;
	} else
		sk->sk_uid	=	SOCK_INODE(sock)->i_uid;
	} else {
		sk->sk_wq	=	NULL;
		sk->sk_uid	=	make_kuid(sock_net(sk)->user_ns, 0);
	}

	spin_lock_init(&sk->sk_dst_lock);
	rwlock_init(&sk->sk_callback_lock);
+14 −0
Original line number Diff line number Diff line
@@ -524,9 +524,23 @@ static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
	return used;
}

int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
{
	int err = simple_setattr(dentry, iattr);

	if (!err) {
		struct socket *sock = SOCKET_I(dentry->d_inode);

		sock->sk->sk_uid = iattr->ia_uid;
	}

	return err;
}

static const struct inode_operations sockfs_inode_ops = {
	.getxattr = sockfs_getxattr,
	.listxattr = sockfs_listxattr,
	.setattr = sockfs_setattr,
};

/**