diff options
-rw-r--r-- | sys/kern/uipc_usrreq.c | 28 | ||||
-rw-r--r-- | sys/sys/socket.h | 26 |
2 files changed, 50 insertions, 4 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 3b668a2..3c68f05 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 - * $Id: uipc_usrreq.c,v 1.19 1997/02/22 09:39:29 peter Exp $ + * $Id: uipc_usrreq.c,v 1.20 1997/02/24 20:30:58 wollman Exp $ */ #include <sys/param.h> @@ -697,6 +697,10 @@ unp_externalize(rights) return (0); } +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + static int unp_internalize(control, p) struct mbuf *control; @@ -707,11 +711,29 @@ unp_internalize(control, p) register struct file **rp; register struct file *fp; register int i, fd; + register struct cmsgcred *cmcred; int oldfds; - if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || - cm->cmsg_len != control->m_len) + if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) || + cm->cmsg_level != SOL_SOCKET || cm->cmsg_len != control->m_len) return (EINVAL); + + /* + * Fill in credential information. + */ + if (cm->cmsg_type == SCM_CREDS) { + cmcred = (struct cmsgcred *)(cm + 1); + cmcred->cmcred_pid = p->p_pid; + cmcred->cmcred_uid = p->p_cred->p_ruid; + cmcred->cmcred_gid = p->p_cred->p_rgid; + cmcred->cmcred_euid = p->p_ucred->cr_uid; + cmcred->cmcred_ngroups = MIN(p->p_ucred->cr_ngroups, + CMGROUP_MAX); + for (i = 0; i < cmcred->cmcred_ngroups; i++) + cmcred->cmcred_groups[i] = p->p_ucred->cr_groups[i]; + return(0); + } + oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int); /* * check that all the FDs passed in refer to legal OPEN files diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 7e0f6c7..c770a67 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)socket.h 8.4 (Berkeley) 2/21/94 - * $Id$ + * $Id: socket.h,v 1.17 1997/02/22 09:45:55 peter Exp $ */ #ifndef _SYS_SOCKET_H_ @@ -289,6 +289,29 @@ struct cmsghdr { /* followed by u_char cmsg_data[]; */ }; +/* + * While we may have more groups than this, the cmsgcred struct must + * be able to fit in an mbuf, and NGROUPS_MAX is too large to allow + * this. +*/ +#define CMGROUP_MAX 16 + +/* + * Credentials structure, used to verify the identity of a peer + * process that has sent us a message. This is allocated by the + * peer process but filled in by the kernel. This prevents the + * peer from lying about its identity. (Note that cmcred_groups[0] + * is the effective GID.) + */ +struct cmsgcred { + pid_t cmcred_pid; /* PID of sending process */ + uid_t cmcred_uid; /* real UID of sending process */ + uid_t cmcred_euid; /* effective UID of sending process */ + gid_t cmcred_gid; /* real GID of sending process */ + short cmcred_ngroups; /* number or groups */ + gid_t cmcred_groups[CMGROUP_MAX]; /* groups */ +}; + /* given pointer to struct cmsghdr, return pointer to data */ #define CMSG_DATA(cmsg) ((u_char *)((cmsg) + 1)) @@ -304,6 +327,7 @@ struct cmsghdr { /* "Socket"-level control message types: */ #define SCM_RIGHTS 0x01 /* access rights (array of int) */ #define SCM_TIMESTAMP 0x02 /* timestamp (struct timeval) */ +#define SCM_CREDS 0x03 /* process creds (struct cmsgcred) */ /* * 4.3 compat sockaddr, move to compat file later |