diff mbox

[net-next,1/3] net: core: Add a UID field to struct sock.

Message ID 1477588841-140767-2-git-send-email-lorenzo@google.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Lorenzo Colitti Oct. 27, 2016, 5:20 p.m. UTC
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 (e.g., a kernel
     ICMP socket): UID 0 inside the user namespace corresponding
     to the network namespace the socket belongs to. This is
     arguably better than GLOBAL_ROOT_UID because it allows
     "--owner-uid 0" to match kernel-originated packets in
     non-root namespaces.

Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
---
 include/net/sock.h |  7 +++++++
 net/core/sock.c    |  6 +++++-
 net/socket.c       | 14 ++++++++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)

Comments

Eric Dumazet Oct. 27, 2016, 5:36 p.m. UTC | #1
On Fri, 2016-10-28 at 02:20 +0900, Lorenzo Colitti wrote:

> diff --git a/net/core/sock.c b/net/core/sock.c
> index d8e4532e..831e4e8 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1570,6 +1570,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
>  		 */
>  		sk_refcnt_debug_inc(newsk);
>  		sk_set_socket(newsk, NULL);
> +		newsk->sk_uid = sk->sk_uid;

Not sure why this is needed ?

sk_clone_lock() already copies sk to newsk, using sock_copy(newsk, sk);

>  		newsk->sk_wq = NULL;
>  
>  		if (newsk->sk_prot->sockets_allocated)
> @@ -2460,8 +2461,11 @@ void sock_init_data(struct socket *sock, struct sock *sk)
kernel test robot Oct. 27, 2016, 7:05 p.m. UTC | #2
Hi Lorenzo,

[auto build test WARNING on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Lorenzo-Colitti/net-core-Add-a-UID-field-to-struct-sock/20161028-020552
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   include/linux/skbuff.h:947: warning: No description found for parameter 'sk'
   include/net/sock.h:450: warning: No description found for parameter 'sk_padding'
>> include/net/sock.h:450: warning: No description found for parameter 'sk_uid'
   include/net/sock.h:450: warning: No description found for parameter 'sk_rcu'
   include/linux/netdevice.h:1902: warning: No description found for parameter 'prio_tc_map[TC_BITMASK + 1]'

vim +/sk_uid +450 include/net/sock.h

ef64a54f6 Pavel Emelyanov 2012-02-21  434  	__s32			sk_peek_off;
^1da177e4 Linus Torvalds  2005-04-16  435  	int			sk_write_pending;
d5f642384 Alexey Dobriyan 2008-11-04  436  #ifdef CONFIG_SECURITY
^1da177e4 Linus Torvalds  2005-04-16  437  	void			*sk_security;
d5f642384 Alexey Dobriyan 2008-11-04  438  #endif
2a56a1fec Tejun Heo       2015-12-07  439  	struct sock_cgroup_data	sk_cgrp_data;
baac50bbc Johannes Weiner 2016-01-14  440  	struct mem_cgroup	*sk_memcg;
^1da177e4 Linus Torvalds  2005-04-16  441  	void			(*sk_state_change)(struct sock *sk);
676d23690 David S. Miller 2014-04-11  442  	void			(*sk_data_ready)(struct sock *sk);
^1da177e4 Linus Torvalds  2005-04-16  443  	void			(*sk_write_space)(struct sock *sk);
^1da177e4 Linus Torvalds  2005-04-16  444  	void			(*sk_error_report)(struct sock *sk);
^1da177e4 Linus Torvalds  2005-04-16  445  	int			(*sk_backlog_rcv)(struct sock *sk,
^1da177e4 Linus Torvalds  2005-04-16  446  						  struct sk_buff *skb);
^1da177e4 Linus Torvalds  2005-04-16  447  	void                    (*sk_destruct)(struct sock *sk);
ef456144d Craig Gallek    2016-01-04  448  	struct sock_reuseport __rcu	*sk_reuseport_cb;
a4298e452 Eric Dumazet    2016-04-01  449  	struct rcu_head		sk_rcu;
^1da177e4 Linus Torvalds  2005-04-16 @450  };
^1da177e4 Linus Torvalds  2005-04-16  451  
559835ea7 Pravin B Shelar 2013-09-24  452  #define __sk_user_data(sk) ((*((void __rcu **)&(sk)->sk_user_data)))
559835ea7 Pravin B Shelar 2013-09-24  453  
559835ea7 Pravin B Shelar 2013-09-24  454  #define rcu_dereference_sk_user_data(sk)	rcu_dereference(__sk_user_data((sk)))
559835ea7 Pravin B Shelar 2013-09-24  455  #define rcu_assign_sk_user_data(sk, ptr)	rcu_assign_pointer(__sk_user_data((sk)), ptr)
559835ea7 Pravin B Shelar 2013-09-24  456  
4a17fd522 Pavel Emelyanov 2012-04-19  457  /*
4a17fd522 Pavel Emelyanov 2012-04-19  458   * SK_CAN_REUSE and SK_NO_REUSE on a socket mean that the socket is OK

:::::: The code at line 450 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2

:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
David Miller Oct. 27, 2016, 8:02 p.m. UTC | #3
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 27 Oct 2016 10:36:26 -0700

> On Fri, 2016-10-28 at 02:20 +0900, Lorenzo Colitti wrote:
> 
>> diff --git a/net/core/sock.c b/net/core/sock.c
>> index d8e4532e..831e4e8 100644
>> --- a/net/core/sock.c
>> +++ b/net/core/sock.c
>> @@ -1570,6 +1570,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
>>  		 */
>>  		sk_refcnt_debug_inc(newsk);
>>  		sk_set_socket(newsk, NULL);
>> +		newsk->sk_uid = sk->sk_uid;
> 
> Not sure why this is needed ?
> 
> sk_clone_lock() already copies sk to newsk, using sock_copy(newsk, sk);

Agreed.
diff mbox

Patch

diff --git a/include/net/sock.h b/include/net/sock.h
index 2764895..2086922 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -417,6 +417,7 @@  struct sock {
 	u32			sk_max_ack_backlog;
 	__u32			sk_priority;
 	__u32			sk_mark;
+	kuid_t			sk_uid;
 	struct pid		*sk_peer_pid;
 	const struct cred	*sk_peer_cred;
 	long			sk_rcvtimeo;
@@ -1651,6 +1652,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);
 }
@@ -1658,6 +1660,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(struct net *net, const struct sock *sk)
+{
+	return sk ? sk->sk_uid : make_kuid(net->user_ns, 0);
+}
+
 static inline u32 net_tx_rndhash(void)
 {
 	u32 v = prandom_u32();
diff --git a/net/core/sock.c b/net/core/sock.c
index d8e4532e..831e4e8 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1570,6 +1570,7 @@  struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
 		 */
 		sk_refcnt_debug_inc(newsk);
 		sk_set_socket(newsk, NULL);
+		newsk->sk_uid = sk->sk_uid;
 		newsk->sk_wq = NULL;
 
 		if (newsk->sk_prot->sockets_allocated)
@@ -2460,8 +2461,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);
+	}
 
 	rwlock_init(&sk->sk_callback_lock);
 	lockdep_set_class_and_name(&sk->sk_callback_lock,
diff --git a/net/socket.c b/net/socket.c
index 5a9bf5e..5a4747e 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -518,8 +518,22 @@  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(d_inode(dentry));
+
+		sock->sk->sk_uid = iattr->ia_uid;
+	}
+
+	return err;
+}
+
 static const struct inode_operations sockfs_inode_ops = {
 	.listxattr = sockfs_listxattr,
+	.setattr = sockfs_setattr,
 };
 
 /**