1*4882a593Smuzhiyun /************************************************************
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
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 this permission notice appear in supporting documentation. This permission
8*4882a593Smuzhiyun notice shall be included in all copies or substantial portions of the
9*4882a593Smuzhiyun Software.
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14*4882a593Smuzhiyun AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun ********************************************************/
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
21*4882a593Smuzhiyun #include <dix-config.h>
22*4882a593Smuzhiyun #endif
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #include "selection.h"
25*4882a593Smuzhiyun #include "inputstr.h"
26*4882a593Smuzhiyun #include "windowstr.h"
27*4882a593Smuzhiyun #include "propertyst.h"
28*4882a593Smuzhiyun #include "extnsionst.h"
29*4882a593Smuzhiyun #include "extinit.h"
30*4882a593Smuzhiyun #include "xselinuxint.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid)
33*4882a593Smuzhiyun #define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid)
34*4882a593Smuzhiyun #define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid)
35*4882a593Smuzhiyun #define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid)
36*4882a593Smuzhiyun #define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid)
37*4882a593Smuzhiyun #define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid)
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun typedef struct {
40*4882a593Smuzhiyun security_context_t octx;
41*4882a593Smuzhiyun security_context_t dctx;
42*4882a593Smuzhiyun CARD32 octx_len;
43*4882a593Smuzhiyun CARD32 dctx_len;
44*4882a593Smuzhiyun CARD32 id;
45*4882a593Smuzhiyun } SELinuxListItemRec;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun * Extension Dispatch
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun static security_context_t
SELinuxCopyContext(char * ptr,unsigned len)52*4882a593Smuzhiyun SELinuxCopyContext(char *ptr, unsigned len)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun security_context_t copy = malloc(len + 1);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun if (!copy)
57*4882a593Smuzhiyun return NULL;
58*4882a593Smuzhiyun strncpy(copy, ptr, len);
59*4882a593Smuzhiyun copy[len] = '\0';
60*4882a593Smuzhiyun return copy;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static int
ProcSELinuxQueryVersion(ClientPtr client)64*4882a593Smuzhiyun ProcSELinuxQueryVersion(ClientPtr client)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun SELinuxQueryVersionReply rep = {
67*4882a593Smuzhiyun .type = X_Reply,
68*4882a593Smuzhiyun .sequenceNumber = client->sequence,
69*4882a593Smuzhiyun .length = 0,
70*4882a593Smuzhiyun .server_major = SELINUX_MAJOR_VERSION,
71*4882a593Smuzhiyun .server_minor = SELINUX_MINOR_VERSION
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun if (client->swapped) {
74*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
75*4882a593Smuzhiyun swapl(&rep.length);
76*4882a593Smuzhiyun swaps(&rep.server_major);
77*4882a593Smuzhiyun swaps(&rep.server_minor);
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun WriteToClient(client, sizeof(rep), &rep);
80*4882a593Smuzhiyun return Success;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun static int
SELinuxSendContextReply(ClientPtr client,security_id_t sid)84*4882a593Smuzhiyun SELinuxSendContextReply(ClientPtr client, security_id_t sid)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun SELinuxGetContextReply rep;
87*4882a593Smuzhiyun security_context_t ctx = NULL;
88*4882a593Smuzhiyun int len = 0;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (sid) {
91*4882a593Smuzhiyun if (avc_sid_to_context_raw(sid, &ctx) < 0)
92*4882a593Smuzhiyun return BadValue;
93*4882a593Smuzhiyun len = strlen(ctx) + 1;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun rep = (SELinuxGetContextReply) {
97*4882a593Smuzhiyun .type = X_Reply,
98*4882a593Smuzhiyun .sequenceNumber = client->sequence,
99*4882a593Smuzhiyun .length = bytes_to_int32(len),
100*4882a593Smuzhiyun .context_len = len
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun if (client->swapped) {
104*4882a593Smuzhiyun swapl(&rep.length);
105*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
106*4882a593Smuzhiyun swapl(&rep.context_len);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun WriteToClient(client, sizeof(SELinuxGetContextReply), &rep);
110*4882a593Smuzhiyun WriteToClient(client, len, ctx);
111*4882a593Smuzhiyun freecon(ctx);
112*4882a593Smuzhiyun return Success;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun static int
ProcSELinuxSetCreateContext(ClientPtr client,unsigned offset)116*4882a593Smuzhiyun ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun PrivateRec **privPtr = &client->devPrivates;
119*4882a593Smuzhiyun security_id_t *pSid;
120*4882a593Smuzhiyun security_context_t ctx = NULL;
121*4882a593Smuzhiyun char *ptr;
122*4882a593Smuzhiyun int rc;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun REQUEST(SELinuxSetCreateContextReq);
125*4882a593Smuzhiyun REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (stuff->context_len > 0) {
128*4882a593Smuzhiyun ctx = SELinuxCopyContext((char *) (stuff + 1), stuff->context_len);
129*4882a593Smuzhiyun if (!ctx)
130*4882a593Smuzhiyun return BadAlloc;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun ptr = dixLookupPrivate(privPtr, subjectKey);
134*4882a593Smuzhiyun pSid = (security_id_t *) (ptr + offset);
135*4882a593Smuzhiyun *pSid = NULL;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun rc = Success;
138*4882a593Smuzhiyun if (stuff->context_len > 0) {
139*4882a593Smuzhiyun if (security_check_context_raw(ctx) < 0 ||
140*4882a593Smuzhiyun avc_context_to_sid_raw(ctx, pSid) < 0)
141*4882a593Smuzhiyun rc = BadValue;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun free(ctx);
145*4882a593Smuzhiyun return rc;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun static int
ProcSELinuxGetCreateContext(ClientPtr client,unsigned offset)149*4882a593Smuzhiyun ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun security_id_t *pSid;
152*4882a593Smuzhiyun char *ptr;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun if (offset == CTX_DEV)
157*4882a593Smuzhiyun ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
158*4882a593Smuzhiyun else
159*4882a593Smuzhiyun ptr = dixLookupPrivate(&client->devPrivates, subjectKey);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun pSid = (security_id_t *) (ptr + offset);
162*4882a593Smuzhiyun return SELinuxSendContextReply(client, *pSid);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun static int
ProcSELinuxSetDeviceContext(ClientPtr client)166*4882a593Smuzhiyun ProcSELinuxSetDeviceContext(ClientPtr client)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun security_context_t ctx;
169*4882a593Smuzhiyun security_id_t sid;
170*4882a593Smuzhiyun DeviceIntPtr dev;
171*4882a593Smuzhiyun SELinuxSubjectRec *subj;
172*4882a593Smuzhiyun SELinuxObjectRec *obj;
173*4882a593Smuzhiyun int rc;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun REQUEST(SELinuxSetContextReq);
176*4882a593Smuzhiyun REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun if (stuff->context_len < 1)
179*4882a593Smuzhiyun return BadLength;
180*4882a593Smuzhiyun ctx = SELinuxCopyContext((char *) (stuff + 1), stuff->context_len);
181*4882a593Smuzhiyun if (!ctx)
182*4882a593Smuzhiyun return BadAlloc;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess);
185*4882a593Smuzhiyun if (rc != Success)
186*4882a593Smuzhiyun goto out;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if (security_check_context_raw(ctx) < 0 ||
189*4882a593Smuzhiyun avc_context_to_sid_raw(ctx, &sid) < 0) {
190*4882a593Smuzhiyun rc = BadValue;
191*4882a593Smuzhiyun goto out;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
195*4882a593Smuzhiyun subj->sid = sid;
196*4882a593Smuzhiyun obj = dixLookupPrivate(&dev->devPrivates, objectKey);
197*4882a593Smuzhiyun obj->sid = sid;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun rc = Success;
200*4882a593Smuzhiyun out:
201*4882a593Smuzhiyun free(ctx);
202*4882a593Smuzhiyun return rc;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun static int
ProcSELinuxGetDeviceContext(ClientPtr client)206*4882a593Smuzhiyun ProcSELinuxGetDeviceContext(ClientPtr client)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun DeviceIntPtr dev;
209*4882a593Smuzhiyun SELinuxSubjectRec *subj;
210*4882a593Smuzhiyun int rc;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
213*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess);
216*4882a593Smuzhiyun if (rc != Success)
217*4882a593Smuzhiyun return rc;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
220*4882a593Smuzhiyun return SELinuxSendContextReply(client, subj->sid);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun static int
ProcSELinuxGetDrawableContext(ClientPtr client)224*4882a593Smuzhiyun ProcSELinuxGetDrawableContext(ClientPtr client)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun DrawablePtr pDraw;
227*4882a593Smuzhiyun PrivateRec **privatePtr;
228*4882a593Smuzhiyun SELinuxObjectRec *obj;
229*4882a593Smuzhiyun int rc;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
232*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun rc = dixLookupDrawable(&pDraw, stuff->id, client, 0, DixGetAttrAccess);
235*4882a593Smuzhiyun if (rc != Success)
236*4882a593Smuzhiyun return rc;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun if (pDraw->type == DRAWABLE_PIXMAP)
239*4882a593Smuzhiyun privatePtr = &((PixmapPtr) pDraw)->devPrivates;
240*4882a593Smuzhiyun else
241*4882a593Smuzhiyun privatePtr = &((WindowPtr) pDraw)->devPrivates;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun obj = dixLookupPrivate(privatePtr, objectKey);
244*4882a593Smuzhiyun return SELinuxSendContextReply(client, obj->sid);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun static int
ProcSELinuxGetPropertyContext(ClientPtr client,void * privKey)248*4882a593Smuzhiyun ProcSELinuxGetPropertyContext(ClientPtr client, void *privKey)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun WindowPtr pWin;
251*4882a593Smuzhiyun PropertyPtr pProp;
252*4882a593Smuzhiyun SELinuxObjectRec *obj;
253*4882a593Smuzhiyun int rc;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun REQUEST(SELinuxGetPropertyContextReq);
256*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess);
259*4882a593Smuzhiyun if (rc != Success)
260*4882a593Smuzhiyun return rc;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun rc = dixLookupProperty(&pProp, pWin, stuff->property, client,
263*4882a593Smuzhiyun DixGetAttrAccess);
264*4882a593Smuzhiyun if (rc != Success)
265*4882a593Smuzhiyun return rc;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun obj = dixLookupPrivate(&pProp->devPrivates, privKey);
268*4882a593Smuzhiyun return SELinuxSendContextReply(client, obj->sid);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun static int
ProcSELinuxGetSelectionContext(ClientPtr client,void * privKey)272*4882a593Smuzhiyun ProcSELinuxGetSelectionContext(ClientPtr client, void *privKey)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun Selection *pSel;
275*4882a593Smuzhiyun SELinuxObjectRec *obj;
276*4882a593Smuzhiyun int rc;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
279*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
282*4882a593Smuzhiyun if (rc != Success)
283*4882a593Smuzhiyun return rc;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun obj = dixLookupPrivate(&pSel->devPrivates, privKey);
286*4882a593Smuzhiyun return SELinuxSendContextReply(client, obj->sid);
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun static int
ProcSELinuxGetClientContext(ClientPtr client)290*4882a593Smuzhiyun ProcSELinuxGetClientContext(ClientPtr client)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun ClientPtr target;
293*4882a593Smuzhiyun SELinuxSubjectRec *subj;
294*4882a593Smuzhiyun int rc;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
297*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess);
300*4882a593Smuzhiyun if (rc != Success)
301*4882a593Smuzhiyun return rc;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun subj = dixLookupPrivate(&target->devPrivates, subjectKey);
304*4882a593Smuzhiyun return SELinuxSendContextReply(client, subj->sid);
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun static int
SELinuxPopulateItem(SELinuxListItemRec * i,PrivateRec ** privPtr,CARD32 id,int * size)308*4882a593Smuzhiyun SELinuxPopulateItem(SELinuxListItemRec * i, PrivateRec ** privPtr, CARD32 id,
309*4882a593Smuzhiyun int *size)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey);
312*4882a593Smuzhiyun SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey);
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun if (avc_sid_to_context_raw(obj->sid, &i->octx) < 0)
315*4882a593Smuzhiyun return BadValue;
316*4882a593Smuzhiyun if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0)
317*4882a593Smuzhiyun return BadValue;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun i->id = id;
320*4882a593Smuzhiyun i->octx_len = bytes_to_int32(strlen(i->octx) + 1);
321*4882a593Smuzhiyun i->dctx_len = bytes_to_int32(strlen(i->dctx) + 1);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun *size += i->octx_len + i->dctx_len + 3;
324*4882a593Smuzhiyun return Success;
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun static void
SELinuxFreeItems(SELinuxListItemRec * items,int count)328*4882a593Smuzhiyun SELinuxFreeItems(SELinuxListItemRec * items, int count)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun int k;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun for (k = 0; k < count; k++) {
333*4882a593Smuzhiyun freecon(items[k].octx);
334*4882a593Smuzhiyun freecon(items[k].dctx);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun free(items);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun static int
SELinuxSendItemsToClient(ClientPtr client,SELinuxListItemRec * items,int size,int count)340*4882a593Smuzhiyun SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec * items,
341*4882a593Smuzhiyun int size, int count)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun int rc, k, pos = 0;
344*4882a593Smuzhiyun SELinuxListItemsReply rep;
345*4882a593Smuzhiyun CARD32 *buf;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun buf = calloc(size, sizeof(CARD32));
348*4882a593Smuzhiyun if (size && !buf) {
349*4882a593Smuzhiyun rc = BadAlloc;
350*4882a593Smuzhiyun goto out;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun /* Fill in the buffer */
354*4882a593Smuzhiyun for (k = 0; k < count; k++) {
355*4882a593Smuzhiyun buf[pos] = items[k].id;
356*4882a593Smuzhiyun if (client->swapped)
357*4882a593Smuzhiyun swapl(buf + pos);
358*4882a593Smuzhiyun pos++;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun buf[pos] = items[k].octx_len * 4;
361*4882a593Smuzhiyun if (client->swapped)
362*4882a593Smuzhiyun swapl(buf + pos);
363*4882a593Smuzhiyun pos++;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun buf[pos] = items[k].dctx_len * 4;
366*4882a593Smuzhiyun if (client->swapped)
367*4882a593Smuzhiyun swapl(buf + pos);
368*4882a593Smuzhiyun pos++;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun memcpy((char *) (buf + pos), items[k].octx, strlen(items[k].octx) + 1);
371*4882a593Smuzhiyun pos += items[k].octx_len;
372*4882a593Smuzhiyun memcpy((char *) (buf + pos), items[k].dctx, strlen(items[k].dctx) + 1);
373*4882a593Smuzhiyun pos += items[k].dctx_len;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun /* Send reply to client */
377*4882a593Smuzhiyun rep = (SELinuxListItemsReply) {
378*4882a593Smuzhiyun .type = X_Reply,
379*4882a593Smuzhiyun .sequenceNumber = client->sequence,
380*4882a593Smuzhiyun .length = size,
381*4882a593Smuzhiyun .count = count
382*4882a593Smuzhiyun };
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun if (client->swapped) {
385*4882a593Smuzhiyun swapl(&rep.length);
386*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
387*4882a593Smuzhiyun swapl(&rep.count);
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun WriteToClient(client, sizeof(SELinuxListItemsReply), &rep);
391*4882a593Smuzhiyun WriteToClient(client, size * 4, buf);
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun /* Free stuff and return */
394*4882a593Smuzhiyun rc = Success;
395*4882a593Smuzhiyun free(buf);
396*4882a593Smuzhiyun out:
397*4882a593Smuzhiyun SELinuxFreeItems(items, count);
398*4882a593Smuzhiyun return rc;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun static int
ProcSELinuxListProperties(ClientPtr client)402*4882a593Smuzhiyun ProcSELinuxListProperties(ClientPtr client)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun WindowPtr pWin;
405*4882a593Smuzhiyun PropertyPtr pProp;
406*4882a593Smuzhiyun SELinuxListItemRec *items;
407*4882a593Smuzhiyun int rc, count, size, i;
408*4882a593Smuzhiyun CARD32 id;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
411*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
414*4882a593Smuzhiyun if (rc != Success)
415*4882a593Smuzhiyun return rc;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /* Count the number of properties and allocate items */
418*4882a593Smuzhiyun count = 0;
419*4882a593Smuzhiyun for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
420*4882a593Smuzhiyun count++;
421*4882a593Smuzhiyun items = calloc(count, sizeof(SELinuxListItemRec));
422*4882a593Smuzhiyun if (count && !items)
423*4882a593Smuzhiyun return BadAlloc;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun /* Fill in the items and calculate size */
426*4882a593Smuzhiyun i = 0;
427*4882a593Smuzhiyun size = 0;
428*4882a593Smuzhiyun for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
429*4882a593Smuzhiyun id = pProp->propertyName;
430*4882a593Smuzhiyun rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size);
431*4882a593Smuzhiyun if (rc != Success) {
432*4882a593Smuzhiyun SELinuxFreeItems(items, count);
433*4882a593Smuzhiyun return rc;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun i++;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun return SELinuxSendItemsToClient(client, items, size, count);
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun static int
ProcSELinuxListSelections(ClientPtr client)442*4882a593Smuzhiyun ProcSELinuxListSelections(ClientPtr client)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun Selection *pSel;
445*4882a593Smuzhiyun SELinuxListItemRec *items;
446*4882a593Smuzhiyun int rc, count, size, i;
447*4882a593Smuzhiyun CARD32 id;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun /* Count the number of selections and allocate items */
452*4882a593Smuzhiyun count = 0;
453*4882a593Smuzhiyun for (pSel = CurrentSelections; pSel; pSel = pSel->next)
454*4882a593Smuzhiyun count++;
455*4882a593Smuzhiyun items = calloc(count, sizeof(SELinuxListItemRec));
456*4882a593Smuzhiyun if (count && !items)
457*4882a593Smuzhiyun return BadAlloc;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun /* Fill in the items and calculate size */
460*4882a593Smuzhiyun i = 0;
461*4882a593Smuzhiyun size = 0;
462*4882a593Smuzhiyun for (pSel = CurrentSelections; pSel; pSel = pSel->next) {
463*4882a593Smuzhiyun id = pSel->selection;
464*4882a593Smuzhiyun rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size);
465*4882a593Smuzhiyun if (rc != Success) {
466*4882a593Smuzhiyun SELinuxFreeItems(items, count);
467*4882a593Smuzhiyun return rc;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun i++;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun return SELinuxSendItemsToClient(client, items, size, count);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun static int
ProcSELinuxDispatch(ClientPtr client)476*4882a593Smuzhiyun ProcSELinuxDispatch(ClientPtr client)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun REQUEST(xReq);
479*4882a593Smuzhiyun switch (stuff->data) {
480*4882a593Smuzhiyun case X_SELinuxQueryVersion:
481*4882a593Smuzhiyun return ProcSELinuxQueryVersion(client);
482*4882a593Smuzhiyun case X_SELinuxSetDeviceCreateContext:
483*4882a593Smuzhiyun return ProcSELinuxSetCreateContext(client, CTX_DEV);
484*4882a593Smuzhiyun case X_SELinuxGetDeviceCreateContext:
485*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, CTX_DEV);
486*4882a593Smuzhiyun case X_SELinuxSetDeviceContext:
487*4882a593Smuzhiyun return ProcSELinuxSetDeviceContext(client);
488*4882a593Smuzhiyun case X_SELinuxGetDeviceContext:
489*4882a593Smuzhiyun return ProcSELinuxGetDeviceContext(client);
490*4882a593Smuzhiyun case X_SELinuxSetDrawableCreateContext:
491*4882a593Smuzhiyun return ProcSELinuxSetCreateContext(client, CTX_WIN);
492*4882a593Smuzhiyun case X_SELinuxGetDrawableCreateContext:
493*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, CTX_WIN);
494*4882a593Smuzhiyun case X_SELinuxGetDrawableContext:
495*4882a593Smuzhiyun return ProcSELinuxGetDrawableContext(client);
496*4882a593Smuzhiyun case X_SELinuxSetPropertyCreateContext:
497*4882a593Smuzhiyun return ProcSELinuxSetCreateContext(client, CTX_PRP);
498*4882a593Smuzhiyun case X_SELinuxGetPropertyCreateContext:
499*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, CTX_PRP);
500*4882a593Smuzhiyun case X_SELinuxSetPropertyUseContext:
501*4882a593Smuzhiyun return ProcSELinuxSetCreateContext(client, USE_PRP);
502*4882a593Smuzhiyun case X_SELinuxGetPropertyUseContext:
503*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, USE_PRP);
504*4882a593Smuzhiyun case X_SELinuxGetPropertyContext:
505*4882a593Smuzhiyun return ProcSELinuxGetPropertyContext(client, objectKey);
506*4882a593Smuzhiyun case X_SELinuxGetPropertyDataContext:
507*4882a593Smuzhiyun return ProcSELinuxGetPropertyContext(client, dataKey);
508*4882a593Smuzhiyun case X_SELinuxListProperties:
509*4882a593Smuzhiyun return ProcSELinuxListProperties(client);
510*4882a593Smuzhiyun case X_SELinuxSetSelectionCreateContext:
511*4882a593Smuzhiyun return ProcSELinuxSetCreateContext(client, CTX_SEL);
512*4882a593Smuzhiyun case X_SELinuxGetSelectionCreateContext:
513*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, CTX_SEL);
514*4882a593Smuzhiyun case X_SELinuxSetSelectionUseContext:
515*4882a593Smuzhiyun return ProcSELinuxSetCreateContext(client, USE_SEL);
516*4882a593Smuzhiyun case X_SELinuxGetSelectionUseContext:
517*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, USE_SEL);
518*4882a593Smuzhiyun case X_SELinuxGetSelectionContext:
519*4882a593Smuzhiyun return ProcSELinuxGetSelectionContext(client, objectKey);
520*4882a593Smuzhiyun case X_SELinuxGetSelectionDataContext:
521*4882a593Smuzhiyun return ProcSELinuxGetSelectionContext(client, dataKey);
522*4882a593Smuzhiyun case X_SELinuxListSelections:
523*4882a593Smuzhiyun return ProcSELinuxListSelections(client);
524*4882a593Smuzhiyun case X_SELinuxGetClientContext:
525*4882a593Smuzhiyun return ProcSELinuxGetClientContext(client);
526*4882a593Smuzhiyun default:
527*4882a593Smuzhiyun return BadRequest;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxQueryVersion(ClientPtr client)532*4882a593Smuzhiyun SProcSELinuxQueryVersion(ClientPtr client)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun return ProcSELinuxQueryVersion(client);
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxSetCreateContext(ClientPtr client,unsigned offset)538*4882a593Smuzhiyun SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun REQUEST(SELinuxSetCreateContextReq);
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
543*4882a593Smuzhiyun swapl(&stuff->context_len);
544*4882a593Smuzhiyun return ProcSELinuxSetCreateContext(client, offset);
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxSetDeviceContext(ClientPtr client)548*4882a593Smuzhiyun SProcSELinuxSetDeviceContext(ClientPtr client)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun REQUEST(SELinuxSetContextReq);
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq);
553*4882a593Smuzhiyun swapl(&stuff->id);
554*4882a593Smuzhiyun swapl(&stuff->context_len);
555*4882a593Smuzhiyun return ProcSELinuxSetDeviceContext(client);
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxGetDeviceContext(ClientPtr client)559*4882a593Smuzhiyun SProcSELinuxGetDeviceContext(ClientPtr client)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
564*4882a593Smuzhiyun swapl(&stuff->id);
565*4882a593Smuzhiyun return ProcSELinuxGetDeviceContext(client);
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxGetDrawableContext(ClientPtr client)569*4882a593Smuzhiyun SProcSELinuxGetDrawableContext(ClientPtr client)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
574*4882a593Smuzhiyun swapl(&stuff->id);
575*4882a593Smuzhiyun return ProcSELinuxGetDrawableContext(client);
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxGetPropertyContext(ClientPtr client,void * privKey)579*4882a593Smuzhiyun SProcSELinuxGetPropertyContext(ClientPtr client, void *privKey)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun REQUEST(SELinuxGetPropertyContextReq);
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
584*4882a593Smuzhiyun swapl(&stuff->window);
585*4882a593Smuzhiyun swapl(&stuff->property);
586*4882a593Smuzhiyun return ProcSELinuxGetPropertyContext(client, privKey);
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxGetSelectionContext(ClientPtr client,void * privKey)590*4882a593Smuzhiyun SProcSELinuxGetSelectionContext(ClientPtr client, void *privKey)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
595*4882a593Smuzhiyun swapl(&stuff->id);
596*4882a593Smuzhiyun return ProcSELinuxGetSelectionContext(client, privKey);
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxListProperties(ClientPtr client)600*4882a593Smuzhiyun SProcSELinuxListProperties(ClientPtr client)
601*4882a593Smuzhiyun {
602*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
605*4882a593Smuzhiyun swapl(&stuff->id);
606*4882a593Smuzhiyun return ProcSELinuxListProperties(client);
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxGetClientContext(ClientPtr client)610*4882a593Smuzhiyun SProcSELinuxGetClientContext(ClientPtr client)
611*4882a593Smuzhiyun {
612*4882a593Smuzhiyun REQUEST(SELinuxGetContextReq);
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun REQUEST_SIZE_MATCH(SELinuxGetContextReq);
615*4882a593Smuzhiyun swapl(&stuff->id);
616*4882a593Smuzhiyun return ProcSELinuxGetClientContext(client);
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun static int _X_COLD
SProcSELinuxDispatch(ClientPtr client)620*4882a593Smuzhiyun SProcSELinuxDispatch(ClientPtr client)
621*4882a593Smuzhiyun {
622*4882a593Smuzhiyun REQUEST(xReq);
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun swaps(&stuff->length);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun switch (stuff->data) {
627*4882a593Smuzhiyun case X_SELinuxQueryVersion:
628*4882a593Smuzhiyun return SProcSELinuxQueryVersion(client);
629*4882a593Smuzhiyun case X_SELinuxSetDeviceCreateContext:
630*4882a593Smuzhiyun return SProcSELinuxSetCreateContext(client, CTX_DEV);
631*4882a593Smuzhiyun case X_SELinuxGetDeviceCreateContext:
632*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, CTX_DEV);
633*4882a593Smuzhiyun case X_SELinuxSetDeviceContext:
634*4882a593Smuzhiyun return SProcSELinuxSetDeviceContext(client);
635*4882a593Smuzhiyun case X_SELinuxGetDeviceContext:
636*4882a593Smuzhiyun return SProcSELinuxGetDeviceContext(client);
637*4882a593Smuzhiyun case X_SELinuxSetDrawableCreateContext:
638*4882a593Smuzhiyun return SProcSELinuxSetCreateContext(client, CTX_WIN);
639*4882a593Smuzhiyun case X_SELinuxGetDrawableCreateContext:
640*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, CTX_WIN);
641*4882a593Smuzhiyun case X_SELinuxGetDrawableContext:
642*4882a593Smuzhiyun return SProcSELinuxGetDrawableContext(client);
643*4882a593Smuzhiyun case X_SELinuxSetPropertyCreateContext:
644*4882a593Smuzhiyun return SProcSELinuxSetCreateContext(client, CTX_PRP);
645*4882a593Smuzhiyun case X_SELinuxGetPropertyCreateContext:
646*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, CTX_PRP);
647*4882a593Smuzhiyun case X_SELinuxSetPropertyUseContext:
648*4882a593Smuzhiyun return SProcSELinuxSetCreateContext(client, USE_PRP);
649*4882a593Smuzhiyun case X_SELinuxGetPropertyUseContext:
650*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, USE_PRP);
651*4882a593Smuzhiyun case X_SELinuxGetPropertyContext:
652*4882a593Smuzhiyun return SProcSELinuxGetPropertyContext(client, objectKey);
653*4882a593Smuzhiyun case X_SELinuxGetPropertyDataContext:
654*4882a593Smuzhiyun return SProcSELinuxGetPropertyContext(client, dataKey);
655*4882a593Smuzhiyun case X_SELinuxListProperties:
656*4882a593Smuzhiyun return SProcSELinuxListProperties(client);
657*4882a593Smuzhiyun case X_SELinuxSetSelectionCreateContext:
658*4882a593Smuzhiyun return SProcSELinuxSetCreateContext(client, CTX_SEL);
659*4882a593Smuzhiyun case X_SELinuxGetSelectionCreateContext:
660*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, CTX_SEL);
661*4882a593Smuzhiyun case X_SELinuxSetSelectionUseContext:
662*4882a593Smuzhiyun return SProcSELinuxSetCreateContext(client, USE_SEL);
663*4882a593Smuzhiyun case X_SELinuxGetSelectionUseContext:
664*4882a593Smuzhiyun return ProcSELinuxGetCreateContext(client, USE_SEL);
665*4882a593Smuzhiyun case X_SELinuxGetSelectionContext:
666*4882a593Smuzhiyun return SProcSELinuxGetSelectionContext(client, objectKey);
667*4882a593Smuzhiyun case X_SELinuxGetSelectionDataContext:
668*4882a593Smuzhiyun return SProcSELinuxGetSelectionContext(client, dataKey);
669*4882a593Smuzhiyun case X_SELinuxListSelections:
670*4882a593Smuzhiyun return ProcSELinuxListSelections(client);
671*4882a593Smuzhiyun case X_SELinuxGetClientContext:
672*4882a593Smuzhiyun return SProcSELinuxGetClientContext(client);
673*4882a593Smuzhiyun default:
674*4882a593Smuzhiyun return BadRequest;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun /*
679*4882a593Smuzhiyun * Extension Setup / Teardown
680*4882a593Smuzhiyun */
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun static void
SELinuxResetProc(ExtensionEntry * extEntry)683*4882a593Smuzhiyun SELinuxResetProc(ExtensionEntry * extEntry)
684*4882a593Smuzhiyun {
685*4882a593Smuzhiyun SELinuxFlaskReset();
686*4882a593Smuzhiyun SELinuxLabelReset();
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun void
SELinuxExtensionInit(void)690*4882a593Smuzhiyun SELinuxExtensionInit(void)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun ExtensionEntry *extEntry;
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun /* Check SELinux mode on system, configuration file, and boolean */
695*4882a593Smuzhiyun if (!is_selinux_enabled()) {
696*4882a593Smuzhiyun LogMessage(X_INFO, "SELinux: Disabled on system\n");
697*4882a593Smuzhiyun return;
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun if (selinuxEnforcingState == SELINUX_MODE_DISABLED) {
700*4882a593Smuzhiyun LogMessage(X_INFO, "SELinux: Disabled in configuration file\n");
701*4882a593Smuzhiyun return;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun if (!security_get_boolean_active("xserver_object_manager")) {
704*4882a593Smuzhiyun LogMessage(X_INFO, "SELinux: Disabled by boolean\n");
705*4882a593Smuzhiyun return;
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun /* Set up XACE hooks */
709*4882a593Smuzhiyun SELinuxLabelInit();
710*4882a593Smuzhiyun SELinuxFlaskInit();
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun /* Add extension to server */
713*4882a593Smuzhiyun extEntry = AddExtension(SELINUX_EXTENSION_NAME,
714*4882a593Smuzhiyun SELinuxNumberEvents, SELinuxNumberErrors,
715*4882a593Smuzhiyun ProcSELinuxDispatch, SProcSELinuxDispatch,
716*4882a593Smuzhiyun SELinuxResetProc, StandardMinorOpcode);
717*4882a593Smuzhiyun }
718