NetBSD Problem Report #39108

From mmondor@pulsar-zone.net  Sat Jul  5 20:49:51 2008
Return-Path: <mmondor@pulsar-zone.net>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by narn.NetBSD.org (Postfix) with ESMTP id 966E063B880
	for <gnats-bugs@gnats.NetBSD.org>; Sat,  5 Jul 2008 20:49:51 +0000 (UTC)
Message-Id: <200807052049.m65KnmuO012422@ginseng.xisop>
Date: Sat, 5 Jul 2008 16:49:48 -0400 (EDT)
From: mmondor@pulsar-zone.net
Reply-To: mmondor@pulsar-zone.net
To: gnats-bugs@gnats.NetBSD.org
Subject: Proposal for unix(4) LOCAL_PROC/SCM_PROC
X-Send-Pr-Version: 3.95

>Number:         39108
>Category:       kern
>Synopsis:       Proposal for unix(4) LOCAL_PROC/SCM_PROC
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Jul 05 20:50:00 +0000 2008
>Last-Modified:  Mon Nov 03 03:05:01 +0000 2008
>Originator:     Matthew Mondor
>Release:        NetBSD 4.99.67
>Organization:
Pulsar-Zone
>Environment:
>Description:
	SCM_CREDS allow to obtain sending user credentials, but no
	information about which process sent the packet.

	SCM_PEEREID provides a pid_t and is otherwise redundant
	with SCM_CREDS since it also provides user credentials,
	but it only works with SOCK_STREAM at connect(2)/bind(2)
	time and requires an extra getsockopt(2) syscall to query
	the information.

	This proposes SCM_PROC which can be used along SCM_CREDS
	for both SOCK_STREAM and SOCK_DGRAM without an extra
	syscall per packet.  This structure provides the process
	PID as well as its PGID.  This will be useful to enhance
	security of systems such as syslogd(8).
>How-To-Repeat:
>Fix:

Unified diff against -current /usr/src


Index: sys/sys/socket.h
===================================================================
RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/sys/socket.h,v
retrieving revision 1.90
diff -u -r1.90 socket.h
--- sys/sys/socket.h	15 Jun 2008 21:14:06 -0000	1.90
+++ sys/sys/socket.h	5 Jul 2008 08:45:12 -0000
@@ -325,6 +325,22 @@
 	(sizeof(struct sockcred) + (sizeof(gid_t) * ((ngrps) - 1)))
 #endif /* _NETBSD_SOURCE */

+#if defined(_NETBSD_SOURCE)
+
+#ifndef pid_t
+typedef __pid_t		pid_t;		/* process id */
+#define pid_t		__pid_t
+#endif
+
+/*
+ * Like sockcred but to obtain PID/PGID
+ */
+struct sockproc {
+	pid_t	sp_pid;			/* process id */
+	pid_t	sp_pgid;		/* process group id */
+};
+
+#endif /* _NETBSD_SOURCE */

 #if defined(_NETBSD_SOURCE)
 /*
@@ -536,6 +552,7 @@
 #if defined(_NETBSD_SOURCE)
 #define	SCM_TIMESTAMP	0x02		/* timestamp (struct timeval) */
 #define	SCM_CREDS	0x04		/* credentials (struct sockcred) */
+#define SCM_PROC	0x08		/* PID/PGID (struct sockproc) */
 #endif

 /*
Index: sys/sys/un.h
===================================================================
RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/sys/un.h,v
retrieving revision 1.43
diff -u -r1.43 un.h
--- sys/sys/un.h	24 Apr 2008 11:38:39 -0000	1.43
+++ sys/sys/un.h	5 Jul 2008 09:00:21 -0000
@@ -59,6 +59,7 @@
 #define	LOCAL_CREDS	0x0001		/* pass credentials to receiver */
 #define	LOCAL_CONNWAIT	0x0002		/* connects block until accepted */
 #define	LOCAL_PEEREID	0x0003		/* get peer identification */
+#define LOCAL_PROC	0x0004		/* pass PID/PGID to receiver */
 #endif

 /*
Index: sys/kern/uipc_usrreq.c
===================================================================
RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.117
diff -u -r1.117 uipc_usrreq.c
--- sys/kern/uipc_usrreq.c	20 Jun 2008 15:27:50 -0000	1.117
+++ sys/kern/uipc_usrreq.c	5 Jul 2008 20:06:51 -0000
@@ -167,7 +167,10 @@
 };
 ino_t	unp_ino;			/* prototype for fake inode numbers */

+inline struct mbuf *unp_addsockalloc(struct mbuf *, int, int);
+inline struct mbuf *unp_addsockappend(struct mbuf *, struct mbuf *);
 struct mbuf *unp_addsockcred(struct lwp *, struct mbuf *);
+struct mbuf *unp_addsockproc(struct lwp *, struct mbuf *);
 static kmutex_t *uipc_lock;

 /*
@@ -286,6 +289,8 @@
 		sun = &sun_noname;
 	if (unp->unp_conn->unp_flags & UNP_WANTCRED)
 		control = unp_addsockcred(l, control);
+	if (unp->unp_conn->unp_flags & UNP_WANTPROC)
+		control = unp_addsockproc(l, control);
 	if (sbappendaddr(&so2->so_rcv, (const struct sockaddr *)sun, m,
 	    control) == 0) {
 		so2->so_rcv.sb_overflowed++;
@@ -481,7 +486,7 @@
 		 * Note: unp_internalize() rejects any control message
 		 * other than SCM_RIGHTS, and only allows one.  This
 		 * has the side-effect of preventing a caller from
-		 * forging SCM_CREDS.
+		 * forging SCM_CREDS or SCM_PROC.
 		 */
 		if (control) {
 			sounlock(so);
@@ -548,6 +553,14 @@
 				unp->unp_conn->unp_flags &= ~UNP_WANTCRED;
 				control = unp_addsockcred(l, control);
 			}
+			if (unp->unp_conn->unp_flags & UNP_WANTPROC) {
+				/*
+				 * PID/PGID are passed only once on
+				 * SOCK_STREAM.
+				 */
+				unp->unp_conn->unp_flags &= ~UNP_WANTPROC;
+				control = unp_addsockproc(l, control);
+			}
 			/*
 			 * Send to paired receive port, and then reduce
 			 * send buffer hiwater marks to maintain backpressure.
@@ -657,6 +670,7 @@
 	case PRCO_SETOPT:
 		switch (optname) {
 		case LOCAL_CREDS:
+		case LOCAL_PROC:
 		case LOCAL_CONNWAIT:
 			if (m == NULL || m->m_len != sizeof(int))
 				error = EINVAL;
@@ -672,6 +686,9 @@
 				case LOCAL_CREDS:
 					OPTSET(UNP_WANTCRED);
 					break;
+				case LOCAL_PROC:
+					OPTSET(UNP_WANTPROC);
+					break;
 				case LOCAL_CONNWAIT:
 					OPTSET(UNP_CONNWAIT);
 					break;
@@ -688,6 +705,7 @@
 			(void) m_free(m);
 		break;

+#define	OPTBIT(bit)	(unp->unp_flags & (bit) ? 1 : 0)
 	case PRCO_GETOPT:
 		sounlock(so);
 		switch (optname) {
@@ -703,12 +721,15 @@
 		case LOCAL_CREDS:
 			*mp = m = m_get(M_WAIT, MT_SOOPTS);
 			m->m_len = sizeof(int);
-
-#define	OPTBIT(bit)	(unp->unp_flags & (bit) ? 1 : 0)
-
 			optval = OPTBIT(UNP_WANTCRED);
 			*mtod(m, int *) = optval;
 			break;
+		case LOCAL_PROC:
+			*mp = m = m_get(M_WAIT, MT_SOOPTS);
+			m->m_len = sizeof(int);
+			optval = OPTBIT(UNP_WANTPROC);
+			*mtod(m, int *) = optval;
+			break;
 #undef OPTBIT

 		default:
@@ -1364,16 +1385,10 @@
 	return error;
 }

-struct mbuf *
-unp_addsockcred(struct lwp *l, struct mbuf *control)
+inline struct mbuf *
+unp_addsockalloc(struct mbuf *control, int len, int space)
 {
-	struct cmsghdr *cmp;
-	struct sockcred *sc;
-	struct mbuf *m, *n;
-	int len, space, i;
-
-	len = CMSG_LEN(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
-	space = CMSG_SPACE(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
+	struct mbuf *m;

 	m = m_get(M_WAIT, MT_CONTROL);
 	if (space > MLEN) {
@@ -1387,6 +1402,36 @@
 		}
 	}

+	return m;
+}
+
+inline struct mbuf *
+unp_addsockappend(struct mbuf *control, struct mbuf *m)
+{
+	struct mbuf *n;
+
+	if (control != NULL) {
+		for (n = control; n->m_next != NULL; n = n->m_next) ;
+		n->m_next = m;
+		return control;
+	}
+
+	return m;
+}
+
+struct mbuf *
+unp_addsockcred(struct lwp *l, struct mbuf *control)
+{
+	struct cmsghdr *cmp;
+	struct sockcred *sc;
+	struct mbuf *m;
+	int len, space, i;
+
+	len = CMSG_LEN(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
+	space = CMSG_SPACE(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
+
+	m = unp_addsockalloc(control, len, space);
+
 	m->m_len = space;
 	m->m_next = NULL;
 	cmp = mtod(m, struct cmsghdr *);
@@ -1402,17 +1447,33 @@
 	for (i = 0; i < sc->sc_ngroups; i++)
 		sc->sc_groups[i] = kauth_cred_group(l->l_cred, i);

-	/*
-	 * If a control message already exists, append us to the end.
-	 */
-	if (control != NULL) {
-		for (n = control; n->m_next != NULL; n = n->m_next)
-			;
-		n->m_next = m;
-	} else
-		control = m;
+	return unp_addsockappend(m, control);
+}
+
+struct mbuf *
+unp_addsockproc(struct lwp *l, struct mbuf *control)
+{
+	struct cmsghdr *cmp;
+	struct sockproc *sp;
+	struct mbuf *m;
+	int len, space;
+
+	len = CMSG_LEN(sizeof(struct sockproc));
+	space = CMSG_SPACE(sizeof(struct sockproc));
+
+	m = unp_addsockalloc(control, len, space);
+
+	m->m_len = space;
+	m->m_next = NULL;
+	cmp = mtod(m, struct cmsghdr *);
+	sp = (struct sockproc *)CMSG_DATA(cmp);
+	cmp->cmsg_len = len;
+	cmp->cmsg_level = SOL_SOCKET;
+	cmp->cmsg_type = SCM_PROC;
+	sp->sp_pid = l->l_proc->p_pid;
+	sp->sp_pgid = l->l_proc->p_pgid;

-	return (control);
+	return unp_addsockappend(m, control);
 }

 int	unp_defer, unp_gcing;
Index: share/man/man4/unix.4
===================================================================
RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/share/man/man4/unix.4,v
retrieving revision 1.19
diff -u -r1.19 unix.4
--- share/man/man4/unix.4	9 Aug 2007 15:23:03 -0000	1.19
+++ share/man/man4/unix.4	5 Jul 2008 20:33:38 -0000
@@ -168,7 +168,7 @@
 purposely not received, are automatically closed by the system
 when the destination socket is closed.
 .Pp
-There are two
+There are three
 .Tn socket-level
 .Xr setsockopt 2 / Ns Xr getsockopt 2
 option available in the
@@ -177,15 +177,17 @@
 .Pp
 The
 .Dv LOCAL_CREDS
+or
+.Dv LOCAL_PROC
 option may be enabled on a
 .Dv SOCK_DGRAM
 or a
 .Dv SOCK_STREAM
 socket.
 This option provides a mechanism for the receiver to
-receive the credentials of the process as a
+receive the credentials or identity of the process as a
 .Xr recvmsg 2
-control message.
+control message with ancillary data.
 The msg_control field in the msghdr structure points
 to a buffer that contains a cmsghdr structure followed by a variable
 length sockcred structure, defined in
@@ -202,6 +204,14 @@
 };
 .Ed
 .Pp
+or a sockproc structure, defined as follows:
+.Bd -literal
+struct sockproc {
+	pid_t	sp_pid;			/* PID of process */
+	pid_t	sp_pgid;		/* PGID of process */
+};
+.Ed
+.Pp
 The
 .Dv LOCAL_PEEREID
 option may be used with


Or context diff:


Index: sys/sys/socket.h
===================================================================
RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/sys/socket.h,v
retrieving revision 1.90
diff -r1.90 socket.h
327a328,343
> #if defined(_NETBSD_SOURCE)
> 
> #ifndef pid_t
> typedef __pid_t		pid_t;		/* process id */
> #define pid_t		__pid_t
> #endif
> 
> /*
>  * Like sockcred but to obtain PID/PGID
>  */
> struct sockproc {
> 	pid_t	sp_pid;			/* process id */
> 	pid_t	sp_pgid;		/* process group id */
> };
> 
> #endif /* _NETBSD_SOURCE */
538a555
> #define SCM_PROC	0x08		/* PID/PGID (struct sockproc) */
Index: sys/sys/un.h
===================================================================
RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/sys/un.h,v
retrieving revision 1.43
diff -r1.43 un.h
61a62
> #define LOCAL_PROC	0x0004		/* pass PID/PGID to receiver */
Index: sys/kern/uipc_usrreq.c
===================================================================
RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.117
diff -r1.117 uipc_usrreq.c
169a170,171
> inline struct mbuf *unp_addsockalloc(struct mbuf *, int, int);
> inline struct mbuf *unp_addsockappend(struct mbuf *, struct mbuf *);
170a173
> struct mbuf *unp_addsockproc(struct lwp *, struct mbuf *);
288a292,293
> 	if (unp->unp_conn->unp_flags & UNP_WANTPROC)
> 		control = unp_addsockproc(l, control);
484c489
< 		 * forging SCM_CREDS.
---
> 		 * forging SCM_CREDS or SCM_PROC.
550a556,563
> 			if (unp->unp_conn->unp_flags & UNP_WANTPROC) {
> 				/*
> 				 * PID/PGID are passed only once on
> 				 * SOCK_STREAM.
> 				 */
> 				unp->unp_conn->unp_flags &= ~UNP_WANTPROC;
> 				control = unp_addsockproc(l, control);
> 			}
659a673
> 		case LOCAL_PROC:
674a689,691
> 				case LOCAL_PROC:
> 					OPTSET(UNP_WANTPROC);
> 					break;
690a708
> #define	OPTBIT(bit)	(unp->unp_flags & (bit) ? 1 : 0)
706,708d723
< 
< #define	OPTBIT(bit)	(unp->unp_flags & (bit) ? 1 : 0)
< 
711a727,732
> 		case LOCAL_PROC:
> 			*mp = m = m_get(M_WAIT, MT_SOOPTS);
> 			m->m_len = sizeof(int);
> 			optval = OPTBIT(UNP_WANTPROC);
> 			*mtod(m, int *) = optval;
> 			break;
1367,1368c1388,1389
< struct mbuf *
< unp_addsockcred(struct lwp *l, struct mbuf *control)
---
> inline struct mbuf *
> unp_addsockalloc(struct mbuf *control, int len, int space)
1370,1376c1391
< 	struct cmsghdr *cmp;
< 	struct sockcred *sc;
< 	struct mbuf *m, *n;
< 	int len, space, i;
< 
< 	len = CMSG_LEN(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
< 	space = CMSG_SPACE(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
---
> 	struct mbuf *m;
1389a1405,1434
> 	return m;
> }
> 
> inline struct mbuf *
> unp_addsockappend(struct mbuf *control, struct mbuf *m)
> {
> 	struct mbuf *n;
> 
> 	if (control != NULL) {
> 		for (n = control; n->m_next != NULL; n = n->m_next) ;
> 		n->m_next = m;
> 		return control;
> 	}
> 
> 	return m;
> }
> 
> struct mbuf *
> unp_addsockcred(struct lwp *l, struct mbuf *control)
> {
> 	struct cmsghdr *cmp;
> 	struct sockcred *sc;
> 	struct mbuf *m;
> 	int len, space, i;
> 
> 	len = CMSG_LEN(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
> 	space = CMSG_SPACE(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
> 
> 	m = unp_addsockalloc(control, len, space);
> 
1405,1413c1450,1474
< 	/*
< 	 * If a control message already exists, append us to the end.
< 	 */
< 	if (control != NULL) {
< 		for (n = control; n->m_next != NULL; n = n->m_next)
< 			;
< 		n->m_next = m;
< 	} else
< 		control = m;
---
> 	return unp_addsockappend(m, control);
> }
> 
> struct mbuf *
> unp_addsockproc(struct lwp *l, struct mbuf *control)
> {
> 	struct cmsghdr *cmp;
> 	struct sockproc *sp;
> 	struct mbuf *m;
> 	int len, space;
> 
> 	len = CMSG_LEN(sizeof(struct sockproc));
> 	space = CMSG_SPACE(sizeof(struct sockproc));
> 
> 	m = unp_addsockalloc(control, len, space);
> 
> 	m->m_len = space;
> 	m->m_next = NULL;
> 	cmp = mtod(m, struct cmsghdr *);
> 	sp = (struct sockproc *)CMSG_DATA(cmp);
> 	cmp->cmsg_len = len;
> 	cmp->cmsg_level = SOL_SOCKET;
> 	cmp->cmsg_type = SCM_PROC;
> 	sp->sp_pid = l->l_proc->p_pid;
> 	sp->sp_pgid = l->l_proc->p_pgid;
1415c1476
< 	return (control);
---
> 	return unp_addsockappend(m, control);
Index: share/man/man4/unix.4
===================================================================
RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/share/man/man4/unix.4,v
retrieving revision 1.19
diff -r1.19 unix.4
171c171
< There are two
---
> There are three
179a180,181
> or
> .Dv LOCAL_PROC
186c188
< receive the credentials of the process as a
---
> receive the credentials or identity of the process as a
188c190
< control message.
---
> control message with ancillary data.
204a207,214
> or a sockproc structure, defined as follows:
> .Bd -literal
> struct sockproc {
> 	pid_t	sp_pid;			/* PID of process */
> 	pid_t	sp_pgid;		/* PGID of process */
> };
> .Ed
> .Pp


Thanks,
Matthew Mondor

>Audit-Trail:
From: mmondor@pulsar-zone.net
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: Re: kern/39108 (Proposal for unix(4) LOCAL_PROC/SCM_PROC)
Date: Sun, 2 Nov 2008 22:03:10 -0500

 Updated diff for 5.99.01:


 Index: sys/sys/socket.h
 ===================================================================
 RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/sys/socket.h,v
 retrieving revision 1.91
 diff -u -p -r1.91 socket.h
 --- sys/sys/socket.h	4 Aug 2008 03:55:47 -0000	1.91
 +++ sys/sys/socket.h	31 Oct 2008 02:17:58 -0000
 @@ -331,6 +331,22 @@ struct sockcred {
  	(sizeof(struct sockcred) + (sizeof(gid_t) * ((ngrps) - 1)))
  #endif /* _NETBSD_SOURCE */

 +#if defined(_NETBSD_SOURCE)
 +
 +#ifndef pid_t
 +typedef __pid_t		pid_t;		/* process id */
 +#define pid_t		__pid_t
 +#endif
 +
 +/*
 + * Like sockcred but to obtain PID/PGID
 + */
 +struct sockproc {
 +	pid_t	sp_pid;			/* process id */
 +	pid_t	sp_pgid;		/* process group id */
 +};
 +
 +#endif /* _NETBSD_SOURCE */

  #if defined(_NETBSD_SOURCE)
  /*
 @@ -542,6 +558,7 @@ struct cmsghdr {
  #if defined(_NETBSD_SOURCE)
  #define	SCM_TIMESTAMP	0x02		/* timestamp (struct timeval) */
  #define	SCM_CREDS	0x04		/* credentials (struct sockcred) */
 +#define SCM_PROC	0x08		/* PID/PGID (struct sockproc) */
  #endif

  /*
 Index: sys/sys/un.h
 ===================================================================
 RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/sys/un.h,v
 retrieving revision 1.44
 diff -u -p -r1.44 un.h
 --- sys/sys/un.h	6 Aug 2008 15:01:24 -0000	1.44
 +++ sys/sys/un.h	31 Oct 2008 02:18:00 -0000
 @@ -59,6 +59,7 @@ struct	sockaddr_un {
  #define	LOCAL_CREDS	0x0001		/* pass credentials to receiver */
  #define	LOCAL_CONNWAIT	0x0002		/* connects block until accepted */
  #define	LOCAL_PEEREID	0x0003		/* get peer identification */
 +#define LOCAL_PROC	0x0004		/* pass PID/PGID to receiver */
  #endif

  /*
 Index: sys/kern/uipc_usrreq.c
 ===================================================================
 RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/sys/kern/uipc_usrreq.c,v
 retrieving revision 1.119
 diff -u -p -r1.119 uipc_usrreq.c
 --- sys/kern/uipc_usrreq.c	11 Oct 2008 13:40:57 -0000	1.119
 +++ sys/kern/uipc_usrreq.c	3 Nov 2008 01:44:54 -0000
 @@ -168,7 +168,10 @@ const struct sockaddr_un sun_noname = {
  };
  ino_t	unp_ino;			/* prototype for fake inode numbers */

 +inline struct mbuf *unp_addsockalloc(struct mbuf *, int, int);
 +inline struct mbuf *unp_addsockappend(struct mbuf *, struct mbuf *);
  struct mbuf *unp_addsockcred(struct lwp *, struct mbuf *);
 +struct mbuf *unp_addsockproc(struct lwp *, struct mbuf *);
  static kmutex_t *uipc_lock;

  /*
 @@ -287,6 +290,8 @@ unp_output(struct mbuf *m, struct mbuf *
  		sun = &sun_noname;
  	if (unp->unp_conn->unp_flags & UNP_WANTCRED)
  		control = unp_addsockcred(l, control);
 +	if (unp->unp_conn->unp_flags & UNP_WANTPROC)
 +		control = unp_addsockproc(l, control);
  	if (sbappendaddr(&so2->so_rcv, (const struct sockaddr *)sun, m,
  	    control) == 0) {
  		so2->so_rcv.sb_overflowed++;
 @@ -482,7 +487,7 @@ uipc_usrreq(struct socket *so, int req, 
  		 * Note: unp_internalize() rejects any control message
  		 * other than SCM_RIGHTS, and only allows one.  This
  		 * has the side-effect of preventing a caller from
 -		 * forging SCM_CREDS.
 +		 * forging SCM_CREDS or SCM_PROC.
  		 */
  		if (control) {
  			sounlock(so);
 @@ -549,6 +554,14 @@ uipc_usrreq(struct socket *so, int req, 
  				unp->unp_conn->unp_flags &= ~UNP_WANTCRED;
  				control = unp_addsockcred(l, control);
  			}
 +			if (unp->unp_conn->unp_flags & UNP_WANTPROC) {
 +				/*
 +				 * PID/PGID are passed only once on
 +				 * SOCK_STREAM.
 +				 */
 +				unp->unp_conn->unp_flags &= ~UNP_WANTPROC;
 +				control = unp_addsockproc(l, control);
 +			}
  			/*
  			 * Send to paired receive port, and then reduce
  			 * send buffer hiwater marks to maintain backpressure.
 @@ -654,6 +667,7 @@ uipc_ctloutput(int op, struct socket *so
  	case PRCO_SETOPT:
  		switch (sopt->sopt_name) {
  		case LOCAL_CREDS:
 +		case LOCAL_PROC:
  		case LOCAL_CONNWAIT:
  			error = sockopt_getint(sopt, &optval);
  			if (error)
 @@ -668,6 +682,9 @@ uipc_ctloutput(int op, struct socket *so
  			case LOCAL_CREDS:
  				OPTSET(UNP_WANTCRED);
  				break;
 +			case LOCAL_PROC:
 +				OPTSET(UNP_WANTPROC);
 +				break;
  			case LOCAL_CONNWAIT:
  				OPTSET(UNP_CONNWAIT);
  				break;
 @@ -681,6 +698,7 @@ uipc_ctloutput(int op, struct socket *so
  		}
  		break;

 +#define	OPTBIT(bit)	(unp->unp_flags & (bit) ? 1 : 0)
  	case PRCO_GETOPT:
  		sounlock(so);
  		switch (sopt->sopt_name) {
 @@ -693,11 +711,13 @@ uipc_ctloutput(int op, struct socket *so
  			}
  			break;
  		case LOCAL_CREDS:
 -#define	OPTBIT(bit)	(unp->unp_flags & (bit) ? 1 : 0)
 -
  			optval = OPTBIT(UNP_WANTCRED);
  			error = sockopt_setint(sopt, optval);
  			break;
 +		case LOCAL_PROC:
 +			optval = OPTBIT(UNP_WANTPROC);
 +			error = sockopt_setint(sopt, optval);
 +			break;
  #undef OPTBIT

  		default:
 @@ -1353,16 +1373,10 @@ unp_internalize(struct mbuf **controlp)
  	return error;
  }

 -struct mbuf *
 -unp_addsockcred(struct lwp *l, struct mbuf *control)
 +inline struct mbuf *
 +unp_addsockalloc(struct mbuf *control, int len, int space)
  {
 -	struct cmsghdr *cmp;
 -	struct sockcred *sc;
 -	struct mbuf *m, *n;
 -	int len, space, i;
 -
 -	len = CMSG_LEN(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
 -	space = CMSG_SPACE(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
 +	struct mbuf *m;

  	m = m_get(M_WAIT, MT_CONTROL);
  	if (space > MLEN) {
 @@ -1376,6 +1390,36 @@ unp_addsockcred(struct lwp *l, struct mb
  		}
  	}

 +	return m;
 +}
 +
 +inline struct mbuf *
 +unp_addsockappend(struct mbuf *control, struct mbuf *m)
 +{
 +	struct mbuf *n;
 +
 +	if (control != NULL) {
 +		for (n = control; n->m_next != NULL; n = n->m_next) ;
 +		n->m_next = m;
 +		return control;
 +	}
 +
 +	return m;
 +}
 +
 +struct mbuf *
 +unp_addsockcred(struct lwp *l, struct mbuf *control)
 +{
 +	struct cmsghdr *cmp;
 +	struct sockcred *sc;
 +	struct mbuf *m;
 +	int len, space, i;
 +
 +	len = CMSG_LEN(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
 +	space = CMSG_SPACE(SOCKCREDSIZE(kauth_cred_ngroups(l->l_cred)));
 +
 +	m = unp_addsockalloc(control, len, space);
 +
  	m->m_len = space;
  	m->m_next = NULL;
  	cmp = mtod(m, struct cmsghdr *);
 @@ -1391,17 +1435,33 @@ unp_addsockcred(struct lwp *l, struct mb
  	for (i = 0; i < sc->sc_ngroups; i++)
  		sc->sc_groups[i] = kauth_cred_group(l->l_cred, i);

 -	/*
 -	 * If a control message already exists, append us to the end.
 -	 */
 -	if (control != NULL) {
 -		for (n = control; n->m_next != NULL; n = n->m_next)
 -			;
 -		n->m_next = m;
 -	} else
 -		control = m;
 +	return unp_addsockappend(m, control);
 +}
 +
 +struct mbuf *
 +unp_addsockproc(struct lwp *l, struct mbuf *control)
 +{
 +	struct cmsghdr *cmp;
 +	struct sockproc *sp;
 +	struct mbuf *m;
 +	int len, space;
 +
 +	len = CMSG_LEN(sizeof(struct sockproc));
 +	space = CMSG_SPACE(sizeof(struct sockproc));
 +
 +	m = unp_addsockalloc(control, len, space);
 +
 +	m->m_len = space;
 +	m->m_next = NULL;
 +	cmp = mtod(m, struct cmsghdr *);
 +	sp = (struct sockproc *)CMSG_DATA(cmp);
 +	cmp->cmsg_len = len;
 +	cmp->cmsg_level = SOL_SOCKET;
 +	cmp->cmsg_type = SCM_PROC;
 +	sp->sp_pid = l->l_proc->p_pid;
 +	sp->sp_pgid = l->l_proc->p_pgid;

 -	return (control);
 +	return unp_addsockappend(m, control);
  }

  int	unp_defer, unp_gcing;
 Index: share/man/man4/unix.4
 ===================================================================
 RCS file: /nfs/ginseng/home/data/cvsup/netbsd/src/share/man/man4/unix.4,v
 retrieving revision 1.19
 diff -u -p -r1.19 unix.4
 --- share/man/man4/unix.4	9 Aug 2007 15:23:03 -0000	1.19
 +++ share/man/man4/unix.4	5 Jul 2008 20:33:38 -0000
 @@ -168,7 +168,7 @@ Descriptors that are awaiting delivery, 
  purposely not received, are automatically closed by the system
  when the destination socket is closed.
  .Pp
 -There are two
 +There are three
  .Tn socket-level
  .Xr setsockopt 2 / Ns Xr getsockopt 2
  option available in the
 @@ -177,15 +177,17 @@ domain:
  .Pp
  The
  .Dv LOCAL_CREDS
 +or
 +.Dv LOCAL_PROC
  option may be enabled on a
  .Dv SOCK_DGRAM
  or a
  .Dv SOCK_STREAM
  socket.
  This option provides a mechanism for the receiver to
 -receive the credentials of the process as a
 +receive the credentials or identity of the process as a
  .Xr recvmsg 2
 -control message.
 +control message with ancillary data.
  The msg_control field in the msghdr structure points
  to a buffer that contains a cmsghdr structure followed by a variable
  length sockcred structure, defined in
 @@ -202,6 +204,14 @@ struct sockcred {
  };
  .Ed
  .Pp
 +or a sockproc structure, defined as follows:
 +.Bd -literal
 +struct sockproc {
 +	pid_t	sp_pid;			/* PID of process */
 +	pid_t	sp_pgid;		/* PGID of process */
 +};
 +.Ed
 +.Pp
  The
  .Dv LOCAL_PEEREID
  option may be used with

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.