Skip to content

Commit 7d8d93f

Browse files
q2vendavem330
authored andcommitted
net: Restrict SO_PASS{CRED,PIDFD,SEC} to AF_{UNIX,NETLINK,BLUETOOTH}.
SCM_CREDENTIALS and SCM_SECURITY can be recv()ed by calling scm_recv() or scm_recv_unix(), and SCM_PIDFD is only used by scm_recv_unix(). scm_recv() is called from AF_NETLINK and AF_BLUETOOTH. scm_recv_unix() is literally called from AF_UNIX. Let's restrict SO_PASSCRED and SO_PASSSEC to such sockets and SO_PASSPIDFD to AF_UNIX only. Later, SOCK_PASS{CRED,PIDFD,SEC} will be moved to struct sock and united with another field. Signed-off-by: Kuniyuki Iwashima <[email protected]> Reviewed-by: Willem de Bruijn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ae4f2f5 commit 7d8d93f

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

include/net/sock.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2773,16 +2773,28 @@ static inline bool sk_is_udp(const struct sock *sk)
27732773
sk->sk_protocol == IPPROTO_UDP;
27742774
}
27752775

2776+
static inline bool sk_is_unix(const struct sock *sk)
2777+
{
2778+
return sk->sk_family == AF_UNIX;
2779+
}
2780+
27762781
static inline bool sk_is_stream_unix(const struct sock *sk)
27772782
{
2778-
return sk->sk_family == AF_UNIX && sk->sk_type == SOCK_STREAM;
2783+
return sk_is_unix(sk) && sk->sk_type == SOCK_STREAM;
27792784
}
27802785

27812786
static inline bool sk_is_vsock(const struct sock *sk)
27822787
{
27832788
return sk->sk_family == AF_VSOCK;
27842789
}
27852790

2791+
static inline bool sk_may_scm_recv(const struct sock *sk)
2792+
{
2793+
return (IS_ENABLED(CONFIG_UNIX) && sk->sk_family == AF_UNIX) ||
2794+
sk->sk_family == AF_NETLINK ||
2795+
(IS_ENABLED(CONFIG_BT) && sk->sk_family == AF_BLUETOOTH);
2796+
}
2797+
27862798
/**
27872799
* sk_eat_skb - Release a skb if it is no longer needed
27882800
* @sk: socket to eat this skb from

net/core/sock.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,12 +1221,21 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
12211221
}
12221222
return -EPERM;
12231223
case SO_PASSSEC:
1224+
if (!IS_ENABLED(CONFIG_SECURITY_NETWORK) || sk_may_scm_recv(sk))
1225+
return -EOPNOTSUPP;
1226+
12241227
assign_bit(SOCK_PASSSEC, &sock->flags, valbool);
12251228
return 0;
12261229
case SO_PASSCRED:
1230+
if (!sk_may_scm_recv(sk))
1231+
return -EOPNOTSUPP;
1232+
12271233
assign_bit(SOCK_PASSCRED, &sock->flags, valbool);
12281234
return 0;
12291235
case SO_PASSPIDFD:
1236+
if (!sk_is_unix(sk))
1237+
return -EOPNOTSUPP;
1238+
12301239
assign_bit(SOCK_PASSPIDFD, &sock->flags, valbool);
12311240
return 0;
12321241
case SO_TYPE:
@@ -1855,10 +1864,16 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
18551864
break;
18561865

18571866
case SO_PASSCRED:
1867+
if (!sk_may_scm_recv(sk))
1868+
return -EOPNOTSUPP;
1869+
18581870
v.val = !!test_bit(SOCK_PASSCRED, &sock->flags);
18591871
break;
18601872

18611873
case SO_PASSPIDFD:
1874+
if (!sk_is_unix(sk))
1875+
return -EOPNOTSUPP;
1876+
18621877
v.val = !!test_bit(SOCK_PASSPIDFD, &sock->flags);
18631878
break;
18641879

@@ -1956,6 +1971,9 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
19561971
break;
19571972

19581973
case SO_PASSSEC:
1974+
if (!IS_ENABLED(CONFIG_SECURITY_NETWORK) || !sk_may_scm_recv(sk))
1975+
return -EOPNOTSUPP;
1976+
19591977
v.val = !!test_bit(SOCK_PASSSEC, &sock->flags);
19601978
break;
19611979

0 commit comments

Comments
 (0)