| File: | Xext/shm.c |
| Location: | line 858, column 5 |
| Description: | Potential leak of memory pointed to by 'drawables' |
| 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 | } |