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>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <87zfuqb2mx.fsf@email.froward.int.ebiederm.org>
Date: Fri, 22 Mar 2024 12:24:54 -0500
From: "Eric W. Biederman" <ebiederm@...ssion.com>
To: Leo Yan <leo.yan@....com>
Cc: Alexander Viro <viro@...iv.linux.org.uk>,  Christian Brauner
 <brauner@...nel.org>,  Jan Kara <jack@...e.cz>,  Kees Cook
 <keescook@...omium.org>,  linux-fsdevel@...r.kernel.org,
  linux-mm@...ck.org,  linux-kernel@...r.kernel.org,  Peter Zijlstra
 <peterz@...radead.org>,  Ingo Molnar <mingo@...hat.com>,  Arnaldo Carvalho
 de Melo <acme@...nel.org>,  Namhyung Kim <namhyung@...nel.org>,  Ian
 Rogers <irogers@...gle.com>,  Al Grant <al.grant@....com>,  James Clark
 <james.clark@....com>,  Mark Rutland <mark.rutland@....com>
Subject: Re: [PATCH] exec: Don't disable perf events for setuid root
 executables

Leo Yan <leo.yan@....com> writes:

> Al Grant reported that the 'perf record' command terminates abnormally
> after setting the setuid bit for the executable. To reproduce this
> issue, an additional condition is the binary file is owned by the root
> user but is running under a non-privileged user. The logs below provide
> details:
>
>     $ sudo chmod u+s perf
>     $ ls -l perf
>     -rwsr-xr-x 1 root root 13147600 Mar 17 14:56 perf
>     $ ./perf record -e cycles -- uname
>     [ perf record: Woken up 1 times to write data ]
>     [ perf record: Captured and wrote 0.003 MB perf.data (7 samples) ]
>     Terminated
>
> Comparatively, the same command can succeed if the setuid bit is cleared
> for the perf executable:
>
>     $ sudo chmod u-s perf
>     $ ls -l perf
>     -rwxr-xr-x 1 root root 13147600 Mar 17 14:56 perf
>     $ ./perf record -e cycles -- uname
>     Linux
>     [ perf record: Woken up 1 times to write data ]
>     [ perf record: Captured and wrote 0.003 MB perf.data (13 samples) ]
>
> After setting the setuid bit, the problem arises when begin_new_exec()
> disables the perf events upon detecting that a regular user is executing
> a setuid binary, which notifies the perf process. Consequently, the perf
> tool in user space exits from polling and sends a SIGTERM signal to kill
> child processes and itself. This explains why we observe the tool being
> 'Terminated'.
>
> With the setuid bit a non-privileged user can obtain the same
> permissions as the executable's owner. If the owner has the privileged
> permission for accessing perf events, the kernel should keep enabling
> perf events. For this reason, this patch adds a condition checking for
> perfmon_capable() to not disabling perf events when the user has
> privileged permission yet.
>
> Note the begin_new_exec() function only checks permission for the
> per-thread mode in a perf session. This is why we don't need to add any
> extra checking for the global knob 'perf_event_paranoid', as it always
> grants permission for per-thread performance monitoring for unprivileged
> users (see Documentation/admin-guide/perf-security.rst).

This code change makes no sense.

The logic you are attempting to implement, allowing performance
measurements of a setuid application if it has sufficient capabilities
does make sense.

perfmon_capable tests if the current program has sufficient privileges
to use perf, not the program that enabled performance measurements.

The location perfmon_capable is being called in the new executable is
after the new executable gets it's new credentials.  AKA the suidroot
has already happened.  So it will always succeed for suidroot
executables.

I suggest you take a look at ptracer_capable that is used to test if the
ptracer has sufficient credentials to trace a suid root exectuable.

Eric



> Signed-off-by: Leo Yan <leo.yan@....com>
> Cc: Al Grant <al.grant@....com>
> Cc: James Clark <james.clark@....com>
> Cc: Mark Rutland <mark.rutland@....com>
> ---
>  fs/exec.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/fs/exec.c b/fs/exec.c
> index ff6f26671cfc..5ded01190278 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -1401,7 +1401,8 @@ int begin_new_exec(struct linux_binprm * bprm)
>  	 * wait until new credentials are committed
>  	 * by commit_creds() above
>  	 */
> -	if (get_dumpable(me->mm) != SUID_DUMP_USER)
> +	if ((get_dumpable(me->mm) != SUID_DUMP_USER) &&
> +	    !perfmon_capable())
>  		perf_event_exit_task(me);
>  	/*
>  	 * cred_guard_mutex must be held at least to this point to prevent

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ