From nobody Thu Mar 19 03:43:20 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 CE6F030F934; Mon, 16 Feb 2026 13:32:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771248775; cv=none; b=eQVuKAJEq70pXr4odPFOw43ITkHGW57e9BoAnE0QJXn2ie7+qrIyyDNGdjZD0lXftWQxCz7BnIEQnNdwM7OAj3YRHqZSySgEBdQMjdMZSd5TKlfxPzVPC7O/VD0l3hVIdJPIw21eqUf/a3YPCXbddOtS8YgrZOY0WFCVJXf/ErU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771248775; c=relaxed/simple; bh=og9OzjKrpi8J5E7G7hJ+vPxRQ2I1HIq12Wata8xWsm0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IasE0YcJcFTR3aHQzHRCb3WhHyT738+Jz3JAL0fVHYC4vn4Rnaies6Lr6q8Z+EdYP23Izrn23dZWYkhSGH0a8RciamDCYqvm+PNRCgQTlGqgIZLbRfEoqq87KxWspTuMdBdV0i8To63Bx/uhCDG5M10zAtdPnpKceKmVMsG8jcc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=D7ZNZED1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="D7ZNZED1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 169F6C116C6; Mon, 16 Feb 2026 13:32:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771248775; bh=og9OzjKrpi8J5E7G7hJ+vPxRQ2I1HIq12Wata8xWsm0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=D7ZNZED1zVSUgXHnknRdsN5fnqrXmOkp67JAmSwDSe+PK8bQFgt96/kDlQo6vPy+e BtM+EBnrBA2O/wQT8jZWiwz0THc1m2jdshzViEFjOlNKWXKETkMPfJYUVAY/oKuMi/ YRcDj4uqfAisaXLvE2ZqQlmwx2Fl+UuQVZDRR3Q4A+zR0QqncNqtkl1HIUTW8eId3W yG9hHZEZmservuk4/LjGzCfDRM3RUAxC0jqiXoa9nmmHcS4DFx3hpqMZNDPEvzwBwG Xa3Y+eqrTklaWmhpza74vXKPcQ5ZuOpqpn8xVQ2kSwWVwU70MpzjPsF/vmJ982xeN9 Kg/3z4Ayz35Xg== From: Christian Brauner Date: Mon, 16 Feb 2026 14:32:06 +0100 Subject: [PATCH 10/14] xattr,net: support limited amount of extended attributes on sockfs sockets Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260216-work-xattr-socket-v1-10-c2efa4f74cb7@kernel.org> References: <20260216-work-xattr-socket-v1-0-c2efa4f74cb7@kernel.org> In-Reply-To: <20260216-work-xattr-socket-v1-0-c2efa4f74cb7@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Jeff Layton , Josef Bacik , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, Hugh Dickins , linux-mm@kvack.org, Greg Kroah-Hartman , Tejun Heo , Eric Dumazet , Jakub Kicinski , Jann Horn , netdev@vger.kernel.org, Christian Brauner X-Mailer: b4 0.15-dev-47773 X-Developer-Signature: v=1; a=openpgp-sha256; l=5847; i=brauner@kernel.org; h=from:subject:message-id; bh=og9OzjKrpi8J5E7G7hJ+vPxRQ2I1HIq12Wata8xWsm0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWROlomz2jXPdLuwPOdjplbdwIYlMzUXVL7iWrP81ndR0 7p3z7RcOkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACYyfyMjw+4fXYaf2bsnPbg7 c/LP93saJ1y3nx97u7Of58fyldsl/AUZ/tnnXFZP07TV1dp5duaDLW6FUl8e2m9x/W+8nduoa31 nBB8A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Now that we've generalized the infrastructure for user.* xattrs make it possible to set up to 128 user.* extended attributes on a sockfs inode or up to 128kib. kernfs (cgroupfs) has the same limits and it has proven to be quite sufficient for nearly all use-cases. This will allow containers to label sockets and will e.g., be used by systemd and Gnome to find various sockets in containers where high-privilege or more complicated solutions aren't available. Signed-off-by: Christian Brauner Reviewed-by: Jan Kara --- net/socket.c | 119 +++++++++++++++++++++++++++++++++++++++++++++----------= ---- 1 file changed, 92 insertions(+), 27 deletions(-) diff --git a/net/socket.c b/net/socket.c index 136b98c54fb3..7aa94fce7a8b 100644 --- a/net/socket.c +++ b/net/socket.c @@ -315,45 +315,70 @@ static int move_addr_to_user(struct sockaddr_storage = *kaddr, int klen, =20 static struct kmem_cache *sock_inode_cachep __ro_after_init; =20 +struct sockfs_inode { + struct simple_xattrs *xattrs; + struct simple_xattr_limits xattr_limits; + struct socket_alloc; +}; + +static struct sockfs_inode *SOCKFS_I(struct inode *inode) +{ + return container_of(inode, struct sockfs_inode, vfs_inode); +} + static struct inode *sock_alloc_inode(struct super_block *sb) { - struct socket_alloc *ei; + struct sockfs_inode *si; =20 - ei =3D alloc_inode_sb(sb, sock_inode_cachep, GFP_KERNEL); - if (!ei) + si =3D alloc_inode_sb(sb, sock_inode_cachep, GFP_KERNEL); + if (!si) return NULL; - init_waitqueue_head(&ei->socket.wq.wait); - ei->socket.wq.fasync_list =3D NULL; - ei->socket.wq.flags =3D 0; + si->xattrs =3D NULL; + simple_xattr_limits_init(&si->xattr_limits); + + init_waitqueue_head(&si->socket.wq.wait); + si->socket.wq.fasync_list =3D NULL; + si->socket.wq.flags =3D 0; + + si->socket.state =3D SS_UNCONNECTED; + si->socket.flags =3D 0; + si->socket.ops =3D NULL; + si->socket.sk =3D NULL; + si->socket.file =3D NULL; =20 - ei->socket.state =3D SS_UNCONNECTED; - ei->socket.flags =3D 0; - ei->socket.ops =3D NULL; - ei->socket.sk =3D NULL; - ei->socket.file =3D NULL; + return &si->vfs_inode; +} + +static void sock_evict_inode(struct inode *inode) +{ + struct sockfs_inode *si =3D SOCKFS_I(inode); + struct simple_xattrs *xattrs =3D si->xattrs; =20 - return &ei->vfs_inode; + if (xattrs) { + simple_xattrs_free(xattrs, NULL); + kfree(xattrs); + } + clear_inode(inode); } =20 static void sock_free_inode(struct inode *inode) { - struct socket_alloc *ei; + struct sockfs_inode *si =3D SOCKFS_I(inode); =20 - ei =3D container_of(inode, struct socket_alloc, vfs_inode); - kmem_cache_free(sock_inode_cachep, ei); + kmem_cache_free(sock_inode_cachep, si); } =20 static void init_once(void *foo) { - struct socket_alloc *ei =3D (struct socket_alloc *)foo; + struct sockfs_inode *si =3D (struct sockfs_inode *)foo; =20 - inode_init_once(&ei->vfs_inode); + inode_init_once(&si->vfs_inode); } =20 static void init_inodecache(void) { sock_inode_cachep =3D kmem_cache_create("sock_inode_cache", - sizeof(struct socket_alloc), + sizeof(struct sockfs_inode), 0, (SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT | @@ -365,6 +390,7 @@ static void init_inodecache(void) static const struct super_operations sockfs_ops =3D { .alloc_inode =3D sock_alloc_inode, .free_inode =3D sock_free_inode, + .evict_inode =3D sock_evict_inode, .statfs =3D simple_statfs, }; =20 @@ -417,9 +443,48 @@ static const struct xattr_handler sockfs_security_xatt= r_handler =3D { .set =3D sockfs_security_xattr_set, }; =20 +static int sockfs_user_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *suffix, void *value, size_t size) +{ + const char *name =3D xattr_full_name(handler, suffix); + struct simple_xattrs *xattrs; + + xattrs =3D READ_ONCE(SOCKFS_I(inode)->xattrs); + if (!xattrs) + return -ENODATA; + + return simple_xattr_get(xattrs, name, value, size); +} + +static int sockfs_user_xattr_set(const struct xattr_handler *handler, + struct mnt_idmap *idmap, + struct dentry *dentry, struct inode *inode, + const char *suffix, const void *value, + size_t size, int flags) +{ + const char *name =3D xattr_full_name(handler, suffix); + struct sockfs_inode *si =3D SOCKFS_I(inode); + struct simple_xattrs *xattrs; + + xattrs =3D simple_xattrs_lazy_alloc(&si->xattrs, value, flags); + if (IS_ERR_OR_NULL(xattrs)) + return PTR_ERR(xattrs); + + return simple_xattr_set_limited(xattrs, &si->xattr_limits, + name, value, size, flags); +} + +static const struct xattr_handler sockfs_user_xattr_handler =3D { + .prefix =3D XATTR_USER_PREFIX, + .get =3D sockfs_user_xattr_get, + .set =3D sockfs_user_xattr_set, +}; + static const struct xattr_handler * const sockfs_xattr_handlers[] =3D { &sockfs_xattr_handler, &sockfs_security_xattr_handler, + &sockfs_user_xattr_handler, NULL }; =20 @@ -572,26 +637,26 @@ EXPORT_SYMBOL(sockfd_lookup); static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, size_t size) { - ssize_t len; - ssize_t used =3D 0; + struct sockfs_inode *si =3D SOCKFS_I(d_inode(dentry)); + ssize_t len, used; =20 - len =3D security_inode_listsecurity(d_inode(dentry), buffer, size); + len =3D simple_xattr_list(d_inode(dentry), READ_ONCE(si->xattrs), + buffer, size); if (len < 0) return len; - used +=3D len; + + used =3D len; if (buffer) { - if (size < used) - return -ERANGE; buffer +=3D len; + size -=3D len; } =20 - len =3D (XATTR_NAME_SOCKPROTONAME_LEN + 1); + len =3D XATTR_NAME_SOCKPROTONAME_LEN + 1; used +=3D len; if (buffer) { - if (size < used) + if (size < len) return -ERANGE; memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len); - buffer +=3D len; } =20 return used; --=20 2.47.3