unix_setsockopt() and the SOCK_CUSTOM_SOCKOPT flag were only wired up for SOCK_STREAM (introduced along with the stream-only SO_INQ). Consequently custom AF_UNIX options are unreachable on SOCK_DGRAM and SOCK_SEQPACKET: those setsockopt() calls bypass unix_setsockopt() and fall through to the generic sock_setsockopt(), failing with -ENOPROTOOPT. Set SOCK_CUSTOM_SOCKOPT for every AF_UNIX socket type in unix_create(), and also for accepted sockets in unix_accept() (reachable for stream and seqpacket). This is a prerequisite for making SO_RIGHTS_NOTRUNC settable on all AF_UNIX socket types. Signed-off-by: Jori Koolstra --- net/unix/af_unix.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 10ed9421e43a..51cbf920130d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -950,7 +950,7 @@ static int unix_setsockopt(struct socket *sock, int level, int optname, switch (optname) { case SO_INQ: if (sk->sk_type != SOCK_STREAM) - return -EINVAL; + return -ENOPROTOOPT; if (val > 1 || val < 0) return -EINVAL; @@ -1006,6 +1006,7 @@ static const struct proto_ops unix_dgram_ops = { #endif .listen = sock_no_listen, .shutdown = unix_shutdown, + .setsockopt = unix_setsockopt, .sendmsg = unix_dgram_sendmsg, .read_skb = unix_read_skb, .recvmsg = unix_dgram_recvmsg, @@ -1030,6 +1031,7 @@ static const struct proto_ops unix_seqpacket_ops = { #endif .listen = unix_listen, .shutdown = unix_shutdown, + .setsockopt = unix_setsockopt, .sendmsg = unix_seqpacket_sendmsg, .recvmsg = unix_seqpacket_recvmsg, .mmap = sock_no_mmap, @@ -1143,9 +1145,10 @@ static int unix_create(struct net *net, struct socket *sock, int protocol, if (protocol && protocol != PF_UNIX) return -EPROTONOSUPPORT; + set_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags); + switch (sock->type) { case SOCK_STREAM: - set_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags); sock->ops = &unix_stream_ops; break; /* @@ -1865,8 +1868,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, skb_free_datagram(sk, skb); wake_up_interruptible(&unix_sk(sk)->peer_wait); - if (tsk->sk_type == SOCK_STREAM) - set_bit(SOCK_CUSTOM_SOCKOPT, &newsock->flags); + set_bit(SOCK_CUSTOM_SOCKOPT, &newsock->flags); /* attach accepted sock to socket */ unix_state_lock(tsk); -- 2.55.0