diff mbox series

[bpf,6/9] bpf: Only allow sleepable program for resched-able iterator

Message ID 20220806074019.2756957-7-houtao@huaweicloud.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series fixes for bpf map iterator | expand

Checks

Context Check Description
bpf/vmtest-bpf-PR success PR summary
bpf/vmtest-bpf-VM_Test-1 success Logs for Kernel LATEST on ubuntu-latest with gcc
bpf/vmtest-bpf-VM_Test-2 success Logs for Kernel LATEST on ubuntu-latest with llvm-16
bpf/vmtest-bpf-VM_Test-3 success Logs for Kernel LATEST on z15 with gcc
netdev/tree_selection success Clearly marked for bpf
netdev/fixes_present success Fixes tag present in non-next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 2 this patch: 2
netdev/cc_maintainers warning 2 maintainers not CCed: song@kernel.org martin.lau@linux.dev
netdev/build_clang success Errors and warnings before: 5 this patch: 5
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 2 this patch: 2
netdev/checkpatch warning WARNING: line length of 92 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline fail Was 0 now: 1

Commit Message

Hou Tao Aug. 6, 2022, 7:40 a.m. UTC
From: Hou Tao <houtao1@huawei.com>

When a sleepable program is attached to a hash map iterator, might_fault()
will report "BUG: sleeping function called from invalid context..." if
CONFIG_DEBUG_ATOMIC_SLEEP is enabled. The reason is that rcu_read_lock()
is held in bpf_hash_map_seq_next() and won't be released until all elements
are traversed or bpf_hash_map_seq_stop() is called.

Fixing it by reusing BPF_ITER_RESCHED to indicate that only non-sleepable
program is allowed for iterator without BPF_ITER_RESCHED. Another fine-grained
flag can be added later if needed.

Signed-off-by: Hou Tao <houtao1@huawei.com>
---
 kernel/bpf/bpf_iter.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

Comments

Yonghong Song Aug. 8, 2022, 3:07 p.m. UTC | #1
On 8/6/22 12:40 AM, Hou Tao wrote:
> From: Hou Tao <houtao1@huawei.com>
> 
> When a sleepable program is attached to a hash map iterator, might_fault()
> will report "BUG: sleeping function called from invalid context..." if
> CONFIG_DEBUG_ATOMIC_SLEEP is enabled. The reason is that rcu_read_lock()
> is held in bpf_hash_map_seq_next() and won't be released until all elements
> are traversed or bpf_hash_map_seq_stop() is called.
> 
> Fixing it by reusing BPF_ITER_RESCHED to indicate that only non-sleepable
> program is allowed for iterator without BPF_ITER_RESCHED. Another fine-grained
> flag can be added later if needed.

I think this is okay. BPF_ITER_RESCHED will enable cond_resched() which
won't work in a rcu_read_lock()/rcu_read_unlock() context. We can
revisit bpf_iter_link_attach() later if later there are other
conditions which may cause rcu_read_lock() issues.

> 
> Signed-off-by: Hou Tao <houtao1@huawei.com>

Acked-by: Yonghong Song <yhs@fb.com>

> ---
>   kernel/bpf/bpf_iter.c | 11 ++++++++++-
>   1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c
> index 7e8fd49406f6..f4db589d1dc5 100644
> --- a/kernel/bpf/bpf_iter.c
> +++ b/kernel/bpf/bpf_iter.c
> @@ -68,13 +68,18 @@ static void bpf_iter_done_stop(struct seq_file *seq)
>   	iter_priv->done_stop = true;
>   }
>   
> +static inline bool bpf_iter_target_support_resched(const struct bpf_iter_target_info *tinfo)
> +{
> +	return tinfo->reg_info->feature & BPF_ITER_RESCHED;
> +}
> +
>   static bool bpf_iter_support_resched(struct seq_file *seq)
>   {
>   	struct bpf_iter_priv_data *iter_priv;
>   
>   	iter_priv = container_of(seq->private, struct bpf_iter_priv_data,
>   				 target_private);
> -	return iter_priv->tinfo->reg_info->feature & BPF_ITER_RESCHED;
> +	return bpf_iter_target_support_resched(iter_priv->tinfo);
>   }
>   
>   /* maximum visited objects before bailing out */
> @@ -538,6 +543,10 @@ int bpf_iter_link_attach(const union bpf_attr *attr, bpfptr_t uattr,
>   	if (!tinfo)
>   		return -ENOENT;
>   
> +	/* Only allow sleepable program for resched-able iterator */
> +	if (prog->aux->sleepable && !bpf_iter_target_support_resched(tinfo))
> +		return -EINVAL;
> +
>   	link = kzalloc(sizeof(*link), GFP_USER | __GFP_NOWARN);
>   	if (!link)
>   		return -ENOMEM;
diff mbox series

Patch

diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c
index 7e8fd49406f6..f4db589d1dc5 100644
--- a/kernel/bpf/bpf_iter.c
+++ b/kernel/bpf/bpf_iter.c
@@ -68,13 +68,18 @@  static void bpf_iter_done_stop(struct seq_file *seq)
 	iter_priv->done_stop = true;
 }
 
+static inline bool bpf_iter_target_support_resched(const struct bpf_iter_target_info *tinfo)
+{
+	return tinfo->reg_info->feature & BPF_ITER_RESCHED;
+}
+
 static bool bpf_iter_support_resched(struct seq_file *seq)
 {
 	struct bpf_iter_priv_data *iter_priv;
 
 	iter_priv = container_of(seq->private, struct bpf_iter_priv_data,
 				 target_private);
-	return iter_priv->tinfo->reg_info->feature & BPF_ITER_RESCHED;
+	return bpf_iter_target_support_resched(iter_priv->tinfo);
 }
 
 /* maximum visited objects before bailing out */
@@ -538,6 +543,10 @@  int bpf_iter_link_attach(const union bpf_attr *attr, bpfptr_t uattr,
 	if (!tinfo)
 		return -ENOENT;
 
+	/* Only allow sleepable program for resched-able iterator */
+	if (prog->aux->sleepable && !bpf_iter_target_support_resched(tinfo))
+		return -EINVAL;
+
 	link = kzalloc(sizeof(*link), GFP_USER | __GFP_NOWARN);
 	if (!link)
 		return -ENOMEM;