This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Running GCC as root


"Maciej W. Rozycki" <macro@linux-mips.org> writes:

> On Mon, 14 Feb 2005, Daniel Jacobowitz wrote:
>
>> > If we are in fact trying to cater to people who run the full compiler
>> > as root, then I suppose there's some auditing to be done to make sure
>> > GCC itself doesn't unlink /dev/null ever, or similar things...
>> 
>> I'm pretty sure that one's already _been_ done.  And in binutils too.
>> I'm just going from memory though.
>
>  Only in GCC.  For gas you need the -Z option, which is not exactly the 
> same and is going to break Makefiles if used (and you get funny 
> dependencies if you hit an internal error).  For ld apparently there is no 
> option to keep output at all.

"Keep output on errors" is not at all the same as "don't unlink the
output if it's not a regular file", which is the way to avoid
destroying /dev/null.

Experimentally ...

$ cd /tmp
$ printf "\t.text\n\t.long 0\n" > test.s
$ touch test.o

$ as --version | head -1
GNU assembler 2.15
$ strace as test.s -o test.o 2>&1 | grep test\\.o | grep -v execve
stat64("test.o", {st_mode=S_IFREG|0664, st_size=445, ...}) = 0
unlink("test.o")                        = 0
open("test.o", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3

and ...

$ strace as -Z test.s -o test.o 2>&1 | grep test\\.o | grep -v execve
stat64("test.o", {st_mode=S_IFREG|0664, st_size=445, ...}) = 0
unlink("test.o")                        = 0
open("test.o", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3

but ...

$ sudo mknod null c 1 3
$ sudo chmod 666 null
$ strace as -Z test.s -o null 2>&1 | grep null | grep -v execve
stat64("null", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
open("null", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3

so gas does seem to do the right thing in this case.  I also observe
the same pattern for ld.

There's a related problem, though: the opens are not using O_EXCL,
which means there may be an exploitable race condition in here, if
root is running the assembler or linker in /tmp:

process 1 (as, root):               process 2 (exploit, not-root):
  stat("test.o") = nonexistent
                                    symlink("/etc/passwd", "test.o")
  open("test.o", O_RDWR|O_CREAT|O_TRUNC)
    -- destroys /etc/passwd

Similar bugs were fixed in cc1 and the gcc driver many years ago.  (If
it were me, I would be writing output to a temporary file and renaming
it into place once it was complete, unless the output existed and was
not a regular file, in which case the existing behavior is correct.)

zw


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]