--- /dev/null
+Index: xc/config/cf/FreeBSD.cf
+===================================================================
+RCS file: /home/x-cvs/xc/config/cf/FreeBSD.cf,v
+retrieving revision 3.112.2.1
+diff -u -r3.112.2.1 FreeBSD.cf
+--- xc/config/cf/FreeBSD.cf 2002/09/04 02:38:08 3.112.2.1
++++ xc/config/cf/FreeBSD.cf 2002/09/12 20:51:03
+@@ -191,6 +191,10 @@
+ #define HasSetUserContext YES
+ #endif
+
++#if OSMajorVersion >= 5 || (OSMajorVersion == 4 && OSMinorVersion >= 6)
++#define HasGetpeereid YES
++#endif
++
+ /* 3.3(?) and later has support for setting MTRRs */
+ #ifndef HasMTRRSupport
+ #if OSMajorVersion > 3 || (OSMajorVersion == 3 && OSMinorVersion >= 3)
+Index: xc/config/cf/Imake.tmpl
+===================================================================
+RCS file: /home/x-cvs/xc/config/cf/Imake.tmpl,v
+retrieving revision 3.116.2.1
+diff -u -r3.116.2.1 Imake.tmpl
+--- xc/config/cf/Imake.tmpl 2002/09/04 02:38:08 3.116.2.1
++++ xc/config/cf/Imake.tmpl 2002/09/12 20:51:06
+@@ -395,6 +395,9 @@
+ #ifndef HasPamMisc
+ #define HasPamMisc NO
+ #endif
++#ifndef HasGetpeereid
++#define HasGetpeereid NO
++#endif
+ /* byte-order defaults */
+ #ifndef ByteOrder
+ #if defined(VaxArchitecture)
+Index: xc/config/cf/OpenBSD.cf
+===================================================================
+RCS file: /home/x-cvs/xc/config/cf/OpenBSD.cf,v
+retrieving revision 3.66.2.1
+diff -u -r3.66.2.1 OpenBSD.cf
+--- xc/config/cf/OpenBSD.cf 2002/09/04 02:38:08 3.66.2.1
++++ xc/config/cf/OpenBSD.cf 2002/09/12 20:51:06
+@@ -97,6 +97,11 @@
+ # define HasBSDAuth YES
+ #endif
+
++/* OpenBSD 3.0 and later has getpeereid() */
++#if OSMajorVersion >= 3
++# define HasGetpeereid YES
++#endif
++
+ /* OpenBSD 3.0 has APM with kqueue interface */
+ #if OSMajorVersion >= 3
+ # define HasApmKqueue YES
+Index: xc/programs/Xserver/Xext/shm.c
+===================================================================
+RCS file: /home/x-cvs/xc/programs/Xserver/Xext/shm.c,v
+retrieving revision 3.33.2.2
+diff -u -r3.33.2.2 shm.c
+--- xc/programs/Xserver/Xext/shm.c 2002/05/29 23:03:19 3.33.2.2
++++ xc/programs/Xserver/Xext/shm.c 2002/09/12 20:51:36
+@@ -38,6 +38,7 @@
+ #include <shm.h>
+ #endif
+ #include <unistd.h>
++#include <sys/stat.h>
+ #define NEED_REPLIES
+ #define NEED_EVENTS
+ #include "X.h"
+@@ -64,12 +65,6 @@
+ #include "panoramiXsrv.h"
+ #endif
+
+-#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
+-#define HAS_SAVED_IDS_AND_SETEUID
+-#else
+-#include <sys/stat.h>
+-#endif
+-
+ typedef struct _ShmDesc {
+ struct _ShmDesc *next;
+ int shmid;
+@@ -361,35 +356,38 @@
+ return (client->noClientException);
+ }
+
+-#ifndef HAS_SAVED_IDS_AND_SETEUID
+ /*
+ * Simulate the access() system call for a shared memory segement,
+- * using the real user and group id of the process
++ * using the credentials from the client if available
+ */
+ static int
+-shm_access(uid_t uid, gid_t gid, struct ipc_perm *perm, int readonly)
++shm_access(ClientPtr client, struct ipc_perm *perm, int readonly)
+ {
++ int uid, gid;
+ mode_t mask;
+
+- /* User id 0 always gets access */
+- if (uid == 0) {
+- return 0;
+- }
+- /* Check the owner */
+- if (perm->uid == uid || perm->cuid == uid) {
+- mask = S_IRUSR;
+- if (!readonly) {
+- mask |= S_IWUSR;
++ if (LocalClientCred(client, &uid, &gid) != -1) {
++
++ /* User id 0 always gets access */
++ if (uid == 0) {
++ return 0;
+ }
+- return (perm->mode & mask) == mask ? 0 : -1;
+- }
+- /* Check the group */
+- if (perm->gid == gid || perm->cgid == gid) {
+- mask = S_IRGRP;
+- if (!readonly) {
+- mask |= S_IWGRP;
++ /* Check the owner */
++ if (perm->uid == uid || perm->cuid == uid) {
++ mask = S_IRUSR;
++ if (!readonly) {
++ mask |= S_IWUSR;
++ }
++ return (perm->mode & mask) == mask ? 0 : -1;
++ }
++ /* Check the group */
++ if (perm->gid == gid || perm->cgid == gid) {
++ mask = S_IRGRP;
++ if (!readonly) {
++ mask |= S_IWGRP;
++ }
++ return (perm->mode & mask) == mask ? 0 : -1;
+ }
+- return (perm->mode & mask) == mask ? 0 : -1;
+ }
+ /* Otherwise, check everyone else */
+ mask = S_IROTH;
+@@ -398,7 +396,6 @@
+ }
+ return (perm->mode & mask) == mask ? 0 : -1;
+ }
+-#endif
+
+ static int
+ ProcShmAttach(client)
+@@ -407,12 +404,6 @@
+ struct shmid_ds buf;
+ ShmDescPtr shmdesc;
+ REQUEST(xShmAttachReq);
+- uid_t ruid;
+- gid_t rgid;
+-#ifdef HAS_SAVED_IDS_AND_SETEUID
+- uid_t euid;
+- gid_t egid;
+-#endif
+
+ REQUEST_SIZE_MATCH(xShmAttachReq);
+ LEGAL_NEW_RESOURCE(stuff->shmseg, client);
+@@ -436,44 +427,25 @@
+ shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec));
+ if (!shmdesc)
+ return BadAlloc;
+- ruid = getuid();
+- rgid = getgid();
+-#ifdef HAS_SAVED_IDS_AND_SETEUID
+- euid = geteuid();
+- egid = getegid();
+-
+- if (euid != ruid || egid != rgid) {
+- /* Temporarly switch back to real ids */
+- if (seteuid(ruid) == -1 || setegid(rgid) == -1) {
+- return BadAccess;
+- }
+- }
+-#endif
+ shmdesc->addr = shmat(stuff->shmid, 0,
+ stuff->readOnly ? SHM_RDONLY : 0);
+-#ifdef HAS_SAVED_IDS_AND_SETEUID
+- if (euid != ruid || egid != rgid) {
+- /* Switch back to root privs */
+- if (seteuid(euid) == -1 || setegid(egid) == -1) {
+- return BadAccess;
+- }
+- }
+-#endif
+ if ((shmdesc->addr == ((char *)-1)) ||
+ shmctl(stuff->shmid, IPC_STAT, &buf))
+ {
+ xfree(shmdesc);
+ return BadAccess;
+ }
+-#ifndef HAS_SAVED_IDS_AND_SETEUID
++
+ /* The attach was performed with root privs. We must
+- * do manual checking of access rights for the real uid/gid */
+- if (shm_access(ruid, rgid, &(buf.shm_perm), stuff->readOnly) == -1) {
++ * do manual checking of access rights for the credentials
++ * of the client */
++
++ if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) {
+ shmdt(shmdesc->addr);
+ xfree(shmdesc);
+ return BadAccess;
+ }
+-#endif
++
+ shmdesc->shmid = stuff->shmid;
+ shmdesc->refcnt = 1;
+ shmdesc->writable = !stuff->readOnly;
+Index: xc/programs/Xserver/include/os.h
+===================================================================
+RCS file: /home/x-cvs/xc/programs/Xserver/include/os.h,v
+retrieving revision 3.40
+diff -u -r3.40 os.h
+--- xc/programs/Xserver/include/os.h 2001/12/14 19:59:55 3.40
++++ xc/programs/Xserver/include/os.h 2002/09/12 20:51:42
+@@ -639,6 +639,8 @@
+ #endif
+ );
+
++extern int LocalClientCred(ClientPtr, int *, int *);
++
+ extern int ChangeAccessControl(
+ #if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+Index: xc/programs/Xserver/os/Imakefile
+===================================================================
+RCS file: /home/x-cvs/xc/programs/Xserver/os/Imakefile,v
+retrieving revision 3.34
+diff -u -r3.34 Imakefile
+--- xc/programs/Xserver/os/Imakefile 2001/10/28 03:34:16 3.34
++++ xc/programs/Xserver/os/Imakefile 2002/09/12 20:51:42
+@@ -78,6 +78,10 @@
+ MALLOC_OBJS=xalloc.o
+ #endif
+
++#if HasGetpeereid
++GETPEEREID_DEFINES = -DHAS_GETPEEREID
++#endif
++
+ BOOTSTRAPCFLAGS =
+ SRCS = WaitFor.c access.c connection.c io.c $(COLOR_SRCS) \
+ osinit.c utils.c auth.c mitauth.c secauth.c $(XDMAUTHSRCS) \
+@@ -111,7 +115,7 @@
+ #endif
+ DEFINES = -DXSERV_t -DTRANS_SERVER $(CONNECTION_FLAGS) $(MEM_DEFINES) \
+ $(XDMAUTHDEFS) $(RPCDEFS) $(SIGNAL_DEFINES) $(OS_DEFINES) \
+- $(KRB5_DEFINES) $(RGB_DEFINES)
++ $(KRB5_DEFINES) $(RGB_DEFINES) $(GETPEEREID_DEFINES)
+ INCLUDES = -I. -I../include -I$(XINCLUDESRC) -I$(EXTINCSRC) \
+ -I$(SERVERSRC)/Xext -I$(FONTINCSRC) \
+ -I$(TOP)/lib/Xau -I../lbx Krb5Includes
+Index: xc/programs/Xserver/os/access.c
+===================================================================
+RCS file: /home/x-cvs/xc/programs/Xserver/os/access.c,v
+retrieving revision 3.39
+diff -u -r3.39 access.c
+--- xc/programs/Xserver/os/access.c 2002/01/07 20:38:29 3.39
++++ xc/programs/Xserver/os/access.c 2002/09/12 20:51:44
+@@ -1007,6 +1007,55 @@
+ return FALSE;
+ }
+
++/*
++ * Return the uid and gid of a connected local client
++ * or the uid/gid for nobody those ids cannot be determinded
++ *
++ * Used by XShm to test access rights to shared memory segments
++ */
++int
++LocalClientCred(ClientPtr client, int *pUid, int *pGid)
++{
++ int fd;
++ XtransConnInfo ci;
++#ifdef HAS_GETPEEREID
++ uid_t uid;
++ gid_t gid;
++#elif defined(SO_PEERCRED)
++ struct ucred peercred;
++ socklen_t so_len = sizeof(peercred);
++#endif
++
++ if (client == NULL)
++ return -1;
++ ci = ((OsCommPtr)client->osPrivate)->trans_conn;
++ /* We can only determine peer credentials for Unix domain sockets */
++ if (!_XSERVTransIsLocal(ci)) {
++ return -1;
++ }
++ fd = _XSERVTransGetConnectionNumber(ci);
++#ifdef HAS_GETPEEREID
++ if (getpeereid(fd, &uid, &gid) == -1)
++ return -1;
++ if (pUid != NULL)
++ *pUid = uid;
++ if (pGid != NULL)
++ *pGid = gid;
++ return 0;
++#elif defined(SO_PEERCRED)
++ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1)
++ return -1;
++ if (pUid != NULL)
++ *pUid = peercred.uid;
++ if (pGid != NULL)
++ *pGid = peercred.gid;
++ return 0;
++#else
++ /* No system call available to get the credentials of the peer */
++ return -1;
++#endif
++}
++
+ static Bool
+ AuthorizedClient(ClientPtr client)
+ {