zsh-workers
 help / color / mirror / code / Atom feed
* [minor] umask 400 causes here-{doc,string} failure
@ 2018-03-11 15:17 Stephane Chazelas
  2018-03-13 10:44 ` Joerg Schilling
  0 siblings, 1 reply; 2+ messages in thread
From: Stephane Chazelas @ 2018-03-11 15:17 UTC (permalink / raw)
  To: bug-bash, Zsh hackers list, Joerg.Schilling

Note: sent to bash, zsh and Schily Bourne shell dev mailing
lists (not mksh as my email provider apparently doesn't play
well with mirbsd.org's expensive greylisting, please feel free
to forward there if you don't use gmail).

That's from:
https://unix.stackexchange.com/questions/429285/cannot-create-temp-file-for-here-document-permission-denied

$ bash -c 'umask 400; cat <<< test'
bash: cannot create temp file for here-document: Permission denied
$ zsh -c 'umask 400; cat <<< test'
zsh:1: can't create temp file for here document: permission denied
$ bosh -c 'umask 400; cat << EOF
test
EOF'
bosh: /tmp/sh193220: cannot open
$ mksh -c 'umask 400; cat <<< test'
mksh: can't open temporary file /tmp/sh933f2z.tmp: Permission denied

Those shells use temporary files to store the content of the
here-documents as the Bourne shell initially did, and open them
in read-only mode to make it cat's stdin.

When umask contains the 0400 bit, the file is created without
read permission to the user, hence the error upon that second
open().

(note that bosh also leaves the temp file behind in that
case).

I can think of several ways to address it:

1- do nothing and blame the user as the user explicitly asked
for files to be unreadable (but then again, it's not obvious
to the user that heredocs imply a temp file)

2- do like AT&T ksh/tcsh (or yash for big heredocs that don't
fit in the pipe buffer) and open the file only once for both
writing the content and making it the command's stdin (with a
lseek() to beginning in between). That means the fd ends up
being writable though I can't see it being a huge problem. (Yash
actually gives the file 000 permissions here regardless of the
umask with open("/tmp/yash-ECCFE6268", O_RDWR|O_CREAT|O_EXCL,
0), but see below about =(...) emulation)

3. do like dash/yash/rc/es and use a pipe instead of a temp
file. That means having to fork a process to feed the data (or
like yash fall back to a temp file for big heredocs). That also
means the fd is no longer seekable

The change could break some scripts for bash, as on Linux (where
/dev/fd/n behaves differently from other *nices), we see some
doing:

cmd1 /dev/fd/3 3<<< "$(cmd2)"

to emulate zsh's cmd1 =(cmd2) (command substitution using a temp
file). (A 0400 umask also makes a =(...) file unreadable, but
definitely here it's the user's problem).

4. Reset the umask temporarily to 077 before creating the temp
file (and block trapped signals until it's restored).


2 would have my preference.

-- 
Stephane


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [minor] umask 400 causes here-{doc,string} failure
  2018-03-11 15:17 [minor] umask 400 causes here-{doc,string} failure Stephane Chazelas
@ 2018-03-13 10:44 ` Joerg Schilling
  0 siblings, 0 replies; 2+ messages in thread
From: Joerg Schilling @ 2018-03-13 10:44 UTC (permalink / raw)
  To: zsh-workers, stephane.chazelas, bug-bash

Stephane Chazelas <stephane.chazelas@gmail.com> wrote:

> Note: sent to bash, zsh and Schily Bourne shell dev mailing
> lists (not mksh as my email provider apparently doesn't play
> well with mirbsd.org's expensive greylisting, please feel free
> to forward there if you don't use gmail).
>
> That's from:
> https://unix.stackexchange.com/questions/429285/cannot-create-temp-file-for-here-document-permission-denied

This is a really interesting problem.

> $ bash -c 'umask 400; cat <<< test'
> bash: cannot create temp file for here-document: Permission denied
> $ zsh -c 'umask 400; cat <<< test'
> zsh:1: can't create temp file for here document: permission denied
> $ bosh -c 'umask 400; cat << EOF
> test
> EOF'
> bosh: /tmp/sh193220: cannot open
> $ mksh -c 'umask 400; cat <<< test'
> mksh: can't open temporary file /tmp/sh933f2z.tmp: Permission denied
>
> Those shells use temporary files to store the content of the
> here-documents as the Bourne shell initially did, and open them
> in read-only mode to make it cat's stdin.

It is a bit more complex:

They first create a temp file for the here document and this is done
before umask(0400) gets executed.

They then create another file that gets the expanded version for the here 
document temp input file. Since this is done after chmod(0400) was executed, 
the second file is not readable.

> When umask contains the 0400 bit, the file is created without
> read permission to the user, hence the error upon that second
> open().
>
> (note that bosh also leaves the temp file behind in that
> case).

This is what bosh inherited from the temp file management from the
SVR4 Bourne Shell that creates hard links to temp files in case there is a 
sub-shell. This in the past created plenty of left over temp files for various 
reasons. At the same time, the original SVR4 Bourne Shell did unlink many of 
the temp files too early. Bosh fixed the latter problem by introducing an io 
barrier in the list of temp files.

The main problem here is that the second (expanded) temp file is not entered 
into the temp file list and thus did not get removed.
With my fixes that keep the file open (see below) the file is now removed before
closing it. I hope this is the only case where temp files still have not been 
removed correctly.


> I can think of several ways to address it:
>
> 1- do nothing and blame the user as the user explicitly asked
> for files to be unreadable (but then again, it's not obvious
> to the user that heredocs imply a temp file)
>
> 2- do like AT&T ksh/tcsh (or yash for big heredocs that don't
> fit in the pipe buffer) and open the file only once for both
> writing the content and making it the command's stdin (with a
> lseek() to beginning in between). That means the fd ends up
> being writable though I can't see it being a huge problem. (Yash
> actually gives the file 000 permissions here regardless of the
> umask with open("/tmp/yash-ECCFE6268", O_RDWR|O_CREAT|O_EXCL,
> 0), but see below about =(...) emulation)

This is not sufficient in case that the original (unexpanded) temp file
was created with 0400 already.

...
> 4. Reset the umask temporarily to 077 before creating the temp
> file (and block trapped signals until it's restored).
>
>
> 2 would have my preference.

See above, this is most likely not sufficient as I am not sure whether it
works to keep the primary temp file open. Ksh93 may do this since it needs to 
implement a more complex housekeeping algorithm as a result of the "virtual 
subshell" feature anyway.

I changed bosh to keep the second temp file open since the original code
creates the file, writes the expanded input to it, closes it and immediately 
reopens it readonly and then removes it.

To fix the write only problem with the primary temp file, I called

	fchmod(fd, 0600)

in the function tmpfil() immediately after the creation of the temp file 
succeeded.

The modified bosh still passes the bosh unit test suite.

Jörg

-- 
 EMail:joerg@schily.net                    (home) Jörg Schilling D-13353 Berlin
    joerg.schilling@fokus.fraunhofer.de (work) Blog: http://schily.blogspot.com/
 URL: http://cdrecord.org/private/ http://sf.net/projects/schilytools/files/'


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-03-13 10:52 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-11 15:17 [minor] umask 400 causes here-{doc,string} failure Stephane Chazelas
2018-03-13 10:44 ` Joerg Schilling

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).