tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Adding sc_pid to SCM_CREDS
Hi List
For AF_UNIX SOCK_DGRAM sockets, the only way of obtaining credentials is
via LOCAL_CREDS which returns SCM_CREDS as a cmsg.
However, struct sockcred lacks the process id of the sender which is of
use to many applications.
For SOCK_STREAM and SOCK_SEQPACKET, we do have LOCAL_PEEREID, but that
comes at the extra expense of a syscall after accepting.
There was a previous discussion here:
https://mail-index.netbsd.org/tech-kern/2008/07/05/msg001969.html
And an open gnats ticket with a LOCAL_PROC suggestion under kern/39108
http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=39108
Attached is a patch which adds sc_pid to struct sockcred and correctly
fills it out. The old sockcred structure is available as osockcred in
compat/sys/socket.h and guarded by COMPAT_70.
Everything seems to work ok with old binaries, but would appreciate some
extra eyes on the compat code or any suggestion how it could be done better.
Roy
Index: sys/compat/sys/socket.h
===================================================================
RCS file: /cvsroot/src/sys/compat/sys/socket.h,v
retrieving revision 1.12
diff -u -r1.12 socket.h
--- sys/compat/sys/socket.h 13 Feb 2009 22:41:04 -0000 1.12
+++ sys/compat/sys/socket.h 29 Mar 2016 16:10:34 -0000
@@ -71,12 +71,28 @@
int msg_accrightslen;
};
+/*
+ * 7.0 compat sockcred
+ */
+struct osockcred {
+ uid_t sc_uid; /* real user id */
+ uid_t sc_euid; /* effective user id */
+ gid_t sc_gid; /* real group id */
+ gid_t sc_egid; /* effective group id */
+ int sc_ngroups; /* number of supplemental groups */
+ gid_t sc_groups[1]; /* variable length */
+};
+#define SOCKOCREDSIZE(ngrps) \
+ (/*CONSTCOND*/sizeof(struct osockcred) + (sizeof(gid_t) * \
+ ((ngrps) ? ((ngrps) - 1) : 0)))
+
#ifdef _KERNEL
#define SO_OSNDTIMEO 0x1005
#define SO_ORCVTIMEO 0x1006
#define SO_OTIMESTAMP 0x0400
#define SCM_OTIMESTAMP 0x2
+#define SCM_OCREDS 0x4
__BEGIN_DECLS
struct socket;
Index: sys/kern/uipc_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.179
diff -u -r1.179 uipc_usrreq.c
--- sys/kern/uipc_usrreq.c 2 May 2015 17:18:03 -0000 1.179
+++ sys/kern/uipc_usrreq.c 29 Mar 2016 16:10:46 -0000
@@ -120,6 +120,10 @@
#include <sys/kernel.h>
#include <sys/kthread.h>
+#ifdef COMPAT_70
+#include "compat/sys/socket.h"
+#endif
+
/*
* Unix communications domain.
*
@@ -171,6 +175,9 @@
ino_t unp_ino; /* prototype for fake inode numbers */
static struct mbuf * unp_addsockcred(struct lwp *, struct mbuf *);
+#ifdef COMPAT_70
+static struct mbuf * unp_addosockcred(struct lwp *, struct mbuf *);
+#endif
static void unp_discard_later(file_t *);
static void unp_discard_now(file_t *);
static void unp_disconnect1(struct unpcb *);
@@ -319,6 +326,10 @@
sun = &sun_noname;
if (unp->unp_conn->unp_flags & UNP_WANTCRED)
control = unp_addsockcred(curlwp, control);
+#ifdef COMPAT_70
+ if (unp->unp_conn->unp_flags & UNP_OWANTCRED)
+ control = unp_addosockcred(curlwp, control);
+#endif
if (sbappendaddr(&so2->so_rcv, (const struct sockaddr *)sun, m,
control) == 0) {
so2->so_rcv.sb_overflowed++;
@@ -491,6 +502,16 @@
unp->unp_conn->unp_flags &= ~UNP_WANTCRED;
control = unp_addsockcred(l, control);
}
+#ifdef COMPAT_70
+ if (unp->unp_conn->unp_flags & UNP_OWANTCRED) {
+ /*
+ * Credentials are passed only once on
+ * SOCK_STREAM and SOCK_SEQPACKET.
+ */
+ unp->unp_conn->unp_flags &= ~UNP_OWANTCRED;
+ control = unp_addsockcred(l, control);
+ }
+#endif
/*
* Send to paired receive port, and then reduce
* send buffer hiwater marks to maintain backpressure.
@@ -566,6 +587,9 @@
switch (sopt->sopt_name) {
case LOCAL_CREDS:
case LOCAL_CONNWAIT:
+#ifdef COMPAT_70
+ case LOCAL_OCREDS:
+#endif
error = sockopt_getint(sopt, &optval);
if (error)
break;
@@ -582,7 +606,12 @@
case LOCAL_CONNWAIT:
OPTSET(UNP_CONNWAIT);
break;
- }
+#ifdef COMPAT_70
+ case LOCAL_OCREDS:
+ OPTSET(UNP_OWANTCRED);
+ break;
+#endif
+ }
break;
#undef OPTSET
@@ -609,6 +638,12 @@
optval = OPTBIT(UNP_WANTCRED);
error = sockopt_setint(sopt, optval);
break;
+#ifdef COMPAT_70
+ case LOCAL_OCREDS:
+ optval = OPTBIT(UNP_OWANTCRED);
+ error = sockopt_setint(sopt, optval);
+ break;
+#endif
#undef OPTBIT
default:
@@ -1572,7 +1607,34 @@
SCM_CREDS, SOL_SOCKET, M_WAITOK);
if (m == NULL)
return control;
-
+
+ sc = p;
+ sc->sc_pid = l->l_proc->p_pid;
+ sc->sc_uid = kauth_cred_getuid(l->l_cred);
+ sc->sc_euid = kauth_cred_geteuid(l->l_cred);
+ sc->sc_gid = kauth_cred_getgid(l->l_cred);
+ sc->sc_egid = kauth_cred_getegid(l->l_cred);
+ sc->sc_ngroups = kauth_cred_ngroups(l->l_cred);
+
+ for (int i = 0; i < sc->sc_ngroups; i++)
+ sc->sc_groups[i] = kauth_cred_group(l->l_cred, i);
+
+ return m_add(control, m);
+}
+
+#ifdef COMPAT_70
+struct mbuf *
+unp_addosockcred(struct lwp *l, struct mbuf *control)
+{
+ struct osockcred *sc;
+ struct mbuf *m;
+ void *p;
+
+ m = sbcreatecontrol1(&p, SOCKOCREDSIZE(kauth_cred_ngroups(l->l_cred)),
+ SCM_OCREDS, SOL_SOCKET, M_WAITOK);
+ if (m == NULL)
+ return control;
+
sc = p;
sc->sc_uid = kauth_cred_getuid(l->l_cred);
sc->sc_euid = kauth_cred_geteuid(l->l_cred);
@@ -1585,6 +1647,7 @@
return m_add(control, m);
}
+#endif
/*
* Do a mark-sweep GC of files in the system, to free up any which are
Index: sys/sys/socket.h
===================================================================
RCS file: /cvsroot/src/sys/sys/socket.h,v
retrieving revision 1.118
diff -u -r1.118 socket.h
--- sys/sys/socket.h 13 Oct 2015 21:28:34 -0000 1.118
+++ sys/sys/socket.h 29 Mar 2016 16:10:49 -0000
@@ -349,6 +349,7 @@
* Socket credentials.
*/
struct sockcred {
+ pid_t sc_pid; /* process id */
uid_t sc_uid; /* real user id */
uid_t sc_euid; /* effective user id */
gid_t sc_gid; /* real group id */
@@ -596,8 +597,9 @@
#define SCM_RIGHTS 0x01 /* access rights (array of int) */
#if defined(_NETBSD_SOURCE)
/* 0x02 timestamp (struct timeval50) */
-#define SCM_CREDS 0x04 /* credentials (struct sockcred) */
+/* 0x04 credentials (struct osockcred) */
#define SCM_TIMESTAMP 0x08 /* timestamp (struct timeval) */
+#define SCM_CREDS 0x10 /* credentials (struct sockcred) */
#endif
/*
Index: sys/sys/un.h
===================================================================
RCS file: /cvsroot/src/sys/sys/un.h,v
retrieving revision 1.56
diff -u -r1.56 un.h
--- sys/sys/un.h 2 May 2015 17:18:04 -0000 1.56
+++ sys/sys/un.h 29 Mar 2016 16:10:49 -0000
@@ -56,9 +56,10 @@
* Socket options for UNIX IPC domain.
*/
#if defined(_NETBSD_SOURCE)
-#define LOCAL_CREDS 0x0001 /* pass credentials to receiver */
+#define LOCAL_OCREDS 0x0001 /* pass credentials to receiver */
#define LOCAL_CONNWAIT 0x0002 /* connects block until accepted */
#define LOCAL_PEEREID 0x0003 /* get peer identification */
+#define LOCAL_CREDS 0x0004 /* pass credentials to receiver */
#endif
/*
Index: sys/sys/unpcb.h
===================================================================
RCS file: /cvsroot/src/sys/sys/unpcb.h,v
retrieving revision 1.17
diff -u -r1.17 unpcb.h
--- sys/sys/unpcb.h 24 Apr 2008 11:38:39 -0000 1.17
+++ sys/sys/unpcb.h 29 Mar 2016 16:10:49 -0000
@@ -97,11 +97,12 @@
* in with data for the listening process. This is set up in unp_bind() when
* it fills in unp_connid for later consumption by unp_connect().
*/
-#define UNP_WANTCRED 0x0001 /* credentials wanted */
+#define UNP_OWANTCRED 0x0001 /* credentials wanted */
#define UNP_CONNWAIT 0x0002 /* connect blocks until accepted */
#define UNP_EIDSVALID 0x0004 /* unp_connid contains valid data */
#define UNP_EIDSBIND 0x0008 /* unp_connid was set by bind() */
#define UNP_BUSY 0x0010 /* busy connecting or binding */
+#define UNP_WANTCRED 0x0020 /* credentials wanted */
#define sotounpcb(so) ((struct unpcb *)((so)->so_pcb))
Home |
Main Index |
Thread Index |
Old Index