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