revoke(2) redux...
I've been studying revoke(2), and somehow fail to see it fulfill its promise from the man-page. Consider this piece of code from init(8): /* * Start a session and allocate a controlling terminal. * Only called by children of init after forking. */ void setctty(char *name) { int fd; (void) revoke(name); if ((fd = open(name, O_RDWR)) == -1) { stall(can't open %s: %m, name); _exit(1); } Isn't there a pretty obvious race between the revoke() and the open() ? Wouldn't it in fact make much more sense if revoke(2) was defined as int revoke(int fd); /* kick everybody else off */ and the code above would look like: if ((fd = open(name, O_RDWR)) == -1) { stall(can't open %s: %m, name); _exit(1); } (void) revoke(fd); -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 [EMAIL PROTECTED] | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
On Tue, Dec 24, 2002 at 12:40:25PM +0100, Poul-Henning Kamp wrote: Wouldn't it in fact make much more sense if revoke(2) was defined as int revoke(int fd); /* kick everybody else off */ and the code above would look like: An O_REVOKE flag to open might be neater? David. To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
-- From: Poul-Henning Kamp [EMAIL PROTECTED] void setctty(char *name) { (void) revoke(name); if ((fd = open(name, O_RDWR)) == -1) { Isn't there a pretty obvious race between the revoke() and the open() ? Wouldn't it in fact make much more sense if revoke(2) was defined as int revoke(int fd);/* kick everybody else off */ and the code above would look like: if ((fd = open(name, O_RDWR)) == -1) { } (void) revoke(fd); But, revoke() invalidates all descriptors for the named path, so any subsequent operations on the open file descriptor would fail, which defeats the purpose of open(). I think what's needed is some form of serialization around revoke() and open(). I'm not a master of the init code, but it may be that the code is inherently non-reentrant, so the original code would then be okay. Paul Paul A. Scott mailto:[EMAIL PROTECTED] http://skycoast.us/pscott/ To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
On Tue, 24 Dec 2002, Poul-Henning Kamp wrote: Isn't there a pretty obvious race between the revoke() and the open() ? Wouldn't it in fact make much more sense if revoke(2) was defined as int revoke(int fd); /* kick everybody else off */ and the code above would look like: There are many races here, but one race is closed by this. The way the login process works is that it chowns the device, then revokes the device. If the problem being addressed is that fd's remain open even after the chown, then revoke works fine, since once you've chowned/chmodded the file, the original process with a normal user uid can't re-open. That said, revoke() has terrible properties from a VFS perspective. I'd be interested in learning about the approaches taken in Linux, etc, to address the same problem. Robert N M Watson FreeBSD Core Team, TrustedBSD Projects [EMAIL PROTECTED] Network Associates Laboratories To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
In message [EMAIL PROTECTED], Paul A. Scott writes: -- From: Poul-Henning Kamp [EMAIL PROTECTED] void setctty(char *name) { (void) revoke(name); if ((fd = open(name, O_RDWR)) == -1) { Isn't there a pretty obvious race between the revoke() and the open() ? Wouldn't it in fact make much more sense if revoke(2) was defined as int revoke(int fd);/* kick everybody else off */ and the code above would look like: if ((fd = open(name, O_RDWR)) == -1) { } (void) revoke(fd); But, revoke() invalidates all descriptors for the named path, so any subsequent operations on the open file descriptor would fail, which defeats the purpose of open(). I think you missed the fine point in the kick everybody *else* off comment. I think what's needed is some form of serialization around revoke() and open(). I'm not a master of the init code, but it may be that the code is inherently non-reentrant, so the original code would then be okay. There is more code like this in places. The point is you cannot serialize against other processes. -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 [EMAIL PROTECTED] | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
From: Paul A. Scott [EMAIL PROTECTED] I think what's needed is some form of serialization around revoke() and open(). I'm not a master of the init code, but it may be that the code is inherently non-reentrant, so the original code would then be okay. Or, it may use spltty()? Or some other lock-out mechanism? Paul -- Paul A. Scott mailto:[EMAIL PROTECTED] http://skycoast.us/pscott/ To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
I think you missed the fine point in the kick everybody *else* off comment. Ahhh. I guess you mean that revoke() would change to do that. You're right, I did miss your point. The point is you cannot serialize against other processes. But that's the point of serialization. Anyway, if init is the only process opening a tty, serialization would be inherent. But, like I said earlier, I'm no master of init code. I've just never heard of any problems springing from this, so I offer a possible explanation of why it seems (to me) to work. -- Paul A. Scott mailto:[EMAIL PROTECTED] http://skycoast.us/pscott/ To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
revoke(2) redux...
On Tue, 24 Dec 2002 12:40:25 +0100, Poul-Henning Kamp [EMAIL PROTECTED] said: Isn't there a pretty obvious race between the revoke() and the open() ? To the extent that the race matters, it is obviated by making sure that only the current user has permission to open the device. If the user somehow manages to open a device that he owns anyway, it's his problem if doing so screws it up. revoke() was a POSIX invention; it replaces the older vhangup(). The problem with vhangup() was that it merely signalled the previous openers -- if they had a SIGHUP handler installed, they did not actually lose access to the device. AIX has an extension such as you suggest (they call it frevoke()). AIX also implements it for all vnodes, not just device-specials, so it is somewhat more general-purpose. The POSIX function was introduced for only one reason: to provide a secure replacement for vhangup() in the POSIX tty model. Thus, it is not fully general. -GAWollman To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
In message [EMAIL PROTECTED], Paul A. Scott writes: I think you missed the fine point in the kick everybody *else* off comment. Ahhh. I guess you mean that revoke() would change to do that. You're right, I did miss your point. The point is you cannot serialize against other processes. But that's the point of serialization. Anyway, if init is the only process opening a tty, revoke is used in most login daemons, telnetd, getty and elsewhere. There is no way you can close the race between: revoke(/dev/ttyfoo); and open(/dev/ttyfoo); Not even in init(8). There is always the risk that another process opens the device between the two. -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 [EMAIL PROTECTED] | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
On Tue, 24 Dec 2002 15:43:56 +0100, [EMAIL PROTECTED] said: There is no way you can close the race between: revoke(/dev/ttyfoo); and open(/dev/ttyfoo); Not even in init(8). There is always the risk that another process opens the device between the two. If that process belongs to root then it doesn't matter. If that process belongs to the user who's logging in, then it doesn't matter (the user can hose himself, but that's his own fault). If that process belongs to someone else, then the permissions on the device are set wrong, and that's a security problem that revoke() isn't trying to fix. -GAWollman To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
In message [EMAIL PROTECTED], Garrett Wollman writes: On Tue, 24 Dec 2002 12:40:25 +0100, Poul-Henning Kamp [EMAIL PROTECTED] said: Isn't there a pretty obvious race between the revoke() and the open() ? To the extent that the race matters, it is obviated by making sure that only the current user has permission to open the device. If the user somehow manages to open a device that he owns anyway, it's his problem if doing so screws it up. revoke() was a POSIX invention; it replaces the older vhangup(). But I can't find mention of it in SUS ? AIX has an extension such as you suggest (they call it frevoke()). I think we should implement that in the kernel instead of revoke(2) because it is actually a lot simpler to implement correctly. We can then provide revoke(2) as a wrapper: revoke(const char *name) { int fd, e; fd = open(name, O_RDONLY); if (fd 0) return (fd); e = frevoke(fd); close(fd); return (e); } -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 [EMAIL PROTECTED] | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
* De: [EMAIL PROTECTED] [ Data: 2002-12-24 ] [ Subjecte: Re: revoke(2) redux... ] revoke is used in most login daemons, telnetd, getty and elsewhere. There is no way you can close the race between: revoke(/dev/ttyfoo); and open(/dev/ttyfoo); Not even in init(8). There is always the risk that another process opens the device between the two. Don't the chmod hacks performed on TTYs to essentially go from this is free to this is mine close that race more or less? I understand from watching xpty discussion that if a tty matches certain mode/... requirements then one should try to chown it and chmod it appropriately to themselves, and if that fails, go back to looking for one (aquiring a lock on the tty essentially) then do a revoke on it, because it's now really ours, and then go on to open it... Kicking people off only once the open works is an interesting idea (wrt frevoke), but by then we've already trashed the perms... I'm not sure whether there's a meaningful race in that (though of course there are lots of races in that, especially if not appropriately coded) and how much of a bad window exists wrt revoke/frevoke, and whether it is really solved by fvrevoke. juli. -- Juli Mallett [EMAIL PROTECTED] OpenDarwin, Mono, FreeBSD Developer. ircd-hybrid Developer, EFnet addict. FreeBSD on MIPS-Anything on FreeBSD. To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message
Re: revoke(2) redux...
On Tue, Dec 24, 2002 at 03:52:05PM +0100, [EMAIL PROTECTED] wrote: We can then provide revoke(2) as a wrapper: revoke(const char *name) { int fd, e; fd = open(name, O_RDONLY); Assuming you can open the thing name points to. I guess it might be a (NFS) directory or socket. I think revoke used to work on directories for a bit, until someone found it didn't work on named pipes and sockets, and then it was restricted to devices again. David. To Unsubscribe: send mail to [EMAIL PROTECTED] with unsubscribe freebsd-current in the body of the message