16747b715Smrg/************************************************************ 26747b715Smrg 36747b715SmrgAuthor: Eamon Walsh <ewalsh@tycho.nsa.gov> 46747b715Smrg 56747b715SmrgPermission to use, copy, modify, distribute, and sell this software and its 66747b715Smrgdocumentation for any purpose is hereby granted without fee, provided that 76747b715Smrgthis permission notice appear in supporting documentation. This permission 86747b715Smrgnotice shall be included in all copies or substantial portions of the 96747b715SmrgSoftware. 106747b715Smrg 116747b715SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 126747b715SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 136747b715SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 146747b715SmrgAUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 156747b715SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 166747b715SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 176747b715Smrg 186747b715Smrg********************************************************/ 196747b715Smrg 206747b715Smrg/* 216747b715Smrg * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc. 226747b715Smrg * All rights reserved. 236747b715Smrg */ 246747b715Smrg 256747b715Smrg#ifdef HAVE_DIX_CONFIG_H 266747b715Smrg#include <dix-config.h> 276747b715Smrg#endif 286747b715Smrg 296747b715Smrg#include <sys/socket.h> 306747b715Smrg#include <stdio.h> 316747b715Smrg#include <stdarg.h> 326747b715Smrg 336747b715Smrg#include <libaudit.h> 346747b715Smrg 356747b715Smrg#include <X11/Xatom.h> 366747b715Smrg#include "selection.h" 376747b715Smrg#include "inputstr.h" 386747b715Smrg#include "scrnintstr.h" 396747b715Smrg#include "windowstr.h" 406747b715Smrg#include "propertyst.h" 416747b715Smrg#include "extnsionst.h" 426747b715Smrg#include "xacestr.h" 4335c4bbdfSmrg#include "client.h" 446747b715Smrg#define _XSELINUX_NEED_FLASK_MAP 456747b715Smrg#include "xselinuxint.h" 466747b715Smrg 476747b715Smrg/* structure passed to auditing callback */ 486747b715Smrgtypedef struct { 4935c4bbdfSmrg ClientPtr client; /* client */ 5035c4bbdfSmrg DeviceIntPtr dev; /* device */ 5135c4bbdfSmrg char *command; /* client's executable path */ 5235c4bbdfSmrg unsigned id; /* resource id, if any */ 5335c4bbdfSmrg int restype; /* resource type, if any */ 5435c4bbdfSmrg int event; /* event type, if any */ 5535c4bbdfSmrg Atom property; /* property name, if any */ 5635c4bbdfSmrg Atom selection; /* selection name, if any */ 5735c4bbdfSmrg char *extension; /* extension name, if any */ 586747b715Smrg} SELinuxAuditRec; 596747b715Smrg 606747b715Smrg/* private state keys */ 616747b715SmrgDevPrivateKeyRec subjectKeyRec; 626747b715SmrgDevPrivateKeyRec objectKeyRec; 636747b715SmrgDevPrivateKeyRec dataKeyRec; 646747b715Smrg 656747b715Smrg/* audit file descriptor */ 666747b715Smrgstatic int audit_fd; 676747b715Smrg 686747b715Smrg/* atoms for window label properties */ 696747b715Smrgstatic Atom atom_ctx; 706747b715Smrgstatic Atom atom_client_ctx; 716747b715Smrg 726747b715Smrg/* The unlabeled SID */ 736747b715Smrgstatic security_id_t unlabeled_sid; 746747b715Smrg 756747b715Smrg/* forward declarations */ 7635c4bbdfSmrgstatic void SELinuxScreen(CallbackListPtr *, void *, void *); 776747b715Smrg 786747b715Smrg/* "true" pointer value for use as callback data */ 7935c4bbdfSmrgstatic void *truep = (void *) 1; 806747b715Smrg 816747b715Smrg/* 826747b715Smrg * Performs an SELinux permission check. 836747b715Smrg */ 846747b715Smrgstatic int 8535c4bbdfSmrgSELinuxDoCheck(SELinuxSubjectRec * subj, SELinuxObjectRec * obj, 8635c4bbdfSmrg security_class_t class, Mask mode, SELinuxAuditRec * auditdata) 876747b715Smrg{ 886747b715Smrg /* serverClient requests OK */ 896747b715Smrg if (subj->privileged) 9035c4bbdfSmrg return Success; 916747b715Smrg 926747b715Smrg auditdata->command = subj->command; 936747b715Smrg errno = 0; 946747b715Smrg 956747b715Smrg if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, 9635c4bbdfSmrg auditdata) < 0) { 9735c4bbdfSmrg if (mode == DixUnknownAccess) 9835c4bbdfSmrg return Success; /* DixUnknownAccess requests OK ... for now */ 9935c4bbdfSmrg if (errno == EACCES) 10035c4bbdfSmrg return BadAccess; 10135c4bbdfSmrg ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); 10235c4bbdfSmrg return BadValue; 1036747b715Smrg } 1046747b715Smrg 1056747b715Smrg return Success; 1066747b715Smrg} 1076747b715Smrg 1086747b715Smrg/* 1096747b715Smrg * Labels a newly connected client. 1106747b715Smrg */ 1116747b715Smrgstatic void 1126747b715SmrgSELinuxLabelClient(ClientPtr client) 1136747b715Smrg{ 1146747b715Smrg int fd = XaceGetConnectionNumber(client); 1156747b715Smrg SELinuxSubjectRec *subj; 1166747b715Smrg SELinuxObjectRec *obj; 117ed6184dfSmrg char *ctx; 1186747b715Smrg 1196747b715Smrg subj = dixLookupPrivate(&client->devPrivates, subjectKey); 1206747b715Smrg obj = dixLookupPrivate(&client->devPrivates, objectKey); 1216747b715Smrg 1226747b715Smrg /* Try to get a context from the socket */ 1236747b715Smrg if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { 12435c4bbdfSmrg /* Otherwise, fall back to a default context */ 12535c4bbdfSmrg ctx = SELinuxDefaultClientLabel(); 1266747b715Smrg } 1276747b715Smrg 1286747b715Smrg /* For local clients, try and determine the executable name */ 1296747b715Smrg if (XaceIsLocal(client)) { 13035c4bbdfSmrg /* Get cached command name if CLIENTIDS is enabled. */ 13135c4bbdfSmrg const char *cmdname = GetClientCmdName(client); 13235c4bbdfSmrg Bool cached = (cmdname != NULL); 13335c4bbdfSmrg 13435c4bbdfSmrg /* If CLIENTIDS is disabled, figure out the command name from 13535c4bbdfSmrg * scratch. */ 13635c4bbdfSmrg if (!cmdname) { 13735c4bbdfSmrg pid_t pid = DetermineClientPid(client); 13835c4bbdfSmrg 13935c4bbdfSmrg if (pid != -1) 14035c4bbdfSmrg DetermineClientCmd(pid, &cmdname, NULL); 14135c4bbdfSmrg } 14235c4bbdfSmrg 14335c4bbdfSmrg if (!cmdname) 14435c4bbdfSmrg goto finish; 14535c4bbdfSmrg 14635c4bbdfSmrg strncpy(subj->command, cmdname, COMMAND_LEN - 1); 14735c4bbdfSmrg 14835c4bbdfSmrg if (!cached) 14935c4bbdfSmrg free((void *) cmdname); /* const char * */ 1506747b715Smrg } 1516747b715Smrg 15235c4bbdfSmrg finish: 1536747b715Smrg /* Get a SID from the context */ 1546747b715Smrg if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) 15535c4bbdfSmrg FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", 15635c4bbdfSmrg client->index, ctx); 1576747b715Smrg 1586747b715Smrg obj->sid = subj->sid; 1596747b715Smrg freecon(ctx); 1606747b715Smrg} 1616747b715Smrg 1626747b715Smrg/* 1636747b715Smrg * Labels initial server objects. 1646747b715Smrg */ 1656747b715Smrgstatic void 1666747b715SmrgSELinuxLabelInitial(void) 1676747b715Smrg{ 1686747b715Smrg int i; 1696747b715Smrg XaceScreenAccessRec srec; 1706747b715Smrg SELinuxSubjectRec *subj; 1716747b715Smrg SELinuxObjectRec *obj; 172ed6184dfSmrg char *ctx; 17335c4bbdfSmrg void *unused; 1746747b715Smrg 1756747b715Smrg /* Do the serverClient */ 1766747b715Smrg subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); 1776747b715Smrg obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); 1786747b715Smrg subj->privileged = 1; 1796747b715Smrg 1806747b715Smrg /* Use the context of the X server process for the serverClient */ 1816747b715Smrg if (getcon_raw(&ctx) < 0) 18235c4bbdfSmrg FatalError("SELinux: couldn't get context of X server process\n"); 1836747b715Smrg 1846747b715Smrg /* Get a SID from the context */ 1856747b715Smrg if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) 18635c4bbdfSmrg FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); 1876747b715Smrg 1886747b715Smrg obj->sid = subj->sid; 1896747b715Smrg freecon(ctx); 1906747b715Smrg 1916747b715Smrg srec.client = serverClient; 1926747b715Smrg srec.access_mode = DixCreateAccess; 1936747b715Smrg srec.status = Success; 1946747b715Smrg 1956747b715Smrg for (i = 0; i < screenInfo.numScreens; i++) { 19635c4bbdfSmrg /* Do the screen object */ 19735c4bbdfSmrg srec.screen = screenInfo.screens[i]; 19835c4bbdfSmrg SELinuxScreen(NULL, NULL, &srec); 1996747b715Smrg 20035c4bbdfSmrg /* Do the default colormap */ 20135c4bbdfSmrg dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, 20235c4bbdfSmrg RT_COLORMAP, serverClient, DixCreateAccess); 2036747b715Smrg } 2046747b715Smrg} 2056747b715Smrg 2066747b715Smrg/* 2076747b715Smrg * Labels new resource objects. 2086747b715Smrg */ 2096747b715Smrgstatic int 21035c4bbdfSmrgSELinuxLabelResource(XaceResourceAccessRec * rec, SELinuxSubjectRec * subj, 21135c4bbdfSmrg SELinuxObjectRec * obj, security_class_t class) 2126747b715Smrg{ 2136747b715Smrg int offset; 2146747b715Smrg security_id_t tsid; 2156747b715Smrg 2166747b715Smrg /* Check for a create context */ 2176747b715Smrg if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) { 21835c4bbdfSmrg obj->sid = subj->win_create_sid; 21935c4bbdfSmrg return Success; 2206747b715Smrg } 2216747b715Smrg 2226747b715Smrg if (rec->parent) 22335c4bbdfSmrg offset = dixLookupPrivateOffset(rec->ptype); 2246747b715Smrg 2256747b715Smrg if (rec->parent && offset >= 0) { 22635c4bbdfSmrg /* Use the SID of the parent object in the labeling operation */ 22735c4bbdfSmrg PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); 22835c4bbdfSmrg SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); 22935c4bbdfSmrg 23035c4bbdfSmrg tsid = pobj->sid; 23135c4bbdfSmrg } 23235c4bbdfSmrg else { 23335c4bbdfSmrg /* Use the SID of the subject */ 23435c4bbdfSmrg tsid = subj->sid; 2356747b715Smrg } 2366747b715Smrg 2376747b715Smrg /* Perform a transition to obtain the final SID */ 2386747b715Smrg if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { 23935c4bbdfSmrg ErrorF("SELinux: a compute_create call failed!\n"); 24035c4bbdfSmrg return BadValue; 2416747b715Smrg } 2426747b715Smrg 2436747b715Smrg return Success; 2446747b715Smrg} 2456747b715Smrg 2466747b715Smrg/* 2476747b715Smrg * Libselinux Callbacks 2486747b715Smrg */ 2496747b715Smrg 2506747b715Smrgstatic int 2516747b715SmrgSELinuxAudit(void *auditdata, 25235c4bbdfSmrg security_class_t class, char *msgbuf, size_t msgbufsize) 2536747b715Smrg{ 2546747b715Smrg SELinuxAuditRec *audit = auditdata; 2556747b715Smrg ClientPtr client = audit->client; 2566747b715Smrg char idNum[16]; 2576747b715Smrg const char *propertyName, *selectionName; 2586747b715Smrg int major = -1, minor = -1; 2596747b715Smrg 2606747b715Smrg if (client) { 26135c4bbdfSmrg REQUEST(xReq); 26235c4bbdfSmrg if (stuff) { 26335c4bbdfSmrg major = client->majorOp; 26435c4bbdfSmrg minor = client->minorOp; 26535c4bbdfSmrg } 2666747b715Smrg } 2676747b715Smrg if (audit->id) 26835c4bbdfSmrg snprintf(idNum, 16, "%x", audit->id); 2696747b715Smrg 2706747b715Smrg propertyName = audit->property ? NameForAtom(audit->property) : NULL; 2716747b715Smrg selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; 2726747b715Smrg 2736747b715Smrg return snprintf(msgbuf, msgbufsize, 27435c4bbdfSmrg "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 27535c4bbdfSmrg (major >= 0) ? "request=" : "", 27635c4bbdfSmrg (major >= 0) ? LookupRequestName(major, minor) : "", 27735c4bbdfSmrg audit->command ? " comm=" : "", 27835c4bbdfSmrg audit->command ? audit->command : "", 27935c4bbdfSmrg audit->dev ? " xdevice=\"" : "", 28035c4bbdfSmrg audit->dev ? audit->dev->name : "", 28135c4bbdfSmrg audit->dev ? "\"" : "", 28235c4bbdfSmrg audit->id ? " resid=" : "", 28335c4bbdfSmrg audit->id ? idNum : "", 28435c4bbdfSmrg audit->restype ? " restype=" : "", 28535c4bbdfSmrg audit->restype ? LookupResourceName(audit->restype) : "", 28635c4bbdfSmrg audit->event ? " event=" : "", 28735c4bbdfSmrg audit->event ? LookupEventName(audit->event & 127) : "", 28835c4bbdfSmrg audit->property ? " property=" : "", 28935c4bbdfSmrg audit->property ? propertyName : "", 29035c4bbdfSmrg audit->selection ? " selection=" : "", 29135c4bbdfSmrg audit->selection ? selectionName : "", 29235c4bbdfSmrg audit->extension ? " extension=" : "", 29335c4bbdfSmrg audit->extension ? audit->extension : ""); 2946747b715Smrg} 2956747b715Smrg 29635c4bbdfSmrgstatic int 29735c4bbdfSmrgSELinuxLog(int type, const char *fmt, ...) _X_ATTRIBUTE_PRINTF(2, 3); 29835c4bbdfSmrg 2996747b715Smrgstatic int 3006747b715SmrgSELinuxLog(int type, const char *fmt, ...) 3016747b715Smrg{ 3026747b715Smrg va_list ap; 3036747b715Smrg char buf[MAX_AUDIT_MESSAGE_LENGTH]; 3046747b715Smrg int rc, aut; 3056747b715Smrg 3066747b715Smrg switch (type) { 3076747b715Smrg case SELINUX_INFO: 30835c4bbdfSmrg aut = AUDIT_USER_MAC_POLICY_LOAD; 30935c4bbdfSmrg break; 3106747b715Smrg case SELINUX_AVC: 31135c4bbdfSmrg aut = AUDIT_USER_AVC; 31235c4bbdfSmrg break; 3136747b715Smrg default: 31435c4bbdfSmrg aut = AUDIT_USER_SELINUX_ERR; 31535c4bbdfSmrg break; 3166747b715Smrg } 3176747b715Smrg 3186747b715Smrg va_start(ap, fmt); 3196747b715Smrg vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); 3206747b715Smrg rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); 32135c4bbdfSmrg (void) rc; 3226747b715Smrg va_end(ap); 3236747b715Smrg LogMessageVerb(X_WARNING, 0, "%s", buf); 3246747b715Smrg return 0; 3256747b715Smrg} 3266747b715Smrg 3276747b715Smrg/* 3286747b715Smrg * XACE Callbacks 3296747b715Smrg */ 3306747b715Smrg 3316747b715Smrgstatic void 33235c4bbdfSmrgSELinuxDevice(CallbackListPtr *pcbl, void *unused, void *calldata) 3336747b715Smrg{ 3346747b715Smrg XaceDeviceAccessRec *rec = calldata; 3356747b715Smrg SELinuxSubjectRec *subj; 3366747b715Smrg SELinuxObjectRec *obj; 33735c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client,.dev = rec->dev }; 3386747b715Smrg security_class_t cls; 3396747b715Smrg int rc; 3406747b715Smrg 3416747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 3426747b715Smrg obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); 3436747b715Smrg 3446747b715Smrg /* If this is a new object that needs labeling, do it now */ 3456747b715Smrg if (rec->access_mode & DixCreateAccess) { 34635c4bbdfSmrg SELinuxSubjectRec *dsubj; 34735c4bbdfSmrg 34835c4bbdfSmrg dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); 34935c4bbdfSmrg 35035c4bbdfSmrg if (subj->dev_create_sid) { 35135c4bbdfSmrg /* Label the device with the create context */ 35235c4bbdfSmrg obj->sid = subj->dev_create_sid; 35335c4bbdfSmrg dsubj->sid = subj->dev_create_sid; 35435c4bbdfSmrg } 35535c4bbdfSmrg else { 35635c4bbdfSmrg /* Label the device directly with the process SID */ 35735c4bbdfSmrg obj->sid = subj->sid; 35835c4bbdfSmrg dsubj->sid = subj->sid; 35935c4bbdfSmrg } 3606747b715Smrg } 3616747b715Smrg 3626747b715Smrg cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD; 3636747b715Smrg rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata); 3646747b715Smrg if (rc != Success) 36535c4bbdfSmrg rec->status = rc; 3666747b715Smrg} 3676747b715Smrg 3686747b715Smrgstatic void 36935c4bbdfSmrgSELinuxSend(CallbackListPtr *pcbl, void *unused, void *calldata) 3706747b715Smrg{ 3716747b715Smrg XaceSendAccessRec *rec = calldata; 3726747b715Smrg SELinuxSubjectRec *subj; 3736747b715Smrg SELinuxObjectRec *obj, ev_sid; 37435c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client,.dev = rec->dev }; 3756747b715Smrg security_class_t class; 3766747b715Smrg int rc, i, type; 3776747b715Smrg 3786747b715Smrg if (rec->dev) 37935c4bbdfSmrg subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); 3806747b715Smrg else 38135c4bbdfSmrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 3826747b715Smrg 3836747b715Smrg obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); 3846747b715Smrg 3856747b715Smrg /* Check send permission on window */ 3866747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, 38735c4bbdfSmrg &auditdata); 3886747b715Smrg if (rc != Success) 38935c4bbdfSmrg goto err; 3906747b715Smrg 3916747b715Smrg /* Check send permission on specific event types */ 3926747b715Smrg for (i = 0; i < rec->count; i++) { 39335c4bbdfSmrg type = rec->events[i].u.u.type; 39435c4bbdfSmrg class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; 3956747b715Smrg 39635c4bbdfSmrg rc = SELinuxEventToSID(type, obj->sid, &ev_sid); 39735c4bbdfSmrg if (rc != Success) 39835c4bbdfSmrg goto err; 3996747b715Smrg 40035c4bbdfSmrg auditdata.event = type; 40135c4bbdfSmrg rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); 40235c4bbdfSmrg if (rc != Success) 40335c4bbdfSmrg goto err; 4046747b715Smrg } 4056747b715Smrg return; 40635c4bbdfSmrg err: 4076747b715Smrg rec->status = rc; 4086747b715Smrg} 4096747b715Smrg 4106747b715Smrgstatic void 41135c4bbdfSmrgSELinuxReceive(CallbackListPtr *pcbl, void *unused, void *calldata) 4126747b715Smrg{ 4136747b715Smrg XaceReceiveAccessRec *rec = calldata; 4146747b715Smrg SELinuxSubjectRec *subj; 4156747b715Smrg SELinuxObjectRec *obj, ev_sid; 41635c4bbdfSmrg SELinuxAuditRec auditdata = {.client = NULL }; 4176747b715Smrg security_class_t class; 4186747b715Smrg int rc, i, type; 4196747b715Smrg 4206747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 4216747b715Smrg obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); 4226747b715Smrg 4236747b715Smrg /* Check receive permission on window */ 4246747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, 42535c4bbdfSmrg &auditdata); 4266747b715Smrg if (rc != Success) 42735c4bbdfSmrg goto err; 4286747b715Smrg 4296747b715Smrg /* Check receive permission on specific event types */ 4306747b715Smrg for (i = 0; i < rec->count; i++) { 43135c4bbdfSmrg type = rec->events[i].u.u.type; 43235c4bbdfSmrg class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; 4336747b715Smrg 43435c4bbdfSmrg rc = SELinuxEventToSID(type, obj->sid, &ev_sid); 43535c4bbdfSmrg if (rc != Success) 43635c4bbdfSmrg goto err; 4376747b715Smrg 43835c4bbdfSmrg auditdata.event = type; 43935c4bbdfSmrg rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); 44035c4bbdfSmrg if (rc != Success) 44135c4bbdfSmrg goto err; 4426747b715Smrg } 4436747b715Smrg return; 44435c4bbdfSmrg err: 4456747b715Smrg rec->status = rc; 4466747b715Smrg} 4476747b715Smrg 4486747b715Smrgstatic void 44935c4bbdfSmrgSELinuxExtension(CallbackListPtr *pcbl, void *unused, void *calldata) 4506747b715Smrg{ 4516747b715Smrg XaceExtAccessRec *rec = calldata; 4526747b715Smrg SELinuxSubjectRec *subj, *serv; 4536747b715Smrg SELinuxObjectRec *obj; 45435c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client }; 4556747b715Smrg int rc; 4566747b715Smrg 4576747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 4586747b715Smrg obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); 4596747b715Smrg 4606747b715Smrg /* If this is a new object that needs labeling, do it now */ 4616747b715Smrg /* XXX there should be a separate callback for this */ 4626747b715Smrg if (obj->sid == NULL) { 46335c4bbdfSmrg security_id_t sid; 46435c4bbdfSmrg 46535c4bbdfSmrg serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); 46635c4bbdfSmrg rc = SELinuxExtensionToSID(rec->ext->name, &sid); 46735c4bbdfSmrg if (rc != Success) { 46835c4bbdfSmrg rec->status = rc; 46935c4bbdfSmrg return; 47035c4bbdfSmrg } 47135c4bbdfSmrg 47235c4bbdfSmrg /* Perform a transition to obtain the final SID */ 47335c4bbdfSmrg if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, 47435c4bbdfSmrg &obj->sid) < 0) { 47535c4bbdfSmrg ErrorF("SELinux: a SID transition call failed!\n"); 47635c4bbdfSmrg rec->status = BadValue; 47735c4bbdfSmrg return; 47835c4bbdfSmrg } 4796747b715Smrg } 4806747b715Smrg 4816747b715Smrg /* Perform the security check */ 48235c4bbdfSmrg auditdata.extension = (char *) rec->ext->name; 4836747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, 48435c4bbdfSmrg &auditdata); 4856747b715Smrg if (rc != Success) 48635c4bbdfSmrg rec->status = rc; 4876747b715Smrg} 4886747b715Smrg 4896747b715Smrgstatic void 49035c4bbdfSmrgSELinuxSelection(CallbackListPtr *pcbl, void *unused, void *calldata) 4916747b715Smrg{ 4926747b715Smrg XaceSelectionAccessRec *rec = calldata; 4936747b715Smrg SELinuxSubjectRec *subj; 4946747b715Smrg SELinuxObjectRec *obj, *data; 4956747b715Smrg Selection *pSel = *rec->ppSel; 4966747b715Smrg Atom name = pSel->selection; 4976747b715Smrg Mask access_mode = rec->access_mode; 49835c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client,.selection = name }; 4996747b715Smrg security_id_t tsid; 5006747b715Smrg int rc; 5016747b715Smrg 5026747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 5036747b715Smrg obj = dixLookupPrivate(&pSel->devPrivates, objectKey); 5046747b715Smrg 5056747b715Smrg /* If this is a new object that needs labeling, do it now */ 5066747b715Smrg if (access_mode & DixCreateAccess) { 50735c4bbdfSmrg rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); 50835c4bbdfSmrg if (rc != Success) 50935c4bbdfSmrg obj->sid = unlabeled_sid; 51035c4bbdfSmrg access_mode = DixSetAttrAccess; 5116747b715Smrg } 5126747b715Smrg /* If this is a polyinstantiated object, find the right instance */ 5136747b715Smrg else if (obj->poly) { 51435c4bbdfSmrg rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); 51535c4bbdfSmrg if (rc != Success) { 51635c4bbdfSmrg rec->status = rc; 51735c4bbdfSmrg return; 51835c4bbdfSmrg } 51935c4bbdfSmrg while (pSel->selection != name || obj->sid != tsid) { 52035c4bbdfSmrg if ((pSel = pSel->next) == NULL) 52135c4bbdfSmrg break; 52235c4bbdfSmrg obj = dixLookupPrivate(&pSel->devPrivates, objectKey); 52335c4bbdfSmrg } 52435c4bbdfSmrg 52535c4bbdfSmrg if (pSel) 52635c4bbdfSmrg *rec->ppSel = pSel; 52735c4bbdfSmrg else { 52835c4bbdfSmrg rec->status = BadMatch; 52935c4bbdfSmrg return; 53035c4bbdfSmrg } 5316747b715Smrg } 5326747b715Smrg 5336747b715Smrg /* Perform the security check */ 5346747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, 53535c4bbdfSmrg &auditdata); 5366747b715Smrg if (rc != Success) 53735c4bbdfSmrg rec->status = rc; 5386747b715Smrg 5396747b715Smrg /* Label the content (advisory only) */ 5406747b715Smrg if (access_mode & DixSetAttrAccess) { 54135c4bbdfSmrg data = dixLookupPrivate(&pSel->devPrivates, dataKey); 54235c4bbdfSmrg if (subj->sel_create_sid) 54335c4bbdfSmrg data->sid = subj->sel_create_sid; 54435c4bbdfSmrg else 54535c4bbdfSmrg data->sid = obj->sid; 5466747b715Smrg } 5476747b715Smrg} 5486747b715Smrg 5496747b715Smrgstatic void 55035c4bbdfSmrgSELinuxProperty(CallbackListPtr *pcbl, void *unused, void *calldata) 5516747b715Smrg{ 5526747b715Smrg XacePropertyAccessRec *rec = calldata; 5536747b715Smrg SELinuxSubjectRec *subj; 5546747b715Smrg SELinuxObjectRec *obj, *data; 5556747b715Smrg PropertyPtr pProp = *rec->ppProp; 5566747b715Smrg Atom name = pProp->propertyName; 55735c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client,.property = name }; 5586747b715Smrg security_id_t tsid; 5596747b715Smrg int rc; 5606747b715Smrg 5616747b715Smrg /* Don't care about the new content check */ 5626747b715Smrg if (rec->access_mode & DixPostAccess) 56335c4bbdfSmrg return; 5646747b715Smrg 5656747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 5666747b715Smrg obj = dixLookupPrivate(&pProp->devPrivates, objectKey); 5676747b715Smrg 5686747b715Smrg /* If this is a new object that needs labeling, do it now */ 5696747b715Smrg if (rec->access_mode & DixCreateAccess) { 57035c4bbdfSmrg rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); 57135c4bbdfSmrg if (rc != Success) { 57235c4bbdfSmrg rec->status = rc; 57335c4bbdfSmrg return; 57435c4bbdfSmrg } 5756747b715Smrg } 5766747b715Smrg /* If this is a polyinstantiated object, find the right instance */ 5776747b715Smrg else if (obj->poly) { 57835c4bbdfSmrg rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); 57935c4bbdfSmrg if (rc != Success) { 58035c4bbdfSmrg rec->status = rc; 58135c4bbdfSmrg return; 58235c4bbdfSmrg } 58335c4bbdfSmrg while (pProp->propertyName != name || obj->sid != tsid) { 58435c4bbdfSmrg if ((pProp = pProp->next) == NULL) 58535c4bbdfSmrg break; 58635c4bbdfSmrg obj = dixLookupPrivate(&pProp->devPrivates, objectKey); 58735c4bbdfSmrg } 58835c4bbdfSmrg 58935c4bbdfSmrg if (pProp) 59035c4bbdfSmrg *rec->ppProp = pProp; 59135c4bbdfSmrg else { 59235c4bbdfSmrg rec->status = BadMatch; 59335c4bbdfSmrg return; 59435c4bbdfSmrg } 5956747b715Smrg } 5966747b715Smrg 5976747b715Smrg /* Perform the security check */ 5986747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, 59935c4bbdfSmrg &auditdata); 6006747b715Smrg if (rc != Success) 60135c4bbdfSmrg rec->status = rc; 6026747b715Smrg 6036747b715Smrg /* Label the content (advisory only) */ 6046747b715Smrg if (rec->access_mode & DixWriteAccess) { 60535c4bbdfSmrg data = dixLookupPrivate(&pProp->devPrivates, dataKey); 60635c4bbdfSmrg if (subj->prp_create_sid) 60735c4bbdfSmrg data->sid = subj->prp_create_sid; 60835c4bbdfSmrg else 60935c4bbdfSmrg data->sid = obj->sid; 6106747b715Smrg } 6116747b715Smrg} 6126747b715Smrg 6136747b715Smrgstatic void 61435c4bbdfSmrgSELinuxResource(CallbackListPtr *pcbl, void *unused, void *calldata) 6156747b715Smrg{ 6166747b715Smrg XaceResourceAccessRec *rec = calldata; 6176747b715Smrg SELinuxSubjectRec *subj; 6186747b715Smrg SELinuxObjectRec *obj; 61935c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client }; 6206747b715Smrg Mask access_mode = rec->access_mode; 6216747b715Smrg PrivateRec **privatePtr; 6226747b715Smrg security_class_t class; 6236747b715Smrg int rc, offset; 6246747b715Smrg 6256747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 6266747b715Smrg 6276747b715Smrg /* Determine if the resource object has a devPrivates field */ 6286747b715Smrg offset = dixLookupPrivateOffset(rec->rtype); 6296747b715Smrg if (offset < 0) { 63035c4bbdfSmrg /* No: use the SID of the owning client */ 63135c4bbdfSmrg class = SECCLASS_X_RESOURCE; 63235c4bbdfSmrg privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates; 63335c4bbdfSmrg obj = dixLookupPrivate(privatePtr, objectKey); 63435c4bbdfSmrg } 63535c4bbdfSmrg else { 63635c4bbdfSmrg /* Yes: use the SID from the resource object itself */ 63735c4bbdfSmrg class = SELinuxTypeToClass(rec->rtype); 63835c4bbdfSmrg privatePtr = DEVPRIV_AT(rec->res, offset); 63935c4bbdfSmrg obj = dixLookupPrivate(privatePtr, objectKey); 6406747b715Smrg } 6416747b715Smrg 6426747b715Smrg /* If this is a new object that needs labeling, do it now */ 6436747b715Smrg if (access_mode & DixCreateAccess && offset >= 0) { 64435c4bbdfSmrg rc = SELinuxLabelResource(rec, subj, obj, class); 64535c4bbdfSmrg if (rc != Success) { 64635c4bbdfSmrg rec->status = rc; 64735c4bbdfSmrg return; 64835c4bbdfSmrg } 6496747b715Smrg } 6506747b715Smrg 6516747b715Smrg /* Collapse generic resource permissions down to read/write */ 6526747b715Smrg if (class == SECCLASS_X_RESOURCE) { 65335c4bbdfSmrg access_mode = ! !(rec->access_mode & SELinuxReadMask); /* rd */ 65435c4bbdfSmrg access_mode |= ! !(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ 6556747b715Smrg } 6566747b715Smrg 6576747b715Smrg /* Perform the security check */ 6586747b715Smrg auditdata.restype = rec->rtype; 6596747b715Smrg auditdata.id = rec->id; 6606747b715Smrg rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); 6616747b715Smrg if (rc != Success) 66235c4bbdfSmrg rec->status = rc; 6636747b715Smrg 6646747b715Smrg /* Perform the background none check on windows */ 6656747b715Smrg if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { 66635c4bbdfSmrg rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); 66735c4bbdfSmrg if (rc != Success) 66835c4bbdfSmrg ((WindowPtr) rec->res)->forcedBG = TRUE; 6696747b715Smrg } 6706747b715Smrg} 6716747b715Smrg 6726747b715Smrgstatic void 67335c4bbdfSmrgSELinuxScreen(CallbackListPtr *pcbl, void *is_saver, void *calldata) 6746747b715Smrg{ 6756747b715Smrg XaceScreenAccessRec *rec = calldata; 6766747b715Smrg SELinuxSubjectRec *subj; 6776747b715Smrg SELinuxObjectRec *obj; 67835c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client }; 6796747b715Smrg Mask access_mode = rec->access_mode; 6806747b715Smrg int rc; 6816747b715Smrg 6826747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 6836747b715Smrg obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); 6846747b715Smrg 6856747b715Smrg /* If this is a new object that needs labeling, do it now */ 6866747b715Smrg if (access_mode & DixCreateAccess) { 68735c4bbdfSmrg /* Perform a transition to obtain the final SID */ 68835c4bbdfSmrg if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, 68935c4bbdfSmrg &obj->sid) < 0) { 69035c4bbdfSmrg ErrorF("SELinux: a compute_create call failed!\n"); 69135c4bbdfSmrg rec->status = BadValue; 69235c4bbdfSmrg return; 69335c4bbdfSmrg } 6946747b715Smrg } 6956747b715Smrg 6966747b715Smrg if (is_saver) 69735c4bbdfSmrg access_mode <<= 2; 6986747b715Smrg 6996747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); 7006747b715Smrg if (rc != Success) 70135c4bbdfSmrg rec->status = rc; 7026747b715Smrg} 7036747b715Smrg 7046747b715Smrgstatic void 70535c4bbdfSmrgSELinuxClient(CallbackListPtr *pcbl, void *unused, void *calldata) 7066747b715Smrg{ 7076747b715Smrg XaceClientAccessRec *rec = calldata; 7086747b715Smrg SELinuxSubjectRec *subj; 7096747b715Smrg SELinuxObjectRec *obj; 71035c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client }; 7116747b715Smrg int rc; 7126747b715Smrg 7136747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 7146747b715Smrg obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); 7156747b715Smrg 7166747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, 71735c4bbdfSmrg &auditdata); 7186747b715Smrg if (rc != Success) 71935c4bbdfSmrg rec->status = rc; 7206747b715Smrg} 7216747b715Smrg 7226747b715Smrgstatic void 72335c4bbdfSmrgSELinuxServer(CallbackListPtr *pcbl, void *unused, void *calldata) 7246747b715Smrg{ 7256747b715Smrg XaceServerAccessRec *rec = calldata; 7266747b715Smrg SELinuxSubjectRec *subj; 7276747b715Smrg SELinuxObjectRec *obj; 72835c4bbdfSmrg SELinuxAuditRec auditdata = {.client = rec->client }; 7296747b715Smrg int rc; 7306747b715Smrg 7316747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 7326747b715Smrg obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); 7336747b715Smrg 7346747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, 73535c4bbdfSmrg &auditdata); 7366747b715Smrg if (rc != Success) 73735c4bbdfSmrg rec->status = rc; 7386747b715Smrg} 7396747b715Smrg 7406747b715Smrg/* 7416747b715Smrg * DIX Callbacks 7426747b715Smrg */ 7436747b715Smrg 7446747b715Smrgstatic void 74535c4bbdfSmrgSELinuxClientState(CallbackListPtr *pcbl, void *unused, void *calldata) 7466747b715Smrg{ 7476747b715Smrg NewClientInfoRec *pci = calldata; 7486747b715Smrg 7496747b715Smrg switch (pci->client->clientState) { 7506747b715Smrg case ClientStateInitial: 75135c4bbdfSmrg SELinuxLabelClient(pci->client); 75235c4bbdfSmrg break; 7536747b715Smrg 7546747b715Smrg default: 75535c4bbdfSmrg break; 7566747b715Smrg } 7576747b715Smrg} 7586747b715Smrg 7596747b715Smrgstatic void 76035c4bbdfSmrgSELinuxResourceState(CallbackListPtr *pcbl, void *unused, void *calldata) 7616747b715Smrg{ 7626747b715Smrg ResourceStateInfoRec *rec = calldata; 7636747b715Smrg SELinuxSubjectRec *subj; 7646747b715Smrg SELinuxObjectRec *obj; 7656747b715Smrg WindowPtr pWin; 7666747b715Smrg 7676747b715Smrg if (rec->type != RT_WINDOW) 76835c4bbdfSmrg return; 7696747b715Smrg if (rec->state != ResourceStateAdding) 77035c4bbdfSmrg return; 7716747b715Smrg 77235c4bbdfSmrg pWin = (WindowPtr) rec->value; 7736747b715Smrg subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); 7746747b715Smrg 7756747b715Smrg if (subj->sid) { 776ed6184dfSmrg char *ctx; 77735c4bbdfSmrg int rc = avc_sid_to_context_raw(subj->sid, &ctx); 77835c4bbdfSmrg 77935c4bbdfSmrg if (rc < 0) 78035c4bbdfSmrg FatalError("SELinux: Failed to get security context!\n"); 78135c4bbdfSmrg rc = dixChangeWindowProperty(serverClient, 78235c4bbdfSmrg pWin, atom_client_ctx, XA_STRING, 8, 78335c4bbdfSmrg PropModeReplace, strlen(ctx), ctx, FALSE); 78435c4bbdfSmrg if (rc != Success) 78535c4bbdfSmrg FatalError("SELinux: Failed to set label property on window!\n"); 78635c4bbdfSmrg freecon(ctx); 78735c4bbdfSmrg } 78835c4bbdfSmrg else 78935c4bbdfSmrg FatalError("SELinux: Unexpected unlabeled client found\n"); 7906747b715Smrg 7916747b715Smrg obj = dixLookupPrivate(&pWin->devPrivates, objectKey); 7926747b715Smrg 7936747b715Smrg if (obj->sid) { 794ed6184dfSmrg char *ctx; 79535c4bbdfSmrg int rc = avc_sid_to_context_raw(obj->sid, &ctx); 79635c4bbdfSmrg 79735c4bbdfSmrg if (rc < 0) 79835c4bbdfSmrg FatalError("SELinux: Failed to get security context!\n"); 79935c4bbdfSmrg rc = dixChangeWindowProperty(serverClient, 80035c4bbdfSmrg pWin, atom_ctx, XA_STRING, 8, 80135c4bbdfSmrg PropModeReplace, strlen(ctx), ctx, FALSE); 80235c4bbdfSmrg if (rc != Success) 80335c4bbdfSmrg FatalError("SELinux: Failed to set label property on window!\n"); 80435c4bbdfSmrg freecon(ctx); 80535c4bbdfSmrg } 80635c4bbdfSmrg else 80735c4bbdfSmrg FatalError("SELinux: Unexpected unlabeled window found\n"); 8086747b715Smrg} 8096747b715Smrg 8106747b715Smrgstatic int netlink_fd; 8116747b715Smrg 8126747b715Smrgstatic void 8131b5d61b8SmrgSELinuxNetlinkNotify(int fd, int ready, void *data) 8146747b715Smrg{ 8151b5d61b8Smrg avc_netlink_check_nb(); 8166747b715Smrg} 8176747b715Smrg 8186747b715Smrgvoid 8196747b715SmrgSELinuxFlaskReset(void) 8206747b715Smrg{ 8216747b715Smrg /* Unregister callbacks */ 8226747b715Smrg DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); 8236747b715Smrg DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); 8246747b715Smrg 8256747b715Smrg XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); 8266747b715Smrg XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); 8276747b715Smrg XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); 8286747b715Smrg XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); 8296747b715Smrg XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); 8306747b715Smrg XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); 8316747b715Smrg XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); 8326747b715Smrg XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); 8336747b715Smrg XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); 8346747b715Smrg XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); 8356747b715Smrg XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); 8366747b715Smrg XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); 8376747b715Smrg 8386747b715Smrg /* Tear down SELinux stuff */ 8396747b715Smrg audit_close(audit_fd); 8406747b715Smrg avc_netlink_release_fd(); 8411b5d61b8Smrg RemoveNotifyFd(netlink_fd); 8426747b715Smrg 8436747b715Smrg avc_destroy(); 8446747b715Smrg} 8456747b715Smrg 8466747b715Smrgvoid 8476747b715SmrgSELinuxFlaskInit(void) 8486747b715Smrg{ 84935c4bbdfSmrg struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *) 0 }; 850ed6184dfSmrg char *ctx; 8516747b715Smrg int ret = TRUE; 8526747b715Smrg 85335c4bbdfSmrg switch (selinuxEnforcingState) { 8546747b715Smrg case SELINUX_MODE_ENFORCING: 85535c4bbdfSmrg LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); 85635c4bbdfSmrg avc_option.value = (char *) 1; 85735c4bbdfSmrg break; 8586747b715Smrg case SELINUX_MODE_PERMISSIVE: 85935c4bbdfSmrg LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); 86035c4bbdfSmrg avc_option.value = (char *) 0; 86135c4bbdfSmrg break; 8626747b715Smrg default: 86335c4bbdfSmrg avc_option.type = AVC_OPT_UNUSED; 86435c4bbdfSmrg break; 8656747b715Smrg } 8666747b715Smrg 8676747b715Smrg /* Set up SELinux stuff */ 86835c4bbdfSmrg selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) SELinuxLog); 86935c4bbdfSmrg selinux_set_callback(SELINUX_CB_AUDIT, 87035c4bbdfSmrg (union selinux_callback) SELinuxAudit); 8716747b715Smrg 8726747b715Smrg if (selinux_set_mapping(map) < 0) { 87335c4bbdfSmrg if (errno == EINVAL) { 87435c4bbdfSmrg ErrorF 87535c4bbdfSmrg ("SELinux: Invalid object class mapping, disabling SELinux support.\n"); 87635c4bbdfSmrg return; 87735c4bbdfSmrg } 87835c4bbdfSmrg FatalError("SELinux: Failed to set up security class mapping\n"); 8796747b715Smrg } 8806747b715Smrg 8816747b715Smrg if (avc_open(&avc_option, 1) < 0) 88235c4bbdfSmrg FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); 8836747b715Smrg 8846747b715Smrg if (security_get_initial_context_raw("unlabeled", &ctx) < 0) 88535c4bbdfSmrg FatalError("SELinux: Failed to look up unlabeled context\n"); 8866747b715Smrg if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) 88735c4bbdfSmrg FatalError("SELinux: a context_to_SID call failed!\n"); 8886747b715Smrg freecon(ctx); 8896747b715Smrg 8906747b715Smrg /* Prepare for auditing */ 8916747b715Smrg audit_fd = audit_open(); 8926747b715Smrg if (audit_fd < 0) 89335c4bbdfSmrg FatalError("SELinux: Failed to open the system audit log\n"); 8946747b715Smrg 8956747b715Smrg /* Allocate private storage */ 89635c4bbdfSmrg if (!dixRegisterPrivateKey 89735c4bbdfSmrg (subjectKey, PRIVATE_XSELINUX, sizeof(SELinuxSubjectRec)) || 89835c4bbdfSmrg !dixRegisterPrivateKey(objectKey, PRIVATE_XSELINUX, 89935c4bbdfSmrg sizeof(SELinuxObjectRec)) || 90035c4bbdfSmrg !dixRegisterPrivateKey(dataKey, PRIVATE_XSELINUX, 90135c4bbdfSmrg sizeof(SELinuxObjectRec))) 90235c4bbdfSmrg FatalError("SELinux: Failed to allocate private storage.\n"); 9036747b715Smrg 9046747b715Smrg /* Create atoms for doing window labeling */ 9056747b715Smrg atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); 9066747b715Smrg if (atom_ctx == BAD_RESOURCE) 90735c4bbdfSmrg FatalError("SELinux: Failed to create atom\n"); 9086747b715Smrg atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); 9096747b715Smrg if (atom_client_ctx == BAD_RESOURCE) 91035c4bbdfSmrg FatalError("SELinux: Failed to create atom\n"); 9116747b715Smrg 9126747b715Smrg netlink_fd = avc_netlink_acquire_fd(); 9131b5d61b8Smrg SetNotifyFd(netlink_fd, SELinuxNetlinkNotify, X_NOTIFY_READ, NULL); 9146747b715Smrg 9156747b715Smrg /* Register callbacks */ 9166747b715Smrg ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); 9176747b715Smrg ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); 9186747b715Smrg 9196747b715Smrg ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); 9206747b715Smrg ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); 9216747b715Smrg ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); 9226747b715Smrg ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); 9236747b715Smrg ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); 9246747b715Smrg ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); 9256747b715Smrg ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); 9266747b715Smrg ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); 9276747b715Smrg ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); 9286747b715Smrg ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); 9296747b715Smrg ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); 9306747b715Smrg ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); 9316747b715Smrg if (!ret) 93235c4bbdfSmrg FatalError("SELinux: Failed to register one or more callbacks\n"); 9336747b715Smrg 9346747b715Smrg /* Label objects that were created before we could register ourself */ 9356747b715Smrg SELinuxLabelInitial(); 9366747b715Smrg} 937