shm.c revision 7e31ba66
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 15705b261ecSmrgstatic Bool badSysCall = FALSE; 15805b261ecSmrg 15905b261ecSmrgstatic void 1604642e01fSmrgSigSysHandler(int signo) 16105b261ecSmrg{ 16205b261ecSmrg badSysCall = TRUE; 16305b261ecSmrg} 16405b261ecSmrg 165f7df2e56Smrgstatic Bool 166f7df2e56SmrgCheckForShmSyscall(void) 16705b261ecSmrg{ 168f7df2e56Smrg void (*oldHandler) (int); 16905b261ecSmrg int shmid = -1; 17005b261ecSmrg 17105b261ecSmrg /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ 1727e31ba66Smrg oldHandler = OsSignal(SIGSYS, SigSysHandler); 17305b261ecSmrg 17405b261ecSmrg badSysCall = FALSE; 17505b261ecSmrg shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); 17605b261ecSmrg 177f7df2e56Smrg if (shmid != -1) { 17805b261ecSmrg /* Successful allocation - clean up */ 179f7df2e56Smrg shmctl(shmid, IPC_RMID, NULL); 18005b261ecSmrg } 181f7df2e56Smrg else { 18205b261ecSmrg /* Allocation failed */ 18305b261ecSmrg badSysCall = TRUE; 18405b261ecSmrg } 1857e31ba66Smrg OsSignal(SIGSYS, oldHandler); 1864202a189Smrg return !badSysCall; 18705b261ecSmrg} 18805b261ecSmrg 18905b261ecSmrg#define MUST_CHECK_FOR_SHM_SYSCALL 19005b261ecSmrg 19105b261ecSmrg#endif 19205b261ecSmrg 1934202a189Smrgstatic Bool 194f7df2e56SmrgShmCloseScreen(ScreenPtr pScreen) 1954202a189Smrg{ 1964202a189Smrg ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 197f7df2e56Smrg 1984202a189Smrg pScreen->CloseScreen = screen_priv->CloseScreen; 1994202a189Smrg dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL); 2004202a189Smrg free(screen_priv); 201f7df2e56Smrg return (*pScreen->CloseScreen) (pScreen); 2024202a189Smrg} 2034202a189Smrg 2044202a189Smrgstatic ShmScrPrivateRec * 2054202a189SmrgShmInitScreenPriv(ScreenPtr pScreen) 2064202a189Smrg{ 2074202a189Smrg ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 208f7df2e56Smrg 209f7df2e56Smrg if (!screen_priv) { 210f7df2e56Smrg screen_priv = calloc(1, sizeof(ShmScrPrivateRec)); 211f7df2e56Smrg screen_priv->CloseScreen = pScreen->CloseScreen; 212f7df2e56Smrg dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv); 213f7df2e56Smrg pScreen->CloseScreen = ShmCloseScreen; 2144202a189Smrg } 2154202a189Smrg return screen_priv; 2164202a189Smrg} 2174202a189Smrg 2184202a189Smrgstatic Bool 2194202a189SmrgShmRegisterPrivates(void) 2204202a189Smrg{ 2214202a189Smrg if (!dixRegisterPrivateKey(&shmScrPrivateKeyRec, PRIVATE_SCREEN, 0)) 222f7df2e56Smrg return FALSE; 2234202a189Smrg if (!dixRegisterPrivateKey(&shmPixmapPrivateKeyRec, PRIVATE_PIXMAP, 0)) 224f7df2e56Smrg return FALSE; 2254202a189Smrg return TRUE; 2264202a189Smrg} 2274202a189Smrg 228f7df2e56Smrg /*ARGSUSED*/ static void 229f7df2e56SmrgShmResetProc(ExtensionEntry * extEntry) 23005b261ecSmrg{ 23105b261ecSmrg int i; 232f7df2e56Smrg 2334202a189Smrg for (i = 0; i < screenInfo.numScreens; i++) 234f7df2e56Smrg ShmRegisterFuncs(screenInfo.screens[i], NULL); 23505b261ecSmrg} 23605b261ecSmrg 2374202a189Smrgvoid 2384642e01fSmrgShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) 23905b261ecSmrg{ 2404202a189Smrg if (!ShmRegisterPrivates()) 241f7df2e56Smrg return; 2424202a189Smrg ShmInitScreenPriv(pScreen)->shmFuncs = funcs; 24305b261ecSmrg} 24405b261ecSmrg 24505b261ecSmrgstatic Bool 246f7df2e56SmrgShmDestroyPixmap(PixmapPtr pPixmap) 24705b261ecSmrg{ 248f7df2e56Smrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 2494202a189Smrg ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 250f7df2e56Smrg void *shmdesc = NULL; 251f7df2e56Smrg Bool ret; 252f7df2e56Smrg 25305b261ecSmrg if (pPixmap->refcnt == 1) 254f7df2e56Smrg shmdesc = dixLookupPrivate(&pPixmap->devPrivates, shmPixmapPrivateKey); 255f7df2e56Smrg 2564202a189Smrg pScreen->DestroyPixmap = screen_priv->destroyPixmap; 25705b261ecSmrg ret = (*pScreen->DestroyPixmap) (pPixmap); 2584202a189Smrg screen_priv->destroyPixmap = pScreen->DestroyPixmap; 25905b261ecSmrg pScreen->DestroyPixmap = ShmDestroyPixmap; 260f7df2e56Smrg 261f7df2e56Smrg if (shmdesc) 262f7df2e56Smrg ShmDetachSegment(shmdesc, 0); 263f7df2e56Smrg 26405b261ecSmrg return ret; 26505b261ecSmrg} 26605b261ecSmrg 2674202a189Smrgvoid 2684642e01fSmrgShmRegisterFbFuncs(ScreenPtr pScreen) 26905b261ecSmrg{ 2704202a189Smrg ShmRegisterFuncs(pScreen, &fbFuncs); 27105b261ecSmrg} 27205b261ecSmrg 27305b261ecSmrgstatic int 2744642e01fSmrgProcShmQueryVersion(ClientPtr client) 27505b261ecSmrg{ 276f7df2e56Smrg xShmQueryVersionReply rep = { 277f7df2e56Smrg .type = X_Reply, 278f7df2e56Smrg .sharedPixmaps = sharedPixmaps, 279f7df2e56Smrg .sequenceNumber = client->sequence, 280f7df2e56Smrg .length = 0, 281f7df2e56Smrg .majorVersion = SERVER_SHM_MAJOR_VERSION, 282f7df2e56Smrg .minorVersion = SERVER_SHM_MINOR_VERSION, 283f7df2e56Smrg .uid = geteuid(), 284f7df2e56Smrg .gid = getegid(), 285f7df2e56Smrg .pixmapFormat = sharedPixmaps ? ZPixmap : 0 286f7df2e56Smrg }; 28705b261ecSmrg 28805b261ecSmrg REQUEST_SIZE_MATCH(xShmQueryVersionReq); 289f7df2e56Smrg 29005b261ecSmrg if (client->swapped) { 291f7df2e56Smrg swaps(&rep.sequenceNumber); 292f7df2e56Smrg swapl(&rep.length); 293f7df2e56Smrg swaps(&rep.majorVersion); 294f7df2e56Smrg swaps(&rep.minorVersion); 295f7df2e56Smrg swaps(&rep.uid); 296f7df2e56Smrg swaps(&rep.gid); 297f7df2e56Smrg } 298f7df2e56Smrg WriteToClient(client, sizeof(xShmQueryVersionReply), &rep); 2994202a189Smrg return Success; 30005b261ecSmrg} 30105b261ecSmrg 30205b261ecSmrg/* 30305b261ecSmrg * Simulate the access() system call for a shared memory segement, 30405b261ecSmrg * using the credentials from the client if available 30505b261ecSmrg */ 30605b261ecSmrgstatic int 307f7df2e56Smrgshm_access(ClientPtr client, SHMPERM_TYPE * perm, int readonly) 30805b261ecSmrg{ 30905b261ecSmrg int uid, gid; 31005b261ecSmrg mode_t mask; 3114642e01fSmrg int uidset = 0, gidset = 0; 3124642e01fSmrg LocalClientCredRec *lcc; 313f7df2e56Smrg 3144642e01fSmrg if (GetLocalClientCreds(client, &lcc) != -1) { 31505b261ecSmrg 316f7df2e56Smrg if (lcc->fieldsSet & LCC_UID_SET) { 317f7df2e56Smrg uid = lcc->euid; 318f7df2e56Smrg uidset = 1; 319f7df2e56Smrg } 320f7df2e56Smrg if (lcc->fieldsSet & LCC_GID_SET) { 321f7df2e56Smrg gid = lcc->egid; 322f7df2e56Smrg gidset = 1; 323f7df2e56Smrg } 3244642e01fSmrg 3254642e01fSmrg#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) 326f7df2e56Smrg if (((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) 327f7df2e56Smrg || (lcc->zoneid != SHMPERM_ZONEID(perm))) { 328f7df2e56Smrg uidset = 0; 329f7df2e56Smrg gidset = 0; 330f7df2e56Smrg } 3314642e01fSmrg#endif 332f7df2e56Smrg FreeLocalClientCreds(lcc); 333f7df2e56Smrg 334f7df2e56Smrg if (uidset) { 335f7df2e56Smrg /* User id 0 always gets access */ 336f7df2e56Smrg if (uid == 0) { 337f7df2e56Smrg return 0; 338f7df2e56Smrg } 339f7df2e56Smrg /* Check the owner */ 340f7df2e56Smrg if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { 341f7df2e56Smrg mask = S_IRUSR; 342f7df2e56Smrg if (!readonly) { 343f7df2e56Smrg mask |= S_IWUSR; 344f7df2e56Smrg } 345f7df2e56Smrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 346f7df2e56Smrg } 347f7df2e56Smrg } 348f7df2e56Smrg 349f7df2e56Smrg if (gidset) { 350f7df2e56Smrg /* Check the group */ 351f7df2e56Smrg if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { 352f7df2e56Smrg mask = S_IRGRP; 353f7df2e56Smrg if (!readonly) { 354f7df2e56Smrg mask |= S_IWGRP; 355f7df2e56Smrg } 356f7df2e56Smrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 357f7df2e56Smrg } 358f7df2e56Smrg } 35905b261ecSmrg } 36005b261ecSmrg /* Otherwise, check everyone else */ 36105b261ecSmrg mask = S_IROTH; 36205b261ecSmrg if (!readonly) { 363f7df2e56Smrg mask |= S_IWOTH; 36405b261ecSmrg } 3654642e01fSmrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 36605b261ecSmrg} 36705b261ecSmrg 36805b261ecSmrgstatic int 3694642e01fSmrgProcShmAttach(ClientPtr client) 37005b261ecSmrg{ 3714642e01fSmrg SHMSTAT_TYPE buf; 37205b261ecSmrg ShmDescPtr shmdesc; 373f7df2e56Smrg 37405b261ecSmrg REQUEST(xShmAttachReq); 37505b261ecSmrg 37605b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 37705b261ecSmrg LEGAL_NEW_RESOURCE(stuff->shmseg, client); 378f7df2e56Smrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 379f7df2e56Smrg client->errorValue = stuff->readOnly; 3804202a189Smrg return BadValue; 38105b261ecSmrg } 382f7df2e56Smrg for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) { 383f7df2e56Smrg if (!SHMDESC_IS_FD(shmdesc) && shmdesc->shmid == stuff->shmid) 384f7df2e56Smrg break; 38505b261ecSmrg } 386f7df2e56Smrg if (shmdesc) { 387f7df2e56Smrg if (!stuff->readOnly && !shmdesc->writable) 388f7df2e56Smrg return BadAccess; 389f7df2e56Smrg shmdesc->refcnt++; 390f7df2e56Smrg } 391f7df2e56Smrg else { 392f7df2e56Smrg shmdesc = malloc(sizeof(ShmDescRec)); 393f7df2e56Smrg if (!shmdesc) 394f7df2e56Smrg return BadAlloc; 395f7df2e56Smrg#ifdef SHM_FD_PASSING 396f7df2e56Smrg shmdesc->is_fd = FALSE; 397f7df2e56Smrg#endif 398f7df2e56Smrg shmdesc->addr = shmat(stuff->shmid, 0, 399f7df2e56Smrg stuff->readOnly ? SHM_RDONLY : 0); 400f7df2e56Smrg if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) { 401f7df2e56Smrg free(shmdesc); 402f7df2e56Smrg return BadAccess; 403f7df2e56Smrg } 404f7df2e56Smrg 405f7df2e56Smrg /* The attach was performed with root privs. We must 406f7df2e56Smrg * do manual checking of access rights for the credentials 407f7df2e56Smrg * of the client */ 408f7df2e56Smrg 409f7df2e56Smrg if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { 410f7df2e56Smrg shmdt(shmdesc->addr); 411f7df2e56Smrg free(shmdesc); 412f7df2e56Smrg return BadAccess; 413f7df2e56Smrg } 414f7df2e56Smrg 415f7df2e56Smrg shmdesc->shmid = stuff->shmid; 416f7df2e56Smrg shmdesc->refcnt = 1; 417f7df2e56Smrg shmdesc->writable = !stuff->readOnly; 418f7df2e56Smrg shmdesc->size = SHM_SEGSZ(buf); 419f7df2e56Smrg shmdesc->next = Shmsegs; 420f7df2e56Smrg Shmsegs = shmdesc; 42105b261ecSmrg } 422f7df2e56Smrg if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) 423f7df2e56Smrg return BadAlloc; 4244202a189Smrg return Success; 42505b261ecSmrg} 42605b261ecSmrg 427f7df2e56Smrg /*ARGSUSED*/ static int 428f7df2e56SmrgShmDetachSegment(void *value, /* must conform to DeleteType */ 429f7df2e56Smrg XID unused) 43005b261ecSmrg{ 431f7df2e56Smrg ShmDescPtr shmdesc = (ShmDescPtr) value; 43205b261ecSmrg ShmDescPtr *prev; 43305b261ecSmrg 43405b261ecSmrg if (--shmdesc->refcnt) 435f7df2e56Smrg return TRUE; 436f7df2e56Smrg#if SHM_FD_PASSING 437f7df2e56Smrg if (shmdesc->is_fd) { 438f7df2e56Smrg if (shmdesc->busfault) 439f7df2e56Smrg busfault_unregister(shmdesc->busfault); 440f7df2e56Smrg munmap(shmdesc->addr, shmdesc->size); 441f7df2e56Smrg } else 442f7df2e56Smrg#endif 443f7df2e56Smrg shmdt(shmdesc->addr); 444f7df2e56Smrg for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next); 44505b261ecSmrg *prev = shmdesc->next; 4464202a189Smrg free(shmdesc); 44705b261ecSmrg return Success; 44805b261ecSmrg} 44905b261ecSmrg 45005b261ecSmrgstatic int 4514642e01fSmrgProcShmDetach(ClientPtr client) 45205b261ecSmrg{ 45305b261ecSmrg ShmDescPtr shmdesc; 454f7df2e56Smrg 45505b261ecSmrg REQUEST(xShmDetachReq); 45605b261ecSmrg 45705b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 45805b261ecSmrg VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); 45905b261ecSmrg FreeResource(stuff->shmseg, RT_NONE); 4604202a189Smrg return Success; 46105b261ecSmrg} 46205b261ecSmrg 4634642e01fSmrg/* 4644642e01fSmrg * If the given request doesn't exactly match PutImage's constraints, 4654642e01fSmrg * wrap the image in a scratch pixmap header and let CopyArea sort it out. 4664642e01fSmrg */ 46705b261ecSmrgstatic void 4684642e01fSmrgdoShmPutImage(DrawablePtr dst, GCPtr pGC, 469f7df2e56Smrg int depth, unsigned int format, 470f7df2e56Smrg int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, 471f7df2e56Smrg char *data) 47205b261ecSmrg{ 4734642e01fSmrg PixmapPtr pPixmap; 4744202a189Smrg 47545bb0b75Smrg if (format == ZPixmap || (format == XYPixmap && depth == 1)) { 476f7df2e56Smrg pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, 477f7df2e56Smrg BitsPerPixel(depth), 478f7df2e56Smrg PixmapBytePad(w, depth), data); 479f7df2e56Smrg if (!pPixmap) 480f7df2e56Smrg return; 481f7df2e56Smrg pGC->ops->CopyArea((DrawablePtr) pPixmap, dst, pGC, sx, sy, sw, sh, dx, 482f7df2e56Smrg dy); 483f7df2e56Smrg FreeScratchPixmapHeader(pPixmap); 484f7df2e56Smrg } 485f7df2e56Smrg else { 486f7df2e56Smrg GCPtr putGC = GetScratchGC(depth, dst->pScreen); 487f7df2e56Smrg 488f7df2e56Smrg if (!putGC) 489f7df2e56Smrg return; 490f7df2e56Smrg 491f7df2e56Smrg pPixmap = (*dst->pScreen->CreatePixmap) (dst->pScreen, sw, sh, depth, 492f7df2e56Smrg CREATE_PIXMAP_USAGE_SCRATCH); 493f7df2e56Smrg if (!pPixmap) { 494f7df2e56Smrg FreeScratchGC(putGC); 495f7df2e56Smrg return; 496f7df2e56Smrg } 497f7df2e56Smrg ValidateGC(&pPixmap->drawable, putGC); 498f7df2e56Smrg (*putGC->ops->PutImage) (&pPixmap->drawable, putGC, depth, -sx, -sy, w, 499f7df2e56Smrg h, 0, 500f7df2e56Smrg (format == XYPixmap) ? XYPixmap : ZPixmap, 501f7df2e56Smrg data); 502f7df2e56Smrg FreeScratchGC(putGC); 503f7df2e56Smrg if (format == XYBitmap) 504f7df2e56Smrg (void) (*pGC->ops->CopyPlane) (&pPixmap->drawable, dst, pGC, 0, 0, 505f7df2e56Smrg sw, sh, dx, dy, 1L); 506f7df2e56Smrg else 507f7df2e56Smrg (void) (*pGC->ops->CopyArea) (&pPixmap->drawable, dst, pGC, 0, 0, 508f7df2e56Smrg sw, sh, dx, dy); 509f7df2e56Smrg (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); 5104202a189Smrg } 51105b261ecSmrg} 51205b261ecSmrg 51365b04b38Smrgstatic int 51465b04b38SmrgProcShmPutImage(ClientPtr client) 51505b261ecSmrg{ 51665b04b38Smrg GCPtr pGC; 51765b04b38Smrg DrawablePtr pDraw; 51865b04b38Smrg long length; 51965b04b38Smrg ShmDescPtr shmdesc; 520f7df2e56Smrg 52105b261ecSmrg REQUEST(xShmPutImageReq); 52265b04b38Smrg 52305b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 52465b04b38Smrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 52565b04b38Smrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); 52665b04b38Smrg if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) 527f7df2e56Smrg return BadValue; 528f7df2e56Smrg if (stuff->format == XYBitmap) { 52965b04b38Smrg if (stuff->depth != 1) 53065b04b38Smrg return BadMatch; 53165b04b38Smrg length = PixmapBytePad(stuff->totalWidth, 1); 53265b04b38Smrg } 533f7df2e56Smrg else if (stuff->format == XYPixmap) { 53465b04b38Smrg if (pDraw->depth != stuff->depth) 53565b04b38Smrg return BadMatch; 53665b04b38Smrg length = PixmapBytePad(stuff->totalWidth, 1); 537f7df2e56Smrg length *= stuff->depth; 53865b04b38Smrg } 539f7df2e56Smrg else if (stuff->format == ZPixmap) { 54065b04b38Smrg if (pDraw->depth != stuff->depth) 54165b04b38Smrg return BadMatch; 54265b04b38Smrg length = PixmapBytePad(stuff->totalWidth, stuff->depth); 54365b04b38Smrg } 544f7df2e56Smrg else { 545f7df2e56Smrg client->errorValue = stuff->format; 54665b04b38Smrg return BadValue; 54765b04b38Smrg } 54805b261ecSmrg 54965b04b38Smrg /* 55065b04b38Smrg * There's a potential integer overflow in this check: 55165b04b38Smrg * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, 55265b04b38Smrg * client); 55365b04b38Smrg * the version below ought to avoid it 55465b04b38Smrg */ 55565b04b38Smrg if (stuff->totalHeight != 0 && 556f7df2e56Smrg length > (shmdesc->size - stuff->offset) / stuff->totalHeight) { 557f7df2e56Smrg client->errorValue = stuff->totalWidth; 558f7df2e56Smrg return BadValue; 55965b04b38Smrg } 560f7df2e56Smrg if (stuff->srcX > stuff->totalWidth) { 561f7df2e56Smrg client->errorValue = stuff->srcX; 562f7df2e56Smrg return BadValue; 56365b04b38Smrg } 564f7df2e56Smrg if (stuff->srcY > stuff->totalHeight) { 565f7df2e56Smrg client->errorValue = stuff->srcY; 566f7df2e56Smrg return BadValue; 56765b04b38Smrg } 568f7df2e56Smrg if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) { 569f7df2e56Smrg client->errorValue = stuff->srcWidth; 570f7df2e56Smrg return BadValue; 57165b04b38Smrg } 572f7df2e56Smrg if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) { 573f7df2e56Smrg client->errorValue = stuff->srcHeight; 574f7df2e56Smrg return BadValue; 57565b04b38Smrg } 57605b261ecSmrg 57765b04b38Smrg if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || 578f7df2e56Smrg ((stuff->format != ZPixmap) && 579f7df2e56Smrg (stuff->srcX < screenInfo.bitmapScanlinePad) && 580f7df2e56Smrg ((stuff->format == XYBitmap) || 581f7df2e56Smrg ((stuff->srcY == 0) && 582f7df2e56Smrg (stuff->srcHeight == stuff->totalHeight))))) && 583f7df2e56Smrg ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) 584f7df2e56Smrg (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, 585f7df2e56Smrg stuff->dstX, stuff->dstY, 586f7df2e56Smrg stuff->totalWidth, stuff->srcHeight, 587f7df2e56Smrg stuff->srcX, stuff->format, 588f7df2e56Smrg shmdesc->addr + stuff->offset + 589f7df2e56Smrg (stuff->srcY * length)); 59065b04b38Smrg else 591f7df2e56Smrg doShmPutImage(pDraw, pGC, stuff->depth, stuff->format, 592f7df2e56Smrg stuff->totalWidth, stuff->totalHeight, 593f7df2e56Smrg stuff->srcX, stuff->srcY, 594f7df2e56Smrg stuff->srcWidth, stuff->srcHeight, 595f7df2e56Smrg stuff->dstX, stuff->dstY, shmdesc->addr + stuff->offset); 596f7df2e56Smrg 597f7df2e56Smrg if (stuff->sendEvent) { 598f7df2e56Smrg xShmCompletionEvent ev = { 599f7df2e56Smrg .type = ShmCompletionCode, 600f7df2e56Smrg .drawable = stuff->drawable, 601f7df2e56Smrg .minorEvent = X_ShmPutImage, 602f7df2e56Smrg .majorEvent = ShmReqCode, 603f7df2e56Smrg .shmseg = stuff->shmseg, 604f7df2e56Smrg .offset = stuff->offset 605f7df2e56Smrg }; 606f7df2e56Smrg WriteEventsToClient(client, 1, (xEvent *) &ev); 60705b261ecSmrg } 60865b04b38Smrg 60965b04b38Smrg return Success; 61005b261ecSmrg} 61105b261ecSmrg 61265b04b38Smrgstatic int 61365b04b38SmrgProcShmGetImage(ClientPtr client) 61405b261ecSmrg{ 615f7df2e56Smrg DrawablePtr pDraw; 616f7df2e56Smrg long lenPer = 0, length; 617f7df2e56Smrg Mask plane = 0; 618f7df2e56Smrg xShmGetImageReply xgi; 619f7df2e56Smrg ShmDescPtr shmdesc; 620f7df2e56Smrg VisualID visual = None; 621f7df2e56Smrg RegionPtr pVisibleRegion = NULL; 622f7df2e56Smrg int rc; 62305b261ecSmrg 62405b261ecSmrg REQUEST(xShmGetImageReq); 62505b261ecSmrg 62605b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 627f7df2e56Smrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 628f7df2e56Smrg client->errorValue = stuff->format; 6294202a189Smrg return BadValue; 63005b261ecSmrg } 631f7df2e56Smrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess); 63205b261ecSmrg if (rc != Success) 633f7df2e56Smrg return rc; 63405b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 635f7df2e56Smrg if (pDraw->type == DRAWABLE_WINDOW) { 636f7df2e56Smrg if ( /* check for being viewable */ 637f7df2e56Smrg !((WindowPtr) pDraw)->realized || 638f7df2e56Smrg /* check for being on screen */ 639f7df2e56Smrg pDraw->x + stuff->x < 0 || 640f7df2e56Smrg pDraw->x + stuff->x + (int) stuff->width > pDraw->pScreen->width 641f7df2e56Smrg || pDraw->y + stuff->y < 0 || 642f7df2e56Smrg pDraw->y + stuff->y + (int) stuff->height > 643f7df2e56Smrg pDraw->pScreen->height || 644f7df2e56Smrg /* check for being inside of border */ 645f7df2e56Smrg stuff->x < -wBorderWidth((WindowPtr) pDraw) || 646f7df2e56Smrg stuff->x + (int) stuff->width > 647f7df2e56Smrg wBorderWidth((WindowPtr) pDraw) + (int) pDraw->width || 648f7df2e56Smrg stuff->y < -wBorderWidth((WindowPtr) pDraw) || 649f7df2e56Smrg stuff->y + (int) stuff->height > 650f7df2e56Smrg wBorderWidth((WindowPtr) pDraw) + (int) pDraw->height) 651f7df2e56Smrg return BadMatch; 652f7df2e56Smrg visual = wVisual(((WindowPtr) pDraw)); 6537e31ba66Smrg if (pDraw->type == DRAWABLE_WINDOW) 6547e31ba66Smrg pVisibleRegion = &((WindowPtr) pDraw)->borderClip; 65565b04b38Smrg } 656f7df2e56Smrg else { 657f7df2e56Smrg if (stuff->x < 0 || 658f7df2e56Smrg stuff->x + (int) stuff->width > pDraw->width || 659f7df2e56Smrg stuff->y < 0 || stuff->y + (int) stuff->height > pDraw->height) 660f7df2e56Smrg return BadMatch; 661f7df2e56Smrg visual = None; 66265b04b38Smrg } 663f7df2e56Smrg xgi = (xShmGetImageReply) { 664f7df2e56Smrg .type = X_Reply, 665f7df2e56Smrg .sequenceNumber = client->sequence, 666f7df2e56Smrg .length = 0, 667f7df2e56Smrg .visual = visual, 668f7df2e56Smrg .depth = pDraw->depth 669f7df2e56Smrg }; 670f7df2e56Smrg if (stuff->format == ZPixmap) { 671f7df2e56Smrg length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; 672f7df2e56Smrg } 673f7df2e56Smrg else { 674f7df2e56Smrg lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; 675f7df2e56Smrg plane = ((Mask) 1) << (pDraw->depth - 1); 676f7df2e56Smrg /* only planes asked for */ 677f7df2e56Smrg length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); 67865b04b38Smrg } 67965b04b38Smrg 68065b04b38Smrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 68165b04b38Smrg xgi.size = length; 68265b04b38Smrg 683f7df2e56Smrg if (length == 0) { 684f7df2e56Smrg /* nothing to do */ 68565b04b38Smrg } 686f7df2e56Smrg else if (stuff->format == ZPixmap) { 687f7df2e56Smrg (*pDraw->pScreen->GetImage) (pDraw, stuff->x, stuff->y, 688f7df2e56Smrg stuff->width, stuff->height, 689f7df2e56Smrg stuff->format, stuff->planeMask, 690f7df2e56Smrg shmdesc->addr + stuff->offset); 691f7df2e56Smrg if (pVisibleRegion) 692f7df2e56Smrg XaceCensorImage(client, pVisibleRegion, 693f7df2e56Smrg PixmapBytePad(stuff->width, pDraw->depth), pDraw, 694f7df2e56Smrg stuff->x, stuff->y, stuff->width, stuff->height, 695f7df2e56Smrg stuff->format, shmdesc->addr + stuff->offset); 69665b04b38Smrg } 697f7df2e56Smrg else { 69865b04b38Smrg 699f7df2e56Smrg length = stuff->offset; 700f7df2e56Smrg for (; plane; plane >>= 1) { 701f7df2e56Smrg if (stuff->planeMask & plane) { 702f7df2e56Smrg (*pDraw->pScreen->GetImage) (pDraw, 703f7df2e56Smrg stuff->x, stuff->y, 704f7df2e56Smrg stuff->width, stuff->height, 705f7df2e56Smrg stuff->format, plane, 706f7df2e56Smrg shmdesc->addr + length); 707f7df2e56Smrg if (pVisibleRegion) 708f7df2e56Smrg XaceCensorImage(client, pVisibleRegion, 709f7df2e56Smrg BitmapBytePad(stuff->width), pDraw, 710f7df2e56Smrg stuff->x, stuff->y, stuff->width, stuff->height, 711f7df2e56Smrg stuff->format, shmdesc->addr + length); 712f7df2e56Smrg length += lenPer; 713f7df2e56Smrg } 714f7df2e56Smrg } 71565b04b38Smrg } 71665b04b38Smrg 71765b04b38Smrg if (client->swapped) { 718f7df2e56Smrg swaps(&xgi.sequenceNumber); 719f7df2e56Smrg swapl(&xgi.length); 720f7df2e56Smrg swapl(&xgi.visual); 721f7df2e56Smrg swapl(&xgi.size); 72265b04b38Smrg } 723f7df2e56Smrg WriteToClient(client, sizeof(xShmGetImageReply), &xgi); 72465b04b38Smrg 72565b04b38Smrg return Success; 72665b04b38Smrg} 72765b04b38Smrg 72865b04b38Smrg#ifdef PANORAMIX 729f7df2e56Smrgstatic int 73065b04b38SmrgProcPanoramiXShmPutImage(ClientPtr client) 73165b04b38Smrg{ 732f7df2e56Smrg int j, result, orig_x, orig_y; 733f7df2e56Smrg PanoramiXRes *draw, *gc; 734f7df2e56Smrg Bool sendEvent, isRoot; 73565b04b38Smrg 73665b04b38Smrg REQUEST(xShmPutImageReq); 73765b04b38Smrg REQUEST_SIZE_MATCH(xShmPutImageReq); 73865b04b38Smrg 739f7df2e56Smrg result = dixLookupResourceByClass((void **) &draw, stuff->drawable, 740f7df2e56Smrg XRC_DRAWABLE, client, DixWriteAccess); 74165b04b38Smrg if (result != Success) 74265b04b38Smrg return (result == BadValue) ? BadDrawable : result; 74365b04b38Smrg 744f7df2e56Smrg result = dixLookupResourceByType((void **) &gc, stuff->gc, 745f7df2e56Smrg XRT_GC, client, DixReadAccess); 74665b04b38Smrg if (result != Success) 74765b04b38Smrg return result; 74865b04b38Smrg 74965b04b38Smrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 75065b04b38Smrg 75165b04b38Smrg orig_x = stuff->dstX; 75265b04b38Smrg orig_y = stuff->dstY; 75365b04b38Smrg sendEvent = stuff->sendEvent; 75465b04b38Smrg stuff->sendEvent = 0; 75565b04b38Smrg FOR_NSCREENS(j) { 756f7df2e56Smrg if (!j) 757f7df2e56Smrg stuff->sendEvent = sendEvent; 758f7df2e56Smrg stuff->drawable = draw->info[j].id; 759f7df2e56Smrg stuff->gc = gc->info[j].id; 760f7df2e56Smrg if (isRoot) { 761f7df2e56Smrg stuff->dstX = orig_x - screenInfo.screens[j]->x; 762f7df2e56Smrg stuff->dstY = orig_y - screenInfo.screens[j]->y; 763f7df2e56Smrg } 764f7df2e56Smrg result = ProcShmPutImage(client); 765f7df2e56Smrg if (result != Success) 766f7df2e56Smrg break; 76765b04b38Smrg } 76865b04b38Smrg return result; 76965b04b38Smrg} 77065b04b38Smrg 771f7df2e56Smrgstatic int 77265b04b38SmrgProcPanoramiXShmGetImage(ClientPtr client) 77365b04b38Smrg{ 774f7df2e56Smrg PanoramiXRes *draw; 775f7df2e56Smrg DrawablePtr *drawables; 776f7df2e56Smrg DrawablePtr pDraw; 777f7df2e56Smrg xShmGetImageReply xgi; 778f7df2e56Smrg ShmDescPtr shmdesc; 779f7df2e56Smrg int i, x, y, w, h, format, rc; 780f7df2e56Smrg Mask plane = 0, planemask; 781f7df2e56Smrg long lenPer = 0, length, widthBytesLine; 782f7df2e56Smrg Bool isRoot; 78365b04b38Smrg 78465b04b38Smrg REQUEST(xShmGetImageReq); 78565b04b38Smrg 78665b04b38Smrg REQUEST_SIZE_MATCH(xShmGetImageReq); 78765b04b38Smrg 78865b04b38Smrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 789f7df2e56Smrg client->errorValue = stuff->format; 79065b04b38Smrg return BadValue; 79165b04b38Smrg } 79265b04b38Smrg 793f7df2e56Smrg rc = dixLookupResourceByClass((void **) &draw, stuff->drawable, 794f7df2e56Smrg XRC_DRAWABLE, client, DixWriteAccess); 79565b04b38Smrg if (rc != Success) 796f7df2e56Smrg return (rc == BadValue) ? BadDrawable : rc; 79765b04b38Smrg 79865b04b38Smrg if (draw->type == XRT_PIXMAP) 799f7df2e56Smrg return ProcShmGetImage(client); 80065b04b38Smrg 801f7df2e56Smrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess); 80265b04b38Smrg if (rc != Success) 803f7df2e56Smrg return rc; 80465b04b38Smrg 80565b04b38Smrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 80665b04b38Smrg 80765b04b38Smrg x = stuff->x; 80865b04b38Smrg y = stuff->y; 80965b04b38Smrg w = stuff->width; 81065b04b38Smrg h = stuff->height; 81165b04b38Smrg format = stuff->format; 81265b04b38Smrg planemask = stuff->planeMask; 81365b04b38Smrg 81465b04b38Smrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 81565b04b38Smrg 816f7df2e56Smrg if (isRoot) { 817f7df2e56Smrg if ( /* check for being onscreen */ 818f7df2e56Smrg x < 0 || x + w > PanoramiXPixWidth || 819f7df2e56Smrg y < 0 || y + h > PanoramiXPixHeight) 820f7df2e56Smrg return BadMatch; 821f7df2e56Smrg } 822f7df2e56Smrg else { 823f7df2e56Smrg if ( /* check for being onscreen */ 824f7df2e56Smrg screenInfo.screens[0]->x + pDraw->x + x < 0 || 825f7df2e56Smrg screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth 826f7df2e56Smrg || screenInfo.screens[0]->y + pDraw->y + y < 0 || 827f7df2e56Smrg screenInfo.screens[0]->y + pDraw->y + y + h > PanoramiXPixHeight 828f7df2e56Smrg || 829f7df2e56Smrg /* check for being inside of border */ 830f7df2e56Smrg x < -wBorderWidth((WindowPtr) pDraw) || 831f7df2e56Smrg x + w > wBorderWidth((WindowPtr) pDraw) + (int) pDraw->width || 832f7df2e56Smrg y < -wBorderWidth((WindowPtr) pDraw) || 833f7df2e56Smrg y + h > wBorderWidth((WindowPtr) pDraw) + (int) pDraw->height) 834f7df2e56Smrg return BadMatch; 83565b04b38Smrg } 83665b04b38Smrg 8377e31ba66Smrg if (format == ZPixmap) { 8387e31ba66Smrg widthBytesLine = PixmapBytePad(w, pDraw->depth); 8397e31ba66Smrg length = widthBytesLine * h; 8407e31ba66Smrg } 8417e31ba66Smrg else { 8427e31ba66Smrg widthBytesLine = PixmapBytePad(w, 1); 8437e31ba66Smrg lenPer = widthBytesLine * h; 8447e31ba66Smrg plane = ((Mask) 1) << (pDraw->depth - 1); 8457e31ba66Smrg length = lenPer * Ones(planemask & (plane | (plane - 1))); 8467e31ba66Smrg } 8477e31ba66Smrg 8487e31ba66Smrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 8497e31ba66Smrg 8504202a189Smrg drawables = calloc(PanoramiXNumScreens, sizeof(DrawablePtr)); 851f7df2e56Smrg if (!drawables) 852f7df2e56Smrg return BadAlloc; 8534202a189Smrg 85405b261ecSmrg drawables[0] = pDraw; 855f7df2e56Smrg FOR_NSCREENS_FORWARD_SKIP(i) { 856f7df2e56Smrg rc = dixLookupDrawable(drawables + i, draw->info[i].id, client, 0, 857f7df2e56Smrg DixReadAccess); 858f7df2e56Smrg if (rc != Success) { 859f7df2e56Smrg free(drawables); 860f7df2e56Smrg return rc; 861f7df2e56Smrg } 86205b261ecSmrg } 86305b261ecSmrg 864f7df2e56Smrg xgi = (xShmGetImageReply) { 865f7df2e56Smrg .type = X_Reply, 866f7df2e56Smrg .sequenceNumber = client->sequence, 867f7df2e56Smrg .length = 0, 868f7df2e56Smrg .visual = wVisual(((WindowPtr) pDraw)), 869f7df2e56Smrg .depth = pDraw->depth 870f7df2e56Smrg }; 871f7df2e56Smrg 87205b261ecSmrg xgi.size = length; 87305b261ecSmrg 874f7df2e56Smrg if (length == 0) { /* nothing to do */ 875f7df2e56Smrg } 87605b261ecSmrg else if (format == ZPixmap) { 877f7df2e56Smrg XineramaGetImageData(drawables, x, y, w, h, format, planemask, 878f7df2e56Smrg shmdesc->addr + stuff->offset, 879f7df2e56Smrg widthBytesLine, isRoot); 880f7df2e56Smrg } 881f7df2e56Smrg else { 88205b261ecSmrg 883f7df2e56Smrg length = stuff->offset; 88405b261ecSmrg for (; plane; plane >>= 1) { 885f7df2e56Smrg if (planemask & plane) { 886f7df2e56Smrg XineramaGetImageData(drawables, x, y, w, h, 887f7df2e56Smrg format, plane, shmdesc->addr + length, 888f7df2e56Smrg widthBytesLine, isRoot); 889f7df2e56Smrg length += lenPer; 890f7df2e56Smrg } 891f7df2e56Smrg } 89205b261ecSmrg } 8934202a189Smrg free(drawables); 894f7df2e56Smrg 89505b261ecSmrg if (client->swapped) { 896f7df2e56Smrg swaps(&xgi.sequenceNumber); 897f7df2e56Smrg swapl(&xgi.length); 898f7df2e56Smrg swapl(&xgi.visual); 899f7df2e56Smrg swapl(&xgi.size); 90005b261ecSmrg } 901f7df2e56Smrg WriteToClient(client, sizeof(xShmGetImageReply), &xgi); 90205b261ecSmrg 9034202a189Smrg return Success; 90405b261ecSmrg} 90505b261ecSmrg 90605b261ecSmrgstatic int 9074642e01fSmrgProcPanoramiXShmCreatePixmap(ClientPtr client) 90805b261ecSmrg{ 90905b261ecSmrg ScreenPtr pScreen = NULL; 91005b261ecSmrg PixmapPtr pMap = NULL; 91105b261ecSmrg DrawablePtr pDraw; 91205b261ecSmrg DepthPtr pDepth; 91305b261ecSmrg int i, j, result, rc; 91405b261ecSmrg ShmDescPtr shmdesc; 915f7df2e56Smrg 91605b261ecSmrg REQUEST(xShmCreatePixmapReq); 91705b261ecSmrg unsigned int width, height, depth; 91805b261ecSmrg unsigned long size; 91905b261ecSmrg PanoramiXRes *newPix; 92005b261ecSmrg 92105b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 92205b261ecSmrg client->errorValue = stuff->pid; 92305b261ecSmrg if (!sharedPixmaps) 924f7df2e56Smrg return BadImplementation; 92505b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 92605b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 927f7df2e56Smrg DixGetAttrAccess); 92805b261ecSmrg if (rc != Success) 929f7df2e56Smrg return rc; 93005b261ecSmrg 93105b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 93205b261ecSmrg 93305b261ecSmrg width = stuff->width; 93405b261ecSmrg height = stuff->height; 93505b261ecSmrg depth = stuff->depth; 936f7df2e56Smrg if (!width || !height || !depth) { 937f7df2e56Smrg client->errorValue = 0; 93805b261ecSmrg return BadValue; 93905b261ecSmrg } 94005b261ecSmrg if (width > 32767 || height > 32767) 94105b261ecSmrg return BadAlloc; 94205b261ecSmrg 943f7df2e56Smrg if (stuff->depth != 1) { 94405b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 945f7df2e56Smrg for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 946f7df2e56Smrg if (pDepth->depth == stuff->depth) 947f7df2e56Smrg goto CreatePmap; 948f7df2e56Smrg client->errorValue = stuff->depth; 94905b261ecSmrg return BadValue; 95005b261ecSmrg } 95105b261ecSmrg 952f7df2e56Smrg CreatePmap: 95305b261ecSmrg size = PixmapBytePad(width, depth) * height; 95405b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 95505b261ecSmrg if (size < width * height) 95605b261ecSmrg return BadAlloc; 95705b261ecSmrg } 95805b261ecSmrg /* thankfully, offset is unsigned */ 95905b261ecSmrg if (stuff->offset + size < size) 960f7df2e56Smrg return BadAlloc; 96105b261ecSmrg 96205b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 96305b261ecSmrg 964f7df2e56Smrg if (!(newPix = malloc(sizeof(PanoramiXRes)))) 965f7df2e56Smrg return BadAlloc; 96605b261ecSmrg 96705b261ecSmrg newPix->type = XRT_PIXMAP; 96805b261ecSmrg newPix->u.pix.shared = TRUE; 969f7df2e56Smrg panoramix_setup_ids(newPix, client, stuff->pid); 97005b261ecSmrg 9714202a189Smrg result = Success; 97205b261ecSmrg 97305b261ecSmrg FOR_NSCREENS(j) { 974f7df2e56Smrg ShmScrPrivateRec *screen_priv; 975f7df2e56Smrg 976f7df2e56Smrg pScreen = screenInfo.screens[j]; 977f7df2e56Smrg 978f7df2e56Smrg screen_priv = ShmGetScreenPriv(pScreen); 979f7df2e56Smrg pMap = (*screen_priv->shmFuncs->CreatePixmap) (pScreen, 980f7df2e56Smrg stuff->width, 981f7df2e56Smrg stuff->height, 982f7df2e56Smrg stuff->depth, 983f7df2e56Smrg shmdesc->addr + 984f7df2e56Smrg stuff->offset); 985f7df2e56Smrg 986f7df2e56Smrg if (pMap) { 987f7df2e56Smrg result = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, 988f7df2e56Smrg RT_PIXMAP, pMap, RT_NONE, NULL, DixCreateAccess); 989f7df2e56Smrg if (result != Success) { 990f7df2e56Smrg pDraw->pScreen->DestroyPixmap(pMap); 9917e31ba66Smrg break; 992f7df2e56Smrg } 993f7df2e56Smrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc); 99405b261ecSmrg shmdesc->refcnt++; 995f7df2e56Smrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 996f7df2e56Smrg pMap->drawable.id = newPix->info[j].id; 997f7df2e56Smrg if (!AddResource(newPix->info[j].id, RT_PIXMAP, (void *) pMap)) { 998f7df2e56Smrg result = BadAlloc; 999f7df2e56Smrg break; 1000f7df2e56Smrg } 1001f7df2e56Smrg } 1002f7df2e56Smrg else { 1003f7df2e56Smrg result = BadAlloc; 1004f7df2e56Smrg break; 1005f7df2e56Smrg } 100605b261ecSmrg } 100705b261ecSmrg 10087e31ba66Smrg if (result != Success) { 1009f7df2e56Smrg while (j--) 1010f7df2e56Smrg FreeResource(newPix->info[j].id, RT_NONE); 1011f7df2e56Smrg free(newPix); 1012f7df2e56Smrg } 1013f7df2e56Smrg else 1014f7df2e56Smrg AddResource(stuff->pid, XRT_PIXMAP, newPix); 101505b261ecSmrg 101605b261ecSmrg return result; 101705b261ecSmrg} 101805b261ecSmrg#endif 101905b261ecSmrg 102005b261ecSmrgstatic PixmapPtr 1021f7df2e56SmrgfbShmCreatePixmap(ScreenPtr pScreen, 1022f7df2e56Smrg int width, int height, int depth, char *addr) 102305b261ecSmrg{ 10244642e01fSmrg PixmapPtr pPixmap; 102505b261ecSmrg 1026f7df2e56Smrg pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth, 0); 102705b261ecSmrg if (!pPixmap) 1028f7df2e56Smrg return NullPixmap; 1029f7df2e56Smrg 1030f7df2e56Smrg if (!(*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth, 1031f7df2e56Smrg BitsPerPixel(depth), 1032f7df2e56Smrg PixmapBytePad(width, depth), 1033f7df2e56Smrg (void *) addr)) { 1034f7df2e56Smrg (*pScreen->DestroyPixmap) (pPixmap); 1035f7df2e56Smrg return NullPixmap; 103605b261ecSmrg } 103705b261ecSmrg return pPixmap; 103805b261ecSmrg} 103905b261ecSmrg 104005b261ecSmrgstatic int 10414642e01fSmrgProcShmCreatePixmap(ClientPtr client) 104205b261ecSmrg{ 104305b261ecSmrg PixmapPtr pMap; 104405b261ecSmrg DrawablePtr pDraw; 104505b261ecSmrg DepthPtr pDepth; 10464642e01fSmrg int i, rc; 104705b261ecSmrg ShmDescPtr shmdesc; 10484202a189Smrg ShmScrPrivateRec *screen_priv; 1049f7df2e56Smrg 105005b261ecSmrg REQUEST(xShmCreatePixmapReq); 105105b261ecSmrg unsigned int width, height, depth; 105205b261ecSmrg unsigned long size; 105305b261ecSmrg 105405b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 105505b261ecSmrg client->errorValue = stuff->pid; 105605b261ecSmrg if (!sharedPixmaps) 1057f7df2e56Smrg return BadImplementation; 105805b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 105905b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 1060f7df2e56Smrg DixGetAttrAccess); 106105b261ecSmrg if (rc != Success) 1062f7df2e56Smrg return rc; 106305b261ecSmrg 106405b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 1065f7df2e56Smrg 106605b261ecSmrg width = stuff->width; 106705b261ecSmrg height = stuff->height; 106805b261ecSmrg depth = stuff->depth; 1069f7df2e56Smrg if (!width || !height || !depth) { 1070f7df2e56Smrg client->errorValue = 0; 107105b261ecSmrg return BadValue; 107205b261ecSmrg } 107305b261ecSmrg if (width > 32767 || height > 32767) 1074f7df2e56Smrg return BadAlloc; 107505b261ecSmrg 1076f7df2e56Smrg if (stuff->depth != 1) { 107705b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 1078f7df2e56Smrg for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 1079f7df2e56Smrg if (pDepth->depth == stuff->depth) 1080f7df2e56Smrg goto CreatePmap; 1081f7df2e56Smrg client->errorValue = stuff->depth; 108205b261ecSmrg return BadValue; 108305b261ecSmrg } 108405b261ecSmrg 1085f7df2e56Smrg CreatePmap: 108605b261ecSmrg size = PixmapBytePad(width, depth) * height; 108705b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 1088f7df2e56Smrg if (size < width * height) 1089f7df2e56Smrg return BadAlloc; 109005b261ecSmrg } 109105b261ecSmrg /* thankfully, offset is unsigned */ 109205b261ecSmrg if (stuff->offset + size < size) 1093f7df2e56Smrg return BadAlloc; 109405b261ecSmrg 109505b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 10964202a189Smrg screen_priv = ShmGetScreenPriv(pDraw->pScreen); 1097f7df2e56Smrg pMap = (*screen_priv->shmFuncs->CreatePixmap) (pDraw->pScreen, stuff->width, 1098f7df2e56Smrg stuff->height, stuff->depth, 1099f7df2e56Smrg shmdesc->addr + 1100f7df2e56Smrg stuff->offset); 1101f7df2e56Smrg if (pMap) { 1102f7df2e56Smrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 1103f7df2e56Smrg pMap, RT_NONE, NULL, DixCreateAccess); 1104f7df2e56Smrg if (rc != Success) { 1105f7df2e56Smrg pDraw->pScreen->DestroyPixmap(pMap); 1106f7df2e56Smrg return rc; 1107f7df2e56Smrg } 1108f7df2e56Smrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc); 1109f7df2e56Smrg shmdesc->refcnt++; 1110f7df2e56Smrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1111f7df2e56Smrg pMap->drawable.id = stuff->pid; 1112f7df2e56Smrg if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap)) { 1113f7df2e56Smrg return Success; 1114f7df2e56Smrg } 1115f7df2e56Smrg } 1116f7df2e56Smrg return BadAlloc; 1117f7df2e56Smrg} 1118f7df2e56Smrg 1119f7df2e56Smrg#ifdef SHM_FD_PASSING 1120f7df2e56Smrg 1121f7df2e56Smrgstatic void 1122f7df2e56SmrgShmBusfaultNotify(void *context) 1123f7df2e56Smrg{ 1124f7df2e56Smrg ShmDescPtr shmdesc = context; 1125f7df2e56Smrg 1126f7df2e56Smrg ErrorF("shared memory 0x%x truncated by client\n", 1127f7df2e56Smrg (unsigned int) shmdesc->resource); 1128f7df2e56Smrg busfault_unregister(shmdesc->busfault); 1129f7df2e56Smrg shmdesc->busfault = NULL; 1130f7df2e56Smrg FreeResource (shmdesc->resource, RT_NONE); 1131f7df2e56Smrg} 1132f7df2e56Smrg 1133f7df2e56Smrgstatic int 1134f7df2e56SmrgProcShmAttachFd(ClientPtr client) 1135f7df2e56Smrg{ 1136f7df2e56Smrg int fd; 1137f7df2e56Smrg ShmDescPtr shmdesc; 1138f7df2e56Smrg REQUEST(xShmAttachFdReq); 1139f7df2e56Smrg struct stat statb; 1140f7df2e56Smrg 1141f7df2e56Smrg SetReqFds(client, 1); 1142f7df2e56Smrg REQUEST_SIZE_MATCH(xShmAttachFdReq); 1143f7df2e56Smrg LEGAL_NEW_RESOURCE(stuff->shmseg, client); 1144f7df2e56Smrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 1145f7df2e56Smrg client->errorValue = stuff->readOnly; 1146f7df2e56Smrg return BadValue; 1147f7df2e56Smrg } 1148f7df2e56Smrg fd = ReadFdFromClient(client); 1149f7df2e56Smrg if (fd < 0) 1150f7df2e56Smrg return BadMatch; 1151f7df2e56Smrg 1152f7df2e56Smrg if (fstat(fd, &statb) < 0 || statb.st_size == 0) { 1153f7df2e56Smrg close(fd); 1154f7df2e56Smrg return BadMatch; 1155f7df2e56Smrg } 1156f7df2e56Smrg 1157f7df2e56Smrg shmdesc = malloc(sizeof(ShmDescRec)); 1158f7df2e56Smrg if (!shmdesc) { 1159f7df2e56Smrg close(fd); 1160f7df2e56Smrg return BadAlloc; 1161f7df2e56Smrg } 1162f7df2e56Smrg shmdesc->is_fd = TRUE; 1163f7df2e56Smrg shmdesc->addr = mmap(NULL, statb.st_size, 1164f7df2e56Smrg stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, 1165f7df2e56Smrg MAP_SHARED, 1166f7df2e56Smrg fd, 0); 1167f7df2e56Smrg 1168f7df2e56Smrg close(fd); 1169f7df2e56Smrg if (shmdesc->addr == ((char *) -1)) { 1170f7df2e56Smrg free(shmdesc); 1171f7df2e56Smrg return BadAccess; 1172f7df2e56Smrg } 1173f7df2e56Smrg 1174f7df2e56Smrg shmdesc->refcnt = 1; 1175f7df2e56Smrg shmdesc->writable = !stuff->readOnly; 1176f7df2e56Smrg shmdesc->size = statb.st_size; 1177f7df2e56Smrg shmdesc->resource = stuff->shmseg; 1178f7df2e56Smrg 1179f7df2e56Smrg shmdesc->busfault = busfault_register_mmap(shmdesc->addr, shmdesc->size, ShmBusfaultNotify, shmdesc); 1180f7df2e56Smrg if (!shmdesc->busfault) { 1181f7df2e56Smrg munmap(shmdesc->addr, shmdesc->size); 1182f7df2e56Smrg free(shmdesc); 1183f7df2e56Smrg return BadAlloc; 1184f7df2e56Smrg } 1185f7df2e56Smrg 1186f7df2e56Smrg shmdesc->next = Shmsegs; 1187f7df2e56Smrg Shmsegs = shmdesc; 1188f7df2e56Smrg 1189f7df2e56Smrg if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) 1190f7df2e56Smrg return BadAlloc; 1191f7df2e56Smrg return Success; 1192f7df2e56Smrg} 1193f7df2e56Smrg 1194f7df2e56Smrgstatic int 1195f7df2e56Smrgshm_tmpfile(void) 1196f7df2e56Smrg{ 1197f7df2e56Smrg#ifdef SHMDIR 1198f7df2e56Smrg int fd; 1199f7df2e56Smrg char template[] = SHMDIR "/shmfd-XXXXXX"; 1200f7df2e56Smrg#ifdef O_TMPFILE 1201f7df2e56Smrg fd = open(SHMDIR, O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666); 1202f7df2e56Smrg if (fd >= 0) { 12037e31ba66Smrg DebugF ("Using O_TMPFILE\n"); 1204f7df2e56Smrg return fd; 12054642e01fSmrg } 1206f7df2e56Smrg ErrorF ("Not using O_TMPFILE\n"); 1207f7df2e56Smrg#endif 12087e31ba66Smrg#ifdef HAVE_MKOSTEMP 12097e31ba66Smrg fd = mkostemp(template, O_CLOEXEC); 12107e31ba66Smrg#else 1211f7df2e56Smrg fd = mkstemp(template); 12127e31ba66Smrg#endif 1213f7df2e56Smrg if (fd < 0) 1214f7df2e56Smrg return -1; 1215f7df2e56Smrg unlink(template); 12167e31ba66Smrg#ifndef HAVE_MKOSTEMP 12177e31ba66Smrg int flags = fcntl(fd, F_GETFD); 12187e31ba66Smrg if (flags != -1) { 1219f7df2e56Smrg flags |= FD_CLOEXEC; 1220f7df2e56Smrg (void) fcntl(fd, F_SETFD, &flags); 122105b261ecSmrg } 12227e31ba66Smrg#endif 1223f7df2e56Smrg return fd; 1224f7df2e56Smrg#else 1225f7df2e56Smrg return -1; 1226f7df2e56Smrg#endif 1227f7df2e56Smrg} 1228f7df2e56Smrg 1229f7df2e56Smrgstatic int 1230f7df2e56SmrgProcShmCreateSegment(ClientPtr client) 1231f7df2e56Smrg{ 1232f7df2e56Smrg int fd; 1233f7df2e56Smrg ShmDescPtr shmdesc; 1234f7df2e56Smrg REQUEST(xShmCreateSegmentReq); 1235f7df2e56Smrg xShmCreateSegmentReply rep = { 1236f7df2e56Smrg .type = X_Reply, 1237f7df2e56Smrg .nfd = 1, 1238f7df2e56Smrg .sequenceNumber = client->sequence, 1239f7df2e56Smrg .length = 0, 1240f7df2e56Smrg }; 1241f7df2e56Smrg 1242f7df2e56Smrg REQUEST_SIZE_MATCH(xShmCreateSegmentReq); 12437e31ba66Smrg LEGAL_NEW_RESOURCE(stuff->shmseg, client); 1244f7df2e56Smrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 1245f7df2e56Smrg client->errorValue = stuff->readOnly; 1246f7df2e56Smrg return BadValue; 124705b261ecSmrg } 1248f7df2e56Smrg fd = shm_tmpfile(); 1249f7df2e56Smrg if (fd < 0) 1250f7df2e56Smrg return BadAlloc; 1251f7df2e56Smrg if (ftruncate(fd, stuff->size) < 0) { 1252f7df2e56Smrg close(fd); 1253f7df2e56Smrg return BadAlloc; 1254f7df2e56Smrg } 1255f7df2e56Smrg shmdesc = malloc(sizeof(ShmDescRec)); 1256f7df2e56Smrg if (!shmdesc) { 1257f7df2e56Smrg close(fd); 1258f7df2e56Smrg return BadAlloc; 1259f7df2e56Smrg } 1260f7df2e56Smrg shmdesc->is_fd = TRUE; 1261f7df2e56Smrg shmdesc->addr = mmap(NULL, stuff->size, 1262f7df2e56Smrg stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, 1263f7df2e56Smrg MAP_SHARED, 1264f7df2e56Smrg fd, 0); 1265f7df2e56Smrg 1266f7df2e56Smrg if (shmdesc->addr == ((char *) -1)) { 1267f7df2e56Smrg close(fd); 1268f7df2e56Smrg free(shmdesc); 1269f7df2e56Smrg return BadAccess; 1270f7df2e56Smrg } 1271f7df2e56Smrg 1272f7df2e56Smrg shmdesc->refcnt = 1; 1273f7df2e56Smrg shmdesc->writable = !stuff->readOnly; 1274f7df2e56Smrg shmdesc->size = stuff->size; 1275f7df2e56Smrg 1276f7df2e56Smrg shmdesc->busfault = busfault_register_mmap(shmdesc->addr, shmdesc->size, ShmBusfaultNotify, shmdesc); 1277f7df2e56Smrg if (!shmdesc->busfault) { 1278f7df2e56Smrg close(fd); 1279f7df2e56Smrg munmap(shmdesc->addr, shmdesc->size); 1280f7df2e56Smrg free(shmdesc); 1281f7df2e56Smrg return BadAlloc; 1282f7df2e56Smrg } 1283f7df2e56Smrg 1284f7df2e56Smrg shmdesc->next = Shmsegs; 1285f7df2e56Smrg Shmsegs = shmdesc; 1286f7df2e56Smrg 1287f7df2e56Smrg if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) { 1288f7df2e56Smrg close(fd); 1289f7df2e56Smrg return BadAlloc; 1290f7df2e56Smrg } 1291f7df2e56Smrg 1292f7df2e56Smrg if (WriteFdToClient(client, fd, TRUE) < 0) { 1293f7df2e56Smrg FreeResource(stuff->shmseg, RT_NONE); 1294f7df2e56Smrg close(fd); 1295f7df2e56Smrg return BadAlloc; 1296f7df2e56Smrg } 1297f7df2e56Smrg WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep); 1298f7df2e56Smrg return Success; 129905b261ecSmrg} 1300f7df2e56Smrg#endif /* SHM_FD_PASSING */ 130105b261ecSmrg 130205b261ecSmrgstatic int 1303f7df2e56SmrgProcShmDispatch(ClientPtr client) 130405b261ecSmrg{ 130505b261ecSmrg REQUEST(xReq); 13067e31ba66Smrg 13077e31ba66Smrg if (stuff->data == X_ShmQueryVersion) 1308f7df2e56Smrg return ProcShmQueryVersion(client); 13097e31ba66Smrg 13107e31ba66Smrg if (!client->local) 13117e31ba66Smrg return BadRequest; 13127e31ba66Smrg 13137e31ba66Smrg switch (stuff->data) { 131405b261ecSmrg case X_ShmAttach: 1315f7df2e56Smrg return ProcShmAttach(client); 131605b261ecSmrg case X_ShmDetach: 1317f7df2e56Smrg return ProcShmDetach(client); 131805b261ecSmrg case X_ShmPutImage: 131905b261ecSmrg#ifdef PANORAMIX 1320f7df2e56Smrg if (!noPanoramiXExtension) 1321f7df2e56Smrg return ProcPanoramiXShmPutImage(client); 132205b261ecSmrg#endif 1323f7df2e56Smrg return ProcShmPutImage(client); 132405b261ecSmrg case X_ShmGetImage: 132505b261ecSmrg#ifdef PANORAMIX 1326f7df2e56Smrg if (!noPanoramiXExtension) 1327f7df2e56Smrg return ProcPanoramiXShmGetImage(client); 132805b261ecSmrg#endif 1329f7df2e56Smrg return ProcShmGetImage(client); 133005b261ecSmrg case X_ShmCreatePixmap: 133105b261ecSmrg#ifdef PANORAMIX 1332f7df2e56Smrg if (!noPanoramiXExtension) 1333f7df2e56Smrg return ProcPanoramiXShmCreatePixmap(client); 1334f7df2e56Smrg#endif 1335f7df2e56Smrg return ProcShmCreatePixmap(client); 1336f7df2e56Smrg#ifdef SHM_FD_PASSING 1337f7df2e56Smrg case X_ShmAttachFd: 1338f7df2e56Smrg return ProcShmAttachFd(client); 1339f7df2e56Smrg case X_ShmCreateSegment: 1340f7df2e56Smrg return ProcShmCreateSegment(client); 134105b261ecSmrg#endif 134205b261ecSmrg default: 1343f7df2e56Smrg return BadRequest; 134405b261ecSmrg } 134505b261ecSmrg} 134605b261ecSmrg 13477e31ba66Smrgstatic void _X_COLD 1348f7df2e56SmrgSShmCompletionEvent(xShmCompletionEvent * from, xShmCompletionEvent * to) 134905b261ecSmrg{ 135005b261ecSmrg to->type = from->type; 135105b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 135205b261ecSmrg cpswapl(from->drawable, to->drawable); 135305b261ecSmrg cpswaps(from->minorEvent, to->minorEvent); 135405b261ecSmrg to->majorEvent = from->majorEvent; 135505b261ecSmrg cpswapl(from->shmseg, to->shmseg); 135605b261ecSmrg cpswapl(from->offset, to->offset); 135705b261ecSmrg} 135805b261ecSmrg 13597e31ba66Smrgstatic int _X_COLD 13604642e01fSmrgSProcShmQueryVersion(ClientPtr client) 136105b261ecSmrg{ 136205b261ecSmrg REQUEST(xShmQueryVersionReq); 136305b261ecSmrg 1364f7df2e56Smrg swaps(&stuff->length); 136505b261ecSmrg return ProcShmQueryVersion(client); 136605b261ecSmrg} 136705b261ecSmrg 13687e31ba66Smrgstatic int _X_COLD 13694642e01fSmrgSProcShmAttach(ClientPtr client) 137005b261ecSmrg{ 137105b261ecSmrg REQUEST(xShmAttachReq); 1372f7df2e56Smrg swaps(&stuff->length); 137305b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 1374f7df2e56Smrg swapl(&stuff->shmseg); 1375f7df2e56Smrg swapl(&stuff->shmid); 137605b261ecSmrg return ProcShmAttach(client); 137705b261ecSmrg} 137805b261ecSmrg 13797e31ba66Smrgstatic int _X_COLD 13804642e01fSmrgSProcShmDetach(ClientPtr client) 138105b261ecSmrg{ 138205b261ecSmrg REQUEST(xShmDetachReq); 1383f7df2e56Smrg swaps(&stuff->length); 138405b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 1385f7df2e56Smrg swapl(&stuff->shmseg); 138605b261ecSmrg return ProcShmDetach(client); 138705b261ecSmrg} 138805b261ecSmrg 13897e31ba66Smrgstatic int _X_COLD 13904642e01fSmrgSProcShmPutImage(ClientPtr client) 139105b261ecSmrg{ 139205b261ecSmrg REQUEST(xShmPutImageReq); 1393f7df2e56Smrg swaps(&stuff->length); 139405b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 1395f7df2e56Smrg swapl(&stuff->drawable); 1396f7df2e56Smrg swapl(&stuff->gc); 1397f7df2e56Smrg swaps(&stuff->totalWidth); 1398f7df2e56Smrg swaps(&stuff->totalHeight); 1399f7df2e56Smrg swaps(&stuff->srcX); 1400f7df2e56Smrg swaps(&stuff->srcY); 1401f7df2e56Smrg swaps(&stuff->srcWidth); 1402f7df2e56Smrg swaps(&stuff->srcHeight); 1403f7df2e56Smrg swaps(&stuff->dstX); 1404f7df2e56Smrg swaps(&stuff->dstY); 1405f7df2e56Smrg swapl(&stuff->shmseg); 1406f7df2e56Smrg swapl(&stuff->offset); 140705b261ecSmrg return ProcShmPutImage(client); 140805b261ecSmrg} 140905b261ecSmrg 14107e31ba66Smrgstatic int _X_COLD 14114642e01fSmrgSProcShmGetImage(ClientPtr client) 141205b261ecSmrg{ 141305b261ecSmrg REQUEST(xShmGetImageReq); 1414f7df2e56Smrg swaps(&stuff->length); 141505b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 1416f7df2e56Smrg swapl(&stuff->drawable); 1417f7df2e56Smrg swaps(&stuff->x); 1418f7df2e56Smrg swaps(&stuff->y); 1419f7df2e56Smrg swaps(&stuff->width); 1420f7df2e56Smrg swaps(&stuff->height); 1421f7df2e56Smrg swapl(&stuff->planeMask); 1422f7df2e56Smrg swapl(&stuff->shmseg); 1423f7df2e56Smrg swapl(&stuff->offset); 142405b261ecSmrg return ProcShmGetImage(client); 142505b261ecSmrg} 142605b261ecSmrg 14277e31ba66Smrgstatic int _X_COLD 14284642e01fSmrgSProcShmCreatePixmap(ClientPtr client) 142905b261ecSmrg{ 143005b261ecSmrg REQUEST(xShmCreatePixmapReq); 1431f7df2e56Smrg swaps(&stuff->length); 143205b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 1433f7df2e56Smrg swapl(&stuff->pid); 1434f7df2e56Smrg swapl(&stuff->drawable); 1435f7df2e56Smrg swaps(&stuff->width); 1436f7df2e56Smrg swaps(&stuff->height); 1437f7df2e56Smrg swapl(&stuff->shmseg); 1438f7df2e56Smrg swapl(&stuff->offset); 143905b261ecSmrg return ProcShmCreatePixmap(client); 144005b261ecSmrg} 144105b261ecSmrg 1442f7df2e56Smrg#ifdef SHM_FD_PASSING 14437e31ba66Smrgstatic int _X_COLD 1444f7df2e56SmrgSProcShmAttachFd(ClientPtr client) 1445f7df2e56Smrg{ 1446f7df2e56Smrg REQUEST(xShmAttachFdReq); 1447f7df2e56Smrg SetReqFds(client, 1); 1448f7df2e56Smrg swaps(&stuff->length); 1449f7df2e56Smrg REQUEST_SIZE_MATCH(xShmAttachFdReq); 1450f7df2e56Smrg swapl(&stuff->shmseg); 1451f7df2e56Smrg return ProcShmAttachFd(client); 1452f7df2e56Smrg} 1453f7df2e56Smrg 14547e31ba66Smrgstatic int _X_COLD 1455f7df2e56SmrgSProcShmCreateSegment(ClientPtr client) 1456f7df2e56Smrg{ 1457f7df2e56Smrg REQUEST(xShmCreateSegmentReq); 1458f7df2e56Smrg swaps(&stuff->length); 1459f7df2e56Smrg REQUEST_SIZE_MATCH(xShmCreateSegmentReq); 1460f7df2e56Smrg swapl(&stuff->shmseg); 1461f7df2e56Smrg swapl(&stuff->size); 1462f7df2e56Smrg return ProcShmCreateSegment(client); 1463f7df2e56Smrg} 1464f7df2e56Smrg#endif /* SHM_FD_PASSING */ 1465f7df2e56Smrg 14667e31ba66Smrgstatic int _X_COLD 1467f7df2e56SmrgSProcShmDispatch(ClientPtr client) 146805b261ecSmrg{ 146905b261ecSmrg REQUEST(xReq); 14707e31ba66Smrg 14717e31ba66Smrg if (stuff->data == X_ShmQueryVersion) 1472f7df2e56Smrg return SProcShmQueryVersion(client); 14737e31ba66Smrg 14747e31ba66Smrg if (!client->local) 14757e31ba66Smrg return BadRequest; 14767e31ba66Smrg 14777e31ba66Smrg switch (stuff->data) { 147805b261ecSmrg case X_ShmAttach: 1479f7df2e56Smrg return SProcShmAttach(client); 148005b261ecSmrg case X_ShmDetach: 1481f7df2e56Smrg return SProcShmDetach(client); 148205b261ecSmrg case X_ShmPutImage: 1483f7df2e56Smrg return SProcShmPutImage(client); 148405b261ecSmrg case X_ShmGetImage: 1485f7df2e56Smrg return SProcShmGetImage(client); 148605b261ecSmrg case X_ShmCreatePixmap: 1487f7df2e56Smrg return SProcShmCreatePixmap(client); 1488f7df2e56Smrg#ifdef SHM_FD_PASSING 1489f7df2e56Smrg case X_ShmAttachFd: 1490f7df2e56Smrg return SProcShmAttachFd(client); 1491f7df2e56Smrg case X_ShmCreateSegment: 1492f7df2e56Smrg return SProcShmCreateSegment(client); 1493f7df2e56Smrg#endif 149405b261ecSmrg default: 1495f7df2e56Smrg return BadRequest; 149605b261ecSmrg } 149705b261ecSmrg} 149865b04b38Smrg 149965b04b38Smrgvoid 1500f7df2e56SmrgShmExtensionInit(void) 150165b04b38Smrg{ 150265b04b38Smrg ExtensionEntry *extEntry; 150365b04b38Smrg int i; 150465b04b38Smrg 150565b04b38Smrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL 1506f7df2e56Smrg if (!CheckForShmSyscall()) { 1507f7df2e56Smrg ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); 1508f7df2e56Smrg return; 150965b04b38Smrg } 151065b04b38Smrg#endif 151165b04b38Smrg 151265b04b38Smrg if (!ShmRegisterPrivates()) 1513f7df2e56Smrg return; 151465b04b38Smrg 151565b04b38Smrg sharedPixmaps = xFalse; 151665b04b38Smrg { 1517f7df2e56Smrg sharedPixmaps = xTrue; 1518f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 1519f7df2e56Smrg ShmScrPrivateRec *screen_priv = 1520f7df2e56Smrg ShmInitScreenPriv(screenInfo.screens[i]); 1521f7df2e56Smrg if (!screen_priv->shmFuncs) 1522f7df2e56Smrg screen_priv->shmFuncs = &miFuncs; 1523f7df2e56Smrg if (!screen_priv->shmFuncs->CreatePixmap) 1524f7df2e56Smrg sharedPixmaps = xFalse; 1525f7df2e56Smrg } 1526f7df2e56Smrg if (sharedPixmaps) 1527f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 1528f7df2e56Smrg ShmScrPrivateRec *screen_priv = 1529f7df2e56Smrg ShmGetScreenPriv(screenInfo.screens[i]); 1530f7df2e56Smrg screen_priv->destroyPixmap = 1531f7df2e56Smrg screenInfo.screens[i]->DestroyPixmap; 1532f7df2e56Smrg screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; 1533f7df2e56Smrg } 153465b04b38Smrg } 153565b04b38Smrg ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg"); 153665b04b38Smrg if (ShmSegType && 1537f7df2e56Smrg (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, 1538f7df2e56Smrg ProcShmDispatch, SProcShmDispatch, 1539f7df2e56Smrg ShmResetProc, StandardMinorOpcode))) { 1540f7df2e56Smrg ShmReqCode = (unsigned char) extEntry->base; 1541f7df2e56Smrg ShmCompletionCode = extEntry->eventBase; 1542f7df2e56Smrg BadShmSegCode = extEntry->errorBase; 1543f7df2e56Smrg SetResourceTypeErrorValue(ShmSegType, BadShmSegCode); 1544f7df2e56Smrg EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; 154565b04b38Smrg } 154665b04b38Smrg} 1547