From owner-freebsd-bugs@FreeBSD.ORG Wed Jun 10 23:30:02 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2C0E9106566B for ; Wed, 10 Jun 2009 23:30:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 06C6D8FC14 for ; Wed, 10 Jun 2009 23:30:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n5ANU1Ij019954 for ; Wed, 10 Jun 2009 23:30:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n5ANU1nR019953; Wed, 10 Jun 2009 23:30:01 GMT (envelope-from gnats) Resent-Date: Wed, 10 Jun 2009 23:30:01 GMT Resent-Message-Id: <200906102330.n5ANU1nR019953@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Stefan Schmidt Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 88A59106566C for ; Wed, 10 Jun 2009 23:25:47 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 766C38FC13 for ; Wed, 10 Jun 2009 23:25:47 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n5ANPki4062553 for ; Wed, 10 Jun 2009 23:25:46 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id n5ANPkun062552; Wed, 10 Jun 2009 23:25:46 GMT (envelope-from nobody) Message-Id: <200906102325.n5ANPkun062552@www.freebsd.org> Date: Wed, 10 Jun 2009 23:25:46 GMT From: Stefan Schmidt To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/135458: Missing errno translation in Linux getsockopt(, , SO_ERROR, , ) X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Jun 2009 23:30:02 -0000 >Number: 135458 >Category: kern >Synopsis: Missing errno translation in Linux getsockopt(,,SO_ERROR,,) >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Jun 10 23:30:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Stefan Schmidt >Release: FreeBSD 8.0-CURRENT as of 2009-06-10 >Organization: >Environment: FreeBSD shuttle.stadtbuch.de 8.0-CURRENT FreeBSD 8.0-CURRENT #0: Tue Jun 9 21:16:43 CEST 2009 root@shuttle.stadtbuch.de:/usr/obj/usr/src/sys/SHUTTLE amd64 >Description: FreeBSD's Linux emulation layer uses a translation table to convert Linux errnos to FreeBSD errnos. However, while working on some non-blocking networking code (Java NIO, running on Sun's Linux JDK 1.6.0_14), I found that some errnos are not translated. For example, I get "No data available" (= Linux errno 61) instead of the expected "Connection refused" (= FreeBSD errno 61). Some digging revealed that Sun's implementation of Java NIO uses getsockopt under the hood to retrieve the failure reason of a non-blocking connect request. And the emulated Linux getsockopt does not translate FreeBSD's errno to Linux'... >How-To-Repeat: The following (stripped down) test program (sorry for using Java) initiates a non-blocking connect and waits for the result. Using a Linux JDK (e.g. 1.6.0_14), the output is "java.net.ConnectException: No data available" instead of the expected "java.net.ConnectException: Connection refused". package javaapplication1; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; public class Main { public static void main(String[] args) { try { Selector selector = Selector.open(); SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_CONNECT); socketChannel.connect(new InetSocketAddress("127.0.0.1", 12345)); selector.select(); socketChannel.finishConnect(); } catch (IOException e) { System.out.println(e); } } } >Fix: I've attached a patch which adds errno translation to the emulated getsockopt syscall. Works fine for me. Maybe someone can review the patch and commit it? Patch attached with submission follows: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # getsockopt.patch # echo x - getsockopt.patch sed 's/^X//' >getsockopt.patch << '375616829dae7c22aabec4029ce3ff39' XIndex: sys/compat/linux/linux_socket.c X=================================================================== XRCS file: /home/ncvs/src/sys/compat/linux/linux_socket.c,v Xretrieving revision 1.99 Xdiff -u -r1.99 linux_socket.c X--- sys/compat/linux/linux_socket.c 1 Jun 2009 20:54:41 -0000 1.99 X+++ sys/compat/linux/linux_socket.c 10 Jun 2009 22:22:41 -0000 X@@ -396,6 +396,23 @@ X return (error); X } X X+static int X+bsd_to_linux_errno(int *arg) X+{ X+ int errno; X+ size_t errno_len = sizeof(int); X+ int error; X+ X+ if ((error = copyin(arg, &errno, errno_len))) X+ return (error); X+ X+ if (errno < elf_linux_sysvec.sv_errsize) X+ errno = -elf_linux_sysvec.sv_errtbl[errno]; X+ X+ error = copyout(&errno, arg, errno_len); X+ X+ return (error); X+} X X static int X linux_sa_put(struct osockaddr *osa) X@@ -1521,11 +1538,12 @@ X bsd_args.val = PTRIN(args->optval); X bsd_args.avalsize = PTRIN(args->optlen); X X- if (name == IPV6_NEXTHOP) { X- error = getsockopt(td, &bsd_args); X+ error = getsockopt(td, &bsd_args); X+ X+ if (name == IPV6_NEXTHOP) X bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val); X- } else X- error = getsockopt(td, &bsd_args); X+ else if (name == SO_ERROR) X+ bsd_to_linux_errno((int *)bsd_args.val); X X return (error); X } 375616829dae7c22aabec4029ce3ff39 exit >Release-Note: >Audit-Trail: >Unformatted: