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