[RFC PATCH 1/3] af_unix: factor out unix_lookup_bsd_path()
John Ericson <[email protected]>
| Newsgroups | org.kernel.vger.linux-security-module,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
From: John Ericson <[email protected]> Split the inode -> sock mapping out of `unix_find_bsd()` into a new helper, `unix_lookup_bsd_path()`: given an already-resolved `struct path`, check it is a socket, look the bound socket up by inode, and check its type, returning a held `struct sock` (or an `ERR_PTR`). `unix_find_bsd()` keeps doing the path resolution, the `MAY_WRITE` permission check, the `security_unix_find()` LSM hook and `touch_atime()`, and calls the helper for the lookup. No functional change. The function documentation anticipates (in an example) the way this will be used later in the patch series. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: John Ericson <[email protected]> --- include/net/af_unix.h | 1 + net/unix/af_unix.c | 50 ++++++++++++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 34f53dde65ce..fe4547508af1 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -14,6 +14,7 @@ #if IS_ENABLED(CONFIG_UNIX) struct unix_sock *unix_get_socket(struct file *filp); +struct sock *unix_lookup_bsd_path(const struct path *path, int type); #else static inline struct unix_sock *unix_get_socket(struct file *filp) { diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index f7a9d55eee8a..3270299238c4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1185,10 +1185,43 @@ static int unix_release(struct socket *sock) return 0; } +/** + * unix_lookup_bsd_path - find the AF_UNIX socket bound at a resolved path + * @path: a path the caller has already resolved under its own policy + * @type: required socket type (SOCK_STREAM/SOCK_SEQPACKET/SOCK_DGRAM) + * + * Unlike the connect(2) lookup, this performs no path resolution and no + * DAC or LSM check of its own: the caller is responsible for having + * resolved @path with whatever policy is appropriate. Used by kernel + * callers (e.g. coredump-to-socket) that must resolve the path under + * their own root and credentials rather than the current task's. + * + * Returns a held sock, or an ERR_PTR. + */ +struct sock *unix_lookup_bsd_path(const struct path *path, int type) +{ + struct inode *inode = d_backing_inode(path->dentry); + struct sock *sk; + + if (!S_ISSOCK(inode->i_mode)) + return ERR_PTR(-ECONNREFUSED); + + sk = unix_find_socket_byinode(inode); + if (!sk) + return ERR_PTR(-ECONNREFUSED); + + if (sk->sk_type != type) { + sock_put(sk); + return ERR_PTR(-EPROTOTYPE); + } + + return sk; +} +EXPORT_SYMBOL_GPL(unix_lookup_bsd_path); + static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len, int type, int flags) { - struct inode *inode; struct path path; struct sock *sk; int err; @@ -1219,18 +1252,11 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len, goto path_put; } - err = -ECONNREFUSED; - inode = d_backing_inode(path.dentry); - if (!S_ISSOCK(inode->i_mode)) + sk = unix_lookup_bsd_path(&path, type); + if (IS_ERR(sk)) { + err = PTR_ERR(sk); goto path_put; - - sk = unix_find_socket_byinode(inode); - if (!sk) - goto path_put; - - err = -EPROTOTYPE; - if (sk->sk_type != type) - goto sock_put; + } err = security_unix_find(&path, sk, flags); if (err) -- 2.54.0