Problematic fixed "stack ghci" temporary script (parent) directory

When I run "stack ghci", an attempt is made to create a temporary directory named: /tmp/haskell-stack-ghci/<unique-subdir> in which various temporary artefacts are stored. The parent directory is created with permissions (0777 & ~umask). Security issues aside, this can't work reliably on a multi-user system. Does anyone know whether this is something peculiar to my FreeBSD setup, or a systemic issue with "stack ghci"? I don't see the same behaviour with "stack script", though if I create a script to run in "/tmp", then ghc is, somewhat unexpectely, executed with "-i/tmp/", which also has security implications... -- Viktor.

Does cabal repl work? On 10/6/19 1:36 AM, Viktor Dukhovni wrote:
When I run "stack ghci", an attempt is made to create a temporary directory named:
/tmp/haskell-stack-ghci/<unique-subdir>
in which various temporary artefacts are stored. The parent directory is created with permissions (0777 & ~umask).
Security issues aside, this can't work reliably on a multi-user system. Does anyone know whether this is something peculiar to my FreeBSD setup, or a systemic issue with "stack ghci"?
I don't see the same behaviour with "stack script", though if I create a script to run in "/tmp", then ghc is, somewhat unexpectely, executed with "-i/tmp/", which also has security implications...

On Sun, Oct 06, 2019 at 11:24:50AM -0500, Vanessa McHale wrote:
Does "cabal repl" work?
With "cabal new-repl" I see the unique directory created directly under /tmp, with no fixed intermediate ancestor: drwx------ 3 viktor wheel 128 Oct 6 15:58 cabal-repl.-30676 this looks reasonably safe and should work fine on multi-user systems. A system-call trace (with names for some predicted pids pre-created) shows that the mkdir(2) starts at the process id, and retries on failure with ++pid: 30989: getpid() = 30989 (0x790d) 30989: mkdir("/tmp/cabal-repl.-30989",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30990",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30991",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30992",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30993",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30994",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30995",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30996",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30997",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30998",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-30999",0700) ERR#17 'File exists' 30989: mkdir("/tmp/cabal-repl.-31000",0700) = 0 (0x0) So this can be DoSed by a determined hostile user, but if, as is typical, there are no per-user quotas in /tmp, one can also just consume all the available free space in /tmp, ... Adding a second less predictable name component to the pid, (say microsecond time, or a random number) is perhaps better, but not very compelling. With "cabal v1-repl", I did't see any temp files created right away, but after loading a module, I see: 31288: mkdir("/tmp/ghc31288_0",0777) ERR#17 'File exists' 31288: mkdir("/tmp/ghc31288_1",0777) ERR#17 'File exists' 31288: mkdir("/tmp/ghc31288_2",0777) ERR#17 'File exists' 31288: mkdir("/tmp/ghc31288_3",0777) ERR#17 'File exists' 31288: mkdir("/tmp/ghc31288_4",0777) = 0 (0x0) which is somewhat better than incrementing the pid. -- Viktor.

You can override the temporary directory by setting the TMPDIR environment
variable.
To have this apply to all of your stack invocations, consider putting an
alias in your .bashrc, something like:
$ alias stack="TMPDIR=~/.local/tmp ~/.local/bin/stack"
Note that you might also need to
$ mkdir ~/.local/tmp
-Michael
On Sun, Oct 6, 2019 at 12:36 AM Viktor Dukhovni
When I run "stack ghci", an attempt is made to create a temporary directory named:
/tmp/haskell-stack-ghci/<unique-subdir>
in which various temporary artefacts are stored. The parent directory is created with permissions (0777 & ~umask).
Security issues aside, this can't work reliably on a multi-user system. Does anyone know whether this is something peculiar to my FreeBSD setup, or a systemic issue with "stack ghci"?
I don't see the same behaviour with "stack script", though if I create a script to run in "/tmp", then ghc is, somewhat unexpectely, executed with "-i/tmp/", which also has security implications...
-- Viktor.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On Sun, Oct 06, 2019 at 11:06:26AM -0600, Michael Sloan wrote:
You can override the temporary directory by setting the TMPDIR environment variable.
To have this apply to all of your stack invocations, consider putting an alias in your .bashrc, something like:
$ alias stack="TMPDIR=~/.local/tmp ~/.local/bin/stack"
Thanks, though I am inclined for the fancier[1]: stack() { ( dir=$(mktemp -d /tmp/stack.XXXXXX) || exit 1 trap '/bin/rm -rf $dir; exit' EXIT HUP INT QUIT TERM TMPDIR=$dir $HOME/.local/bin/stack "$@" ); } [1] Note mktemp(1) is not covered by the Single Unix Specification, so portability is not assured, the below should work on at least BSD Systems and Linux.
I don't see the same behaviour with "stack script", though if I create a script to run in "/tmp", then ghc is, somewhat unexpectely, executed with "-i/tmp/", which also has security implications...
But I probably still need to take care to avoid building single-use throw-away scripts for "stack script" in /tmp: $ script=$(mktemp /tmp/script.XXXXXX) $ ... generate content of $script ... $ stack script "$script" since it seems that the above will search /tmp for dependencies. -- Viktor.
participants (3)
-
Michael Sloan
-
Vanessa McHale
-
Viktor Dukhovni