Subject: bug#30918: Don't use syscall() to call renameat2()

From: Richard Purdie <[email-masked]>
Date: Sun, 25 Mar 2018 11:15:48 +0100

> On 03/23/2018 10:38 AM, Ross Burton wrote:
> > Please consider changing renameat2.c so that it doesn't hit 
> > syscall() if the wrapper isn't available.
> 
> That would reintroduce race-condition security holes in the ordinary 
> build of GNU Coreutils on GNU/Linux, which would not be a good 
> thing. Instead, how about fixing fakeroot so that it traps 'syscall' 
> and fails with errno == ENOTSUP? Better yet, fix fakeroot so that it 
> implements the renameat2 semantics with that syscall. (Or even 
> better, add renameat2 to both glibc and fakeroot. :-)

I've just had a look at this situation and its not as simple as it may
first appear. The function prototype for syscall() in posix/unistd.h
is:

extern long int syscall (long int __sysno, ...)

and the implementation in glibc is in assembler for each architecture.
The syscall(2) man page also gives a little bit more of a hint of the
challenges in the syscall() function with register splits and alignment
along with different forms of error handling. You can call it with
varying numbers of options and the register usage needs to be tightly
controlled, its not a "normal" function where standard function calling
conventions will always work.

So yes, we could add a wrapper in pseudo however we're likely going to
have to end up using assembler to avoid smashing the calling stack in
the general case. That would be on a per architecture basis and comes
with all the complexities that brings.

I'd therefore like to add my own plea to figure out and use some glibc
API for this even if we have to establish it.

Cheers,

Richard