Agenix seems to expect that TMPDIR and the destination after encryption is on the same filesystem with mv -f in certain cases
mitchty opened this issue · 1 comments
With this layout:
$ df / /home /tmp
Filesystem 1K-blocks Used Available Use% Mounted on
zroot/os/root 1058116992 596608 1057520384 1% /
zroot/user/home 1715647104 658126720 1057520384 39% /home
tmpfs 24936036 28688 24907348 1% /tmp
I get this when trying to edit an existing secret:
++ dirname git/gh-cli-pub.age
+ mkdir -p git
+ mv -f /tmp/tmp.CsA6RGWVJS/gh-cli-pub.age git/gh-cli-pub.age
mv: inter-device move failed: '/tmp/tmp.CsA6RGWVJS/gh-cli-pub.age' to 'git/gh-cli-pub.age'; unable to remove target
: Permission denied
+ cleanup
+ '[' -n x ']'
+ rm -rf /tmp/tmp.4ebOPFI9Ow
+ '[' -n x ']'
+ rm -rf /tmp/tmp.CsA6RGWVJS
zsh: exit 1 ( cd secrets; env EDITOR=vim nix run github:ryantm/agenix -- --verbose --edit)
This looks to be this mv:
Line 188 in 24a7ea3
I think using mv is slightly invalid in this use case, if we're nuking the /tmp/tmp. dir in exit/etc traps anyway in the cleanup function an install command to copy the reencrypted file or plain old copy would be less problematic as then rename() won't fail with EPERM underneath of mv if the underlying filesystem doesn't support rename() in this way.
Worthy of a pr to swap mv to copy or install instead here?
Ref from rename() on linux (note this is nixos 23.11 if it matters but its more glibc than anything):
EPERM or EACCES
The directory containing oldpath has the sticky bit
(S_ISVTX) set and the process's effective user ID is
neither the user ID of the file to be deleted nor that of
the directory containing it, and the process is not
privileged (Linux: does not have the CAP_FOWNER
capability); or newpath is an existing file and the
directory containing it has the sticky bit set and the
process's effective user ID is neither the user ID of the
file to be replaced nor that of the directory containing
it, and the process is not privileged (Linux: does not
have the CAP_FOWNER capability); or the filesystem
containing oldpath does not support renaming of the type
requested.
In this case we're hitting EPERM in mv via rename() and that last condition in that rename on this tmpfs fs is saying no in spite of the dir in /tmp and file being owned by my user.