From nobody Thu Oct 9 08:13:00 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 C1AF21C2324; Wed, 18 Jun 2025 23:37:54 +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=1750289874; cv=none; b=h/u1JJUw1Zetro+C+U7HUZ6B/NtO3+LtWxF69cra3/vxSua1g3KMrLYpC0fuKSSxb+2yt8hutqYAbk4WmAt7lhLctYgWOjd7jvRPFwTC64tWAbDw456YIrNxNaqwToy/u12oAZAFrc/Wlys+PbooklbBbNGkMj5DdiEjCLnFiwY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750289874; c=relaxed/simple; bh=jT/WFn/kSkE09z8k3BXM/m+RCnGxFogqiqP15XNsKRo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C2lelxa1iLv6SK3xPTzCxEiz8Bh8MyFhcg3HerZlcc7dxx+oUC/alXHQlV0XozBI8ecPMQ0809tG5kyRFszihNMb+Y1rxJ0Vy7KroMTQaiLhBXCk3gRSm9T2L7p8eF65GCXXZ1o2duPKH/HbAbdHD9dLbj2eGonpN6Dpy3ueZdo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ES9mJ4rw; 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="ES9mJ4rw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6AE26C4CEE7; Wed, 18 Jun 2025 23:37:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750289874; bh=jT/WFn/kSkE09z8k3BXM/m+RCnGxFogqiqP15XNsKRo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ES9mJ4rwtG5/ZtGfVWFHtsmiTMBcFpcSaEXTvPgHZlS76WjXMVBCA3uIHEamugSao cBv5QIFkh8+ELXvq4LxmIPNMi+KC7h6/D2c/mnNE2tEz6UFjJSzZa7w+HSwlD9N45K lA3KJm4Vr5YtYDtHoo61eF8Byf+IDsVG0veALgNNiuDo3wJQA6BlebIvparThMFrH1 PHVAmijUN9t5udkm9xgWCaABgT8v1pkvH1YGdjK0LZwkJ+t/eNubn/nrIiPbjT6ikb HtaBqnCvDt727blfXodxoyoKsiNWNceDo1U/XrrLtY6An0b9s4ai90cKw14e074lAV Gggod2EFldkag== 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 bpf-next 1/4] kernfs: Add __kernfs_xattr_get for RCU protected access Date: Wed, 18 Jun 2025 16:37:36 -0700 Message-ID: <20250618233739.189106-2-song@kernel.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250618233739.189106-1-song@kernel.org> References: <20250618233739.189106-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" Existing kernfs_xattr_get() locks iattr_mutex, so it cannot be used in RCU critical sections. Introduce __kernfs_xattr_get(), which reads xattr under RCU read lock. This can be used by BPF programs to access cgroupfs xattrs. Signed-off-by: Song Liu Acked-by: Greg Kroah-Hartman Acked-by: Tejun Heo --- fs/kernfs/inode.c | 14 ++++++++++++++ include/linux/kernfs.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index b83054da68b3..0ca231d2012c 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -302,6 +302,20 @@ int kernfs_xattr_get(struct kernfs_node *kn, const cha= r *name, return simple_xattr_get(&attrs->xattrs, name, value, size); } =20 +int __kernfs_xattr_get(struct kernfs_node *kn, const char *name, + void *value, size_t size) +{ + struct kernfs_iattrs *attrs; + + WARN_ON_ONCE(!rcu_read_lock_held()); + + attrs =3D rcu_dereference(kn->iattr); + if (!attrs) + return -ENODATA; + + return simple_xattr_get(&attrs->xattrs, name, value, size); +} + int kernfs_xattr_set(struct kernfs_node *kn, const char *name, const void *value, size_t size, int flags) { diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index b5a5f32fdfd1..8536ffc5c9f1 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h @@ -456,6 +456,8 @@ void kernfs_notify(struct kernfs_node *kn); =20 int kernfs_xattr_get(struct kernfs_node *kn, const char *name, void *value, size_t size); +int __kernfs_xattr_get(struct kernfs_node *kn, const char *name, + void *value, size_t size); int kernfs_xattr_set(struct kernfs_node *kn, const char *name, const void *value, size_t size, int flags); =20 --=20 2.47.1 From nobody Thu Oct 9 08:13:00 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 B5EB328466C; Wed, 18 Jun 2025 23:38:00 +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=1750289880; cv=none; b=fiepiC3Gu/sN893f4U9CbuMElRFVTq829fA0fReP+Y5gqjPEv4IHq8+vR0GhYR0z/6FFYmoL1erSPEn/B7JOESGV3nxiPfH5lU1anGYJh9QwM2qOv20yxBHE7n6HvpnlbPV6heQDRj8WrRMZztZ9Tt04YZM53hRty0KrYw+FV8o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750289880; c=relaxed/simple; bh=ZsxNKP/5L7kax4tFNOKGSX/EsEcy4YWBATqLLzfkmoI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i5dNqNWBrpPsEmX/lBBORqOnyek7qPjUEGDYyzf9u+vCcdvlOuAiCnDgY5pykxXQGMBVGOMHBCeMEB5RL192QUaO76j1HSe5bm8EgBSrwDWuKQ2BZ7IodaY84qyWDFCd/b45fvJGnx4I7h1s8VTi5W1sUipKbGeAI5KnV7lu8FM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=klAHhgdx; 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="klAHhgdx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 476FCC4CEE7; Wed, 18 Jun 2025 23:37:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750289880; bh=ZsxNKP/5L7kax4tFNOKGSX/EsEcy4YWBATqLLzfkmoI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=klAHhgdx1mhHargsK8Gda2XXGuzU+NPLzSU++tI9EjnQTWy8sSe6Ay2LitA9ZpvSF +tRugWS7paLH/pa+XrZupYNJleWR87/1yIN/4b4S9oZPsDX5td9W4OztkRIDjVkb4n +XIxjlE5bmm54OpKGeOyAk45sMo9DXsF49uQXN/JH5tftF0iZXX0AFHhR9JYqf9H/e wH/J36sRFJVUi3BCnTV90cCIbWWAAj0lSmtr86AmlYbv3A0YFlKDjq6ptaUIv6aqs/ d7qmrP4SL4UP5dhZPtPfQhn1yqeZg7Bn2YOfMJFYTVA15eLmDLtDklthIh0BZySeEz tweiWRcH8oXkA== 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 bpf-next 2/4] bpf: Introduce bpf_kernfs_read_xattr to read xattr of kernfs nodes Date: Wed, 18 Jun 2025 16:37:37 -0700 Message-ID: <20250618233739.189106-3-song@kernel.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250618233739.189106-1-song@kernel.org> References: <20250618233739.189106-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 files and folders. Introduce kfunc bpf_kernfs_read_xattr, which allows reading kernfs xattr under RCU read lock. 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. Signed-off-by: Song Liu --- fs/bpf_fs_kfuncs.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/fs/bpf_fs_kfuncs.c b/fs/bpf_fs_kfuncs.c index 08412532db1b..7576dbc9b340 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,37 @@ __bpf_kfunc int bpf_remove_dentry_xattr(struct dentry = *dentry, const char *name_ return ret; } =20 +/** + * bpf_kernfs_read_xattr - get xattr of a kernfs node + * @kn: kernfs_node to get xattr from + * @name__str: name of the xattr + * @value_p: output buffer of the xattr value + * + * Get xattr *name__str* of *kn* 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_kernfs_read_xattr(struct kernfs_node *kn, const char *= name__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(kn, name__str, value, value_len); +} + __bpf_kfunc_end_defs(); =20 BTF_KFUNCS_START(bpf_fs_kfunc_set_ids) @@ -333,6 +365,7 @@ BTF_ID_FLAGS(func, bpf_get_dentry_xattr, KF_SLEEPABLE |= KF_TRUSTED_ARGS) BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) BTF_ID_FLAGS(func, bpf_set_dentry_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) BTF_ID_FLAGS(func, bpf_remove_dentry_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) +BTF_ID_FLAGS(func, bpf_kernfs_read_xattr, KF_RCU | KF_RCU_PROTECTED) BTF_KFUNCS_END(bpf_fs_kfunc_set_ids) =20 static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id) --=20 2.47.1 From nobody Thu Oct 9 08:13:00 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 8068628506B; Wed, 18 Jun 2025 23:38:06 +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=1750289886; cv=none; b=Hn8ZSmHT5UwWTbqEelzepwbtwdxfJFng9O4MfgHIwyiAG9BUn+JHcfy3P9UwzXZUQK8l08KdXg90UGBxKe3i/GEQtqvfr5RdIDn3DJi7pTgR5cbMqISas8rNbLKWkp1qvNeglM/EyE4uBRqclgxg3L4TJKYv48FevKtEZ0XbNUM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750289886; c=relaxed/simple; bh=BEJZRN76m+6IEQPpBHY905TwGMpPvyUC5d/zGM477GM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hBIw4DoArUQtRr2V50+2ptRd1inWNOiOQc6ubhP92X6eSsyDEmu4v4jc3b8ECC1O+Y1c+Wug3GDxNfGT2WVwGugttcAvp5+JIRn1awNGdv8whqXQkGw4KXNor1YcXTTbHmr8i060ToH8Vi7+qdqPR0cXBTjIi9xDPGkQwwFBtpg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ybjnhxgl; 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="Ybjnhxgl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 28F88C4CEE7; Wed, 18 Jun 2025 23:38:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750289886; bh=BEJZRN76m+6IEQPpBHY905TwGMpPvyUC5d/zGM477GM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ybjnhxgl6S4FzP8XrakM4Pq5QDHYuyAdLu/JGs8nDTFsHNTkE5DneuKuFow8jUFmH Ho9TZtHZwyLS1bajq8tO0UM3/3iZJ1X+j7jHJhD/pP0x/QX+444aoffZCwt7+2/An+ a0OFx7mMQe/P81gzLkg0m/pez7LxATcFP+/MAuJLDUQ3yPylVtZePFwP0/EdVu13e1 HmYNspkagu26CrWYB+BL0ZDycuOIEko8NyisNepGPSsEsCXDRyLZRLou1igdIOb3GF cj/MQR+R1IAdlHUNwohtIbQl9VZ8HWprxyQFf6gBChg1APZ7sEwBJ2tIwt++gdb3g5 TNc2dfmo/n1ZA== 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 bpf-next 3/4] bpf: Mark cgroup_subsys_state->cgroup RCU safe Date: Wed, 18 Jun 2025 16:37:38 -0700 Message-ID: <20250618233739.189106-4-song@kernel.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250618233739.189106-1-song@kernel.org> References: <20250618233739.189106-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 Thu Oct 9 08:13:00 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 44CEC29B221; Wed, 18 Jun 2025 23:38:11 +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=1750289892; cv=none; b=s88uSA9sbPmOUV/UNKx0sZnK0Xmuq+u74MV9ezwWoXip/04ZkaTx1UvfdysVCgvnI4YJvQ6CbxplW02gvjM9tEQDx44RhpL8ITuY4tATVUxU+KRuyY5WYpwEAcjoZPZTzRQowKeH1thnt0i743dDwiOOa360mexi5z/AB0pxTuM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750289892; c=relaxed/simple; bh=XUqG1vdMsgMYI/VRCB/BmmdtBIx3k72lJdL4ZezPJyo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ck+Bch7lxJN7srRmOjssaDP39jNjydIqKibYhgzEpcqwr4HtgFCN9YyzDUw83h6JEd3MJaMFenDZlbXhVQMS6WAzadg/JHiTLxUXgnoWpudX5UTBgvkiIKIHg/aKXJg/WPzQrPoEo7yyOZ6UvLgp/SqNHz6lsX999Oy4xJ8LwXs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZK+gCY65; 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="ZK+gCY65" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E7AF4C4CEE7; Wed, 18 Jun 2025 23:38:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750289891; bh=XUqG1vdMsgMYI/VRCB/BmmdtBIx3k72lJdL4ZezPJyo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZK+gCY65lV5Wcvx3fgQsrFNipIOQHaFb6xxqf9MaYhVICC0mnbUETyNCX4D2hkzz4 LPSHAlHgaGFjvMZbo/K0Yx08Al9YEdNTRe2pFPPz/1qwv2PXv0cBl+9ikmR1cKnfM8 xOpNv92Peb0EwJYfzdyBUcdw5n6mztV3BGVpVHJvGIpePuwEk41amGzR+OTx7WPbXo QkcK0susK2ZXcKuKqXc9BPFhgmSedXnQ/jzh3JWw0VTcXgse5QOVH24dNX4kZMfNeU MWocEkdeYORK361MlgCkygSrafU/EYSS9laznCk9Y8qMptDLv3vVfBH2CmREHFlEjP aWuy7fAYmkgKg== 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 bpf-next 4/4] selftests/bpf: Add tests for bpf_kernfs_read_xattr Date: Wed, 18 Jun 2025 16:37:39 -0700 Message-ID: <20250618233739.189106-5-song@kernel.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250618233739.189106-1-song@kernel.org> References: <20250618233739.189106-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_kernfs_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. Verifier reject using bpf_kernfs_read_xattr in sleepable contexts. 5. Use bpf_kernfs_read_xattr in LSM hook security_socket_connect. Signed-off-by: Song Liu --- .../selftests/bpf/prog_tests/kernfs_xattr.c | 145 ++++++++++++++++++ .../selftests/bpf/progs/kernfs_read_xattr.c | 117 ++++++++++++++ .../selftests/bpf/progs/read_cgroupfs_xattr.c | 60 ++++++++ 3 files changed, 322 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/kernfs_xattr.c create mode 100644 tools/testing/selftests/bpf/progs/kernfs_read_xattr.c create mode 100644 tools/testing/selftests/bpf/progs/read_cgroupfs_xattr.c diff --git a/tools/testing/selftests/bpf/prog_tests/kernfs_xattr.c b/tools/= testing/selftests/bpf/prog_tests/kernfs_xattr.c new file mode 100644 index 000000000000..b60ccfdc4c4d --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/kernfs_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 "kernfs_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_kernfs_xattr(void) +{ + RUN_TESTS(kernfs_read_xattr); + + if (test__start_subtest("read_cgroupfs_xattr")) + test_read_cgroup_xattr(); +} diff --git a/tools/testing/selftests/bpf/progs/kernfs_read_xattr.c b/tools/= testing/selftests/bpf/progs/kernfs_read_xattr.c new file mode 100644 index 000000000000..851cdcec05a6 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/kernfs_read_xattr.c @@ -0,0 +1,117 @@ +// 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]; + +__always_inline void read_xattr(struct cgroup *cgroup) +{ + struct bpf_dynptr value_ptr; + + bpf_dynptr_from_mem(value, sizeof(value), 0, &value_ptr); + bpf_kernfs_read_xattr(cgroup->kn, "user.bpf_test", + &value_ptr); +} + +SEC("lsm.s/socket_connect") +__failure __msg("R1 must be a rcu pointer") +int BPF_PROG(sleepable_missing_rcu_lock, struct file *f) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup *cgrp; + + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + return 0; + + /* Sleepable, so cgrp->kn is not trusted */ + read_xattr(cgrp); + bpf_cgroup_release(cgrp); + return 0; +} + +SEC("lsm.s/socket_connect") +__success +int BPF_PROG(sleepable_with_rcu_lock, struct file *f) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup *cgrp; + + bpf_rcu_read_lock(); + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + goto out; + + /* In rcu read lock, so cgrp->kn is trusted */ + read_xattr(cgrp); + bpf_cgroup_release(cgrp); +out: + bpf_rcu_read_unlock(); + return 0; +} + +SEC("lsm/socket_connect") +__success +int BPF_PROG(non_sleepable, struct file *f) +{ + u64 cgrp_id =3D bpf_get_current_cgroup_id(); + struct cgroup *cgrp; + + cgrp =3D bpf_cgroup_from_id(cgrp_id); + if (!cgrp) + return 0; + + /* non-sleepable, so cgrp->kn is trusted */ + read_xattr(cgrp); + bpf_cgroup_release(cgrp); + return 0; +} + +SEC("lsm/socket_connect") +__success +int BPF_PROG(use_css_iter, struct file *f) +{ + 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/socket_connect") +__success +int BPF_PROG(use_bpf_cgroup_ancestor, struct file *f) +{ + 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; + /* non-sleepable, so cgrp->kn is trusted */ + 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..5109e800a443 --- /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]; +const char expected_value_a[] =3D "bpf_selftest_value_a"; +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, struct file *f) +{ + 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_kernfs_read_xattr(tmp->cgroup->kn, "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