shm.c revision f7df2e56
105b261ecSmrg/************************************************************ 205b261ecSmrg 305b261ecSmrgCopyright 1989, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrg********************************************************/ 2605b261ecSmrg 2705b261ecSmrg/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ 2805b261ecSmrg 2905b261ecSmrg#define SHM 3005b261ecSmrg 3105b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3205b261ecSmrg#include <dix-config.h> 3305b261ecSmrg#endif 3405b261ecSmrg 3505b261ecSmrg#include <sys/types.h> 3605b261ecSmrg#include <sys/ipc.h> 3705b261ecSmrg#include <sys/shm.h> 3805b261ecSmrg#include <unistd.h> 3905b261ecSmrg#include <sys/stat.h> 40f7df2e56Smrg#include <fcntl.h> 4105b261ecSmrg#include <X11/X.h> 4205b261ecSmrg#include <X11/Xproto.h> 4305b261ecSmrg#include "misc.h" 4405b261ecSmrg#include "os.h" 4505b261ecSmrg#include "dixstruct.h" 4605b261ecSmrg#include "resource.h" 4705b261ecSmrg#include "scrnintstr.h" 4805b261ecSmrg#include "windowstr.h" 4905b261ecSmrg#include "pixmapstr.h" 5005b261ecSmrg#include "gcstruct.h" 5105b261ecSmrg#include "extnsionst.h" 5205b261ecSmrg#include "servermd.h" 534642e01fSmrg#include "shmint.h" 544642e01fSmrg#include "xace.h" 55684baedfSmrg#include <X11/extensions/shmproto.h> 5605b261ecSmrg#include <X11/Xfuncproto.h> 57f7df2e56Smrg#include <sys/mman.h> 584202a189Smrg#include "protocol-versions.h" 59f7df2e56Smrg#include "busfault.h" 6005b261ecSmrg 614642e01fSmrg/* Needed for Solaris cross-zone shared memory extension */ 624642e01fSmrg#ifdef HAVE_SHMCTL64 634642e01fSmrg#include <sys/ipc_impl.h> 644642e01fSmrg#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf) 654642e01fSmrg#define SHMSTAT_TYPE struct shmid_ds64 664642e01fSmrg#define SHMPERM_TYPE struct ipc_perm64 674642e01fSmrg#define SHM_PERM(buf) buf.shmx_perm 684642e01fSmrg#define SHM_SEGSZ(buf) buf.shmx_segsz 694642e01fSmrg#define SHMPERM_UID(p) p->ipcx_uid 704642e01fSmrg#define SHMPERM_CUID(p) p->ipcx_cuid 714642e01fSmrg#define SHMPERM_GID(p) p->ipcx_gid 724642e01fSmrg#define SHMPERM_CGID(p) p->ipcx_cgid 734642e01fSmrg#define SHMPERM_MODE(p) p->ipcx_mode 744642e01fSmrg#define SHMPERM_ZONEID(p) p->ipcx_zoneid 754642e01fSmrg#else 764642e01fSmrg#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf) 774642e01fSmrg#define SHMSTAT_TYPE struct shmid_ds 784642e01fSmrg#define SHMPERM_TYPE struct ipc_perm 794642e01fSmrg#define SHM_PERM(buf) buf.shm_perm 804642e01fSmrg#define SHM_SEGSZ(buf) buf.shm_segsz 814642e01fSmrg#define SHMPERM_UID(p) p->uid 824642e01fSmrg#define SHMPERM_CUID(p) p->cuid 834642e01fSmrg#define SHMPERM_GID(p) p->gid 844642e01fSmrg#define SHMPERM_CGID(p) p->cgid 854642e01fSmrg#define SHMPERM_MODE(p) p->mode 864642e01fSmrg#endif 874642e01fSmrg 8805b261ecSmrg#ifdef PANORAMIX 8905b261ecSmrg#include "panoramiX.h" 9005b261ecSmrg#include "panoramiXsrv.h" 9105b261ecSmrg#endif 9205b261ecSmrg 93f7df2e56Smrg#include "extinit.h" 9405b261ecSmrg 954202a189Smrgtypedef struct _ShmScrPrivateRec { 964202a189Smrg CloseScreenProcPtr CloseScreen; 974202a189Smrg ShmFuncsPtr shmFuncs; 984202a189Smrg DestroyPixmapProcPtr destroyPixmap; 994202a189Smrg} ShmScrPrivateRec; 1004202a189Smrg 10105b261ecSmrgstatic PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); 102f7df2e56Smrgstatic int ShmDetachSegment(void *value, XID shmseg); 103f7df2e56Smrgstatic void ShmResetProc(ExtensionEntry *extEntry); 104f7df2e56Smrgstatic void SShmCompletionEvent(xShmCompletionEvent *from, 105f7df2e56Smrg xShmCompletionEvent *to); 10605b261ecSmrg 107f7df2e56Smrgstatic Bool ShmDestroyPixmap(PixmapPtr pPixmap); 10805b261ecSmrg 10905b261ecSmrgstatic unsigned char ShmReqCode; 1104202a189Smrgint ShmCompletionCode; 1114202a189Smrgint BadShmSegCode; 1124202a189SmrgRESTYPE ShmSegType; 11305b261ecSmrgstatic ShmDescPtr Shmsegs; 11405b261ecSmrgstatic Bool sharedPixmaps; 1154202a189Smrgstatic DevPrivateKeyRec shmScrPrivateKeyRec; 116f7df2e56Smrg 1174202a189Smrg#define shmScrPrivateKey (&shmScrPrivateKeyRec) 1184202a189Smrgstatic DevPrivateKeyRec shmPixmapPrivateKeyRec; 119f7df2e56Smrg 1204202a189Smrg#define shmPixmapPrivateKey (&shmPixmapPrivateKeyRec) 121f7df2e56Smrgstatic ShmFuncs miFuncs = { NULL, NULL }; 122f7df2e56Smrgstatic ShmFuncs fbFuncs = { fbShmCreatePixmap, NULL }; 12305b261ecSmrg 1244202a189Smrg#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey)) 1254202a189Smrg 12605b261ecSmrg#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ 12705b261ecSmrg{ \ 128f7df2e56Smrg int tmprc; \ 129f7df2e56Smrg tmprc = dixLookupResourceByType((void **)&(shmdesc), shmseg, ShmSegType, \ 130f7df2e56Smrg client, DixReadAccess); \ 131f7df2e56Smrg if (tmprc != Success) \ 132f7df2e56Smrg return tmprc; \ 13305b261ecSmrg} 13405b261ecSmrg 13505b261ecSmrg#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ 13605b261ecSmrg{ \ 13705b261ecSmrg VERIFY_SHMSEG(shmseg, shmdesc, client); \ 13805b261ecSmrg if ((offset & 3) || (offset > shmdesc->size)) \ 13905b261ecSmrg { \ 14005b261ecSmrg client->errorValue = offset; \ 14105b261ecSmrg return BadValue; \ 14205b261ecSmrg } \ 14305b261ecSmrg if (needwrite && !shmdesc->writable) \ 14405b261ecSmrg return BadAccess; \ 14505b261ecSmrg} 14605b261ecSmrg 14705b261ecSmrg#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ 14805b261ecSmrg{ \ 14905b261ecSmrg if ((offset + len) > shmdesc->size) \ 15005b261ecSmrg { \ 15105b261ecSmrg return BadAccess; \ 15205b261ecSmrg } \ 15305b261ecSmrg} 15405b261ecSmrg 15505b261ecSmrg#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) 15605b261ecSmrg#include <sys/signal.h> 15705b261ecSmrg 15805b261ecSmrgstatic Bool badSysCall = FALSE; 15905b261ecSmrg 16005b261ecSmrgstatic void 1614642e01fSmrgSigSysHandler(int signo) 16205b261ecSmrg{ 16305b261ecSmrg badSysCall = TRUE; 16405b261ecSmrg} 16505b261ecSmrg 166f7df2e56Smrgstatic Bool 167f7df2e56SmrgCheckForShmSyscall(void) 16805b261ecSmrg{ 169f7df2e56Smrg void (*oldHandler) (int); 17005b261ecSmrg int shmid = -1; 17105b261ecSmrg 17205b261ecSmrg /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ 17305b261ecSmrg oldHandler = signal(SIGSYS, SigSysHandler); 17405b261ecSmrg 17505b261ecSmrg badSysCall = FALSE; 17605b261ecSmrg shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); 17705b261ecSmrg 178f7df2e56Smrg if (shmid != -1) { 17905b261ecSmrg /* Successful allocation - clean up */ 180f7df2e56Smrg shmctl(shmid, IPC_RMID, NULL); 18105b261ecSmrg } 182f7df2e56Smrg else { 18305b261ecSmrg /* Allocation failed */ 18405b261ecSmrg badSysCall = TRUE; 18505b261ecSmrg } 18605b261ecSmrg signal(SIGSYS, oldHandler); 1874202a189Smrg return !badSysCall; 18805b261ecSmrg} 18905b261ecSmrg 19005b261ecSmrg#define MUST_CHECK_FOR_SHM_SYSCALL 19105b261ecSmrg 19205b261ecSmrg#endif 19305b261ecSmrg 1944202a189Smrgstatic Bool 195f7df2e56SmrgShmCloseScreen(ScreenPtr pScreen) 1964202a189Smrg{ 1974202a189Smrg ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 198f7df2e56Smrg 1994202a189Smrg pScreen->CloseScreen = screen_priv->CloseScreen; 2004202a189Smrg dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL); 2014202a189Smrg free(screen_priv); 202f7df2e56Smrg return (*pScreen->CloseScreen) (pScreen); 2034202a189Smrg} 2044202a189Smrg 2054202a189Smrgstatic ShmScrPrivateRec * 2064202a189SmrgShmInitScreenPriv(ScreenPtr pScreen) 2074202a189Smrg{ 2084202a189Smrg ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 209f7df2e56Smrg 210f7df2e56Smrg if (!screen_priv) { 211f7df2e56Smrg screen_priv = calloc(1, sizeof(ShmScrPrivateRec)); 212f7df2e56Smrg screen_priv->CloseScreen = pScreen->CloseScreen; 213f7df2e56Smrg dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv); 214f7df2e56Smrg pScreen->CloseScreen = ShmCloseScreen; 2154202a189Smrg } 2164202a189Smrg return screen_priv; 2174202a189Smrg} 2184202a189Smrg 2194202a189Smrgstatic Bool 2204202a189SmrgShmRegisterPrivates(void) 2214202a189Smrg{ 2224202a189Smrg if (!dixRegisterPrivateKey(&shmScrPrivateKeyRec, PRIVATE_SCREEN, 0)) 223f7df2e56Smrg return FALSE; 2244202a189Smrg if (!dixRegisterPrivateKey(&shmPixmapPrivateKeyRec, PRIVATE_PIXMAP, 0)) 225f7df2e56Smrg return FALSE; 2264202a189Smrg return TRUE; 2274202a189Smrg} 2284202a189Smrg 229f7df2e56Smrg /*ARGSUSED*/ static void 230f7df2e56SmrgShmResetProc(ExtensionEntry * extEntry) 23105b261ecSmrg{ 23205b261ecSmrg int i; 233f7df2e56Smrg 2344202a189Smrg for (i = 0; i < screenInfo.numScreens; i++) 235f7df2e56Smrg ShmRegisterFuncs(screenInfo.screens[i], NULL); 23605b261ecSmrg} 23705b261ecSmrg 2384202a189Smrgvoid 2394642e01fSmrgShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) 24005b261ecSmrg{ 2414202a189Smrg if (!ShmRegisterPrivates()) 242f7df2e56Smrg return; 2434202a189Smrg ShmInitScreenPriv(pScreen)->shmFuncs = funcs; 24405b261ecSmrg} 24505b261ecSmrg 24605b261ecSmrgstatic Bool 247f7df2e56SmrgShmDestroyPixmap(PixmapPtr pPixmap) 24805b261ecSmrg{ 249f7df2e56Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 2504202a189Smrg ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 251f7df2e56Smrg void *shmdesc = NULL; 252f7df2e56Smrg Bool ret; 253f7df2e56Smrg 25405b261ecSmrg if (pPixmap->refcnt == 1) 255f7df2e56Smrg shmdesc = dixLookupPrivate(&pPixmap->devPrivates, shmPixmapPrivateKey); 256f7df2e56Smrg 2574202a189Smrg pScreen->DestroyPixmap = screen_priv->destroyPixmap; 25805b261ecSmrg ret = (*pScreen->DestroyPixmap) (pPixmap); 2594202a189Smrg screen_priv->destroyPixmap = pScreen->DestroyPixmap; 26005b261ecSmrg pScreen->DestroyPixmap = ShmDestroyPixmap; 261f7df2e56Smrg 262f7df2e56Smrg if (shmdesc) 263f7df2e56Smrg ShmDetachSegment(shmdesc, 0); 264f7df2e56Smrg 26505b261ecSmrg return ret; 26605b261ecSmrg} 26705b261ecSmrg 2684202a189Smrgvoid 2694642e01fSmrgShmRegisterFbFuncs(ScreenPtr pScreen) 27005b261ecSmrg{ 2714202a189Smrg ShmRegisterFuncs(pScreen, &fbFuncs); 27205b261ecSmrg} 27305b261ecSmrg 27405b261ecSmrgstatic int 2754642e01fSmrgProcShmQueryVersion(ClientPtr client) 27605b261ecSmrg{ 277f7df2e56Smrg xShmQueryVersionReply rep = { 278f7df2e56Smrg .type = X_Reply, 279f7df2e56Smrg .sharedPixmaps = sharedPixmaps, 280f7df2e56Smrg .sequenceNumber = client->sequence, 281f7df2e56Smrg .length = 0, 282f7df2e56Smrg .majorVersion = SERVER_SHM_MAJOR_VERSION, 283f7df2e56Smrg .minorVersion = SERVER_SHM_MINOR_VERSION, 284f7df2e56Smrg .uid = geteuid(), 285f7df2e56Smrg .gid = getegid(), 286f7df2e56Smrg .pixmapFormat = sharedPixmaps ? ZPixmap : 0 287f7df2e56Smrg }; 28805b261ecSmrg 28905b261ecSmrg REQUEST_SIZE_MATCH(xShmQueryVersionReq); 290f7df2e56Smrg 29105b261ecSmrg if (client->swapped) { 292f7df2e56Smrg swaps(&rep.sequenceNumber); 293f7df2e56Smrg swapl(&rep.length); 294f7df2e56Smrg swaps(&rep.majorVersion); 295f7df2e56Smrg swaps(&rep.minorVersion); 296f7df2e56Smrg swaps(&rep.uid); 297f7df2e56Smrg swaps(&rep.gid); 298f7df2e56Smrg } 299f7df2e56Smrg WriteToClient(client, sizeof(xShmQueryVersionReply), &rep); 3004202a189Smrg return Success; 30105b261ecSmrg} 30205b261ecSmrg 30305b261ecSmrg/* 30405b261ecSmrg * Simulate the access() system call for a shared memory segement, 30505b261ecSmrg * using the credentials from the client if available 30605b261ecSmrg */ 30705b261ecSmrgstatic int 308f7df2e56Smrgshm_access(ClientPtr client, SHMPERM_TYPE * perm, int readonly) 30905b261ecSmrg{ 31005b261ecSmrg int uid, gid; 31105b261ecSmrg mode_t mask; 3124642e01fSmrg int uidset = 0, gidset = 0; 3134642e01fSmrg LocalClientCredRec *lcc; 314f7df2e56Smrg 3154642e01fSmrg if (GetLocalClientCreds(client, &lcc) != -1) { 31605b261ecSmrg 317f7df2e56Smrg if (lcc->fieldsSet & LCC_UID_SET) { 318f7df2e56Smrg uid = lcc->euid; 319f7df2e56Smrg uidset = 1; 320f7df2e56Smrg } 321f7df2e56Smrg if (lcc->fieldsSet & LCC_GID_SET) { 322f7df2e56Smrg gid = lcc->egid; 323f7df2e56Smrg gidset = 1; 324f7df2e56Smrg } 3254642e01fSmrg 3264642e01fSmrg#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) 327f7df2e56Smrg if (((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) 328f7df2e56Smrg || (lcc->zoneid != SHMPERM_ZONEID(perm))) { 329f7df2e56Smrg uidset = 0; 330f7df2e56Smrg gidset = 0; 331f7df2e56Smrg } 3324642e01fSmrg#endif 333f7df2e56Smrg FreeLocalClientCreds(lcc); 334f7df2e56Smrg 335f7df2e56Smrg if (uidset) { 336f7df2e56Smrg /* User id 0 always gets access */ 337f7df2e56Smrg if (uid == 0) { 338f7df2e56Smrg return 0; 339f7df2e56Smrg } 340f7df2e56Smrg /* Check the owner */ 341f7df2e56Smrg if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { 342f7df2e56Smrg mask = S_IRUSR; 343f7df2e56Smrg if (!readonly) { 344f7df2e56Smrg mask |= S_IWUSR; 345f7df2e56Smrg } 346f7df2e56Smrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 347f7df2e56Smrg } 348f7df2e56Smrg } 349f7df2e56Smrg 350f7df2e56Smrg if (gidset) { 351f7df2e56Smrg /* Check the group */ 352f7df2e56Smrg if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { 353f7df2e56Smrg mask = S_IRGRP; 354f7df2e56Smrg if (!readonly) { 355f7df2e56Smrg mask |= S_IWGRP; 356f7df2e56Smrg } 357f7df2e56Smrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 358f7df2e56Smrg } 359f7df2e56Smrg } 36005b261ecSmrg } 36105b261ecSmrg /* Otherwise, check everyone else */ 36205b261ecSmrg mask = S_IROTH; 36305b261ecSmrg if (!readonly) { 364f7df2e56Smrg mask |= S_IWOTH; 36505b261ecSmrg } 3664642e01fSmrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 36705b261ecSmrg} 36805b261ecSmrg 36905b261ecSmrgstatic int 3704642e01fSmrgProcShmAttach(ClientPtr client) 37105b261ecSmrg{ 3724642e01fSmrg SHMSTAT_TYPE buf; 37305b261ecSmrg ShmDescPtr shmdesc; 374f7df2e56Smrg 37505b261ecSmrg REQUEST(xShmAttachReq); 37605b261ecSmrg 37705b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 37805b261ecSmrg LEGAL_NEW_RESOURCE(stuff->shmseg, client); 379f7df2e56Smrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 380f7df2e56Smrg client->errorValue = stuff->readOnly; 3814202a189Smrg return BadValue; 38205b261ecSmrg } 383f7df2e56Smrg for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) { 384f7df2e56Smrg if (!SHMDESC_IS_FD(shmdesc) && shmdesc->shmid == stuff->shmid) 385f7df2e56Smrg break; 38605b261ecSmrg } 387f7df2e56Smrg if (shmdesc) { 388f7df2e56Smrg if (!stuff->readOnly && !shmdesc->writable) 389f7df2e56Smrg return BadAccess; 390f7df2e56Smrg shmdesc->refcnt++; 391f7df2e56Smrg } 392f7df2e56Smrg else { 393f7df2e56Smrg shmdesc = malloc(sizeof(ShmDescRec)); 394f7df2e56Smrg if (!shmdesc) 395f7df2e56Smrg return BadAlloc; 396f7df2e56Smrg#ifdef SHM_FD_PASSING 397f7df2e56Smrg shmdesc->is_fd = FALSE; 398f7df2e56Smrg#endif 399f7df2e56Smrg shmdesc->addr = shmat(stuff->shmid, 0, 400f7df2e56Smrg stuff->readOnly ? SHM_RDONLY : 0); 401f7df2e56Smrg if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) { 402f7df2e56Smrg free(shmdesc); 403f7df2e56Smrg return BadAccess; 404f7df2e56Smrg } 405f7df2e56Smrg 406f7df2e56Smrg /* The attach was performed with root privs. We must 407f7df2e56Smrg * do manual checking of access rights for the credentials 408f7df2e56Smrg * of the client */ 409f7df2e56Smrg 410f7df2e56Smrg if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { 411f7df2e56Smrg shmdt(shmdesc->addr); 412f7df2e56Smrg free(shmdesc); 413f7df2e56Smrg return BadAccess; 414f7df2e56Smrg } 415f7df2e56Smrg 416f7df2e56Smrg shmdesc->shmid = stuff->shmid; 417f7df2e56Smrg shmdesc->refcnt = 1; 418f7df2e56Smrg shmdesc->writable = !stuff->readOnly; 419f7df2e56Smrg shmdesc->size = SHM_SEGSZ(buf); 420f7df2e56Smrg shmdesc->next = Shmsegs; 421f7df2e56Smrg Shmsegs = shmdesc; 42205b261ecSmrg } 423f7df2e56Smrg if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) 424f7df2e56Smrg return BadAlloc; 4254202a189Smrg return Success; 42605b261ecSmrg} 42705b261ecSmrg 428f7df2e56Smrg /*ARGSUSED*/ static int 429f7df2e56SmrgShmDetachSegment(void *value, /* must conform to DeleteType */ 430f7df2e56Smrg XID unused) 43105b261ecSmrg{ 432f7df2e56Smrg ShmDescPtr shmdesc = (ShmDescPtr) value; 43305b261ecSmrg ShmDescPtr *prev; 43405b261ecSmrg 43505b261ecSmrg if (--shmdesc->refcnt) 436f7df2e56Smrg return TRUE; 437f7df2e56Smrg#if SHM_FD_PASSING 438f7df2e56Smrg if (shmdesc->is_fd) { 439f7df2e56Smrg if (shmdesc->busfault) 440f7df2e56Smrg busfault_unregister(shmdesc->busfault); 441f7df2e56Smrg munmap(shmdesc->addr, shmdesc->size); 442f7df2e56Smrg } else 443f7df2e56Smrg#endif 444f7df2e56Smrg shmdt(shmdesc->addr); 445f7df2e56Smrg for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next); 44605b261ecSmrg *prev = shmdesc->next; 4474202a189Smrg free(shmdesc); 44805b261ecSmrg return Success; 44905b261ecSmrg} 45005b261ecSmrg 45105b261ecSmrgstatic int 4524642e01fSmrgProcShmDetach(ClientPtr client) 45305b261ecSmrg{ 45405b261ecSmrg ShmDescPtr shmdesc; 455f7df2e56Smrg 45605b261ecSmrg REQUEST(xShmDetachReq); 45705b261ecSmrg 45805b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 45905b261ecSmrg VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); 46005b261ecSmrg FreeResource(stuff->shmseg, RT_NONE); 4614202a189Smrg return Success; 46205b261ecSmrg} 46305b261ecSmrg 4644642e01fSmrg/* 4654642e01fSmrg * If the given request doesn't exactly match PutImage's constraints, 4664642e01fSmrg * wrap the image in a scratch pixmap header and let CopyArea sort it out. 4674642e01fSmrg */ 46805b261ecSmrgstatic void 4694642e01fSmrgdoShmPutImage(DrawablePtr dst, GCPtr pGC, 470f7df2e56Smrg int depth, unsigned int format, 471f7df2e56Smrg int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, 472f7df2e56Smrg char *data) 47305b261ecSmrg{ 4744642e01fSmrg PixmapPtr pPixmap; 4754202a189Smrg 47645bb0b75Smrg if (format == ZPixmap || (format == XYPixmap && depth == 1)) { 477f7df2e56Smrg pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, 478f7df2e56Smrg BitsPerPixel(depth), 479f7df2e56Smrg PixmapBytePad(w, depth), data); 480f7df2e56Smrg if (!pPixmap) 481f7df2e56Smrg return; 482f7df2e56Smrg pGC->ops->CopyArea((DrawablePtr) pPixmap, dst, pGC, sx, sy, sw, sh, dx, 483f7df2e56Smrg dy); 484f7df2e56Smrg FreeScratchPixmapHeader(pPixmap); 485f7df2e56Smrg } 486f7df2e56Smrg else { 487f7df2e56Smrg GCPtr putGC = GetScratchGC(depth, dst->pScreen); 488f7df2e56Smrg 489f7df2e56Smrg if (!putGC) 490f7df2e56Smrg return; 491f7df2e56Smrg 492f7df2e56Smrg pPixmap = (*dst->pScreen->CreatePixmap) (dst->pScreen, sw, sh, depth, 493f7df2e56Smrg CREATE_PIXMAP_USAGE_SCRATCH); 494f7df2e56Smrg if (!pPixmap) { 495f7df2e56Smrg FreeScratchGC(putGC); 496f7df2e56Smrg return; 497f7df2e56Smrg } 498f7df2e56Smrg ValidateGC(&pPixmap->drawable, putGC); 499f7df2e56Smrg (*putGC->ops->PutImage) (&pPixmap->drawable, putGC, depth, -sx, -sy, w, 500f7df2e56Smrg h, 0, 501f7df2e56Smrg (format == XYPixmap) ? XYPixmap : ZPixmap, 502f7df2e56Smrg data); 503f7df2e56Smrg FreeScratchGC(putGC); 504f7df2e56Smrg if (format == XYBitmap) 505f7df2e56Smrg (void) (*pGC->ops->CopyPlane) (&pPixmap->drawable, dst, pGC, 0, 0, 506f7df2e56Smrg sw, sh, dx, dy, 1L); 507f7df2e56Smrg else 508f7df2e56Smrg (void) (*pGC->ops->CopyArea) (&pPixmap->drawable, dst, pGC, 0, 0, 509f7df2e56Smrg sw, sh, dx, dy); 510f7df2e56Smrg (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); 5114202a189Smrg } 51205b261ecSmrg} 51305b261ecSmrg 51465b04b38Smrgstatic int 51565b04b38SmrgProcShmPutImage(ClientPtr client) 51605b261ecSmrg{ 51765b04b38Smrg GCPtr pGC; 51865b04b38Smrg DrawablePtr pDraw; 51965b04b38Smrg long length; 52065b04b38Smrg ShmDescPtr shmdesc; 521f7df2e56Smrg 52205b261ecSmrg REQUEST(xShmPutImageReq); 52365b04b38Smrg 52405b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 52565b04b38Smrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 52665b04b38Smrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); 52765b04b38Smrg if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) 528f7df2e56Smrg return BadValue; 529f7df2e56Smrg if (stuff->format == XYBitmap) { 53065b04b38Smrg if (stuff->depth != 1) 53165b04b38Smrg return BadMatch; 53265b04b38Smrg length = PixmapBytePad(stuff->totalWidth, 1); 53365b04b38Smrg } 534f7df2e56Smrg else if (stuff->format == XYPixmap) { 53565b04b38Smrg if (pDraw->depth != stuff->depth) 53665b04b38Smrg return BadMatch; 53765b04b38Smrg length = PixmapBytePad(stuff->totalWidth, 1); 538f7df2e56Smrg length *= stuff->depth; 53965b04b38Smrg } 540f7df2e56Smrg else if (stuff->format == ZPixmap) { 54165b04b38Smrg if (pDraw->depth != stuff->depth) 54265b04b38Smrg return BadMatch; 54365b04b38Smrg length = PixmapBytePad(stuff->totalWidth, stuff->depth); 54465b04b38Smrg } 545f7df2e56Smrg else { 546f7df2e56Smrg client->errorValue = stuff->format; 54765b04b38Smrg return BadValue; 54865b04b38Smrg } 54905b261ecSmrg 55065b04b38Smrg /* 55165b04b38Smrg * There's a potential integer overflow in this check: 55265b04b38Smrg * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, 55365b04b38Smrg * client); 55465b04b38Smrg * the version below ought to avoid it 55565b04b38Smrg */ 55665b04b38Smrg if (stuff->totalHeight != 0 && 557f7df2e56Smrg length > (shmdesc->size - stuff->offset) / stuff->totalHeight) { 558f7df2e56Smrg client->errorValue = stuff->totalWidth; 559f7df2e56Smrg return BadValue; 56065b04b38Smrg } 561f7df2e56Smrg if (stuff->srcX > stuff->totalWidth) { 562f7df2e56Smrg client->errorValue = stuff->srcX; 563f7df2e56Smrg return BadValue; 56465b04b38Smrg } 565f7df2e56Smrg if (stuff->srcY > stuff->totalHeight) { 566f7df2e56Smrg client->errorValue = stuff->srcY; 567f7df2e56Smrg return BadValue; 56865b04b38Smrg } 569f7df2e56Smrg if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) { 570f7df2e56Smrg client->errorValue = stuff->srcWidth; 571f7df2e56Smrg return BadValue; 57265b04b38Smrg } 573f7df2e56Smrg if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) { 574f7df2e56Smrg client->errorValue = stuff->srcHeight; 575f7df2e56Smrg return BadValue; 57665b04b38Smrg } 57705b261ecSmrg 57865b04b38Smrg if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || 579f7df2e56Smrg ((stuff->format != ZPixmap) && 580f7df2e56Smrg (stuff->srcX < screenInfo.bitmapScanlinePad) && 581f7df2e56Smrg ((stuff->format == XYBitmap) || 582f7df2e56Smrg ((stuff->srcY == 0) && 583f7df2e56Smrg (stuff->srcHeight == stuff->totalHeight))))) && 584f7df2e56Smrg ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) 585f7df2e56Smrg (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, 586f7df2e56Smrg stuff->dstX, stuff->dstY, 587f7df2e56Smrg stuff->totalWidth, stuff->srcHeight, 588f7df2e56Smrg stuff->srcX, stuff->format, 589f7df2e56Smrg shmdesc->addr + stuff->offset + 590f7df2e56Smrg (stuff->srcY * length)); 59165b04b38Smrg else 592f7df2e56Smrg doShmPutImage(pDraw, pGC, stuff->depth, stuff->format, 593f7df2e56Smrg stuff->totalWidth, stuff->totalHeight, 594f7df2e56Smrg stuff->srcX, stuff->srcY, 595f7df2e56Smrg stuff->srcWidth, stuff->srcHeight, 596f7df2e56Smrg stuff->dstX, stuff->dstY, shmdesc->addr + stuff->offset); 597f7df2e56Smrg 598f7df2e56Smrg if (stuff->sendEvent) { 599f7df2e56Smrg xShmCompletionEvent ev = { 600f7df2e56Smrg .type = ShmCompletionCode, 601f7df2e56Smrg .drawable = stuff->drawable, 602f7df2e56Smrg .minorEvent = X_ShmPutImage, 603f7df2e56Smrg .majorEvent = ShmReqCode, 604f7df2e56Smrg .shmseg = stuff->shmseg, 605f7df2e56Smrg .offset = stuff->offset 606f7df2e56Smrg }; 607f7df2e56Smrg WriteEventsToClient(client, 1, (xEvent *) &ev); 60805b261ecSmrg } 60965b04b38Smrg 61065b04b38Smrg return Success; 61105b261ecSmrg} 61205b261ecSmrg 61365b04b38Smrgstatic int 61465b04b38SmrgProcShmGetImage(ClientPtr client) 61505b261ecSmrg{ 616f7df2e56Smrg DrawablePtr pDraw; 617f7df2e56Smrg long lenPer = 0, length; 618f7df2e56Smrg Mask plane = 0; 619f7df2e56Smrg xShmGetImageReply xgi; 620f7df2e56Smrg ShmDescPtr shmdesc; 621f7df2e56Smrg VisualID visual = None; 622f7df2e56Smrg RegionPtr pVisibleRegion = NULL; 623f7df2e56Smrg int rc; 62405b261ecSmrg 62505b261ecSmrg REQUEST(xShmGetImageReq); 62605b261ecSmrg 62705b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 628f7df2e56Smrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 629f7df2e56Smrg client->errorValue = stuff->format; 6304202a189Smrg return BadValue; 63105b261ecSmrg } 632f7df2e56Smrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess); 63305b261ecSmrg if (rc != Success) 634f7df2e56Smrg return rc; 63505b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 636f7df2e56Smrg if (pDraw->type == DRAWABLE_WINDOW) { 637f7df2e56Smrg if ( /* check for being viewable */ 638f7df2e56Smrg !((WindowPtr) pDraw)->realized || 639f7df2e56Smrg /* check for being on screen */ 640f7df2e56Smrg pDraw->x + stuff->x < 0 || 641f7df2e56Smrg pDraw->x + stuff->x + (int) stuff->width > pDraw->pScreen->width 642f7df2e56Smrg || pDraw->y + stuff->y < 0 || 643f7df2e56Smrg pDraw->y + stuff->y + (int) stuff->height > 644f7df2e56Smrg pDraw->pScreen->height || 645f7df2e56Smrg /* check for being inside of border */ 646f7df2e56Smrg stuff->x < -wBorderWidth((WindowPtr) pDraw) || 647f7df2e56Smrg stuff->x + (int) stuff->width > 648f7df2e56Smrg wBorderWidth((WindowPtr) pDraw) + (int) pDraw->width || 649f7df2e56Smrg stuff->y < -wBorderWidth((WindowPtr) pDraw) || 650f7df2e56Smrg stuff->y + (int) stuff->height > 651f7df2e56Smrg wBorderWidth((WindowPtr) pDraw) + (int) pDraw->height) 652f7df2e56Smrg return BadMatch; 653f7df2e56Smrg visual = wVisual(((WindowPtr) pDraw)); 654f7df2e56Smrg pVisibleRegion = NotClippedByChildren((WindowPtr) pDraw); 655f7df2e56Smrg if (pVisibleRegion) 656f7df2e56Smrg RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y); 65765b04b38Smrg } 658f7df2e56Smrg else { 659f7df2e56Smrg if (stuff->x < 0 || 660f7df2e56Smrg stuff->x + (int) stuff->width > pDraw->width || 661f7df2e56Smrg stuff->y < 0 || stuff->y + (int) stuff->height > pDraw->height) 662f7df2e56Smrg return BadMatch; 663f7df2e56Smrg visual = None; 66465b04b38Smrg } 665f7df2e56Smrg xgi = (xShmGetImageReply) { 666f7df2e56Smrg .type = X_Reply, 667f7df2e56Smrg .sequenceNumber = client->sequence, 668f7df2e56Smrg .length = 0, 669f7df2e56Smrg .visual = visual, 670f7df2e56Smrg .depth = pDraw->depth 671f7df2e56Smrg }; 672f7df2e56Smrg if (stuff->format == ZPixmap) { 673f7df2e56Smrg length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; 674f7df2e56Smrg } 675f7df2e56Smrg else { 676f7df2e56Smrg lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; 677f7df2e56Smrg plane = ((Mask) 1) << (pDraw->depth - 1); 678f7df2e56Smrg /* only planes asked for */ 679f7df2e56Smrg length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); 68065b04b38Smrg } 68165b04b38Smrg 68265b04b38Smrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 68365b04b38Smrg xgi.size = length; 68465b04b38Smrg 685f7df2e56Smrg if (length == 0) { 686f7df2e56Smrg /* nothing to do */ 68765b04b38Smrg } 688f7df2e56Smrg else if (stuff->format == ZPixmap) { 689f7df2e56Smrg (*pDraw->pScreen->GetImage) (pDraw, stuff->x, stuff->y, 690f7df2e56Smrg stuff->width, stuff->height, 691f7df2e56Smrg stuff->format, stuff->planeMask, 692f7df2e56Smrg shmdesc->addr + stuff->offset); 693f7df2e56Smrg if (pVisibleRegion) 694f7df2e56Smrg XaceCensorImage(client, pVisibleRegion, 695f7df2e56Smrg PixmapBytePad(stuff->width, pDraw->depth), pDraw, 696f7df2e56Smrg stuff->x, stuff->y, stuff->width, stuff->height, 697f7df2e56Smrg stuff->format, shmdesc->addr + stuff->offset); 69865b04b38Smrg } 699f7df2e56Smrg else { 70065b04b38Smrg 701f7df2e56Smrg length = stuff->offset; 702f7df2e56Smrg for (; plane; plane >>= 1) { 703f7df2e56Smrg if (stuff->planeMask & plane) { 704f7df2e56Smrg (*pDraw->pScreen->GetImage) (pDraw, 705f7df2e56Smrg stuff->x, stuff->y, 706f7df2e56Smrg stuff->width, stuff->height, 707f7df2e56Smrg stuff->format, plane, 708f7df2e56Smrg shmdesc->addr + length); 709f7df2e56Smrg if (pVisibleRegion) 710f7df2e56Smrg XaceCensorImage(client, pVisibleRegion, 711f7df2e56Smrg BitmapBytePad(stuff->width), pDraw, 712f7df2e56Smrg stuff->x, stuff->y, stuff->width, stuff->height, 713f7df2e56Smrg stuff->format, shmdesc->addr + length); 714f7df2e56Smrg length += lenPer; 715f7df2e56Smrg } 716f7df2e56Smrg } 71765b04b38Smrg } 71865b04b38Smrg 719f7df2e56Smrg if (pVisibleRegion) 720f7df2e56Smrg RegionDestroy(pVisibleRegion); 721f7df2e56Smrg 72265b04b38Smrg if (client->swapped) { 723f7df2e56Smrg swaps(&xgi.sequenceNumber); 724f7df2e56Smrg swapl(&xgi.length); 725f7df2e56Smrg swapl(&xgi.visual); 726f7df2e56Smrg swapl(&xgi.size); 72765b04b38Smrg } 728f7df2e56Smrg WriteToClient(client, sizeof(xShmGetImageReply), &xgi); 72965b04b38Smrg 73065b04b38Smrg return Success; 73165b04b38Smrg} 73265b04b38Smrg 73365b04b38Smrg#ifdef PANORAMIX 734f7df2e56Smrgstatic int 73565b04b38SmrgProcPanoramiXShmPutImage(ClientPtr client) 73665b04b38Smrg{ 737f7df2e56Smrg int j, result, orig_x, orig_y; 738f7df2e56Smrg PanoramiXRes *draw, *gc; 739f7df2e56Smrg Bool sendEvent, isRoot; 74065b04b38Smrg 74165b04b38Smrg REQUEST(xShmPutImageReq); 74265b04b38Smrg REQUEST_SIZE_MATCH(xShmPutImageReq); 74365b04b38Smrg 744f7df2e56Smrg result = dixLookupResourceByClass((void **) &draw, stuff->drawable, 745f7df2e56Smrg XRC_DRAWABLE, client, DixWriteAccess); 74665b04b38Smrg if (result != Success) 74765b04b38Smrg return (result == BadValue) ? BadDrawable : result; 74865b04b38Smrg 749f7df2e56Smrg result = dixLookupResourceByType((void **) &gc, stuff->gc, 750f7df2e56Smrg XRT_GC, client, DixReadAccess); 75165b04b38Smrg if (result != Success) 75265b04b38Smrg return result; 75365b04b38Smrg 75465b04b38Smrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 75565b04b38Smrg 75665b04b38Smrg orig_x = stuff->dstX; 75765b04b38Smrg orig_y = stuff->dstY; 75865b04b38Smrg sendEvent = stuff->sendEvent; 75965b04b38Smrg stuff->sendEvent = 0; 76065b04b38Smrg FOR_NSCREENS(j) { 761f7df2e56Smrg if (!j) 762f7df2e56Smrg stuff->sendEvent = sendEvent; 763f7df2e56Smrg stuff->drawable = draw->info[j].id; 764f7df2e56Smrg stuff->gc = gc->info[j].id; 765f7df2e56Smrg if (isRoot) { 766f7df2e56Smrg stuff->dstX = orig_x - screenInfo.screens[j]->x; 767f7df2e56Smrg stuff->dstY = orig_y - screenInfo.screens[j]->y; 768f7df2e56Smrg } 769f7df2e56Smrg result = ProcShmPutImage(client); 770f7df2e56Smrg if (result != Success) 771f7df2e56Smrg break; 77265b04b38Smrg } 77365b04b38Smrg return result; 77465b04b38Smrg} 77565b04b38Smrg 776f7df2e56Smrgstatic int 77765b04b38SmrgProcPanoramiXShmGetImage(ClientPtr client) 77865b04b38Smrg{ 779f7df2e56Smrg PanoramiXRes *draw; 780f7df2e56Smrg DrawablePtr *drawables; 781f7df2e56Smrg DrawablePtr pDraw; 782f7df2e56Smrg xShmGetImageReply xgi; 783f7df2e56Smrg ShmDescPtr shmdesc; 784f7df2e56Smrg int i, x, y, w, h, format, rc; 785f7df2e56Smrg Mask plane = 0, planemask; 786f7df2e56Smrg long lenPer = 0, length, widthBytesLine; 787f7df2e56Smrg Bool isRoot; 78865b04b38Smrg 78965b04b38Smrg REQUEST(xShmGetImageReq); 79065b04b38Smrg 79165b04b38Smrg REQUEST_SIZE_MATCH(xShmGetImageReq); 79265b04b38Smrg 79365b04b38Smrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 794f7df2e56Smrg client->errorValue = stuff->format; 79565b04b38Smrg return BadValue; 79665b04b38Smrg } 79765b04b38Smrg 798f7df2e56Smrg rc = dixLookupResourceByClass((void **) &draw, stuff->drawable, 799f7df2e56Smrg XRC_DRAWABLE, client, DixWriteAccess); 80065b04b38Smrg if (rc != Success) 801f7df2e56Smrg return (rc == BadValue) ? BadDrawable : rc; 80265b04b38Smrg 80365b04b38Smrg if (draw->type == XRT_PIXMAP) 804f7df2e56Smrg return ProcShmGetImage(client); 80565b04b38Smrg 806f7df2e56Smrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess); 80765b04b38Smrg if (rc != Success) 808f7df2e56Smrg return rc; 80965b04b38Smrg 81065b04b38Smrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 81165b04b38Smrg 81265b04b38Smrg x = stuff->x; 81365b04b38Smrg y = stuff->y; 81465b04b38Smrg w = stuff->width; 81565b04b38Smrg h = stuff->height; 81665b04b38Smrg format = stuff->format; 81765b04b38Smrg planemask = stuff->planeMask; 81865b04b38Smrg 81965b04b38Smrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 82065b04b38Smrg 821f7df2e56Smrg if (isRoot) { 822f7df2e56Smrg if ( /* check for being onscreen */ 823f7df2e56Smrg x < 0 || x + w > PanoramiXPixWidth || 824f7df2e56Smrg y < 0 || y + h > PanoramiXPixHeight) 825f7df2e56Smrg return BadMatch; 826f7df2e56Smrg } 827f7df2e56Smrg else { 828f7df2e56Smrg if ( /* check for being onscreen */ 829f7df2e56Smrg screenInfo.screens[0]->x + pDraw->x + x < 0 || 830f7df2e56Smrg screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth 831f7df2e56Smrg || screenInfo.screens[0]->y + pDraw->y + y < 0 || 832f7df2e56Smrg screenInfo.screens[0]->y + pDraw->y + y + h > PanoramiXPixHeight 833f7df2e56Smrg || 834f7df2e56Smrg /* check for being inside of border */ 835f7df2e56Smrg x < -wBorderWidth((WindowPtr) pDraw) || 836f7df2e56Smrg x + w > wBorderWidth((WindowPtr) pDraw) + (int) pDraw->width || 837f7df2e56Smrg y < -wBorderWidth((WindowPtr) pDraw) || 838f7df2e56Smrg y + h > wBorderWidth((WindowPtr) pDraw) + (int) pDraw->height) 839f7df2e56Smrg return BadMatch; 84065b04b38Smrg } 84165b04b38Smrg 8424202a189Smrg drawables = calloc(PanoramiXNumScreens, sizeof(DrawablePtr)); 843f7df2e56Smrg if (!drawables) 844f7df2e56Smrg return BadAlloc; 8454202a189Smrg 84605b261ecSmrg drawables[0] = pDraw; 847f7df2e56Smrg FOR_NSCREENS_FORWARD_SKIP(i) { 848f7df2e56Smrg rc = dixLookupDrawable(drawables + i, draw->info[i].id, client, 0, 849f7df2e56Smrg DixReadAccess); 850f7df2e56Smrg if (rc != Success) { 851f7df2e56Smrg free(drawables); 852f7df2e56Smrg return rc; 853f7df2e56Smrg } 85405b261ecSmrg } 85505b261ecSmrg 856f7df2e56Smrg xgi = (xShmGetImageReply) { 857f7df2e56Smrg .type = X_Reply, 858f7df2e56Smrg .sequenceNumber = client->sequence, 859f7df2e56Smrg .length = 0, 860f7df2e56Smrg .visual = wVisual(((WindowPtr) pDraw)), 861f7df2e56Smrg .depth = pDraw->depth 862f7df2e56Smrg }; 863f7df2e56Smrg 864f7df2e56Smrg if (format == ZPixmap) { 865f7df2e56Smrg widthBytesLine = PixmapBytePad(w, pDraw->depth); 866f7df2e56Smrg length = widthBytesLine * h; 867f7df2e56Smrg } 868f7df2e56Smrg else { 869f7df2e56Smrg widthBytesLine = PixmapBytePad(w, 1); 870f7df2e56Smrg lenPer = widthBytesLine * h; 871f7df2e56Smrg plane = ((Mask) 1) << (pDraw->depth - 1); 872f7df2e56Smrg length = lenPer * Ones(planemask & (plane | (plane - 1))); 87305b261ecSmrg } 87405b261ecSmrg 87505b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 87605b261ecSmrg xgi.size = length; 87705b261ecSmrg 878f7df2e56Smrg if (length == 0) { /* nothing to do */ 879f7df2e56Smrg } 88005b261ecSmrg else if (format == ZPixmap) { 881f7df2e56Smrg XineramaGetImageData(drawables, x, y, w, h, format, planemask, 882f7df2e56Smrg shmdesc->addr + stuff->offset, 883f7df2e56Smrg widthBytesLine, isRoot); 884f7df2e56Smrg } 885f7df2e56Smrg else { 88605b261ecSmrg 887f7df2e56Smrg length = stuff->offset; 88805b261ecSmrg for (; plane; plane >>= 1) { 889f7df2e56Smrg if (planemask & plane) { 890f7df2e56Smrg XineramaGetImageData(drawables, x, y, w, h, 891f7df2e56Smrg format, plane, shmdesc->addr + length, 892f7df2e56Smrg widthBytesLine, isRoot); 893f7df2e56Smrg length += lenPer; 894f7df2e56Smrg } 895f7df2e56Smrg } 89605b261ecSmrg } 8974202a189Smrg free(drawables); 898f7df2e56Smrg 89905b261ecSmrg if (client->swapped) { 900f7df2e56Smrg swaps(&xgi.sequenceNumber); 901f7df2e56Smrg swapl(&xgi.length); 902f7df2e56Smrg swapl(&xgi.visual); 903f7df2e56Smrg swapl(&xgi.size); 90405b261ecSmrg } 905f7df2e56Smrg WriteToClient(client, sizeof(xShmGetImageReply), &xgi); 90605b261ecSmrg 9074202a189Smrg return Success; 90805b261ecSmrg} 90905b261ecSmrg 91005b261ecSmrgstatic int 9114642e01fSmrgProcPanoramiXShmCreatePixmap(ClientPtr client) 91205b261ecSmrg{ 91305b261ecSmrg ScreenPtr pScreen = NULL; 91405b261ecSmrg PixmapPtr pMap = NULL; 91505b261ecSmrg DrawablePtr pDraw; 91605b261ecSmrg DepthPtr pDepth; 91705b261ecSmrg int i, j, result, rc; 91805b261ecSmrg ShmDescPtr shmdesc; 919f7df2e56Smrg 92005b261ecSmrg REQUEST(xShmCreatePixmapReq); 92105b261ecSmrg unsigned int width, height, depth; 92205b261ecSmrg unsigned long size; 92305b261ecSmrg PanoramiXRes *newPix; 92405b261ecSmrg 92505b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 92605b261ecSmrg client->errorValue = stuff->pid; 92705b261ecSmrg if (!sharedPixmaps) 928f7df2e56Smrg return BadImplementation; 92905b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 93005b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 931f7df2e56Smrg DixGetAttrAccess); 93205b261ecSmrg if (rc != Success) 933f7df2e56Smrg return rc; 93405b261ecSmrg 93505b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 93605b261ecSmrg 93705b261ecSmrg width = stuff->width; 93805b261ecSmrg height = stuff->height; 93905b261ecSmrg depth = stuff->depth; 940f7df2e56Smrg if (!width || !height || !depth) { 941f7df2e56Smrg client->errorValue = 0; 94205b261ecSmrg return BadValue; 94305b261ecSmrg } 94405b261ecSmrg if (width > 32767 || height > 32767) 94505b261ecSmrg return BadAlloc; 94605b261ecSmrg 947f7df2e56Smrg if (stuff->depth != 1) { 94805b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 949f7df2e56Smrg for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 950f7df2e56Smrg if (pDepth->depth == stuff->depth) 951f7df2e56Smrg goto CreatePmap; 952f7df2e56Smrg client->errorValue = stuff->depth; 95305b261ecSmrg return BadValue; 95405b261ecSmrg } 95505b261ecSmrg 956f7df2e56Smrg CreatePmap: 95705b261ecSmrg size = PixmapBytePad(width, depth) * height; 95805b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 95905b261ecSmrg if (size < width * height) 96005b261ecSmrg return BadAlloc; 96105b261ecSmrg } 96205b261ecSmrg /* thankfully, offset is unsigned */ 96305b261ecSmrg if (stuff->offset + size < size) 964f7df2e56Smrg return BadAlloc; 96505b261ecSmrg 96605b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 96705b261ecSmrg 968f7df2e56Smrg if (!(newPix = malloc(sizeof(PanoramiXRes)))) 969f7df2e56Smrg return BadAlloc; 97005b261ecSmrg 97105b261ecSmrg newPix->type = XRT_PIXMAP; 97205b261ecSmrg newPix->u.pix.shared = TRUE; 973f7df2e56Smrg panoramix_setup_ids(newPix, client, stuff->pid); 97405b261ecSmrg 9754202a189Smrg result = Success; 97605b261ecSmrg 97705b261ecSmrg FOR_NSCREENS(j) { 978f7df2e56Smrg ShmScrPrivateRec *screen_priv; 979f7df2e56Smrg 980f7df2e56Smrg pScreen = screenInfo.screens[j]; 981f7df2e56Smrg 982f7df2e56Smrg screen_priv = ShmGetScreenPriv(pScreen); 983f7df2e56Smrg pMap = (*screen_priv->shmFuncs->CreatePixmap) (pScreen, 984f7df2e56Smrg stuff->width, 985f7df2e56Smrg stuff->height, 986f7df2e56Smrg stuff->depth, 987f7df2e56Smrg shmdesc->addr + 988f7df2e56Smrg stuff->offset); 989f7df2e56Smrg 990f7df2e56Smrg if (pMap) { 991f7df2e56Smrg result = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, 992f7df2e56Smrg RT_PIXMAP, pMap, RT_NONE, NULL, DixCreateAccess); 993f7df2e56Smrg if (result != Success) { 994f7df2e56Smrg pDraw->pScreen->DestroyPixmap(pMap); 995f7df2e56Smrg return result; 996f7df2e56Smrg } 997f7df2e56Smrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc); 99805b261ecSmrg shmdesc->refcnt++; 999f7df2e56Smrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1000f7df2e56Smrg pMap->drawable.id = newPix->info[j].id; 1001f7df2e56Smrg if (!AddResource(newPix->info[j].id, RT_PIXMAP, (void *) pMap)) { 1002f7df2e56Smrg result = BadAlloc; 1003f7df2e56Smrg break; 1004f7df2e56Smrg } 1005f7df2e56Smrg } 1006f7df2e56Smrg else { 1007f7df2e56Smrg result = BadAlloc; 1008f7df2e56Smrg break; 1009f7df2e56Smrg } 101005b261ecSmrg } 101105b261ecSmrg 1012f7df2e56Smrg if (result == BadAlloc) { 1013f7df2e56Smrg while (j--) 1014f7df2e56Smrg FreeResource(newPix->info[j].id, RT_NONE); 1015f7df2e56Smrg free(newPix); 1016f7df2e56Smrg } 1017f7df2e56Smrg else 1018f7df2e56Smrg AddResource(stuff->pid, XRT_PIXMAP, newPix); 101905b261ecSmrg 102005b261ecSmrg return result; 102105b261ecSmrg} 102205b261ecSmrg#endif 102305b261ecSmrg 102405b261ecSmrgstatic PixmapPtr 1025f7df2e56SmrgfbShmCreatePixmap(ScreenPtr pScreen, 1026f7df2e56Smrg int width, int height, int depth, char *addr) 102705b261ecSmrg{ 10284642e01fSmrg PixmapPtr pPixmap; 102905b261ecSmrg 1030f7df2e56Smrg pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth, 0); 103105b261ecSmrg if (!pPixmap) 1032f7df2e56Smrg return NullPixmap; 1033f7df2e56Smrg 1034f7df2e56Smrg if (!(*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth, 1035f7df2e56Smrg BitsPerPixel(depth), 1036f7df2e56Smrg PixmapBytePad(width, depth), 1037f7df2e56Smrg (void *) addr)) { 1038f7df2e56Smrg (*pScreen->DestroyPixmap) (pPixmap); 1039f7df2e56Smrg return NullPixmap; 104005b261ecSmrg } 104105b261ecSmrg return pPixmap; 104205b261ecSmrg} 104305b261ecSmrg 104405b261ecSmrgstatic int 10454642e01fSmrgProcShmCreatePixmap(ClientPtr client) 104605b261ecSmrg{ 104705b261ecSmrg PixmapPtr pMap; 104805b261ecSmrg DrawablePtr pDraw; 104905b261ecSmrg DepthPtr pDepth; 10504642e01fSmrg int i, rc; 105105b261ecSmrg ShmDescPtr shmdesc; 10524202a189Smrg ShmScrPrivateRec *screen_priv; 1053f7df2e56Smrg 105405b261ecSmrg REQUEST(xShmCreatePixmapReq); 105505b261ecSmrg unsigned int width, height, depth; 105605b261ecSmrg unsigned long size; 105705b261ecSmrg 105805b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 105905b261ecSmrg client->errorValue = stuff->pid; 106005b261ecSmrg if (!sharedPixmaps) 1061f7df2e56Smrg return BadImplementation; 106205b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 106305b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 1064f7df2e56Smrg DixGetAttrAccess); 106505b261ecSmrg if (rc != Success) 1066f7df2e56Smrg return rc; 106705b261ecSmrg 106805b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 1069f7df2e56Smrg 107005b261ecSmrg width = stuff->width; 107105b261ecSmrg height = stuff->height; 107205b261ecSmrg depth = stuff->depth; 1073f7df2e56Smrg if (!width || !height || !depth) { 1074f7df2e56Smrg client->errorValue = 0; 107505b261ecSmrg return BadValue; 107605b261ecSmrg } 107705b261ecSmrg if (width > 32767 || height > 32767) 1078f7df2e56Smrg return BadAlloc; 107905b261ecSmrg 1080f7df2e56Smrg if (stuff->depth != 1) { 108105b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 1082f7df2e56Smrg for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 1083f7df2e56Smrg if (pDepth->depth == stuff->depth) 1084f7df2e56Smrg goto CreatePmap; 1085f7df2e56Smrg client->errorValue = stuff->depth; 108605b261ecSmrg return BadValue; 108705b261ecSmrg } 108805b261ecSmrg 1089f7df2e56Smrg CreatePmap: 109005b261ecSmrg size = PixmapBytePad(width, depth) * height; 109105b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 1092f7df2e56Smrg if (size < width * height) 1093f7df2e56Smrg return BadAlloc; 109405b261ecSmrg } 109505b261ecSmrg /* thankfully, offset is unsigned */ 109605b261ecSmrg if (stuff->offset + size < size) 1097f7df2e56Smrg return BadAlloc; 109805b261ecSmrg 109905b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 11004202a189Smrg screen_priv = ShmGetScreenPriv(pDraw->pScreen); 1101f7df2e56Smrg pMap = (*screen_priv->shmFuncs->CreatePixmap) (pDraw->pScreen, stuff->width, 1102f7df2e56Smrg stuff->height, stuff->depth, 1103f7df2e56Smrg shmdesc->addr + 1104f7df2e56Smrg stuff->offset); 1105f7df2e56Smrg if (pMap) { 1106f7df2e56Smrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 1107f7df2e56Smrg pMap, RT_NONE, NULL, DixCreateAccess); 1108f7df2e56Smrg if (rc != Success) { 1109f7df2e56Smrg pDraw->pScreen->DestroyPixmap(pMap); 1110f7df2e56Smrg return rc; 1111f7df2e56Smrg } 1112f7df2e56Smrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc); 1113f7df2e56Smrg shmdesc->refcnt++; 1114f7df2e56Smrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1115f7df2e56Smrg pMap->drawable.id = stuff->pid; 1116f7df2e56Smrg if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap)) { 1117f7df2e56Smrg return Success; 1118f7df2e56Smrg } 1119f7df2e56Smrg } 1120f7df2e56Smrg return BadAlloc; 1121f7df2e56Smrg} 1122f7df2e56Smrg 1123f7df2e56Smrg#ifdef SHM_FD_PASSING 1124f7df2e56Smrg 1125f7df2e56Smrgstatic void 1126f7df2e56SmrgShmBusfaultNotify(void *context) 1127f7df2e56Smrg{ 1128f7df2e56Smrg ShmDescPtr shmdesc = context; 1129f7df2e56Smrg 1130f7df2e56Smrg ErrorF("shared memory 0x%x truncated by client\n", 1131f7df2e56Smrg (unsigned int) shmdesc->resource); 1132f7df2e56Smrg busfault_unregister(shmdesc->busfault); 1133f7df2e56Smrg shmdesc->busfault = NULL; 1134f7df2e56Smrg FreeResource (shmdesc->resource, RT_NONE); 1135f7df2e56Smrg} 1136f7df2e56Smrg 1137f7df2e56Smrgstatic int 1138f7df2e56SmrgProcShmAttachFd(ClientPtr client) 1139f7df2e56Smrg{ 1140f7df2e56Smrg int fd; 1141f7df2e56Smrg ShmDescPtr shmdesc; 1142f7df2e56Smrg REQUEST(xShmAttachFdReq); 1143f7df2e56Smrg struct stat statb; 1144f7df2e56Smrg 1145f7df2e56Smrg SetReqFds(client, 1); 1146f7df2e56Smrg REQUEST_SIZE_MATCH(xShmAttachFdReq); 1147f7df2e56Smrg LEGAL_NEW_RESOURCE(stuff->shmseg, client); 1148f7df2e56Smrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 1149f7df2e56Smrg client->errorValue = stuff->readOnly; 1150f7df2e56Smrg return BadValue; 1151f7df2e56Smrg } 1152f7df2e56Smrg fd = ReadFdFromClient(client); 1153f7df2e56Smrg if (fd < 0) 1154f7df2e56Smrg return BadMatch; 1155f7df2e56Smrg 1156f7df2e56Smrg if (fstat(fd, &statb) < 0 || statb.st_size == 0) { 1157f7df2e56Smrg close(fd); 1158f7df2e56Smrg return BadMatch; 1159f7df2e56Smrg } 1160f7df2e56Smrg 1161f7df2e56Smrg shmdesc = malloc(sizeof(ShmDescRec)); 1162f7df2e56Smrg if (!shmdesc) { 1163f7df2e56Smrg close(fd); 1164f7df2e56Smrg return BadAlloc; 1165f7df2e56Smrg } 1166f7df2e56Smrg shmdesc->is_fd = TRUE; 1167f7df2e56Smrg shmdesc->addr = mmap(NULL, statb.st_size, 1168f7df2e56Smrg stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, 1169f7df2e56Smrg MAP_SHARED, 1170f7df2e56Smrg fd, 0); 1171f7df2e56Smrg 1172f7df2e56Smrg close(fd); 1173f7df2e56Smrg if (shmdesc->addr == ((char *) -1)) { 1174f7df2e56Smrg free(shmdesc); 1175f7df2e56Smrg return BadAccess; 1176f7df2e56Smrg } 1177f7df2e56Smrg 1178f7df2e56Smrg shmdesc->refcnt = 1; 1179f7df2e56Smrg shmdesc->writable = !stuff->readOnly; 1180f7df2e56Smrg shmdesc->size = statb.st_size; 1181f7df2e56Smrg shmdesc->resource = stuff->shmseg; 1182f7df2e56Smrg 1183f7df2e56Smrg shmdesc->busfault = busfault_register_mmap(shmdesc->addr, shmdesc->size, ShmBusfaultNotify, shmdesc); 1184f7df2e56Smrg if (!shmdesc->busfault) { 1185f7df2e56Smrg munmap(shmdesc->addr, shmdesc->size); 1186f7df2e56Smrg free(shmdesc); 1187f7df2e56Smrg return BadAlloc; 1188f7df2e56Smrg } 1189f7df2e56Smrg 1190f7df2e56Smrg shmdesc->next = Shmsegs; 1191f7df2e56Smrg Shmsegs = shmdesc; 1192f7df2e56Smrg 1193f7df2e56Smrg if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) 1194f7df2e56Smrg return BadAlloc; 1195f7df2e56Smrg return Success; 1196f7df2e56Smrg} 1197f7df2e56Smrg 1198f7df2e56Smrgstatic int 1199f7df2e56Smrgshm_tmpfile(void) 1200f7df2e56Smrg{ 1201f7df2e56Smrg#ifdef SHMDIR 1202f7df2e56Smrg int fd; 1203f7df2e56Smrg int flags; 1204f7df2e56Smrg char template[] = SHMDIR "/shmfd-XXXXXX"; 1205f7df2e56Smrg#ifdef O_TMPFILE 1206f7df2e56Smrg fd = open(SHMDIR, O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666); 1207f7df2e56Smrg if (fd >= 0) { 1208f7df2e56Smrg ErrorF ("Using O_TMPFILE\n"); 1209f7df2e56Smrg return fd; 12104642e01fSmrg } 1211f7df2e56Smrg ErrorF ("Not using O_TMPFILE\n"); 1212f7df2e56Smrg#endif 1213f7df2e56Smrg fd = mkstemp(template); 1214f7df2e56Smrg if (fd < 0) 1215f7df2e56Smrg return -1; 1216f7df2e56Smrg unlink(template); 1217f7df2e56Smrg if (fcntl(fd, F_GETFD, &flags) >= 0) { 1218f7df2e56Smrg flags |= FD_CLOEXEC; 1219f7df2e56Smrg (void) fcntl(fd, F_SETFD, &flags); 122005b261ecSmrg } 1221f7df2e56Smrg return fd; 1222f7df2e56Smrg#else 1223f7df2e56Smrg return -1; 1224f7df2e56Smrg#endif 1225f7df2e56Smrg} 1226f7df2e56Smrg 1227f7df2e56Smrgstatic int 1228f7df2e56SmrgProcShmCreateSegment(ClientPtr client) 1229f7df2e56Smrg{ 1230f7df2e56Smrg int fd; 1231f7df2e56Smrg ShmDescPtr shmdesc; 1232f7df2e56Smrg REQUEST(xShmCreateSegmentReq); 1233f7df2e56Smrg xShmCreateSegmentReply rep = { 1234f7df2e56Smrg .type = X_Reply, 1235f7df2e56Smrg .nfd = 1, 1236f7df2e56Smrg .sequenceNumber = client->sequence, 1237f7df2e56Smrg .length = 0, 1238f7df2e56Smrg }; 1239f7df2e56Smrg 1240f7df2e56Smrg REQUEST_SIZE_MATCH(xShmCreateSegmentReq); 1241f7df2e56Smrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 1242f7df2e56Smrg client->errorValue = stuff->readOnly; 1243f7df2e56Smrg return BadValue; 124405b261ecSmrg } 1245f7df2e56Smrg fd = shm_tmpfile(); 1246f7df2e56Smrg if (fd < 0) 1247f7df2e56Smrg return BadAlloc; 1248f7df2e56Smrg if (ftruncate(fd, stuff->size) < 0) { 1249f7df2e56Smrg close(fd); 1250f7df2e56Smrg return BadAlloc; 1251f7df2e56Smrg } 1252f7df2e56Smrg shmdesc = malloc(sizeof(ShmDescRec)); 1253f7df2e56Smrg if (!shmdesc) { 1254f7df2e56Smrg close(fd); 1255f7df2e56Smrg return BadAlloc; 1256f7df2e56Smrg } 1257f7df2e56Smrg shmdesc->is_fd = TRUE; 1258f7df2e56Smrg shmdesc->addr = mmap(NULL, stuff->size, 1259f7df2e56Smrg stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, 1260f7df2e56Smrg MAP_SHARED, 1261f7df2e56Smrg fd, 0); 1262f7df2e56Smrg 1263f7df2e56Smrg if (shmdesc->addr == ((char *) -1)) { 1264f7df2e56Smrg close(fd); 1265f7df2e56Smrg free(shmdesc); 1266f7df2e56Smrg return BadAccess; 1267f7df2e56Smrg } 1268f7df2e56Smrg 1269f7df2e56Smrg shmdesc->refcnt = 1; 1270f7df2e56Smrg shmdesc->writable = !stuff->readOnly; 1271f7df2e56Smrg shmdesc->size = stuff->size; 1272f7df2e56Smrg 1273f7df2e56Smrg shmdesc->busfault = busfault_register_mmap(shmdesc->addr, shmdesc->size, ShmBusfaultNotify, shmdesc); 1274f7df2e56Smrg if (!shmdesc->busfault) { 1275f7df2e56Smrg close(fd); 1276f7df2e56Smrg munmap(shmdesc->addr, shmdesc->size); 1277f7df2e56Smrg free(shmdesc); 1278f7df2e56Smrg return BadAlloc; 1279f7df2e56Smrg } 1280f7df2e56Smrg 1281f7df2e56Smrg shmdesc->next = Shmsegs; 1282f7df2e56Smrg Shmsegs = shmdesc; 1283f7df2e56Smrg 1284f7df2e56Smrg if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) { 1285f7df2e56Smrg close(fd); 1286f7df2e56Smrg return BadAlloc; 1287f7df2e56Smrg } 1288f7df2e56Smrg 1289f7df2e56Smrg if (WriteFdToClient(client, fd, TRUE) < 0) { 1290f7df2e56Smrg FreeResource(stuff->shmseg, RT_NONE); 1291f7df2e56Smrg close(fd); 1292f7df2e56Smrg return BadAlloc; 1293f7df2e56Smrg } 1294f7df2e56Smrg WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep); 1295f7df2e56Smrg return Success; 129605b261ecSmrg} 1297f7df2e56Smrg#endif /* SHM_FD_PASSING */ 129805b261ecSmrg 129905b261ecSmrgstatic int 1300f7df2e56SmrgProcShmDispatch(ClientPtr client) 130105b261ecSmrg{ 130205b261ecSmrg REQUEST(xReq); 1303f7df2e56Smrg switch (stuff->data) { 130405b261ecSmrg case X_ShmQueryVersion: 1305f7df2e56Smrg return ProcShmQueryVersion(client); 130605b261ecSmrg case X_ShmAttach: 1307f7df2e56Smrg return ProcShmAttach(client); 130805b261ecSmrg case X_ShmDetach: 1309f7df2e56Smrg return ProcShmDetach(client); 131005b261ecSmrg case X_ShmPutImage: 131105b261ecSmrg#ifdef PANORAMIX 1312f7df2e56Smrg if (!noPanoramiXExtension) 1313f7df2e56Smrg return ProcPanoramiXShmPutImage(client); 131405b261ecSmrg#endif 1315f7df2e56Smrg return ProcShmPutImage(client); 131605b261ecSmrg case X_ShmGetImage: 131705b261ecSmrg#ifdef PANORAMIX 1318f7df2e56Smrg if (!noPanoramiXExtension) 1319f7df2e56Smrg return ProcPanoramiXShmGetImage(client); 132005b261ecSmrg#endif 1321f7df2e56Smrg return ProcShmGetImage(client); 132205b261ecSmrg case X_ShmCreatePixmap: 132305b261ecSmrg#ifdef PANORAMIX 1324f7df2e56Smrg if (!noPanoramiXExtension) 1325f7df2e56Smrg return ProcPanoramiXShmCreatePixmap(client); 1326f7df2e56Smrg#endif 1327f7df2e56Smrg return ProcShmCreatePixmap(client); 1328f7df2e56Smrg#ifdef SHM_FD_PASSING 1329f7df2e56Smrg case X_ShmAttachFd: 1330f7df2e56Smrg return ProcShmAttachFd(client); 1331f7df2e56Smrg case X_ShmCreateSegment: 1332f7df2e56Smrg return ProcShmCreateSegment(client); 133305b261ecSmrg#endif 133405b261ecSmrg default: 1335f7df2e56Smrg return BadRequest; 133605b261ecSmrg } 133705b261ecSmrg} 133805b261ecSmrg 133905b261ecSmrgstatic void 1340f7df2e56SmrgSShmCompletionEvent(xShmCompletionEvent * from, xShmCompletionEvent * to) 134105b261ecSmrg{ 134205b261ecSmrg to->type = from->type; 134305b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 134405b261ecSmrg cpswapl(from->drawable, to->drawable); 134505b261ecSmrg cpswaps(from->minorEvent, to->minorEvent); 134605b261ecSmrg to->majorEvent = from->majorEvent; 134705b261ecSmrg cpswapl(from->shmseg, to->shmseg); 134805b261ecSmrg cpswapl(from->offset, to->offset); 134905b261ecSmrg} 135005b261ecSmrg 135105b261ecSmrgstatic int 13524642e01fSmrgSProcShmQueryVersion(ClientPtr client) 135305b261ecSmrg{ 135405b261ecSmrg REQUEST(xShmQueryVersionReq); 135505b261ecSmrg 1356f7df2e56Smrg swaps(&stuff->length); 135705b261ecSmrg return ProcShmQueryVersion(client); 135805b261ecSmrg} 135905b261ecSmrg 136005b261ecSmrgstatic int 13614642e01fSmrgSProcShmAttach(ClientPtr client) 136205b261ecSmrg{ 136305b261ecSmrg REQUEST(xShmAttachReq); 1364f7df2e56Smrg swaps(&stuff->length); 136505b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 1366f7df2e56Smrg swapl(&stuff->shmseg); 1367f7df2e56Smrg swapl(&stuff->shmid); 136805b261ecSmrg return ProcShmAttach(client); 136905b261ecSmrg} 137005b261ecSmrg 137105b261ecSmrgstatic int 13724642e01fSmrgSProcShmDetach(ClientPtr client) 137305b261ecSmrg{ 137405b261ecSmrg REQUEST(xShmDetachReq); 1375f7df2e56Smrg swaps(&stuff->length); 137605b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 1377f7df2e56Smrg swapl(&stuff->shmseg); 137805b261ecSmrg return ProcShmDetach(client); 137905b261ecSmrg} 138005b261ecSmrg 138105b261ecSmrgstatic int 13824642e01fSmrgSProcShmPutImage(ClientPtr client) 138305b261ecSmrg{ 138405b261ecSmrg REQUEST(xShmPutImageReq); 1385f7df2e56Smrg swaps(&stuff->length); 138605b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 1387f7df2e56Smrg swapl(&stuff->drawable); 1388f7df2e56Smrg swapl(&stuff->gc); 1389f7df2e56Smrg swaps(&stuff->totalWidth); 1390f7df2e56Smrg swaps(&stuff->totalHeight); 1391f7df2e56Smrg swaps(&stuff->srcX); 1392f7df2e56Smrg swaps(&stuff->srcY); 1393f7df2e56Smrg swaps(&stuff->srcWidth); 1394f7df2e56Smrg swaps(&stuff->srcHeight); 1395f7df2e56Smrg swaps(&stuff->dstX); 1396f7df2e56Smrg swaps(&stuff->dstY); 1397f7df2e56Smrg swapl(&stuff->shmseg); 1398f7df2e56Smrg swapl(&stuff->offset); 139905b261ecSmrg return ProcShmPutImage(client); 140005b261ecSmrg} 140105b261ecSmrg 140205b261ecSmrgstatic int 14034642e01fSmrgSProcShmGetImage(ClientPtr client) 140405b261ecSmrg{ 140505b261ecSmrg REQUEST(xShmGetImageReq); 1406f7df2e56Smrg swaps(&stuff->length); 140705b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 1408f7df2e56Smrg swapl(&stuff->drawable); 1409f7df2e56Smrg swaps(&stuff->x); 1410f7df2e56Smrg swaps(&stuff->y); 1411f7df2e56Smrg swaps(&stuff->width); 1412f7df2e56Smrg swaps(&stuff->height); 1413f7df2e56Smrg swapl(&stuff->planeMask); 1414f7df2e56Smrg swapl(&stuff->shmseg); 1415f7df2e56Smrg swapl(&stuff->offset); 141605b261ecSmrg return ProcShmGetImage(client); 141705b261ecSmrg} 141805b261ecSmrg 141905b261ecSmrgstatic int 14204642e01fSmrgSProcShmCreatePixmap(ClientPtr client) 142105b261ecSmrg{ 142205b261ecSmrg REQUEST(xShmCreatePixmapReq); 1423f7df2e56Smrg swaps(&stuff->length); 142405b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 1425f7df2e56Smrg swapl(&stuff->pid); 1426f7df2e56Smrg swapl(&stuff->drawable); 1427f7df2e56Smrg swaps(&stuff->width); 1428f7df2e56Smrg swaps(&stuff->height); 1429f7df2e56Smrg swapl(&stuff->shmseg); 1430f7df2e56Smrg swapl(&stuff->offset); 143105b261ecSmrg return ProcShmCreatePixmap(client); 143205b261ecSmrg} 143305b261ecSmrg 1434f7df2e56Smrg#ifdef SHM_FD_PASSING 143505b261ecSmrgstatic int 1436f7df2e56SmrgSProcShmAttachFd(ClientPtr client) 1437f7df2e56Smrg{ 1438f7df2e56Smrg REQUEST(xShmAttachFdReq); 1439f7df2e56Smrg SetReqFds(client, 1); 1440f7df2e56Smrg swaps(&stuff->length); 1441f7df2e56Smrg REQUEST_SIZE_MATCH(xShmAttachFdReq); 1442f7df2e56Smrg swapl(&stuff->shmseg); 1443f7df2e56Smrg return ProcShmAttachFd(client); 1444f7df2e56Smrg} 1445f7df2e56Smrg 1446f7df2e56Smrgstatic int 1447f7df2e56SmrgSProcShmCreateSegment(ClientPtr client) 1448f7df2e56Smrg{ 1449f7df2e56Smrg REQUEST(xShmCreateSegmentReq); 1450f7df2e56Smrg swaps(&stuff->length); 1451f7df2e56Smrg REQUEST_SIZE_MATCH(xShmCreateSegmentReq); 1452f7df2e56Smrg swapl(&stuff->shmseg); 1453f7df2e56Smrg swapl(&stuff->size); 1454f7df2e56Smrg return ProcShmCreateSegment(client); 1455f7df2e56Smrg} 1456f7df2e56Smrg#endif /* SHM_FD_PASSING */ 1457f7df2e56Smrg 1458f7df2e56Smrgstatic int 1459f7df2e56SmrgSProcShmDispatch(ClientPtr client) 146005b261ecSmrg{ 146105b261ecSmrg REQUEST(xReq); 1462f7df2e56Smrg switch (stuff->data) { 146305b261ecSmrg case X_ShmQueryVersion: 1464f7df2e56Smrg return SProcShmQueryVersion(client); 146505b261ecSmrg case X_ShmAttach: 1466f7df2e56Smrg return SProcShmAttach(client); 146705b261ecSmrg case X_ShmDetach: 1468f7df2e56Smrg return SProcShmDetach(client); 146905b261ecSmrg case X_ShmPutImage: 1470f7df2e56Smrg return SProcShmPutImage(client); 147105b261ecSmrg case X_ShmGetImage: 1472f7df2e56Smrg return SProcShmGetImage(client); 147305b261ecSmrg case X_ShmCreatePixmap: 1474f7df2e56Smrg return SProcShmCreatePixmap(client); 1475f7df2e56Smrg#ifdef SHM_FD_PASSING 1476f7df2e56Smrg case X_ShmAttachFd: 1477f7df2e56Smrg return SProcShmAttachFd(client); 1478f7df2e56Smrg case X_ShmCreateSegment: 1479f7df2e56Smrg return SProcShmCreateSegment(client); 1480f7df2e56Smrg#endif 148105b261ecSmrg default: 1482f7df2e56Smrg return BadRequest; 148305b261ecSmrg } 148405b261ecSmrg} 148565b04b38Smrg 148665b04b38Smrgvoid 1487f7df2e56SmrgShmExtensionInit(void) 148865b04b38Smrg{ 148965b04b38Smrg ExtensionEntry *extEntry; 149065b04b38Smrg int i; 149165b04b38Smrg 149265b04b38Smrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL 1493f7df2e56Smrg if (!CheckForShmSyscall()) { 1494f7df2e56Smrg ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); 1495f7df2e56Smrg return; 149665b04b38Smrg } 149765b04b38Smrg#endif 149865b04b38Smrg 149965b04b38Smrg if (!ShmRegisterPrivates()) 1500f7df2e56Smrg return; 150165b04b38Smrg 150265b04b38Smrg sharedPixmaps = xFalse; 150365b04b38Smrg { 1504f7df2e56Smrg sharedPixmaps = xTrue; 1505f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 1506f7df2e56Smrg ShmScrPrivateRec *screen_priv = 1507f7df2e56Smrg ShmInitScreenPriv(screenInfo.screens[i]); 1508f7df2e56Smrg if (!screen_priv->shmFuncs) 1509f7df2e56Smrg screen_priv->shmFuncs = &miFuncs; 1510f7df2e56Smrg if (!screen_priv->shmFuncs->CreatePixmap) 1511f7df2e56Smrg sharedPixmaps = xFalse; 1512f7df2e56Smrg } 1513f7df2e56Smrg if (sharedPixmaps) 1514f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 1515f7df2e56Smrg ShmScrPrivateRec *screen_priv = 1516f7df2e56Smrg ShmGetScreenPriv(screenInfo.screens[i]); 1517f7df2e56Smrg screen_priv->destroyPixmap = 1518f7df2e56Smrg screenInfo.screens[i]->DestroyPixmap; 1519f7df2e56Smrg screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; 1520f7df2e56Smrg } 152165b04b38Smrg } 152265b04b38Smrg ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg"); 152365b04b38Smrg if (ShmSegType && 1524f7df2e56Smrg (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, 1525f7df2e56Smrg ProcShmDispatch, SProcShmDispatch, 1526f7df2e56Smrg ShmResetProc, StandardMinorOpcode))) { 1527f7df2e56Smrg ShmReqCode = (unsigned char) extEntry->base; 1528f7df2e56Smrg ShmCompletionCode = extEntry->eventBase; 1529f7df2e56Smrg BadShmSegCode = extEntry->errorBase; 1530f7df2e56Smrg SetResourceTypeErrorValue(ShmSegType, BadShmSegCode); 1531f7df2e56Smrg EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; 153265b04b38Smrg } 153365b04b38Smrg} 1534