cher@ksr.com (Mike Cherepov) (03/01/90)
Two bugs having to do with rights-passing and file structure garbage
collection in kernel socket code:
making a sendmsg() call with huge msg_accrightslen and msg_accrights
crashes our Solbourne. The problem is that the kernel sendit() does not
check whether the rights (int array in AF_UN*X domain) fit into an mbuf.
Something like this before the sockargs(&rights,...) call in sendit()
should help:
if (mp->msg_accrightslen > MLLEN) {
u.u_error=EMSGSIZE;
return;
}
A more interesting case (crashes a SparcStation) involves passing rights
to a socket, closing it, then opening and closing another socket causing
unp_gc (the garbage collection) to come alive:
get datagram socket in AF_UN*X domain, assume fd is 3;
bind it;
int rights[2]={3,3};
call sendmsg(3,msg,0) passing rights to itself;
close(3);
get another socket;
close it, and presto - machine crashes
This is how we seem to get there:
unp_gc /* garbage collection */
unp_discard
closef
soo_close
soclose /* NOFDREF flag on the orphaned socket cleared here */
sofree
sorflush /* flush rights buffers */
unp_dispose
unp_scan
unp_discard
closef /* close same fd we are working on */
soo_close
soclose /* but NOFDREF cleared already */
panic
One way to fix this is to make sure we don't call closef on the same file
the second time around, to this end unp_discard could do this:
if (fp->f_msgcount<=0)
return;
before doing anything else. Discard is not supposed to be called if there
are no rights to discard. However, I am not sure it does not introduce
some other unforeseen problems; perhaps looking at NOFDREF is a better way
to go. Any comments from well-informed quarters?
Mike Cherepov
expressing views not necessarily coincidental
with those of my employer...
uunet!ksr!cher
ksr!cher@harvard.harvard.edu