Any idea why sftp
is unable to read the temporary file descriptor?
Few facts:
- the
<(pass foo)
process substitution will cause bash
to create a pipe, run the pass foo
command asynchronously with its output connected to the writing end of the pipe and replace the <(...)
with a path of the form /dev/fd/63
, where 63
is the file descriptor referring to the reading end of the pipe.
- the
/dev/fd/63
is a special path which allows a process to stat()
and re-open the file referred by one of its file descriptors.
- the shell forks + execs
sftp
, then sftp
itself forks and execs ssh
, causing the 63
file descriptor to be passed down via inheritance.
ssh
will close all its file descriptors except 0, 1, 2 using the closefrom()
function. That will also close fd 63
.
Since 63
is no longer an open file descriptor in the ssh
process, a stat()
on /dev/fd/63
will fail with the error from the OP.
How to fix it?
Temporarily store the key in a filesystem in memory. In my Debian systemd
provides me tmpfs under /run/user/<myUID>
. The mountpoint is inaccessible to anyone but me (and root, of course).
Note a rogue process running under your user (or root) can read the file. But such process could also read from sshd
's file descriptor 63
in your original approach.
Alternatively, when there is no safe tmpfs available:
Create a temporary fifo. Note mktemp
cannot do this directly. The safe way is to create a temporary private directory and then mkfifo
in it.
Make sure the permissions of the fifo itself are narrow, otherwise ssh
will complain.
Run
sftp -i "/temp_dir/the_fifo" user@host
In parallel run pass foo > "/temp_dir/the_fifo"
. A quirk: you need to do this twice; at least in my Debian ssh
reads the key twice. The following command seems to work in my tests: cat ~/.ssh/id_rsa > "/temp_dir/the_fifo" && cat ~/.ssh/id_rsa > "/temp_dir/the_fifo"
. Probably a similar duplicated command will work for you:
pass foo > "/temp_dir/the_fifo" && pass foo > "/temp_dir/the_fifo"
You can run it in the background just before sftp
(unless pass
is interactive, I'm not familiar with the tool at all).
At the end remove the fifo and the directory.
Still, a rogue process running under your user (or root) can read from the fifo before ssh
does.