[comp.unix.wizards] fcntl/socket anomaly

peralta@pinocchio.Encore.COM (Rick Peralta) (12/29/89)

[ode to old bugs...]

Why when setting the F_SETOWN on a socket a pfind is not done on the PID?
Maybe more to the point, why the double standard on how a pgrp is specified?


 - Rick

lm@snafu.Sun.COM (Larry McVoy) (01/08/90)

In article <10763@encore.Encore.COM> peralta@encore.com (Rick Peralta) writes:
>[ode to old bugs...]
>
>Why when setting the F_SETOWN on a socket a pfind is not done on the PID?
>Maybe more to the point, why the double standard on how a pgrp is specified?
>
>
> - Rick

F_SETOWN has been a botch from day one as far as I'm concerned.  For
those who don't know (or don't remember) F_SETOWN is used to say "send
this pid the SIGIO when the time is right".  The documentation has
always said that you can specify pgrps instead of pids (one of them was
negative to indicate the type) and SunOS, at least, never did that
(stay tuned).  Furthermore, the F_SETOWN uses the same field in the tty
structure that the tty sub system uses for job control (where ^Z and
others get sent).  So if you use F_SETOWN on an active tty you get very
strange things happening.

My guess is that the SIGIO interface was a hack that some grad student
needed.  They hacked it in, it works in the obvious cases, it's stuck
around.  It needs a rewack to be clean (I just checked SunOS - we do
absolutely no permissions checks on F_SETOWN on sockets).

If you are thinking of fixing this, beware of this:  Some programs may
depend on the tty pgrp for SIGIO.  In other words, if you split the
field into two (tty pgrp and sigio pgrp), then have the sigio go to the
tty pgrp if the sigio field is not initialized.
---
What I say is my opinion.  I am not paid to speak for Sun, I'm paid to hack.

Larry McVoy, Sun Microsystems     (415) 336-7627       ...!sun!lm or lm@sun.com

chris@mimsy.umd.edu (Chris Torek) (01/08/90)

>In article <10763@encore.Encore.COM> peralta@encore.com (Rick Peralta) writes:
>>Why when setting the F_SETOWN on a socket a pfind is not done on the PID?
>>Maybe more to the point, why the double standard on how a pgrp is specified?

4.3-tahoe does a pfind, but not for pgroups (negative values), only for
pids (positive values), and only when translating to TIOCSPGRP (more
below).

In article <129970@sun.Eng.Sun.COM> lm@snafu.Sun.COM (Larry McVoy) writes:
>F_SETOWN has been a botch from day one as far as I'm concerned.  For
>those who don't know (or don't remember) F_SETOWN is used to say "send
>this pid the SIGIO when the time is right".  The documentation has
>always said that you can specify pgrps instead of pids (one of them was
>negative to indicate the type) and SunOS, at least, never did that
>(stay tuned).

Actually, I am fairly sure that SunOS 3.x had the 4.2BSD bug where pid
and pgroup were reversed (between documentation and code).  Whether that
has been fixed, I do not know.  (The SunOS 4.x code is substantially
different, and I have not read it.)

>Furthermore, the F_SETOWN uses the same field in the tty
>structure that the tty sub system uses for job control (where ^Z and
>others get sent).  So if you use F_SETOWN on an active tty you get very
>strange things happening.

(The following applies only to 4.3BSD and otherwise-unchanged derivatives
thereof.)

F_SETOWN on an inode translates into a TIOCSPGRP ioctl, so that whatever
checks are applied to TIOCSPGRP are applied to fcntl(ttyf, F_SETOWN).
The translation goes like this:

	if (value > 0) {		[value is a pid, not a pgroup]
		struct proc *p = pfind(value);
		if (p == 0)
			return (ESRCH);
		value = p->p_pgrp;
	} else				[value is a negated pgroup ID]
		value = -value;
	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value);

For a socket, it sets ((struct socket *)fp->f_data)->so_pgrp to the
given value.  Tty pgroups are stored in tp->t_pgrp: a different place.

>My guess is that the SIGIO interface was a hack that some grad student
>needed.

Not really.  It does seem to be done rather badly, however.

>They hacked it in, it works in the obvious cases, it's stuck
>around.  It needs a rewack to be clean (I just checked SunOS - we do
>absolutely no permissions checks on F_SETOWN on sockets).

They are unnecessary.   SIGIO is a completely benign signal.  If a
process is not catching it, SIGIO is discarded.  If a process *is*
catching it, that process is required to figure out why the SIGIO occurred
and whether it still has any reason to do anything about it, so extra
SIGIO signals merely reduce efficiency.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

sms@WLV.IMSD.CONTEL.COM (Steven M. Schultz) (01/08/90)

In article <129970@sun.Eng.Sun.COM> lm@sun.UUCP (Larry McVoy) writes:
>In article <10763@encore.Encore.COM> peralta@encore.com (Rick Peralta) writes:
>>
>>Why when setting the F_SETOWN on a socket a pfind is not done on the PID?
>>Maybe more to the point, why the double standard on how a pgrp is specified?
>
>F_SETOWN has been a botch from day one as far as I'm concerned.  For
	
	amen.

>those who don't know (or don't remember) F_SETOWN is used to say "send
>this pid the SIGIO when the time is right"...
>Furthermore, the F_SETOWN uses the same field in the tty
>structure that the tty sub system uses for job control...
>My guess is that the SIGIO interface was a hack that some grad student
>needed.  They hacked it in, it works in the obvious cases, it's stuck
>around...

	The hack/botch is the F_SETOWN, or rather the whole fcntl(2) syscall.
	As i recall fcntl(2) was (needlessly?) instituted by the creators of 
	System V(anilla) and adopted by Berkeley as a compatability measure,
	nothing that really couldn't be done by ioctl(2) but a new syscall
	was created anyhow.

	and don't forget the overlaying (reuse) of the VTIME and VEOT
	members of the AT&G Unix tty system - switch modes from to/from
	'cbreak' and you have surprises too.  but then, i suppose it was
	done by a graduate student... .5;-)

	Steven

lm@snafu.Sun.COM (Larry McVoy) (01/09/90)

In article <21691@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
>F_SETOWN on an inode translates into a TIOCSPGRP ioctl, so that whatever
>checks are applied to TIOCSPGRP are applied to fcntl(ttyf, F_SETOWN).
>The translation goes like this:
>
>	if (value > 0) {		[value is a pid, not a pgroup]
>		struct proc *p = pfind(value);
>		if (p == 0)
>			return (ESRCH);
>		value = p->p_pgrp;
>	} else				[value is a negated pgroup ID]
>		value = -value;
>	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value);

Those checks are inappropriate for the F_SETOWN.  For example, POSIX
insists that the tty in question be your controlling tty.  That's both
unecessary and unlikely for processes wanting SIGIO on a tty.

>>My guess is that the SIGIO interface was a hack that some grad student
>>needed.
>
>Not really.  It does seem to be done rather badly, however.
>
>>They hacked it in, it works in the obvious cases, it's stuck
>>around.  It needs a rewack to be clean (I just checked SunOS - we do
>>absolutely no permissions checks on F_SETOWN on sockets).
>
>They are unnecessary.   SIGIO is a completely benign signal.  If a
>process is not catching it, SIGIO is discarded.  If a process *is*
>catching it, that process is required to figure out why the SIGIO occurred
>and whether it still has any reason to do anything about it, so extra
>SIGIO signals merely reduce efficiency.

Permission checks are rarely "unnecessary", it's much more likely that
they're either missing or incorrect.  In this case, they're missing.
Suppose I have process A and process B.  A does a F_SETOWN on some
socket and then goes on, expecting a SIGIO at some later time.  B comes
along, and also does a F_SETOWN on the same socket.  A has been
robbed.

To head off a needless discussion: yes, I realize that if you do the
"right thing" everything is OK and there is no need for permission
checks.  My claim is that the number of programmers who "do the right
thing" (sorry spike) are getting fewer and fewer.
---
What I say is my opinion.  I am not paid to speak for Sun, I'm paid to hack.

Larry McVoy, Sun Microsystems     (415) 336-7627       ...!sun!lm or lm@sun.com

chris@mimsy.umd.edu (Chris Torek) (01/09/90)

In article <129979@sun.Eng.Sun.COM> lm@snafu.Sun.COM (Larry McVoy) writes:
>Those checks [applied by TIOCSPGRP] are inappropriate for the F_SETOWN.
>For example, POSIX insists that the tty in question be your controlling tty.
>That's both unecessary and unlikely for processes wanting SIGIO on a tty.

Ah: this is different from what you said (or at least, what I understood)
before.  Now you seem to mean `any process should be allowed to ask for
SIGIO on any file descriptor to which it can apply an fcntl, and should
receive SIGIO signals whenever it could read from / write to that descriptor.'

(This is a reasonable interpretation of what SIGIO should be, but would
require major kernel restructuring, since per-file-descriptor flags can
only be stored in a u. area.)

>Suppose I have process A and process B.  A does a F_SETOWN on some
>socket and then goes on, expecting a SIGIO at some later time.  B comes
>along, and also does a F_SETOWN on the same socket.  A has been
>robbed.

Ah.  This, of course, is a property of the shared-ness of descriptors.
A dup()ed descriptor (either with the dup() or dup2() system calls,
or simply shared across fork+exec) has only one underlying object,
and (for reasons having to do with the basic kernel structure) signals
have to refer to the underlying object%, hence are shared.

Fortunately, two different endpoints on a socket are not shared.  A
program (your `A') that passes its own socket endpoint to another program
(your `B') has explicitly---well, okay, implicitly---given control of
the socket to the second program.  For instance, `B' could issue a
shutdown on the socket as well.

Thus, I think this objection does not apply.  (It *does* apply to tty
devices.)

-----
% Actually, they refer to the object underlying the underlying object,
  in the case of inodes; but this, at least, could be changed in
  principle.  (Thread a linked list of signal info through the file
  table.)  Then you have the problem of *giving up* SIGIO signals for
  a descriptor.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

lm@snafu.Sun.COM (Larry McVoy) (01/10/90)

In article <21710@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
>In article <129979@sun.Eng.Sun.COM> lm@snafu.Sun.COM (Larry McVoy) writes:
>>Those checks [applied by TIOCSPGRP] are inappropriate for the F_SETOWN.
>>For example, POSIX insists that the tty in question be your controlling tty.
>>That's both unecessary and unlikely for processes wanting SIGIO on a tty.
>
>Ah: this is different from what you said (or at least, what I understood)
>before.  Now you seem to mean `any process should be allowed to ask for
>SIGIO on any file descriptor to which it can apply an fcntl, and should
>receive SIGIO signals whenever it could read from / write to that descriptor.'

Well, while I agree that this would be nice, it's not at all what I
meant and I think you know it.  SIGIO is commonly applied to tty's.
The point you made about permission checks is bogus because POSIX won't
let you get SIGIO on anything but your controlling terminal if you
continue with this braindead implementation that calls TIOCSPGRP.

>>Suppose I have process A and process B.  A does a F_SETOWN on some
>>socket and then goes on, expecting a SIGIO at some later time.  B comes
>>along, and also does a F_SETOWN on the same socket.  A has been
>>robbed.
>
>Ah.  This, of course, is a property of the shared-ness of descriptors.

Not really.  If sockets can be named in the file system (Unix domain) then
you can get at it by opeing the file (like the printer for instance).

>A dup()ed descriptor (either with the dup() or dup2() system calls,
>or simply shared across fork+exec) has only one underlying object,
>and (for reasons having to do with the basic kernel structure) signals
>have to refer to the underlying object%, hence are shared.
>
>Thus, I think this objection does not apply.  (It *does* apply to tty
>devices.)

This is missing the point completely.  I don't care (and neither do
you) that cooperating processes can hurt each other (a new definition
of cooperating :-)  It's the tty and named socket case that's broken.


Let's take this offline, Chris - I think the horse is dead....
---
What I say is my opinion.  I am not paid to speak for Sun, I'm paid to hack.

Larry McVoy, Sun Microsystems     (415) 336-7627       ...!sun!lm or lm@sun.com