lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <rta37trkqzuvoim5muoukxmkbxcamlydwn6zfpm65k5qxyxb7y@pcq6nj54z6hl>
Date: Wed, 30 Jul 2025 10:22:23 +0200
From: Nicolas Bouchinet <nicolas.bouchinet@....cyber.gouv.fr>
To: linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org, 
	Jann Horn <jannh@...gle.com>
Cc: Nicolas Bouchinet <nicolas.bouchinet@....gouv.fr>
Subject: Re: [PATCH] fs: hidepid: Fixes hidepid non dumpable behavior

Hi Jann,

While documenting "hidepid=" I encountered those clunky behavior, which
I think we should not have.

Let say we set the "hidepid=" option to "invisible", processes will be fully
invisible to other users than root and the user that reads the procfs entry.

The fact that root is able to see every processes is partialy due to the fact
that the "gid=" variable is set to "0" by default :

```C has_pid_permissions
[...]
	if (in_group_p(fs_info->pid_gid))
		return true;
[...]
```

This means that if a process GID is in the group defined by the "gid=" option,
an authorization is directly returned, and the `ptrace_may_access()` function
is never called.

Thus, if one sets the "gid=" option to "1000", if a process is in this group,
it will now bypass the `security_ptrace_access_check()` hook calls.

This comes with the side effect that now, root will go through the
`ptrace_may_access()` checks and thus, if I have a root process without the
cap_sys_ptrace in its effective set, it will not be able to see other processes
anymore.

```C __ptrace_may_access
[...]
	if (ptrace_has_cap(tcred->user_ns, mode))
		goto ok;
	rcu_read_unlock();
	return -EPERM;
[...]
```

The following behavior thus happens :

```bash
$ sudo capsh --user=root --drop=cap_sys_ptrace -- -c /bin/bash
# mount -o remount,hidepid=2 /proc
# getpcaps $$
=ep cap_sys_ptrace-ep
# ps aux
root         1  0.0  0.1 204724  1404 ?        S    09:43   0:00 /usr/lib/python3.13/site-packages/virtme/guest/bin/virtme-ng-init
root         2  0.0  0.0      0     0 ?        S    09:43   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    09:43   0:00 [pool_workqueue_release]
[...]

# mount -o remount,hidepid=2,gid=1000 /proc
# getpcaps $$
=ep cap_sys_ptrace-ep
# ps aux
root       621  0.0  0.2   8656  2556 pts/0    S    09:46   0:00 /bin/bash
root       641  0.0  0.4   9592  4012 pts/0    R+   10:03   0:00 ps aux
root       642  0.0  0.2   6896  2452 pts/0    S+   10:03   0:00 less
```

This also means that if a process accesses were controled by an LSM, lets say
with the `audit ptrace` option of AppArmor, they magically disappears for the
process in the group defined in the "gid=" hidepid option and those controls
are "transfered" to root, which was not controlled at first.

Also, note that with "hidepid=ptraceable", the "gid=" option is ignored
and `ptrace_may_access()` is always called.

Shouldn't we always check for the "gid=0" and also call the
`security_ptrace_access_check()` even if the group is set ?

Best regards,

Nicolas

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ