diff options
-rw-r--r-- | Xext/shm.c | 98 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | include/dix-config.h.in | 3 |
3 files changed, 79 insertions, 24 deletions
diff --git a/Xext/shm.c b/Xext/shm.c index 7fa834952..a688aa8d9 100644 --- a/Xext/shm.c +++ b/Xext/shm.c @@ -62,6 +62,33 @@ in this Software without prior written authorization from The Open Group. #include <X11/extensions/shmstr.h> #include <X11/Xfuncproto.h> +/* Needed for Solaris cross-zone shared memory extension */ +#ifdef HAVE_SHMCTL64 +#include <sys/ipc_impl.h> +#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf) +#define SHMSTAT_TYPE struct shmid_ds64 +#define SHMPERM_TYPE struct ipc_perm64 +#define SHM_PERM(buf) buf.shmx_perm +#define SHM_SEGSZ(buf) buf.shmx_segsz +#define SHMPERM_UID(p) p->ipcx_uid +#define SHMPERM_CUID(p) p->ipcx_cuid +#define SHMPERM_GID(p) p->ipcx_gid +#define SHMPERM_CGID(p) p->ipcx_cgid +#define SHMPERM_MODE(p) p->ipcx_mode +#define SHMPERM_ZONEID(p) p->ipcx_zoneid +#else +#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf) +#define SHMSTAT_TYPE struct shmid_ds +#define SHMPERM_TYPE struct ipc_perm +#define SHM_PERM(buf) buf.shm_perm +#define SHM_SEGSZ(buf) buf.shm_segsz +#define SHMPERM_UID(p) p->uid +#define SHMPERM_CUID(p) p->cuid +#define SHMPERM_GID(p) p->gid +#define SHMPERM_CGID(p) p->cgid +#define SHMPERM_MODE(p) p->mode +#endif + #ifdef PANORAMIX #include "panoramiX.h" #include "panoramiXsrv.h" @@ -348,32 +375,57 @@ ProcShmQueryVersion(client) * using the credentials from the client if available */ static int -shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) { int uid, gid; mode_t mask; + int uidset = 0, gidset = 0; + LocalClientCredRec *lcc; + + if (GetLocalClientCreds(client, &lcc) != -1) { - if (LocalClientCred(client, &uid, &gid) != -1) { - - /* User id 0 always gets access */ - if (uid == 0) { - return 0; + if (lcc->fieldsSet & LCC_UID_SET) { + uid = lcc->euid; + uidset = 1; + } + if (lcc->fieldsSet & LCC_GID_SET) { + gid = lcc->egid; + gidset = 1; } - /* Check the owner */ - if (perm->uid == uid || perm->cuid == uid) { - mask = S_IRUSR; - if (!readonly) { - mask |= S_IWUSR; + +#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) + if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) + || (lcc->zoneid != SHMPERM_ZONEID(perm))) { + uidset = 0; + gidset = 0; + } +#endif + FreeLocalClientCreds(lcc); + + if (uidset) { + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; } - 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; + + if (gidset) { + /* Check the group */ + if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; } - return (perm->mode & mask) == mask ? 0 : -1; } } /* Otherwise, check everyone else */ @@ -381,14 +433,14 @@ shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) if (!readonly) { mask |= S_IWOTH; } - return (perm->mode & mask) == mask ? 0 : -1; + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; } static int ProcShmAttach(client) register ClientPtr client; { - struct shmid_ds buf; + SHMSTAT_TYPE buf; ShmDescPtr shmdesc; REQUEST(xShmAttachReq); @@ -417,7 +469,7 @@ ProcShmAttach(client) shmdesc->addr = shmat(stuff->shmid, 0, stuff->readOnly ? SHM_RDONLY : 0); if ((shmdesc->addr == ((char *)-1)) || - shmctl(stuff->shmid, IPC_STAT, &buf)) + SHMSTAT(stuff->shmid, &buf)) { xfree(shmdesc); return BadAccess; @@ -427,7 +479,7 @@ ProcShmAttach(client) * do manual checking of access rights for the credentials * of the client */ - if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { shmdt(shmdesc->addr); xfree(shmdesc); return BadAccess; @@ -436,7 +488,7 @@ ProcShmAttach(client) shmdesc->shmid = stuff->shmid; shmdesc->refcnt = 1; shmdesc->writable = !stuff->readOnly; - shmdesc->size = buf.shm_segsz; + shmdesc->size = SHM_SEGSZ(buf); shmdesc->next = Shmsegs; Shmsegs = shmdesc; } diff --git a/configure.ac b/configure.ac index 6565445f0..444edfd70 100644 --- a/configure.ac +++ b/configure.ac @@ -179,7 +179,7 @@ dnl Checks for library functions. AC_FUNC_VPRINTF AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr \ strtol getopt getopt_long vsnprintf walkcontext backtrace \ - getisax getzoneid]) + getisax getzoneid shmctl64]) AC_FUNC_ALLOCA dnl Old HAS_* names used in os/*.c. AC_CHECK_FUNC([getdtablesize], diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 3b9f15c28..5635d64ae 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -184,6 +184,9 @@ /* Define to 1 if you have the <rpcsvc/dbm.h> header file. */ #undef HAVE_RPCSVC_DBM_H +/* Define to 1 if you have the `shmctl64' function. */ +#undef HAVE_SHMCTL64 + /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H |