* Ed Schouten <[EMAIL PROTECTED]> wrote:
> The patch below prevents this by performing this check by do_dup(). It
> will prevent fcntl() from PROC_LOCK()'ing twice. It also fixes the
> return value of fcntl(). The manual page states that it should return
> EMFILE when it exceeds its limit, though the actual code sets EINVAL.

Woops - It looks like I wasn't awake when I was reading the fcntl()
manual page. fcntl() should return EINVAL when the minimum value is
higher than the limit and EMFILE when it can't find a free descriptor in
the range from the minimum value to the maximum. dup() generalizes this
to EMFILE. It cannot return EINVAL.

I decided to change the patch that do_dup() can return EINVAL for the
fcntl() scenario and that the dup()/dup2() system calls readjust the
errno right before returning. Please use the patch below.

%%%
--- src/sys/kern/kern_descrip.c Thu Nov  9 20:18:41 2006
+++ src/sys/kern/kern_descrip.c Thu Nov  9 20:26:25 2006
@@ -283,8 +283,14 @@
 dup2(struct thread *td, struct dup2_args *uap)
 {
 
-       return (do_dup(td, DUP_FIXED, (int)uap->from, (int)uap->to,
-                   td->td_retval));
+       int error;
+
+       error = do_dup(td, DUP_FIXED, (int)uap->from, (int)uap->to,
+                   td->td_retval);
+       /* dup2() should only return EMFILE when exceeding limits */
+       if (error == EINVAL)
+               error = EMFILE;
+       return (error);
 }
 
 /*
@@ -302,8 +308,13 @@
 int
 dup(struct thread *td, struct dup_args *uap)
 {
+       int error;
 
-       return (do_dup(td, DUP_VARIABLE, (int)uap->fd, 0, td->td_retval));
+       error = do_dup(td, DUP_VARIABLE, (int)uap->fd, 0, td->td_retval);
+       /* dup() should only return EMFILE when exceeding limits */
+       if (error == EINVAL)
+               error = EMFILE;
+       return (error);
 }
 
 /*
@@ -358,7 +369,6 @@
        struct proc *p;
        char *pop;
        struct vnode *vp;
-       u_int newmin;
        int error, flg, tmp;
        int giant_locked;
 
@@ -396,16 +406,7 @@
        case F_DUPFD:
                /* mtx_assert(&Giant, MA_NOTOWNED); */
                FILEDESC_UNLOCK(fdp);
-               newmin = arg;
-               PROC_LOCK(p);
-               if (newmin >= lim_cur(p, RLIMIT_NOFILE) ||
-                   newmin >= maxfilesperproc) {
-                       PROC_UNLOCK(p);
-                       error = EINVAL;
-                       break;
-               }
-               PROC_UNLOCK(p);
-               error = do_dup(td, DUP_VARIABLE, fd, newmin, td->td_retval);
+               error = do_dup(td, DUP_VARIABLE, fd, arg, td->td_retval);
                break;
 
        case F_GETFD:
@@ -629,7 +630,7 @@
        maxfd = min((int)lim_cur(p, RLIMIT_NOFILE), maxfilesperproc);
        PROC_UNLOCK(p);
        if (new >= maxfd)
-               return (EMFILE);
+               return (EINVAL);
 
        FILEDESC_LOCK(fdp);
        if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL) {
%%%

-- 
 Ed Schouten <[EMAIL PROTECTED]>
 WWW: http://g-rave.nl/

Attachment: pgpqP8VPzFHz8.pgp
Description: PGP signature

Reply via email to