Skip to content

Commit eb25e20

Browse files
ArcMutexHashmapl0kod
authored andcommitted
lsm: Add LSM hook security_unix_find
Add an 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: Mickaël Salaün <mic@digikod.net> Cc: Paul Moore <paul@paul-moore.com> Signed-off-by: Justin Suess <utilityemal77@gmail.com> Signed-off-by: Günther Noack <gnoack3000@gmail.com> Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com> Acked-by: Paul Moore <paul@paul-moore.com> Link: https://lore.kernel.org/r/20260327164838.38231-2-gnoack3000@gmail.com Signed-off-by: Mickaël Salaün <mic@digikod.net>
1 parent 64617ec commit eb25e20

4 files changed

Lines changed: 43 additions & 3 deletions

File tree

include/linux/lsm_hook_defs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,11 @@ LSM_HOOK(int, 0, post_notification, const struct cred *w_cred,
317317
LSM_HOOK(int, 0, watch_key, struct key *key)
318318
#endif /* CONFIG_SECURITY && CONFIG_KEY_NOTIFICATIONS */
319319

320+
#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_SECURITY_PATH)
321+
LSM_HOOK(int, 0, unix_find, const struct path *path, struct sock *other,
322+
int flags)
323+
#endif /* CONFIG_SECURITY_NETWORK && CONFIG_SECURITY_PATH */
324+
320325
#ifdef CONFIG_SECURITY_NETWORK
321326
LSM_HOOK(int, 0, unix_stream_connect, struct sock *sock, struct sock *other,
322327
struct sock *newsk)

include/linux/security.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,17 @@ static inline int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
19321932
}
19331933
#endif /* CONFIG_SECURITY_NETWORK */
19341934

1935+
#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_SECURITY_PATH)
1936+
1937+
int security_unix_find(const struct path *path, struct sock *other, int flags);
1938+
1939+
#else /* CONFIG_SECURITY_NETWORK && CONFIG_SECURITY_PATH */
1940+
static inline int security_unix_find(const struct path *path, struct sock *other, int flags)
1941+
{
1942+
return 0;
1943+
}
1944+
#endif /* CONFIG_SECURITY_NETWORK && CONFIG_SECURITY_PATH */
1945+
19351946
#ifdef CONFIG_SECURITY_INFINIBAND
19361947
int security_ib_pkey_access(void *sec, u64 subnet_prefix, u16 pkey);
19371948
int security_ib_endport_manage_subnet(void *sec, const char *name, u8 port_num);

net/unix/af_unix.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,11 +1231,15 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
12311231
goto path_put;
12321232

12331233
err = -EPROTOTYPE;
1234-
if (sk->sk_type == type)
1235-
touch_atime(&path);
1236-
else
1234+
if (sk->sk_type != type)
12371235
goto sock_put;
12381236

1237+
err = security_unix_find(&path, sk, flags);
1238+
if (err)
1239+
goto sock_put;
1240+
1241+
touch_atime(&path);
1242+
12391243
path_put(&path);
12401244

12411245
return sk;

security/security.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4732,6 +4732,26 @@ int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
47324732

47334733
#endif /* CONFIG_SECURITY_NETWORK */
47344734

4735+
#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_SECURITY_PATH)
4736+
/**
4737+
* security_unix_find() - Check if a named AF_UNIX socket can connect
4738+
* @path: path of the socket being connected to
4739+
* @other: peer sock
4740+
* @flags: flags associated with the socket
4741+
*
4742+
* This hook is called to check permissions before connecting to a named
4743+
* AF_UNIX socket. The caller does not hold any locks on @other.
4744+
*
4745+
* Return: Returns 0 if permission is granted.
4746+
*/
4747+
int security_unix_find(const struct path *path, struct sock *other, int flags)
4748+
{
4749+
return call_int_hook(unix_find, path, other, flags);
4750+
}
4751+
EXPORT_SYMBOL(security_unix_find);
4752+
4753+
#endif /* CONFIG_SECURITY_NETWORK && CONFIG_SECURITY_PATH */
4754+
47354755
#ifdef CONFIG_SECURITY_INFINIBAND
47364756
/**
47374757
* security_ib_pkey_access() - Check if access to an IB pkey is allowed

0 commit comments

Comments
 (0)