All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] tuntap: correctly initialize socket uid
@ 2023-02-01  0:35 Pietro Borrello
  2023-02-01  0:35 ` [PATCH net-next 1/2] tun: tun_chr_open(): " Pietro Borrello
  2023-02-01  0:35 ` [PATCH net-next 2/2] tap: tap_open(): " Pietro Borrello
  0 siblings, 2 replies; 5+ messages in thread
From: Pietro Borrello @ 2023-02-01  0:35 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Lorenzo Colitti
  Cc: Cristiano Giuffrida, Bos, H.J.,
	Jakob Koschel, netdev, linux-kernel, Pietro Borrello

sock_init_data() assumes that the `struct socket` passed in input is
contained in a `struct socket_alloc` allocated with sock_alloc().
However, tap_open() and tun_chr_open() pass a `struct socket` embedded
in a `struct tap_queue` and `struct tun_file` respectively, both
allocated with sk_alloc().
This causes a type confusion when issuing a container_of() with
SOCK_INODE() in sock_init_data() which results in assigning a wrong
sk_uid to the `struct sock` in input.

Due to the type confusion, both sockets happen to have their uid set
to 0, i.e. root.
While it will be often correct, as tuntap devices require
CAP_NET_ADMIN, it may not always be the case.
Not sure how widespread is the impact of this, it seems the socket uid
may be used for network filtering and routing, thus tuntap sockets may
be incorrectly managed.
Additionally, it seems a socket with an incorrect uid may be returned
to the vhost driver when issuing a get_socket() on a tuntap device in
vhost_net_set_backend().

The proposed fix may not be the cleanest one, as it simply overrides
the incorrect uid after the type confusion in sock_init_data()
happens.
While minimal, this may not be solid in case more logic relying on
SOCK_INODE() is added to sock_init_data().
The alternative fix would be to pass a NULL sock, and manually perform
the assignments after the sock_init_data() call:
```
sk_set_socket(sk, sock);
// and
sk->sk_type	=	sock->type;
RCU_INIT_POINTER(sk->sk_wq, &sock->wq);
sock->sk	=	sk;
sk->sk_uid	=	SOCK_INODE(sock)->i_uid;
```

To: "David S. Miller" <davem@davemloft.net>
To: Eric Dumazet <edumazet@google.com>
To: Jakub Kicinski <kuba@kernel.org>
To: Paolo Abeni <pabeni@redhat.com>
To: Lorenzo Colitti <lorenzo@google.com>
Cc: Cristiano Giuffrida <c.giuffrida@vu.nl>
Cc: "Bos, H.J." <h.j.bos@vu.nl>
Cc: Jakob Koschel <jkl820.git@gmail.com>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Pietro Borrello <borrello@diag.uniroma1.it>

---
Pietro Borrello (2):
      tun: tun_chr_open(): correctly initialize socket uid
      tap: tap_open(): correctly initialize socket uid

 drivers/net/tap.c | 4 ++++
 drivers/net/tun.c | 5 +++++
 2 files changed, 9 insertions(+)
---
base-commit: 6d796c50f84ca79f1722bb131799e5a5710c4700
change-id: 20230131-tuntap-sk-uid-78efc80f4b82

Best regards,
-- 
Pietro Borrello <borrello@diag.uniroma1.it>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH net-next 1/2] tun: tun_chr_open(): correctly initialize socket uid
  2023-02-01  0:35 [PATCH net-next 0/2] tuntap: correctly initialize socket uid Pietro Borrello
@ 2023-02-01  0:35 ` Pietro Borrello
  2023-02-01  3:10   ` Stephen Hemminger
  2023-02-01  0:35 ` [PATCH net-next 2/2] tap: tap_open(): " Pietro Borrello
  1 sibling, 1 reply; 5+ messages in thread
From: Pietro Borrello @ 2023-02-01  0:35 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Lorenzo Colitti
  Cc: Cristiano Giuffrida, Bos, H.J.,
	Jakob Koschel, netdev, linux-kernel, Pietro Borrello

sock_init_data() assumes that the `struct socket` passed in input is
contained in a `struct socket_alloc` allocated with sock_alloc().
However, tun_chr_open() passes a `struct socket` embedded in a `struct
tun_file` allocated with sk_alloc().
This causes a type confusion when issuing a container_of() with
SOCK_INODE() in sock_init_data() which results in assigning a wrong
sk_uid to the `struct sock` in input.
On default configuration, the type confused field overlaps with the
high 4 bytes of `struct tun_struct __rcu *tun` of `struct tun_file`,
NULL at the time of call, which makes the uid of all tun sockets 0,
i.e., the root one.  Fix the assignment by overriding it with the
correct uid.

Fixes: 86741ec25462 ("net: core: Add a UID field to struct sock.")
Signed-off-by: Pietro Borrello <borrello@diag.uniroma1.it>
---
 drivers/net/tun.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a7d17c680f4a..6713fffb1488 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -3450,6 +3450,11 @@ static int tun_chr_open(struct inode *inode, struct file * file)
 
 	sock_init_data(&tfile->socket, &tfile->sk);
 
+	// sock_init_data initializes sk.sk_uid assuming tfile->socket is embedded
+	// in a struct socket_alloc and reading its corresponding inode. Since we
+	// pass a socket contained in a struct tun_file we have to fix this manually
+	tfile->sk.sk_uid = inode->i_uid;
+
 	tfile->sk.sk_write_space = tun_sock_write_space;
 	tfile->sk.sk_sndbuf = INT_MAX;
 

-- 
2.25.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next 2/2] tap: tap_open(): correctly initialize socket uid
  2023-02-01  0:35 [PATCH net-next 0/2] tuntap: correctly initialize socket uid Pietro Borrello
  2023-02-01  0:35 ` [PATCH net-next 1/2] tun: tun_chr_open(): " Pietro Borrello
@ 2023-02-01  0:35 ` Pietro Borrello
  1 sibling, 0 replies; 5+ messages in thread
From: Pietro Borrello @ 2023-02-01  0:35 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Lorenzo Colitti
  Cc: Cristiano Giuffrida, Bos, H.J.,
	Jakob Koschel, netdev, linux-kernel, Pietro Borrello

sock_init_data() assumes that the `struct socket` passed in input is
contained in a `struct socket_alloc` allocated with sock_alloc().
However, tap_open() passes a `struct socket` embedded in a `struct
tap_queue` allocated with sk_alloc().
This causes a type confusion when issuing a container_of() with
SOCK_INODE() in sock_init_data() which results in assigning a wrong
sk_uid to the `struct sock` in input.
On default configuration, the type confused field overlaps with
padding bytes between `int vnet_hdr_sz` and `struct tap_dev __rcu
*tap` in `struct tap_queue`, which makes the uid of all tap sockets 0,
i.e., the root one.  Fix the assignment by overriding it with the
correct uid.

Fixes: 86741ec25462 ("net: core: Add a UID field to struct sock.")
Signed-off-by: Pietro Borrello <borrello@diag.uniroma1.it>
---
 drivers/net/tap.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index a2be1994b389..9a287363d695 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -538,6 +538,10 @@ static int tap_open(struct inode *inode, struct file *file)
 	q->sk.sk_destruct = tap_sock_destruct;
 	q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
 	q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
+	// sock_init_data initializes sk.sk_uid assuming q->sock is embedded in a
+	// struct socket_alloc and reading its corresponding inode. Since we pass a
+	// socket contained in a struct tap_queue we have to fix this manually
+	q->sk.sk_uid = inode->i_uid;
 
 	/*
 	 * so far only KVM virtio_net uses tap, enable zero copy between

-- 
2.25.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next 1/2] tun: tun_chr_open(): correctly initialize socket uid
  2023-02-01  0:35 ` [PATCH net-next 1/2] tun: tun_chr_open(): " Pietro Borrello
@ 2023-02-01  3:10   ` Stephen Hemminger
  2023-02-01 11:01     ` Pietro Borrello
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Hemminger @ 2023-02-01  3:10 UTC (permalink / raw)
  To: Pietro Borrello
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Lorenzo Colitti, Cristiano Giuffrida, Bos, H.J.,
	Jakob Koschel, netdev, linux-kernel

On Wed, 01 Feb 2023 00:35:45 +0000
Pietro Borrello <borrello@diag.uniroma1.it> wrote:

> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index a7d17c680f4a..6713fffb1488 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -3450,6 +3450,11 @@ static int tun_chr_open(struct inode *inode, struct file * file)
>  
>  	sock_init_data(&tfile->socket, &tfile->sk);
>  
> +	// sock_init_data initializes sk.sk_uid assuming tfile->socket is embedded
> +	// in a struct socket_alloc and reading its corresponding inode. Since we
> +	// pass a socket contained in a struct tun_file we have to fix this manually
> +	tfile->sk.sk_uid = inode->i_uid;
> +

Do not use C++ style comments in the kernel.

Rule #1 of code maintenance. Bug fixes should not stand out.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next 1/2] tun: tun_chr_open(): correctly initialize socket uid
  2023-02-01  3:10   ` Stephen Hemminger
@ 2023-02-01 11:01     ` Pietro Borrello
  0 siblings, 0 replies; 5+ messages in thread
From: Pietro Borrello @ 2023-02-01 11:01 UTC (permalink / raw)
  To: stephen
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Lorenzo Colitti, Cristiano Giuffrida, Bos, H.J.,
	Jakob Koschel, netdev, linux-kernel

On Wed, 1 Feb 2023 at 04:10, Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> On Wed, 01 Feb 2023 00:35:45 +0000
> Pietro Borrello <borrello@diag.uniroma1.it> wrote:
>
> > diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> > index a7d17c680f4a..6713fffb1488 100644
> > --- a/drivers/net/tun.c
> > +++ b/drivers/net/tun.c
> > @@ -3450,6 +3450,11 @@ static int tun_chr_open(struct inode *inode, struct file * file)
> >
> >       sock_init_data(&tfile->socket, &tfile->sk);
> >
> > +     // sock_init_data initializes sk.sk_uid assuming tfile->socket is embedded
> > +     // in a struct socket_alloc and reading its corresponding inode. Since we
> > +     // pass a socket contained in a struct tun_file we have to fix this manually
> > +     tfile->sk.sk_uid = inode->i_uid;
> > +
>
> Do not use C++ style comments in the kernel.

Thanks for pointing it out. I will fix this in v2.

> Rule #1 of code maintenance. Bug fixes should not stand out.

Thanks for the comment. I agree bug fixes should not stand out.
I sent the patches also to sparkle some discussion on how this should be
better fixed.
As briefly mentioned in the cover letter, I am not sure what is the
cleanest fix according
to Linux standards.
Are you suggesting a briefer comment or removing it completely?

The alternative fixes I see, would be:
1) pass a NULL socket and manually initialize it, which I think would
make the fix
to stand out more, but it would be probably cleaner
2) change the API of sock_init_data, but probably not worth it, given
tuntap devices
are the only 2 users among almost 60 to break the socket_alloc assumption
3) introduce a sock_init_data_with_inode which explicitly uses an
inode to initialize
uid, but would be a bad solution for code duplication
4) wrap sock_init_data call to fix uid in a similar fashion as done
here, maybe cleaner

Best regards,
Pietro

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-02-01 11:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-01  0:35 [PATCH net-next 0/2] tuntap: correctly initialize socket uid Pietro Borrello
2023-02-01  0:35 ` [PATCH net-next 1/2] tun: tun_chr_open(): " Pietro Borrello
2023-02-01  3:10   ` Stephen Hemminger
2023-02-01 11:01     ` Pietro Borrello
2023-02-01  0:35 ` [PATCH net-next 2/2] tap: tap_open(): " Pietro Borrello

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.