shm.c revision f7df2e56
1/************************************************************ 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25********************************************************/ 26 27/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ 28 29#define SHM 30 31#ifdef HAVE_DIX_CONFIG_H 32#include <dix-config.h> 33#endif 34 35#include <sys/types.h> 36#include <sys/ipc.h> 37#include <sys/shm.h> 38#include <unistd.h> 39#include <sys/stat.h> 40#include <fcntl.h> 41#include <X11/X.h> 42#include <X11/Xproto.h> 43#include "misc.h" 44#include "os.h" 45#include "dixstruct.h" 46#include "resource.h" 47#include "scrnintstr.h" 48#include "windowstr.h" 49#include "pixmapstr.h" 50#include "gcstruct.h" 51#include "extnsionst.h" 52#include "servermd.h" 53#include "shmint.h" 54#include "xace.h" 55#include <X11/extensions/shmproto.h> 56#include <X11/Xfuncproto.h> 57#include <sys/mman.h> 58#include "protocol-versions.h" 59#include "busfault.h" 60 61/* Needed for Solaris cross-zone shared memory extension */ 62#ifdef HAVE_SHMCTL64 63#include <sys/ipc_impl.h> 64#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf) 65#define SHMSTAT_TYPE struct shmid_ds64 66#define SHMPERM_TYPE struct ipc_perm64 67#define SHM_PERM(buf) buf.shmx_perm 68#define SHM_SEGSZ(buf) buf.shmx_segsz 69#define SHMPERM_UID(p) p->ipcx_uid 70#define SHMPERM_CUID(p) p->ipcx_cuid 71#define SHMPERM_GID(p) p->ipcx_gid 72#define SHMPERM_CGID(p) p->ipcx_cgid 73#define SHMPERM_MODE(p) p->ipcx_mode 74#define SHMPERM_ZONEID(p) p->ipcx_zoneid 75#else 76#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf) 77#define SHMSTAT_TYPE struct shmid_ds 78#define SHMPERM_TYPE struct ipc_perm 79#define SHM_PERM(buf) buf.shm_perm 80#define SHM_SEGSZ(buf) buf.shm_segsz 81#define SHMPERM_UID(p) p->uid 82#define SHMPERM_CUID(p) p->cuid 83#define SHMPERM_GID(p) p->gid 84#define SHMPERM_CGID(p) p->cgid 85#define SHMPERM_MODE(p) p->mode 86#endif 87 88#ifdef PANORAMIX 89#include "panoramiX.h" 90#include "panoramiXsrv.h" 91#endif 92 93#include "extinit.h" 94 95typedef struct _ShmScrPrivateRec { 96 CloseScreenProcPtr CloseScreen; 97 ShmFuncsPtr shmFuncs; 98 DestroyPixmapProcPtr destroyPixmap; 99} ShmScrPrivateRec; 100 101static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); 102static int ShmDetachSegment(void *value, XID shmseg); 103static void ShmResetProc(ExtensionEntry *extEntry); 104static void SShmCompletionEvent(xShmCompletionEvent *from, 105 xShmCompletionEvent *to); 106 107static Bool ShmDestroyPixmap(PixmapPtr pPixmap); 108 109static unsigned char ShmReqCode; 110int ShmCompletionCode; 111int BadShmSegCode; 112RESTYPE ShmSegType; 113static ShmDescPtr Shmsegs; 114static Bool sharedPixmaps; 115static DevPrivateKeyRec shmScrPrivateKeyRec; 116 117#define shmScrPrivateKey (&shmScrPrivateKeyRec) 118static DevPrivateKeyRec shmPixmapPrivateKeyRec; 119 120#define shmPixmapPrivateKey (&shmPixmapPrivateKeyRec) 121static ShmFuncs miFuncs = { NULL, NULL }; 122static ShmFuncs fbFuncs = { fbShmCreatePixmap, NULL }; 123 124#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey)) 125 126#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ 127{ \ 128 int tmprc; \ 129 tmprc = dixLookupResourceByType((void **)&(shmdesc), shmseg, ShmSegType, \ 130 client, DixReadAccess); \ 131 if (tmprc != Success) \ 132 return tmprc; \ 133} 134 135#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ 136{ \ 137 VERIFY_SHMSEG(shmseg, shmdesc, client); \ 138 if ((offset & 3) || (offset > shmdesc->size)) \ 139 { \ 140 client->errorValue = offset; \ 141 return BadValue; \ 142 } \ 143 if (needwrite && !shmdesc->writable) \ 144 return BadAccess; \ 145} 146 147#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ 148{ \ 149 if ((offset + len) > shmdesc->size) \ 150 { \ 151 return BadAccess; \ 152 } \ 153} 154 155#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) 156#include <sys/signal.h> 157 158static Bool badSysCall = FALSE; 159 160static void 161SigSysHandler(int signo) 162{ 163 badSysCall = TRUE; 164} 165 166static Bool 167CheckForShmSyscall(void) 168{ 169 void (*oldHandler) (int); 170 int shmid = -1; 171 172 /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ 173 oldHandler = signal(SIGSYS, SigSysHandler); 174 175 badSysCall = FALSE; 176 shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); 177 178 if (shmid != -1) { 179 /* Successful allocation - clean up */ 180 shmctl(shmid, IPC_RMID, NULL); 181 } 182 else { 183 /* Allocation failed */ 184 badSysCall = TRUE; 185 } 186 signal(SIGSYS, oldHandler); 187 return !badSysCall; 188} 189 190#define MUST_CHECK_FOR_SHM_SYSCALL 191 192#endif 193 194static Bool 195ShmCloseScreen(ScreenPtr pScreen) 196{ 197 ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 198 199 pScreen->CloseScreen = screen_priv->CloseScreen; 200 dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL); 201 free(screen_priv); 202 return (*pScreen->CloseScreen) (pScreen); 203} 204 205static ShmScrPrivateRec * 206ShmInitScreenPriv(ScreenPtr pScreen) 207{ 208 ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 209 210 if (!screen_priv) { 211 screen_priv = calloc(1, sizeof(ShmScrPrivateRec)); 212 screen_priv->CloseScreen = pScreen->CloseScreen; 213 dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv); 214 pScreen->CloseScreen = ShmCloseScreen; 215 } 216 return screen_priv; 217} 218 219static Bool 220ShmRegisterPrivates(void) 221{ 222 if (!dixRegisterPrivateKey(&shmScrPrivateKeyRec, PRIVATE_SCREEN, 0)) 223 return FALSE; 224 if (!dixRegisterPrivateKey(&shmPixmapPrivateKeyRec, PRIVATE_PIXMAP, 0)) 225 return FALSE; 226 return TRUE; 227} 228 229 /*ARGSUSED*/ static void 230ShmResetProc(ExtensionEntry * extEntry) 231{ 232 int i; 233 234 for (i = 0; i < screenInfo.numScreens; i++) 235 ShmRegisterFuncs(screenInfo.screens[i], NULL); 236} 237 238void 239ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) 240{ 241 if (!ShmRegisterPrivates()) 242 return; 243 ShmInitScreenPriv(pScreen)->shmFuncs = funcs; 244} 245 246static Bool 247ShmDestroyPixmap(PixmapPtr pPixmap) 248{ 249 ScreenPtr pScreen = pPixmap->drawable.pScreen; 250 ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); 251 void *shmdesc = NULL; 252 Bool ret; 253 254 if (pPixmap->refcnt == 1) 255 shmdesc = dixLookupPrivate(&pPixmap->devPrivates, shmPixmapPrivateKey); 256 257 pScreen->DestroyPixmap = screen_priv->destroyPixmap; 258 ret = (*pScreen->DestroyPixmap) (pPixmap); 259 screen_priv->destroyPixmap = pScreen->DestroyPixmap; 260 pScreen->DestroyPixmap = ShmDestroyPixmap; 261 262 if (shmdesc) 263 ShmDetachSegment(shmdesc, 0); 264 265 return ret; 266} 267 268void 269ShmRegisterFbFuncs(ScreenPtr pScreen) 270{ 271 ShmRegisterFuncs(pScreen, &fbFuncs); 272} 273 274static int 275ProcShmQueryVersion(ClientPtr client) 276{ 277 xShmQueryVersionReply rep = { 278 .type = X_Reply, 279 .sharedPixmaps = sharedPixmaps, 280 .sequenceNumber = client->sequence, 281 .length = 0, 282 .majorVersion = SERVER_SHM_MAJOR_VERSION, 283 .minorVersion = SERVER_SHM_MINOR_VERSION, 284 .uid = geteuid(), 285 .gid = getegid(), 286 .pixmapFormat = sharedPixmaps ? ZPixmap : 0 287 }; 288 289 REQUEST_SIZE_MATCH(xShmQueryVersionReq); 290 291 if (client->swapped) { 292 swaps(&rep.sequenceNumber); 293 swapl(&rep.length); 294 swaps(&rep.majorVersion); 295 swaps(&rep.minorVersion); 296 swaps(&rep.uid); 297 swaps(&rep.gid); 298 } 299 WriteToClient(client, sizeof(xShmQueryVersionReply), &rep); 300 return Success; 301} 302 303/* 304 * Simulate the access() system call for a shared memory segement, 305 * using the credentials from the client if available 306 */ 307static int 308shm_access(ClientPtr client, SHMPERM_TYPE * perm, int readonly) 309{ 310 int uid, gid; 311 mode_t mask; 312 int uidset = 0, gidset = 0; 313 LocalClientCredRec *lcc; 314 315 if (GetLocalClientCreds(client, &lcc) != -1) { 316 317 if (lcc->fieldsSet & LCC_UID_SET) { 318 uid = lcc->euid; 319 uidset = 1; 320 } 321 if (lcc->fieldsSet & LCC_GID_SET) { 322 gid = lcc->egid; 323 gidset = 1; 324 } 325 326#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) 327 if (((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) 328 || (lcc->zoneid != SHMPERM_ZONEID(perm))) { 329 uidset = 0; 330 gidset = 0; 331 } 332#endif 333 FreeLocalClientCreds(lcc); 334 335 if (uidset) { 336 /* User id 0 always gets access */ 337 if (uid == 0) { 338 return 0; 339 } 340 /* Check the owner */ 341 if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { 342 mask = S_IRUSR; 343 if (!readonly) { 344 mask |= S_IWUSR; 345 } 346 return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 347 } 348 } 349 350 if (gidset) { 351 /* Check the group */ 352 if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { 353 mask = S_IRGRP; 354 if (!readonly) { 355 mask |= S_IWGRP; 356 } 357 return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 358 } 359 } 360 } 361 /* Otherwise, check everyone else */ 362 mask = S_IROTH; 363 if (!readonly) { 364 mask |= S_IWOTH; 365 } 366 return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 367} 368 369static int 370ProcShmAttach(ClientPtr client) 371{ 372 SHMSTAT_TYPE buf; 373 ShmDescPtr shmdesc; 374 375 REQUEST(xShmAttachReq); 376 377 REQUEST_SIZE_MATCH(xShmAttachReq); 378 LEGAL_NEW_RESOURCE(stuff->shmseg, client); 379 if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 380 client->errorValue = stuff->readOnly; 381 return BadValue; 382 } 383 for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) { 384 if (!SHMDESC_IS_FD(shmdesc) && shmdesc->shmid == stuff->shmid) 385 break; 386 } 387 if (shmdesc) { 388 if (!stuff->readOnly && !shmdesc->writable) 389 return BadAccess; 390 shmdesc->refcnt++; 391 } 392 else { 393 shmdesc = malloc(sizeof(ShmDescRec)); 394 if (!shmdesc) 395 return BadAlloc; 396#ifdef SHM_FD_PASSING 397 shmdesc->is_fd = FALSE; 398#endif 399 shmdesc->addr = shmat(stuff->shmid, 0, 400 stuff->readOnly ? SHM_RDONLY : 0); 401 if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) { 402 free(shmdesc); 403 return BadAccess; 404 } 405 406 /* The attach was performed with root privs. We must 407 * do manual checking of access rights for the credentials 408 * of the client */ 409 410 if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { 411 shmdt(shmdesc->addr); 412 free(shmdesc); 413 return BadAccess; 414 } 415 416 shmdesc->shmid = stuff->shmid; 417 shmdesc->refcnt = 1; 418 shmdesc->writable = !stuff->readOnly; 419 shmdesc->size = SHM_SEGSZ(buf); 420 shmdesc->next = Shmsegs; 421 Shmsegs = shmdesc; 422 } 423 if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) 424 return BadAlloc; 425 return Success; 426} 427 428 /*ARGSUSED*/ static int 429ShmDetachSegment(void *value, /* must conform to DeleteType */ 430 XID unused) 431{ 432 ShmDescPtr shmdesc = (ShmDescPtr) value; 433 ShmDescPtr *prev; 434 435 if (--shmdesc->refcnt) 436 return TRUE; 437#if SHM_FD_PASSING 438 if (shmdesc->is_fd) { 439 if (shmdesc->busfault) 440 busfault_unregister(shmdesc->busfault); 441 munmap(shmdesc->addr, shmdesc->size); 442 } else 443#endif 444 shmdt(shmdesc->addr); 445 for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next); 446 *prev = shmdesc->next; 447 free(shmdesc); 448 return Success; 449} 450 451static int 452ProcShmDetach(ClientPtr client) 453{ 454 ShmDescPtr shmdesc; 455 456 REQUEST(xShmDetachReq); 457 458 REQUEST_SIZE_MATCH(xShmDetachReq); 459 VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); 460 FreeResource(stuff->shmseg, RT_NONE); 461 return Success; 462} 463 464/* 465 * If the given request doesn't exactly match PutImage's constraints, 466 * wrap the image in a scratch pixmap header and let CopyArea sort it out. 467 */ 468static void 469doShmPutImage(DrawablePtr dst, GCPtr pGC, 470 int depth, unsigned int format, 471 int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, 472 char *data) 473{ 474 PixmapPtr pPixmap; 475 476 if (format == ZPixmap || (format == XYPixmap && depth == 1)) { 477 pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, 478 BitsPerPixel(depth), 479 PixmapBytePad(w, depth), data); 480 if (!pPixmap) 481 return; 482 pGC->ops->CopyArea((DrawablePtr) pPixmap, dst, pGC, sx, sy, sw, sh, dx, 483 dy); 484 FreeScratchPixmapHeader(pPixmap); 485 } 486 else { 487 GCPtr putGC = GetScratchGC(depth, dst->pScreen); 488 489 if (!putGC) 490 return; 491 492 pPixmap = (*dst->pScreen->CreatePixmap) (dst->pScreen, sw, sh, depth, 493 CREATE_PIXMAP_USAGE_SCRATCH); 494 if (!pPixmap) { 495 FreeScratchGC(putGC); 496 return; 497 } 498 ValidateGC(&pPixmap->drawable, putGC); 499 (*putGC->ops->PutImage) (&pPixmap->drawable, putGC, depth, -sx, -sy, w, 500 h, 0, 501 (format == XYPixmap) ? XYPixmap : ZPixmap, 502 data); 503 FreeScratchGC(putGC); 504 if (format == XYBitmap) 505 (void) (*pGC->ops->CopyPlane) (&pPixmap->drawable, dst, pGC, 0, 0, 506 sw, sh, dx, dy, 1L); 507 else 508 (void) (*pGC->ops->CopyArea) (&pPixmap->drawable, dst, pGC, 0, 0, 509 sw, sh, dx, dy); 510 (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); 511 } 512} 513 514static int 515ProcShmPutImage(ClientPtr client) 516{ 517 GCPtr pGC; 518 DrawablePtr pDraw; 519 long length; 520 ShmDescPtr shmdesc; 521 522 REQUEST(xShmPutImageReq); 523 524 REQUEST_SIZE_MATCH(xShmPutImageReq); 525 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 526 VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); 527 if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) 528 return BadValue; 529 if (stuff->format == XYBitmap) { 530 if (stuff->depth != 1) 531 return BadMatch; 532 length = PixmapBytePad(stuff->totalWidth, 1); 533 } 534 else if (stuff->format == XYPixmap) { 535 if (pDraw->depth != stuff->depth) 536 return BadMatch; 537 length = PixmapBytePad(stuff->totalWidth, 1); 538 length *= stuff->depth; 539 } 540 else if (stuff->format == ZPixmap) { 541 if (pDraw->depth != stuff->depth) 542 return BadMatch; 543 length = PixmapBytePad(stuff->totalWidth, stuff->depth); 544 } 545 else { 546 client->errorValue = stuff->format; 547 return BadValue; 548 } 549 550 /* 551 * There's a potential integer overflow in this check: 552 * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, 553 * client); 554 * the version below ought to avoid it 555 */ 556 if (stuff->totalHeight != 0 && 557 length > (shmdesc->size - stuff->offset) / stuff->totalHeight) { 558 client->errorValue = stuff->totalWidth; 559 return BadValue; 560 } 561 if (stuff->srcX > stuff->totalWidth) { 562 client->errorValue = stuff->srcX; 563 return BadValue; 564 } 565 if (stuff->srcY > stuff->totalHeight) { 566 client->errorValue = stuff->srcY; 567 return BadValue; 568 } 569 if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) { 570 client->errorValue = stuff->srcWidth; 571 return BadValue; 572 } 573 if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) { 574 client->errorValue = stuff->srcHeight; 575 return BadValue; 576 } 577 578 if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || 579 ((stuff->format != ZPixmap) && 580 (stuff->srcX < screenInfo.bitmapScanlinePad) && 581 ((stuff->format == XYBitmap) || 582 ((stuff->srcY == 0) && 583 (stuff->srcHeight == stuff->totalHeight))))) && 584 ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) 585 (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, 586 stuff->dstX, stuff->dstY, 587 stuff->totalWidth, stuff->srcHeight, 588 stuff->srcX, stuff->format, 589 shmdesc->addr + stuff->offset + 590 (stuff->srcY * length)); 591 else 592 doShmPutImage(pDraw, pGC, stuff->depth, stuff->format, 593 stuff->totalWidth, stuff->totalHeight, 594 stuff->srcX, stuff->srcY, 595 stuff->srcWidth, stuff->srcHeight, 596 stuff->dstX, stuff->dstY, shmdesc->addr + stuff->offset); 597 598 if (stuff->sendEvent) { 599 xShmCompletionEvent ev = { 600 .type = ShmCompletionCode, 601 .drawable = stuff->drawable, 602 .minorEvent = X_ShmPutImage, 603 .majorEvent = ShmReqCode, 604 .shmseg = stuff->shmseg, 605 .offset = stuff->offset 606 }; 607 WriteEventsToClient(client, 1, (xEvent *) &ev); 608 } 609 610 return Success; 611} 612 613static int 614ProcShmGetImage(ClientPtr client) 615{ 616 DrawablePtr pDraw; 617 long lenPer = 0, length; 618 Mask plane = 0; 619 xShmGetImageReply xgi; 620 ShmDescPtr shmdesc; 621 VisualID visual = None; 622 RegionPtr pVisibleRegion = NULL; 623 int rc; 624 625 REQUEST(xShmGetImageReq); 626 627 REQUEST_SIZE_MATCH(xShmGetImageReq); 628 if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 629 client->errorValue = stuff->format; 630 return BadValue; 631 } 632 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess); 633 if (rc != Success) 634 return rc; 635 VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 636 if (pDraw->type == DRAWABLE_WINDOW) { 637 if ( /* check for being viewable */ 638 !((WindowPtr) pDraw)->realized || 639 /* check for being on screen */ 640 pDraw->x + stuff->x < 0 || 641 pDraw->x + stuff->x + (int) stuff->width > pDraw->pScreen->width 642 || pDraw->y + stuff->y < 0 || 643 pDraw->y + stuff->y + (int) stuff->height > 644 pDraw->pScreen->height || 645 /* check for being inside of border */ 646 stuff->x < -wBorderWidth((WindowPtr) pDraw) || 647 stuff->x + (int) stuff->width > 648 wBorderWidth((WindowPtr) pDraw) + (int) pDraw->width || 649 stuff->y < -wBorderWidth((WindowPtr) pDraw) || 650 stuff->y + (int) stuff->height > 651 wBorderWidth((WindowPtr) pDraw) + (int) pDraw->height) 652 return BadMatch; 653 visual = wVisual(((WindowPtr) pDraw)); 654 pVisibleRegion = NotClippedByChildren((WindowPtr) pDraw); 655 if (pVisibleRegion) 656 RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y); 657 } 658 else { 659 if (stuff->x < 0 || 660 stuff->x + (int) stuff->width > pDraw->width || 661 stuff->y < 0 || stuff->y + (int) stuff->height > pDraw->height) 662 return BadMatch; 663 visual = None; 664 } 665 xgi = (xShmGetImageReply) { 666 .type = X_Reply, 667 .sequenceNumber = client->sequence, 668 .length = 0, 669 .visual = visual, 670 .depth = pDraw->depth 671 }; 672 if (stuff->format == ZPixmap) { 673 length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; 674 } 675 else { 676 lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; 677 plane = ((Mask) 1) << (pDraw->depth - 1); 678 /* only planes asked for */ 679 length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); 680 } 681 682 VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 683 xgi.size = length; 684 685 if (length == 0) { 686 /* nothing to do */ 687 } 688 else if (stuff->format == ZPixmap) { 689 (*pDraw->pScreen->GetImage) (pDraw, stuff->x, stuff->y, 690 stuff->width, stuff->height, 691 stuff->format, stuff->planeMask, 692 shmdesc->addr + stuff->offset); 693 if (pVisibleRegion) 694 XaceCensorImage(client, pVisibleRegion, 695 PixmapBytePad(stuff->width, pDraw->depth), pDraw, 696 stuff->x, stuff->y, stuff->width, stuff->height, 697 stuff->format, shmdesc->addr + stuff->offset); 698 } 699 else { 700 701 length = stuff->offset; 702 for (; plane; plane >>= 1) { 703 if (stuff->planeMask & plane) { 704 (*pDraw->pScreen->GetImage) (pDraw, 705 stuff->x, stuff->y, 706 stuff->width, stuff->height, 707 stuff->format, plane, 708 shmdesc->addr + length); 709 if (pVisibleRegion) 710 XaceCensorImage(client, pVisibleRegion, 711 BitmapBytePad(stuff->width), pDraw, 712 stuff->x, stuff->y, stuff->width, stuff->height, 713 stuff->format, shmdesc->addr + length); 714 length += lenPer; 715 } 716 } 717 } 718 719 if (pVisibleRegion) 720 RegionDestroy(pVisibleRegion); 721 722 if (client->swapped) { 723 swaps(&xgi.sequenceNumber); 724 swapl(&xgi.length); 725 swapl(&xgi.visual); 726 swapl(&xgi.size); 727 } 728 WriteToClient(client, sizeof(xShmGetImageReply), &xgi); 729 730 return Success; 731} 732 733#ifdef PANORAMIX 734static int 735ProcPanoramiXShmPutImage(ClientPtr client) 736{ 737 int j, result, orig_x, orig_y; 738 PanoramiXRes *draw, *gc; 739 Bool sendEvent, isRoot; 740 741 REQUEST(xShmPutImageReq); 742 REQUEST_SIZE_MATCH(xShmPutImageReq); 743 744 result = dixLookupResourceByClass((void **) &draw, stuff->drawable, 745 XRC_DRAWABLE, client, DixWriteAccess); 746 if (result != Success) 747 return (result == BadValue) ? BadDrawable : result; 748 749 result = dixLookupResourceByType((void **) &gc, stuff->gc, 750 XRT_GC, client, DixReadAccess); 751 if (result != Success) 752 return result; 753 754 isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 755 756 orig_x = stuff->dstX; 757 orig_y = stuff->dstY; 758 sendEvent = stuff->sendEvent; 759 stuff->sendEvent = 0; 760 FOR_NSCREENS(j) { 761 if (!j) 762 stuff->sendEvent = sendEvent; 763 stuff->drawable = draw->info[j].id; 764 stuff->gc = gc->info[j].id; 765 if (isRoot) { 766 stuff->dstX = orig_x - screenInfo.screens[j]->x; 767 stuff->dstY = orig_y - screenInfo.screens[j]->y; 768 } 769 result = ProcShmPutImage(client); 770 if (result != Success) 771 break; 772 } 773 return result; 774} 775 776static int 777ProcPanoramiXShmGetImage(ClientPtr client) 778{ 779 PanoramiXRes *draw; 780 DrawablePtr *drawables; 781 DrawablePtr pDraw; 782 xShmGetImageReply xgi; 783 ShmDescPtr shmdesc; 784 int i, x, y, w, h, format, rc; 785 Mask plane = 0, planemask; 786 long lenPer = 0, length, widthBytesLine; 787 Bool isRoot; 788 789 REQUEST(xShmGetImageReq); 790 791 REQUEST_SIZE_MATCH(xShmGetImageReq); 792 793 if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 794 client->errorValue = stuff->format; 795 return BadValue; 796 } 797 798 rc = dixLookupResourceByClass((void **) &draw, stuff->drawable, 799 XRC_DRAWABLE, client, DixWriteAccess); 800 if (rc != Success) 801 return (rc == BadValue) ? BadDrawable : rc; 802 803 if (draw->type == XRT_PIXMAP) 804 return ProcShmGetImage(client); 805 806 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReadAccess); 807 if (rc != Success) 808 return rc; 809 810 VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 811 812 x = stuff->x; 813 y = stuff->y; 814 w = stuff->width; 815 h = stuff->height; 816 format = stuff->format; 817 planemask = stuff->planeMask; 818 819 isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 820 821 if (isRoot) { 822 if ( /* check for being onscreen */ 823 x < 0 || x + w > PanoramiXPixWidth || 824 y < 0 || y + h > PanoramiXPixHeight) 825 return BadMatch; 826 } 827 else { 828 if ( /* check for being onscreen */ 829 screenInfo.screens[0]->x + pDraw->x + x < 0 || 830 screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth 831 || screenInfo.screens[0]->y + pDraw->y + y < 0 || 832 screenInfo.screens[0]->y + pDraw->y + y + h > PanoramiXPixHeight 833 || 834 /* check for being inside of border */ 835 x < -wBorderWidth((WindowPtr) pDraw) || 836 x + w > wBorderWidth((WindowPtr) pDraw) + (int) pDraw->width || 837 y < -wBorderWidth((WindowPtr) pDraw) || 838 y + h > wBorderWidth((WindowPtr) pDraw) + (int) pDraw->height) 839 return BadMatch; 840 } 841 842 drawables = calloc(PanoramiXNumScreens, sizeof(DrawablePtr)); 843 if (!drawables) 844 return BadAlloc; 845 846 drawables[0] = pDraw; 847 FOR_NSCREENS_FORWARD_SKIP(i) { 848 rc = dixLookupDrawable(drawables + i, draw->info[i].id, client, 0, 849 DixReadAccess); 850 if (rc != Success) { 851 free(drawables); 852 return rc; 853 } 854 } 855 856 xgi = (xShmGetImageReply) { 857 .type = X_Reply, 858 .sequenceNumber = client->sequence, 859 .length = 0, 860 .visual = wVisual(((WindowPtr) pDraw)), 861 .depth = pDraw->depth 862 }; 863 864 if (format == ZPixmap) { 865 widthBytesLine = PixmapBytePad(w, pDraw->depth); 866 length = widthBytesLine * h; 867 } 868 else { 869 widthBytesLine = PixmapBytePad(w, 1); 870 lenPer = widthBytesLine * h; 871 plane = ((Mask) 1) << (pDraw->depth - 1); 872 length = lenPer * Ones(planemask & (plane | (plane - 1))); 873 } 874 875 VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 876 xgi.size = length; 877 878 if (length == 0) { /* nothing to do */ 879 } 880 else if (format == ZPixmap) { 881 XineramaGetImageData(drawables, x, y, w, h, format, planemask, 882 shmdesc->addr + stuff->offset, 883 widthBytesLine, isRoot); 884 } 885 else { 886 887 length = stuff->offset; 888 for (; plane; plane >>= 1) { 889 if (planemask & plane) { 890 XineramaGetImageData(drawables, x, y, w, h, 891 format, plane, shmdesc->addr + length, 892 widthBytesLine, isRoot); 893 length += lenPer; 894 } 895 } 896 } 897 free(drawables); 898 899 if (client->swapped) { 900 swaps(&xgi.sequenceNumber); 901 swapl(&xgi.length); 902 swapl(&xgi.visual); 903 swapl(&xgi.size); 904 } 905 WriteToClient(client, sizeof(xShmGetImageReply), &xgi); 906 907 return Success; 908} 909 910static int 911ProcPanoramiXShmCreatePixmap(ClientPtr client) 912{ 913 ScreenPtr pScreen = NULL; 914 PixmapPtr pMap = NULL; 915 DrawablePtr pDraw; 916 DepthPtr pDepth; 917 int i, j, result, rc; 918 ShmDescPtr shmdesc; 919 920 REQUEST(xShmCreatePixmapReq); 921 unsigned int width, height, depth; 922 unsigned long size; 923 PanoramiXRes *newPix; 924 925 REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 926 client->errorValue = stuff->pid; 927 if (!sharedPixmaps) 928 return BadImplementation; 929 LEGAL_NEW_RESOURCE(stuff->pid, client); 930 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 931 DixGetAttrAccess); 932 if (rc != Success) 933 return rc; 934 935 VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 936 937 width = stuff->width; 938 height = stuff->height; 939 depth = stuff->depth; 940 if (!width || !height || !depth) { 941 client->errorValue = 0; 942 return BadValue; 943 } 944 if (width > 32767 || height > 32767) 945 return BadAlloc; 946 947 if (stuff->depth != 1) { 948 pDepth = pDraw->pScreen->allowedDepths; 949 for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 950 if (pDepth->depth == stuff->depth) 951 goto CreatePmap; 952 client->errorValue = stuff->depth; 953 return BadValue; 954 } 955 956 CreatePmap: 957 size = PixmapBytePad(width, depth) * height; 958 if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 959 if (size < width * height) 960 return BadAlloc; 961 } 962 /* thankfully, offset is unsigned */ 963 if (stuff->offset + size < size) 964 return BadAlloc; 965 966 VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 967 968 if (!(newPix = malloc(sizeof(PanoramiXRes)))) 969 return BadAlloc; 970 971 newPix->type = XRT_PIXMAP; 972 newPix->u.pix.shared = TRUE; 973 panoramix_setup_ids(newPix, client, stuff->pid); 974 975 result = Success; 976 977 FOR_NSCREENS(j) { 978 ShmScrPrivateRec *screen_priv; 979 980 pScreen = screenInfo.screens[j]; 981 982 screen_priv = ShmGetScreenPriv(pScreen); 983 pMap = (*screen_priv->shmFuncs->CreatePixmap) (pScreen, 984 stuff->width, 985 stuff->height, 986 stuff->depth, 987 shmdesc->addr + 988 stuff->offset); 989 990 if (pMap) { 991 result = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, 992 RT_PIXMAP, pMap, RT_NONE, NULL, DixCreateAccess); 993 if (result != Success) { 994 pDraw->pScreen->DestroyPixmap(pMap); 995 return result; 996 } 997 dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc); 998 shmdesc->refcnt++; 999 pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1000 pMap->drawable.id = newPix->info[j].id; 1001 if (!AddResource(newPix->info[j].id, RT_PIXMAP, (void *) pMap)) { 1002 result = BadAlloc; 1003 break; 1004 } 1005 } 1006 else { 1007 result = BadAlloc; 1008 break; 1009 } 1010 } 1011 1012 if (result == BadAlloc) { 1013 while (j--) 1014 FreeResource(newPix->info[j].id, RT_NONE); 1015 free(newPix); 1016 } 1017 else 1018 AddResource(stuff->pid, XRT_PIXMAP, newPix); 1019 1020 return result; 1021} 1022#endif 1023 1024static PixmapPtr 1025fbShmCreatePixmap(ScreenPtr pScreen, 1026 int width, int height, int depth, char *addr) 1027{ 1028 PixmapPtr pPixmap; 1029 1030 pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth, 0); 1031 if (!pPixmap) 1032 return NullPixmap; 1033 1034 if (!(*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth, 1035 BitsPerPixel(depth), 1036 PixmapBytePad(width, depth), 1037 (void *) addr)) { 1038 (*pScreen->DestroyPixmap) (pPixmap); 1039 return NullPixmap; 1040 } 1041 return pPixmap; 1042} 1043 1044static int 1045ProcShmCreatePixmap(ClientPtr client) 1046{ 1047 PixmapPtr pMap; 1048 DrawablePtr pDraw; 1049 DepthPtr pDepth; 1050 int i, rc; 1051 ShmDescPtr shmdesc; 1052 ShmScrPrivateRec *screen_priv; 1053 1054 REQUEST(xShmCreatePixmapReq); 1055 unsigned int width, height, depth; 1056 unsigned long size; 1057 1058 REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 1059 client->errorValue = stuff->pid; 1060 if (!sharedPixmaps) 1061 return BadImplementation; 1062 LEGAL_NEW_RESOURCE(stuff->pid, client); 1063 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 1064 DixGetAttrAccess); 1065 if (rc != Success) 1066 return rc; 1067 1068 VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 1069 1070 width = stuff->width; 1071 height = stuff->height; 1072 depth = stuff->depth; 1073 if (!width || !height || !depth) { 1074 client->errorValue = 0; 1075 return BadValue; 1076 } 1077 if (width > 32767 || height > 32767) 1078 return BadAlloc; 1079 1080 if (stuff->depth != 1) { 1081 pDepth = pDraw->pScreen->allowedDepths; 1082 for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 1083 if (pDepth->depth == stuff->depth) 1084 goto CreatePmap; 1085 client->errorValue = stuff->depth; 1086 return BadValue; 1087 } 1088 1089 CreatePmap: 1090 size = PixmapBytePad(width, depth) * height; 1091 if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 1092 if (size < width * height) 1093 return BadAlloc; 1094 } 1095 /* thankfully, offset is unsigned */ 1096 if (stuff->offset + size < size) 1097 return BadAlloc; 1098 1099 VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 1100 screen_priv = ShmGetScreenPriv(pDraw->pScreen); 1101 pMap = (*screen_priv->shmFuncs->CreatePixmap) (pDraw->pScreen, stuff->width, 1102 stuff->height, stuff->depth, 1103 shmdesc->addr + 1104 stuff->offset); 1105 if (pMap) { 1106 rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 1107 pMap, RT_NONE, NULL, DixCreateAccess); 1108 if (rc != Success) { 1109 pDraw->pScreen->DestroyPixmap(pMap); 1110 return rc; 1111 } 1112 dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc); 1113 shmdesc->refcnt++; 1114 pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1115 pMap->drawable.id = stuff->pid; 1116 if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap)) { 1117 return Success; 1118 } 1119 } 1120 return BadAlloc; 1121} 1122 1123#ifdef SHM_FD_PASSING 1124 1125static void 1126ShmBusfaultNotify(void *context) 1127{ 1128 ShmDescPtr shmdesc = context; 1129 1130 ErrorF("shared memory 0x%x truncated by client\n", 1131 (unsigned int) shmdesc->resource); 1132 busfault_unregister(shmdesc->busfault); 1133 shmdesc->busfault = NULL; 1134 FreeResource (shmdesc->resource, RT_NONE); 1135} 1136 1137static int 1138ProcShmAttachFd(ClientPtr client) 1139{ 1140 int fd; 1141 ShmDescPtr shmdesc; 1142 REQUEST(xShmAttachFdReq); 1143 struct stat statb; 1144 1145 SetReqFds(client, 1); 1146 REQUEST_SIZE_MATCH(xShmAttachFdReq); 1147 LEGAL_NEW_RESOURCE(stuff->shmseg, client); 1148 if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 1149 client->errorValue = stuff->readOnly; 1150 return BadValue; 1151 } 1152 fd = ReadFdFromClient(client); 1153 if (fd < 0) 1154 return BadMatch; 1155 1156 if (fstat(fd, &statb) < 0 || statb.st_size == 0) { 1157 close(fd); 1158 return BadMatch; 1159 } 1160 1161 shmdesc = malloc(sizeof(ShmDescRec)); 1162 if (!shmdesc) { 1163 close(fd); 1164 return BadAlloc; 1165 } 1166 shmdesc->is_fd = TRUE; 1167 shmdesc->addr = mmap(NULL, statb.st_size, 1168 stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, 1169 MAP_SHARED, 1170 fd, 0); 1171 1172 close(fd); 1173 if (shmdesc->addr == ((char *) -1)) { 1174 free(shmdesc); 1175 return BadAccess; 1176 } 1177 1178 shmdesc->refcnt = 1; 1179 shmdesc->writable = !stuff->readOnly; 1180 shmdesc->size = statb.st_size; 1181 shmdesc->resource = stuff->shmseg; 1182 1183 shmdesc->busfault = busfault_register_mmap(shmdesc->addr, shmdesc->size, ShmBusfaultNotify, shmdesc); 1184 if (!shmdesc->busfault) { 1185 munmap(shmdesc->addr, shmdesc->size); 1186 free(shmdesc); 1187 return BadAlloc; 1188 } 1189 1190 shmdesc->next = Shmsegs; 1191 Shmsegs = shmdesc; 1192 1193 if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) 1194 return BadAlloc; 1195 return Success; 1196} 1197 1198static int 1199shm_tmpfile(void) 1200{ 1201#ifdef SHMDIR 1202 int fd; 1203 int flags; 1204 char template[] = SHMDIR "/shmfd-XXXXXX"; 1205#ifdef O_TMPFILE 1206 fd = open(SHMDIR, O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666); 1207 if (fd >= 0) { 1208 ErrorF ("Using O_TMPFILE\n"); 1209 return fd; 1210 } 1211 ErrorF ("Not using O_TMPFILE\n"); 1212#endif 1213 fd = mkstemp(template); 1214 if (fd < 0) 1215 return -1; 1216 unlink(template); 1217 if (fcntl(fd, F_GETFD, &flags) >= 0) { 1218 flags |= FD_CLOEXEC; 1219 (void) fcntl(fd, F_SETFD, &flags); 1220 } 1221 return fd; 1222#else 1223 return -1; 1224#endif 1225} 1226 1227static int 1228ProcShmCreateSegment(ClientPtr client) 1229{ 1230 int fd; 1231 ShmDescPtr shmdesc; 1232 REQUEST(xShmCreateSegmentReq); 1233 xShmCreateSegmentReply rep = { 1234 .type = X_Reply, 1235 .nfd = 1, 1236 .sequenceNumber = client->sequence, 1237 .length = 0, 1238 }; 1239 1240 REQUEST_SIZE_MATCH(xShmCreateSegmentReq); 1241 if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { 1242 client->errorValue = stuff->readOnly; 1243 return BadValue; 1244 } 1245 fd = shm_tmpfile(); 1246 if (fd < 0) 1247 return BadAlloc; 1248 if (ftruncate(fd, stuff->size) < 0) { 1249 close(fd); 1250 return BadAlloc; 1251 } 1252 shmdesc = malloc(sizeof(ShmDescRec)); 1253 if (!shmdesc) { 1254 close(fd); 1255 return BadAlloc; 1256 } 1257 shmdesc->is_fd = TRUE; 1258 shmdesc->addr = mmap(NULL, stuff->size, 1259 stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, 1260 MAP_SHARED, 1261 fd, 0); 1262 1263 if (shmdesc->addr == ((char *) -1)) { 1264 close(fd); 1265 free(shmdesc); 1266 return BadAccess; 1267 } 1268 1269 shmdesc->refcnt = 1; 1270 shmdesc->writable = !stuff->readOnly; 1271 shmdesc->size = stuff->size; 1272 1273 shmdesc->busfault = busfault_register_mmap(shmdesc->addr, shmdesc->size, ShmBusfaultNotify, shmdesc); 1274 if (!shmdesc->busfault) { 1275 close(fd); 1276 munmap(shmdesc->addr, shmdesc->size); 1277 free(shmdesc); 1278 return BadAlloc; 1279 } 1280 1281 shmdesc->next = Shmsegs; 1282 Shmsegs = shmdesc; 1283 1284 if (!AddResource(stuff->shmseg, ShmSegType, (void *) shmdesc)) { 1285 close(fd); 1286 return BadAlloc; 1287 } 1288 1289 if (WriteFdToClient(client, fd, TRUE) < 0) { 1290 FreeResource(stuff->shmseg, RT_NONE); 1291 close(fd); 1292 return BadAlloc; 1293 } 1294 WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep); 1295 return Success; 1296} 1297#endif /* SHM_FD_PASSING */ 1298 1299static int 1300ProcShmDispatch(ClientPtr client) 1301{ 1302 REQUEST(xReq); 1303 switch (stuff->data) { 1304 case X_ShmQueryVersion: 1305 return ProcShmQueryVersion(client); 1306 case X_ShmAttach: 1307 return ProcShmAttach(client); 1308 case X_ShmDetach: 1309 return ProcShmDetach(client); 1310 case X_ShmPutImage: 1311#ifdef PANORAMIX 1312 if (!noPanoramiXExtension) 1313 return ProcPanoramiXShmPutImage(client); 1314#endif 1315 return ProcShmPutImage(client); 1316 case X_ShmGetImage: 1317#ifdef PANORAMIX 1318 if (!noPanoramiXExtension) 1319 return ProcPanoramiXShmGetImage(client); 1320#endif 1321 return ProcShmGetImage(client); 1322 case X_ShmCreatePixmap: 1323#ifdef PANORAMIX 1324 if (!noPanoramiXExtension) 1325 return ProcPanoramiXShmCreatePixmap(client); 1326#endif 1327 return ProcShmCreatePixmap(client); 1328#ifdef SHM_FD_PASSING 1329 case X_ShmAttachFd: 1330 return ProcShmAttachFd(client); 1331 case X_ShmCreateSegment: 1332 return ProcShmCreateSegment(client); 1333#endif 1334 default: 1335 return BadRequest; 1336 } 1337} 1338 1339static void 1340SShmCompletionEvent(xShmCompletionEvent * from, xShmCompletionEvent * to) 1341{ 1342 to->type = from->type; 1343 cpswaps(from->sequenceNumber, to->sequenceNumber); 1344 cpswapl(from->drawable, to->drawable); 1345 cpswaps(from->minorEvent, to->minorEvent); 1346 to->majorEvent = from->majorEvent; 1347 cpswapl(from->shmseg, to->shmseg); 1348 cpswapl(from->offset, to->offset); 1349} 1350 1351static int 1352SProcShmQueryVersion(ClientPtr client) 1353{ 1354 REQUEST(xShmQueryVersionReq); 1355 1356 swaps(&stuff->length); 1357 return ProcShmQueryVersion(client); 1358} 1359 1360static int 1361SProcShmAttach(ClientPtr client) 1362{ 1363 REQUEST(xShmAttachReq); 1364 swaps(&stuff->length); 1365 REQUEST_SIZE_MATCH(xShmAttachReq); 1366 swapl(&stuff->shmseg); 1367 swapl(&stuff->shmid); 1368 return ProcShmAttach(client); 1369} 1370 1371static int 1372SProcShmDetach(ClientPtr client) 1373{ 1374 REQUEST(xShmDetachReq); 1375 swaps(&stuff->length); 1376 REQUEST_SIZE_MATCH(xShmDetachReq); 1377 swapl(&stuff->shmseg); 1378 return ProcShmDetach(client); 1379} 1380 1381static int 1382SProcShmPutImage(ClientPtr client) 1383{ 1384 REQUEST(xShmPutImageReq); 1385 swaps(&stuff->length); 1386 REQUEST_SIZE_MATCH(xShmPutImageReq); 1387 swapl(&stuff->drawable); 1388 swapl(&stuff->gc); 1389 swaps(&stuff->totalWidth); 1390 swaps(&stuff->totalHeight); 1391 swaps(&stuff->srcX); 1392 swaps(&stuff->srcY); 1393 swaps(&stuff->srcWidth); 1394 swaps(&stuff->srcHeight); 1395 swaps(&stuff->dstX); 1396 swaps(&stuff->dstY); 1397 swapl(&stuff->shmseg); 1398 swapl(&stuff->offset); 1399 return ProcShmPutImage(client); 1400} 1401 1402static int 1403SProcShmGetImage(ClientPtr client) 1404{ 1405 REQUEST(xShmGetImageReq); 1406 swaps(&stuff->length); 1407 REQUEST_SIZE_MATCH(xShmGetImageReq); 1408 swapl(&stuff->drawable); 1409 swaps(&stuff->x); 1410 swaps(&stuff->y); 1411 swaps(&stuff->width); 1412 swaps(&stuff->height); 1413 swapl(&stuff->planeMask); 1414 swapl(&stuff->shmseg); 1415 swapl(&stuff->offset); 1416 return ProcShmGetImage(client); 1417} 1418 1419static int 1420SProcShmCreatePixmap(ClientPtr client) 1421{ 1422 REQUEST(xShmCreatePixmapReq); 1423 swaps(&stuff->length); 1424 REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 1425 swapl(&stuff->pid); 1426 swapl(&stuff->drawable); 1427 swaps(&stuff->width); 1428 swaps(&stuff->height); 1429 swapl(&stuff->shmseg); 1430 swapl(&stuff->offset); 1431 return ProcShmCreatePixmap(client); 1432} 1433 1434#ifdef SHM_FD_PASSING 1435static int 1436SProcShmAttachFd(ClientPtr client) 1437{ 1438 REQUEST(xShmAttachFdReq); 1439 SetReqFds(client, 1); 1440 swaps(&stuff->length); 1441 REQUEST_SIZE_MATCH(xShmAttachFdReq); 1442 swapl(&stuff->shmseg); 1443 return ProcShmAttachFd(client); 1444} 1445 1446static int 1447SProcShmCreateSegment(ClientPtr client) 1448{ 1449 REQUEST(xShmCreateSegmentReq); 1450 swaps(&stuff->length); 1451 REQUEST_SIZE_MATCH(xShmCreateSegmentReq); 1452 swapl(&stuff->shmseg); 1453 swapl(&stuff->size); 1454 return ProcShmCreateSegment(client); 1455} 1456#endif /* SHM_FD_PASSING */ 1457 1458static int 1459SProcShmDispatch(ClientPtr client) 1460{ 1461 REQUEST(xReq); 1462 switch (stuff->data) { 1463 case X_ShmQueryVersion: 1464 return SProcShmQueryVersion(client); 1465 case X_ShmAttach: 1466 return SProcShmAttach(client); 1467 case X_ShmDetach: 1468 return SProcShmDetach(client); 1469 case X_ShmPutImage: 1470 return SProcShmPutImage(client); 1471 case X_ShmGetImage: 1472 return SProcShmGetImage(client); 1473 case X_ShmCreatePixmap: 1474 return SProcShmCreatePixmap(client); 1475#ifdef SHM_FD_PASSING 1476 case X_ShmAttachFd: 1477 return SProcShmAttachFd(client); 1478 case X_ShmCreateSegment: 1479 return SProcShmCreateSegment(client); 1480#endif 1481 default: 1482 return BadRequest; 1483 } 1484} 1485 1486void 1487ShmExtensionInit(void) 1488{ 1489 ExtensionEntry *extEntry; 1490 int i; 1491 1492#ifdef MUST_CHECK_FOR_SHM_SYSCALL 1493 if (!CheckForShmSyscall()) { 1494 ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); 1495 return; 1496 } 1497#endif 1498 1499 if (!ShmRegisterPrivates()) 1500 return; 1501 1502 sharedPixmaps = xFalse; 1503 { 1504 sharedPixmaps = xTrue; 1505 for (i = 0; i < screenInfo.numScreens; i++) { 1506 ShmScrPrivateRec *screen_priv = 1507 ShmInitScreenPriv(screenInfo.screens[i]); 1508 if (!screen_priv->shmFuncs) 1509 screen_priv->shmFuncs = &miFuncs; 1510 if (!screen_priv->shmFuncs->CreatePixmap) 1511 sharedPixmaps = xFalse; 1512 } 1513 if (sharedPixmaps) 1514 for (i = 0; i < screenInfo.numScreens; i++) { 1515 ShmScrPrivateRec *screen_priv = 1516 ShmGetScreenPriv(screenInfo.screens[i]); 1517 screen_priv->destroyPixmap = 1518 screenInfo.screens[i]->DestroyPixmap; 1519 screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; 1520 } 1521 } 1522 ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg"); 1523 if (ShmSegType && 1524 (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, 1525 ProcShmDispatch, SProcShmDispatch, 1526 ShmResetProc, StandardMinorOpcode))) { 1527 ShmReqCode = (unsigned char) extEntry->base; 1528 ShmCompletionCode = extEntry->eventBase; 1529 BadShmSegCode = extEntry->errorBase; 1530 SetResourceTypeErrorValue(ShmSegType, BadShmSegCode); 1531 EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; 1532 } 1533} 1534