"Permission denied" reading from a process-substitution FIFO in an unprivileged child process

Viewed 248

Consider the following, observed with bash 4.4 on a Linux 3.19 kernel:

# in reality, this may access files "nobody" isn't allowed
get_a_secret() { printf '%s\n' "This is a secret"; }

# attach a process substitution reading the secret to FD 10
exec 10< <(get_a_secret)

# run a less-privileged program that needs the secret, passing it the file descriptor.
chpst -u nobody:nobody -- cat /dev/fd/10

...or the shorter/simpler:

chpst -u nobody:nobody -- cat <(get_a_secret)

Either fails in a manner akin to the following:

cat: /proc/self/fd/10: Permission denied

So, two branches to this question:

  • What's going on here?

  • Is there a way to get the desired behavior (passing the ability to read the secret through to the single child process being invoked in a way that doesn't persistently expose that secret to other processes running as "nobody") without exposing the FIFO's output to other processes?

(Yes, I'm well aware that I need to lock down ptrace and /proc/*/mem to prevent another process running as "nobody" from pulling the secret out of the client as it's being read; that said, that's (1) something I can do, and (2) when the process is only run before any potentially-attacker-controlled executables are invoked, less exposure than allowing any process running as nobody to pull the secret out of /proc/*/environ for the full duration of that process).

1 Answers
Related