[PATCH] fork: Ensure copy_process() returns a valid error pointer on failure

Shijia Hu posted 1 patch 1 week ago
kernel/fork.c | 7 +++++++
1 file changed, 7 insertions(+)
[PATCH] fork: Ensure copy_process() returns a valid error pointer on failure
Posted by Shijia Hu 1 week ago
copy_process() returns ERR_PTR(retval) from its error path, so retval
must be a negative errno in the range [-MAX_ERRNO, -1]. Values outside
that range produce a pointer which is not caught by IS_ERR() in
kernel_clone().

This can be triggered by attaching a BPF_MODIFY_RETURN program to
security_task_alloc() and returning an invalid value. copy_process()
treats the non-zero return as a failure, but ERR_PTR(1) or
ERR_PTR(-MAX_ERRNO - 1) does not produce an error pointer recognized by
IS_ERR(). kernel_clone() may then dereference the returned pointer.

Normalize unexpected values before returning ERR_PTR() from the
copy_process() error path. This keeps the fix local to the fork error
handling contract and does not change BPF_MODIFY_RETURN verifier behavior.

Fixes: 6ba43b761c41 ("bpf: Attachment verification for BPF_MODIFY_RETURN")
Reported-by: Quan Sun <2022090917019@std.uestc.edu.cn>
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Closes: https://lore.kernel.org/bpf/973a1b7b-8ee7-407a-890a-11455d9cc5bf@std.uestc.edu.cn/
Link: https://lore.kernel.org/all/20260411163556.8567-1-yangfeng59949@163.com/
Cc: stable@vger.kernel.org
Signed-off-by: Shijia Hu <hushijia1@uniontech.com>
---
 kernel/fork.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kernel/fork.c b/kernel/fork.c
index 8ac38beae360..40bfbdfffbdc 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2599,6 +2599,13 @@ __latent_entropy struct task_struct *copy_process(
 	spin_lock_irq(&current->sighand->siglock);
 	hlist_del_init(&delayed.node);
 	spin_unlock_irq(&current->sighand->siglock);
+	/*
+	 * The error path returns ERR_PTR(retval), which requires retval to be a
+	 * negative errno in the range [-MAX_ERRNO, -1]. Normalize unexpected
+	 * values to avoid returning non-error pointers to callers.
+	 */
+	if (unlikely(retval >= 0 || retval < -MAX_ERRNO))
+		retval = -EINVAL;
 	return ERR_PTR(retval);
 }
 
-- 
2.20.1
Re: [PATCH] fork: Ensure copy_process() returns a valid error pointer on failure
Posted by Alexei Starovoitov 1 week ago
On Sun, May 31, 2026 at 8:08 PM Shijia Hu <hushijia1@uniontech.com> wrote:
>
> copy_process() returns ERR_PTR(retval) from its error path, so retval
> must be a negative errno in the range [-MAX_ERRNO, -1]. Values outside
> that range produce a pointer which is not caught by IS_ERR() in
> kernel_clone().
>
> This can be triggered by attaching a BPF_MODIFY_RETURN program to
> security_task_alloc() and returning an invalid value. copy_process()
> treats the non-zero return as a failure, but ERR_PTR(1) or
> ERR_PTR(-MAX_ERRNO - 1) does not produce an error pointer recognized by
> IS_ERR(). kernel_clone() may then dereference the returned pointer.
>
> Normalize unexpected values before returning ERR_PTR() from the
> copy_process() error path. This keeps the fix local to the fork error
> handling contract and does not change BPF_MODIFY_RETURN verifier behavior.
>
> Fixes: 6ba43b761c41 ("bpf: Attachment verification for BPF_MODIFY_RETURN")
> Reported-by: Quan Sun <2022090917019@std.uestc.edu.cn>
> Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
> Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
> Closes: https://lore.kernel.org/bpf/973a1b7b-8ee7-407a-890a-11455d9cc5bf@std.uestc.edu.cn/
> Link: https://lore.kernel.org/all/20260411163556.8567-1-yangfeng59949@163.com/
> Cc: stable@vger.kernel.org
> Signed-off-by: Shijia Hu <hushijia1@uniontech.com>
> ---
>  kernel/fork.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/kernel/fork.c b/kernel/fork.c
> index 8ac38beae360..40bfbdfffbdc 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -2599,6 +2599,13 @@ __latent_entropy struct task_struct *copy_process(
>         spin_lock_irq(&current->sighand->siglock);
>         hlist_del_init(&delayed.node);
>         spin_unlock_irq(&current->sighand->siglock);
> +       /*
> +        * The error path returns ERR_PTR(retval), which requires retval to be a
> +        * negative errno in the range [-MAX_ERRNO, -1]. Normalize unexpected
> +        * values to avoid returning non-error pointers to callers.
> +        */
> +       if (unlikely(retval >= 0 || retval < -MAX_ERRNO))
> +               retval = -EINVAL;

This was reported earlier and there is a fix in the works.
This approach is incorrect.
You have to fix the root cause, not the symptom.

pw-bot: cr
Re: [PATCH] fork: Ensure copy_process() returns a valid error pointer on failure
Posted by Shijia Hu 1 week ago
On Sun, 31 May 2026 20:58:49 -0700, Alexei Starovoitov wrote:
> This was reported earlier and there is a fix in the works.
> This approach is incorrect.
> You have to fix the root cause, not the symptom.
>
> pw-bot: cr

Thanks for taking a look.

I'll drop this copy_process() approach for upstream.
 
Is the follow-up fix still being tracked in this thread?

  https://lore.kernel.org/all/20260411163556.8567-1-yangfeng59949@163.com/

If so, I can follow the progress there and help test the fix with the
security_* fmod_ret reproducer once it is available.

Thanks,
Shijia