diff options
| author | Mickaël Salaün <mic@digikod.net> | 2026-07-03 17:27:48 +0200 |
|---|---|---|
| committer | Mickaël Salaün <mic@digikod.net> | 2026-08-14 12:38:26 +0200 |
| commit | 07dca8ef89fc92b89ce36d9727547b10d8e840d6 (patch) | |
| tree | 3e82df4568dde22bcf65950d1b87cf521ed62eda /security | |
| parent | 075b74841bd0065a3bda3440873c747938e69b68 (diff) | |
landlock: Harden sock_is_scoped() against file-less sockets
sock_is_scoped() dereferences other->sk_socket->file->f_cred to read the
peer's Landlock domain when evaluating
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET, without first checking that the
peer has a backing socket and file. hook_unix_find() performs the same
dereference for LANDLOCK_ACCESS_FS_RESOLVE_UNIX and does guard it.
Guard it here too and treat a peer with no backing file, such as a
kernel socket created by sock_create_kern(), as unscoped.
This is defensive hardening, not a fix for a reachable bug. The
unix_stream_connect() and unix_may_send() hooks run with the peer held
under unix_state_lock() and only after the AF_UNIX core has excluded
SOCK_DEAD, and no in-tree code binds a file-less AF_UNIX socket to an
abstract address, so other->sk_socket->file is always valid at these
call sites today.
Cc: Günther Noack <gnoack@google.com>
Link: https://patch.msgid.link/20260703152750.2022878-1-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Diffstat (limited to 'security')
| -rw-r--r-- | security/landlock/task.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/security/landlock/task.c b/security/landlock/task.c index 360d226d0f51..55522a601367 100644 --- a/security/landlock/task.c +++ b/security/landlock/task.c @@ -242,6 +242,17 @@ static bool sock_is_scoped(struct sock *const other, /* The credentials will not change. */ lockdep_assert_held(&unix_sk(other)->lock); + + /* + * A live kernel socket (e.g. from sock_create_kern()) has no backing + * file, hence no Landlock domain, so treat it as unscoped. The + * sk_socket check only guards that dereference; sk_socket is NULL + * solely for a dead peer, which the caller already excludes under the + * held lock, so no separate SOCK_DEAD check is needed. + */ + if (unlikely(!other->sk_socket || !other->sk_socket->file)) + return false; + dom_other = landlock_cred(other->sk_socket->file->f_cred)->domain; return domain_is_scoped(domain, dom_other, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); |
