Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Feb 2012 09:46:10 +1100 (EST)
From:      Peter Jeremy <peterjeremy@acm.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/164970: dup2(2) incorrectly returns EMFILE instead of EBADF
Message-ID:  <201202102246.q1AMkAhN019307@server.vk2pj.dyndns.org>
Resent-Message-ID: <201202102250.q1AMoCCB074250@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         164970
>Category:       kern
>Synopsis:       dup2(2) incorrectly returns EMFILE instead of EBADF
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Feb 10 22:50:11 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Peter Jeremy
>Release:        FreeBSD 8.2-STABLE amd64
>Organization:
>Environment:
System: FreeBSD server.vk2pj.dyndns.org 8.2-STABLE FreeBSD 8.2-STABLE #15: Thu Feb 2 11:02:29 EST 2012 root@server.vk2pj.dyndns.org:/var/obj/usr/src/sys/server amd64

>Description:
	http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html
	states that dup2() should return EBADF if the second argumunt is
	"greater than or equal to {OPEN_MAX}."  FreeBSD returns EMFILE in
	this case (this was broken in r124548).  FreeBSD also returns
	EMFILE for fcntl(F_DUP2FD) but this operation is not defined by
	The Open Group.

	Note that GNU autotools disables the use of dup2() on FreeBSD due
	to this error.

>How-To-Repeat:
	ktrace the execution of:
#include <unistd.h>
int main(int argc, char **argv) { return dup2(1,1000000); }

>Fix:
Index: sys/kern/kern_descrip.c
===================================================================
--- sys/kern/kern_descrip.c	(revision 231385)
+++ sys/kern/kern_descrip.c	(working copy)
@@ -813,7 +813,7 @@
 	maxfd = min((int)lim_cur(p, RLIMIT_NOFILE), maxfilesperproc);
 	PROC_UNLOCK(p);
 	if (new >= maxfd)
-		return (flags & DUP_FCNTL ? EINVAL : EMFILE);
+		return (flags & DUP_FCNTL ? EINVAL : EBADF);
 
 	FILEDESC_XLOCK(fdp);
 	if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL) {
Index: lib/libc/sys/fcntl.2
===================================================================
--- lib/libc/sys/fcntl.2	(revision 231385)
+++ lib/libc/sys/fcntl.2	(working copy)
@@ -539,8 +539,6 @@
 .Fa cmd
 is
 .Dv F_DUPFD
-or
-.Dv F_DUP2FD
 and the maximum number of file descriptors permitted for the
 process are already in use,
 or no file descriptors greater than or equal to
Index: lib/libc/sys/dup.2
===================================================================
--- lib/libc/sys/dup.2	(revision 231385)
+++ lib/libc/sys/dup.2	(working copy)
@@ -128,20 +128,27 @@
 .Sh ERRORS
 The
 .Fn dup
-and
-.Fn dup2
-system calls fail if:
+system call fails if:
 .Bl -tag -width Er
 .It Bq Er EBADF
 The
 .Fa oldd
-or
-.Fa newd
 argument
 is not a valid active descriptor
 .It Bq Er EMFILE
 Too many descriptors are active.
 .El
+The
+.Fn dup2
+system call fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa oldd
+argument is not a valid active descriptor or the
+.Fa newd
+argument is negative or exceeds the maximum allowable descriptor number
+.El
 .Sh SEE ALSO
 .Xr accept 2 ,
 .Xr cap_new 2 ,
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202102246.q1AMkAhN019307>