Re: [PATCH] kernel/sys.c: use RCU when accessing task_struct->real_parent

From: Alex Elder

Date: Tue Aug 11 2026 - 22:08:50 EST


On 8/11/26 8:17 PM, Andrew Morton wrote:
On Tue, 11 Aug 2026 14:05:00 -0500 Alex Elder <elder@xxxxxxxxxxxx> wrote:

In the setpgid() syscall definition, a check is made to determine
whether the target process is in the same thread group as the
current process. The check accesses the target process's real_parent
pointer directly, however that field is supposed to be accessed via
RCU. Use rcu_dereference() to avoid this C=1 build warning:

kernel/sys.c:1144:32: warning: incorrect type in argument 1 (different address spaces)

Oh.

Why don't all those other uses of ->real_parent produce this warning?

Looks like there are others; this was just the one that kept
showing up in my builds. Maybe some cases simply don't need
the rcu_dereference() (like initializing init_task.real_parent
in init/init_task.c).

It's inconsistent. Some files use rcu_dereference() always
for task_struct->real_parent:
- drivers/connector/cn_proc.c
- fs/binfmt_elf.c
- fs/nfs/dir.c
- fs/binfmt_elf_fdpic.c
- kernel/sched/core.c
- kernel/acct.c
- security/keys/keyctl.c
- security/selinux/hooks.c
- security/yama/yama_lsm.c

But others do not. And there are lots of other fields
annotated with __rcu that don't always use rcu_dereference():
- task_struct->parent
- task_struct->sighand
- mm_struct->owner
and so on.

I could go dig a little deeper and solve this more comprehensively.
It would probably have to be a long-running background effort.
Do you think it's worth it?

If not, I don't mind just retracting this suggestion for now.

-Alex



--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1114,6 +1114,7 @@ COMPAT_SYSCALL_DEFINE1(times, struct compat_tms __user *, tbuf)
SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
{
struct task_struct *p;
+ struct task_struct *real_parent;
struct task_struct *group_leader = current->group_leader;
struct pid *pids[PIDTYPE_MAX] = { 0 };
struct pid *pgrp;
@@ -1141,7 +1142,8 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
if (!thread_group_leader(p))
goto out;
- if (same_thread_group(p->real_parent, group_leader)) {
+ real_parent = rcu_dereference(p->real_parent);
+ if (same_thread_group(real_parent, group_leader)) {
err = -EPERM;
if (task_session(p) != task_session(group_leader))
goto out;