From: Justin Suess <utilityemal77@gmail.com>
To: paul@paul-moore.com
Cc: bigeasy@linutronix.de, brauner@kernel.org, demiobenour@gmail.com,
fahimitahera@gmail.com, gnoack3000@gmail.com, hi@alyssa.is,
horms@kernel.org, ivanov.mikhail1@huawei-partners.com,
jannh@google.com, jmorris@namei.org, john.johansen@canonical.com,
konstantin.meskhidze@huawei.com, kuniyu@google.com,
linux-security-module@vger.kernel.org, m@maowtm.org,
matthieu@buffet.re, mic@digikod.net, netdev@vger.kernel.org,
samasth.norway.ananda@oracle.com, serge@hallyn.com,
utilityemal77@gmail.com, viro@zeniv.linux.org.uk
Subject: [PATCH v7 1/9] lsm: Add LSM hook security_unix_find
Date: Tue, 17 Mar 2026 19:20:41 -0400 [thread overview]
Message-ID: <20260317232041.330576-1-utilityemal77@gmail.com> (raw)
In-Reply-To: <2697b9f672967b1318630f2ffa21914f@paul-moore.com>
Add a LSM hook security_unix_find.
This hook is called to check the path of a named unix socket before a
connection is initiated. The peer socket may be inspected as well.
Why existing hooks are unsuitable:
Existing socket hooks, security_unix_stream_connect(),
security_unix_may_send(), and security_socket_connect() don't provide
TOCTOU-free / namespace independent access to the paths of sockets.
(1) We cannot resolve the path from the struct sockaddr in existing hooks.
This requires another path lookup. A change in the path between the
two lookups will cause a TOCTOU bug.
(2) We cannot use the struct path from the listening socket, because it
may be bound to a path in a different namespace than the caller,
resulting in a path that cannot be referenced at policy creation time.
Consumers of the hook wishing to reference @other are responsible
for acquiring the unix_state_lock and checking for the SOCK_DEAD flag
therein, ensuring the socket hasn't died since lookup.
Cc: Günther Noack <gnoack3000@gmail.com>
Cc: Tingmao Wang <m@maowtm.org>
Cc: Paul Moore <paul@paul-moore.com>
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
Paul,
I updated the hook placement as per your suggestions. Moving the hook into
the block does require duplicate stubs, but I don't see another way to move the
stub into that block and properly handle the case where CONFIG_SECURITY_PATH is
defined but CONFIG_SECURITY_NETWORK isn't. If the stub is moved into that #else
block it will never be defined in that case.
I removed the self-evident comment as well from security_unix_find and added
the whitespace.
I also updated the comments and commit message with respect to locking.
include/linux/lsm_hook_defs.h | 6 ++++++
include/linux/security.h | 13 +++++++++++++
net/unix/af_unix.c | 10 +++++++---
security/security.c | 19 +++++++++++++++++++
4 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 8c42b4bde09c..0017a540c2fb 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -321,6 +321,12 @@ LSM_HOOK(int, 0, watch_key, struct key *key)
LSM_HOOK(int, 0, unix_stream_connect, struct sock *sock, struct sock *other,
struct sock *newsk)
LSM_HOOK(int, 0, unix_may_send, struct socket *sock, struct socket *other)
+
+#ifdef CONFIG_SECURITY_PATH
+LSM_HOOK(int, 0, unix_find, const struct path *path, struct sock *other,
+ int flags)
+#endif /* CONFIG_SECURITY_PATH */
+
LSM_HOOK(int, 0, socket_create, int family, int type, int protocol, int kern)
LSM_HOOK(int, 0, socket_post_create, struct socket *sock, int family, int type,
int protocol, int kern)
diff --git a/include/linux/security.h b/include/linux/security.h
index 83a646d72f6f..3f8c23ad1199 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1641,6 +1641,14 @@ static inline int security_watch_key(struct key *key)
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk);
int security_unix_may_send(struct socket *sock, struct socket *other);
+#ifdef CONFIG_SECURITY_PATH
+int security_unix_find(const struct path *path, struct sock *other, int flags);
+#else /* CONFIG_SECURITY_PATH */
+static inline int security_unix_find(const struct path *path, struct sock *other, int flags)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY_PATH */
int security_socket_create(int family, int type, int protocol, int kern);
int security_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern);
@@ -1712,6 +1720,11 @@ static inline int security_unix_may_send(struct socket *sock,
return 0;
}
+static inline int security_unix_find(const struct path *path, struct sock *other, int flags)
+{
+ return 0;
+}
+
static inline int security_socket_create(int family, int type,
int protocol, int kern)
{
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 3756a93dc63a..5ef3c2e31757 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1231,11 +1231,15 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
goto path_put;
err = -EPROTOTYPE;
- if (sk->sk_type == type)
- touch_atime(&path);
- else
+ if (sk->sk_type != type)
goto sock_put;
+ err = security_unix_find(&path, sk, flags);
+ if (err)
+ goto sock_put;
+
+ touch_atime(&path);
+
path_put(&path);
return sk;
diff --git a/security/security.c b/security/security.c
index 67af9228c4e9..f8df5e1b55e6 100644
--- a/security/security.c
+++ b/security/security.c
@@ -4073,6 +4073,25 @@ int security_unix_may_send(struct socket *sock, struct socket *other)
}
EXPORT_SYMBOL(security_unix_may_send);
+#ifdef CONFIG_SECURITY_PATH
+/**
+ * security_unix_find() - Check if a named AF_UNIX socket can connect
+ * @path: path of the socket being connected to
+ * @other: peer sock
+ * @flags: flags associated with the socket
+ *
+ * This hook is called to check permissions before connecting to a named
+ * AF_UNIX socket. The caller does not hold any locks on @other.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_unix_find(const struct path *path, struct sock *other, int flags)
+{
+ return call_int_hook(unix_find, path, other, flags);
+}
+EXPORT_SYMBOL(security_unix_find);
+#endif /* CONFIG_SECURITY_PATH */
+
/**
* security_socket_create() - Check if creating a new socket is allowed
* @family: protocol family
--
2.51.0
next prev parent reply other threads:[~2026-03-17 23:21 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-15 22:21 [PATCH v6 0/9] landlock: UNIX connect() control by pathname and scope Günther Noack
2026-03-15 22:21 ` [PATCH v6 1/9] lsm: Add LSM hook security_unix_find Günther Noack
2026-03-17 21:14 ` Mickaël Salaün
2026-03-17 21:34 ` Paul Moore
2026-03-17 23:20 ` Justin Suess [this message]
2026-03-18 1:28 ` [PATCH v7 " Paul Moore
2026-03-18 8:48 ` [PATCH v6 " Mickaël Salaün
2026-03-18 14:44 ` Paul Moore
2026-03-18 16:22 ` Mickaël Salaün
2026-03-18 16:43 ` Paul Moore
2026-03-23 14:37 ` Georgia Garcia
2026-03-23 20:26 ` Paul Moore
2026-03-18 16:51 ` Mickaël Salaün
2026-03-15 22:21 ` [PATCH v6 2/9] landlock: use mem_is_zero() in is_layer_masks_allowed() Günther Noack
2026-03-18 16:52 ` Mickaël Salaün
2026-03-20 10:50 ` Günther Noack
2026-03-15 22:21 ` [PATCH v6 3/9] landlock: Control pathname UNIX domain socket resolution by path Günther Noack
2026-03-18 11:15 ` Sebastian Andrzej Siewior
2026-03-18 14:14 ` Justin Suess
2026-03-18 15:05 ` Sebastian Andrzej Siewior
2026-03-18 16:26 ` Mickaël Salaün
2026-03-18 16:43 ` Justin Suess
2026-03-18 17:52 ` Mickaël Salaün
2026-03-20 12:28 ` Günther Noack
2026-03-18 16:52 ` Mickaël Salaün
2026-03-20 16:15 ` Günther Noack
2026-03-20 17:51 ` Mickaël Salaün
2026-03-20 22:25 ` Günther Noack
2026-03-21 9:09 ` Mickaël Salaün
2026-03-23 15:31 ` Günther Noack
2026-03-15 22:21 ` [PATCH v6 4/9] samples/landlock: Add support for named UNIX domain socket restrictions Günther Noack
2026-03-15 22:21 ` [PATCH v6 5/9] landlock/selftests: Test LANDLOCK_ACCESS_FS_RESOLVE_UNIX Günther Noack
2026-03-18 16:53 ` Mickaël Salaün
2026-03-20 10:51 ` Günther Noack
2026-03-15 22:21 ` [PATCH v6 6/9] landlock/selftests: Audit test for LANDLOCK_ACCESS_FS_RESOLVE_UNIX Günther Noack
2026-03-18 16:53 ` Mickaël Salaün
2026-03-15 22:21 ` [PATCH v6 7/9] landlock/selftests: Check that coredump sockets stay unrestricted Günther Noack
2026-03-18 16:53 ` Mickaël Salaün
2026-03-20 16:44 ` Günther Noack
2026-03-15 22:21 ` [PATCH v6 8/9] landlock/selftests: fs_test: Simplify ruleset creation and enforcement Günther Noack
2026-03-15 22:21 ` [PATCH v6 9/9] landlock: Document FS access right for pathname UNIX sockets Günther Noack
2026-03-18 16:54 ` Mickaël Salaün
2026-03-20 17:04 ` Günther Noack
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260317232041.330576-1-utilityemal77@gmail.com \
--to=utilityemal77@gmail.com \
--cc=bigeasy@linutronix.de \
--cc=brauner@kernel.org \
--cc=demiobenour@gmail.com \
--cc=fahimitahera@gmail.com \
--cc=gnoack3000@gmail.com \
--cc=hi@alyssa.is \
--cc=horms@kernel.org \
--cc=ivanov.mikhail1@huawei-partners.com \
--cc=jannh@google.com \
--cc=jmorris@namei.org \
--cc=john.johansen@canonical.com \
--cc=konstantin.meskhidze@huawei.com \
--cc=kuniyu@google.com \
--cc=linux-security-module@vger.kernel.org \
--cc=m@maowtm.org \
--cc=matthieu@buffet.re \
--cc=mic@digikod.net \
--cc=netdev@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=samasth.norway.ananda@oracle.com \
--cc=serge@hallyn.com \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.