From nobody Sat Jul 25 22:33:06 2026 Received: from ewsoutbound.kpnmail.nl (ewsoutbound.kpnmail.nl [195.121.94.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68EC3370D69 for ; Sun, 12 Jul 2026 19:29:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.121.94.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783884558; cv=none; b=nTi3Umt2rHWRD3ndCmvHJiw5HMBs3b9quSrMFLzAhbDzNzWBLP6zvjgrl84U5VSlPXoVqoJ0tiTNMvZGOzdU1LDVNpMEiBpouuUzn8qWAccb9pi8wQDyokucwNvxbjwv1wtsXKhTns/2nb0IIutZOVA+57kH7bz5SP8OMwvbs9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783884558; c=relaxed/simple; bh=/hwMuqFPbV2RXCxBKoN/ZEHNqijXQT8Lwh9RVoeAq9k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LVp7POrC81ycfbEKFDdO1vsccv7TNt67e1clZVqYl2xh+jFiUE8X0ZXBFDh9d6pknHy96FsGGuJPeUfVAURU1qmjqrO+QoF1oTg4yUhX163iu6R6oCIIyZmCLGm8gSGtfrAdMI2kmJsJOWc1jKQlIMVctcKfNAXglz1qxqQ3rlQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=xs4all.nl; spf=pass smtp.mailfrom=xs4all.nl; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b=odHs2vLg; arc=none smtp.client-ip=195.121.94.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=xs4all.nl Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=xs4all.nl Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b="odHs2vLg" X-KPN-MessageId: f6b53a40-7e27-11f1-a59f-005056994fde Received: from smtp.kpnmail.nl (unknown [10.31.155.8]) by ewsoutbound.so.kpn.org (Halon) with ESMTPS id f6b53a40-7e27-11f1-a59f-005056994fde; Sun, 12 Jul 2026 21:29:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xs4all.nl; s=xs4all01; h=mime-version:message-id:date:subject:to:from; bh=x7uJpPkF3ZQUrVWrgYFqwWsVpOjT67/X4ytnP1oLCCo=; b=odHs2vLgRLPOqLbKwyekwuvOqYahbKcL+JC65XHkWeAIM0Y0hgqya7YQAoRyV99weSkYZnjEYslyL ZFGankDxkO5LbgcmvUfaRJqecVAE788dMFPbkSZ5rooGV2McHnx7s7plh7UPShzQ+xz7pEa9wK6ZuD mouaZ4GZmpVq4yzUA38NjeYzF9pY+3Sr/GrQ9wVHN+zX8bXOzJpzADx3Yk6l/VEQyjo0fw5sKDR4tX PAN+OQ5Ytubh8eGsvWZgT0oWkNyXaFv6N1LkSPGcYH0Q6ad0SDr8mQE1jn6z3RoPF8FRSoFIX3/P0d +uypT3d65g29wao4T+WYvWMgznhiQgg== X-KPN-MID: 33|aCmUk9DR42MJvYEnNg0Xnbr6u00Xeqlc/Tdp34eeaQa8IIp64EU9sbHhMeiG2xO r7yi8bYDYCCzm6sdMbu1pWbo95qSfEMna1AuwxTxxLGw= X-KPN-VerifiedSender: Yes X-CMASSUN: 33|hch6RI3T8pEZhkRaOvP0IjHnMogfJP0PF8nk8jIHnZM6qrB+mgTlOC+83Uc670Z Pj9ZBYjWhSCx3VmwHCrsPHQ== Received: from daedalus.home (unknown [178.230.226.124]) by smtp.xs4all.nl (Halon) with ESMTPSA id f6757dc1-7e27-11f1-8dcc-00505699d6e5; Sun, 12 Jul 2026 21:29:13 +0200 (CEST) From: Jori Koolstra To: Christian Brauner , Aleksa Sarai , Kuniyuki Iwashima , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Jori Koolstra Subject: [net-next v5 1/4] net: af_unix: enable custom setsockopt for all socket types Date: Sun, 12 Jul 2026 21:29:55 +0200 Message-ID: <20260712192958.1631672-2-jkoolstra@xs4all.nl> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260712192958.1631672-1-jkoolstra@xs4all.nl> References: <20260712192958.1631672-1-jkoolstra@xs4all.nl> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 f7a9d55eee8a..3d256255085b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -949,7 +949,7 @@ static int unix_setsockopt(struct socket *sock, int lev= el, int optname, switch (optname) { case SO_INQ: if (sk->sk_type !=3D SOCK_STREAM) - return -EINVAL; + return -ENOPROTOOPT; =20 if (val > 1 || val < 0) return -EINVAL; @@ -1005,6 +1005,7 @@ static const struct proto_ops unix_dgram_ops =3D { #endif .listen =3D sock_no_listen, .shutdown =3D unix_shutdown, + .setsockopt =3D unix_setsockopt, .sendmsg =3D unix_dgram_sendmsg, .read_skb =3D unix_read_skb, .recvmsg =3D unix_dgram_recvmsg, @@ -1029,6 +1030,7 @@ static const struct proto_ops unix_seqpacket_ops =3D { #endif .listen =3D unix_listen, .shutdown =3D unix_shutdown, + .setsockopt =3D unix_setsockopt, .sendmsg =3D unix_seqpacket_sendmsg, .recvmsg =3D unix_seqpacket_recvmsg, .mmap =3D sock_no_mmap, @@ -1142,9 +1144,10 @@ static int unix_create(struct net *net, struct socke= t *sock, int protocol, if (protocol && protocol !=3D PF_UNIX) return -EPROTONOSUPPORT; =20 + set_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags); + switch (sock->type) { case SOCK_STREAM: - set_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags); sock->ops =3D &unix_stream_ops; break; /* @@ -1864,8 +1867,7 @@ static int unix_accept(struct socket *sock, struct so= cket *newsock, skb_free_datagram(sk, skb); wake_up_interruptible(&unix_sk(sk)->peer_wait); =20 - if (tsk->sk_type =3D=3D SOCK_STREAM) - set_bit(SOCK_CUSTOM_SOCKOPT, &newsock->flags); + set_bit(SOCK_CUSTOM_SOCKOPT, &newsock->flags); =20 /* attach accepted sock to socket */ unix_state_lock(tsk); --=20 2.55.0 From nobody Sat Jul 25 22:33:06 2026 Received: from ewsoutbound.kpnmail.nl (ewsoutbound.kpnmail.nl [195.121.94.185]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B05053B388E for ; Sun, 12 Jul 2026 19:29:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.121.94.185 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783884558; cv=none; b=LNK6ybG1u/FyzmL2/SvLbDs1qe1F94g+HTs/JvU5kRiWjRF32RV17oS6QWxA9iEdmaTMfp62XiJPpbtVVLB3IUBUko5Yx8Xc06Fp6PEl9Ln0lAx/1kOoDLJHXUCV/Ak5oSlWBUZcvNoiABpGxZKcJdjUC7+oc2Pvof3+1TImU+4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783884558; c=relaxed/simple; bh=QJQE/GXd0K169a8mwkplKKdkmQ5sBJfTjp2LDq9OYG0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iONYdzOe3gnGj07/ufkiyKFpnn0Si7u99qaxbJ0jiHEUOUEMWeVOlBSm4QHhnCqTmDUlE6S+cARAbVLc7Q6tCH1si7slLyZRRUUnewCrrjYpZOWmz8PjoHgS/pAIrw18yPMSZzR3D3/26w6fAPZ0J8OkNtfKIkSmp7jXGXV94IM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=xs4all.nl; spf=pass smtp.mailfrom=xs4all.nl; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b=P4xxHuf9; arc=none smtp.client-ip=195.121.94.185 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=xs4all.nl Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=xs4all.nl Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b="P4xxHuf9" X-KPN-MessageId: f798f299-7e27-11f1-9e8e-005056999439 Received: from smtp.kpnmail.nl (unknown [10.31.155.8]) by ewsoutbound.so.kpn.org (Halon) with ESMTPS id f798f299-7e27-11f1-9e8e-005056999439; Sun, 12 Jul 2026 21:29:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xs4all.nl; s=xs4all01; h=mime-version:message-id:date:subject:to:from; bh=jTewONXvFxgGhvbpYUlhsacZJwkbZKyIKe17J6I4b48=; b=P4xxHuf9t62cHKEpGb8t8CYqH1Jo9Yzt4DwnlWQdIvKB5c/bifaVrVkLK21nLkdXiDOEw6J0TrH7u 5X8mBl4JeOjrgEqzn2I5w4BlZYBBGaXZgHxHZd/XMHeChXLIfSjTs29IaLtg8jMzJPDfOXBRYDYxd8 M9FH4lyE+Diyax8ZS2FYC9Do0vGMUGpn4Vunqn0mpLgrV7l9jKRTO9KmP7277dekfVIGO01MTkvAKS 2B1bRypjDG+MahpGNzYoYoi/7uKuin1gAXXcbY2k+5Xs83vTWaCPJgmEZAvxrrdsUXd+jYe6Y58tTf iEMuUJ/kv3SXrU0pa5ecQeWF7SMcAhg== X-KPN-MID: 33|CwIQjKs957AdyUdlOp28+PvDB5Y+7tZPq2VDRTbC4dBudSZCQT7UlPggFgSIGBk 0a9iTxHxpnTlNdDTQVGrIQzku4B7uHbphAiBJbSelbKM= X-KPN-VerifiedSender: Yes X-CMASSUN: 33|NTLceOVGjkZuZpL9PCIGW5OMiyJ1Uw8ilTMavKGxPBNhuwrZUZcnYJg6hQHzEKF 2D3BmVEg5K2TpefHHy1d+8A== Received: from daedalus.home (unknown [178.230.226.124]) by smtp.xs4all.nl (Halon) with ESMTPSA id f757ec1f-7e27-11f1-8dcc-00505699d6e5; Sun, 12 Jul 2026 21:29:14 +0200 (CEST) From: Jori Koolstra To: Christian Brauner , Aleksa Sarai , Kuniyuki Iwashima , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Jori Koolstra Subject: [net-next v5 2/4] net: scm: move scm_detach_fds() from common path to scm_recv_unix() Date: Sun, 12 Jul 2026 21:29:56 +0200 Message-ID: <20260712192958.1631672-3-jkoolstra@xs4all.nl> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260712192958.1631672-1-jkoolstra@xs4all.nl> References: <20260712192958.1631672-1-jkoolstra@xs4all.nl> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" scm->fp can only be set when using UNIX sockets, therefore we should move it out of the common path __scm_recv_common() into scm_recv_unix(). Reviewed-by: Kuniyuki Iwashima Signed-off-by: Jori Koolstra --- net/core/scm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/core/scm.c b/net/core/scm.c index eec13f50ecaf..a73b1eb30fd2 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -523,9 +523,6 @@ static bool __scm_recv_common(struct sock *sk, struct m= sghdr *msg, =20 scm_passec(sk, msg, scm); =20 - if (scm->fp) - scm_detach_fds(msg, scm); - return true; } =20 @@ -545,6 +542,9 @@ void scm_recv_unix(struct socket *sock, struct msghdr *= msg, if (!__scm_recv_common(sock->sk, msg, scm, flags)) return; =20 + if (scm->fp) + scm_detach_fds(msg, scm); + if (sock->sk->sk_scm_pidfd) scm_pidfd_recv(msg, scm); =20 --=20 2.55.0 From nobody Sat Jul 25 22:33:06 2026 Received: from ewsoutbound.kpnmail.nl (ewsoutbound.kpnmail.nl [195.121.94.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18E7B3B42F8 for ; Sun, 12 Jul 2026 19:29:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.121.94.186 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783884560; cv=none; b=i4szRPZeoSQ6fdVZcTtLRaqtl06bJCUpfEJ50utrU2/HKke+vZq5Cqdl1zfzC4tiyCKQXBTFbjdvOmeaERE2qt7KqMTWyRMmG7/FjiYnXU9CHmrF2S1NEI8Q5FxIeFPiBCMLDQ8jaMThaJUT1Hoc/F3BsJll7jXYXy0RBB2suwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783884560; c=relaxed/simple; bh=5ew7vtkhCx25RA4Y2WYl4QUyM9+0YkTmdzM8NfLaeAs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TJDowwebh3MG0lhRJK7rjPa3zV+w1cDlh/ZyC+ryAdCdscBdTfawh8dvpGOJ/2bdmZKHCcY/hInG6xSszPUwyfWM6yD8bZDc6jkEQ/0aF+BUvn5czRbCMC00ZO76pR1JKqwYkptvedV7wkPmij0hc9E1FNZtRQQ+494oJ1dAHdw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=xs4all.nl; spf=pass smtp.mailfrom=xs4all.nl; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b=Gm9nOCaT; arc=none smtp.client-ip=195.121.94.186 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=xs4all.nl Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=xs4all.nl Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b="Gm9nOCaT" X-KPN-MessageId: f8538e4a-7e27-11f1-bfba-00505699b430 Received: from smtp.kpnmail.nl (unknown [10.31.155.8]) by ewsoutbound.so.kpn.org (Halon) with ESMTPS id f8538e4a-7e27-11f1-bfba-00505699b430; Sun, 12 Jul 2026 21:29:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xs4all.nl; s=xs4all01; h=mime-version:message-id:date:subject:to:from; bh=sruf6qqqWXHR0y2gkzYFVTzl4Yid+EZNc8vc50uaFDI=; b=Gm9nOCaTocH34kkTad6D9C+INE9ynJWKupb+il9vysZD6BCYz9D5Z3MNPEchVjoVPtwTquBH+x9L6 5gZekx07UvMVF6K80Qwgz280Tu08zYsiAkDKsTJxwD8AKirD930bjOcVIjCfw++G5ZOcElSIgh0g7W bplVh+mysVNApdNJWSMghHGHhQ6IEbbs5m7IBHzdwmzVwnHT9MoCQjZ6Rw2T5Hdi86TIl9uEkrBgPu n6H2wH0uS97JxXwNIJwi/a5SW+KhUszN6I+EBVZ+8Knml2nEzqJ8uPYK5Xz6mImaVIF3axcWowEvt/ Zm8oBqqdRX/9Peus6JlJlZjFVI92lOA== X-KPN-MID: 33|M8e36xt7EPf5XHLZwodcbpL9W7ImY4pamSmps8ikLZU7lWa7+afxr6nipI4TUx4 Vf14q67qss1ClSkU/EmgGhYqFtUeMGOsWGyTln2kiEWg= X-KPN-VerifiedSender: Yes X-CMASSUN: 33|GMSnAkCdtfs8VFwbqjKfxL/MHcOEm9md99JjB8Sv1OIwCvejpp6RM3qI7nsPy3f Ywmc9/cxq1VLWglS3H8URdA== Received: from daedalus.home (unknown [178.230.226.124]) by smtp.xs4all.nl (Halon) with ESMTPSA id f80febca-7e27-11f1-8dcc-00505699d6e5; Sun, 12 Jul 2026 21:29:15 +0200 (CEST) From: Jori Koolstra To: Christian Brauner , Aleksa Sarai , Kuniyuki Iwashima , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Jori Koolstra Subject: [net-next v5 3/4] net: af_unix: useful handling of LSM denials on SCM_RIGHTS Date: Sun, 12 Jul 2026 21:29:57 +0200 Message-ID: <20260712192958.1631672-4-jkoolstra@xs4all.nl> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260712192958.1631672-1-jkoolstra@xs4all.nl> References: <20260712192958.1631672-1-jkoolstra@xs4all.nl> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Right now if some LSM such as Smack denies an AF_UNIX socket peer to receive an SCM_RIGHTS fd, the SCM_RIGHTS fd array will be cut short at that point, and MSG_CTRUNC is set on return of recvmsg(). This is highly problematic behaviour, because it leaves the receiver wondering what happened. As per man page MSG_CTRUNC is supposed to indicate that the control buffer was sized too short, but suddenly a permission error might result in the exact same flag being set. Moreover, the receiver has no chance to determine how many fds got originally sent and how many were suppressed.[1] Add a SO_RIGHTS_NOTRUNC option to UNIX sockets to enable more useful handling of LSM denials when receiving SCM_RIGHTS messages: instead of truncating the message at the first blocked fd, keep every fd slot and store the LSM errno in the blocked slot. [1]: https://github.com/uapi-group/kernel-features#useful-handling-of-lsm-d= enials-on-scm_rights Reviewed-by: Christian Brauner (Amutable) Signed-off-by: Jori Koolstra --- arch/alpha/include/uapi/asm/socket.h | 2 ++ arch/mips/include/uapi/asm/socket.h | 2 ++ arch/parisc/include/uapi/asm/socket.h | 2 ++ arch/sparc/include/uapi/asm/socket.h | 2 ++ include/net/af_unix.h | 1 + include/net/scm.h | 13 +++------ include/uapi/asm-generic/socket.h | 2 ++ net/compat.c | 4 +-- net/core/scm.c | 38 +++++++++++++++++++++++---- net/unix/af_unix.c | 9 +++++++ 10 files changed, 59 insertions(+), 16 deletions(-) diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi= /asm/socket.h index 5ef57f88df6b..946a5fad2691 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -155,6 +155,8 @@ #define SO_INQ 84 #define SCM_INQ SO_INQ =20 +#define SO_RIGHTS_NOTRUNC 85 + #if !defined(__KERNEL__) =20 #if __BITS_PER_LONG =3D=3D 64 diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/a= sm/socket.h index 72fb1b006da9..f1641dde135f 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -166,6 +166,8 @@ #define SO_INQ 84 #define SCM_INQ SO_INQ =20 +#define SO_RIGHTS_NOTRUNC 85 + #if !defined(__KERNEL__) =20 #if __BITS_PER_LONG =3D=3D 64 diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/ua= pi/asm/socket.h index c16ec36dfee6..f3a3815c7dc2 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -147,6 +147,8 @@ #define SO_INQ 0x4052 #define SCM_INQ SO_INQ =20 +#define SO_RIGHTS_NOTRUNC 0x4053 + #if !defined(__KERNEL__) =20 #if __BITS_PER_LONG =3D=3D 64 diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi= /asm/socket.h index 71befa109e1c..7907f3b1f0ee 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -148,6 +148,8 @@ #define SO_INQ 0x005d #define SCM_INQ SO_INQ =20 +#define SO_RIGHTS_NOTRUNC 0x005e + #if !defined(__KERNEL__) =20 =20 diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 34f53dde65ce..bb1b3dee02e8 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -49,6 +49,7 @@ struct unix_sock { struct scm_stat scm_stat; int inq_len; bool recvmsg_inq; + bool scm_rights_notrunc; #if IS_ENABLED(CONFIG_AF_UNIX_OOB) struct sk_buff *oob_skb; #endif diff --git a/include/net/scm.h b/include/net/scm.h index c52519669349..86ae6bc109ec 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -50,8 +50,8 @@ struct scm_cookie { #endif }; =20 -void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); -void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); +void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm, bool notru= nc); +void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm, boo= l notrunc); int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie = *scm); void __scm_destroy(struct scm_cookie *scm); struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl); @@ -107,13 +107,8 @@ void scm_recv(struct socket *sock, struct msghdr *msg, void scm_recv_unix(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm, int flags); =20 -static inline int scm_recv_one_fd(struct file *f, int __user *ufd, - unsigned int flags) -{ - if (!ufd) - return -EFAULT; - return receive_fd(f, ufd, flags); -} +int scm_recv_one_fd(struct file *f, int __user *ufd, unsigned int flags, + bool notrunc); =20 #endif /* __LINUX_NET_SCM_H */ =20 diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/s= ocket.h index 53b5a8c002b1..84ea7b92936e 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -150,6 +150,8 @@ #define SO_INQ 84 #define SCM_INQ SO_INQ =20 +#define SO_RIGHTS_NOTRUNC 85 + #if !defined(__KERNEL__) =20 #if __BITS_PER_LONG =3D=3D 64 || (defined(__x86_64__) && defined(__ILP32__= )) diff --git a/net/compat.c b/net/compat.c index d68cf9c3aad5..6bdf4a2c9077 100644 --- a/net/compat.c +++ b/net/compat.c @@ -286,7 +286,7 @@ static int scm_max_fds_compat(struct msghdr *msg) return (msg->msg_controllen - sizeof(struct compat_cmsghdr)) / sizeof(int= ); } =20 -void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm) +void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm, boo= l notrunc) { struct compat_cmsghdr __user *cm =3D (struct compat_cmsghdr __user *)msg->msg_control_user; @@ -296,7 +296,7 @@ void scm_detach_fds_compat(struct msghdr *msg, struct s= cm_cookie *scm) int err =3D 0, i; =20 for (i =3D 0; i < fdmax; i++) { - err =3D scm_recv_one_fd(scm->fp->fp[i], cmsg_data + i, o_flags); + err =3D scm_recv_one_fd(scm->fp->fp[i], cmsg_data + i, o_flags, notrunc); if (err < 0) break; } diff --git a/net/core/scm.c b/net/core/scm.c index a73b1eb30fd2..f0d44ecdb11f 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -351,7 +351,31 @@ static int scm_max_fds(struct msghdr *msg) return (msg->msg_controllen - sizeof(struct cmsghdr)) / sizeof(int); } =20 -void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) +int scm_recv_one_fd(struct file *f, int __user *ufd, unsigned int flags, + bool notrunc) +{ + int error; + + if (!ufd) + return -EFAULT; + + error =3D security_file_receive(f); + if (error) + return notrunc ? put_user(error, ufd) : error; + + FD_PREPARE(fdf, flags, get_file(f)); + if (fdf.err) + return fdf.err; + + error =3D put_user(fd_prepare_fd(fdf), ufd); + if (error) + return error; + + __receive_sock(fd_prepare_file(fdf)); + return fd_publish(fdf); +} + +void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm, bool notru= nc) { struct cmsghdr __user *cm =3D (__force struct cmsghdr __user *)msg->msg_control_user; @@ -365,12 +389,12 @@ void scm_detach_fds(struct msghdr *msg, struct scm_co= okie *scm) return; =20 if (msg->msg_flags & MSG_CMSG_COMPAT) { - scm_detach_fds_compat(msg, scm); + scm_detach_fds_compat(msg, scm, notrunc); return; } =20 for (i =3D 0; i < fdmax; i++) { - err =3D scm_recv_one_fd(scm->fp->fp[i], cmsg_data + i, o_flags); + err =3D scm_recv_one_fd(scm->fp->fp[i], cmsg_data + i, o_flags, notrunc); if (err < 0) break; } @@ -542,8 +566,12 @@ void scm_recv_unix(struct socket *sock, struct msghdr = *msg, if (!__scm_recv_common(sock->sk, msg, scm, flags)) return; =20 - if (scm->fp) - scm_detach_fds(msg, scm); + if (scm->fp) { + struct unix_sock *u; + + u =3D unix_sk(sock->sk); + scm_detach_fds(msg, scm, READ_ONCE(u->scm_rights_notrunc)); + } =20 if (sock->sk->sk_scm_pidfd) scm_pidfd_recv(msg, scm); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 3d256255085b..e7b3aab2f176 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -921,6 +921,7 @@ static bool unix_custom_sockopt(int optname) { switch (optname) { case SO_INQ: + case SO_RIGHTS_NOTRUNC: return true; default: return false; @@ -956,6 +957,14 @@ static int unix_setsockopt(struct socket *sock, int le= vel, int optname, =20 WRITE_ONCE(u->recvmsg_inq, val); break; + + case SO_RIGHTS_NOTRUNC: + if (val > 1 || val < 0) + return -EINVAL; + + WRITE_ONCE(u->scm_rights_notrunc, val); + break; + default: return -ENOPROTOOPT; } --=20 2.55.0 From nobody Sat Jul 25 22:33:06 2026 Received: from ewsoutbound.kpnmail.nl (ewsoutbound.kpnmail.nl [195.121.94.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7BFE33B47C6 for ; Sun, 12 Jul 2026 19:29:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.121.94.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783884560; cv=none; b=epDGdlgepc3S0glVk9SbwwGuYAPOkPDf+vmzjxFhw9fVYlcwLqrKEsJD+48KNv6zaxo9q4nyH9+n7WmFbEvs1kbnaEQNjB3p5tnKpYGXT8AebKbif6pFeO81JGxXWIRgFXfZXMWnwDL0qoGbZDZE3wewnpX+vWLz/ewLghv+1ek= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783884560; c=relaxed/simple; bh=XHMuebYMDE2zzCjQFdsX95/uaswpEPC90O4vAxeBb5g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JMFIfX69aeNok29YuZlMf54s3rj3T+dWQlZfINyax78AGm5z+sAuI2mxEtqxflT9B2jF01xAPrZzyAPRAhfSnQ1kLl4mjJOTjpOb6zlHcmxnazVgAifOIOAdvrU4Rz7ntMGERoy+GydjnaiTJpIf6WhL94plie2e+qY4jJvbgoI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=xs4all.nl; spf=pass smtp.mailfrom=xs4all.nl; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b=qo+rb81T; arc=none smtp.client-ip=195.121.94.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=xs4all.nl Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=xs4all.nl Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=xs4all.nl header.i=@xs4all.nl header.b="qo+rb81T" X-KPN-MessageId: f9160ab9-7e27-11f1-a59f-005056994fde Received: from smtp.kpnmail.nl (unknown [10.31.155.8]) by ewsoutbound.so.kpn.org (Halon) with ESMTPS id f9160ab9-7e27-11f1-a59f-005056994fde; Sun, 12 Jul 2026 21:29:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xs4all.nl; s=xs4all01; h=mime-version:message-id:date:subject:to:from; bh=IsKD/gs8IXHiatP/vMKAcAxR/5yaXOivhFB8vtSUSTc=; b=qo+rb81T5KwzK/VfqCCsbRYH37g5mzD1X0NLkLT9/sWldJ6LWOO8mnbcqjRuH5eIHG/uXSo4py6e/ 9BCCkCe5KVruqiLUfNV8LlFqUBNi/jIfC1VgCqXQYxQdpwkRvpIa1CculLOGm5A7LrtaFTaH1tsc2M hi0SZr+ucscelO82nV6zYLmhUViMvg2ljIDRz027RcDsR6bOWPtrJnQdDHbDABSXx6Qg24HLFxnc3Y +2MgMe3bessbKOHxUwNHUGnZhuropyOaOmchabypiFh2JvbTDiIv1uXiYpgBQaVgmuCuP0pODrB1zw jMPDzNOmagRDSSFiW1qed3Cm3lXxnxg== X-KPN-MID: 33|8Y1Jad/S6DZgaGjPq0rLrP6+7VwycBE0/CzINa4P908phdBoulpXSaiKUDUYVQc 2G2IcPkwwJ3uTpUiZnMPOIA== X-KPN-VerifiedSender: Yes X-CMASSUN: 33|6qjR8TQeKZ5/loBxW6q/REu1IKiGcUHsGHtkiJ0I4pcTVVXM690JVRbdMUL/yBK upDT/Mg3PkajZV1G+UXvFGg== Received: from daedalus.home (unknown [178.230.226.124]) by smtp.xs4all.nl (Halon) with ESMTPSA id f8d4259c-7e27-11f1-8dcc-00505699d6e5; Sun, 12 Jul 2026 21:29:17 +0200 (CEST) From: Jori Koolstra To: Christian Brauner , Aleksa Sarai , Kuniyuki Iwashima , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Jori Koolstra Subject: [net-next v5 4/4] selftest: Add tests for useful handling of LSM denials on SCM_RIGHTS Date: Sun, 12 Jul 2026 21:29:58 +0200 Message-ID: <20260712192958.1631672-5-jkoolstra@xs4all.nl> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260712192958.1631672-1-jkoolstra@xs4all.nl> References: <20260712192958.1631672-1-jkoolstra@xs4all.nl> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Tests SCM_RIGHTS fd passing on a socket with the new socket option SO_RIGHTS_NOTRUNC turned on. To hook into the security_file_receive() call, BPF is used. The BPF program shares a hashmap with userspace that lists the inos to be blocked (of the receiver tgid). Signed-off-by: Jori Koolstra --- .../testing/selftests/net/af_unix/.gitignore | 2 + tools/testing/selftests/net/af_unix/Makefile | 8 + tools/testing/selftests/net/af_unix/config | 7 + .../net/af_unix/scm_rights_denial_lsm.bpf.c | 36 +++ .../net/af_unix/scm_rights_denial_lsm.c | 285 ++++++++++++++++++ 5 files changed, 338 insertions(+) create mode 100644 tools/testing/selftests/net/af_unix/scm_rights_denial_l= sm.bpf.c create mode 100644 tools/testing/selftests/net/af_unix/scm_rights_denial_l= sm.c diff --git a/tools/testing/selftests/net/af_unix/.gitignore b/tools/testing= /selftests/net/af_unix/.gitignore index 240b26740c9e..5034482f8864 100644 --- a/tools/testing/selftests/net/af_unix/.gitignore +++ b/tools/testing/selftests/net/af_unix/.gitignore @@ -3,6 +3,8 @@ msg_oob scm_inq scm_pidfd scm_rights +scm_rights_denial_lsm +scm_rights_denial_lsm.bpf.o so_peek_off unix_connect unix_connreset diff --git a/tools/testing/selftests/net/af_unix/Makefile b/tools/testing/s= elftests/net/af_unix/Makefile index 4c0375e28bbe..594cd26ec398 100644 --- a/tools/testing/selftests/net/af_unix/Makefile +++ b/tools/testing/selftests/net/af_unix/Makefile @@ -11,9 +11,17 @@ TEST_GEN_PROGS :=3D \ scm_inq \ scm_pidfd \ scm_rights \ + scm_rights_denial_lsm \ so_peek_off \ unix_connect \ unix_connreset \ # end of TEST_GEN_PROGS =20 +TEST_GEN_FILES :=3D scm_rights_denial_lsm.bpf.o + include ../../lib.mk +include ../bpf.mk + +$(OUTPUT)/scm_rights_denial_lsm: $(BPFOBJ) +$(OUTPUT)/scm_rights_denial_lsm: CFLAGS +=3D -I$(SCRATCH_DIR)/include +$(OUTPUT)/scm_rights_denial_lsm: LDLIBS +=3D -lelf -lz diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/sel= ftests/net/af_unix/config index b5429c15a53c..acec3f94937e 100644 --- a/tools/testing/selftests/net/af_unix/config +++ b/tools/testing/selftests/net/af_unix/config @@ -1,3 +1,10 @@ CONFIG_AF_UNIX_OOB=3Dy CONFIG_UNIX=3Dy CONFIG_UNIX_DIAG=3Dm +CONFIG_BPF=3Dy +CONFIG_BPF_SYSCALL=3Dy +CONFIG_BPF_EVENTS=3Dy +CONFIG_BPF_JIT=3Dy +CONFIG_SECURITY=3Dy +CONFIG_BPF_LSM=3Dy +CONFIG_DEBUG_INFO_BTF=3Dy diff --git a/tools/testing/selftests/net/af_unix/scm_rights_denial_lsm.bpf.= c b/tools/testing/selftests/net/af_unix/scm_rights_denial_lsm.bpf.c new file mode 100644 index 000000000000..4f2414465bfd --- /dev/null +++ b/tools/testing/selftests/net/af_unix/scm_rights_denial_lsm.bpf.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +char _license[] SEC("license") =3D "GPL"; + +struct inode { + unsigned long i_ino; +} __attribute__((preserve_access_index)); + +struct file { + struct inode *f_inode; +} __attribute__((preserve_access_index)); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 16); + __type(key, __u64); /* inode number */ + __type(value, __u32); /* tgid of the receiver being tested */ +} denied_inodes SEC(".maps"); + +SEC("lsm/file_receive") +int BPF_PROG(scm_rights_deny, struct file *file) +{ + __u32 tgid =3D bpf_get_current_pid_tgid() >> 32; + __u64 ino =3D file->f_inode->i_ino; + __u32 *owner; + + owner =3D bpf_map_lookup_elem(&denied_inodes, &ino); + if (owner && *owner =3D=3D tgid) + return -EPERM; + + return 0; +} diff --git a/tools/testing/selftests/net/af_unix/scm_rights_denial_lsm.c b/= tools/testing/selftests/net/af_unix/scm_rights_denial_lsm.c new file mode 100644 index 000000000000..941b7decf798 --- /dev/null +++ b/tools/testing/selftests/net/af_unix/scm_rights_denial_lsm.c @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "kselftest_harness.h" + +#ifndef SO_RIGHTS_NOTRUNC +#define SO_RIGHTS_NOTRUNC 85 +#endif + +#define NR_FILES 2 + +/* Per-file content, so a received fd can be matched to the file sent */ +#define SECRET(n) "secret %d", (n) + +/* Indices into the socketpair */ +#define SK_SENDER 0 +#define SK_RECEIVER 1 + +FIXTURE(scm_rights_denial_bpf) +{ + struct bpf_object *obj; + struct bpf_link *link; + int map_fd; + int sk[2]; + int files[NR_FILES]; + __u64 inos[NR_FILES]; + char paths[NR_FILES][64]; +}; + +FIXTURE_VARIANT(scm_rights_denial_bpf) +{ + int sock_type; +}; + +FIXTURE_VARIANT_ADD(scm_rights_denial_bpf, stream) +{ + .sock_type =3D SOCK_STREAM, +}; + +FIXTURE_VARIANT_ADD(scm_rights_denial_bpf, dgram) +{ + .sock_type =3D SOCK_DGRAM, +}; + +FIXTURE_VARIANT_ADD(scm_rights_denial_bpf, seqpacket) +{ + .sock_type =3D SOCK_SEQPACKET, +}; + +FIXTURE_SETUP(scm_rights_denial_bpf) +{ + struct bpf_program *prog; + char lsms[256] =3D {}; + int i, fd; + + if (geteuid() !=3D 0) + SKIP(return, "requires root"); + + fd =3D open("/sys/kernel/security/lsm", O_RDONLY); + ASSERT_GE(fd, 0); + ASSERT_LT(0, read(fd, lsms, sizeof(lsms) - 1)); + close(fd); + + if (!strstr(lsms, "bpf")) + SKIP(return, "BPF LSM not active (boot with lsm=3D...,bpf)"); + + self->obj =3D bpf_object__open_file("scm_rights_denial_lsm.bpf.o", NULL); + ASSERT_NE(NULL, self->obj); + ASSERT_EQ(0, bpf_object__load(self->obj)); + + prog =3D bpf_object__find_program_by_name(self->obj, "scm_rights_deny"); + ASSERT_NE(NULL, prog); + + self->link =3D bpf_program__attach_lsm(prog); + ASSERT_NE(NULL, self->link); + + self->map_fd =3D bpf_object__find_map_fd_by_name(self->obj, + "denied_inodes"); + ASSERT_GE(self->map_fd, 0); + + ASSERT_EQ(0, socketpair(AF_UNIX, variant->sock_type, 0, self->sk)); + + for (i =3D 0; i < NR_FILES; i++) { + struct stat st; + + snprintf(self->paths[i], sizeof(self->paths[i]), + "/tmp/scm_rights_denial_bpf.%d.XXXXXX", i); + self->files[i] =3D mkstemp(self->paths[i]); + ASSERT_GE(self->files[i], 0); + + ASSERT_LT(0, dprintf(self->files[i], SECRET(i))); + + ASSERT_EQ(0, fstat(self->files[i], &st)); + self->inos[i] =3D st.st_ino; + } +} + +FIXTURE_TEARDOWN(scm_rights_denial_bpf) +{ + bpf_link__destroy(self->link); + bpf_object__close(self->obj); + + for (int i =3D 0; i < NR_FILES; i++) { + if (self->files[i] >=3D 0) { + close(self->files[i]); + unlink(self->paths[i]); + } + } + + close(self->sk[SK_SENDER]); + close(self->sk[SK_RECEIVER]); +} + +static int deny_inode(int map_fd, __u64 ino) +{ + __u32 tgid =3D getpid(); + + return bpf_map_update_elem(map_fd, &ino, &tgid, BPF_ANY); +} + +static int set_notrunc(int sk) +{ + int one =3D 1; + + return setsockopt(sk, SOL_SOCKET, SO_RIGHTS_NOTRUNC, + &one, sizeof(one)); +} + +static int send_fds(int sk, int *fds, int n) +{ + char ctrl[CMSG_SPACE(NR_FILES * sizeof(int))] =3D {}; + char data =3D 'x'; + struct iovec iov =3D { + .iov_base =3D &data, + .iov_len =3D sizeof(data), + }; + struct msghdr msg =3D { + .msg_iov =3D &iov, + .msg_iovlen =3D 1, + .msg_control =3D ctrl, + .msg_controllen =3D CMSG_SPACE(n * sizeof(int)), + }; + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(n * sizeof(int)); + memcpy(CMSG_DATA(cmsg), fds, n * sizeof(int)); + + return sendmsg(sk, &msg, 0); +} + +static int recv_fd_slots(int sk, int *slots, int *msg_flags) +{ + int nr_slots; + char ctrl[CMSG_SPACE(NR_FILES * sizeof(int))]; + char data; + struct iovec iov =3D { + .iov_base =3D &data, + .iov_len =3D sizeof(data), + }; + struct msghdr msg =3D { + .msg_iov =3D &iov, + .msg_iovlen =3D 1, + .msg_control =3D ctrl, + .msg_controllen =3D sizeof(ctrl), + }; + struct cmsghdr *cmsg; + + if (recvmsg(sk, &msg, 0) < 0) + return -1; + + *msg_flags =3D msg.msg_flags; + + cmsg =3D CMSG_FIRSTHDR(&msg); + if (!cmsg) + return 0; + + nr_slots =3D (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + memcpy(slots, CMSG_DATA(cmsg), nr_slots * sizeof(int)); + + return nr_slots; +} + +/* Prove a received fd works by reading back the file's content. */ +static int check_secret(int fd, int idx) +{ + char want[32], got[32] =3D {}; + + snprintf(want, sizeof(want), SECRET(idx)); + if (pread(fd, got, sizeof(got) - 1, 0) < 0) + return -1; + + return strcmp(want, got); +} + +TEST_F(scm_rights_denial_bpf, all_allowed) +{ + int slots[NR_FILES], nr_slots, flags, i; + + ASSERT_EQ(0, set_notrunc(self->sk[SK_RECEIVER])); + ASSERT_NE(-1, send_fds(self->sk[SK_SENDER], self->files, NR_FILES)); + nr_slots =3D recv_fd_slots(self->sk[SK_RECEIVER], slots, &flags); + + ASSERT_EQ(NR_FILES, nr_slots); + EXPECT_EQ(0, flags & MSG_CTRUNC); + + for (i =3D 0; i < NR_FILES; i++) { + ASSERT_GE(slots[i], 0); + EXPECT_EQ(0, check_secret(slots[i], i)); + close(slots[i]); + } +} + +TEST_F(scm_rights_denial_bpf, first_denied) +{ + int slots[NR_FILES], nr_slots, flags; + + ASSERT_EQ(0, deny_inode(self->map_fd, self->inos[0])); + + ASSERT_EQ(0, set_notrunc(self->sk[SK_RECEIVER])); + ASSERT_NE(-1, send_fds(self->sk[SK_SENDER], self->files, NR_FILES)); + nr_slots =3D recv_fd_slots(self->sk[SK_RECEIVER], slots, &flags); + + ASSERT_EQ(NR_FILES, nr_slots); + EXPECT_EQ(0, flags & MSG_CTRUNC); + EXPECT_EQ(-EPERM, slots[0]); + + ASSERT_GE(slots[1], 0); + EXPECT_EQ(0, check_secret(slots[1], 1)); + close(slots[1]); +} + +TEST_F(scm_rights_denial_bpf, all_denied) +{ + int slots[NR_FILES], nr_slots, flags, i; + + for (i =3D 0; i < NR_FILES; i++) + ASSERT_EQ(0, deny_inode(self->map_fd, self->inos[i])); + + ASSERT_EQ(0, set_notrunc(self->sk[SK_RECEIVER])); + ASSERT_NE(-1, send_fds(self->sk[SK_SENDER], self->files, NR_FILES)); + nr_slots =3D recv_fd_slots(self->sk[SK_RECEIVER], slots, &flags); + + ASSERT_EQ(NR_FILES, nr_slots); + EXPECT_EQ(0, flags & MSG_CTRUNC); + + for (i =3D 0; i < NR_FILES; i++) + EXPECT_EQ(-EPERM, slots[i]); +} + +TEST_F(scm_rights_denial_bpf, denied_without_notrunc) +{ + int slots[NR_FILES], nr_slots, flags; + + /* + * Baseline behaviour without SO_RIGHTS_NOTRUNC: the fd array is + * truncated at the first denied fd and MSG_CTRUNC is set. + */ + ASSERT_EQ(0, deny_inode(self->map_fd, self->inos[1])); + + ASSERT_NE(-1, send_fds(self->sk[SK_SENDER], self->files, NR_FILES)); + nr_slots =3D recv_fd_slots(self->sk[SK_RECEIVER], slots, &flags); + + ASSERT_EQ(1, nr_slots); + EXPECT_NE(0, flags & MSG_CTRUNC); + + ASSERT_GE(slots[0], 0); + EXPECT_EQ(0, check_secret(slots[0], 0)); + close(slots[0]); +} + +TEST_HARNESS_MAIN --=20 2.55.0