kern/134276: [linux][patch] MSG_NOSIGNAL not translated for recv(), socket timeout incorrect for 64-bit hosts

Thomas Mueller tmueller at sysgo.com
Wed May 6 17:00:10 UTC 2009


>Number:         134276
>Category:       kern
>Synopsis:       [linux][patch] MSG_NOSIGNAL not translated for recv(), socket timeout incorrect for 64-bit hosts
>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 May 06 17:00:07 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator:     Thomas Mueller
>Release:        7.2-STABLE
>Organization:
>Environment:
FreeBSD tom.ulm.sysgo.com 7.2-STABLE FreeBSD 7.2-STABLE #16: Mon May  4 15:12:43 CEST 2009     toor at tom.ulm.sysgo.com:/usr/obj/usr/src/sys/TOM  amd64
>Description:
I've encountered two socket related problems with the Linux emulation:

1. A Linux application passing the MSG_NOSIGNAL flag in calls to 
   recv() or recvfrom() will still receive a SIGPIPE if the condition
   for sending the signal is met.

2. An attempt to set socket timeouts with a call to setsocktopt() using the 
   SO_RECVTIMEO or SO_SNDTIMEO option will fail with [EINVAL] on amd64.

>How-To-Repeat:

>Fix:
1. Call linux_to_bsd_msg_flags() in linux_recv().
2. Translate l_timeval arg to native struct timeval in linux_setsockopt().

Patch attached.

Patch attached with submission follows:

Index: linux_socket.c
===================================================================
RCS file: /usr/home/tmu/repos/FreeBSD/repo/src/sys/compat/linux/linux_socket.c,v
retrieving revision 1.74.2.1
diff -u -p -r1.74.2.1 linux_socket.c
--- linux_socket.c	17 Sep 2008 08:05:39 -0000	1.74.2.1
+++ linux_socket.c	6 May 2009 16:51:16 -0000
@@ -871,7 +871,7 @@ linux_recv(struct thread *td, struct lin
 	bsd_args.s = args->s;
 	bsd_args.buf = (caddr_t)PTRIN(args->msg);
 	bsd_args.len = args->len;
-	bsd_args.flags = args->flags;
+	bsd_args.flags = linux_to_bsd_msg_flags(args->flags);
 	bsd_args.from = NULL;
 	bsd_args.fromlenaddr = 0;
 	return (recvfrom(td, &bsd_args));
@@ -1104,6 +1104,17 @@ linux_setsockopt(struct thread *td, stru
 			bsd_args.valsize);
 		error = setsockopt(td, &bsd_args);
 		bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val);
+	} else if (name == SO_RCVTIMEO || name == SO_SNDTIMEO) {
+		l_timeval lnx_tv;
+		struct timeval tv;
+
+		error = copyin(bsd_args.val, &lnx_tv, sizeof(lnx_tv));
+		if (!error) {
+			tv.tv_sec = lnx_tv.tv_sec;
+			tv.tv_usec = lnx_tv.tv_usec;
+			error = kern_setsockopt(td, bsd_args.s, bsd_args.level,
+				bsd_args.name, &tv, UIO_SYSSPACE, sizeof(tv));
+		}
 	} else
 		error = setsockopt(td, &bsd_args);
 


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list