From nobody@FreeBSD.org  Sun Aug  1 04:20:14 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id B8390106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Sun,  1 Aug 2010 04:20:14 +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 A77748FC13
	for <freebsd-gnats-submit@FreeBSD.org>; Sun,  1 Aug 2010 04:20:14 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o714KEA9062690
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 1 Aug 2010 04:20:14 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o714KEMn062689;
	Sun, 1 Aug 2010 04:20:14 GMT
	(envelope-from nobody)
Message-Id: <201008010420.o714KEMn062689@www.freebsd.org>
Date: Sun, 1 Aug 2010 04:20:14 GMT
From: John Wehle <john@feith.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Linux sendmsg / recvmsg / etc fixes for pulseaudio
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         149168
>Category:       kern
>Synopsis:       [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    avg
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 01 04:30:04 UTC 2010
>Closed-Date:    Sat Apr 09 09:34:31 UTC 2011
>Last-Modified:  Sat Apr  9 09:40:07 UTC 2011
>Originator:     John Wehle
>Release:        8.1
>Organization:
>Environment:
FreeBSD wagner.FEITH.COM 8.1-RC2 FreeBSD 8.1-RC2 #0: Thu Jul 29 03:35:35 EDT 2010     root@wagner.FEITH.COM:/usr/obj/usr/src/sys/CUSTOM  i386
>Description:
The enclosed lightly tested patch extends the Linux emulation
so that pulseaudio runs.  Specifically tested:

  a) Fedora 10 paplay (client) talking to FreeBSD 8.1 pulseaudio (server)
     over both TCP and UNIX domain sockets.

  b) FreeBSD 8.1 paplay (client) talking to Fedora 10 pulseaudio (server)
     over both TCP and UNIX domain sockets.

  c) Fedora 10 paplay (client) talking to Fedora 10 pulseaudio (server)
     over both TCP and UNIX domain sockets.

Changes:

  1) Implement NO-OP stubs for capget, capset, prctl PR_GET_KEEPCAPS,
     and prctl PR_SET_KEEPCAPS so that the pulseaudio server will
     start.

  2) Added SCM_CREDS support to sendmsg and recvmsg.

  3) Modify sendmsg to ignore control messages if not using UNIX
     domain sockets.

>How-To-Repeat:
Install the Fedora 10 pulseaudio client / server software and try
using paplay.
>Fix:


Patch attached with submission follows:

--- ./compat/linux/linux_misc.h.ORIGINAL	2010-06-13 22:09:06.000000000 -0400
+++ ./compat/linux/linux_misc.h	2010-07-31 23:33:18.000000000 -0400
@@ -37,6 +37,8 @@
 					 * Second arg is a ptr to return the
 					 * signal.
 					 */
+#define	LINUX_PR_GET_KEEPCAPS	7	/* Get drop capabilities on setuid */
+#define	LINUX_PR_SET_KEEPCAPS	8	/* Set drop capabilities on setuid */
 #define	LINUX_PR_SET_NAME	15	/* Set process name. */
 #define	LINUX_PR_GET_NAME	16	/* Get process name. */
 
--- ./compat/linux/linux_misc.c.ORIGINAL	2010-06-13 22:09:06.000000000 -0400
+++ ./compat/linux/linux_misc.c	2010-07-31 00:09:16.000000000 -0400
@@ -1733,6 +1733,87 @@ linux_exit_group(struct thread *td, stru
 	return (0);
 }
 
+#define _LINUX_CAPABILITY_VERSION  0x19980330
+
+struct l_user_cap_header {
+	l_int	version;
+	l_int	pid;
+};
+
+struct l_user_cap_data {
+	l_int	effective;
+	l_int	permitted;
+	l_int	inheritable;
+};
+
+int
+linux_capget(struct thread *td, struct linux_capget_args *args)
+{
+	struct l_user_cap_header luch;
+	struct l_user_cap_data lucd;
+	int error;
+
+	if (! args->hdrp)
+		return (EFAULT);
+
+	error = copyin(args->hdrp, &luch, sizeof(luch));
+	if (error != 0)
+		return (error);
+
+	if (luch.version != _LINUX_CAPABILITY_VERSION) {
+		luch.version = _LINUX_CAPABILITY_VERSION;
+		error = copyout(&luch, args->hdrp, sizeof(luch));
+		if (error)
+			return (error);
+		return (EINVAL);
+	}
+
+	if (luch.pid)
+		return (EPERM);
+
+	if (args->datap) {
+		bzero (&lucd, sizeof(lucd));
+		error = copyout(&lucd, args->datap, sizeof(lucd));
+	}
+
+	return (error);
+}
+
+int
+linux_capset(struct thread *td, struct linux_capset_args *args)
+{
+	struct l_user_cap_header luch;
+	struct l_user_cap_data lucd;
+	int error;
+
+	if (! args->hdrp || ! args->datap)
+		return (EFAULT);
+
+	error = copyin(args->hdrp, &luch, sizeof(luch));
+	if (error != 0)
+		return (error);
+
+	if (luch.version != _LINUX_CAPABILITY_VERSION) {
+		luch.version = _LINUX_CAPABILITY_VERSION;
+		error = copyout(&luch, args->hdrp, sizeof(luch));
+		if (error)
+			return (error);
+		return (EINVAL);
+	}
+
+	if (luch.pid)
+		return (EPERM);
+
+	error = copyin(args->datap, &lucd, sizeof(lucd));
+	if (error != 0)
+		return (error);
+
+	if (lucd.effective || lucd.permitted || lucd.inheritable)
+		return (EPERM);
+
+	return (0);
+}
+
 int
 linux_prctl(struct thread *td, struct linux_prctl_args *args)
 {
@@ -1766,6 +1847,11 @@ linux_prctl(struct thread *td, struct li
 		    (void *)(register_t)args->arg2,
 		    sizeof(pdeath_signal));
 		break;
+	case LINUX_PR_GET_KEEPCAPS:
+		td->td_retval[0] = 0;
+		break;
+	case LINUX_PR_SET_KEEPCAPS:
+		break;
 	case LINUX_PR_SET_NAME:
 		/*
 		 * To be on the safe side we need to make sure to not
--- ./compat/linux/linux_socket.h.ORIGINAL	2010-06-13 22:09:06.000000000 -0400
+++ ./compat/linux/linux_socket.h	2010-07-28 23:44:10.000000000 -0400
@@ -53,6 +53,7 @@
 /* Socket-level control message types */
 
 #define LINUX_SCM_RIGHTS	0x01
+#define LINUX_SCM_CREDENTIALS   0x02
 
 /* Ancilliary data object information macros */
 
--- ./compat/linux/linux_socket.c.ORIGINAL	2010-07-28 23:45:26.000000000 -0400
+++ ./compat/linux/linux_socket.c	2010-07-31 23:56:08.000000000 -0400
@@ -433,6 +433,8 @@ linux_to_bsd_cmsg_type(int cmsg_type)
 	switch (cmsg_type) {
 	case LINUX_SCM_RIGHTS:
 		return (SCM_RIGHTS);
+	case LINUX_SCM_CREDENTIALS:
+		return (SCM_CREDS);
 	}
 	return (-1);
 }
@@ -444,6 +446,8 @@ bsd_to_linux_cmsg_type(int cmsg_type)
 	switch (cmsg_type) {
 	case SCM_RIGHTS:
 		return (LINUX_SCM_RIGHTS);
+	case SCM_CREDS:
+		return (LINUX_SCM_CREDENTIALS);
 	}
 	return (-1);
 }
@@ -472,7 +476,7 @@ bsd_to_linux_msghdr(const struct msghdr 
 	lhdr->msg_iov		= PTROUT(bhdr->msg_iov);
 	lhdr->msg_iovlen	= bhdr->msg_iovlen;
 	lhdr->msg_control	= PTROUT(bhdr->msg_control);
-	lhdr->msg_controllen	= bhdr->msg_controllen;
+	/* msg_controllen skipped */
 	/* msg_flags skipped */
 	return (0);
 }
@@ -1092,6 +1096,7 @@ static int
 linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
 {
 	struct cmsghdr *cmsg;
+	struct cmsgcred cmcred;
 	struct mbuf *control;
 	struct msghdr msg;
 	struct l_cmsghdr linux_cmsg;
@@ -1099,6 +1104,8 @@ linux_sendmsg(struct thread *td, struct 
 	struct l_msghdr linux_msg;
 	struct iovec *iov;
 	socklen_t datalen;
+	struct sockaddr *sa;
+	sa_family_t sa_family;
 	void *data;
 	int error;
 
@@ -1128,7 +1135,16 @@ linux_sendmsg(struct thread *td, struct 
 	if (error)
 		return (error);
 
+	control = NULL;
+	cmsg = NULL;
+
 	if (msg.msg_control != NULL) {
+		error = kern_getsockname(td, args->s, &sa, &datalen);
+		if (error)
+			goto bad;
+		sa_family = sa->sa_family;
+		free(sa, M_SONAME);
+
 		error = ENOBUFS;
 		cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
 		control = m_get(M_WAIT, MT_CONTROL);
@@ -1147,18 +1163,46 @@ linux_sendmsg(struct thread *td, struct 
 				goto bad;
 
 			/*
-			 * Now we support only SCM_RIGHTS, so return EINVAL
-			 * in any other cmsg_type
+			 * Now we support only SCM_RIGHTS and SCM_CRED,
+			 * so return EINVAL in any other cmsg_type
 			 */
-			if ((cmsg->cmsg_type =
-			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1)
-				goto bad;
+			cmsg->cmsg_type =
+			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
 			cmsg->cmsg_level =
 			    linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
+			if (cmsg->cmsg_type == -1
+			    || cmsg->cmsg_level != SOL_SOCKET)
+				goto bad;
+
+			/*
+			 * Some applications (e.g. pulseaudio) attempt to
+			 * send ancillary data even if the underlying protocol
+			 * doesn't support it which is not allowed in the
+			 * FreeBSD system call interface.
+			 */
+			if (sa_family != AF_UNIX)
+				continue;
 
+			data = LINUX_CMSG_DATA(ptr_cmsg);
 			datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
+
+			switch (cmsg->cmsg_type)
+			{
+			case SCM_RIGHTS:
+				break;
+
+			case SCM_CREDS:
+				data = &cmcred;
+				datalen = sizeof(cmcred);
+
+				/*
+				 * The lower levels will fill in the structure
+				 */
+				bzero(data, datalen);
+				break;
+			}
+
 			cmsg->cmsg_len = CMSG_LEN(datalen);
-			data = LINUX_CMSG_DATA(ptr_cmsg);
 
 			error = ENOBUFS;
 			if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg))
@@ -1166,9 +1210,11 @@ linux_sendmsg(struct thread *td, struct 
 			if (!m_append(control, datalen, (c_caddr_t) data))
 				goto bad;
 		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg)));
-	} else {
-		control = NULL;
-		cmsg = NULL;
+
+		if (m_length(control, NULL) == 0) {
+			m_freem(control);
+			control = NULL;
+		}
 	}
 
 	msg.msg_iov = iov;
@@ -1193,9 +1239,11 @@ static int
 linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
 {
 	struct cmsghdr *cm;
+	struct cmsgcred *cmcred;
 	struct msghdr msg;
 	struct l_cmsghdr *linux_cmsg = NULL;
-	socklen_t datalen, outlen, clen;
+	struct l_ucred linux_ucred;
+	socklen_t datalen, outlen;
 	struct l_msghdr linux_msg;
 	struct iovec *iov, *uiov;
 	struct mbuf *control = NULL;
@@ -1252,39 +1300,35 @@ linux_recvmsg(struct thread *td, struct 
 			goto bad;
 	}
 
-	if (control) {
+	outbuf = PTRIN(linux_msg.msg_control);
+	outlen = 0;
 
+	if (control) {
 		linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
-		outbuf = PTRIN(linux_msg.msg_control);
-		cm = mtod(control, struct cmsghdr *);
-		outlen = 0;
-		clen = control->m_len;
 
-		while (cm != NULL) {
+		msg.msg_control = mtod(control, struct cmsghdr *);
+		msg.msg_controllen = control->m_len;
+
+		cm = CMSG_FIRSTHDR(&msg);
 
-			if ((linux_cmsg->cmsg_type =
-			    bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1)
+		while (cm != NULL) {
+			linux_cmsg->cmsg_type =
+			    bsd_to_linux_cmsg_type(cm->cmsg_type);
+			linux_cmsg->cmsg_level =
+			    bsd_to_linux_sockopt_level(cm->cmsg_level);
+			if (linux_cmsg->cmsg_type == -1
+			    || cm->cmsg_level != SOL_SOCKET)
 			{
 				error = EINVAL;
 				goto bad;
 			}
+
 			data = CMSG_DATA(cm);
 			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
 
-			switch (linux_cmsg->cmsg_type)
+			switch (cm->cmsg_type)
 			{
-			case LINUX_SCM_RIGHTS:
-				if (outlen + LINUX_CMSG_LEN(datalen) >
-				    linux_msg.msg_controllen) {
-					if (outlen == 0) {
-						error = EMSGSIZE;
-						goto bad;
-					} else {
-						linux_msg.msg_flags |=
-						    LINUX_MSG_CTRUNC;
-						goto out;
-					}
-				}
+			case SCM_RIGHTS:
 				if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
 					fds = datalen / sizeof(int);
 					fdp = data;
@@ -1295,11 +1339,40 @@ linux_recvmsg(struct thread *td, struct 
 					}
 				}
 				break;
+
+			case SCM_CREDS:
+				/*
+				 * Currently LOCAL_CREDS is never in
+				 * effect for Linux so no need to worry
+				 * about sockcred
+				 */
+				if (datalen != sizeof (*cmcred)) {
+					error = EMSGSIZE;
+					goto bad;
+				}
+				cmcred = (struct cmsgcred *)data;
+				bzero(&linux_ucred, sizeof(linux_ucred));
+				linux_ucred.pid = cmcred->cmcred_pid;
+				linux_ucred.uid = cmcred->cmcred_uid;
+				linux_ucred.gid = cmcred->cmcred_gid;
+				data = &linux_ucred;
+				datalen = sizeof(linux_ucred);
+				break;
+			}
+
+			if (outlen + LINUX_CMSG_LEN(datalen) >
+			    linux_msg.msg_controllen) {
+				if (outlen == 0) {
+					error = EMSGSIZE;
+					goto bad;
+				} else {
+					linux_msg.msg_flags |=
+					    LINUX_MSG_CTRUNC;
+					goto out;
+				}
 			}
 
 			linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
-			linux_cmsg->cmsg_level =
-			    bsd_to_linux_sockopt_level(cm->cmsg_level);
 
 			error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
 			if (error)
@@ -1312,18 +1385,13 @@ linux_recvmsg(struct thread *td, struct 
 
 			outbuf += LINUX_CMSG_ALIGN(datalen);
 			outlen += LINUX_CMSG_LEN(datalen);
-			linux_msg.msg_controllen = outlen;
 
-			if (CMSG_SPACE(datalen) < clen) {
-				clen -= CMSG_SPACE(datalen);
-				cm = (struct cmsghdr *)
-				    ((caddr_t)cm + CMSG_SPACE(datalen));
-			} else
-				cm = NULL;
+			cm = CMSG_NXTHDR(&msg, cm);
 		}
 	}
 
 out:
+	linux_msg.msg_controllen = outlen;
 	error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
 
 bad:
--- ./i386/linux/linux_proto.h.ORIGINAL	2010-06-13 22:09:06.000000000 -0400
+++ ./i386/linux/linux_proto.h	2010-07-30 23:33:15.000000000 -0400
@@ -586,10 +586,12 @@ struct linux_getcwd_args {
 	char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)];
 };
 struct linux_capget_args {
-	register_t dummy;
+	char hdrp_l_[PADL_(void *)]; void * hdrp; char hdrp_r_[PADR_(void *)];
+	char datap_l_[PADL_(void *)]; void * datap; char datap_r_[PADR_(void *)];
 };
 struct linux_capset_args {
-	register_t dummy;
+	char hdrp_l_[PADL_(void *)]; void * hdrp; char hdrp_r_[PADR_(void *)];
+	char datap_l_[PADL_(void *)]; void * datap; char datap_r_[PADR_(void *)];
 };
 struct linux_sigaltstack_args {
 	char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)];
--- ./i386/linux/linux_dummy.c.ORIGINAL	2010-06-13 22:09:06.000000000 -0400
+++ ./i386/linux/linux_dummy.c	2010-07-30 23:33:46.000000000 -0400
@@ -57,8 +57,6 @@ DUMMY(vm86);
 DUMMY(query_module);
 DUMMY(nfsservctl);
 DUMMY(rt_sigqueueinfo);
-DUMMY(capget);
-DUMMY(capset);
 DUMMY(sendfile);		/* different semantics */
 DUMMY(setfsuid);
 DUMMY(setfsgid);


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-emulation 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Tue Aug 3 00:11:26 UTC 2010 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=149168 

From: Andriy Gapon <avg@FreeBSD.org>
To: bug-followup@FreeBSD.org, john@feith.com
Cc: rdivacky@FreeBSD.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes
 for pulseaudio
Date: Mon, 07 Feb 2011 16:43:12 -0500

 John,
 couple of comments for the patch:
 
 1. What is a reason for "msg_controllen skipped" ?  Is this a proper 
 solution or some hacking remnants?
 
 2. amd64 counterparts of changes in i386 arch code are missing.  Those 
 should be trivial to add.
 
 Roman,
 do you have additional comments which I might have forgotten?
 
 Thanks!
 -- 
 Andriy Gapon

From: John Wehle <john@feith.com>
To: avg@FreeBSD.org
Cc: rdivacky@FreeBSD.org, bug-followup@FreeBSD.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Date: Tue, 8 Feb 2011 00:28:29 -0500 (EST)

 >  1. What is a reason for "msg_controllen skipped" ?  Is this a proper 
 > solution or some hacking remnants?
 
 It's in the spirit of /* msg_flags skipped */.
 
 Since the BSD and LINUX control messages are potentially different
 sizes (e.g. the cred structure used by SCM_CREDS is different between
 the two operating system) you can't just copy msg_controllen.
 linux_recvmsg fills in the proper value after it has parse / converted
 the control messages.
 
 For consistency it would probably be nice if this was also reflected
 in linux_to_bsd_msghdr / linux_sendmsg.  I'm happy to address this
 issue, though it existed prior to my patch so I don't know if you
 want me to just bundle the necessary changes into an updated version
 of my patch for kern/149168 or if you want it addressed as in separate
 patch.
 
 > 2. amd64 counterparts of changes in i386 arch code are missing.  Those 
 > should be trivial to add.
 
 Yep ... the original patch probably should have had a comment to the effect:
 
   a) The amd64 counterparts of the changes in the i386 arch code are not
      supplied since I don't have a way of testing amd64 changes and I
      try to avoid supplying untested code.
 
   b) The changes should be trivial to implement by someone who has an
      amd64 environment.
 
 -- John
 -------------------------------------------------------------------------
 |   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
 |    John Wehle    |     Fax: 1-215-540-5495  |                         |
 -------------------------------------------------------------------------
 

From: Roman Divacky <rdivacky@FreeBSD.org>
To: Andriy Gapon <avg@FreeBSD.org>
Cc: bug-followup@FreeBSD.org, john@feith.com
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Date: Tue, 8 Feb 2011 08:57:51 +0100

 you also want to modify syscalls.master instead of the script
 generated .h files
 
 On Mon, Feb 07, 2011 at 04:43:12PM -0500, Andriy Gapon wrote:
 > 
 > John,
 > couple of comments for the patch:
 > 
 > 1. What is a reason for "msg_controllen skipped" ?  Is this a proper 
 > solution or some hacking remnants?
 > 
 > 2. amd64 counterparts of changes in i386 arch code are missing.  Those 
 > should be trivial to add.
 > 
 > Roman,
 > do you have additional comments which I might have forgotten?
 > 
 > Thanks!
 > -- 
 > Andriy Gapon

From: John Wehle <john@feith.com>
To: rdivacky@vlk.vlakno.cz
Cc: bug-followup@FreeBSD.org, avg@FreeBSD.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Date: Wed, 9 Feb 2011 17:04:45 -0500 (EST)

 > you also want to modify syscalls.master instead of the script
 > generated .h files
 
 Thanks for pointing that out.
 
 I can see about putting together a tweaked version of the patch this weekend.
 
 -- John
 -------------------------------------------------------------------------
 |   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
 |    John Wehle    |     Fax: 1-215-540-5495  |                         |
 -------------------------------------------------------------------------
 

From: John Wehle <john@feith.com>
To: avg@FreeBSD.org
Cc: rdivacky@FreeBSD.org, bug-followup@FreeBSD.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Date: Sun, 13 Feb 2011 01:59:43 -0500 (EST)

 Enclosed is a slightly tweaked and lightly tested version.
 
 Changes from previous:
 
   1) Modify linux/syscalls.master in i386 & amd64 instead of mucking a
      generated file.
 
   2) For symmetry also ignore msg_controllen in linux_to_bsd_msghdr.
 
 -- John
 -----------------------8<----------------------------8<------------------
 --- ./compat/linux/linux_misc.h.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_misc.h	2011-02-12 22:36:57.000000000 -0500
 @@ -37,6 +37,8 @@
  					 * Second arg is a ptr to return the
  					 * signal.
  					 */
 +#define	LINUX_PR_GET_KEEPCAPS	7	/* Get drop capabilities on setuid */
 +#define	LINUX_PR_SET_KEEPCAPS	8	/* Set drop capabilities on setuid */
  #define	LINUX_PR_SET_NAME	15	/* Set process name. */
  #define	LINUX_PR_GET_NAME	16	/* Get process name. */
  
 --- ./compat/linux/linux_misc.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_misc.c	2011-02-12 22:36:57.000000000 -0500
 @@ -1733,6 +1733,87 @@ linux_exit_group(struct thread *td, stru
  	return (0);
  }
  
 +#define _LINUX_CAPABILITY_VERSION  0x19980330
 +
 +struct l_user_cap_header {
 +	l_int	version;
 +	l_int	pid;
 +};
 +
 +struct l_user_cap_data {
 +	l_int	effective;
 +	l_int	permitted;
 +	l_int	inheritable;
 +};
 +
 +int
 +linux_capget(struct thread *td, struct linux_capget_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (! args->hdrp)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	if (args->datap) {
 +		bzero (&lucd, sizeof(lucd));
 +		error = copyout(&lucd, args->datap, sizeof(lucd));
 +	}
 +
 +	return (error);
 +}
 +
 +int
 +linux_capset(struct thread *td, struct linux_capset_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (! args->hdrp || ! args->datap)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	error = copyin(args->datap, &lucd, sizeof(lucd));
 +	if (error != 0)
 +		return (error);
 +
 +	if (lucd.effective || lucd.permitted || lucd.inheritable)
 +		return (EPERM);
 +
 +	return (0);
 +}
 +
  int
  linux_prctl(struct thread *td, struct linux_prctl_args *args)
  {
 @@ -1766,6 +1847,11 @@ linux_prctl(struct thread *td, struct li
  		    (void *)(register_t)args->arg2,
  		    sizeof(pdeath_signal));
  		break;
 +	case LINUX_PR_GET_KEEPCAPS:
 +		td->td_retval[0] = 0;
 +		break;
 +	case LINUX_PR_SET_KEEPCAPS:
 +		break;
  	case LINUX_PR_SET_NAME:
  		/*
  		 * To be on the safe side we need to make sure to not
 --- ./compat/linux/linux_socket.h.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_socket.h	2011-02-12 22:36:57.000000000 -0500
 @@ -53,6 +53,7 @@
  /* Socket-level control message types */
  
  #define LINUX_SCM_RIGHTS	0x01
 +#define LINUX_SCM_CREDENTIALS   0x02
  
  /* Ancilliary data object information macros */
  
 --- ./compat/linux/linux_socket.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_socket.c	2011-02-13 00:22:58.000000000 -0500
 @@ -433,6 +433,8 @@ linux_to_bsd_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case LINUX_SCM_RIGHTS:
  		return (SCM_RIGHTS);
 +	case LINUX_SCM_CREDENTIALS:
 +		return (SCM_CREDS);
  	}
  	return (-1);
  }
 @@ -444,6 +446,8 @@ bsd_to_linux_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case SCM_RIGHTS:
  		return (LINUX_SCM_RIGHTS);
 +	case SCM_CREDS:
 +		return (LINUX_SCM_CREDENTIALS);
  	}
  	return (-1);
  }
 @@ -459,7 +463,7 @@ linux_to_bsd_msghdr(struct msghdr *bhdr,
  	bhdr->msg_iov		= PTRIN(lhdr->msg_iov);
  	bhdr->msg_iovlen	= lhdr->msg_iovlen;
  	bhdr->msg_control	= PTRIN(lhdr->msg_control);
 -	bhdr->msg_controllen	= lhdr->msg_controllen;
 +	/* msg_controllen skipped */
  	bhdr->msg_flags		= linux_to_bsd_msg_flags(lhdr->msg_flags);
  	return (0);
  }
 @@ -472,7 +476,7 @@ bsd_to_linux_msghdr(const struct msghdr 
  	lhdr->msg_iov		= PTROUT(bhdr->msg_iov);
  	lhdr->msg_iovlen	= bhdr->msg_iovlen;
  	lhdr->msg_control	= PTROUT(bhdr->msg_control);
 -	lhdr->msg_controllen	= bhdr->msg_controllen;
 +	/* msg_controllen skipped */
  	/* msg_flags skipped */
  	return (0);
  }
 @@ -1092,6 +1096,7 @@ static int
  linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
  {
  	struct cmsghdr *cmsg;
 +	struct cmsgcred cmcred;
  	struct mbuf *control;
  	struct msghdr msg;
  	struct l_cmsghdr linux_cmsg;
 @@ -1099,15 +1104,14 @@ linux_sendmsg(struct thread *td, struct 
  	struct l_msghdr linux_msg;
  	struct iovec *iov;
  	socklen_t datalen;
 +	struct sockaddr *sa;
 +	sa_family_t sa_family;
  	void *data;
  	int error;
  
  	error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
  	if (error)
  		return (error);
 -	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 -	if (error)
 -		return (error);
  
  	/*
  	 * Some Linux applications (ping) define a non-NULL control data
 @@ -1116,8 +1120,12 @@ linux_sendmsg(struct thread *td, struct 
  	 * order to handle this case.  This should be checked, but allows the
  	 * Linux ping to work.
  	 */
 -	if (msg.msg_control != NULL && msg.msg_controllen == 0)
 -		msg.msg_control = NULL;
 +	if (PTRIN(linux_msg.msg_control) != NULL && linux_msg.msg_controllen == 0)
 +		linux_msg.msg_control = PTROUT(NULL);
 +
 +	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 +	if (error)
 +		return (error);
  
  #ifdef COMPAT_LINUX32
  	error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
 @@ -1128,13 +1136,21 @@ linux_sendmsg(struct thread *td, struct 
  	if (error)
  		return (error);
  
 -	if (msg.msg_control != NULL) {
 +	control = NULL;
 +	cmsg = NULL;
 +
 +	if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
 +		error = kern_getsockname(td, args->s, &sa, &datalen);
 +		if (error)
 +			goto bad;
 +		sa_family = sa->sa_family;
 +		free(sa, M_SONAME);
 +
  		error = ENOBUFS;
  		cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
  		control = m_get(M_WAIT, MT_CONTROL);
  		if (control == NULL)
  			goto bad;
 -		ptr_cmsg = LINUX_CMSG_FIRSTHDR(&msg);
  
  		do {
  			error = copyin(ptr_cmsg, &linux_cmsg,
 @@ -1147,18 +1163,46 @@ linux_sendmsg(struct thread *td, struct 
  				goto bad;
  
  			/*
 -			 * Now we support only SCM_RIGHTS, so return EINVAL
 -			 * in any other cmsg_type
 +			 * Now we support only SCM_RIGHTS and SCM_CRED,
 +			 * so return EINVAL in any other cmsg_type
  			 */
 -			if ((cmsg->cmsg_type =
 -			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1)
 -				goto bad;
 +			cmsg->cmsg_type =
 +			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
  			cmsg->cmsg_level =
  			    linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
 +			if (cmsg->cmsg_type == -1
 +			    || cmsg->cmsg_level != SOL_SOCKET)
 +				goto bad;
 +
 +			/*
 +			 * Some applications (e.g. pulseaudio) attempt to
 +			 * send ancillary data even if the underlying protocol
 +			 * doesn't support it which is not allowed in the
 +			 * FreeBSD system call interface.
 +			 */
 +			if (sa_family != AF_UNIX)
 +				continue;
  
 +			data = LINUX_CMSG_DATA(ptr_cmsg);
  			datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
 +
 +			switch (cmsg->cmsg_type)
 +			{
 +			case SCM_RIGHTS:
 +				break;
 +
 +			case SCM_CREDS:
 +				data = &cmcred;
 +				datalen = sizeof(cmcred);
 +
 +				/*
 +				 * The lower levels will fill in the structure
 +				 */
 +				bzero(data, datalen);
 +				break;
 +			}
 +
  			cmsg->cmsg_len = CMSG_LEN(datalen);
 -			data = LINUX_CMSG_DATA(ptr_cmsg);
  
  			error = ENOBUFS;
  			if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg))
 @@ -1166,9 +1210,11 @@ linux_sendmsg(struct thread *td, struct 
  			if (!m_append(control, datalen, (c_caddr_t) data))
  				goto bad;
  		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg)));
 -	} else {
 -		control = NULL;
 -		cmsg = NULL;
 +
 +		if (m_length(control, NULL) == 0) {
 +			m_freem(control);
 +			control = NULL;
 +		}
  	}
  
  	msg.msg_iov = iov;
 @@ -1193,9 +1239,11 @@ static int
  linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
  {
  	struct cmsghdr *cm;
 +	struct cmsgcred *cmcred;
  	struct msghdr msg;
  	struct l_cmsghdr *linux_cmsg = NULL;
 -	socklen_t datalen, outlen, clen;
 +	struct l_ucred linux_ucred;
 +	socklen_t datalen, outlen;
  	struct l_msghdr linux_msg;
  	struct iovec *iov, *uiov;
  	struct mbuf *control = NULL;
 @@ -1252,39 +1300,35 @@ linux_recvmsg(struct thread *td, struct 
  			goto bad;
  	}
  
 -	if (control) {
 +	outbuf = PTRIN(linux_msg.msg_control);
 +	outlen = 0;
  
 +	if (control) {
  		linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
 -		outbuf = PTRIN(linux_msg.msg_control);
 -		cm = mtod(control, struct cmsghdr *);
 -		outlen = 0;
 -		clen = control->m_len;
  
 -		while (cm != NULL) {
 +		msg.msg_control = mtod(control, struct cmsghdr *);
 +		msg.msg_controllen = control->m_len;
 +
 +		cm = CMSG_FIRSTHDR(&msg);
  
 -			if ((linux_cmsg->cmsg_type =
 -			    bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1)
 +		while (cm != NULL) {
 +			linux_cmsg->cmsg_type =
 +			    bsd_to_linux_cmsg_type(cm->cmsg_type);
 +			linux_cmsg->cmsg_level =
 +			    bsd_to_linux_sockopt_level(cm->cmsg_level);
 +			if (linux_cmsg->cmsg_type == -1
 +			    || cm->cmsg_level != SOL_SOCKET)
  			{
  				error = EINVAL;
  				goto bad;
  			}
 +
  			data = CMSG_DATA(cm);
  			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
  
 -			switch (linux_cmsg->cmsg_type)
 +			switch (cm->cmsg_type)
  			{
 -			case LINUX_SCM_RIGHTS:
 -				if (outlen + LINUX_CMSG_LEN(datalen) >
 -				    linux_msg.msg_controllen) {
 -					if (outlen == 0) {
 -						error = EMSGSIZE;
 -						goto bad;
 -					} else {
 -						linux_msg.msg_flags |=
 -						    LINUX_MSG_CTRUNC;
 -						goto out;
 -					}
 -				}
 +			case SCM_RIGHTS:
  				if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
  					fds = datalen / sizeof(int);
  					fdp = data;
 @@ -1295,11 +1339,40 @@ linux_recvmsg(struct thread *td, struct 
  					}
  				}
  				break;
 +
 +			case SCM_CREDS:
 +				/*
 +				 * Currently LOCAL_CREDS is never in
 +				 * effect for Linux so no need to worry
 +				 * about sockcred
 +				 */
 +				if (datalen != sizeof (*cmcred)) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				}
 +				cmcred = (struct cmsgcred *)data;
 +				bzero(&linux_ucred, sizeof(linux_ucred));
 +				linux_ucred.pid = cmcred->cmcred_pid;
 +				linux_ucred.uid = cmcred->cmcred_uid;
 +				linux_ucred.gid = cmcred->cmcred_gid;
 +				data = &linux_ucred;
 +				datalen = sizeof(linux_ucred);
 +				break;
 +			}
 +
 +			if (outlen + LINUX_CMSG_LEN(datalen) >
 +			    linux_msg.msg_controllen) {
 +				if (outlen == 0) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				} else {
 +					linux_msg.msg_flags |=
 +					    LINUX_MSG_CTRUNC;
 +					goto out;
 +				}
  			}
  
  			linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
 -			linux_cmsg->cmsg_level =
 -			    bsd_to_linux_sockopt_level(cm->cmsg_level);
  
  			error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
  			if (error)
 @@ -1312,18 +1385,13 @@ linux_recvmsg(struct thread *td, struct 
  
  			outbuf += LINUX_CMSG_ALIGN(datalen);
  			outlen += LINUX_CMSG_LEN(datalen);
 -			linux_msg.msg_controllen = outlen;
  
 -			if (CMSG_SPACE(datalen) < clen) {
 -				clen -= CMSG_SPACE(datalen);
 -				cm = (struct cmsghdr *)
 -				    ((caddr_t)cm + CMSG_SPACE(datalen));
 -			} else
 -				cm = NULL;
 +			cm = CMSG_NXTHDR(&msg, cm);
  		}
  	}
  
  out:
 +	linux_msg.msg_controllen = outlen;
  	error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
  
  bad:
 --- ./i386/linux/linux_dummy.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./i386/linux/linux_dummy.c	2011-02-12 22:36:57.000000000 -0500
 @@ -57,8 +57,6 @@ DUMMY(vm86);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);		/* different semantics */
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 --- ./i386/linux/syscalls.master.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./i386/linux/syscalls.master	2011-02-12 22:50:39.000000000 -0500
 @@ -329,8 +329,8 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(void *hdrp, void *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(void *hdrp, const void *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 --- ./amd64/linux32/syscalls.master.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./amd64/linux32/syscalls.master	2011-02-12 22:50:35.000000000 -0500
 @@ -327,8 +327,8 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(void *hdrp, void *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(void *hdrp, const void *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 -------------------------------------------------------------------------
 |   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
 |    John Wehle    |     Fax: 1-215-540-5495  |                         |
 -------------------------------------------------------------------------
 

From: Andriy Gapon <avg@freebsd.org>
To: John Wehle <john@feith.com>
Cc: rdivacky@freebsd.org, bug-followup@freebsd.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes
 for pulseaudio
Date: Sat, 26 Feb 2011 20:13:02 +0200

 on 13/02/2011 08:59 John Wehle said the following:
 > Enclosed is a slightly tweaked and lightly tested version.
 > 
 > Changes from previous:
 > 
 >   1) Modify linux/syscalls.master in i386 & amd64 instead of mucking a
 >      generated file.
 > 
 >   2) For symmetry also ignore msg_controllen in linux_to_bsd_msghdr.
 
 The patch is still missing changes to sys/amd64/linux32/linux32_dummy.c, but
 otherwise looks good.
 
 -- 
 Andriy Gapon

From: Andriy Gapon <avg@freebsd.org>
To: John Wehle <john@feith.com>
Cc: rdivacky@freebsd.org, bug-followup@freebsd.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes
 for pulseaudio
Date: Sun, 27 Feb 2011 12:01:25 +0200

 on 26/02/2011 20:13 Andriy Gapon said the following:
 > on 13/02/2011 08:59 John Wehle said the following:
 >> Enclosed is a slightly tweaked and lightly tested version.
 >>
 >> Changes from previous:
 >>
 >>   1) Modify linux/syscalls.master in i386 & amd64 instead of mucking a
 >>      generated file.
 >>
 >>   2) For symmetry also ignore msg_controllen in linux_to_bsd_msghdr.
 > 
 > The patch is still missing changes to sys/amd64/linux32/linux32_dummy.c, but
 > otherwise looks good.
 > 
 
 I wasn't right.
 Unfortunately, with this patch (unlike its original version) linux skype no
 longer connects to FreeBSD pulseaudio daemon for me on CURRENT/amd64.
 So something important seems to have been lost or broken while making the
 improvements.
 
 -- 
 Andriy Gapon

From: John Wehle <john@feith.com>
To: avg@freebsd.org
Cc: rdivacky@freebsd.org, bug-followup@freebsd.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Date: Mon, 28 Feb 2011 02:57:26 -0500 (EST)

 > Unfortunately, with this patch (unlike its original version) linux skype no
 > longer connects to FreeBSD pulseaudio daemon for me on CURRENT/amd64.
 > So something important seems to have been lost or broken while making the
 > improvements.
 
 That's a bit strange.  The amd64 specific bits are for capget / capset
 which are only used if you're running the Linux pulseaudio daemon,
 they're not used by the client code so I don't suspect a problem
 there.
 
 The rest of the code works fine (at least under light use) on my
 FreeBSD 8.2 i386 machine. The only changes between this patch and
 the previous are:
 
   a) Mucking linux/syscalls.master in i386 & amd64 ... unlikely
      to be a problem.
 
   b) "Cosmetic" change to linux_to_bsd_msghdr / linux_sendmsg to
      also ignore msg_controllen.  The change was unnecessary and
      rather minor, however it made the msg_controllen handling
      more symmetrical.
 
      Not sure what would have work on the i386 and not amd64 in what
      I mucked. :-(
 
 Are you sure the problem is with the later patch?  Did anything else
 change in your environment?  Does paplay work?  If not, what does
 paplay / pulseaudio daemon debug report?
 
 I'm not setup with CURRENT or amd64 ... how do you want to proceed?
 Do you want to provide access to a CURRENT/amd64 machine that I
 can reboot / muck the kernel?  Do you want to debug this?  Should
 I invest in setting up FreeBSD CURRENT/amd64 running under QEMU / Virtualbox?
 
 Don't mean to be asking too many questions. :-)  Just interesting in
 the game plan.
 
 -- John
 -------------------------------------------------------------------------
 |   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
 |    John Wehle    |     Fax: 1-215-540-5495  |                         |
 -------------------------------------------------------------------------
 

From: John Wehle <john@feith.com>
To: avg@freebsd.org
Cc: rdivacky@freebsd.org, bug-followup@freebsd.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Date: Mon, 28 Feb 2011 03:04:41 -0500 (EST)

 > Not sure what would have work on the i386 and not amd64 in what
 >  I mucked. :-(
 
 Grumble ... of course after I send the message I think I see something.
 Give me a couple of days to poke about and I'll get back to you with
 an update.
 
 -- John
 -------------------------------------------------------------------------
 |   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
 |    John Wehle    |     Fax: 1-215-540-5495  |                         |
 -------------------------------------------------------------------------
 

From: John Wehle <john@feith.com>
To: avg@freebsd.org
Cc: rdivacky@freebsd.org, bug-followup@freebsd.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Date: Tue, 8 Mar 2011 02:32:09 -0500 (EST)

 Enclosed is yet another slightly tweaked and lightly tested version.
 
 I made a bootable amd64 drive which mirrors my existing i386 system
 so I was able to test these changes on both amd64 and i386.
 
 Changes from previous:
 
   1) Include changes to amd64/linux32/linux32_dummy.c.
 
   2) Use PTRIN in LINUX_CMSG_FIRSTHDR and LINUX_CMSG_NXTHDR so
      linux_socket.c compiles without complaints on amd64.
 
   3) Invoke LINUX_CMSG_NXTHDR with the correct variable (basically
      I missed a place in my last round of changes).
 
 Notes:
 
   1) This has been tested on both i386 and amd64 with Fedora 10 paplay
      (client) talking to FreeBSD 8.2 pulseaudio (server) over both TCP
      and UNIX domain sockets.
 
   2) PulseAudio generates the socket name slightly differently between
      FreeBSD and Linux.  When using UNIX domain sockets please set
      PULSE_SERVER prior to invoking the client application.  E.g.:
 
        setenv PULSE_SERVER unix:/tmp/pulse-J1eO0ABCS0DM/native
 
      where /tmp/pulse-J1eO0ABCS0DM/native is the name of the FreeBSD
      PulseAudio socket.  Someone knowledgeable may be able to muck
 
        /usr/compat/linux/etc/pulse/client.conf
 
      so this is not necessary.
 
 -- John
 -----------------------8<----------------------------8<------------------
 --- ./compat/linux/linux_misc.h.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_misc.h	2011-02-26 22:41:49.000000000 -0500
 @@ -37,6 +37,8 @@
  					 * Second arg is a ptr to return the
  					 * signal.
  					 */
 +#define	LINUX_PR_GET_KEEPCAPS	7	/* Get drop capabilities on setuid */
 +#define	LINUX_PR_SET_KEEPCAPS	8	/* Set drop capabilities on setuid */
  #define	LINUX_PR_SET_NAME	15	/* Set process name. */
  #define	LINUX_PR_GET_NAME	16	/* Get process name. */
  
 --- ./compat/linux/linux_misc.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_misc.c	2011-02-26 22:41:49.000000000 -0500
 @@ -1733,6 +1733,87 @@ linux_exit_group(struct thread *td, stru
  	return (0);
  }
  
 +#define _LINUX_CAPABILITY_VERSION  0x19980330
 +
 +struct l_user_cap_header {
 +	l_int	version;
 +	l_int	pid;
 +};
 +
 +struct l_user_cap_data {
 +	l_int	effective;
 +	l_int	permitted;
 +	l_int	inheritable;
 +};
 +
 +int
 +linux_capget(struct thread *td, struct linux_capget_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (! args->hdrp)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	if (args->datap) {
 +		bzero (&lucd, sizeof(lucd));
 +		error = copyout(&lucd, args->datap, sizeof(lucd));
 +	}
 +
 +	return (error);
 +}
 +
 +int
 +linux_capset(struct thread *td, struct linux_capset_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (! args->hdrp || ! args->datap)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	error = copyin(args->datap, &lucd, sizeof(lucd));
 +	if (error != 0)
 +		return (error);
 +
 +	if (lucd.effective || lucd.permitted || lucd.inheritable)
 +		return (EPERM);
 +
 +	return (0);
 +}
 +
  int
  linux_prctl(struct thread *td, struct linux_prctl_args *args)
  {
 @@ -1766,6 +1847,11 @@ linux_prctl(struct thread *td, struct li
  		    (void *)(register_t)args->arg2,
  		    sizeof(pdeath_signal));
  		break;
 +	case LINUX_PR_GET_KEEPCAPS:
 +		td->td_retval[0] = 0;
 +		break;
 +	case LINUX_PR_SET_KEEPCAPS:
 +		break;
  	case LINUX_PR_SET_NAME:
  		/*
  		 * To be on the safe side we need to make sure to not
 --- ./compat/linux/linux_socket.h.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_socket.h	2011-03-07 23:40:31.000000000 -0500
 @@ -53,6 +53,7 @@
  /* Socket-level control message types */
  
  #define LINUX_SCM_RIGHTS	0x01
 +#define LINUX_SCM_CREDENTIALS   0x02
  
  /* Ancilliary data object information macros */
  
 @@ -66,13 +67,14 @@
  #define LINUX_CMSG_FIRSTHDR(msg) \
  				((msg)->msg_controllen >= \
  				    sizeof(struct l_cmsghdr) ? \
 -				    (struct l_cmsghdr *)((msg)->msg_control) : \
 +				    (struct l_cmsghdr *) \
 +				        PTRIN((msg)->msg_control) : \
  				    (struct l_cmsghdr *)(NULL))
  #define LINUX_CMSG_NXTHDR(msg, cmsg) \
  				((((char *)(cmsg) + \
  				    LINUX_CMSG_ALIGN((cmsg)->cmsg_len) + \
  				    sizeof(*(cmsg))) > \
 -				    (((char *)(msg)->msg_control) + \
 +				    (((char *)PTRIN((msg)->msg_control)) + \
  				    (msg)->msg_controllen)) ? \
  				    (struct l_cmsghdr *) NULL : \
  				    (struct l_cmsghdr *)((char *)(cmsg) + \
 --- ./compat/linux/linux_socket.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_socket.c	2011-03-07 23:38:21.000000000 -0500
 @@ -433,6 +433,8 @@ linux_to_bsd_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case LINUX_SCM_RIGHTS:
  		return (SCM_RIGHTS);
 +	case LINUX_SCM_CREDENTIALS:
 +		return (SCM_CREDS);
  	}
  	return (-1);
  }
 @@ -444,6 +446,8 @@ bsd_to_linux_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case SCM_RIGHTS:
  		return (LINUX_SCM_RIGHTS);
 +	case SCM_CREDS:
 +		return (LINUX_SCM_CREDENTIALS);
  	}
  	return (-1);
  }
 @@ -459,7 +463,7 @@ linux_to_bsd_msghdr(struct msghdr *bhdr,
  	bhdr->msg_iov		= PTRIN(lhdr->msg_iov);
  	bhdr->msg_iovlen	= lhdr->msg_iovlen;
  	bhdr->msg_control	= PTRIN(lhdr->msg_control);
 -	bhdr->msg_controllen	= lhdr->msg_controllen;
 +	/* msg_controllen skipped */
  	bhdr->msg_flags		= linux_to_bsd_msg_flags(lhdr->msg_flags);
  	return (0);
  }
 @@ -472,7 +476,7 @@ bsd_to_linux_msghdr(const struct msghdr 
  	lhdr->msg_iov		= PTROUT(bhdr->msg_iov);
  	lhdr->msg_iovlen	= bhdr->msg_iovlen;
  	lhdr->msg_control	= PTROUT(bhdr->msg_control);
 -	lhdr->msg_controllen	= bhdr->msg_controllen;
 +	/* msg_controllen skipped */
  	/* msg_flags skipped */
  	return (0);
  }
 @@ -1092,6 +1096,7 @@ static int
  linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
  {
  	struct cmsghdr *cmsg;
 +	struct cmsgcred cmcred;
  	struct mbuf *control;
  	struct msghdr msg;
  	struct l_cmsghdr linux_cmsg;
 @@ -1099,15 +1104,14 @@ linux_sendmsg(struct thread *td, struct 
  	struct l_msghdr linux_msg;
  	struct iovec *iov;
  	socklen_t datalen;
 +	struct sockaddr *sa;
 +	sa_family_t sa_family;
  	void *data;
  	int error;
  
  	error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
  	if (error)
  		return (error);
 -	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 -	if (error)
 -		return (error);
  
  	/*
  	 * Some Linux applications (ping) define a non-NULL control data
 @@ -1116,8 +1120,12 @@ linux_sendmsg(struct thread *td, struct 
  	 * order to handle this case.  This should be checked, but allows the
  	 * Linux ping to work.
  	 */
 -	if (msg.msg_control != NULL && msg.msg_controllen == 0)
 -		msg.msg_control = NULL;
 +	if (PTRIN(linux_msg.msg_control) != NULL && linux_msg.msg_controllen == 0)
 +		linux_msg.msg_control = PTROUT(NULL);
 +
 +	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 +	if (error)
 +		return (error);
  
  #ifdef COMPAT_LINUX32
  	error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
 @@ -1128,13 +1136,21 @@ linux_sendmsg(struct thread *td, struct 
  	if (error)
  		return (error);
  
 -	if (msg.msg_control != NULL) {
 +	control = NULL;
 +	cmsg = NULL;
 +
 +	if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
 +		error = kern_getsockname(td, args->s, &sa, &datalen);
 +		if (error)
 +			goto bad;
 +		sa_family = sa->sa_family;
 +		free(sa, M_SONAME);
 +
  		error = ENOBUFS;
  		cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
  		control = m_get(M_WAIT, MT_CONTROL);
  		if (control == NULL)
  			goto bad;
 -		ptr_cmsg = LINUX_CMSG_FIRSTHDR(&msg);
  
  		do {
  			error = copyin(ptr_cmsg, &linux_cmsg,
 @@ -1147,28 +1163,58 @@ linux_sendmsg(struct thread *td, struct 
  				goto bad;
  
  			/*
 -			 * Now we support only SCM_RIGHTS, so return EINVAL
 -			 * in any other cmsg_type
 +			 * Now we support only SCM_RIGHTS and SCM_CRED,
 +			 * so return EINVAL in any other cmsg_type
  			 */
 -			if ((cmsg->cmsg_type =
 -			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1)
 -				goto bad;
 +			cmsg->cmsg_type =
 +			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
  			cmsg->cmsg_level =
  			    linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
 +			if (cmsg->cmsg_type == -1
 +			    || cmsg->cmsg_level != SOL_SOCKET)
 +				goto bad;
 +
 +			/*
 +			 * Some applications (e.g. pulseaudio) attempt to
 +			 * send ancillary data even if the underlying protocol
 +			 * doesn't support it which is not allowed in the
 +			 * FreeBSD system call interface.
 +			 */
 +			if (sa_family != AF_UNIX)
 +				continue;
  
 +			data = LINUX_CMSG_DATA(ptr_cmsg);
  			datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
 +
 +			switch (cmsg->cmsg_type)
 +			{
 +			case SCM_RIGHTS:
 +				break;
 +
 +			case SCM_CREDS:
 +				data = &cmcred;
 +				datalen = sizeof(cmcred);
 +
 +				/*
 +				 * The lower levels will fill in the structure
 +				 */
 +				bzero(data, datalen);
 +				break;
 +			}
 +
  			cmsg->cmsg_len = CMSG_LEN(datalen);
 -			data = LINUX_CMSG_DATA(ptr_cmsg);
  
  			error = ENOBUFS;
  			if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg))
  				goto bad;
  			if (!m_append(control, datalen, (c_caddr_t) data))
  				goto bad;
 -		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg)));
 -	} else {
 -		control = NULL;
 -		cmsg = NULL;
 +		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
 +
 +		if (m_length(control, NULL) == 0) {
 +			m_freem(control);
 +			control = NULL;
 +		}
  	}
  
  	msg.msg_iov = iov;
 @@ -1193,9 +1239,11 @@ static int
  linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
  {
  	struct cmsghdr *cm;
 +	struct cmsgcred *cmcred;
  	struct msghdr msg;
  	struct l_cmsghdr *linux_cmsg = NULL;
 -	socklen_t datalen, outlen, clen;
 +	struct l_ucred linux_ucred;
 +	socklen_t datalen, outlen;
  	struct l_msghdr linux_msg;
  	struct iovec *iov, *uiov;
  	struct mbuf *control = NULL;
 @@ -1252,39 +1300,35 @@ linux_recvmsg(struct thread *td, struct 
  			goto bad;
  	}
  
 -	if (control) {
 +	outbuf = PTRIN(linux_msg.msg_control);
 +	outlen = 0;
  
 +	if (control) {
  		linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
 -		outbuf = PTRIN(linux_msg.msg_control);
 -		cm = mtod(control, struct cmsghdr *);
 -		outlen = 0;
 -		clen = control->m_len;
  
 -		while (cm != NULL) {
 +		msg.msg_control = mtod(control, struct cmsghdr *);
 +		msg.msg_controllen = control->m_len;
 +
 +		cm = CMSG_FIRSTHDR(&msg);
  
 -			if ((linux_cmsg->cmsg_type =
 -			    bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1)
 +		while (cm != NULL) {
 +			linux_cmsg->cmsg_type =
 +			    bsd_to_linux_cmsg_type(cm->cmsg_type);
 +			linux_cmsg->cmsg_level =
 +			    bsd_to_linux_sockopt_level(cm->cmsg_level);
 +			if (linux_cmsg->cmsg_type == -1
 +			    || cm->cmsg_level != SOL_SOCKET)
  			{
  				error = EINVAL;
  				goto bad;
  			}
 +
  			data = CMSG_DATA(cm);
  			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
  
 -			switch (linux_cmsg->cmsg_type)
 +			switch (cm->cmsg_type)
  			{
 -			case LINUX_SCM_RIGHTS:
 -				if (outlen + LINUX_CMSG_LEN(datalen) >
 -				    linux_msg.msg_controllen) {
 -					if (outlen == 0) {
 -						error = EMSGSIZE;
 -						goto bad;
 -					} else {
 -						linux_msg.msg_flags |=
 -						    LINUX_MSG_CTRUNC;
 -						goto out;
 -					}
 -				}
 +			case SCM_RIGHTS:
  				if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
  					fds = datalen / sizeof(int);
  					fdp = data;
 @@ -1295,11 +1339,40 @@ linux_recvmsg(struct thread *td, struct 
  					}
  				}
  				break;
 +
 +			case SCM_CREDS:
 +				/*
 +				 * Currently LOCAL_CREDS is never in
 +				 * effect for Linux so no need to worry
 +				 * about sockcred
 +				 */
 +				if (datalen != sizeof (*cmcred)) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				}
 +				cmcred = (struct cmsgcred *)data;
 +				bzero(&linux_ucred, sizeof(linux_ucred));
 +				linux_ucred.pid = cmcred->cmcred_pid;
 +				linux_ucred.uid = cmcred->cmcred_uid;
 +				linux_ucred.gid = cmcred->cmcred_gid;
 +				data = &linux_ucred;
 +				datalen = sizeof(linux_ucred);
 +				break;
 +			}
 +
 +			if (outlen + LINUX_CMSG_LEN(datalen) >
 +			    linux_msg.msg_controllen) {
 +				if (outlen == 0) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				} else {
 +					linux_msg.msg_flags |=
 +					    LINUX_MSG_CTRUNC;
 +					goto out;
 +				}
  			}
  
  			linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
 -			linux_cmsg->cmsg_level =
 -			    bsd_to_linux_sockopt_level(cm->cmsg_level);
  
  			error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
  			if (error)
 @@ -1312,18 +1385,13 @@ linux_recvmsg(struct thread *td, struct 
  
  			outbuf += LINUX_CMSG_ALIGN(datalen);
  			outlen += LINUX_CMSG_LEN(datalen);
 -			linux_msg.msg_controllen = outlen;
  
 -			if (CMSG_SPACE(datalen) < clen) {
 -				clen -= CMSG_SPACE(datalen);
 -				cm = (struct cmsghdr *)
 -				    ((caddr_t)cm + CMSG_SPACE(datalen));
 -			} else
 -				cm = NULL;
 +			cm = CMSG_NXTHDR(&msg, cm);
  		}
  	}
  
  out:
 +	linux_msg.msg_controllen = outlen;
  	error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
  
  bad:
 --- ./i386/linux/linux_dummy.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./i386/linux/linux_dummy.c	2011-02-26 22:41:49.000000000 -0500
 @@ -57,8 +57,6 @@ DUMMY(vm86);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);		/* different semantics */
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 --- ./i386/linux/syscalls.master.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./i386/linux/syscalls.master	2011-02-26 22:41:49.000000000 -0500
 @@ -329,8 +329,8 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(void *hdrp, void *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(void *hdrp, const void *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 --- ./amd64/linux32/linux32_dummy.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./amd64/linux32/linux32_dummy.c	2011-03-07 23:36:02.000000000 -0500
 @@ -54,8 +54,6 @@ DUMMY(sysfs);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 --- ./amd64/linux32/syscalls.master.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./amd64/linux32/syscalls.master	2011-02-26 22:41:49.000000000 -0500
 @@ -327,8 +327,8 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(void *hdrp, void *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(void *hdrp, const void *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 -------------------------------------------------------------------------
 |   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
 |    John Wehle    |     Fax: 1-215-540-5495  |                         |
 -------------------------------------------------------------------------
 

From: Andriy Gapon <avg@freebsd.org>
To: John Wehle <john@feith.com>
Cc: rdivacky@freebsd.org, bug-followup@freebsd.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes
 for pulseaudio
Date: Thu, 10 Mar 2011 11:54:31 +0200

 on 08/03/2011 09:32 John Wehle said the following:
 > Enclosed is yet another slightly tweaked and lightly tested version.
 > 
 > I made a bootable amd64 drive which mirrors my existing i386 system
 > so I was able to test these changes on both amd64 and i386.
 > 
 > Changes from previous:
 > 
 >   1) Include changes to amd64/linux32/linux32_dummy.c.
 > 
 >   2) Use PTRIN in LINUX_CMSG_FIRSTHDR and LINUX_CMSG_NXTHDR so
 >      linux_socket.c compiles without complaints on amd64.
 > 
 >   3) Invoke LINUX_CMSG_NXTHDR with the correct variable (basically
 >      I missed a place in my last round of changes).
 
 Thanks a lot!  This patch works as expected for me.
 Unless anybody objects or wants to hold this patch for further reviewing I will
 try to commit it this coming weekend.
 
 > Notes:
 > 
 >   1) This has been tested on both i386 and amd64 with Fedora 10 paplay
 >      (client) talking to FreeBSD 8.2 pulseaudio (server) over both TCP
 >      and UNIX domain sockets.
 > 
 >   2) PulseAudio generates the socket name slightly differently between
 >      FreeBSD and Linux.  When using UNIX domain sockets please set
 >      PULSE_SERVER prior to invoking the client application.  E.g.:
 > 
 >        setenv PULSE_SERVER unix:/tmp/pulse-J1eO0ABCS0DM/native
 > 
 >      where /tmp/pulse-J1eO0ABCS0DM/native is the name of the FreeBSD
 >      PulseAudio socket.  Someone knowledgeable may be able to muck
 > 
 >        /usr/compat/linux/etc/pulse/client.conf
 > 
 >      so this is not necessary.
 
 Looks like the pulseaudio developers changed their mind about the separator
 somewhere between versions 0.9.14 and 0.9.21.  If we could find a more recent
 package for f10 that would help.  Not sure if a package from later fedora
 versions would work.
 
 -- 
 Andriy Gapon

From: John Wehle <john@feith.com>
To: alexander@leidinger.net
Cc: freebsd-emulation@FreeBSD.org, bug-followup@FreeBSD.org, avg@FreeBSD.org
Subject: Re: kern/149168: [linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Date: Mon, 21 Mar 2011 01:27:41 -0400 (EDT)

 Enclosed is yet another slightly tweaked and lightly tested version.
 
 Changes from previous:
 
   1) Address some style issues.
 
   2) Add additional comments.
 
 Notes:
 
   1) This has been tested on both i386 and amd64 with Fedora 10 paplay
      (client) talking to FreeBSD 8.2 pulseaudio (server) over both TCP
      and UNIX domain sockets.
 
 -- John
 -----------------------8<----------------------------8<------------------
 --- ./compat/linux/linux_misc.h.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_misc.h	2011-03-07 23:54:17.000000000 -0500
 @@ -37,6 +37,8 @@
  					 * Second arg is a ptr to return the
  					 * signal.
  					 */
 +#define	LINUX_PR_GET_KEEPCAPS	7	/* Get drop capabilities on setuid */
 +#define	LINUX_PR_SET_KEEPCAPS	8	/* Set drop capabilities on setuid */
  #define	LINUX_PR_SET_NAME	15	/* Set process name. */
  #define	LINUX_PR_GET_NAME	16	/* Get process name. */
  
 --- ./compat/linux/linux_misc.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_misc.c	2011-03-18 00:02:48.000000000 -0400
 @@ -1733,6 +1733,100 @@ linux_exit_group(struct thread *td, stru
  	return (0);
  }
  
 +#define _LINUX_CAPABILITY_VERSION  0x19980330
 +
 +struct l_user_cap_header {
 +	l_int	version;
 +	l_int	pid;
 +};
 +
 +struct l_user_cap_data {
 +	l_int	effective;
 +	l_int	permitted;
 +	l_int	inheritable;
 +};
 +
 +int
 +linux_capget(struct thread *td, struct linux_capget_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (args->hdrp == NULL)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	if (args->datap) {
 +		/*
 +		 * The current implementation doesn't support setting
 +		 * a capability (it's essentially a stub) so indicate
 +		 * that no capabilities are currently set or available
 +		 * to request.
 +		 */
 +		bzero (&lucd, sizeof(lucd));
 +		error = copyout(&lucd, args->datap, sizeof(lucd));
 +	}
 +
 +	return (error);
 +}
 +
 +int
 +linux_capset(struct thread *td, struct linux_capset_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (args->hdrp == NULL || args->datap == NULL)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	error = copyin(args->datap, &lucd, sizeof(lucd));
 +	if (error != 0)
 +		return (error);
 +
 +	/* We currently don't support setting any capabilities. */
 +	if (lucd.effective || lucd.permitted || lucd.inheritable) {
 +		linux_msg(td,
 +			  "capset effective=0x%x, permitted=0x%x, "
 +			  "inheritable=0x%x is not implemented",
 +			  (int)lucd.effective, (int)lucd.permitted,
 +			  (int)lucd.inheritable);
 +		return (EPERM);
 +	}
 +
 +	return (0);
 +}
 +
  int
  linux_prctl(struct thread *td, struct linux_prctl_args *args)
  {
 @@ -1766,6 +1860,21 @@ linux_prctl(struct thread *td, struct li
  		    (void *)(register_t)args->arg2,
  		    sizeof(pdeath_signal));
  		break;
 +	case LINUX_PR_GET_KEEPCAPS:
 +		/*
 +		 * Indicate that we always clear the effective and
 +		 * permitted capability sets when the user id becomes
 +		 * non-zero (actually the capability sets are simply
 +		 * always zero in the current implementation).
 +		 */
 +		td->td_retval[0] = 0;
 +		break;
 +	case LINUX_PR_SET_KEEPCAPS:
 +		/*
 +		 * Ignore requests to keep the effective and permitted
 +		 * capability sets when the user id becomes non-zero.
 +		 */
 +		break;
  	case LINUX_PR_SET_NAME:
  		/*
  		 * To be on the safe side we need to make sure to not
 --- ./compat/linux/linux_socket.h.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_socket.h	2011-03-07 23:54:17.000000000 -0500
 @@ -53,6 +53,7 @@
  /* Socket-level control message types */
  
  #define LINUX_SCM_RIGHTS	0x01
 +#define LINUX_SCM_CREDENTIALS   0x02
  
  /* Ancilliary data object information macros */
  
 @@ -66,13 +67,14 @@
  #define LINUX_CMSG_FIRSTHDR(msg) \
  				((msg)->msg_controllen >= \
  				    sizeof(struct l_cmsghdr) ? \
 -				    (struct l_cmsghdr *)((msg)->msg_control) : \
 +				    (struct l_cmsghdr *) \
 +				        PTRIN((msg)->msg_control) : \
  				    (struct l_cmsghdr *)(NULL))
  #define LINUX_CMSG_NXTHDR(msg, cmsg) \
  				((((char *)(cmsg) + \
  				    LINUX_CMSG_ALIGN((cmsg)->cmsg_len) + \
  				    sizeof(*(cmsg))) > \
 -				    (((char *)(msg)->msg_control) + \
 +				    (((char *)PTRIN((msg)->msg_control)) + \
  				    (msg)->msg_controllen)) ? \
  				    (struct l_cmsghdr *) NULL : \
  				    (struct l_cmsghdr *)((char *)(cmsg) + \
 --- ./compat/linux/linux_socket.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./compat/linux/linux_socket.c	2011-03-17 23:35:37.000000000 -0400
 @@ -433,6 +433,8 @@ linux_to_bsd_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case LINUX_SCM_RIGHTS:
  		return (SCM_RIGHTS);
 +	case LINUX_SCM_CREDENTIALS:
 +		return (SCM_CREDS);
  	}
  	return (-1);
  }
 @@ -444,6 +446,8 @@ bsd_to_linux_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case SCM_RIGHTS:
  		return (LINUX_SCM_RIGHTS);
 +	case SCM_CREDS:
 +		return (LINUX_SCM_CREDENTIALS);
  	}
  	return (-1);
  }
 @@ -459,7 +463,16 @@ linux_to_bsd_msghdr(struct msghdr *bhdr,
  	bhdr->msg_iov		= PTRIN(lhdr->msg_iov);
  	bhdr->msg_iovlen	= lhdr->msg_iovlen;
  	bhdr->msg_control	= PTRIN(lhdr->msg_control);
 -	bhdr->msg_controllen	= lhdr->msg_controllen;
 +
 +	/*
 +	 * msg_controllen is skipped since BSD and LINUX control messages
 +	 * are potentially different sizes (e.g. the cred structure used
 +	 * by SCM_CREDS is different between the two operating system).
 +	 *
 +	 * The caller can set it (if necessary) after converting all the
 +	 * control messages.
 +	 */
 +
  	bhdr->msg_flags		= linux_to_bsd_msg_flags(lhdr->msg_flags);
  	return (0);
  }
 @@ -472,7 +485,16 @@ bsd_to_linux_msghdr(const struct msghdr 
  	lhdr->msg_iov		= PTROUT(bhdr->msg_iov);
  	lhdr->msg_iovlen	= bhdr->msg_iovlen;
  	lhdr->msg_control	= PTROUT(bhdr->msg_control);
 -	lhdr->msg_controllen	= bhdr->msg_controllen;
 +
 +	/*
 +	 * msg_controllen is skipped since BSD and LINUX control messages
 +	 * are potentially different sizes (e.g. the cred structure used
 +	 * by SCM_CREDS is different between the two operating system).
 +	 *
 +	 * The caller can set it (if necessary) after converting all the
 +	 * control messages.
 +	 */
 +
  	/* msg_flags skipped */
  	return (0);
  }
 @@ -1092,6 +1114,7 @@ static int
  linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
  {
  	struct cmsghdr *cmsg;
 +	struct cmsgcred cmcred;
  	struct mbuf *control;
  	struct msghdr msg;
  	struct l_cmsghdr linux_cmsg;
 @@ -1099,15 +1122,14 @@ linux_sendmsg(struct thread *td, struct 
  	struct l_msghdr linux_msg;
  	struct iovec *iov;
  	socklen_t datalen;
 +	struct sockaddr *sa;
 +	sa_family_t sa_family;
  	void *data;
  	int error;
  
  	error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
  	if (error)
  		return (error);
 -	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 -	if (error)
 -		return (error);
  
  	/*
  	 * Some Linux applications (ping) define a non-NULL control data
 @@ -1116,8 +1138,12 @@ linux_sendmsg(struct thread *td, struct 
  	 * order to handle this case.  This should be checked, but allows the
  	 * Linux ping to work.
  	 */
 -	if (msg.msg_control != NULL && msg.msg_controllen == 0)
 -		msg.msg_control = NULL;
 +	if (PTRIN(linux_msg.msg_control) != NULL && linux_msg.msg_controllen == 0)
 +		linux_msg.msg_control = PTROUT(NULL);
 +
 +	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 +	if (error)
 +		return (error);
  
  #ifdef COMPAT_LINUX32
  	error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
 @@ -1128,13 +1154,21 @@ linux_sendmsg(struct thread *td, struct 
  	if (error)
  		return (error);
  
 -	if (msg.msg_control != NULL) {
 +	control = NULL;
 +	cmsg = NULL;
 +
 +	if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
 +		error = kern_getsockname(td, args->s, &sa, &datalen);
 +		if (error)
 +			goto bad;
 +		sa_family = sa->sa_family;
 +		free(sa, M_SONAME);
 +
  		error = ENOBUFS;
  		cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
  		control = m_get(M_WAIT, MT_CONTROL);
  		if (control == NULL)
  			goto bad;
 -		ptr_cmsg = LINUX_CMSG_FIRSTHDR(&msg);
  
  		do {
  			error = copyin(ptr_cmsg, &linux_cmsg,
 @@ -1147,28 +1181,58 @@ linux_sendmsg(struct thread *td, struct 
  				goto bad;
  
  			/*
 -			 * Now we support only SCM_RIGHTS, so return EINVAL
 -			 * in any other cmsg_type
 +			 * Now we support only SCM_RIGHTS and SCM_CRED,
 +			 * so return EINVAL in any other cmsg_type
  			 */
 -			if ((cmsg->cmsg_type =
 -			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1)
 -				goto bad;
 +			cmsg->cmsg_type =
 +			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
  			cmsg->cmsg_level =
  			    linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
 +			if (cmsg->cmsg_type == -1
 +			    || cmsg->cmsg_level != SOL_SOCKET)
 +				goto bad;
  
 +			/*
 +			 * Some applications (e.g. pulseaudio) attempt to
 +			 * send ancillary data even if the underlying protocol
 +			 * doesn't support it which is not allowed in the
 +			 * FreeBSD system call interface.
 +			 */
 +			if (sa_family != AF_UNIX)
 +				continue;
 +
 +			data = LINUX_CMSG_DATA(ptr_cmsg);
  			datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
 +
 +			switch (cmsg->cmsg_type)
 +			{
 +			case SCM_RIGHTS:
 +				break;
 +
 +			case SCM_CREDS:
 +				data = &cmcred;
 +				datalen = sizeof(cmcred);
 +
 +				/*
 +				 * The lower levels will fill in the structure
 +				 */
 +				bzero(data, datalen);
 +				break;
 +			}
 +
  			cmsg->cmsg_len = CMSG_LEN(datalen);
 -			data = LINUX_CMSG_DATA(ptr_cmsg);
  
  			error = ENOBUFS;
  			if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg))
  				goto bad;
  			if (!m_append(control, datalen, (c_caddr_t) data))
  				goto bad;
 -		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg)));
 -	} else {
 -		control = NULL;
 -		cmsg = NULL;
 +		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
 +
 +		if (m_length(control, NULL) == 0) {
 +			m_freem(control);
 +			control = NULL;
 +		}
  	}
  
  	msg.msg_iov = iov;
 @@ -1193,9 +1257,11 @@ static int
  linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
  {
  	struct cmsghdr *cm;
 +	struct cmsgcred *cmcred;
  	struct msghdr msg;
  	struct l_cmsghdr *linux_cmsg = NULL;
 -	socklen_t datalen, outlen, clen;
 +	struct l_ucred linux_ucred;
 +	socklen_t datalen, outlen;
  	struct l_msghdr linux_msg;
  	struct iovec *iov, *uiov;
  	struct mbuf *control = NULL;
 @@ -1252,39 +1318,35 @@ linux_recvmsg(struct thread *td, struct 
  			goto bad;
  	}
  
 -	if (control) {
 +	outbuf = PTRIN(linux_msg.msg_control);
 +	outlen = 0;
  
 +	if (control) {
  		linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
 -		outbuf = PTRIN(linux_msg.msg_control);
 -		cm = mtod(control, struct cmsghdr *);
 -		outlen = 0;
 -		clen = control->m_len;
  
 -		while (cm != NULL) {
 +		msg.msg_control = mtod(control, struct cmsghdr *);
 +		msg.msg_controllen = control->m_len;
 +
 +		cm = CMSG_FIRSTHDR(&msg);
  
 -			if ((linux_cmsg->cmsg_type =
 -			    bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1)
 +		while (cm != NULL) {
 +			linux_cmsg->cmsg_type =
 +			    bsd_to_linux_cmsg_type(cm->cmsg_type);
 +			linux_cmsg->cmsg_level =
 +			    bsd_to_linux_sockopt_level(cm->cmsg_level);
 +			if (linux_cmsg->cmsg_type == -1
 +			    || cm->cmsg_level != SOL_SOCKET)
  			{
  				error = EINVAL;
  				goto bad;
  			}
 +
  			data = CMSG_DATA(cm);
  			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
  
 -			switch (linux_cmsg->cmsg_type)
 +			switch (cm->cmsg_type)
  			{
 -			case LINUX_SCM_RIGHTS:
 -				if (outlen + LINUX_CMSG_LEN(datalen) >
 -				    linux_msg.msg_controllen) {
 -					if (outlen == 0) {
 -						error = EMSGSIZE;
 -						goto bad;
 -					} else {
 -						linux_msg.msg_flags |=
 -						    LINUX_MSG_CTRUNC;
 -						goto out;
 -					}
 -				}
 +			case SCM_RIGHTS:
  				if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
  					fds = datalen / sizeof(int);
  					fdp = data;
 @@ -1295,11 +1357,40 @@ linux_recvmsg(struct thread *td, struct 
  					}
  				}
  				break;
 +
 +			case SCM_CREDS:
 +				/*
 +				 * Currently LOCAL_CREDS is never in
 +				 * effect for Linux so no need to worry
 +				 * about sockcred
 +				 */
 +				if (datalen != sizeof (*cmcred)) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				}
 +				cmcred = (struct cmsgcred *)data;
 +				bzero(&linux_ucred, sizeof(linux_ucred));
 +				linux_ucred.pid = cmcred->cmcred_pid;
 +				linux_ucred.uid = cmcred->cmcred_uid;
 +				linux_ucred.gid = cmcred->cmcred_gid;
 +				data = &linux_ucred;
 +				datalen = sizeof(linux_ucred);
 +				break;
 +			}
 +
 +			if (outlen + LINUX_CMSG_LEN(datalen) >
 +			    linux_msg.msg_controllen) {
 +				if (outlen == 0) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				} else {
 +					linux_msg.msg_flags |=
 +					    LINUX_MSG_CTRUNC;
 +					goto out;
 +				}
  			}
  
  			linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
 -			linux_cmsg->cmsg_level =
 -			    bsd_to_linux_sockopt_level(cm->cmsg_level);
  
  			error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
  			if (error)
 @@ -1312,18 +1403,13 @@ linux_recvmsg(struct thread *td, struct 
  
  			outbuf += LINUX_CMSG_ALIGN(datalen);
  			outlen += LINUX_CMSG_LEN(datalen);
 -			linux_msg.msg_controllen = outlen;
  
 -			if (CMSG_SPACE(datalen) < clen) {
 -				clen -= CMSG_SPACE(datalen);
 -				cm = (struct cmsghdr *)
 -				    ((caddr_t)cm + CMSG_SPACE(datalen));
 -			} else
 -				cm = NULL;
 +			cm = CMSG_NXTHDR(&msg, cm);
  		}
  	}
  
  out:
 +	linux_msg.msg_controllen = outlen;
  	error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
  
  bad:
 --- ./i386/linux/linux_dummy.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./i386/linux/linux_dummy.c	2011-03-07 23:54:17.000000000 -0500
 @@ -57,8 +57,6 @@ DUMMY(vm86);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);		/* different semantics */
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 --- ./i386/linux/syscalls.master.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./i386/linux/syscalls.master	2011-03-17 23:46:17.000000000 -0400
 @@ -329,8 +329,10 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 --- ./amd64/linux32/linux32_dummy.c.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./amd64/linux32/linux32_dummy.c	2011-03-07 23:54:17.000000000 -0500
 @@ -54,8 +54,6 @@ DUMMY(sysfs);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 --- ./amd64/linux32/syscalls.master.ORIGINAL	2010-12-21 12:09:25.000000000 -0500
 +++ ./amd64/linux32/syscalls.master	2011-03-17 23:47:06.000000000 -0400
 @@ -327,8 +327,10 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 -------------------------------------------------------------------------
 |   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
 |    John Wehle    |     Fax: 1-215-540-5495  |                         |
 -------------------------------------------------------------------------
 -------------------------------------------------------------------------
 |   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
 |    John Wehle    |     Fax: 1-215-540-5495  |                         |
 -------------------------------------------------------------------------
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat, 26 Mar 2011 10:52:06 +0000 (UTC)

 Author: avg
 Date: Sat Mar 26 10:51:56 2011
 New Revision: 220028
 URL: http://svn.freebsd.org/changeset/base/220028
 
 Log:
   linux compat: add non-dummy capget and capset system calls
   
   PR:		kern/149168
   Submitted by:	John Wehle <john@feith.com>
   Reviewed by:	netchild
   MFC after:	2 weeks
 
 Modified:
   head/sys/amd64/linux32/syscalls.master
   head/sys/i386/linux/syscalls.master
 
 Modified: head/sys/amd64/linux32/syscalls.master
 ==============================================================================
 --- head/sys/amd64/linux32/syscalls.master	Sat Mar 26 10:47:17 2011	(r220027)
 +++ head/sys/amd64/linux32/syscalls.master	Sat Mar 26 10:51:56 2011	(r220028)
 @@ -326,8 +326,10 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 
 Modified: head/sys/i386/linux/syscalls.master
 ==============================================================================
 --- head/sys/i386/linux/syscalls.master	Sat Mar 26 10:47:17 2011	(r220027)
 +++ head/sys/i386/linux/syscalls.master	Sat Mar 26 10:51:56 2011	(r220028)
 @@ -328,8 +328,10 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat, 26 Mar 2011 10:59:38 +0000 (UTC)

 Author: avg
 Date: Sat Mar 26 10:59:24 2011
 New Revision: 220030
 URL: http://svn.freebsd.org/changeset/base/220030
 
 Log:
   linux compat: add non-dummy capget and capset system calls, regenerate
   
   And drop dummy definitions for those system calls.
   This may transiently break the build.
   
   PR:		kern/149168
   Submitted by:	John Wehle <john@feith.com>
   Reviewed by:	netchild
   MFC after:	2 weeks
 
 Modified:
   head/sys/amd64/linux32/linux32_dummy.c
   head/sys/amd64/linux32/linux32_proto.h
   head/sys/amd64/linux32/linux32_syscall.h
   head/sys/amd64/linux32/linux32_syscalls.c
   head/sys/amd64/linux32/linux32_sysent.c
   head/sys/amd64/linux32/linux32_systrace_args.c
   head/sys/i386/linux/linux_dummy.c
   head/sys/i386/linux/linux_proto.h
   head/sys/i386/linux/linux_syscall.h
   head/sys/i386/linux/linux_syscalls.c
   head/sys/i386/linux/linux_sysent.c
   head/sys/i386/linux/linux_systrace_args.c
 
 Modified: head/sys/amd64/linux32/linux32_dummy.c
 ==============================================================================
 --- head/sys/amd64/linux32/linux32_dummy.c	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/amd64/linux32/linux32_dummy.c	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -54,8 +54,6 @@ DUMMY(sysfs);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 
 Modified: head/sys/amd64/linux32/linux32_proto.h
 ==============================================================================
 --- head/sys/amd64/linux32/linux32_proto.h	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/amd64/linux32/linux32_proto.h	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 219559 2011-03-12 08:51:43Z avg 
 + * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 220028 2011-03-26 10:51:56Z avg 
   */
  
  #ifndef _LINUX_SYSPROTO_H_
 @@ -589,10 +589,12 @@ struct linux_getcwd_args {
  	char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)];
  };
  struct linux_capget_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_capset_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_sigaltstack_args {
  	char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)];
 
 Modified: head/sys/amd64/linux32/linux32_syscall.h
 ==============================================================================
 --- head/sys/amd64/linux32/linux32_syscall.h	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/amd64/linux32/linux32_syscall.h	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 219559 2011-03-12 08:51:43Z avg 
 + * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 220028 2011-03-26 10:51:56Z avg 
   */
  
  #define	LINUX_SYS_exit	1
 
 Modified: head/sys/amd64/linux32/linux32_syscalls.c
 ==============================================================================
 --- head/sys/amd64/linux32/linux32_syscalls.c	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/amd64/linux32/linux32_syscalls.c	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 219559 2011-03-12 08:51:43Z avg 
 + * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 220028 2011-03-26 10:51:56Z avg 
   */
  
  const char *linux_syscallnames[] = {
 
 Modified: head/sys/amd64/linux32/linux32_sysent.c
 ==============================================================================
 --- head/sys/amd64/linux32/linux32_sysent.c	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/amd64/linux32/linux32_sysent.c	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 219559 2011-03-12 08:51:43Z avg 
 + * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 220028 2011-03-26 10:51:56Z avg 
   */
  
  #include "opt_compat.h"
 @@ -203,8 +203,8 @@ struct sysent linux_sysent[] = {
  	{ AS(linux_pwrite_args), (sy_call_t *)linux_pwrite, AUE_PWRITE, NULL, 0, 0, 0, SY_THR_STATIC },	/* 181 = linux_pwrite */
  	{ AS(linux_chown16_args), (sy_call_t *)linux_chown16, AUE_CHOWN, NULL, 0, 0, 0, SY_THR_STATIC },	/* 182 = linux_chown16 */
  	{ AS(linux_getcwd_args), (sy_call_t *)linux_getcwd, AUE_GETCWD, NULL, 0, 0, 0, SY_THR_STATIC },	/* 183 = linux_getcwd */
 -	{ 0, (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 184 = linux_capget */
 -	{ 0, (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 185 = linux_capset */
 +	{ AS(linux_capget_args), (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 184 = linux_capget */
 +	{ AS(linux_capset_args), (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 185 = linux_capset */
  	{ AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 186 = linux_sigaltstack */
  	{ 0, (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0, 0, SY_THR_STATIC },	/* 187 = linux_sendfile */
  	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },			/* 188 = getpmsg */
 
 Modified: head/sys/amd64/linux32/linux32_systrace_args.c
 ==============================================================================
 --- head/sys/amd64/linux32/linux32_systrace_args.c	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/amd64/linux32/linux32_systrace_args.c	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -1284,12 +1284,18 @@ systrace_args(int sysnum, void *params, 
  	}
  	/* linux_capget */
  	case 184: {
 -		*n_args = 0;
 +		struct linux_capget_args *p = params;
 +		uarg[0] = (intptr_t) p->hdrp; /* struct l_user_cap_header * */
 +		uarg[1] = (intptr_t) p->datap; /* struct l_user_cap_data * */
 +		*n_args = 2;
  		break;
  	}
  	/* linux_capset */
  	case 185: {
 -		*n_args = 0;
 +		struct linux_capset_args *p = params;
 +		uarg[0] = (intptr_t) p->hdrp; /* struct l_user_cap_header * */
 +		uarg[1] = (intptr_t) p->datap; /* struct l_user_cap_data * */
 +		*n_args = 2;
  		break;
  	}
  	/* linux_sigaltstack */
 @@ -4051,9 +4057,29 @@ systrace_setargdesc(int sysnum, int ndx,
  		break;
  	/* linux_capget */
  	case 184:
 +		switch(ndx) {
 +		case 0:
 +			p = "struct l_user_cap_header *";
 +			break;
 +		case 1:
 +			p = "struct l_user_cap_data *";
 +			break;
 +		default:
 +			break;
 +		};
  		break;
  	/* linux_capset */
  	case 185:
 +		switch(ndx) {
 +		case 0:
 +			p = "struct l_user_cap_header *";
 +			break;
 +		case 1:
 +			p = "struct l_user_cap_data *";
 +			break;
 +		default:
 +			break;
 +		};
  		break;
  	/* linux_sigaltstack */
  	case 186:
 
 Modified: head/sys/i386/linux/linux_dummy.c
 ==============================================================================
 --- head/sys/i386/linux/linux_dummy.c	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/i386/linux/linux_dummy.c	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -57,8 +57,6 @@ DUMMY(vm86);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);		/* different semantics */
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 
 Modified: head/sys/i386/linux/linux_proto.h
 ==============================================================================
 --- head/sys/i386/linux/linux_proto.h	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/i386/linux/linux_proto.h	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: head/sys/i386/linux/syscalls.master 219559 2011-03-12 08:51:43Z avg 
 + * created from FreeBSD: head/sys/i386/linux/syscalls.master 220028 2011-03-26 10:51:56Z avg 
   */
  
  #ifndef _LINUX_SYSPROTO_H_
 @@ -586,10 +586,12 @@ struct linux_getcwd_args {
  	char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)];
  };
  struct linux_capget_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_capset_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_sigaltstack_args {
  	char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)];
 
 Modified: head/sys/i386/linux/linux_syscall.h
 ==============================================================================
 --- head/sys/i386/linux/linux_syscall.h	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/i386/linux/linux_syscall.h	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: head/sys/i386/linux/syscalls.master 219559 2011-03-12 08:51:43Z avg 
 + * created from FreeBSD: head/sys/i386/linux/syscalls.master 220028 2011-03-26 10:51:56Z avg 
   */
  
  #define	LINUX_SYS_exit	1
 
 Modified: head/sys/i386/linux/linux_syscalls.c
 ==============================================================================
 --- head/sys/i386/linux/linux_syscalls.c	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/i386/linux/linux_syscalls.c	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: head/sys/i386/linux/syscalls.master 219559 2011-03-12 08:51:43Z avg 
 + * created from FreeBSD: head/sys/i386/linux/syscalls.master 220028 2011-03-26 10:51:56Z avg 
   */
  
  const char *linux_syscallnames[] = {
 
 Modified: head/sys/i386/linux/linux_sysent.c
 ==============================================================================
 --- head/sys/i386/linux/linux_sysent.c	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/i386/linux/linux_sysent.c	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: head/sys/i386/linux/syscalls.master 219559 2011-03-12 08:51:43Z avg 
 + * created from FreeBSD: head/sys/i386/linux/syscalls.master 220028 2011-03-26 10:51:56Z avg 
   */
  
  #include <sys/param.h>
 @@ -202,8 +202,8 @@ struct sysent linux_sysent[] = {
  	{ AS(linux_pwrite_args), (sy_call_t *)linux_pwrite, AUE_PWRITE, NULL, 0, 0, 0, SY_THR_STATIC },	/* 181 = linux_pwrite */
  	{ AS(linux_chown16_args), (sy_call_t *)linux_chown16, AUE_CHOWN, NULL, 0, 0, 0, SY_THR_STATIC },	/* 182 = linux_chown16 */
  	{ AS(linux_getcwd_args), (sy_call_t *)linux_getcwd, AUE_GETCWD, NULL, 0, 0, 0, SY_THR_STATIC },	/* 183 = linux_getcwd */
 -	{ 0, (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 184 = linux_capget */
 -	{ 0, (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 185 = linux_capset */
 +	{ AS(linux_capget_args), (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 184 = linux_capget */
 +	{ AS(linux_capset_args), (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 185 = linux_capset */
  	{ AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 186 = linux_sigaltstack */
  	{ 0, (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0, 0, SY_THR_STATIC },	/* 187 = linux_sendfile */
  	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },			/* 188 = getpmsg */
 
 Modified: head/sys/i386/linux/linux_systrace_args.c
 ==============================================================================
 --- head/sys/i386/linux/linux_systrace_args.c	Sat Mar 26 10:52:37 2011	(r220029)
 +++ head/sys/i386/linux/linux_systrace_args.c	Sat Mar 26 10:59:24 2011	(r220030)
 @@ -1327,12 +1327,18 @@ systrace_args(int sysnum, void *params, 
  	}
  	/* linux_capget */
  	case 184: {
 -		*n_args = 0;
 +		struct linux_capget_args *p = params;
 +		uarg[0] = (intptr_t) p->hdrp; /* struct l_user_cap_header * */
 +		uarg[1] = (intptr_t) p->datap; /* struct l_user_cap_data * */
 +		*n_args = 2;
  		break;
  	}
  	/* linux_capset */
  	case 185: {
 -		*n_args = 0;
 +		struct linux_capset_args *p = params;
 +		uarg[0] = (intptr_t) p->hdrp; /* struct l_user_cap_header * */
 +		uarg[1] = (intptr_t) p->datap; /* struct l_user_cap_data * */
 +		*n_args = 2;
  		break;
  	}
  	/* linux_sigaltstack */
 @@ -4203,9 +4209,29 @@ systrace_setargdesc(int sysnum, int ndx,
  		break;
  	/* linux_capget */
  	case 184:
 +		switch(ndx) {
 +		case 0:
 +			p = "struct l_user_cap_header *";
 +			break;
 +		case 1:
 +			p = "struct l_user_cap_data *";
 +			break;
 +		default:
 +			break;
 +		};
  		break;
  	/* linux_capset */
  	case 185:
 +		switch(ndx) {
 +		case 0:
 +			p = "struct l_user_cap_header *";
 +			break;
 +		case 1:
 +			p = "struct l_user_cap_data *";
 +			break;
 +		default:
 +			break;
 +		};
  		break;
  	/* linux_sigaltstack */
  	case 186:
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat, 26 Mar 2011 11:06:08 +0000 (UTC)

 Author: avg
 Date: Sat Mar 26 11:05:53 2011
 New Revision: 220031
 URL: http://svn.freebsd.org/changeset/base/220031
 
 Log:
   linux compat: improve and fix sendmsg/recvmsg compatibility
   
   - implement baseic stubs for capget, capset, prctl PR_GET_KEEPCAPS
     and prctl PR_SET_KEEPCAPS.
   - add SCM_CREDS support to sendmsg and recvmsg
   - modify sendmsg to ignore control messages if not using UNIX
     domain sockets
   
   This should allow linux pulse audio daemon and client work on FreeBSD
   and interoperate with native counter-parts modulo the differences in
   pulseaudio versions.
   
   PR:		kern/149168
   Submitted by:	John Wehle <john@feith.com>
   Reviewed by:	netchild
   MFC after:	2 weeks
 
 Modified:
   head/sys/compat/linux/linux_misc.c
   head/sys/compat/linux/linux_misc.h
   head/sys/compat/linux/linux_socket.c
   head/sys/compat/linux/linux_socket.h
 
 Modified: head/sys/compat/linux/linux_misc.c
 ==============================================================================
 --- head/sys/compat/linux/linux_misc.c	Sat Mar 26 10:59:24 2011	(r220030)
 +++ head/sys/compat/linux/linux_misc.c	Sat Mar 26 11:05:53 2011	(r220031)
 @@ -1679,6 +1679,100 @@ linux_exit_group(struct thread *td, stru
  	return (0);
  }
  
 +#define _LINUX_CAPABILITY_VERSION  0x19980330
 +
 +struct l_user_cap_header {
 +	l_int	version;
 +	l_int	pid;
 +};
 +
 +struct l_user_cap_data {
 +	l_int	effective;
 +	l_int	permitted;
 +	l_int	inheritable;
 +};
 +
 +int
 +linux_capget(struct thread *td, struct linux_capget_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (args->hdrp == NULL)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	if (args->datap) {
 +		/*
 +		 * The current implementation doesn't support setting
 +		 * a capability (it's essentially a stub) so indicate
 +		 * that no capabilities are currently set or available
 +		 * to request.
 +		 */
 +		bzero (&lucd, sizeof(lucd));
 +		error = copyout(&lucd, args->datap, sizeof(lucd));
 +	}
 +
 +	return (error);
 +}
 +
 +int
 +linux_capset(struct thread *td, struct linux_capset_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (args->hdrp == NULL || args->datap == NULL)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	error = copyin(args->datap, &lucd, sizeof(lucd));
 +	if (error != 0)
 +		return (error);
 +
 +	/* We currently don't support setting any capabilities. */
 +	if (lucd.effective || lucd.permitted || lucd.inheritable) {
 +		linux_msg(td,
 +			  "capset effective=0x%x, permitted=0x%x, "
 +			  "inheritable=0x%x is not implemented",
 +			  (int)lucd.effective, (int)lucd.permitted,
 +			  (int)lucd.inheritable);
 +		return (EPERM);
 +	}
 +
 +	return (0);
 +}
 +
  int
  linux_prctl(struct thread *td, struct linux_prctl_args *args)
  {
 @@ -1712,6 +1806,21 @@ linux_prctl(struct thread *td, struct li
  		    (void *)(register_t)args->arg2,
  		    sizeof(pdeath_signal));
  		break;
 +	case LINUX_PR_GET_KEEPCAPS:
 +		/*
 +		 * Indicate that we always clear the effective and
 +		 * permitted capability sets when the user id becomes
 +		 * non-zero (actually the capability sets are simply
 +		 * always zero in the current implementation).
 +		 */
 +		td->td_retval[0] = 0;
 +		break;
 +	case LINUX_PR_SET_KEEPCAPS:
 +		/*
 +		 * Ignore requests to keep the effective and permitted
 +		 * capability sets when the user id becomes non-zero.
 +		 */
 +		break;
  	case LINUX_PR_SET_NAME:
  		/*
  		 * To be on the safe side we need to make sure to not
 
 Modified: head/sys/compat/linux/linux_misc.h
 ==============================================================================
 --- head/sys/compat/linux/linux_misc.h	Sat Mar 26 10:59:24 2011	(r220030)
 +++ head/sys/compat/linux/linux_misc.h	Sat Mar 26 11:05:53 2011	(r220031)
 @@ -37,6 +37,8 @@
  					 * Second arg is a ptr to return the
  					 * signal.
  					 */
 +#define	LINUX_PR_GET_KEEPCAPS	7	/* Get drop capabilities on setuid */
 +#define	LINUX_PR_SET_KEEPCAPS	8	/* Set drop capabilities on setuid */
  #define	LINUX_PR_SET_NAME	15	/* Set process name. */
  #define	LINUX_PR_GET_NAME	16	/* Get process name. */
  
 
 Modified: head/sys/compat/linux/linux_socket.c
 ==============================================================================
 --- head/sys/compat/linux/linux_socket.c	Sat Mar 26 10:59:24 2011	(r220030)
 +++ head/sys/compat/linux/linux_socket.c	Sat Mar 26 11:05:53 2011	(r220031)
 @@ -433,6 +433,8 @@ linux_to_bsd_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case LINUX_SCM_RIGHTS:
  		return (SCM_RIGHTS);
 +	case LINUX_SCM_CREDENTIALS:
 +		return (SCM_CREDS);
  	}
  	return (-1);
  }
 @@ -444,6 +446,8 @@ bsd_to_linux_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case SCM_RIGHTS:
  		return (LINUX_SCM_RIGHTS);
 +	case SCM_CREDS:
 +		return (LINUX_SCM_CREDENTIALS);
  	}
  	return (-1);
  }
 @@ -459,7 +463,16 @@ linux_to_bsd_msghdr(struct msghdr *bhdr,
  	bhdr->msg_iov		= PTRIN(lhdr->msg_iov);
  	bhdr->msg_iovlen	= lhdr->msg_iovlen;
  	bhdr->msg_control	= PTRIN(lhdr->msg_control);
 -	bhdr->msg_controllen	= lhdr->msg_controllen;
 +
 +	/*
 +	 * msg_controllen is skipped since BSD and LINUX control messages
 +	 * are potentially different sizes (e.g. the cred structure used
 +	 * by SCM_CREDS is different between the two operating system).
 +	 *
 +	 * The caller can set it (if necessary) after converting all the
 +	 * control messages.
 +	 */
 +
  	bhdr->msg_flags		= linux_to_bsd_msg_flags(lhdr->msg_flags);
  	return (0);
  }
 @@ -472,7 +485,16 @@ bsd_to_linux_msghdr(const struct msghdr 
  	lhdr->msg_iov		= PTROUT(bhdr->msg_iov);
  	lhdr->msg_iovlen	= bhdr->msg_iovlen;
  	lhdr->msg_control	= PTROUT(bhdr->msg_control);
 -	lhdr->msg_controllen	= bhdr->msg_controllen;
 +
 +	/*
 +	 * msg_controllen is skipped since BSD and LINUX control messages
 +	 * are potentially different sizes (e.g. the cred structure used
 +	 * by SCM_CREDS is different between the two operating system).
 +	 *
 +	 * The caller can set it (if necessary) after converting all the
 +	 * control messages.
 +	 */
 +
  	/* msg_flags skipped */
  	return (0);
  }
 @@ -1092,6 +1114,7 @@ static int
  linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
  {
  	struct cmsghdr *cmsg;
 +	struct cmsgcred cmcred;
  	struct mbuf *control;
  	struct msghdr msg;
  	struct l_cmsghdr linux_cmsg;
 @@ -1099,15 +1122,14 @@ linux_sendmsg(struct thread *td, struct 
  	struct l_msghdr linux_msg;
  	struct iovec *iov;
  	socklen_t datalen;
 +	struct sockaddr *sa;
 +	sa_family_t sa_family;
  	void *data;
  	int error;
  
  	error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
  	if (error)
  		return (error);
 -	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 -	if (error)
 -		return (error);
  
  	/*
  	 * Some Linux applications (ping) define a non-NULL control data
 @@ -1116,8 +1138,12 @@ linux_sendmsg(struct thread *td, struct 
  	 * order to handle this case.  This should be checked, but allows the
  	 * Linux ping to work.
  	 */
 -	if (msg.msg_control != NULL && msg.msg_controllen == 0)
 -		msg.msg_control = NULL;
 +	if (PTRIN(linux_msg.msg_control) != NULL && linux_msg.msg_controllen == 0)
 +		linux_msg.msg_control = PTROUT(NULL);
 +
 +	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 +	if (error)
 +		return (error);
  
  #ifdef COMPAT_LINUX32
  	error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
 @@ -1128,13 +1154,21 @@ linux_sendmsg(struct thread *td, struct 
  	if (error)
  		return (error);
  
 -	if (msg.msg_control != NULL) {
 +	control = NULL;
 +	cmsg = NULL;
 +
 +	if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
 +		error = kern_getsockname(td, args->s, &sa, &datalen);
 +		if (error)
 +			goto bad;
 +		sa_family = sa->sa_family;
 +		free(sa, M_SONAME);
 +
  		error = ENOBUFS;
  		cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
  		control = m_get(M_WAIT, MT_CONTROL);
  		if (control == NULL)
  			goto bad;
 -		ptr_cmsg = LINUX_CMSG_FIRSTHDR(&msg);
  
  		do {
  			error = copyin(ptr_cmsg, &linux_cmsg,
 @@ -1147,28 +1181,58 @@ linux_sendmsg(struct thread *td, struct 
  				goto bad;
  
  			/*
 -			 * Now we support only SCM_RIGHTS, so return EINVAL
 -			 * in any other cmsg_type
 +			 * Now we support only SCM_RIGHTS and SCM_CRED,
 +			 * so return EINVAL in any other cmsg_type
  			 */
 -			if ((cmsg->cmsg_type =
 -			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1)
 -				goto bad;
 +			cmsg->cmsg_type =
 +			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
  			cmsg->cmsg_level =
  			    linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
 +			if (cmsg->cmsg_type == -1
 +			    || cmsg->cmsg_level != SOL_SOCKET)
 +				goto bad;
  
 +			/*
 +			 * Some applications (e.g. pulseaudio) attempt to
 +			 * send ancillary data even if the underlying protocol
 +			 * doesn't support it which is not allowed in the
 +			 * FreeBSD system call interface.
 +			 */
 +			if (sa_family != AF_UNIX)
 +				continue;
 +
 +			data = LINUX_CMSG_DATA(ptr_cmsg);
  			datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
 +
 +			switch (cmsg->cmsg_type)
 +			{
 +			case SCM_RIGHTS:
 +				break;
 +
 +			case SCM_CREDS:
 +				data = &cmcred;
 +				datalen = sizeof(cmcred);
 +
 +				/*
 +				 * The lower levels will fill in the structure
 +				 */
 +				bzero(data, datalen);
 +				break;
 +			}
 +
  			cmsg->cmsg_len = CMSG_LEN(datalen);
 -			data = LINUX_CMSG_DATA(ptr_cmsg);
  
  			error = ENOBUFS;
  			if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg))
  				goto bad;
  			if (!m_append(control, datalen, (c_caddr_t) data))
  				goto bad;
 -		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg)));
 -	} else {
 -		control = NULL;
 -		cmsg = NULL;
 +		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
 +
 +		if (m_length(control, NULL) == 0) {
 +			m_freem(control);
 +			control = NULL;
 +		}
  	}
  
  	msg.msg_iov = iov;
 @@ -1193,9 +1257,11 @@ static int
  linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
  {
  	struct cmsghdr *cm;
 +	struct cmsgcred *cmcred;
  	struct msghdr msg;
  	struct l_cmsghdr *linux_cmsg = NULL;
 -	socklen_t datalen, outlen, clen;
 +	struct l_ucred linux_ucred;
 +	socklen_t datalen, outlen;
  	struct l_msghdr linux_msg;
  	struct iovec *iov, *uiov;
  	struct mbuf *control = NULL;
 @@ -1252,39 +1318,35 @@ linux_recvmsg(struct thread *td, struct 
  			goto bad;
  	}
  
 -	if (control) {
 +	outbuf = PTRIN(linux_msg.msg_control);
 +	outlen = 0;
  
 +	if (control) {
  		linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
 -		outbuf = PTRIN(linux_msg.msg_control);
 -		cm = mtod(control, struct cmsghdr *);
 -		outlen = 0;
 -		clen = control->m_len;
  
 -		while (cm != NULL) {
 +		msg.msg_control = mtod(control, struct cmsghdr *);
 +		msg.msg_controllen = control->m_len;
 +
 +		cm = CMSG_FIRSTHDR(&msg);
  
 -			if ((linux_cmsg->cmsg_type =
 -			    bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1)
 +		while (cm != NULL) {
 +			linux_cmsg->cmsg_type =
 +			    bsd_to_linux_cmsg_type(cm->cmsg_type);
 +			linux_cmsg->cmsg_level =
 +			    bsd_to_linux_sockopt_level(cm->cmsg_level);
 +			if (linux_cmsg->cmsg_type == -1
 +			    || cm->cmsg_level != SOL_SOCKET)
  			{
  				error = EINVAL;
  				goto bad;
  			}
 +
  			data = CMSG_DATA(cm);
  			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
  
 -			switch (linux_cmsg->cmsg_type)
 +			switch (cm->cmsg_type)
  			{
 -			case LINUX_SCM_RIGHTS:
 -				if (outlen + LINUX_CMSG_LEN(datalen) >
 -				    linux_msg.msg_controllen) {
 -					if (outlen == 0) {
 -						error = EMSGSIZE;
 -						goto bad;
 -					} else {
 -						linux_msg.msg_flags |=
 -						    LINUX_MSG_CTRUNC;
 -						goto out;
 -					}
 -				}
 +			case SCM_RIGHTS:
  				if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
  					fds = datalen / sizeof(int);
  					fdp = data;
 @@ -1295,11 +1357,40 @@ linux_recvmsg(struct thread *td, struct 
  					}
  				}
  				break;
 +
 +			case SCM_CREDS:
 +				/*
 +				 * Currently LOCAL_CREDS is never in
 +				 * effect for Linux so no need to worry
 +				 * about sockcred
 +				 */
 +				if (datalen != sizeof (*cmcred)) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				}
 +				cmcred = (struct cmsgcred *)data;
 +				bzero(&linux_ucred, sizeof(linux_ucred));
 +				linux_ucred.pid = cmcred->cmcred_pid;
 +				linux_ucred.uid = cmcred->cmcred_uid;
 +				linux_ucred.gid = cmcred->cmcred_gid;
 +				data = &linux_ucred;
 +				datalen = sizeof(linux_ucred);
 +				break;
 +			}
 +
 +			if (outlen + LINUX_CMSG_LEN(datalen) >
 +			    linux_msg.msg_controllen) {
 +				if (outlen == 0) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				} else {
 +					linux_msg.msg_flags |=
 +					    LINUX_MSG_CTRUNC;
 +					goto out;
 +				}
  			}
  
  			linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
 -			linux_cmsg->cmsg_level =
 -			    bsd_to_linux_sockopt_level(cm->cmsg_level);
  
  			error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
  			if (error)
 @@ -1312,18 +1403,13 @@ linux_recvmsg(struct thread *td, struct 
  
  			outbuf += LINUX_CMSG_ALIGN(datalen);
  			outlen += LINUX_CMSG_LEN(datalen);
 -			linux_msg.msg_controllen = outlen;
  
 -			if (CMSG_SPACE(datalen) < clen) {
 -				clen -= CMSG_SPACE(datalen);
 -				cm = (struct cmsghdr *)
 -				    ((caddr_t)cm + CMSG_SPACE(datalen));
 -			} else
 -				cm = NULL;
 +			cm = CMSG_NXTHDR(&msg, cm);
  		}
  	}
  
  out:
 +	linux_msg.msg_controllen = outlen;
  	error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
  
  bad:
 
 Modified: head/sys/compat/linux/linux_socket.h
 ==============================================================================
 --- head/sys/compat/linux/linux_socket.h	Sat Mar 26 10:59:24 2011	(r220030)
 +++ head/sys/compat/linux/linux_socket.h	Sat Mar 26 11:05:53 2011	(r220031)
 @@ -53,6 +53,7 @@
  /* Socket-level control message types */
  
  #define LINUX_SCM_RIGHTS	0x01
 +#define LINUX_SCM_CREDENTIALS   0x02
  
  /* Ancilliary data object information macros */
  
 @@ -66,13 +67,14 @@
  #define LINUX_CMSG_FIRSTHDR(msg) \
  				((msg)->msg_controllen >= \
  				    sizeof(struct l_cmsghdr) ? \
 -				    (struct l_cmsghdr *)((msg)->msg_control) : \
 +				    (struct l_cmsghdr *) \
 +				        PTRIN((msg)->msg_control) : \
  				    (struct l_cmsghdr *)(NULL))
  #define LINUX_CMSG_NXTHDR(msg, cmsg) \
  				((((char *)(cmsg) + \
  				    LINUX_CMSG_ALIGN((cmsg)->cmsg_len) + \
  				    sizeof(*(cmsg))) > \
 -				    (((char *)(msg)->msg_control) + \
 +				    (((char *)PTRIN((msg)->msg_control)) + \
  				    (msg)->msg_controllen)) ? \
  				    (struct l_cmsghdr *) NULL : \
  				    (struct l_cmsghdr *)((char *)(cmsg) + \
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: avg 
State-Changed-When: Sat Apr 2 08:11:02 UTC 2011 
State-Changed-Why:  
The patch is committed to head. 


Responsible-Changed-From-To: freebsd-emulation->avg 
Responsible-Changed-By: avg 
Responsible-Changed-When: Sat Apr 2 08:11:02 UTC 2011 
Responsible-Changed-Why:  
I am handling this PR. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=149168 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat,  9 Apr 2011 08:29:22 +0000 (UTC)

 Author: avg
 Date: Sat Apr  9 08:29:07 2011
 New Revision: 220466
 URL: http://svn.freebsd.org/changeset/base/220466
 
 Log:
   MFC r220028: linux compat: add non-dummy capget and capset system calls
   
   PR:		kern/149168
 
 Modified:
   stable/8/sys/amd64/linux32/syscalls.master
   stable/8/sys/i386/linux/syscalls.master
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
 
 Modified: stable/8/sys/amd64/linux32/syscalls.master
 ==============================================================================
 --- stable/8/sys/amd64/linux32/syscalls.master	Sat Apr  9 07:42:25 2011	(r220465)
 +++ stable/8/sys/amd64/linux32/syscalls.master	Sat Apr  9 08:29:07 2011	(r220466)
 @@ -326,8 +326,10 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 
 Modified: stable/8/sys/i386/linux/syscalls.master
 ==============================================================================
 --- stable/8/sys/i386/linux/syscalls.master	Sat Apr  9 07:42:25 2011	(r220465)
 +++ stable/8/sys/i386/linux/syscalls.master	Sat Apr  9 08:29:07 2011	(r220466)
 @@ -328,8 +328,10 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat,  9 Apr 2011 08:32:05 +0000 (UTC)

 Author: avg
 Date: Sat Apr  9 08:31:50 2011
 New Revision: 220467
 URL: http://svn.freebsd.org/changeset/base/220467
 
 Log:
   Regen for r220466
   
   PR:		kern/149168
 
 Modified:
   stable/8/sys/amd64/linux32/linux32_proto.h
   stable/8/sys/amd64/linux32/linux32_syscall.h
   stable/8/sys/amd64/linux32/linux32_sysent.c
   stable/8/sys/i386/linux/linux_proto.h
   stable/8/sys/i386/linux/linux_syscall.h
   stable/8/sys/i386/linux/linux_sysent.c
 
 Modified: stable/8/sys/amd64/linux32/linux32_proto.h
 ==============================================================================
 --- stable/8/sys/amd64/linux32/linux32_proto.h	Sat Apr  9 08:29:07 2011	(r220466)
 +++ stable/8/sys/amd64/linux32/linux32_proto.h	Sat Apr  9 08:31:50 2011	(r220467)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/8/sys/amd64/linux32/syscalls.master 219171 2011-03-02 06:23:19Z dchagin 
 + * created from FreeBSD: stable/8/sys/amd64/linux32/syscalls.master 220466 2011-04-09 08:29:07Z avg 
   */
  
  #ifndef _LINUX_SYSPROTO_H_
 @@ -589,10 +589,12 @@ struct linux_getcwd_args {
  	char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)];
  };
  struct linux_capget_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_capset_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_sigaltstack_args {
  	char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)];
 
 Modified: stable/8/sys/amd64/linux32/linux32_syscall.h
 ==============================================================================
 --- stable/8/sys/amd64/linux32/linux32_syscall.h	Sat Apr  9 08:29:07 2011	(r220466)
 +++ stable/8/sys/amd64/linux32/linux32_syscall.h	Sat Apr  9 08:31:50 2011	(r220467)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/8/sys/amd64/linux32/syscalls.master 219171 2011-03-02 06:23:19Z dchagin 
 + * created from FreeBSD: stable/8/sys/amd64/linux32/syscalls.master 220466 2011-04-09 08:29:07Z avg 
   */
  
  #define	LINUX_SYS_exit	1
 
 Modified: stable/8/sys/amd64/linux32/linux32_sysent.c
 ==============================================================================
 --- stable/8/sys/amd64/linux32/linux32_sysent.c	Sat Apr  9 08:29:07 2011	(r220466)
 +++ stable/8/sys/amd64/linux32/linux32_sysent.c	Sat Apr  9 08:31:50 2011	(r220467)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/8/sys/amd64/linux32/syscalls.master 219171 2011-03-02 06:23:19Z dchagin 
 + * created from FreeBSD: stable/8/sys/amd64/linux32/syscalls.master 220466 2011-04-09 08:29:07Z avg 
   */
  
  #include "opt_compat.h"
 @@ -203,8 +203,8 @@ struct sysent linux_sysent[] = {
  	{ AS(linux_pwrite_args), (sy_call_t *)linux_pwrite, AUE_PWRITE, NULL, 0, 0, 0 },	/* 181 = linux_pwrite */
  	{ AS(linux_chown16_args), (sy_call_t *)linux_chown16, AUE_CHOWN, NULL, 0, 0, 0 },	/* 182 = linux_chown16 */
  	{ AS(linux_getcwd_args), (sy_call_t *)linux_getcwd, AUE_GETCWD, NULL, 0, 0, 0 },	/* 183 = linux_getcwd */
 -	{ 0, (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0 },	/* 184 = linux_capget */
 -	{ 0, (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0 },	/* 185 = linux_capset */
 +	{ AS(linux_capget_args), (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0 },	/* 184 = linux_capget */
 +	{ AS(linux_capset_args), (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0 },	/* 185 = linux_capset */
  	{ AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL, NULL, 0, 0, 0 },	/* 186 = linux_sigaltstack */
  	{ 0, (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0, 0 },	/* 187 = linux_sendfile */
  	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0 },			/* 188 = getpmsg */
 
 Modified: stable/8/sys/i386/linux/linux_proto.h
 ==============================================================================
 --- stable/8/sys/i386/linux/linux_proto.h	Sat Apr  9 08:29:07 2011	(r220466)
 +++ stable/8/sys/i386/linux/linux_proto.h	Sat Apr  9 08:31:50 2011	(r220467)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/8/sys/i386/linux/syscalls.master 219171 2011-03-02 06:23:19Z dchagin 
 + * created from FreeBSD: stable/8/sys/i386/linux/syscalls.master 220466 2011-04-09 08:29:07Z avg 
   */
  
  #ifndef _LINUX_SYSPROTO_H_
 @@ -586,10 +586,12 @@ struct linux_getcwd_args {
  	char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)];
  };
  struct linux_capget_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_capset_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_sigaltstack_args {
  	char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)];
 
 Modified: stable/8/sys/i386/linux/linux_syscall.h
 ==============================================================================
 --- stable/8/sys/i386/linux/linux_syscall.h	Sat Apr  9 08:29:07 2011	(r220466)
 +++ stable/8/sys/i386/linux/linux_syscall.h	Sat Apr  9 08:31:50 2011	(r220467)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/8/sys/i386/linux/syscalls.master 219171 2011-03-02 06:23:19Z dchagin 
 + * created from FreeBSD: stable/8/sys/i386/linux/syscalls.master 220466 2011-04-09 08:29:07Z avg 
   */
  
  #define	LINUX_SYS_exit	1
 
 Modified: stable/8/sys/i386/linux/linux_sysent.c
 ==============================================================================
 --- stable/8/sys/i386/linux/linux_sysent.c	Sat Apr  9 08:29:07 2011	(r220466)
 +++ stable/8/sys/i386/linux/linux_sysent.c	Sat Apr  9 08:31:50 2011	(r220467)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/8/sys/i386/linux/syscalls.master 219171 2011-03-02 06:23:19Z dchagin 
 + * created from FreeBSD: stable/8/sys/i386/linux/syscalls.master 220466 2011-04-09 08:29:07Z avg 
   */
  
  #include <sys/param.h>
 @@ -202,8 +202,8 @@ struct sysent linux_sysent[] = {
  	{ AS(linux_pwrite_args), (sy_call_t *)linux_pwrite, AUE_PWRITE, NULL, 0, 0, 0 },	/* 181 = linux_pwrite */
  	{ AS(linux_chown16_args), (sy_call_t *)linux_chown16, AUE_CHOWN, NULL, 0, 0, 0 },	/* 182 = linux_chown16 */
  	{ AS(linux_getcwd_args), (sy_call_t *)linux_getcwd, AUE_GETCWD, NULL, 0, 0, 0 },	/* 183 = linux_getcwd */
 -	{ 0, (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0 },	/* 184 = linux_capget */
 -	{ 0, (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0 },	/* 185 = linux_capset */
 +	{ AS(linux_capget_args), (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0, 0 },	/* 184 = linux_capget */
 +	{ AS(linux_capset_args), (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0, 0 },	/* 185 = linux_capset */
  	{ AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL, NULL, 0, 0, 0 },	/* 186 = linux_sigaltstack */
  	{ 0, (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0, 0 },	/* 187 = linux_sendfile */
  	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0 },			/* 188 = getpmsg */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat,  9 Apr 2011 08:44:06 +0000 (UTC)

 Author: avg
 Date: Sat Apr  9 08:43:57 2011
 New Revision: 220468
 URL: http://svn.freebsd.org/changeset/base/220468
 
 Log:
   MFC r220030: drop dummy definitions
   
   PR:		kern/149168
 
 Modified:
   stable/8/sys/amd64/linux32/linux32_dummy.c
   stable/8/sys/i386/linux/linux_dummy.c
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
 
 Modified: stable/8/sys/amd64/linux32/linux32_dummy.c
 ==============================================================================
 --- stable/8/sys/amd64/linux32/linux32_dummy.c	Sat Apr  9 08:31:50 2011	(r220467)
 +++ stable/8/sys/amd64/linux32/linux32_dummy.c	Sat Apr  9 08:43:57 2011	(r220468)
 @@ -54,8 +54,6 @@ DUMMY(sysfs);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 
 Modified: stable/8/sys/i386/linux/linux_dummy.c
 ==============================================================================
 --- stable/8/sys/i386/linux/linux_dummy.c	Sat Apr  9 08:31:50 2011	(r220467)
 +++ stable/8/sys/i386/linux/linux_dummy.c	Sat Apr  9 08:43:57 2011	(r220468)
 @@ -57,8 +57,6 @@ DUMMY(vm86);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);		/* different semantics */
  DUMMY(setfsuid);
  DUMMY(setfsgid);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat,  9 Apr 2011 08:52:33 +0000 (UTC)

 Author: avg
 Date: Sat Apr  9 08:52:22 2011
 New Revision: 220469
 URL: http://svn.freebsd.org/changeset/base/220469
 
 Log:
   MFC r220031: linux compat: improve and fix sendmsg/recvmsg compatibility
   
   PR:		kern/149168
 
 Modified:
   stable/8/sys/compat/linux/linux_misc.c
   stable/8/sys/compat/linux/linux_misc.h
   stable/8/sys/compat/linux/linux_socket.c
   stable/8/sys/compat/linux/linux_socket.h
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
 
 Modified: stable/8/sys/compat/linux/linux_misc.c
 ==============================================================================
 --- stable/8/sys/compat/linux/linux_misc.c	Sat Apr  9 08:43:57 2011	(r220468)
 +++ stable/8/sys/compat/linux/linux_misc.c	Sat Apr  9 08:52:22 2011	(r220469)
 @@ -1679,6 +1679,100 @@ linux_exit_group(struct thread *td, stru
  	return (0);
  }
  
 +#define _LINUX_CAPABILITY_VERSION  0x19980330
 +
 +struct l_user_cap_header {
 +	l_int	version;
 +	l_int	pid;
 +};
 +
 +struct l_user_cap_data {
 +	l_int	effective;
 +	l_int	permitted;
 +	l_int	inheritable;
 +};
 +
 +int
 +linux_capget(struct thread *td, struct linux_capget_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (args->hdrp == NULL)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	if (args->datap) {
 +		/*
 +		 * The current implementation doesn't support setting
 +		 * a capability (it's essentially a stub) so indicate
 +		 * that no capabilities are currently set or available
 +		 * to request.
 +		 */
 +		bzero (&lucd, sizeof(lucd));
 +		error = copyout(&lucd, args->datap, sizeof(lucd));
 +	}
 +
 +	return (error);
 +}
 +
 +int
 +linux_capset(struct thread *td, struct linux_capset_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (args->hdrp == NULL || args->datap == NULL)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	error = copyin(args->datap, &lucd, sizeof(lucd));
 +	if (error != 0)
 +		return (error);
 +
 +	/* We currently don't support setting any capabilities. */
 +	if (lucd.effective || lucd.permitted || lucd.inheritable) {
 +		linux_msg(td,
 +			  "capset effective=0x%x, permitted=0x%x, "
 +			  "inheritable=0x%x is not implemented",
 +			  (int)lucd.effective, (int)lucd.permitted,
 +			  (int)lucd.inheritable);
 +		return (EPERM);
 +	}
 +
 +	return (0);
 +}
 +
  int
  linux_prctl(struct thread *td, struct linux_prctl_args *args)
  {
 @@ -1712,6 +1806,21 @@ linux_prctl(struct thread *td, struct li
  		    (void *)(register_t)args->arg2,
  		    sizeof(pdeath_signal));
  		break;
 +	case LINUX_PR_GET_KEEPCAPS:
 +		/*
 +		 * Indicate that we always clear the effective and
 +		 * permitted capability sets when the user id becomes
 +		 * non-zero (actually the capability sets are simply
 +		 * always zero in the current implementation).
 +		 */
 +		td->td_retval[0] = 0;
 +		break;
 +	case LINUX_PR_SET_KEEPCAPS:
 +		/*
 +		 * Ignore requests to keep the effective and permitted
 +		 * capability sets when the user id becomes non-zero.
 +		 */
 +		break;
  	case LINUX_PR_SET_NAME:
  		/*
  		 * To be on the safe side we need to make sure to not
 
 Modified: stable/8/sys/compat/linux/linux_misc.h
 ==============================================================================
 --- stable/8/sys/compat/linux/linux_misc.h	Sat Apr  9 08:43:57 2011	(r220468)
 +++ stable/8/sys/compat/linux/linux_misc.h	Sat Apr  9 08:52:22 2011	(r220469)
 @@ -37,6 +37,8 @@
  					 * Second arg is a ptr to return the
  					 * signal.
  					 */
 +#define	LINUX_PR_GET_KEEPCAPS	7	/* Get drop capabilities on setuid */
 +#define	LINUX_PR_SET_KEEPCAPS	8	/* Set drop capabilities on setuid */
  #define	LINUX_PR_SET_NAME	15	/* Set process name. */
  #define	LINUX_PR_GET_NAME	16	/* Get process name. */
  
 
 Modified: stable/8/sys/compat/linux/linux_socket.c
 ==============================================================================
 --- stable/8/sys/compat/linux/linux_socket.c	Sat Apr  9 08:43:57 2011	(r220468)
 +++ stable/8/sys/compat/linux/linux_socket.c	Sat Apr  9 08:52:22 2011	(r220469)
 @@ -433,6 +433,8 @@ linux_to_bsd_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case LINUX_SCM_RIGHTS:
  		return (SCM_RIGHTS);
 +	case LINUX_SCM_CREDENTIALS:
 +		return (SCM_CREDS);
  	}
  	return (-1);
  }
 @@ -444,6 +446,8 @@ bsd_to_linux_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case SCM_RIGHTS:
  		return (LINUX_SCM_RIGHTS);
 +	case SCM_CREDS:
 +		return (LINUX_SCM_CREDENTIALS);
  	}
  	return (-1);
  }
 @@ -459,7 +463,16 @@ linux_to_bsd_msghdr(struct msghdr *bhdr,
  	bhdr->msg_iov		= PTRIN(lhdr->msg_iov);
  	bhdr->msg_iovlen	= lhdr->msg_iovlen;
  	bhdr->msg_control	= PTRIN(lhdr->msg_control);
 -	bhdr->msg_controllen	= lhdr->msg_controllen;
 +
 +	/*
 +	 * msg_controllen is skipped since BSD and LINUX control messages
 +	 * are potentially different sizes (e.g. the cred structure used
 +	 * by SCM_CREDS is different between the two operating system).
 +	 *
 +	 * The caller can set it (if necessary) after converting all the
 +	 * control messages.
 +	 */
 +
  	bhdr->msg_flags		= linux_to_bsd_msg_flags(lhdr->msg_flags);
  	return (0);
  }
 @@ -472,7 +485,16 @@ bsd_to_linux_msghdr(const struct msghdr 
  	lhdr->msg_iov		= PTROUT(bhdr->msg_iov);
  	lhdr->msg_iovlen	= bhdr->msg_iovlen;
  	lhdr->msg_control	= PTROUT(bhdr->msg_control);
 -	lhdr->msg_controllen	= bhdr->msg_controllen;
 +
 +	/*
 +	 * msg_controllen is skipped since BSD and LINUX control messages
 +	 * are potentially different sizes (e.g. the cred structure used
 +	 * by SCM_CREDS is different between the two operating system).
 +	 *
 +	 * The caller can set it (if necessary) after converting all the
 +	 * control messages.
 +	 */
 +
  	/* msg_flags skipped */
  	return (0);
  }
 @@ -1092,6 +1114,7 @@ static int
  linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
  {
  	struct cmsghdr *cmsg;
 +	struct cmsgcred cmcred;
  	struct mbuf *control;
  	struct msghdr msg;
  	struct l_cmsghdr linux_cmsg;
 @@ -1099,15 +1122,14 @@ linux_sendmsg(struct thread *td, struct 
  	struct l_msghdr linux_msg;
  	struct iovec *iov;
  	socklen_t datalen;
 +	struct sockaddr *sa;
 +	sa_family_t sa_family;
  	void *data;
  	int error;
  
  	error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
  	if (error)
  		return (error);
 -	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 -	if (error)
 -		return (error);
  
  	/*
  	 * Some Linux applications (ping) define a non-NULL control data
 @@ -1116,8 +1138,12 @@ linux_sendmsg(struct thread *td, struct 
  	 * order to handle this case.  This should be checked, but allows the
  	 * Linux ping to work.
  	 */
 -	if (msg.msg_control != NULL && msg.msg_controllen == 0)
 -		msg.msg_control = NULL;
 +	if (PTRIN(linux_msg.msg_control) != NULL && linux_msg.msg_controllen == 0)
 +		linux_msg.msg_control = PTROUT(NULL);
 +
 +	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 +	if (error)
 +		return (error);
  
  #ifdef COMPAT_LINUX32
  	error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
 @@ -1128,13 +1154,21 @@ linux_sendmsg(struct thread *td, struct 
  	if (error)
  		return (error);
  
 -	if (msg.msg_control != NULL) {
 +	control = NULL;
 +	cmsg = NULL;
 +
 +	if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
 +		error = kern_getsockname(td, args->s, &sa, &datalen);
 +		if (error)
 +			goto bad;
 +		sa_family = sa->sa_family;
 +		free(sa, M_SONAME);
 +
  		error = ENOBUFS;
  		cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
  		control = m_get(M_WAIT, MT_CONTROL);
  		if (control == NULL)
  			goto bad;
 -		ptr_cmsg = LINUX_CMSG_FIRSTHDR(&msg);
  
  		do {
  			error = copyin(ptr_cmsg, &linux_cmsg,
 @@ -1147,28 +1181,58 @@ linux_sendmsg(struct thread *td, struct 
  				goto bad;
  
  			/*
 -			 * Now we support only SCM_RIGHTS, so return EINVAL
 -			 * in any other cmsg_type
 +			 * Now we support only SCM_RIGHTS and SCM_CRED,
 +			 * so return EINVAL in any other cmsg_type
  			 */
 -			if ((cmsg->cmsg_type =
 -			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1)
 -				goto bad;
 +			cmsg->cmsg_type =
 +			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
  			cmsg->cmsg_level =
  			    linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
 +			if (cmsg->cmsg_type == -1
 +			    || cmsg->cmsg_level != SOL_SOCKET)
 +				goto bad;
  
 +			/*
 +			 * Some applications (e.g. pulseaudio) attempt to
 +			 * send ancillary data even if the underlying protocol
 +			 * doesn't support it which is not allowed in the
 +			 * FreeBSD system call interface.
 +			 */
 +			if (sa_family != AF_UNIX)
 +				continue;
 +
 +			data = LINUX_CMSG_DATA(ptr_cmsg);
  			datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
 +
 +			switch (cmsg->cmsg_type)
 +			{
 +			case SCM_RIGHTS:
 +				break;
 +
 +			case SCM_CREDS:
 +				data = &cmcred;
 +				datalen = sizeof(cmcred);
 +
 +				/*
 +				 * The lower levels will fill in the structure
 +				 */
 +				bzero(data, datalen);
 +				break;
 +			}
 +
  			cmsg->cmsg_len = CMSG_LEN(datalen);
 -			data = LINUX_CMSG_DATA(ptr_cmsg);
  
  			error = ENOBUFS;
  			if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg))
  				goto bad;
  			if (!m_append(control, datalen, (c_caddr_t) data))
  				goto bad;
 -		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg)));
 -	} else {
 -		control = NULL;
 -		cmsg = NULL;
 +		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
 +
 +		if (m_length(control, NULL) == 0) {
 +			m_freem(control);
 +			control = NULL;
 +		}
  	}
  
  	msg.msg_iov = iov;
 @@ -1193,9 +1257,11 @@ static int
  linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
  {
  	struct cmsghdr *cm;
 +	struct cmsgcred *cmcred;
  	struct msghdr msg;
  	struct l_cmsghdr *linux_cmsg = NULL;
 -	socklen_t datalen, outlen, clen;
 +	struct l_ucred linux_ucred;
 +	socklen_t datalen, outlen;
  	struct l_msghdr linux_msg;
  	struct iovec *iov, *uiov;
  	struct mbuf *control = NULL;
 @@ -1252,39 +1318,35 @@ linux_recvmsg(struct thread *td, struct 
  			goto bad;
  	}
  
 -	if (control) {
 +	outbuf = PTRIN(linux_msg.msg_control);
 +	outlen = 0;
  
 +	if (control) {
  		linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
 -		outbuf = PTRIN(linux_msg.msg_control);
 -		cm = mtod(control, struct cmsghdr *);
 -		outlen = 0;
 -		clen = control->m_len;
  
 -		while (cm != NULL) {
 +		msg.msg_control = mtod(control, struct cmsghdr *);
 +		msg.msg_controllen = control->m_len;
 +
 +		cm = CMSG_FIRSTHDR(&msg);
  
 -			if ((linux_cmsg->cmsg_type =
 -			    bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1)
 +		while (cm != NULL) {
 +			linux_cmsg->cmsg_type =
 +			    bsd_to_linux_cmsg_type(cm->cmsg_type);
 +			linux_cmsg->cmsg_level =
 +			    bsd_to_linux_sockopt_level(cm->cmsg_level);
 +			if (linux_cmsg->cmsg_type == -1
 +			    || cm->cmsg_level != SOL_SOCKET)
  			{
  				error = EINVAL;
  				goto bad;
  			}
 +
  			data = CMSG_DATA(cm);
  			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
  
 -			switch (linux_cmsg->cmsg_type)
 +			switch (cm->cmsg_type)
  			{
 -			case LINUX_SCM_RIGHTS:
 -				if (outlen + LINUX_CMSG_LEN(datalen) >
 -				    linux_msg.msg_controllen) {
 -					if (outlen == 0) {
 -						error = EMSGSIZE;
 -						goto bad;
 -					} else {
 -						linux_msg.msg_flags |=
 -						    LINUX_MSG_CTRUNC;
 -						goto out;
 -					}
 -				}
 +			case SCM_RIGHTS:
  				if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
  					fds = datalen / sizeof(int);
  					fdp = data;
 @@ -1295,11 +1357,40 @@ linux_recvmsg(struct thread *td, struct 
  					}
  				}
  				break;
 +
 +			case SCM_CREDS:
 +				/*
 +				 * Currently LOCAL_CREDS is never in
 +				 * effect for Linux so no need to worry
 +				 * about sockcred
 +				 */
 +				if (datalen != sizeof (*cmcred)) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				}
 +				cmcred = (struct cmsgcred *)data;
 +				bzero(&linux_ucred, sizeof(linux_ucred));
 +				linux_ucred.pid = cmcred->cmcred_pid;
 +				linux_ucred.uid = cmcred->cmcred_uid;
 +				linux_ucred.gid = cmcred->cmcred_gid;
 +				data = &linux_ucred;
 +				datalen = sizeof(linux_ucred);
 +				break;
 +			}
 +
 +			if (outlen + LINUX_CMSG_LEN(datalen) >
 +			    linux_msg.msg_controllen) {
 +				if (outlen == 0) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				} else {
 +					linux_msg.msg_flags |=
 +					    LINUX_MSG_CTRUNC;
 +					goto out;
 +				}
  			}
  
  			linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
 -			linux_cmsg->cmsg_level =
 -			    bsd_to_linux_sockopt_level(cm->cmsg_level);
  
  			error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
  			if (error)
 @@ -1312,18 +1403,13 @@ linux_recvmsg(struct thread *td, struct 
  
  			outbuf += LINUX_CMSG_ALIGN(datalen);
  			outlen += LINUX_CMSG_LEN(datalen);
 -			linux_msg.msg_controllen = outlen;
  
 -			if (CMSG_SPACE(datalen) < clen) {
 -				clen -= CMSG_SPACE(datalen);
 -				cm = (struct cmsghdr *)
 -				    ((caddr_t)cm + CMSG_SPACE(datalen));
 -			} else
 -				cm = NULL;
 +			cm = CMSG_NXTHDR(&msg, cm);
  		}
  	}
  
  out:
 +	linux_msg.msg_controllen = outlen;
  	error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
  
  bad:
 
 Modified: stable/8/sys/compat/linux/linux_socket.h
 ==============================================================================
 --- stable/8/sys/compat/linux/linux_socket.h	Sat Apr  9 08:43:57 2011	(r220468)
 +++ stable/8/sys/compat/linux/linux_socket.h	Sat Apr  9 08:52:22 2011	(r220469)
 @@ -53,6 +53,7 @@
  /* Socket-level control message types */
  
  #define LINUX_SCM_RIGHTS	0x01
 +#define LINUX_SCM_CREDENTIALS   0x02
  
  /* Ancilliary data object information macros */
  
 @@ -66,13 +67,14 @@
  #define LINUX_CMSG_FIRSTHDR(msg) \
  				((msg)->msg_controllen >= \
  				    sizeof(struct l_cmsghdr) ? \
 -				    (struct l_cmsghdr *)((msg)->msg_control) : \
 +				    (struct l_cmsghdr *) \
 +				        PTRIN((msg)->msg_control) : \
  				    (struct l_cmsghdr *)(NULL))
  #define LINUX_CMSG_NXTHDR(msg, cmsg) \
  				((((char *)(cmsg) + \
  				    LINUX_CMSG_ALIGN((cmsg)->cmsg_len) + \
  				    sizeof(*(cmsg))) > \
 -				    (((char *)(msg)->msg_control) + \
 +				    (((char *)PTRIN((msg)->msg_control)) + \
  				    (msg)->msg_controllen)) ? \
  				    (struct l_cmsghdr *) NULL : \
  				    (struct l_cmsghdr *)((char *)(cmsg) + \
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat,  9 Apr 2011 09:13:26 +0000 (UTC)

 Author: avg
 Date: Sat Apr  9 09:12:44 2011
 New Revision: 220471
 URL: http://svn.freebsd.org/changeset/base/220471
 
 Log:
   MFC r220028: linux compat: add non-dummy capget and capset system calls
   
   PR:		kern/149168
 
 Modified:
   stable/7/sys/amd64/linux32/syscalls.master
   stable/7/sys/i386/linux/syscalls.master
 Directory Properties:
   stable/7/sys/   (props changed)
   stable/7/sys/cddl/contrib/opensolaris/   (props changed)
   stable/7/sys/contrib/dev/acpica/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
 
 Modified: stable/7/sys/amd64/linux32/syscalls.master
 ==============================================================================
 --- stable/7/sys/amd64/linux32/syscalls.master	Sat Apr  9 09:07:31 2011	(r220470)
 +++ stable/7/sys/amd64/linux32/syscalls.master	Sat Apr  9 09:12:44 2011	(r220471)
 @@ -327,8 +327,10 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 
 Modified: stable/7/sys/i386/linux/syscalls.master
 ==============================================================================
 --- stable/7/sys/i386/linux/syscalls.master	Sat Apr  9 09:07:31 2011	(r220470)
 +++ stable/7/sys/i386/linux/syscalls.master	Sat Apr  9 09:12:44 2011	(r220471)
 @@ -329,8 +329,10 @@
  				    l_uid16_t uid, l_gid16_t gid); }
  183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
  				    l_ulong bufsize); }
 -184	AUE_CAPGET	STD	{ int linux_capget(void); }
 -185	AUE_CAPSET	STD	{ int linux_capset(void); }
 +184	AUE_CAPGET	STD	{ int linux_capget(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
 +185	AUE_CAPSET	STD	{ int linux_capset(struct l_user_cap_header *hdrp, \
 +				    struct l_user_cap_data *datap); }
  186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
  				    l_stack_t *uoss); }
  187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat,  9 Apr 2011 09:20:21 +0000 (UTC)

 Author: avg
 Date: Sat Apr  9 09:20:11 2011
 New Revision: 220472
 URL: http://svn.freebsd.org/changeset/base/220472
 
 Log:
   Regen after r220471
   
   PR:		kern/149168
 
 Modified:
   stable/7/sys/amd64/linux32/linux32_proto.h
   stable/7/sys/amd64/linux32/linux32_syscall.h
   stable/7/sys/amd64/linux32/linux32_sysent.c
   stable/7/sys/i386/linux/linux_proto.h
   stable/7/sys/i386/linux/linux_syscall.h
   stable/7/sys/i386/linux/linux_sysent.c
 
 Modified: stable/7/sys/amd64/linux32/linux32_proto.h
 ==============================================================================
 --- stable/7/sys/amd64/linux32/linux32_proto.h	Sat Apr  9 09:12:44 2011	(r220471)
 +++ stable/7/sys/amd64/linux32/linux32_proto.h	Sat Apr  9 09:20:11 2011	(r220472)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/7/sys/amd64/linux32/syscalls.master 194400 2009-06-17 21:12:32Z dchagin 
 + * created from FreeBSD: stable/7/sys/amd64/linux32/syscalls.master 220471 2011-04-09 09:12:44Z avg 
   */
  
  #ifndef _LINUX_SYSPROTO_H_
 @@ -585,10 +585,12 @@ struct linux_getcwd_args {
  	char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)];
  };
  struct linux_capget_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_capset_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_sigaltstack_args {
  	char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)];
 
 Modified: stable/7/sys/amd64/linux32/linux32_syscall.h
 ==============================================================================
 --- stable/7/sys/amd64/linux32/linux32_syscall.h	Sat Apr  9 09:12:44 2011	(r220471)
 +++ stable/7/sys/amd64/linux32/linux32_syscall.h	Sat Apr  9 09:20:11 2011	(r220472)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/7/sys/amd64/linux32/syscalls.master 194400 2009-06-17 21:12:32Z dchagin 
 + * created from FreeBSD: stable/7/sys/amd64/linux32/syscalls.master 220471 2011-04-09 09:12:44Z avg 
   */
  
  #define	LINUX_SYS_exit	1
 
 Modified: stable/7/sys/amd64/linux32/linux32_sysent.c
 ==============================================================================
 --- stable/7/sys/amd64/linux32/linux32_sysent.c	Sat Apr  9 09:12:44 2011	(r220471)
 +++ stable/7/sys/amd64/linux32/linux32_sysent.c	Sat Apr  9 09:20:11 2011	(r220472)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/7/sys/amd64/linux32/syscalls.master 194400 2009-06-17 21:12:32Z dchagin 
 + * created from FreeBSD: stable/7/sys/amd64/linux32/syscalls.master 220471 2011-04-09 09:12:44Z avg 
   */
  
  #include "opt_compat.h"
 @@ -203,8 +203,8 @@ struct sysent linux_sysent[] = {
  	{ AS(linux_pwrite_args), (sy_call_t *)linux_pwrite, AUE_PWRITE, NULL, 0, 0 },	/* 181 = linux_pwrite */
  	{ AS(linux_chown16_args), (sy_call_t *)linux_chown16, AUE_CHOWN, NULL, 0, 0 },	/* 182 = linux_chown16 */
  	{ AS(linux_getcwd_args), (sy_call_t *)linux_getcwd, AUE_GETCWD, NULL, 0, 0 },	/* 183 = linux_getcwd */
 -	{ 0, (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0 },	/* 184 = linux_capget */
 -	{ 0, (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0 },	/* 185 = linux_capset */
 +	{ AS(linux_capget_args), (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0 },	/* 184 = linux_capget */
 +	{ AS(linux_capset_args), (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0 },	/* 185 = linux_capset */
  	{ AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL, NULL, 0, 0 },	/* 186 = linux_sigaltstack */
  	{ 0, (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0 },	/* 187 = linux_sendfile */
  	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 },			/* 188 = getpmsg */
 
 Modified: stable/7/sys/i386/linux/linux_proto.h
 ==============================================================================
 --- stable/7/sys/i386/linux/linux_proto.h	Sat Apr  9 09:12:44 2011	(r220471)
 +++ stable/7/sys/i386/linux/linux_proto.h	Sat Apr  9 09:20:11 2011	(r220472)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/7/sys/i386/linux/syscalls.master 191820 2009-05-05 14:53:58Z dchagin 
 + * created from FreeBSD: stable/7/sys/i386/linux/syscalls.master 220471 2011-04-09 09:12:44Z avg 
   */
  
  #ifndef _LINUX_SYSPROTO_H_
 @@ -582,10 +582,12 @@ struct linux_getcwd_args {
  	char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)];
  };
  struct linux_capget_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_capset_args {
 -	register_t dummy;
 +	char hdrp_l_[PADL_(struct l_user_cap_header *)]; struct l_user_cap_header * hdrp; char hdrp_r_[PADR_(struct l_user_cap_header *)];
 +	char datap_l_[PADL_(struct l_user_cap_data *)]; struct l_user_cap_data * datap; char datap_r_[PADR_(struct l_user_cap_data *)];
  };
  struct linux_sigaltstack_args {
  	char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)];
 
 Modified: stable/7/sys/i386/linux/linux_syscall.h
 ==============================================================================
 --- stable/7/sys/i386/linux/linux_syscall.h	Sat Apr  9 09:12:44 2011	(r220471)
 +++ stable/7/sys/i386/linux/linux_syscall.h	Sat Apr  9 09:20:11 2011	(r220472)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/7/sys/i386/linux/syscalls.master 191820 2009-05-05 14:53:58Z dchagin 
 + * created from FreeBSD: stable/7/sys/i386/linux/syscalls.master 220471 2011-04-09 09:12:44Z avg 
   */
  
  #define	LINUX_SYS_exit	1
 
 Modified: stable/7/sys/i386/linux/linux_sysent.c
 ==============================================================================
 --- stable/7/sys/i386/linux/linux_sysent.c	Sat Apr  9 09:12:44 2011	(r220471)
 +++ stable/7/sys/i386/linux/linux_sysent.c	Sat Apr  9 09:20:11 2011	(r220472)
 @@ -3,7 +3,7 @@
   *
   * DO NOT EDIT-- this file is automatically generated.
   * $FreeBSD$
 - * created from FreeBSD: stable/7/sys/i386/linux/syscalls.master 191820 2009-05-05 14:53:58Z dchagin 
 + * created from FreeBSD: stable/7/sys/i386/linux/syscalls.master 220471 2011-04-09 09:12:44Z avg 
   */
  
  #include <sys/param.h>
 @@ -202,8 +202,8 @@ struct sysent linux_sysent[] = {
  	{ AS(linux_pwrite_args), (sy_call_t *)linux_pwrite, AUE_PWRITE, NULL, 0, 0 },	/* 181 = linux_pwrite */
  	{ AS(linux_chown16_args), (sy_call_t *)linux_chown16, AUE_CHOWN, NULL, 0, 0 },	/* 182 = linux_chown16 */
  	{ AS(linux_getcwd_args), (sy_call_t *)linux_getcwd, AUE_GETCWD, NULL, 0, 0 },	/* 183 = linux_getcwd */
 -	{ 0, (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0 },	/* 184 = linux_capget */
 -	{ 0, (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0 },	/* 185 = linux_capset */
 +	{ AS(linux_capget_args), (sy_call_t *)linux_capget, AUE_CAPGET, NULL, 0, 0 },	/* 184 = linux_capget */
 +	{ AS(linux_capset_args), (sy_call_t *)linux_capset, AUE_CAPSET, NULL, 0, 0 },	/* 185 = linux_capset */
  	{ AS(linux_sigaltstack_args), (sy_call_t *)linux_sigaltstack, AUE_NULL, NULL, 0, 0 },	/* 186 = linux_sigaltstack */
  	{ 0, (sy_call_t *)linux_sendfile, AUE_SENDFILE, NULL, 0, 0 },	/* 187 = linux_sendfile */
  	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 },			/* 188 = getpmsg */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat,  9 Apr 2011 09:27:20 +0000 (UTC)

 Author: avg
 Date: Sat Apr  9 09:27:11 2011
 New Revision: 220473
 URL: http://svn.freebsd.org/changeset/base/220473
 
 Log:
   MFC r220030: drop dummy definitions
   
   PR:		kern/149168
 
 Modified:
   stable/7/sys/amd64/linux32/linux32_dummy.c
   stable/7/sys/i386/linux/linux_dummy.c
 Directory Properties:
   stable/7/sys/   (props changed)
   stable/7/sys/cddl/contrib/opensolaris/   (props changed)
   stable/7/sys/contrib/dev/acpica/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
 
 Modified: stable/7/sys/amd64/linux32/linux32_dummy.c
 ==============================================================================
 --- stable/7/sys/amd64/linux32/linux32_dummy.c	Sat Apr  9 09:20:11 2011	(r220472)
 +++ stable/7/sys/amd64/linux32/linux32_dummy.c	Sat Apr  9 09:27:11 2011	(r220473)
 @@ -54,8 +54,6 @@ DUMMY(sysfs);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);
  DUMMY(truncate64);
  DUMMY(setfsuid);
 
 Modified: stable/7/sys/i386/linux/linux_dummy.c
 ==============================================================================
 --- stable/7/sys/i386/linux/linux_dummy.c	Sat Apr  9 09:20:11 2011	(r220472)
 +++ stable/7/sys/i386/linux/linux_dummy.c	Sat Apr  9 09:27:11 2011	(r220473)
 @@ -57,8 +57,6 @@ DUMMY(vm86);
  DUMMY(query_module);
  DUMMY(nfsservctl);
  DUMMY(rt_sigqueueinfo);
 -DUMMY(capget);
 -DUMMY(capset);
  DUMMY(sendfile);		/* different semantics */
  DUMMY(truncate64);
  DUMMY(setfsuid);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: avg 
State-Changed-When: Sat Apr 9 09:33:56 UTC 2011 
State-Changed-Why:  
The code is in all supported branches now. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=149168 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/149168: commit references a PR
Date: Sat,  9 Apr 2011 09:33:56 +0000 (UTC)

 Author: avg
 Date: Sat Apr  9 09:33:36 2011
 New Revision: 220474
 URL: http://svn.freebsd.org/changeset/base/220474
 
 Log:
   MFC r220031: linux compat: improve and fix sendmsg/recvmsg compatibility
   
   PR:		kern/149168
 
 Modified:
   stable/7/sys/compat/linux/linux_misc.c
   stable/7/sys/compat/linux/linux_misc.h
   stable/7/sys/compat/linux/linux_socket.c
   stable/7/sys/compat/linux/linux_socket.h
 Directory Properties:
   stable/7/sys/   (props changed)
   stable/7/sys/cddl/contrib/opensolaris/   (props changed)
   stable/7/sys/contrib/dev/acpica/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
 
 Modified: stable/7/sys/compat/linux/linux_misc.c
 ==============================================================================
 --- stable/7/sys/compat/linux/linux_misc.c	Sat Apr  9 09:27:11 2011	(r220473)
 +++ stable/7/sys/compat/linux/linux_misc.c	Sat Apr  9 09:33:36 2011	(r220474)
 @@ -1633,6 +1633,100 @@ linux_exit_group(struct thread *td, stru
  	return (0);
  }
  
 +#define _LINUX_CAPABILITY_VERSION  0x19980330
 +
 +struct l_user_cap_header {
 +	l_int	version;
 +	l_int	pid;
 +};
 +
 +struct l_user_cap_data {
 +	l_int	effective;
 +	l_int	permitted;
 +	l_int	inheritable;
 +};
 +
 +int
 +linux_capget(struct thread *td, struct linux_capget_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (args->hdrp == NULL)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	if (args->datap) {
 +		/*
 +		 * The current implementation doesn't support setting
 +		 * a capability (it's essentially a stub) so indicate
 +		 * that no capabilities are currently set or available
 +		 * to request.
 +		 */
 +		bzero (&lucd, sizeof(lucd));
 +		error = copyout(&lucd, args->datap, sizeof(lucd));
 +	}
 +
 +	return (error);
 +}
 +
 +int
 +linux_capset(struct thread *td, struct linux_capset_args *args)
 +{
 +	struct l_user_cap_header luch;
 +	struct l_user_cap_data lucd;
 +	int error;
 +
 +	if (args->hdrp == NULL || args->datap == NULL)
 +		return (EFAULT);
 +
 +	error = copyin(args->hdrp, &luch, sizeof(luch));
 +	if (error != 0)
 +		return (error);
 +
 +	if (luch.version != _LINUX_CAPABILITY_VERSION) {
 +		luch.version = _LINUX_CAPABILITY_VERSION;
 +		error = copyout(&luch, args->hdrp, sizeof(luch));
 +		if (error)
 +			return (error);
 +		return (EINVAL);
 +	}
 +
 +	if (luch.pid)
 +		return (EPERM);
 +
 +	error = copyin(args->datap, &lucd, sizeof(lucd));
 +	if (error != 0)
 +		return (error);
 +
 +	/* We currently don't support setting any capabilities. */
 +	if (lucd.effective || lucd.permitted || lucd.inheritable) {
 +		linux_msg(td,
 +			  "capset effective=0x%x, permitted=0x%x, "
 +			  "inheritable=0x%x is not implemented",
 +			  (int)lucd.effective, (int)lucd.permitted,
 +			  (int)lucd.inheritable);
 +		return (EPERM);
 +	}
 +
 +	return (0);
 +}
 +
  int
  linux_prctl(struct thread *td, struct linux_prctl_args *args)
  {
 @@ -1666,6 +1760,21 @@ linux_prctl(struct thread *td, struct li
  		    (void *)(register_t)args->arg2,
  		    sizeof(pdeath_signal));
  		break;
 +	case LINUX_PR_GET_KEEPCAPS:
 +		/*
 +		 * Indicate that we always clear the effective and
 +		 * permitted capability sets when the user id becomes
 +		 * non-zero (actually the capability sets are simply
 +		 * always zero in the current implementation).
 +		 */
 +		td->td_retval[0] = 0;
 +		break;
 +	case LINUX_PR_SET_KEEPCAPS:
 +		/*
 +		 * Ignore requests to keep the effective and permitted
 +		 * capability sets when the user id becomes non-zero.
 +		 */
 +		break;
  	case LINUX_PR_SET_NAME:
  		/*
  		 * To be on the safe side we need to make sure to not
 
 Modified: stable/7/sys/compat/linux/linux_misc.h
 ==============================================================================
 --- stable/7/sys/compat/linux/linux_misc.h	Sat Apr  9 09:27:11 2011	(r220473)
 +++ stable/7/sys/compat/linux/linux_misc.h	Sat Apr  9 09:33:36 2011	(r220474)
 @@ -37,6 +37,8 @@
  					 * Second arg is a ptr to return the
  					 * signal.
  					 */
 +#define	LINUX_PR_GET_KEEPCAPS	7	/* Get drop capabilities on setuid */
 +#define	LINUX_PR_SET_KEEPCAPS	8	/* Set drop capabilities on setuid */
  #define	LINUX_PR_SET_NAME	15	/* Set process name. */
  #define	LINUX_PR_GET_NAME	16	/* Get process name. */
  
 
 Modified: stable/7/sys/compat/linux/linux_socket.c
 ==============================================================================
 --- stable/7/sys/compat/linux/linux_socket.c	Sat Apr  9 09:27:11 2011	(r220473)
 +++ stable/7/sys/compat/linux/linux_socket.c	Sat Apr  9 09:33:36 2011	(r220474)
 @@ -431,6 +431,8 @@ linux_to_bsd_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case LINUX_SCM_RIGHTS:
  		return (SCM_RIGHTS);
 +	case LINUX_SCM_CREDENTIALS:
 +		return (SCM_CREDS);
  	}
  	return (-1);
  }
 @@ -442,6 +444,8 @@ bsd_to_linux_cmsg_type(int cmsg_type)
  	switch (cmsg_type) {
  	case SCM_RIGHTS:
  		return (LINUX_SCM_RIGHTS);
 +	case SCM_CREDS:
 +		return (LINUX_SCM_CREDENTIALS);
  	}
  	return (-1);
  }
 @@ -459,7 +463,16 @@ linux_to_bsd_msghdr(struct msghdr *bhdr,
  	bhdr->msg_iov		= PTRIN(lhdr->msg_iov);
  	bhdr->msg_iovlen	= lhdr->msg_iovlen;
  	bhdr->msg_control	= PTRIN(lhdr->msg_control);
 -	bhdr->msg_controllen	= lhdr->msg_controllen;
 +
 +	/*
 +	 * msg_controllen is skipped since BSD and LINUX control messages
 +	 * are potentially different sizes (e.g. the cred structure used
 +	 * by SCM_CREDS is different between the two operating system).
 +	 *
 +	 * The caller can set it (if necessary) after converting all the
 +	 * control messages.
 +	 */
 +
  	bhdr->msg_flags		= linux_to_bsd_msg_flags(lhdr->msg_flags);
  	return (0);
  }
 @@ -472,7 +485,16 @@ bsd_to_linux_msghdr(const struct msghdr 
  	lhdr->msg_iov		= PTROUT(bhdr->msg_iov);
  	lhdr->msg_iovlen	= bhdr->msg_iovlen;
  	lhdr->msg_control	= PTROUT(bhdr->msg_control);
 -	lhdr->msg_controllen	= bhdr->msg_controllen;
 +
 +	/*
 +	 * msg_controllen is skipped since BSD and LINUX control messages
 +	 * are potentially different sizes (e.g. the cred structure used
 +	 * by SCM_CREDS is different between the two operating system).
 +	 *
 +	 * The caller can set it (if necessary) after converting all the
 +	 * control messages.
 +	 */
 +
  	/* msg_flags skipped */
  	return (0);
  }
 @@ -1034,6 +1056,7 @@ static int
  linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
  {
  	struct cmsghdr *cmsg;
 +	struct cmsgcred cmcred;
  	struct mbuf *control;
  	struct msghdr msg;
  	struct l_cmsghdr linux_cmsg;
 @@ -1041,15 +1064,14 @@ linux_sendmsg(struct thread *td, struct 
  	struct l_msghdr linux_msg;
  	struct iovec *iov;
  	socklen_t datalen;
 +	struct sockaddr *sa;
 +	sa_family_t sa_family;
  	void *data;
  	int error;
  
  	error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
  	if (error)
  		return (error);
 -	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 -	if (error)
 -		return (error);
  
  	/*
  	 * Some Linux applications (ping) define a non-NULL control data
 @@ -1058,8 +1080,12 @@ linux_sendmsg(struct thread *td, struct 
  	 * order to handle this case.  This should be checked, but allows the
  	 * Linux ping to work.
  	 */
 -	if (msg.msg_control != NULL && msg.msg_controllen == 0)
 -		msg.msg_control = NULL;
 +	if (PTRIN(linux_msg.msg_control) != NULL && linux_msg.msg_controllen == 0)
 +		linux_msg.msg_control = PTROUT(NULL);
 +
 +	error = linux_to_bsd_msghdr(&msg, &linux_msg);
 +	if (error)
 +		return (error);
  
  #ifdef COMPAT_LINUX32
  	error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
 @@ -1070,13 +1096,21 @@ linux_sendmsg(struct thread *td, struct 
  	if (error)
  		return (error);
  
 -	if (msg.msg_control != NULL) {
 +	control = NULL;
 +	cmsg = NULL;
 +
 +	if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
 +		error = kern_getsockname(td, args->s, &sa, &datalen);
 +		if (error)
 +			goto bad;
 +		sa_family = sa->sa_family;
 +		free(sa, M_SONAME);
 +
  		error = ENOBUFS;
  		cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
  		control = m_get(M_WAIT, MT_CONTROL);
  		if (control == NULL)
  			goto bad;
 -		ptr_cmsg = LINUX_CMSG_FIRSTHDR(&msg);
  
  		do {
  			error = copyin(ptr_cmsg, &linux_cmsg,
 @@ -1089,28 +1123,58 @@ linux_sendmsg(struct thread *td, struct 
  				goto bad;
  
  			/*
 -			 * Now we support only SCM_RIGHTS, so return EINVAL
 -			 * in any other cmsg_type
 +			 * Now we support only SCM_RIGHTS and SCM_CRED,
 +			 * so return EINVAL in any other cmsg_type
  			 */
 -			if ((cmsg->cmsg_type =
 -			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1)
 -				goto bad;
 +			cmsg->cmsg_type =
 +			    linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
  			cmsg->cmsg_level =
  			    linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
 +			if (cmsg->cmsg_type == -1
 +			    || cmsg->cmsg_level != SOL_SOCKET)
 +				goto bad;
  
 +			/*
 +			 * Some applications (e.g. pulseaudio) attempt to
 +			 * send ancillary data even if the underlying protocol
 +			 * doesn't support it which is not allowed in the
 +			 * FreeBSD system call interface.
 +			 */
 +			if (sa_family != AF_UNIX)
 +				continue;
 +
 +			data = LINUX_CMSG_DATA(ptr_cmsg);
  			datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
 +
 +			switch (cmsg->cmsg_type)
 +			{
 +			case SCM_RIGHTS:
 +				break;
 +
 +			case SCM_CREDS:
 +				data = &cmcred;
 +				datalen = sizeof(cmcred);
 +
 +				/*
 +				 * The lower levels will fill in the structure
 +				 */
 +				bzero(data, datalen);
 +				break;
 +			}
 +
  			cmsg->cmsg_len = CMSG_LEN(datalen);
 -			data = LINUX_CMSG_DATA(ptr_cmsg);
  
  			error = ENOBUFS;
  			if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg))
  				goto bad;
  			if (!m_append(control, datalen, (c_caddr_t) data))
  				goto bad;
 -		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg)));
 -	} else {
 -		control = NULL;
 -		cmsg = NULL;
 +		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
 +
 +		if (m_length(control, NULL) == 0) {
 +			m_freem(control);
 +			control = NULL;
 +		}
  	}
  
  	msg.msg_iov = iov;
 @@ -1135,9 +1199,11 @@ static int
  linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
  {
  	struct cmsghdr *cm;
 +	struct cmsgcred *cmcred;
  	struct msghdr msg;
  	struct l_cmsghdr *linux_cmsg = NULL;
 -	socklen_t datalen, outlen, clen;
 +	struct l_ucred linux_ucred;
 +	socklen_t datalen, outlen;
  	struct l_msghdr linux_msg;
  	struct iovec *iov, *uiov;
  	struct mbuf *control = NULL;
 @@ -1194,39 +1260,35 @@ linux_recvmsg(struct thread *td, struct 
  			goto bad;
  	}
  
 -	if (control) {
 +	outbuf = PTRIN(linux_msg.msg_control);
 +	outlen = 0;
  
 +	if (control) {
  		linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
 -		outbuf = PTRIN(linux_msg.msg_control);
 -		cm = mtod(control, struct cmsghdr *);
 -		outlen = 0;
 -		clen = control->m_len;
  
 -		while (cm != NULL) {
 +		msg.msg_control = mtod(control, struct cmsghdr *);
 +		msg.msg_controllen = control->m_len;
 +
 +		cm = CMSG_FIRSTHDR(&msg);
  
 -			if ((linux_cmsg->cmsg_type =
 -			    bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1)
 +		while (cm != NULL) {
 +			linux_cmsg->cmsg_type =
 +			    bsd_to_linux_cmsg_type(cm->cmsg_type);
 +			linux_cmsg->cmsg_level =
 +			    bsd_to_linux_sockopt_level(cm->cmsg_level);
 +			if (linux_cmsg->cmsg_type == -1
 +			    || cm->cmsg_level != SOL_SOCKET)
  			{
  				error = EINVAL;
  				goto bad;
  			}
 +
  			data = CMSG_DATA(cm);
  			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
  
 -			switch (linux_cmsg->cmsg_type)
 +			switch (cm->cmsg_type)
  			{
 -			case LINUX_SCM_RIGHTS:
 -				if (outlen + LINUX_CMSG_LEN(datalen) >
 -				    linux_msg.msg_controllen) {
 -					if (outlen == 0) {
 -						error = EMSGSIZE;
 -						goto bad;
 -					} else {
 -						linux_msg.msg_flags |=
 -						    LINUX_MSG_CTRUNC;
 -						goto out;
 -					}
 -				}
 +			case SCM_RIGHTS:
  				if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
  					fds = datalen / sizeof(int);
  					fdp = data;
 @@ -1237,11 +1299,40 @@ linux_recvmsg(struct thread *td, struct 
  					}
  				}
  				break;
 +
 +			case SCM_CREDS:
 +				/*
 +				 * Currently LOCAL_CREDS is never in
 +				 * effect for Linux so no need to worry
 +				 * about sockcred
 +				 */
 +				if (datalen != sizeof (*cmcred)) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				}
 +				cmcred = (struct cmsgcred *)data;
 +				bzero(&linux_ucred, sizeof(linux_ucred));
 +				linux_ucred.pid = cmcred->cmcred_pid;
 +				linux_ucred.uid = cmcred->cmcred_uid;
 +				linux_ucred.gid = cmcred->cmcred_gid;
 +				data = &linux_ucred;
 +				datalen = sizeof(linux_ucred);
 +				break;
 +			}
 +
 +			if (outlen + LINUX_CMSG_LEN(datalen) >
 +			    linux_msg.msg_controllen) {
 +				if (outlen == 0) {
 +					error = EMSGSIZE;
 +					goto bad;
 +				} else {
 +					linux_msg.msg_flags |=
 +					    LINUX_MSG_CTRUNC;
 +					goto out;
 +				}
  			}
  
  			linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
 -			linux_cmsg->cmsg_level =
 -			    bsd_to_linux_sockopt_level(cm->cmsg_level);
  
  			error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
  			if (error)
 @@ -1254,18 +1345,13 @@ linux_recvmsg(struct thread *td, struct 
  
  			outbuf += LINUX_CMSG_ALIGN(datalen);
  			outlen += LINUX_CMSG_LEN(datalen);
 -			linux_msg.msg_controllen = outlen;
  
 -			if (CMSG_SPACE(datalen) < clen) {
 -				clen -= CMSG_SPACE(datalen);
 -				cm = (struct cmsghdr *)
 -				    ((caddr_t)cm + CMSG_SPACE(datalen));
 -			} else
 -				cm = NULL;
 +			cm = CMSG_NXTHDR(&msg, cm);
  		}
  	}
  
  out:
 +	linux_msg.msg_controllen = outlen;
  	error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
  
  bad:
 
 Modified: stable/7/sys/compat/linux/linux_socket.h
 ==============================================================================
 --- stable/7/sys/compat/linux/linux_socket.h	Sat Apr  9 09:27:11 2011	(r220473)
 +++ stable/7/sys/compat/linux/linux_socket.h	Sat Apr  9 09:33:36 2011	(r220474)
 @@ -53,6 +53,7 @@
  /* Socket-level control message types */
  
  #define LINUX_SCM_RIGHTS	0x01
 +#define LINUX_SCM_CREDENTIALS   0x02
  
  /* Ancilliary data object information macros */
  
 @@ -66,13 +67,14 @@
  #define LINUX_CMSG_FIRSTHDR(msg) \
  				((msg)->msg_controllen >= \
  				    sizeof(struct l_cmsghdr) ? \
 -				    (struct l_cmsghdr *)((msg)->msg_control) : \
 +				    (struct l_cmsghdr *) \
 +				        PTRIN((msg)->msg_control) : \
  				    (struct l_cmsghdr *)(NULL))
  #define LINUX_CMSG_NXTHDR(msg, cmsg) \
  				((((char *)(cmsg) + \
  				    LINUX_CMSG_ALIGN((cmsg)->cmsg_len) + \
  				    sizeof(*(cmsg))) > \
 -				    (((char *)(msg)->msg_control) + \
 +				    (((char *)PTRIN((msg)->msg_control)) + \
  				    (msg)->msg_controllen)) ? \
  				    (struct l_cmsghdr *) NULL : \
  				    (struct l_cmsghdr *)((char *)(cmsg) + \
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
