net: core: add getsockopt SO_PEERPIDFD
Add SO_PEERPIDFD which allows to get pidfd of peer socket holder pidfd. This thing is direct analog of SO_PEERCRED which allows to get plain PID. Cc: "David S. Miller" <davem@davemloft.net> Cc: Eric Dumazet <edumazet@google.com> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Paolo Abeni <pabeni@redhat.com> Cc: Leon Romanovsky <leon@kernel.org> Cc: David Ahern <dsahern@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Kees Cook <keescook@chromium.org> Cc: Christian Brauner <brauner@kernel.org> Cc: Kuniyuki Iwashima <kuniyu@amazon.com> Cc: Lennart Poettering <mzxreary@0pointer.de> Cc: Luca Boccassi <bluca@debian.org> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: Stanislav Fomichev <sdf@google.com> Cc: bpf@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org Cc: linux-arch@vger.kernel.org Reviewed-by: Christian Brauner <brauner@kernel.org> Acked-by: Stanislav Fomichev <sdf@google.com> Tested-by: Luca Boccassi <bluca@debian.org> Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5e2ff6704a
commit
7b26952a91
|
@ -138,6 +138,7 @@
|
||||||
#define SO_RCVMARK 75
|
#define SO_RCVMARK 75
|
||||||
|
|
||||||
#define SO_PASSPIDFD 76
|
#define SO_PASSPIDFD 76
|
||||||
|
#define SO_PEERPIDFD 77
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,7 @@
|
||||||
#define SO_RCVMARK 75
|
#define SO_RCVMARK 75
|
||||||
|
|
||||||
#define SO_PASSPIDFD 76
|
#define SO_PASSPIDFD 76
|
||||||
|
#define SO_PEERPIDFD 77
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@
|
||||||
#define SO_RCVMARK 0x4049
|
#define SO_RCVMARK 0x4049
|
||||||
|
|
||||||
#define SO_PASSPIDFD 0x404A
|
#define SO_PASSPIDFD 0x404A
|
||||||
|
#define SO_PEERPIDFD 0x404B
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,7 @@
|
||||||
#define SO_RCVMARK 0x0054
|
#define SO_RCVMARK 0x0054
|
||||||
|
|
||||||
#define SO_PASSPIDFD 0x0055
|
#define SO_PASSPIDFD 0x0055
|
||||||
|
#define SO_PEERPIDFD 0x0056
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,7 @@
|
||||||
#define SO_RCVMARK 75
|
#define SO_RCVMARK 75
|
||||||
|
|
||||||
#define SO_PASSPIDFD 76
|
#define SO_PASSPIDFD 76
|
||||||
|
#define SO_PEERPIDFD 77
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
|
|
|
@ -1758,6 +1758,39 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
|
||||||
goto lenout;
|
goto lenout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SO_PEERPIDFD:
|
||||||
|
{
|
||||||
|
struct pid *peer_pid;
|
||||||
|
struct file *pidfd_file = NULL;
|
||||||
|
int pidfd;
|
||||||
|
|
||||||
|
if (len > sizeof(pidfd))
|
||||||
|
len = sizeof(pidfd);
|
||||||
|
|
||||||
|
spin_lock(&sk->sk_peer_lock);
|
||||||
|
peer_pid = get_pid(sk->sk_peer_pid);
|
||||||
|
spin_unlock(&sk->sk_peer_lock);
|
||||||
|
|
||||||
|
if (!peer_pid)
|
||||||
|
return -ESRCH;
|
||||||
|
|
||||||
|
pidfd = pidfd_prepare(peer_pid, 0, &pidfd_file);
|
||||||
|
put_pid(peer_pid);
|
||||||
|
if (pidfd < 0)
|
||||||
|
return pidfd;
|
||||||
|
|
||||||
|
if (copy_to_sockptr(optval, &pidfd, len) ||
|
||||||
|
copy_to_sockptr(optlen, &len, sizeof(int))) {
|
||||||
|
put_unused_fd(pidfd);
|
||||||
|
fput(pidfd_file);
|
||||||
|
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_install(pidfd, pidfd_file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
case SO_PEERGROUPS:
|
case SO_PEERGROUPS:
|
||||||
{
|
{
|
||||||
const struct cred *cred;
|
const struct cred *cred;
|
||||||
|
|
|
@ -921,11 +921,26 @@ static void unix_unhash(struct sock *sk)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool unix_bpf_bypass_getsockopt(int level, int optname)
|
||||||
|
{
|
||||||
|
if (level == SOL_SOCKET) {
|
||||||
|
switch (optname) {
|
||||||
|
case SO_PEERPIDFD:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct proto unix_dgram_proto = {
|
struct proto unix_dgram_proto = {
|
||||||
.name = "UNIX",
|
.name = "UNIX",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.obj_size = sizeof(struct unix_sock),
|
.obj_size = sizeof(struct unix_sock),
|
||||||
.close = unix_close,
|
.close = unix_close,
|
||||||
|
.bpf_bypass_getsockopt = unix_bpf_bypass_getsockopt,
|
||||||
#ifdef CONFIG_BPF_SYSCALL
|
#ifdef CONFIG_BPF_SYSCALL
|
||||||
.psock_update_sk_prot = unix_dgram_bpf_update_proto,
|
.psock_update_sk_prot = unix_dgram_bpf_update_proto,
|
||||||
#endif
|
#endif
|
||||||
|
@ -937,6 +952,7 @@ struct proto unix_stream_proto = {
|
||||||
.obj_size = sizeof(struct unix_sock),
|
.obj_size = sizeof(struct unix_sock),
|
||||||
.close = unix_close,
|
.close = unix_close,
|
||||||
.unhash = unix_unhash,
|
.unhash = unix_unhash,
|
||||||
|
.bpf_bypass_getsockopt = unix_bpf_bypass_getsockopt,
|
||||||
#ifdef CONFIG_BPF_SYSCALL
|
#ifdef CONFIG_BPF_SYSCALL
|
||||||
.psock_update_sk_prot = unix_stream_bpf_update_proto,
|
.psock_update_sk_prot = unix_stream_bpf_update_proto,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -122,6 +122,7 @@
|
||||||
#define SO_RCVMARK 75
|
#define SO_RCVMARK 75
|
||||||
|
|
||||||
#define SO_PASSPIDFD 76
|
#define SO_PASSPIDFD 76
|
||||||
|
#define SO_PEERPIDFD 77
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue