From nobody Wed Oct 8 23:42:45 2025 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 39FD4136348; Mon, 23 Jun 2025 06:39:07 +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=1750660748; cv=none; b=JIS6I3UrDS823Q7VCp1v8lJMzvtYCC8TXcBiBUWjkxH2e5jHwfHOnsZa+jojndCq8VOGPP/wK2CFl/aPulfPoehjIgH5TQAI5qw5vKeBEqcj7Dt6+UxrjsKVC9CQwuy8FbaNPBGJ3cyYKkc3NxzjRL2YX02v6iN5pWFFNaX3h4M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750660748; c=relaxed/simple; bh=Iq4V29IJHRN+HGdtZbJJFkh/3xipxCP1mOjzQxBtJ9U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WMkbfSNzBGfKs41FHio28660vJPRDcCYkL0xF1LnvdT3KH3RNm1Rq7AK92750HWACKDEfuou10qYmU/LrhepH1bEUhBDbLc4I1ZooQGi7ebi6R5kuvUEI2SXPjTpAqjGgNuC9JQpW+FjSZns+vdHGt/VfGhlTLOUBJ9/omXXHdc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RU7wYbIy; 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="RU7wYbIy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CF563C4CEED; Mon, 23 Jun 2025 06:39:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750660747; bh=Iq4V29IJHRN+HGdtZbJJFkh/3xipxCP1mOjzQxBtJ9U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RU7wYbIyMAI4sSqHAPFv23D87d2Qh0iOsz0sMgK4TZ9l2GgLhx+et25IaDrFCd2Dp 6/Ago/J17uOKbzspnZLP08UaX28i9Uti2dyL1FfV5Ez2P5uH/dYGrP8mdJcis7RO1z qcgaxrCHen75HRh0GCgj62j/nRwIFqNEgND66bEt82+hbiivkOrau0/WqBdKEyLoao lZBp9iub+qLJ/eyvkdhdR5pBBXTS0QlkvCQYi7aU9XwkMpnuWfNeeHR6CHJobZz/GY XYjwHJa+tt2F/7D5FDGG/MLEjcCh18In8Jgz3G9xk1P3h1Y/HY+xbiDbvP0KVg2Dpo Z+LgyJAKj1xPg== From: Song Liu To: bpf@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org Cc: kernel-team@meta.com, andrii@kernel.org, eddyz87@gmail.com, ast@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz, kpsingh@kernel.org, mattbobrowski@google.com, amir73il@gmail.com, gregkh@linuxfoundation.org, tj@kernel.org, daan.j.demeyer@gmail.com, Song Liu Subject: [PATCH v3 bpf-next 1/4] kernfs: remove iattr_mutex Date: Sun, 22 Jun 2025 23:38:51 -0700 Message-ID: <20250623063854.1896364-2-song@kernel.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250623063854.1896364-1-song@kernel.org> References: <20250623063854.1896364-1-song@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Christian Brauner All allocations of struct kernfs_iattrs are serialized through a global mutex. Simply do a racy allocation and let the first one win. I bet most callers are under inode->i_rwsem anyway and it wouldn't be needed but let's not require that. Signed-off-by: Christian Brauner Acked-by: Greg Kroah-Hartman Acked-by: Tejun Heo Signed-off-by: Song Liu --- fs/kernfs/inode.c | 74 +++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index b83054da68b3..f4b73b9482b7 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -24,45 +24,46 @@ static const struct inode_operations kernfs_iops =3D { .listxattr =3D kernfs_iop_listxattr, }; =20 -static struct kernfs_iattrs *__kernfs_iattrs(struct kernfs_node *kn, int a= lloc) +static struct kernfs_iattrs *__kernfs_iattrs(struct kernfs_node *kn, bool = alloc) { - static DEFINE_MUTEX(iattr_mutex); - struct kernfs_iattrs *ret; + struct kernfs_iattrs *ret __free(kfree) =3D NULL; + struct kernfs_iattrs *attr; =20 - mutex_lock(&iattr_mutex); + attr =3D READ_ONCE(kn->iattr); + if (attr || !alloc) + return attr; =20 - if (kn->iattr || !alloc) - goto out_unlock; - - kn->iattr =3D kmem_cache_zalloc(kernfs_iattrs_cache, GFP_KERNEL); - if (!kn->iattr) - goto out_unlock; + ret =3D kmem_cache_zalloc(kernfs_iattrs_cache, GFP_KERNEL); + if (!ret) + return NULL; =20 /* assign default attributes */ - kn->iattr->ia_uid =3D GLOBAL_ROOT_UID; - kn->iattr->ia_gid =3D GLOBAL_ROOT_GID; - - ktime_get_real_ts64(&kn->iattr->ia_atime); - kn->iattr->ia_mtime =3D kn->iattr->ia_atime; - kn->iattr->ia_ctime =3D kn->iattr->ia_atime; - - simple_xattrs_init(&kn->iattr->xattrs); - atomic_set(&kn->iattr->nr_user_xattrs, 0); - atomic_set(&kn->iattr->user_xattr_size, 0); -out_unlock: - ret =3D kn->iattr; - mutex_unlock(&iattr_mutex); - return ret; + ret->ia_uid =3D GLOBAL_ROOT_UID; + ret->ia_gid =3D GLOBAL_ROOT_GID; + + ktime_get_real_ts64(&ret->ia_atime); + ret->ia_mtime =3D ret->ia_atime; + ret->ia_ctime =3D ret->ia_atime; + + simple_xattrs_init(&ret->xattrs); + atomic_set(&ret->nr_user_xattrs, 0); + atomic_set(&ret->user_xattr_size, 0); + + /* If someone raced us, recognize it. */ + if (!try_cmpxchg(&kn->iattr, &attr, ret)) + return READ_ONCE(kn->iattr); + + return no_free_ptr(ret); } =20 static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) { - return __kernfs_iattrs(kn, 1); + return __kernfs_iattrs(kn, true); } =20 static struct kernfs_iattrs *kernfs_iattrs_noalloc(struct kernfs_node *kn) { - return __kernfs_iattrs(kn, 0); + return __kernfs_iattrs(kn, false); } =20 int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) @@ -141,9 +142,9 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, cha= r *buf, size_t size) struct kernfs_node *kn =3D kernfs_dentry_node(dentry); struct kernfs_iattrs *attrs; =20 - attrs =3D kernfs_iattrs(kn); + attrs =3D kernfs_iattrs_noalloc(kn); if (!attrs) - return -ENOMEM; + return -ENODATA; =20 return simple_xattr_list(d_inode(dentry), &attrs->xattrs, buf, size); } @@ -166,9 +167,10 @@ static inline void set_inode_attr(struct inode *inode, =20 static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *ino= de) { - struct kernfs_iattrs *attrs =3D kn->iattr; + struct kernfs_iattrs *attrs; =20 inode->i_mode =3D kn->mode; + attrs =3D kernfs_iattrs_noalloc(kn); if (attrs) /* * kernfs_node has non-default attributes get them from @@ -306,7 +308,9 @@ int kernfs_xattr_set(struct kernfs_node *kn, const char= *name, const void *value, size_t size, int flags) { struct simple_xattr *old_xattr; - struct kernfs_iattrs *attrs =3D kernfs_iattrs(kn); + struct kernfs_iattrs *attrs; + + attrs =3D kernfs_iattrs(kn); if (!attrs) return -ENOMEM; =20 @@ -345,8 +349,9 @@ static int kernfs_vfs_user_xattr_add(struct kernfs_node= *kn, struct simple_xattrs *xattrs, const void *value, size_t size, int flags) { - atomic_t *sz =3D &kn->iattr->user_xattr_size; - atomic_t *nr =3D &kn->iattr->nr_user_xattrs; + struct kernfs_iattrs *attr =3D kernfs_iattrs_noalloc(kn); + atomic_t *sz =3D &attr->user_xattr_size; + atomic_t *nr =3D &attr->nr_user_xattrs; struct simple_xattr *old_xattr; int ret; =20 @@ -384,8 +389,9 @@ static int kernfs_vfs_user_xattr_rm(struct kernfs_node = *kn, struct simple_xattrs *xattrs, const void *value, size_t size, int flags) { - atomic_t *sz =3D &kn->iattr->user_xattr_size; - atomic_t *nr =3D &kn->iattr->nr_user_xattrs; + struct kernfs_iattrs *attr =3D kernfs_iattrs(kn); + atomic_t *sz =3D &attr->user_xattr_size; + atomic_t *nr =3D &attr->nr_user_xattrs; struct simple_xattr *old_xattr; =20 old_xattr =3D simple_xattr_set(xattrs, full_name, value, size, flags); --=20 2.47.1 From nobody Wed Oct 8 23:42:45 2025 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 AFFE9136348; Mon, 23 Jun 2025 06:39:13 +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=1750660753; cv=none; b=m2MDFWlNuFVBDhd7Anlo0v6FkbUjKs+uEiSOXl/vxO/euLHNJzqIGZEefQfTJQW6XYj0YpkBd1T6YQxnwvS4FKEMjQu9U4Z4IaHw/dKsLpdkeQHcuShUTp8L78Mc4uvj3Kv34ndhfXSyHWMrSSqX2Y0hdkaOFUcbSnDKKWTj4Lc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750660753; c=relaxed/simple; bh=0Jo3+klb7sn+Ci+xFRJd1JpVX2+HyuPav+mXSbeFpyg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZuDadEBo064G75Lza65Yb7a/IGRSnyZZ9x86FG7K9jgV+Iv5jo+BcwGvkJo5+kf2Uq4j7o+/4DiHp0HMVqIRDG5b9xarjSXJn2mnxhJtoO0Nyaf436PwU0TLj55CQYIo8SVymTi93RalPungYBOlUeawxpP5mFR7F+TJ4r3Fzy8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HLuuMss4; 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="HLuuMss4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B20B5C4CEED; Mon, 23 Jun 2025 06:39:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750660753; bh=0Jo3+klb7sn+Ci+xFRJd1JpVX2+HyuPav+mXSbeFpyg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HLuuMss4M9D4QRBc7/VWf6NGL+3i7HiOgDoJxTM02s54Z1DxwcPzujdwTg15qjA2E EJHg/UuRL3X2JBYUNyhVSTqDUxzrdTuUwE09KZFixpnBy0Bxn7iY59iLo0kbpbZjGp ljSngmZWE+Om3hkNE7/zMnvuJN5dPiR8hM4UeL4cX0cBSX6v2jiL/R3SuFYkHflpfN +1TJXx7LEYUj2RNIDov++fvdIfRcKDGDuowbmh1uTqoS9EDDdqpjZSG1CP4sfDjCwu WGwPQSv2/0GfNbuqyr5W0IN668U/V89TgZxzXWCfzOocEKqapFcotfFa2NKZNpQYRe t+qpQYvK2oHug== From: Song Liu To: bpf@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org Cc: kernel-team@meta.com, andrii@kernel.org, eddyz87@gmail.com, ast@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz, kpsingh@kernel.org, mattbobrowski@google.com, amir73il@gmail.com, gregkh@linuxfoundation.org, tj@kernel.org, daan.j.demeyer@gmail.com, Song Liu Subject: [PATCH v3 bpf-next 2/4] bpf: Introduce bpf_cgroup_read_xattr to read xattr of cgroup's node Date: Sun, 22 Jun 2025 23:38:52 -0700 Message-ID: <20250623063854.1896364-3-song@kernel.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250623063854.1896364-1-song@kernel.org> References: <20250623063854.1896364-1-song@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" BPF programs, such as LSM and sched_ext, would benefit from tags on cgroups. One common practice to apply such tags is to set xattrs on cgroupfs folders. Introduce kfunc bpf_cgroup_read_xattr, which allows reading cgroup's xattr. Note that, we already have bpf_get_[file|dentry]_xattr. However, these two APIs are not ideal for reading cgroupfs xattrs, because: 1) These two APIs only works in sleepable contexts; 2) There is no kfunc that matches current cgroup to cgroupfs dentry. bpf_cgroup_read_xattr is generic and can be useful for many program types. It is also safe, because it requires trusted or rcu protected argument (KF_RCU). Therefore, we make it available to all program types. Signed-off-by: Song Liu Acked-by: Tejun Heo --- fs/bpf_fs_kfuncs.c | 34 ++++++++++++++++++++++++++++++++++ kernel/bpf/helpers.c | 3 +++ 2 files changed, 37 insertions(+) diff --git a/fs/bpf_fs_kfuncs.c b/fs/bpf_fs_kfuncs.c index 08412532db1b..1e36a12b88f7 100644 --- a/fs/bpf_fs_kfuncs.c +++ b/fs/bpf_fs_kfuncs.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include =20 @@ -322,6 +323,39 @@ __bpf_kfunc int bpf_remove_dentry_xattr(struct dentry = *dentry, const char *name_ return ret; } =20 +#ifdef CONFIG_CGROUPS +/** + * bpf_cgroup_read_xattr - read xattr of a cgroup's node in cgroupfs + * @cgroup: cgroup to get xattr from + * @name__str: name of the xattr + * @value_p: output buffer of the xattr value + * + * Get xattr *name__str* of *cgroup* and store the output in *value_ptr*. + * + * For security reasons, only *name__str* with prefix "user." is allowed. + * + * Return: length of the xattr value on success, a negative value on error. + */ +__bpf_kfunc int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *n= ame__str, + struct bpf_dynptr *value_p) +{ + struct bpf_dynptr_kern *value_ptr =3D (struct bpf_dynptr_kern *)value_p; + u32 value_len; + void *value; + + /* Only allow reading "user.*" xattrs */ + if (strncmp(name__str, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) + return -EPERM; + + value_len =3D __bpf_dynptr_size(value_ptr); + value =3D __bpf_dynptr_data_rw(value_ptr, value_len); + if (!value) + return -EINVAL; + + return kernfs_xattr_get(cgroup->kn, name__str, value, value_len); +} +#endif /* CONFIG_CGROUPS */ + __bpf_kfunc_end_defs(); =20 BTF_KFUNCS_START(bpf_fs_kfunc_set_ids) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index b71e428ad936..9ff1b4090289 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -3397,6 +3397,9 @@ BTF_ID_FLAGS(func, bpf_iter_dmabuf_next, KF_ITER_NEXT= | KF_RET_NULL | KF_SLEEPAB BTF_ID_FLAGS(func, bpf_iter_dmabuf_destroy, KF_ITER_DESTROY | KF_SLEEPABLE) #endif BTF_ID_FLAGS(func, __bpf_trap) +#ifdef CONFIG_CGROUPS +BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU) +#endif BTF_KFUNCS_END(common_btf_ids) =20 static const struct btf_kfunc_id_set common_kfunc_set =3D { --=20 2.47.1 From nobody Wed Oct 8 23:42:45 2025 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 5D0C7136348; Mon, 23 Jun 2025 06:39:19 +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=1750660759; cv=none; b=BlIRf85Ajx8Xobs3oV267NmWIoHNRNQx+wCvX8RKWynlt6esuQvmOiKXtxfIDrpSyl1tf3SvsSKfM3zS1Qm5TTr82I6eAw1E2ljJS8TbY8NQVq2whpsLKA/bVpCPg6lY3IWxnhBl4LDTI7mx2MLtCWZKD6xlNfoAyo+h+MtRQvA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750660759; c=relaxed/simple; bh=BEJZRN76m+6IEQPpBHY905TwGMpPvyUC5d/zGM477GM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rzJDY8pPYLiCCB1FVWgLBTDeJlfuvm3h6Aeae6yPoC4J5/1oMQIEHTC0ZOkmKWOUwdbLQnlLEYgKzpgRVOqvDw8XJtoKWRL97ErPqUxs15RjRyS38dVf45lJY/5DYM+ZxbcFIdQRzYRTrJr4MMGLhhNktG7TaMKptWd3poXluPo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eZz55gwQ; 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="eZz55gwQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A365C4CEED; Mon, 23 Jun 2025 06:39:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750660759; bh=BEJZRN76m+6IEQPpBHY905TwGMpPvyUC5d/zGM477GM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eZz55gwQzhVAj9SiiLd1VjSX7RNKyvtfYkU8MNYyvTwkhQsl9Zu2UUHLcEx6uwrPs oSzGbLs029uaMehBdlNIcdIk99yuaBggfGLyV/sbmK9GLlZsLEr5cciGMtjTVzbbFL aqNLqo9al9spafz0YP4rz43XOmIGOCGdIrz7osdIRVzABc1ikFeP5fAVS+fus2cI7P HJiX28zTPzWCPeqdtLWJII+MNwNMIsr/9LoLhPSqZIy7NN43P2Nh6VSsKM5e9Fv76j FU1Vh0ypxsiyWe7HjfLNhj2CZmHhJJG7dyUgBN6ogo7deT6rxAunV9NmMMWC3SL9bG +qGxrsPoRAyHQ== From: Song Liu To: bpf@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org Cc: kernel-team@meta.com, andrii@kernel.org, eddyz87@gmail.com, ast@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz, kpsingh@kernel.org, mattbobrowski@google.com, amir73il@gmail.com, gregkh@linuxfoundation.org, tj@kernel.org, daan.j.demeyer@gmail.com, Song Liu Subject: [PATCH v3 bpf-next 3/4] bpf: Mark cgroup_subsys_state->cgroup RCU safe Date: Sun, 22 Jun 2025 23:38:53 -0700 Message-ID: <20250623063854.1896364-4-song@kernel.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250623063854.1896364-1-song@kernel.org> References: <20250623063854.1896364-1-song@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Mark struct cgroup_subsys_state->cgroup as safe under RCU read lock. This will enable accessing css->cgroup from a bpf css iterator. Signed-off-by: Song Liu --- kernel/bpf/verifier.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 279a64933262..e2f53dc8766a 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -7058,6 +7058,10 @@ BTF_TYPE_SAFE_RCU(struct css_set) { struct cgroup *dfl_cgrp; }; =20 +BTF_TYPE_SAFE_RCU(struct cgroup_subsys_state) { + struct cgroup *cgroup; +}; + /* RCU trusted: these fields are trusted in RCU CS and can be NULL */ BTF_TYPE_SAFE_RCU_OR_NULL(struct mm_struct) { struct file __rcu *exe_file; @@ -7108,6 +7112,7 @@ static bool type_is_rcu(struct bpf_verifier_env *env, BTF_TYPE_EMIT(BTF_TYPE_SAFE_RCU(struct task_struct)); BTF_TYPE_EMIT(BTF_TYPE_SAFE_RCU(struct cgroup)); BTF_TYPE_EMIT(BTF_TYPE_SAFE_RCU(struct css_set)); + BTF_TYPE_EMIT(BTF_TYPE_SAFE_RCU(struct cgroup_subsys_state)); =20 return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, "__= safe_rcu"); } --=20 2.47.1 From nobody Wed Oct 8 23:42:45 2025 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 83798136348; Mon, 23 Jun 2025 06:39:25 +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=1750660765; cv=none; b=PGr6ejATyhhYdJatO5NCQIU5DFb1A+uDVv4EXG0iKgz4X8JRwpDYQHZIWpLhNTffVNgXtGSntehxBEexYQpbMbg96XPso21eWqbhYxf+SYfybHdGB5a+JtdxEKj6ndLovdgT4ZA50ClK2wHADCJjsZs7z3vgJaenwR6Rrq7XK60= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750660765; c=relaxed/simple; bh=RcUGPc+CuikCuze+InFNKjdzSi3ukfT0DGxKJP07Vco=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IhZKRHsc8Ky1gF32cKjbJPRQaN7NcNK3FGeolarsoty/nYZmhkRy5qC7RGtiilcHxgUvFSICKWuTufl3Ax6tDL/yDQBldLmyE3FiuB7pnOENxENtYN5tfRFP0MLdUm11nqcg0Ucs60rX+SDDZby7vgnvTTflN4ZqNROVdfMJ4TM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JS4OWkcr; 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="JS4OWkcr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2CFC3C4CEED; Mon, 23 Jun 2025 06:39:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750660765; bh=RcUGPc+CuikCuze+InFNKjdzSi3ukfT0DGxKJP07Vco=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JS4OWkcr+Irv3m69dm0SIirYZcN8qYX4Raz0oEZuTcWU3LSFA48MZ2hE5ZZ7Z8Mzj glhLBrzjLqTfwyl1w1yVWDRQ+Kb4p0VOOe4K4Fu95z18RExJIkyrFYFEnxOPF3vAGf YE0+Q61os1v7R6WR/XNquj1xAyiIshjbkafrKBqJ3ElfdMACYwKksEHb1MaqLABfAl vKyLw9r2n2OYkNRFLGDJMUS2Rx5z4QpEMIdlHLjVXvyXHgI+fFuFEDSM1uEhUf9+8c +BAHbXwCbvOBpBrMzZDVsuuqKNTzFK7fxlf0uDm7b5KVjPKT3g4WuT7eG/EQWVl9OI Le+0JbRKhrdMw== From: Song Liu To: bpf@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org Cc: kernel-team@meta.com, andrii@kernel.org, eddyz87@gmail.com, ast@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz, kpsingh@kernel.org, mattbobrowski@google.com, amir73il@gmail.com, gregkh@linuxfoundation.org, tj@kernel.org, daan.j.demeyer@gmail.com, Song Liu Subject: [PATCH v3 bpf-next 4/4] selftests/bpf: Add tests for bpf_cgroup_read_xattr Date: Sun, 22 Jun 2025 23:38:54 -0700 Message-ID: <20250623063854.1896364-5-song@kernel.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250623063854.1896364-1-song@kernel.org> References: <20250623063854.1896364-1-song@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add tests for different scenarios with bpf_cgroup_read_xattr: 1. Read cgroup xattr from bpf_cgroup_from_id; 2. Read cgroup xattr from bpf_cgroup_ancestor; 3. Read cgroup xattr from css_iter; 4. Use bpf_cgroup_read_xattr in LSM hook security_socket_connect. 5. Use bpf_cgroup_read_xattr in cgroup program. Signed-off-by: Song Liu --- .../testing/selftests/bpf/bpf_experimental.h | 3 + .../selftests/bpf/prog_tests/cgroup_xattr.c | 145 ++++++++++++++++ .../selftests/bpf/progs/cgroup_read_xattr.c | 158 ++++++++++++++++++ .../selftests/bpf/progs/read_cgroupfs_xattr.c | 60 +++++++ 4 files changed, 366 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/cgroup_xattr.c create mode 100644 tools/testing/selftests/bpf/progs/cgroup_read_xattr.c create mode 100644 tools/testing/selftests/bpf/progs/read_cgroupfs_xattr.c diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing= /selftests/bpf/bpf_experimental.h index 5e512a1d09d1..da7e230f2781 100644 --- a/tools/testing/selftests/bpf/bpf_experimental.h +++ b/tools/testing/selftests/bpf/bpf_experimental.h @@ -596,4 +596,7 @@ extern int bpf_iter_dmabuf_new(struct bpf_iter_dmabuf *= it) __weak __ksym; extern struct dma_buf *bpf_iter_dmabuf_next(struct bpf_iter_dmabuf *it) __= weak __ksym; extern void bpf_iter_dmabuf_destroy(struct bpf_iter_dmabuf *it) __weak __k= sym; =20 +extern int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__= str, + struct bpf_dynptr *value_p) __weak __ksym; + #endif diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_xattr.c b/tools/= testing/selftests/bpf/prog_tests/cgroup_xattr.c new file mode 100644 index 000000000000..87978a0f7eb7 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/cgroup_xattr.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "read_cgroupfs_xattr.skel.h" +#include "cgroup_read_xattr.skel.h" + +#define CGROUP_FS_ROOT "/sys/fs/cgroup/" +#define CGROUP_FS_PARENT CGROUP_FS_ROOT "foo/" +#define CGROUP_FS_CHILD CGROUP_FS_PARENT "bar/" + +static int move_pid_to_cgroup(const char *cgroup_folder, pid_t pid) +{ + char filename[128]; + char pid_str[64]; + int procs_fd; + int ret; + + snprintf(filename, sizeof(filename), "%scgroup.procs", cgroup_folder); + snprintf(pid_str, sizeof(pid_str), "%d", pid); + + procs_fd =3D open(filename, O_WRONLY | O_APPEND); + if (!ASSERT_OK_FD(procs_fd, "open")) + return -1; + + ret =3D write(procs_fd, pid_str, strlen(pid_str)); + close(procs_fd); + if (!ASSERT_GT(ret, 0, "write cgroup.procs")) + return -1; + return 0; +} + +static void reset_cgroups_and_lo(void) +{ + rmdir(CGROUP_FS_CHILD); + rmdir(CGROUP_FS_PARENT); + system("ip addr del 1.1.1.1/32 dev lo"); + system("ip link set dev lo down"); +} + +static const char xattr_value_a[] =3D "bpf_selftest_value_a"; +static const char xattr_value_b[] =3D "bpf_selftest_value_b"; +static const char xattr_name[] =3D "user.bpf_test"; + +static int setup_cgroups_and_lo(void) +{ + int err; + + err =3D mkdir(CGROUP_FS_PARENT, 0755); + if (!ASSERT_OK(err, "mkdir 1")) + goto error; + err =3D mkdir(CGROUP_FS_CHILD, 0755); + if (!ASSERT_OK(err, "mkdir 2")) + goto error; + + err =3D setxattr(CGROUP_FS_PARENT, xattr_name, xattr_value_a, + strlen(xattr_value_a) + 1, 0); + if (!ASSERT_OK(err, "setxattr 1")) + goto error; + + err =3D setxattr(CGROUP_FS_CHILD, xattr_name, xattr_value_b, + strlen(xattr_value_b) + 1, 0); + if (!ASSERT_OK(err, "setxattr 2")) + goto error; + + err =3D system("ip link set dev lo up"); + if (!ASSERT_OK(err, "lo up")) + goto error; + + err =3D system("ip addr add 1.1.1.1 dev lo"); + if (!ASSERT_OK(err, "lo addr v4")) + goto error; + + err =3D write_sysctl("/proc/sys/net/ipv4/ping_group_range", "0 0"); + if (!ASSERT_OK(err, "write_sysctl")) + goto error; + + return 0; +error: + reset_cgroups_and_lo(); + return err; +} + +static void test_read_cgroup_xattr(void) +{ + struct sockaddr_in sa4 =3D { + .sin_family =3D AF_INET, + .sin_addr.s_addr =3D htonl(INADDR_LOOPBACK), + }; + struct read_cgroupfs_xattr *skel =3D NULL; + pid_t pid =3D gettid(); + int sock_fd =3D -1; + int connect_fd =3D -1; + + if (!ASSERT_OK(setup_cgroups_and_lo(), "setup_cgroups_and_lo")) + return; + if (!ASSERT_OK(move_pid_to_cgroup(CGROUP_FS_CHILD, pid), + "move_pid_to_cgroup")) + goto out; + + skel =3D read_cgroupfs_xattr__open_and_load(); + if (!ASSERT_OK_PTR(skel, "read_cgroupfs_xattr__open_and_load")) + goto out; + + skel->bss->target_pid =3D pid; + + if (!ASSERT_OK(read_cgroupfs_xattr__attach(skel), "read_cgroupfs_xattr__a= ttach")) + goto out; + + sock_fd =3D socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); + if (!ASSERT_OK_FD(sock_fd, "sock create")) + goto out; + + connect_fd =3D connect(sock_fd, &sa4, sizeof(sa4)); + if (!ASSERT_OK_FD(connect_fd, "connect 1")) + goto out; + close(connect_fd); + + ASSERT_TRUE(skel->bss->found_value_a, "found_value_a"); + ASSERT_TRUE(skel->bss->found_value_b, "found_value_b"); + +out: + close(connect_fd); + close(sock_fd); + read_cgroupfs_xattr__destroy(skel); + move_pid_to_cgroup(CGROUP_FS_ROOT, pid); + reset_cgroups_and_lo(); +} + +void test_cgroup_xattr(void) +{ + RUN_TESTS(cgroup_read_xattr); + + if (test__start_subtest("read_cgroupfs_xattr")) + test_read_cgroup_xattr(); +} diff --git a/tools/testing/selftests/bpf/progs/cgroup_read_xattr.c b/tools/= testing/selftests/bpf/progs/cgroup_read_xattr.c new file mode 100644 index 000000000000..092db1d0435e --- /dev/null +++ b/tools/testing/selftests/bpf/progs/cgroup_read_xattr.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ + +#include +#include +#include +#include +#include "bpf_experimental.h" +#include "bpf_misc.h" + +char _license[] SEC("license") =3D "GPL"; + +char value[16]; + +static __always_inline void read_xattr(struct cgroup *cgroup) +{ + struct bpf_dynptr value_ptr; + + bpf_dynptr_from_mem(value, sizeof(value), 0, &value_ptr); + bpf_cgroup_read_xattr(cgroup, "user.bpf_test", + &value_ptr); +} + +SEC("lsm.s/socket_connect") +__success +int BPF_PROG(trusted_cgroup_ptr_sleepable) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup *cgrp; + + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + return 0; + + read_xattr(cgrp); + bpf_cgroup_release(cgrp); + return 0; +} + +SEC("lsm/socket_connect") +__success +int BPF_PROG(trusted_cgroup_ptr_non_sleepable) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup *cgrp; + + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + return 0; + + read_xattr(cgrp); + bpf_cgroup_release(cgrp); + return 0; +} + +SEC("lsm/socket_connect") +__success +int BPF_PROG(use_css_iter_non_sleepable) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup_subsys_state *css; + struct cgroup *cgrp; + + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + return 0; + + bpf_for_each(css, css, &cgrp->self, BPF_CGROUP_ITER_ANCESTORS_UP) + read_xattr(css->cgroup); + + bpf_cgroup_release(cgrp); + return 0; +} + +SEC("lsm.s/socket_connect") +__failure __msg("expected an RCU CS") +int BPF_PROG(use_css_iter_sleepable_missing_rcu_lock) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup_subsys_state *css; + struct cgroup *cgrp; + + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + return 0; + + bpf_for_each(css, css, &cgrp->self, BPF_CGROUP_ITER_ANCESTORS_UP) + read_xattr(css->cgroup); + + bpf_cgroup_release(cgrp); + return 0; +} + +SEC("lsm.s/socket_connect") +__success +int BPF_PROG(use_css_iter_sleepable_with_rcu_lock) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup_subsys_state *css; + struct cgroup *cgrp; + + bpf_rcu_read_lock(); + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + goto out; + + bpf_for_each(css, css, &cgrp->self, BPF_CGROUP_ITER_ANCESTORS_UP) + read_xattr(css->cgroup); + + bpf_cgroup_release(cgrp); +out: + bpf_rcu_read_unlock(); + return 0; +} + +SEC("lsm/socket_connect") +__success +int BPF_PROG(use_bpf_cgroup_ancestor) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup *cgrp, *ancestor; + + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + return 0; + + ancestor =3D bpf_cgroup_ancestor(cgrp, 1); + if (!ancestor) + goto out; + + read_xattr(cgrp); + bpf_cgroup_release(ancestor); +out: + bpf_cgroup_release(cgrp); + return 0; +} + +SEC("cgroup/sendmsg4") +__success +int BPF_PROG(cgroup_skb) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup *cgrp, *ancestor; + + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + return 0; + + ancestor =3D bpf_cgroup_ancestor(cgrp, 1); + if (!ancestor) + goto out; + + read_xattr(cgrp); + bpf_cgroup_release(ancestor); +out: + bpf_cgroup_release(cgrp); + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/read_cgroupfs_xattr.c b/tool= s/testing/selftests/bpf/progs/read_cgroupfs_xattr.c new file mode 100644 index 000000000000..855f85fc5522 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/read_cgroupfs_xattr.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ + +#include +#include +#include +#include +#include "bpf_experimental.h" + +char _license[] SEC("license") =3D "GPL"; + +pid_t target_pid =3D 0; + +char xattr_value[64]; +static const char expected_value_a[] =3D "bpf_selftest_value_a"; +static const char expected_value_b[] =3D "bpf_selftest_value_b"; +bool found_value_a; +bool found_value_b; + +SEC("lsm.s/socket_connect") +int BPF_PROG(test_socket_connect) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup_subsys_state *css, *tmp; + struct bpf_dynptr value_ptr; + struct cgroup *cgrp; + + if ((bpf_get_current_pid_tgid() >> 32) !=3D target_pid) + return 0; + + bpf_rcu_read_lock(); + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) { + bpf_rcu_read_unlock(); + return 0; + } + + css =3D &cgrp->self; + bpf_dynptr_from_mem(xattr_value, sizeof(xattr_value), 0, &value_ptr); + bpf_for_each(css, tmp, css, BPF_CGROUP_ITER_ANCESTORS_UP) { + int ret; + + ret =3D bpf_cgroup_read_xattr(tmp->cgroup, "user.bpf_test", + &value_ptr); + if (ret < 0) + continue; + + if (ret =3D=3D sizeof(expected_value_a) && + !bpf_strncmp(xattr_value, sizeof(expected_value_a), expected_value_a= )) + found_value_a =3D true; + if (ret =3D=3D sizeof(expected_value_b) && + !bpf_strncmp(xattr_value, sizeof(expected_value_b), expected_value_b= )) + found_value_b =3D true; + } + + bpf_rcu_read_unlock(); + bpf_cgroup_release(cgrp); + + return 0; +} --=20 2.47.1