There are several issues here:

    * The process's descriptor table
    * The struct file's referenced by that descriptor table
    * The object underlying a struct file.

    A process's descriptor table is not protected by the proc lock, because
    the descriptor table can be shared across processes that rfork().

    The struct file underlying a descriptor has a reference count.  The
    descriptor table reference to the underlying struct file is part of
    this ref count.  Any process that fhold()'s a struct file pointer also
    bumps this ref count.  However, holding a ref on the struct file does
    not prevent another process from revoking the descriptor, so you aren't
    as safe as you might think.  You are safe from it being closed out
    from under you, but not safe otherwise.

    Additionally, the act of *getting* a new ref count on a struct file is
    not currently protected by anything but Giant.  For example, look
    at kern/kern_descrip.c line 226 in -current:

        if ((unsigned)uap->fd >= fdp->fd_nfiles ||
            (fp = fdp->fd_ofiles[uap->fd]) == NULL)
                return (EBADF);
        pop = &fdp->fd_ofileflags[uap->fd];
            ...

        fhold(fp);

    A race can develope between the point where 'fp' is loaded, and the 
    point where it is held by fhold().  Linux solves this problem by making
    their fhold() equivalent take a descriptor number rather then a struct
    file and doing all necessary locking internally.  

    I did a bunch of work on the descriptor code to handle -stable SMP
    races that were occuring due to a lack of fhold()s around blocking
    conditions, but I never took the final step of encapsulating the
    descriptor number lookup in the fhold() (I ran out of time).

    For -current, you MUST do this if you want to move any 
    descriptor-referencing code out from under Giant.  The process lock
    is not sufficient... the descriptor table needs its own mutex.  It
    is possible to optimize this out by checking to see if the descriptor
    table is shared, but in general you need it.

                                                -Matt


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to