Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

reopen an O_RDONLY file descriptor for O_RDWR

565 views
Skip to first unread message

Albert Cheng

unread,
Jun 14, 1995, 3:00:00 AM6/14/95
to
I am working on a subroutine which accepts a file descriptor
and after some calculations, tries to write some data to the
FD. There is a chance that the FD has been opened O_RDONLY but
my routine wants to "reset" it to be writable. The filename
is not available any more, at least not within my routine, but
I know program has enough privilage to have opened it for write.
Someone has suggested

fcntl(fd, F_SETFL, ..)

but that allows O_APPEND only. I need write access to all offset
positions. Anyone knows a unix portable way to "set a readonly file
descriptor for write access?"

Thanks for any help.

=Albert Cheng

P.S. Logic-wise, I should not violate a readonly file descriptor. Let
me say, "It was not my design and I inherited the code." A programmer
has to do what a programmer must do.


Out of his mind

unread,
Jun 18, 1995, 3:00:00 AM6/18/95
to
On 18 Jun 1995, Albert Cheng wrote:

> Now, I wonder why so? I can see changing an O_RDONLY fd to writable
> have many problems such as file lock conflicts, read-only device (CD-ROM),
> permissions, ... What I don't understand is why fcntl() accepts O_APPEND
> but not O_RDWR? Is there a basic Unix design/limit that makes append
> acceptable but random-write impossible?

First of all, some *IX kernels store the file mode as O_ flags while others
store it as F flags (FREAD, FWRITE bits). Second, when a vfs open is
called, it receives the type of open for a file. That is how it checks
access permissions (i.e. if you don't have write access for a file, you
can't open it O_RDWR or O_WRONLY but you can open it O_RDONLY); the
filesystem would get mighty confused if you then had write privilege to a
file you didn't originally have write privilege to. Otherwise, there'd be a
security hole.

-----
=== Todd Vierling - UFNet, AmiNIX - to...@ufnet.ufl.edu, ami...@aminix.org ===
== Have you done your reality check today? == Hey Kids...what time is it?? ==
== LAISSEZ-FAIRE - No Internet Censorship! == (It's Pol-i-ti-cian Time!!!) ==
== Go Woody! Now I wonder how the Shuttles stand up to those meteorites... ==


Out of his mind

unread,
Jun 18, 1995, 3:00:00 AM6/18/95
to
On 14 Jun 1995, Albert Cheng wrote:

> I am working on a subroutine which accepts a file descriptor
> and after some calculations, tries to write some data to the
> FD. There is a chance that the FD has been opened O_RDONLY but
> my routine wants to "reset" it to be writable. The filename
> is not available any more, at least not within my routine, but
> I know program has enough privilage to have opened it for write.
> Someone has suggested
>
> fcntl(fd, F_SETFL, ..)

If you use this you must use the FREAD/FWRITE bit definitions. However,
most implementations won't allow you to set it, and basically, you're
screwed.

Albert Cheng

unread,
Jun 18, 1995, 3:00:00 AM6/18/95
to
I got several replies to my question. Basically, it can't be done.
I just have to give up.

Now, I wonder why so? I can see changing an O_RDONLY fd to writable
have many problems such as file lock conflicts, read-only device (CD-ROM),
permissions, ... What I don't understand is why fcntl() accepts O_APPEND
but not O_RDWR? Is there a basic Unix design/limit that makes append
acceptable but random-write impossible?

=Albert Cheng

In article <3rn0u7$l...@news.iastate.edu>, ach...@shalom.ncsa.uiuc.edu (Albert Cheng) writes:
>I am working on a subroutine which accepts a file descriptor
>and after some calculations, tries to write some data to the
>FD. There is a chance that the FD has been opened O_RDONLY but
>my routine wants to "reset" it to be writable. The filename
>is not available any more, at least not within my routine, but
>I know program has enough privilage to have opened it for write.
>Someone has suggested
>
> fcntl(fd, F_SETFL, ..)
>

>but that allows O_APPEND only. I need write access to all offset
>positions. Anyone knows a unix portable way to "set a readonly file
>descriptor for write access?"

>...

Nathan Lawson

unread,
Jun 18, 1995, 3:00:00 AM6/18/95
to
Albert Cheng <ach...@shalom.ncsa.uiuc.edu> wrote:
>Now, I wonder why so? I can see changing an O_RDONLY fd to writable
>have many problems such as file lock conflicts, read-only device (CD-ROM),
>permissions, ... What I don't understand is why fcntl() accepts O_APPEND
>but not O_RDWR? Is there a basic Unix design/limit that makes append
>acceptable but random-write impossible?

My guess is that this was done as an easy way of keeping forked processes
from inheriting any privileges. This would be a tidy way of keeping
logfiles (open the descriptor RDONLY and then pass it on exec). It also
might be a throwback to the days when a device opened RDONLY probably wasn't
capable of seeking. Remember that random access devices are a relatively
new source of data, at least in the Unix timeline.

--
= Nathan Lawson = I, the unwilling, led by the unknowing,
- nla...@phoenix.calpoly.edu - am doing the impossible, for the ungrateful
=------------------------------=

John Hascall

unread,
Jun 18, 1995, 3:00:00 AM6/18/95
to
Out of his mind <amig...@vaxu.org> wrote:

}On 18 Jun 1995, Albert Cheng wrote:
}
}> Now, I wonder why so? I can see changing an O_RDONLY fd to writable
}> have many problems such as file lock conflicts, read-only device (CD-ROM),
}> permissions, ... What I don't understand is why fcntl() accepts O_APPEND
}> but not O_RDWR? Is there a basic Unix design/limit that makes append
}> acceptable but random-write impossible?
}
}First of all, some *IX kernels store the file mode as O_ flags while others
}store it as F flags (FREAD, FWRITE bits). Second, when a vfs open is
}called, it receives the type of open for a file. That is how it checks
}access permissions (i.e. if you don't have write access for a file, you
}can't open it O_RDWR or O_WRONLY but you can open it O_RDONLY); the
}filesystem would get mighty confused if you then had write privilege to a
}file you didn't originally have write privilege to. Otherwise, there'd be a
}security hole.

I think he was asking why a "fdreopen(fd, newmode)" syscall couldn't do
the appropriate access checks.

And although I think it would almost work for UFS it *might* present a
problem for other (future) filesystem types. Given that it could work,
I'm not certain it would be desirable.

Why I think it would "work" for UFS. Normally, open permission checking
traverses the directory tree from / to the requested file, checking the
permission bits of the directories in between. This tree would not be
available to fdreopen(), in fact it might no longer exists.

But IF you make the assumption that if the directory tree allowed you
access to the file for open in the first place, then it allows you access
to change it for writing implicitly (so you don't need to check it again),
so you need only check the mode bits of the file itself.

This works because the checking of the directories in the filepath
doesn't vary based on whether the file access requested is read or
write with one possible exception the "directory-sticky-bit hack".
(that's the "almost works" qualifier). Perhaps if it were restricted
to the file-owner and superuser.

It gets pretty ugly.

John
--
John Hascall ``An ill-chosen word is the fool's messenger.''
Moderator, comp.unix.wizards
Systems Software Engineer, ISU Comp Center + Ames, IA 50011 + 515/294-9551
<a href="http://www.cc.iastate.edu/staff/systems/john/"> My Homepage </a>

Guy Harris

unread,
Jun 19, 1995, 3:00:00 AM6/19/95
to
Albert Cheng <ach...@shalom.ncsa.uiuc.edu> wrote:
>What I don't understand is why fcntl() accepts O_APPEND
>but not O_RDWR? Is there a basic Unix design/limit that makes append
>acceptable but random-write impossible?

No.

There is not, at least in most UNIX systems, a notion of "append-only"
files, so there's no need to check permission bits when turning O_APPEND
*OFF* (there's obviously no need to do so when turning it *on*).

Note that turning O_APPEND on for a read-only file descriptor does *NOT*
magically make the descriptor writable, so it's not as if you can take a
read-only descriptor and, merely by turning O_APPEND on, make it allow
append writes. Turning O_APPEND on or off makes sense only for
write-only or read/write descriptors, and I'm not even sure when
anybody'd want to change the mode *then*, at least on systems where you
can *open* with O_APPEND.

There *is*, however, an obvious need to check permissions when changing
a descriptor from O_RDONLY to O_RDWR.

Nathan Lawson <nla...@phoenix.csc.calpoly.edu> wrote:
>My guess is that this was done as an easy way of keeping forked processes
>from inheriting any privileges. This would be a tidy way of keeping
>logfiles (open the descriptor RDONLY and then pass it on exec).

The child process would, as per the above, not be able to log stuff to
that logfile - it could turn O_APPEND on, but that wouldn't let it write
to the file descriptor.

It *might* have been considered a Good Thing to allow a parent process
to prevent a child process from writing to a file descriptor, but I
don't know that this was the rationale for disallowing changing the
read-only/write-only/read-write mode of a descriptor.

>It also
>might be a throwback to the days when a device opened RDONLY probably wasn't
>capable of seeking.

Eh? I know of no "device" that is incapable of seeking if opened RDONLY
but that is capable of it when opened RDWR. Pipes and some special
files are incapable of seeking, but that's true even if they're opened
read/write; plain files have been capable of seeking, whether opened
read-only, write-only, or read/write, at least as far back as V6 in
1975, and probably considerably earlier than that.

>Remember that random access devices are a relatively
>new source of data, at least in the Unix timeline.

Not *very* new - random access to UNIX files, as indicated, dates back
at *least* to 1975, and probably antedates that.

Robert Forsman

unread,
Jun 20, 1995, 3:00:00 AM6/20/95
to

g...@netapp.com (Guy Harris) wrote:

> Nathan Lawson <nla...@phoenix.csc.calpoly.edu> wrote:
> >My guess is that this was done as an easy way of keeping forked processes
> >from inheriting any privileges. This would be a tidy way of keeping
> >logfiles (open the descriptor RDONLY and then pass it on exec).
>
> The child process would, as per the above, not be able to log stuff to
> that logfile - it could turn O_APPEND on, but that wouldn't let it write
> to the file descriptor.
>
> It *might* have been considered a Good Thing to allow a parent process
> to prevent a child process from writing to a file descriptor, but I
> don't know that this was the rationale for disallowing changing the
> read-only/write-only/read-write mode of a descriptor.

The child/log-file argument is not a good one. If the log file is
one the child can't write to, then the conversion from RDONLY to RDWR
would return an EPERM or some such. If it is a file the child can
write to, then there is a computable way to find the file in some
instances:

Use fstat on the file descriptor and then probe the entire file
system looking for a file with identical dev and ino.

This doesn't work when the file is unlinked, though.

ANYway, it seems reasonable to have a system/ioctl call that turns a
RDONLY file descriptor into a RDWR one. It just has to check the
permissions a-la file open.

The only thing standing in the way is a few hundred lines of code to
write and debug
--
Eat now this hot-dog with ketchup, flesh of his flesh, blood of his blood.
Supercalafragalisticextrasacreligious
I deal with Reality as you _don't_ understand it.
blah = realloc(blah, sizeof(*blah)*(blahsize*=2)); /* (TM) */

Wolfgang Denk

unread,
Jun 20, 1995, 3:00:00 AM6/20/95
to
jo...@iastate.edu (John Hascall) writes:

>Out of his mind <amig...@vaxu.org> wrote:
>}On 18 Jun 1995, Albert Cheng wrote:
>}
>}> Now, I wonder why so? I can see changing an O_RDONLY fd to writable
>}> have many problems such as file lock conflicts, read-only device (CD-ROM),

>}> permissions, ... What I don't understand is why fcntl() accepts O_APPEND


>}> but not O_RDWR? Is there a basic Unix design/limit that makes append
>}> acceptable but random-write impossible?

> Why I think it would "work" for UFS. Normally, open permission checking


> traverses the directory tree from / to the requested file, checking the
> permission bits of the directories in between. This tree would not be
> available to fdreopen(), in fact it might no longer exists.

The tree would not be needed any more. All permission bits for the
file itself are in the file inode which is very well known when as
long as the file is open.

Wolfgang

Phone: (+49)-89-95720-110 Fax: (+49)-89-95720-112 w...@denx.muc.de
Office: (+49)-89-722-41782 w...@uebemc.siemens.de
We are all agreed that your theory is crazy. The question which
divides us is whether it is crazy enough to have a chance of being
correct. My own feeling is that it is not crazy enough. - Niels Bohr

Jim Cathey

unread,
Jun 26, 1995, 3:00:00 AM6/26/95
to
In article <3s4mc2$e...@news.iastate.edu> g...@netapp.com (Guy Harris) writes:
>append writes. Turning O_APPEND on or off makes sense only for
>write-only or read/write descriptors, and I'm not even sure when
>anybody'd want to change the mode *then*, at least on systems where you
>can *open* with O_APPEND.

One place where this is used is when processing /etc/utmp during the
login process. If login's updating an existing record it needs to be
able to write into the middle of the file, O_APPEND cannot be on. If
instead it finds it has to add a record to the file, it first turns on
O_APPEND so that if two such logins occur simultaneously both will
reliably get new records.

>There *is*, however, an obvious need to check permissions when changing
>a descriptor from O_RDONLY to O_RDWR.

What permissions, exactly? The file could have been unlinked, or
chowned. The process could have setuid'd to something else, etc.
It's a can of worms, best left unopened methinks.

>It *might* have been considered a Good Thing to allow a parent process
>to prevent a child process from writing to a file descriptor, but I
>don't know that this was the rationale for disallowing changing the
>read-only/write-only/read-write mode of a descriptor.

This sounds likely.


--
+----------------+
! II CCCCCC ! Jim Cathey
! II SSSSCC ! ISC-Bunker Ramo
! II CC ! TAF-C8; Spokane, WA 99220
! IISSSS CC ! UUCP: uunet!isc-br!jimc (ji...@isc-br.isc-br.com)
! II CCCCCC ! (509) 927-5757

Christoph Badura

unread,
Jun 26, 1995, 3:00:00 AM6/26/95
to
In <3s6rgg$9...@news.iastate.edu> th...@cis.ufl.edu (Robert Forsman) writes:

>g...@netapp.com (Guy Harris) wrote:
>> It *might* have been considered a Good Thing to allow a parent process
>> to prevent a child process from writing to a file descriptor, but I
>> don't know that this was the rationale for disallowing changing the
>> read-only/write-only/read-write mode of a descriptor.

> The child/log-file argument is not a good one. If the log file is


>one the child can't write to, then the conversion from RDONLY to RDWR
>would return an EPERM or some such. If it is a file the child can
>write to, then there is a computable way to find the file in some
>instances:

Actually, the child/logfile argument is a good one. E.g. the file
descriptor for logfile could have been obtained by a privileged
process as append only and passed to an un-privileged process for
logging purposes. The logfile might contain other unrelated but
highly sensible information. If the un-privileged process were
allowed to get read access to the logfile this would open a security
hole.

If you execute

su nobody -c "foo" >>/dev/console 2>&1

from the system initialisation scripts, you wouldn't want food to be
able to gain read access to /dev/console and perform the following
dialogue:

login: root
Password: Top%SecreT

Also, the actual permissions might not allow *any* access to the file for
the process trying to change the access mode. E.g.

touch foo-file
chmod 777 foo-file
(sleep 10; foo ) <foo-file &
chmod 0 foo-file

When foo tries to gain write access to fd 0 the kernel would discover
that foo now doesn't even have read access.

There are other problems. E.g. what should be done if the process is
chroot(2)ed and the file descriptor refers to a file above its root?

There is a reason that under Unix a process is granted a specific
access mode to a file when that process opens the file. Once the
access mode has been granted the process retains it until it
closes the file[*]. read(2) and write(2) (and similar system calls) only
check if the file descriptor was opened with the appropriate mode.

Finally, I feel very uncomfortable if any random process could get
more powerful access to a file that I, the user (or worse the
sysadmin), wanted it to have.

[*]
OK, so some systems have a revoke(2) system call (or similar
functionality) and can revoke access rights to an open file
descriptor. And a process can give up access rights.

But there's not even a grant(2) system call, that allows a privileged
process to "upgrade" the access rights of an open file descriptor.

--
Christoph Badura b...@flatlin.ka.sub.org +49 721 606137

Es genuegt nicht, keine Gedanken zu haben;
man muss auch unfaehig sein, sie auszudruecken. - Karl Kraus

Lyle Seaman

unread,
Jun 26, 1995, 3:00:00 AM6/26/95
to
ji...@tau-ceti.isc-br.com (Jim Cathey) writes:
> In article <3s4mc2$e...@news.iastate.edu> g...@netapp.com (Guy Harris) writes:
> >There *is*, however, an obvious need to check permissions when changing
> >a descriptor from O_RDONLY to O_RDWR.
>
> What permissions, exactly? The file could have been unlinked, or
> chowned. The process could have setuid'd to something else, etc.
> It's a can of worms, best left unopened methinks.

Without debating the dubious value of such a feature, maybe someone
can explain to me the harm of allowing writes to an unlinked file,
to which write access had previously been denied me?

I just don't see the big deal.
if (!VOP_ACCESS(vp, VWRITE...))


0 new messages