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