Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using bash process substitution for a sudo command

Tags:

bash

I would like to use bash process substitution for a sudo command.

For example, here's a non-sudo command that works for me:

$ cat <(echo "installed.txt")
installed.txt

And here's a sudo version of the command that does not work:

$ sudo cat <(echo "installed.txt")
cat: /dev/fd/63: Bad file descriptor

Reading the sudo man page, it seems that sudo closes all but the stdin/stdout/stderr file descriptors before running the command as root. This leads me to think that bash is creating the descriptor (and performing the process substitution) before running the sudo command.

I changed root's shell to bash (instead of sh default). I've tested that the command works fine when logged in as root. It only does not work via a sudo command.

What is the appropriate technique to achieve what I'm trying to do here? Eval, quoting, sudo flag, sudoers file mod, other?

like image 654
Clayton Stanley Avatar asked Dec 02 '12 18:12

Clayton Stanley


4 Answers

Try doing this in your shell :

$ sudo bash -c 'cat <(echo "installed.txt for UID=$UID")'
installed.txt for UID=0
like image 136
Gilles Quenot Avatar answered Oct 29 '22 11:10

Gilles Quenot


In case you're asking for process substitution for the security it brings, like hiding a password from the process list, then you might better do it this way:

cat <(echo -n "$PASSWORD") | sudo cryptsetup ... --key-file -

Sure, the password is sent to sudo through its stdin, so the process substitution is not done within sudo as asked. And my answer becomes technically off topic.

I still hope it will help in this particular context, because the accepted answer comes with serious drawbacks: you need to build a properly quoted string, and then spawn a secondary shell to interpret it within the sudo.

This makes it not only slow, but also risky due to shell injection, environment variables and so.

like image 37
MoonCactus Avatar answered Oct 29 '22 12:10

MoonCactus


The behaviour described in the question is due to the design of sudo.

$ sudo cat <(echo "installed.txt")
cat: /dev/fd/63: Bad file descriptor

The error occurs because sudo has a default behaviour which closes file descriptors except for standard input, output and error. As described on the man page:

By default, sudo will close all open file descriptors other than standard input, standard output and standard error when executing a command.

This behaviour can be overridden with the -C (or --close-from) option to specify a file descriptor number below which files should not be closed. However, use of this option must be permitted by an administrator: the following needs to be added to /etc/sudoers

 Defaults closefrom_override

With that in place, the command will work if -C is used:

$ sudo -C64 cat <(echo "installed.txt")
installed.txt

(here the number 64 was given because it was greater than the 63 in the error message).

like image 35
starfry Avatar answered Oct 29 '22 11:10

starfry


sudo bash  -c 'cat <(echo "installed.txt")'
like image 41
emrys57 Avatar answered Oct 29 '22 10:10

emrys57