* tty O_NONBLOCK spooky action at a distance
@ 2007-06-30 7:35 Alan Curry
2007-06-30 10:04 ` Alan Cox
0 siblings, 1 reply; 2+ messages in thread
From: Alan Curry @ 2007-06-30 7:35 UTC (permalink / raw)
To: linux-kernel
Short version: writing to a tty with O_NONBLOCK will block if there is
another, unrelated process already blocking inside a write() to the same tty.
Long version:
Take this test program, nbhello.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int fd;
if(argc!=2) {
fprintf(stderr, "Usage: %s tty\n", argv[0]);
return 2;
}
fd=open(argv[1], O_WRONLY|O_NONBLOCK);
if(fd<0) {
perror("open");
return 1;
}
if(write(fd, "hello world\n", 12)<0) {
perror("write");
return 1;
}
return 0;
}
Open a tty for testing purposes; I do this by logging in on tty11, but
starting a new xterm works just as well. Press ^S on the test tty to block
output. Back on your original tty:
$ cc nbhello.c -o nbhello
$ ./nbhello /dev/tty11
This will report an EAGAIN, as it should.
$ echo block > /dev/tty11
This will block, as it should. ^C to kill it.
$ echo block > /dev/tty11 &
$ ./nbhello /dev/tty11
With a background process blocking in an attempt to write() on the tty, the
non-blocking write also blocks! If you kill the background process first, the
"non-blocking" write will wake up and return EAGAIN.
I've been surprised before by the way O_NONBLOCK propagates from a forked
child back up to the parent's file descriptors, but this not the same thing.
The file descriptors involved here have come from 2 completely separate
open()s.
(Real-world impact of this bug: wall(1) uses O_NONBLOCK to avoid getting
stuck if a user has paused a tty with ^S, but the kernel doesn't respect the
flag and wall gets stuck anyway. When the user finally hits ^Q -- hours,
days, or weeks later -- he gets the message and so does everyone who was
after him in utmp.)
--
Alan Curry
pacman@world.std.com
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: tty O_NONBLOCK spooky action at a distance
2007-06-30 7:35 tty O_NONBLOCK spooky action at a distance Alan Curry
@ 2007-06-30 10:04 ` Alan Cox
0 siblings, 0 replies; 2+ messages in thread
From: Alan Cox @ 2007-06-30 10:04 UTC (permalink / raw)
To: Alan Curry; +Cc: linux-kernel
On Sat, 30 Jun 2007 03:35:07 -0400 (EDT)
Alan Curry <pacman@TheWorld.com> wrote:
> Short version: writing to a tty with O_NONBLOCK will block if there is
> another, unrelated process already blocking inside a write() to the same tty.
I sent Linus patches to fix this minor DoS flaw some time ago. I've
no idea why they still didn't make the base kernel. They are however in
the -mm tree and I'm suprised vendors haven't picked them up. I'll push
them again for 2.6.23-rc1 if Andrew doesn't do it himself.
In general currently I'd strongly recommend the -mm tree. It is
the only kernel which has revoke() support - which is needed to deal with
all sorts of interesting abuses on any system with multiple console users
(SELinux may also save you here). It's also got a lot of ATA layer fixes
so is much more reliable with SATA or with libata PATA at the moment.
Of course the fact it has all the cool stuff means it may also have more
bugs but you can't have everything.
Alan
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-06-30 9:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-30 7:35 tty O_NONBLOCK spooky action at a distance Alan Curry
2007-06-30 10:04 ` Alan Cox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®