xselinux_hooks.c revision 6747b715
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" 436747b715Smrg#include "../os/osdep.h" 446747b715Smrg#define _XSELINUX_NEED_FLASK_MAP 456747b715Smrg#include "xselinuxint.h" 466747b715Smrg 476747b715Smrg 486747b715Smrg/* structure passed to auditing callback */ 496747b715Smrgtypedef struct { 506747b715Smrg ClientPtr client; /* client */ 516747b715Smrg DeviceIntPtr dev; /* device */ 526747b715Smrg char *command; /* client's executable path */ 536747b715Smrg unsigned id; /* resource id, if any */ 546747b715Smrg int restype; /* resource type, if any */ 556747b715Smrg int event; /* event type, if any */ 566747b715Smrg Atom property; /* property name, if any */ 576747b715Smrg Atom selection; /* selection name, if any */ 586747b715Smrg char *extension; /* extension name, if any */ 596747b715Smrg} SELinuxAuditRec; 606747b715Smrg 616747b715Smrg/* private state keys */ 626747b715SmrgDevPrivateKeyRec subjectKeyRec; 636747b715SmrgDevPrivateKeyRec objectKeyRec; 646747b715SmrgDevPrivateKeyRec dataKeyRec; 656747b715Smrg 666747b715Smrg/* audit file descriptor */ 676747b715Smrgstatic int audit_fd; 686747b715Smrg 696747b715Smrg/* atoms for window label properties */ 706747b715Smrgstatic Atom atom_ctx; 716747b715Smrgstatic Atom atom_client_ctx; 726747b715Smrg 736747b715Smrg/* The unlabeled SID */ 746747b715Smrgstatic security_id_t unlabeled_sid; 756747b715Smrg 766747b715Smrg/* forward declarations */ 776747b715Smrgstatic void SELinuxScreen(CallbackListPtr *, pointer, pointer); 786747b715Smrg 796747b715Smrg/* "true" pointer value for use as callback data */ 806747b715Smrgstatic pointer truep = (pointer)1; 816747b715Smrg 826747b715Smrg 836747b715Smrg/* 846747b715Smrg * Performs an SELinux permission check. 856747b715Smrg */ 866747b715Smrgstatic int 876747b715SmrgSELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj, 886747b715Smrg security_class_t class, Mask mode, SELinuxAuditRec *auditdata) 896747b715Smrg{ 906747b715Smrg /* serverClient requests OK */ 916747b715Smrg if (subj->privileged) 926747b715Smrg return Success; 936747b715Smrg 946747b715Smrg auditdata->command = subj->command; 956747b715Smrg errno = 0; 966747b715Smrg 976747b715Smrg if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, 986747b715Smrg auditdata) < 0) { 996747b715Smrg if (mode == DixUnknownAccess) 1006747b715Smrg return Success; /* DixUnknownAccess requests OK ... for now */ 1016747b715Smrg if (errno == EACCES) 1026747b715Smrg return BadAccess; 1036747b715Smrg ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); 1046747b715Smrg return BadValue; 1056747b715Smrg } 1066747b715Smrg 1076747b715Smrg return Success; 1086747b715Smrg} 1096747b715Smrg 1106747b715Smrg/* 1116747b715Smrg * Labels a newly connected client. 1126747b715Smrg */ 1136747b715Smrgstatic void 1146747b715SmrgSELinuxLabelClient(ClientPtr client) 1156747b715Smrg{ 1166747b715Smrg int fd = XaceGetConnectionNumber(client); 1176747b715Smrg SELinuxSubjectRec *subj; 1186747b715Smrg SELinuxObjectRec *obj; 1196747b715Smrg security_context_t ctx; 1206747b715Smrg 1216747b715Smrg subj = dixLookupPrivate(&client->devPrivates, subjectKey); 1226747b715Smrg obj = dixLookupPrivate(&client->devPrivates, objectKey); 1236747b715Smrg 1246747b715Smrg /* Try to get a context from the socket */ 1256747b715Smrg if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { 1266747b715Smrg /* Otherwise, fall back to a default context */ 1276747b715Smrg ctx = SELinuxDefaultClientLabel(); 1286747b715Smrg } 1296747b715Smrg 1306747b715Smrg /* For local clients, try and determine the executable name */ 1316747b715Smrg if (XaceIsLocal(client)) { 1326747b715Smrg struct ucred creds; 1336747b715Smrg socklen_t len = sizeof(creds); 1346747b715Smrg char path[PATH_MAX + 1]; 1356747b715Smrg size_t bytes; 1366747b715Smrg 1376747b715Smrg memset(&creds, 0, sizeof(creds)); 1386747b715Smrg if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0) 1396747b715Smrg goto finish; 1406747b715Smrg 1416747b715Smrg snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid); 1426747b715Smrg fd = open(path, O_RDONLY); 1436747b715Smrg if (fd < 0) 1446747b715Smrg goto finish; 1456747b715Smrg 1466747b715Smrg bytes = read(fd, path, PATH_MAX + 1); 1476747b715Smrg close(fd); 1486747b715Smrg if (bytes <= 0) 1496747b715Smrg goto finish; 1506747b715Smrg 1516747b715Smrg strncpy(subj->command, path, COMMAND_LEN - 1); 1526747b715Smrg } 1536747b715Smrg 1546747b715Smrgfinish: 1556747b715Smrg /* Get a SID from the context */ 1566747b715Smrg if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) 1576747b715Smrg FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", 1586747b715Smrg client->index, ctx); 1596747b715Smrg 1606747b715Smrg obj->sid = subj->sid; 1616747b715Smrg freecon(ctx); 1626747b715Smrg} 1636747b715Smrg 1646747b715Smrg/* 1656747b715Smrg * Labels initial server objects. 1666747b715Smrg */ 1676747b715Smrgstatic void 1686747b715SmrgSELinuxLabelInitial(void) 1696747b715Smrg{ 1706747b715Smrg int i; 1716747b715Smrg XaceScreenAccessRec srec; 1726747b715Smrg SELinuxSubjectRec *subj; 1736747b715Smrg SELinuxObjectRec *obj; 1746747b715Smrg security_context_t ctx; 1756747b715Smrg pointer unused; 1766747b715Smrg 1776747b715Smrg /* Do the serverClient */ 1786747b715Smrg subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); 1796747b715Smrg obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); 1806747b715Smrg subj->privileged = 1; 1816747b715Smrg 1826747b715Smrg /* Use the context of the X server process for the serverClient */ 1836747b715Smrg if (getcon_raw(&ctx) < 0) 1846747b715Smrg FatalError("SELinux: couldn't get context of X server process\n"); 1856747b715Smrg 1866747b715Smrg /* Get a SID from the context */ 1876747b715Smrg if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) 1886747b715Smrg FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); 1896747b715Smrg 1906747b715Smrg obj->sid = subj->sid; 1916747b715Smrg freecon(ctx); 1926747b715Smrg 1936747b715Smrg srec.client = serverClient; 1946747b715Smrg srec.access_mode = DixCreateAccess; 1956747b715Smrg srec.status = Success; 1966747b715Smrg 1976747b715Smrg for (i = 0; i < screenInfo.numScreens; i++) { 1986747b715Smrg /* Do the screen object */ 1996747b715Smrg srec.screen = screenInfo.screens[i]; 2006747b715Smrg SELinuxScreen(NULL, NULL, &srec); 2016747b715Smrg 2026747b715Smrg /* Do the default colormap */ 2036747b715Smrg dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, 2046747b715Smrg RT_COLORMAP, serverClient, DixCreateAccess); 2056747b715Smrg } 2066747b715Smrg} 2076747b715Smrg 2086747b715Smrg/* 2096747b715Smrg * Labels new resource objects. 2106747b715Smrg */ 2116747b715Smrgstatic int 2126747b715SmrgSELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, 2136747b715Smrg SELinuxObjectRec *obj, security_class_t class) 2146747b715Smrg{ 2156747b715Smrg int offset; 2166747b715Smrg security_id_t tsid; 2176747b715Smrg 2186747b715Smrg /* Check for a create context */ 2196747b715Smrg if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) { 2206747b715Smrg obj->sid = subj->win_create_sid; 2216747b715Smrg return Success; 2226747b715Smrg } 2236747b715Smrg 2246747b715Smrg if (rec->parent) 2256747b715Smrg offset = dixLookupPrivateOffset(rec->ptype); 2266747b715Smrg 2276747b715Smrg if (rec->parent && offset >= 0) { 2286747b715Smrg /* Use the SID of the parent object in the labeling operation */ 2296747b715Smrg PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); 2306747b715Smrg SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); 2316747b715Smrg tsid = pobj->sid; 2326747b715Smrg } else { 2336747b715Smrg /* Use the SID of the subject */ 2346747b715Smrg 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) { 2396747b715Smrg ErrorF("SELinux: a compute_create call failed!\n"); 2406747b715Smrg return BadValue; 2416747b715Smrg } 2426747b715Smrg 2436747b715Smrg return Success; 2446747b715Smrg} 2456747b715Smrg 2466747b715Smrg 2476747b715Smrg/* 2486747b715Smrg * Libselinux Callbacks 2496747b715Smrg */ 2506747b715Smrg 2516747b715Smrgstatic int 2526747b715SmrgSELinuxAudit(void *auditdata, 2536747b715Smrg security_class_t class, 2546747b715Smrg char *msgbuf, 2556747b715Smrg size_t msgbufsize) 2566747b715Smrg{ 2576747b715Smrg SELinuxAuditRec *audit = auditdata; 2586747b715Smrg ClientPtr client = audit->client; 2596747b715Smrg char idNum[16]; 2606747b715Smrg const char *propertyName, *selectionName; 2616747b715Smrg int major = -1, minor = -1; 2626747b715Smrg 2636747b715Smrg if (client) { 2646747b715Smrg REQUEST(xReq); 2656747b715Smrg if (stuff) { 2666747b715Smrg major = stuff->reqType; 2676747b715Smrg minor = MinorOpcodeOfRequest(client); 2686747b715Smrg } 2696747b715Smrg } 2706747b715Smrg if (audit->id) 2716747b715Smrg snprintf(idNum, 16, "%x", audit->id); 2726747b715Smrg 2736747b715Smrg propertyName = audit->property ? NameForAtom(audit->property) : NULL; 2746747b715Smrg selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; 2756747b715Smrg 2766747b715Smrg return snprintf(msgbuf, msgbufsize, 2776747b715Smrg "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 2786747b715Smrg (major >= 0) ? "request=" : "", 2796747b715Smrg (major >= 0) ? LookupRequestName(major, minor) : "", 2806747b715Smrg audit->command ? " comm=" : "", 2816747b715Smrg audit->command ? audit->command : "", 2826747b715Smrg audit->dev ? " xdevice=\"" : "", 2836747b715Smrg audit->dev ? audit->dev->name : "", 2846747b715Smrg audit->dev ? "\"" : "", 2856747b715Smrg audit->id ? " resid=" : "", 2866747b715Smrg audit->id ? idNum : "", 2876747b715Smrg audit->restype ? " restype=" : "", 2886747b715Smrg audit->restype ? LookupResourceName(audit->restype) : "", 2896747b715Smrg audit->event ? " event=" : "", 2906747b715Smrg audit->event ? LookupEventName(audit->event & 127) : "", 2916747b715Smrg audit->property ? " property=" : "", 2926747b715Smrg audit->property ? propertyName : "", 2936747b715Smrg audit->selection ? " selection=" : "", 2946747b715Smrg audit->selection ? selectionName : "", 2956747b715Smrg audit->extension ? " extension=" : "", 2966747b715Smrg audit->extension ? audit->extension : ""); 2976747b715Smrg} 2986747b715Smrg 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: 3086747b715Smrg aut = AUDIT_USER_MAC_POLICY_LOAD; 3096747b715Smrg break; 3106747b715Smrg case SELINUX_AVC: 3116747b715Smrg aut = AUDIT_USER_AVC; 3126747b715Smrg break; 3136747b715Smrg default: 3146747b715Smrg aut = AUDIT_USER_SELINUX_ERR; 3156747b715Smrg 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); 3216747b715Smrg va_end(ap); 3226747b715Smrg LogMessageVerb(X_WARNING, 0, "%s", buf); 3236747b715Smrg return 0; 3246747b715Smrg} 3256747b715Smrg 3266747b715Smrg/* 3276747b715Smrg * XACE Callbacks 3286747b715Smrg */ 3296747b715Smrg 3306747b715Smrgstatic void 3316747b715SmrgSELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) 3326747b715Smrg{ 3336747b715Smrg XaceDeviceAccessRec *rec = calldata; 3346747b715Smrg SELinuxSubjectRec *subj; 3356747b715Smrg SELinuxObjectRec *obj; 3366747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; 3376747b715Smrg security_class_t cls; 3386747b715Smrg int rc; 3396747b715Smrg 3406747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 3416747b715Smrg obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); 3426747b715Smrg 3436747b715Smrg /* If this is a new object that needs labeling, do it now */ 3446747b715Smrg if (rec->access_mode & DixCreateAccess) { 3456747b715Smrg SELinuxSubjectRec *dsubj; 3466747b715Smrg dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); 3476747b715Smrg 3486747b715Smrg if (subj->dev_create_sid) { 3496747b715Smrg /* Label the device with the create context */ 3506747b715Smrg obj->sid = subj->dev_create_sid; 3516747b715Smrg dsubj->sid = subj->dev_create_sid; 3526747b715Smrg } else { 3536747b715Smrg /* Label the device directly with the process SID */ 3546747b715Smrg obj->sid = subj->sid; 3556747b715Smrg dsubj->sid = subj->sid; 3566747b715Smrg } 3576747b715Smrg } 3586747b715Smrg 3596747b715Smrg cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD; 3606747b715Smrg rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata); 3616747b715Smrg if (rc != Success) 3626747b715Smrg rec->status = rc; 3636747b715Smrg} 3646747b715Smrg 3656747b715Smrgstatic void 3666747b715SmrgSELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) 3676747b715Smrg{ 3686747b715Smrg XaceSendAccessRec *rec = calldata; 3696747b715Smrg SELinuxSubjectRec *subj; 3706747b715Smrg SELinuxObjectRec *obj, ev_sid; 3716747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; 3726747b715Smrg security_class_t class; 3736747b715Smrg int rc, i, type; 3746747b715Smrg 3756747b715Smrg if (rec->dev) 3766747b715Smrg subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); 3776747b715Smrg else 3786747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 3796747b715Smrg 3806747b715Smrg obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); 3816747b715Smrg 3826747b715Smrg /* Check send permission on window */ 3836747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, 3846747b715Smrg &auditdata); 3856747b715Smrg if (rc != Success) 3866747b715Smrg goto err; 3876747b715Smrg 3886747b715Smrg /* Check send permission on specific event types */ 3896747b715Smrg for (i = 0; i < rec->count; i++) { 3906747b715Smrg type = rec->events[i].u.u.type; 3916747b715Smrg class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; 3926747b715Smrg 3936747b715Smrg rc = SELinuxEventToSID(type, obj->sid, &ev_sid); 3946747b715Smrg if (rc != Success) 3956747b715Smrg goto err; 3966747b715Smrg 3976747b715Smrg auditdata.event = type; 3986747b715Smrg rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); 3996747b715Smrg if (rc != Success) 4006747b715Smrg goto err; 4016747b715Smrg } 4026747b715Smrg return; 4036747b715Smrgerr: 4046747b715Smrg rec->status = rc; 4056747b715Smrg} 4066747b715Smrg 4076747b715Smrgstatic void 4086747b715SmrgSELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) 4096747b715Smrg{ 4106747b715Smrg XaceReceiveAccessRec *rec = calldata; 4116747b715Smrg SELinuxSubjectRec *subj; 4126747b715Smrg SELinuxObjectRec *obj, ev_sid; 4136747b715Smrg SELinuxAuditRec auditdata = { .client = NULL }; 4146747b715Smrg security_class_t class; 4156747b715Smrg int rc, i, type; 4166747b715Smrg 4176747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 4186747b715Smrg obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); 4196747b715Smrg 4206747b715Smrg /* Check receive permission on window */ 4216747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, 4226747b715Smrg &auditdata); 4236747b715Smrg if (rc != Success) 4246747b715Smrg goto err; 4256747b715Smrg 4266747b715Smrg /* Check receive permission on specific event types */ 4276747b715Smrg for (i = 0; i < rec->count; i++) { 4286747b715Smrg type = rec->events[i].u.u.type; 4296747b715Smrg class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; 4306747b715Smrg 4316747b715Smrg rc = SELinuxEventToSID(type, obj->sid, &ev_sid); 4326747b715Smrg if (rc != Success) 4336747b715Smrg goto err; 4346747b715Smrg 4356747b715Smrg auditdata.event = type; 4366747b715Smrg rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); 4376747b715Smrg if (rc != Success) 4386747b715Smrg goto err; 4396747b715Smrg } 4406747b715Smrg return; 4416747b715Smrgerr: 4426747b715Smrg rec->status = rc; 4436747b715Smrg} 4446747b715Smrg 4456747b715Smrgstatic void 4466747b715SmrgSELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) 4476747b715Smrg{ 4486747b715Smrg XaceExtAccessRec *rec = calldata; 4496747b715Smrg SELinuxSubjectRec *subj, *serv; 4506747b715Smrg SELinuxObjectRec *obj; 4516747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 4526747b715Smrg int rc; 4536747b715Smrg 4546747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 4556747b715Smrg obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); 4566747b715Smrg 4576747b715Smrg /* If this is a new object that needs labeling, do it now */ 4586747b715Smrg /* XXX there should be a separate callback for this */ 4596747b715Smrg if (obj->sid == NULL) { 4606747b715Smrg security_id_t sid; 4616747b715Smrg 4626747b715Smrg serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); 4636747b715Smrg rc = SELinuxExtensionToSID(rec->ext->name, &sid); 4646747b715Smrg if (rc != Success) { 4656747b715Smrg rec->status = rc; 4666747b715Smrg return; 4676747b715Smrg } 4686747b715Smrg 4696747b715Smrg /* Perform a transition to obtain the final SID */ 4706747b715Smrg if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, 4716747b715Smrg &obj->sid) < 0) { 4726747b715Smrg ErrorF("SELinux: a SID transition call failed!\n"); 4736747b715Smrg rec->status = BadValue; 4746747b715Smrg return; 4756747b715Smrg } 4766747b715Smrg } 4776747b715Smrg 4786747b715Smrg /* Perform the security check */ 4796747b715Smrg auditdata.extension = rec->ext->name; 4806747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, 4816747b715Smrg &auditdata); 4826747b715Smrg if (rc != Success) 4836747b715Smrg rec->status = rc; 4846747b715Smrg} 4856747b715Smrg 4866747b715Smrgstatic void 4876747b715SmrgSELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) 4886747b715Smrg{ 4896747b715Smrg XaceSelectionAccessRec *rec = calldata; 4906747b715Smrg SELinuxSubjectRec *subj; 4916747b715Smrg SELinuxObjectRec *obj, *data; 4926747b715Smrg Selection *pSel = *rec->ppSel; 4936747b715Smrg Atom name = pSel->selection; 4946747b715Smrg Mask access_mode = rec->access_mode; 4956747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; 4966747b715Smrg security_id_t tsid; 4976747b715Smrg int rc; 4986747b715Smrg 4996747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 5006747b715Smrg obj = dixLookupPrivate(&pSel->devPrivates, objectKey); 5016747b715Smrg 5026747b715Smrg /* If this is a new object that needs labeling, do it now */ 5036747b715Smrg if (access_mode & DixCreateAccess) { 5046747b715Smrg rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); 5056747b715Smrg if (rc != Success) 5066747b715Smrg obj->sid = unlabeled_sid; 5076747b715Smrg access_mode = DixSetAttrAccess; 5086747b715Smrg } 5096747b715Smrg /* If this is a polyinstantiated object, find the right instance */ 5106747b715Smrg else if (obj->poly) { 5116747b715Smrg rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); 5126747b715Smrg if (rc != Success) { 5136747b715Smrg rec->status = rc; 5146747b715Smrg return; 5156747b715Smrg } 5166747b715Smrg while (pSel->selection != name || obj->sid != tsid) { 5176747b715Smrg if ((pSel = pSel->next) == NULL) 5186747b715Smrg break; 5196747b715Smrg obj = dixLookupPrivate(&pSel->devPrivates, objectKey); 5206747b715Smrg } 5216747b715Smrg 5226747b715Smrg if (pSel) 5236747b715Smrg *rec->ppSel = pSel; 5246747b715Smrg else { 5256747b715Smrg rec->status = BadMatch; 5266747b715Smrg return; 5276747b715Smrg } 5286747b715Smrg } 5296747b715Smrg 5306747b715Smrg /* Perform the security check */ 5316747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, 5326747b715Smrg &auditdata); 5336747b715Smrg if (rc != Success) 5346747b715Smrg rec->status = rc; 5356747b715Smrg 5366747b715Smrg /* Label the content (advisory only) */ 5376747b715Smrg if (access_mode & DixSetAttrAccess) { 5386747b715Smrg data = dixLookupPrivate(&pSel->devPrivates, dataKey); 5396747b715Smrg if (subj->sel_create_sid) 5406747b715Smrg data->sid = subj->sel_create_sid; 5416747b715Smrg else 5426747b715Smrg data->sid = obj->sid; 5436747b715Smrg } 5446747b715Smrg} 5456747b715Smrg 5466747b715Smrgstatic void 5476747b715SmrgSELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) 5486747b715Smrg{ 5496747b715Smrg XacePropertyAccessRec *rec = calldata; 5506747b715Smrg SELinuxSubjectRec *subj; 5516747b715Smrg SELinuxObjectRec *obj, *data; 5526747b715Smrg PropertyPtr pProp = *rec->ppProp; 5536747b715Smrg Atom name = pProp->propertyName; 5546747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; 5556747b715Smrg security_id_t tsid; 5566747b715Smrg int rc; 5576747b715Smrg 5586747b715Smrg /* Don't care about the new content check */ 5596747b715Smrg if (rec->access_mode & DixPostAccess) 5606747b715Smrg return; 5616747b715Smrg 5626747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 5636747b715Smrg obj = dixLookupPrivate(&pProp->devPrivates, objectKey); 5646747b715Smrg 5656747b715Smrg /* If this is a new object that needs labeling, do it now */ 5666747b715Smrg if (rec->access_mode & DixCreateAccess) { 5676747b715Smrg rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); 5686747b715Smrg if (rc != Success) { 5696747b715Smrg rec->status = rc; 5706747b715Smrg return; 5716747b715Smrg } 5726747b715Smrg } 5736747b715Smrg /* If this is a polyinstantiated object, find the right instance */ 5746747b715Smrg else if (obj->poly) { 5756747b715Smrg rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); 5766747b715Smrg if (rc != Success) { 5776747b715Smrg rec->status = rc; 5786747b715Smrg return; 5796747b715Smrg } 5806747b715Smrg while (pProp->propertyName != name || obj->sid != tsid) { 5816747b715Smrg if ((pProp = pProp->next) == NULL) 5826747b715Smrg break; 5836747b715Smrg obj = dixLookupPrivate(&pProp->devPrivates, objectKey); 5846747b715Smrg } 5856747b715Smrg 5866747b715Smrg if (pProp) 5876747b715Smrg *rec->ppProp = pProp; 5886747b715Smrg else { 5896747b715Smrg rec->status = BadMatch; 5906747b715Smrg return; 5916747b715Smrg } 5926747b715Smrg } 5936747b715Smrg 5946747b715Smrg /* Perform the security check */ 5956747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, 5966747b715Smrg &auditdata); 5976747b715Smrg if (rc != Success) 5986747b715Smrg rec->status = rc; 5996747b715Smrg 6006747b715Smrg /* Label the content (advisory only) */ 6016747b715Smrg if (rec->access_mode & DixWriteAccess) { 6026747b715Smrg data = dixLookupPrivate(&pProp->devPrivates, dataKey); 6036747b715Smrg if (subj->prp_create_sid) 6046747b715Smrg data->sid = subj->prp_create_sid; 6056747b715Smrg else 6066747b715Smrg data->sid = obj->sid; 6076747b715Smrg } 6086747b715Smrg} 6096747b715Smrg 6106747b715Smrgstatic void 6116747b715SmrgSELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) 6126747b715Smrg{ 6136747b715Smrg XaceResourceAccessRec *rec = calldata; 6146747b715Smrg SELinuxSubjectRec *subj; 6156747b715Smrg SELinuxObjectRec *obj; 6166747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 6176747b715Smrg Mask access_mode = rec->access_mode; 6186747b715Smrg PrivateRec **privatePtr; 6196747b715Smrg security_class_t class; 6206747b715Smrg int rc, offset; 6216747b715Smrg 6226747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 6236747b715Smrg 6246747b715Smrg /* Determine if the resource object has a devPrivates field */ 6256747b715Smrg offset = dixLookupPrivateOffset(rec->rtype); 6266747b715Smrg if (offset < 0) { 6276747b715Smrg /* No: use the SID of the owning client */ 6286747b715Smrg class = SECCLASS_X_RESOURCE; 6296747b715Smrg privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates; 6306747b715Smrg obj = dixLookupPrivate(privatePtr, objectKey); 6316747b715Smrg } else { 6326747b715Smrg /* Yes: use the SID from the resource object itself */ 6336747b715Smrg class = SELinuxTypeToClass(rec->rtype); 6346747b715Smrg privatePtr = DEVPRIV_AT(rec->res, offset); 6356747b715Smrg obj = dixLookupPrivate(privatePtr, objectKey); 6366747b715Smrg } 6376747b715Smrg 6386747b715Smrg /* If this is a new object that needs labeling, do it now */ 6396747b715Smrg if (access_mode & DixCreateAccess && offset >= 0) { 6406747b715Smrg rc = SELinuxLabelResource(rec, subj, obj, class); 6416747b715Smrg if (rc != Success) { 6426747b715Smrg rec->status = rc; 6436747b715Smrg return; 6446747b715Smrg } 6456747b715Smrg } 6466747b715Smrg 6476747b715Smrg /* Collapse generic resource permissions down to read/write */ 6486747b715Smrg if (class == SECCLASS_X_RESOURCE) { 6496747b715Smrg access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ 6506747b715Smrg access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ 6516747b715Smrg } 6526747b715Smrg 6536747b715Smrg /* Perform the security check */ 6546747b715Smrg auditdata.restype = rec->rtype; 6556747b715Smrg auditdata.id = rec->id; 6566747b715Smrg rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); 6576747b715Smrg if (rc != Success) 6586747b715Smrg rec->status = rc; 6596747b715Smrg 6606747b715Smrg /* Perform the background none check on windows */ 6616747b715Smrg if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { 6626747b715Smrg rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); 6636747b715Smrg if (rc != Success) 6646747b715Smrg ((WindowPtr)rec->res)->forcedBG = TRUE; 6656747b715Smrg } 6666747b715Smrg} 6676747b715Smrg 6686747b715Smrgstatic void 6696747b715SmrgSELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) 6706747b715Smrg{ 6716747b715Smrg XaceScreenAccessRec *rec = calldata; 6726747b715Smrg SELinuxSubjectRec *subj; 6736747b715Smrg SELinuxObjectRec *obj; 6746747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 6756747b715Smrg Mask access_mode = rec->access_mode; 6766747b715Smrg int rc; 6776747b715Smrg 6786747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 6796747b715Smrg obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); 6806747b715Smrg 6816747b715Smrg /* If this is a new object that needs labeling, do it now */ 6826747b715Smrg if (access_mode & DixCreateAccess) { 6836747b715Smrg /* Perform a transition to obtain the final SID */ 6846747b715Smrg if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, 6856747b715Smrg &obj->sid) < 0) { 6866747b715Smrg ErrorF("SELinux: a compute_create call failed!\n"); 6876747b715Smrg rec->status = BadValue; 6886747b715Smrg return; 6896747b715Smrg } 6906747b715Smrg } 6916747b715Smrg 6926747b715Smrg if (is_saver) 6936747b715Smrg access_mode <<= 2; 6946747b715Smrg 6956747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); 6966747b715Smrg if (rc != Success) 6976747b715Smrg rec->status = rc; 6986747b715Smrg} 6996747b715Smrg 7006747b715Smrgstatic void 7016747b715SmrgSELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) 7026747b715Smrg{ 7036747b715Smrg XaceClientAccessRec *rec = calldata; 7046747b715Smrg SELinuxSubjectRec *subj; 7056747b715Smrg SELinuxObjectRec *obj; 7066747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 7076747b715Smrg int rc; 7086747b715Smrg 7096747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 7106747b715Smrg obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); 7116747b715Smrg 7126747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, 7136747b715Smrg &auditdata); 7146747b715Smrg if (rc != Success) 7156747b715Smrg rec->status = rc; 7166747b715Smrg} 7176747b715Smrg 7186747b715Smrgstatic void 7196747b715SmrgSELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) 7206747b715Smrg{ 7216747b715Smrg XaceServerAccessRec *rec = calldata; 7226747b715Smrg SELinuxSubjectRec *subj; 7236747b715Smrg SELinuxObjectRec *obj; 7246747b715Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 7256747b715Smrg int rc; 7266747b715Smrg 7276747b715Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 7286747b715Smrg obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); 7296747b715Smrg 7306747b715Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, 7316747b715Smrg &auditdata); 7326747b715Smrg if (rc != Success) 7336747b715Smrg rec->status = rc; 7346747b715Smrg} 7356747b715Smrg 7366747b715Smrg 7376747b715Smrg/* 7386747b715Smrg * DIX Callbacks 7396747b715Smrg */ 7406747b715Smrg 7416747b715Smrgstatic void 7426747b715SmrgSELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) 7436747b715Smrg{ 7446747b715Smrg NewClientInfoRec *pci = calldata; 7456747b715Smrg 7466747b715Smrg switch (pci->client->clientState) { 7476747b715Smrg case ClientStateInitial: 7486747b715Smrg SELinuxLabelClient(pci->client); 7496747b715Smrg break; 7506747b715Smrg 7516747b715Smrg default: 7526747b715Smrg break; 7536747b715Smrg } 7546747b715Smrg} 7556747b715Smrg 7566747b715Smrgstatic void 7576747b715SmrgSELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) 7586747b715Smrg{ 7596747b715Smrg ResourceStateInfoRec *rec = calldata; 7606747b715Smrg SELinuxSubjectRec *subj; 7616747b715Smrg SELinuxObjectRec *obj; 7626747b715Smrg WindowPtr pWin; 7636747b715Smrg 7646747b715Smrg if (rec->type != RT_WINDOW) 7656747b715Smrg return; 7666747b715Smrg if (rec->state != ResourceStateAdding) 7676747b715Smrg return; 7686747b715Smrg 7696747b715Smrg pWin = (WindowPtr)rec->value; 7706747b715Smrg subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); 7716747b715Smrg 7726747b715Smrg if (subj->sid) { 7736747b715Smrg security_context_t ctx; 7746747b715Smrg int rc = avc_sid_to_context_raw(subj->sid, &ctx); 7756747b715Smrg if (rc < 0) 7766747b715Smrg FatalError("SELinux: Failed to get security context!\n"); 7776747b715Smrg rc = dixChangeWindowProperty(serverClient, 7786747b715Smrg pWin, atom_client_ctx, XA_STRING, 8, 7796747b715Smrg PropModeReplace, strlen(ctx), ctx, FALSE); 7806747b715Smrg if (rc != Success) 7816747b715Smrg FatalError("SELinux: Failed to set label property on window!\n"); 7826747b715Smrg freecon(ctx); 7836747b715Smrg } else 7846747b715Smrg FatalError("SELinux: Unexpected unlabeled client found\n"); 7856747b715Smrg 7866747b715Smrg obj = dixLookupPrivate(&pWin->devPrivates, objectKey); 7876747b715Smrg 7886747b715Smrg if (obj->sid) { 7896747b715Smrg security_context_t ctx; 7906747b715Smrg int rc = avc_sid_to_context_raw(obj->sid, &ctx); 7916747b715Smrg if (rc < 0) 7926747b715Smrg FatalError("SELinux: Failed to get security context!\n"); 7936747b715Smrg rc = dixChangeWindowProperty(serverClient, 7946747b715Smrg pWin, atom_ctx, XA_STRING, 8, 7956747b715Smrg PropModeReplace, strlen(ctx), ctx, FALSE); 7966747b715Smrg if (rc != Success) 7976747b715Smrg FatalError("SELinux: Failed to set label property on window!\n"); 7986747b715Smrg freecon(ctx); 7996747b715Smrg } else 8006747b715Smrg FatalError("SELinux: Unexpected unlabeled window found\n"); 8016747b715Smrg} 8026747b715Smrg 8036747b715Smrg 8046747b715Smrgstatic int netlink_fd; 8056747b715Smrg 8066747b715Smrgstatic void 8076747b715SmrgSELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) 8086747b715Smrg{ 8096747b715Smrg} 8106747b715Smrg 8116747b715Smrgstatic void 8126747b715SmrgSELinuxWakeupHandler(void *data, int err, void *read_mask) 8136747b715Smrg{ 8146747b715Smrg if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) 8156747b715Smrg 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(); 8416747b715Smrg RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, 8426747b715Smrg NULL); 8436747b715Smrg RemoveGeneralSocket(netlink_fd); 8446747b715Smrg 8456747b715Smrg avc_destroy(); 8466747b715Smrg} 8476747b715Smrg 8486747b715Smrgvoid 8496747b715SmrgSELinuxFlaskInit(void) 8506747b715Smrg{ 8516747b715Smrg struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; 8526747b715Smrg security_context_t ctx; 8536747b715Smrg int ret = TRUE; 8546747b715Smrg 8556747b715Smrg switch(selinuxEnforcingState) { 8566747b715Smrg case SELINUX_MODE_ENFORCING: 8576747b715Smrg LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); 8586747b715Smrg avc_option.value = (char *)1; 8596747b715Smrg break; 8606747b715Smrg case SELINUX_MODE_PERMISSIVE: 8616747b715Smrg LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); 8626747b715Smrg avc_option.value = (char *)0; 8636747b715Smrg break; 8646747b715Smrg default: 8656747b715Smrg avc_option.type = AVC_OPT_UNUSED; 8666747b715Smrg break; 8676747b715Smrg } 8686747b715Smrg 8696747b715Smrg /* Set up SELinux stuff */ 8706747b715Smrg selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); 8716747b715Smrg selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); 8726747b715Smrg 8736747b715Smrg if (selinux_set_mapping(map) < 0) { 8746747b715Smrg if (errno == EINVAL) { 8756747b715Smrg ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n"); 8766747b715Smrg return; 8776747b715Smrg } 8786747b715Smrg FatalError("SELinux: Failed to set up security class mapping\n"); 8796747b715Smrg } 8806747b715Smrg 8816747b715Smrg if (avc_open(&avc_option, 1) < 0) 8826747b715Smrg FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); 8836747b715Smrg 8846747b715Smrg if (security_get_initial_context_raw("unlabeled", &ctx) < 0) 8856747b715Smrg FatalError("SELinux: Failed to look up unlabeled context\n"); 8866747b715Smrg if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) 8876747b715Smrg 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) 8936747b715Smrg FatalError("SELinux: Failed to open the system audit log\n"); 8946747b715Smrg 8956747b715Smrg /* Allocate private storage */ 8966747b715Smrg if (!dixRegisterPrivateKey(subjectKey, PRIVATE_XSELINUX, sizeof(SELinuxSubjectRec)) || 8976747b715Smrg !dixRegisterPrivateKey(objectKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)) || 8986747b715Smrg !dixRegisterPrivateKey(dataKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec))) 8996747b715Smrg FatalError("SELinux: Failed to allocate private storage.\n"); 9006747b715Smrg 9016747b715Smrg /* Create atoms for doing window labeling */ 9026747b715Smrg atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); 9036747b715Smrg if (atom_ctx == BAD_RESOURCE) 9046747b715Smrg FatalError("SELinux: Failed to create atom\n"); 9056747b715Smrg atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); 9066747b715Smrg if (atom_client_ctx == BAD_RESOURCE) 9076747b715Smrg FatalError("SELinux: Failed to create atom\n"); 9086747b715Smrg 9096747b715Smrg netlink_fd = avc_netlink_acquire_fd(); 9106747b715Smrg AddGeneralSocket(netlink_fd); 9116747b715Smrg RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, 9126747b715Smrg NULL); 9136747b715Smrg 9146747b715Smrg /* Register callbacks */ 9156747b715Smrg ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); 9166747b715Smrg ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); 9176747b715Smrg 9186747b715Smrg ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); 9196747b715Smrg ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); 9206747b715Smrg ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); 9216747b715Smrg ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); 9226747b715Smrg ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); 9236747b715Smrg ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); 9246747b715Smrg ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); 9256747b715Smrg ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); 9266747b715Smrg ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); 9276747b715Smrg ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); 9286747b715Smrg ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); 9296747b715Smrg ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); 9306747b715Smrg if (!ret) 9316747b715Smrg FatalError("SELinux: Failed to register one or more callbacks\n"); 9326747b715Smrg 9336747b715Smrg /* Label objects that were created before we could register ourself */ 9346747b715Smrg SELinuxLabelInitial(); 9356747b715Smrg} 936