NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/39108: Proposal for unix(4) LOCAL_PROC/SCM_PROC
>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
>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
Home |
Main Index |
Thread Index |
Old Index