zsh-workers
 help / color / mirror / code / Atom feed
From: Daniel Shahaf <d.s@daniel.shahaf.name>
To: zsh-workers@zsh.org
Subject: Re: PATCH: [for consideration] TMPSUFFIX
Date: Tue, 27 Sep 2016 07:00:39 +0000	[thread overview]
Message-ID: <20160927070039.GA20798@fujitsu.shahaf.local2> (raw)
In-Reply-To: <160926091922.ZM26758@torch.brasslantern.com>

Bart Schaefer wrote on Mon, Sep 26, 2016 at 09:19:22 -0700:
> On Sep 26,  7:25am, Daniel Shahaf wrote:
> } Subject: Re: PATCH: [for consideration] TMPSUFFIX
> }
> } This looks like a race condition: if another process creates the
> } filename that mktemp() returned before the open(O_EXCL) call [which will
> } therefore fail], zsh will remove that filename even though zsh didn't
> } create it.
> 
> If another process creates the filename that mktemp() returned, we have
> a much larger problem -- the whole point is that it should be impossible
> for another process to create that name first.
> 

That is not impossible; it is only improbable.  That's why O_EXCL is
passed to the open() call that receives the name returned by mktemp().

It would be impossible if the code used mkstemp().

> } [This could trigger through a deliberate attack or through
> } a race condition between two zsh instances calling =(:) concurrently.]
> 
> It definitely CANNOT occur because of two zsh instances using =().  I

In the time window between mktemp() returning and open() called,
a second zsh process could call mktemp() and be returned the same value
that was returned in the first process, couldn't it?

I think it's more likely that a name of the form ${TMPPREFIX}XXXXXX
would be created by another zsh process that has the same $TMPPREFIX
setting than by an attacker.

> won't assert the attack is 100% impossible, but there's nothing more
> we can do about that than we already have.
> 

Yes, there is: we should stop calling addfilelist(nam) if open(nam)
returns negative.

(Sidebar: that mktemp() call is the only warning in my build; it'd be
nice to get rid of it while we're here.)

> So mostly we're concerned with $TMPDIR being unwritable, or full file
> system, etc. -- but of course failure for any other reason including
> attacker-duplicated file name would get swept up if we change the way
> failure is handled.
> 

Agreed, all failure reasons can be handled the same way.

> } I don't get "the caller will create the file".  [...]
> } (The caller can call getoutputfile() again if he wishes.)
> 
> The SHELL SCRIPT caller, not the C code caller.  That is, as currently
> coded, =(...) will substitute a file name whether or not it actually got
> created.  In a case like
> 
>     () { ... do something with $1 ... } =(contents)
> 
> the name in $1 could be used in output redirections, etc.  As written,
> exec.c seems intended to allow this.
> 

I checked 'blame' to find the original motivation for that, but the
lines in question predate the import to git.

> } How is it helpful to return a filename, which may or may not exist and
> } certainly doesn't contain the output of 'cmd'? It seems to me erroring
> } out would be better.
> 
> It'd have to be an error on the same order as "bad substitution" so the
> whole command context fails.  Hence bringing it up for discussion.

I don't know what's best here.

I'm quite sure that if open() fails, we mustn't pass the filename we
tried to code that expects to receive a newly-created filename, since
that exposes us to a symlink attack.

Using ERRFLAG_ERROR risks aborting too much code (39154 being a recent
example).

A middle way would be to force the simple command that =(:) was part to
return 127.  When =(:) is used a an argument to an anonymous function,
that would prevent the function's body from being executed with an
invalid filename argument, which is good... but nobody checks the exit
code of such anonymous functions, so code _after_ the anonymous function
might break because it assumes the function was executed.

Maybe there's some simple solution that I'm overlooking.  (And with any
luck, it will appear in my -workers@ mailbox in the near future ;-).)

Cheers,

Daniel


  reply	other threads:[~2016-09-27  7:01 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-25 22:51 Bart Schaefer
2016-09-26  7:25 ` Daniel Shahaf
2016-09-26 16:19   ` Bart Schaefer
2016-09-27  7:00     ` Daniel Shahaf [this message]
2016-09-27 19:20       ` Bart Schaefer
2016-09-28 10:24         ` Daniel Shahaf
2016-09-28 18:49           ` _dispatch (was Re: PATCH: [for consideration] TMPSUFFIX) Bart Schaefer
2016-09-29  6:39             ` Daniel Shahaf
2016-09-29  7:30               ` Bart Schaefer
2016-09-30  7:03                 ` Daniel Shahaf
2016-09-30 21:53                   ` Bart Schaefer
2016-09-28  6:09 ` PATCH: [for consideration] TMPSUFFIX Sebastian Gniazdowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160927070039.GA20798@fujitsu.shahaf.local2 \
    --to=d.s@daniel.shahaf.name \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).