On Tue, Jul 24, 2012, Oleg Goldshmidt wrote about "Re: how to redirect in 
bash+crontab":
> But you cannot write(2) before you open(2), can you?
>...
> Which s true for file descriptors (e.g., dup()), but to redirect to a file
> you do need to open(2) the file, methinks.

To write(2) you need a file descriptor, but there are many ways to get a
file descriptor besides open(2).

One very common way is to inherit a file descriptor from the parent
process - e.g., consider that a root-owned process opens a root-owned
file, and then forks and the child setuid() to nonroot. The child now
has an open file, which it can fully use, but could have never opened
himself. This is more-or-less how your crontab script got its output file
descriptor - it never open()ed any file.

A process can also acquire an open file descriptor from a local server
(potentially running with the permissions of another user) by using a
little known (but very important) feature of Unix-Domain sockets -
again, see unix(7) for the whole story.

But the end result is that it isn't all that rare for a process to have
access to a file descriptor it couldn't have opened on its own.
A new attempt to open this file through the symbolic link in
/proc/self/fd/2 would now fail, but were /dev/fd/2 implemented as a
device, not a magic directory like in Linux, it would have worked - but
you'd have lost the ability to learn with readlink(2) what is opened on
this file descriptor.


> Whatever crontab uses is irrelevant since all there is in crontab is the
> name of a script that is explicitly #!/bin/bash (and al the scripts that
> are called are explicitly bash as well).
> 
> Strictly speaking, "man bash" does not explicitly say it does not open()
> /dev/stderr (it says it dup()s but does not say this is the only thing it
> does). Nevertheless I think the documentation's intent is exactly that - no
> open(), or at least ignoring mode during open(), consistent with the
> /dev/fd/* behaviour as described by Stevens and everywhere else.

Then this is clearly a bash *bug* - the manual explictly said that when
it sees redirection to "/dev/fd/*" or "/dev/stderr" etc., this file is
NOT actually used, but rather, quoting the manual, "File descriptor 2 is
duplicated". dup(2) can never fail with EACCES - it will succeed no
matter who opened file descriptor 2. If bash does open the real file
"/dev/fd/*" or "/dev/stderr" then this is clearly contrary to the
manual- so either the manual or implementation is wrong.

That being said, I hope they change the manual, not the implementation.
I don't see any reason why the shell needs to override /dev/stderr.
And if it overrides /dev/stderr, why stop there and not also override
writes to /dev/tty, or reads from /dev/urandom, or whatever?

> I would be curious to know how recent versions of
> SuSE/debian/ubuntu/*BSD/Mac OS X/whatever implement /dev/stderr.

Last time I checked BSD, Solaris, and other Unix variants, /dev/stderr
was a character-special device, not a symlink. Sadly, I no longer have
access to any non-Linux Unix-like operating system, so I can't check
now.

-- 
Nadav Har'El                        |          Tuesday, Jul 24 2012, 6 Av 5772
n...@math.technion.ac.il             |-----------------------------------------
Phone +972-523-790466, ICQ 13349191 |"God is dead." - Nietzsche; "Nietzsche is
http://nadav.harel.org.il           |dead" - God

_______________________________________________
Linux-il mailing list
Linux-il@cs.huji.ac.il
http://mailman.cs.huji.ac.il/mailman/listinfo/linux-il

Reply via email to