Stefan Sperling wrote on Tue, Mar 05, 2013 at 14:24:32 +0100:
> On Tue, Mar 05, 2013 at 02:07:11PM +0100, Bert Huijben wrote:
> > > @@ -1743,7 +1743,12 @@ svn_subst_copy_and_translate4(const char
> > >      }
> > > 
> > >    /* Now that dst_tmp contains the translated data, do the atomic rename.
> > > */
> > > -  return svn_error_trace(svn_io_file_rename(dst_tmp, dst, pool));
> > > +  SVN_ERR(svn_io_file_rename(dst_tmp, dst, pool));
> > > +
> > > +  /* Preserve the source file's permission bits. */
> > > +  SVN_ERR(svn_io_copy_perms(src, dst, pool));
> > > +
> > > +  return SVN_NO_ERROR;
> > >  }
> > 
> > There is a possible race condition here, which might be resolved by copying 
> > the permissions before moving. 
> > (But most likely you just get a different race condition by switching the 
> > order)
> 
> Yes, and I believe the other race conditition is more dangerous.
> 
> If the temp file is within a system-wide temp dir, and we end up expanding

When exactly is that going to happen?  You call svn_stream_open_unique()
with dirpath != NULL, so the tempdir it will use is ./ (neither /tmp or
.svn/tmp/).

> read permission on the file in the system-wide temp dir, we might end up
> leaking secrets to observers that manage to access the temporary file after
> perms have been set but before the file is renamed.
> 
> Of course, most of the time the temp file will be within the .svn/tmp area,

Again: AFAICT, the tempfile will live in ./, neither /tmp nor .svn/tmp/.
Is that not the case?

> in which case this doesn't really matter. If the working copy contains
> secrets it had better be within a directory that untrusted users cannot
> access. But I think the code should at least set a good example.
> 

So, can someone explain to me what the "other" race condition is?  The
current code is racy because DST_TMP has (0777 &~ umask) perms while it
is being written to.  Creating DST_TMP and immediately chmod'ing it
would also be racy (since we don't use the third argument to open(2)), 
but that race would last a shorter amount of time, and therefore is
preferable to the current trunk@HEAD code...

> Ideally, we'd have an API we could use to obtain file permissions at the
> beginning of the translation operation, and one to set those perms when
> the operation is done. But svn_io_* doesn't provide that.
> 

It seems to me a "best" fix here would be to use the three-argument form
of open(2) --- i.e., to create the tempfile with the right permissions
to begin with, and at the end of translation just rename(2) the tempfile
without having to worry about permissions.

> BTW, svn_io_copy_file() also copies perms to the temp file before renaming it,
> and is thus vulnerable to a potential data leak as described above.
> I think we should fix that. But again, that function uses the .svn/tmp dir
> and not a system-wide one.

Again, that function passes svn_dirent_dirname(dst) for dirpath, so it
won't use the system-wide tempdir.?

Reply via email to