1706f2543Smrg/************************************************************ 2706f2543Smrg 3706f2543SmrgAuthor: Eamon Walsh <ewalsh@tycho.nsa.gov> 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthis permission notice appear in supporting documentation. This permission 8706f2543Smrgnotice shall be included in all copies or substantial portions of the 9706f2543SmrgSoftware. 10706f2543Smrg 11706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14706f2543SmrgAUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 15706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17706f2543Smrg 18706f2543Smrg********************************************************/ 19706f2543Smrg 20706f2543Smrg/* 21706f2543Smrg * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc. 22706f2543Smrg * All rights reserved. 23706f2543Smrg */ 24706f2543Smrg 25706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 26706f2543Smrg#include <dix-config.h> 27706f2543Smrg#endif 28706f2543Smrg 29706f2543Smrg#include <sys/socket.h> 30706f2543Smrg#include <stdio.h> 31706f2543Smrg#include <stdarg.h> 32706f2543Smrg 33706f2543Smrg#include <libaudit.h> 34706f2543Smrg 35706f2543Smrg#include <X11/Xatom.h> 36706f2543Smrg#include "selection.h" 37706f2543Smrg#include "inputstr.h" 38706f2543Smrg#include "scrnintstr.h" 39706f2543Smrg#include "windowstr.h" 40706f2543Smrg#include "propertyst.h" 41706f2543Smrg#include "extnsionst.h" 42706f2543Smrg#include "xacestr.h" 43706f2543Smrg#include "../os/osdep.h" 44706f2543Smrg#define _XSELINUX_NEED_FLASK_MAP 45706f2543Smrg#include "xselinuxint.h" 46706f2543Smrg 47706f2543Smrg 48706f2543Smrg/* structure passed to auditing callback */ 49706f2543Smrgtypedef struct { 50706f2543Smrg ClientPtr client; /* client */ 51706f2543Smrg DeviceIntPtr dev; /* device */ 52706f2543Smrg char *command; /* client's executable path */ 53706f2543Smrg unsigned id; /* resource id, if any */ 54706f2543Smrg int restype; /* resource type, if any */ 55706f2543Smrg int event; /* event type, if any */ 56706f2543Smrg Atom property; /* property name, if any */ 57706f2543Smrg Atom selection; /* selection name, if any */ 58706f2543Smrg char *extension; /* extension name, if any */ 59706f2543Smrg} SELinuxAuditRec; 60706f2543Smrg 61706f2543Smrg/* private state keys */ 62706f2543SmrgDevPrivateKeyRec subjectKeyRec; 63706f2543SmrgDevPrivateKeyRec objectKeyRec; 64706f2543SmrgDevPrivateKeyRec dataKeyRec; 65706f2543Smrg 66706f2543Smrg/* audit file descriptor */ 67706f2543Smrgstatic int audit_fd; 68706f2543Smrg 69706f2543Smrg/* atoms for window label properties */ 70706f2543Smrgstatic Atom atom_ctx; 71706f2543Smrgstatic Atom atom_client_ctx; 72706f2543Smrg 73706f2543Smrg/* The unlabeled SID */ 74706f2543Smrgstatic security_id_t unlabeled_sid; 75706f2543Smrg 76706f2543Smrg/* forward declarations */ 77706f2543Smrgstatic void SELinuxScreen(CallbackListPtr *, pointer, pointer); 78706f2543Smrg 79706f2543Smrg/* "true" pointer value for use as callback data */ 80706f2543Smrgstatic pointer truep = (pointer)1; 81706f2543Smrg 82706f2543Smrg 83706f2543Smrg/* 84706f2543Smrg * Performs an SELinux permission check. 85706f2543Smrg */ 86706f2543Smrgstatic int 87706f2543SmrgSELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj, 88706f2543Smrg security_class_t class, Mask mode, SELinuxAuditRec *auditdata) 89706f2543Smrg{ 90706f2543Smrg /* serverClient requests OK */ 91706f2543Smrg if (subj->privileged) 92706f2543Smrg return Success; 93706f2543Smrg 94706f2543Smrg auditdata->command = subj->command; 95706f2543Smrg errno = 0; 96706f2543Smrg 97706f2543Smrg if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, 98706f2543Smrg auditdata) < 0) { 99706f2543Smrg if (mode == DixUnknownAccess) 100706f2543Smrg return Success; /* DixUnknownAccess requests OK ... for now */ 101706f2543Smrg if (errno == EACCES) 102706f2543Smrg return BadAccess; 103706f2543Smrg ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); 104706f2543Smrg return BadValue; 105706f2543Smrg } 106706f2543Smrg 107706f2543Smrg return Success; 108706f2543Smrg} 109706f2543Smrg 110706f2543Smrg/* 111706f2543Smrg * Labels a newly connected client. 112706f2543Smrg */ 113706f2543Smrgstatic void 114706f2543SmrgSELinuxLabelClient(ClientPtr client) 115706f2543Smrg{ 116706f2543Smrg int fd = XaceGetConnectionNumber(client); 117706f2543Smrg SELinuxSubjectRec *subj; 118706f2543Smrg SELinuxObjectRec *obj; 119706f2543Smrg security_context_t ctx; 120706f2543Smrg 121706f2543Smrg subj = dixLookupPrivate(&client->devPrivates, subjectKey); 122706f2543Smrg obj = dixLookupPrivate(&client->devPrivates, objectKey); 123706f2543Smrg 124706f2543Smrg /* Try to get a context from the socket */ 125706f2543Smrg if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { 126706f2543Smrg /* Otherwise, fall back to a default context */ 127706f2543Smrg ctx = SELinuxDefaultClientLabel(); 128706f2543Smrg } 129706f2543Smrg 130706f2543Smrg /* For local clients, try and determine the executable name */ 131706f2543Smrg if (XaceIsLocal(client)) { 132706f2543Smrg struct ucred creds; 133706f2543Smrg socklen_t len = sizeof(creds); 134706f2543Smrg char path[PATH_MAX + 1]; 135706f2543Smrg size_t bytes; 136706f2543Smrg 137706f2543Smrg memset(&creds, 0, sizeof(creds)); 138706f2543Smrg if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0) 139706f2543Smrg goto finish; 140706f2543Smrg 141706f2543Smrg snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid); 142706f2543Smrg fd = open(path, O_RDONLY); 143706f2543Smrg if (fd < 0) 144706f2543Smrg goto finish; 145706f2543Smrg 146706f2543Smrg bytes = read(fd, path, PATH_MAX + 1); 147706f2543Smrg close(fd); 148706f2543Smrg if (bytes <= 0) 149706f2543Smrg goto finish; 150706f2543Smrg 151706f2543Smrg strncpy(subj->command, path, COMMAND_LEN - 1); 152706f2543Smrg } 153706f2543Smrg 154706f2543Smrgfinish: 155706f2543Smrg /* Get a SID from the context */ 156706f2543Smrg if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) 157706f2543Smrg FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", 158706f2543Smrg client->index, ctx); 159706f2543Smrg 160706f2543Smrg obj->sid = subj->sid; 161706f2543Smrg freecon(ctx); 162706f2543Smrg} 163706f2543Smrg 164706f2543Smrg/* 165706f2543Smrg * Labels initial server objects. 166706f2543Smrg */ 167706f2543Smrgstatic void 168706f2543SmrgSELinuxLabelInitial(void) 169706f2543Smrg{ 170706f2543Smrg int i; 171706f2543Smrg XaceScreenAccessRec srec; 172706f2543Smrg SELinuxSubjectRec *subj; 173706f2543Smrg SELinuxObjectRec *obj; 174706f2543Smrg security_context_t ctx; 175706f2543Smrg pointer unused; 176706f2543Smrg 177706f2543Smrg /* Do the serverClient */ 178706f2543Smrg subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); 179706f2543Smrg obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); 180706f2543Smrg subj->privileged = 1; 181706f2543Smrg 182706f2543Smrg /* Use the context of the X server process for the serverClient */ 183706f2543Smrg if (getcon_raw(&ctx) < 0) 184706f2543Smrg FatalError("SELinux: couldn't get context of X server process\n"); 185706f2543Smrg 186706f2543Smrg /* Get a SID from the context */ 187706f2543Smrg if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) 188706f2543Smrg FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); 189706f2543Smrg 190706f2543Smrg obj->sid = subj->sid; 191706f2543Smrg freecon(ctx); 192706f2543Smrg 193706f2543Smrg srec.client = serverClient; 194706f2543Smrg srec.access_mode = DixCreateAccess; 195706f2543Smrg srec.status = Success; 196706f2543Smrg 197706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) { 198706f2543Smrg /* Do the screen object */ 199706f2543Smrg srec.screen = screenInfo.screens[i]; 200706f2543Smrg SELinuxScreen(NULL, NULL, &srec); 201706f2543Smrg 202706f2543Smrg /* Do the default colormap */ 203706f2543Smrg dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, 204706f2543Smrg RT_COLORMAP, serverClient, DixCreateAccess); 205706f2543Smrg } 206706f2543Smrg} 207706f2543Smrg 208706f2543Smrg/* 209706f2543Smrg * Labels new resource objects. 210706f2543Smrg */ 211706f2543Smrgstatic int 212706f2543SmrgSELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, 213706f2543Smrg SELinuxObjectRec *obj, security_class_t class) 214706f2543Smrg{ 215706f2543Smrg int offset; 216706f2543Smrg security_id_t tsid; 217706f2543Smrg 218706f2543Smrg /* Check for a create context */ 219706f2543Smrg if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) { 220706f2543Smrg obj->sid = subj->win_create_sid; 221706f2543Smrg return Success; 222706f2543Smrg } 223706f2543Smrg 224706f2543Smrg if (rec->parent) 225706f2543Smrg offset = dixLookupPrivateOffset(rec->ptype); 226706f2543Smrg 227706f2543Smrg if (rec->parent && offset >= 0) { 228706f2543Smrg /* Use the SID of the parent object in the labeling operation */ 229706f2543Smrg PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); 230706f2543Smrg SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); 231706f2543Smrg tsid = pobj->sid; 232706f2543Smrg } else { 233706f2543Smrg /* Use the SID of the subject */ 234706f2543Smrg tsid = subj->sid; 235706f2543Smrg } 236706f2543Smrg 237706f2543Smrg /* Perform a transition to obtain the final SID */ 238706f2543Smrg if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { 239706f2543Smrg ErrorF("SELinux: a compute_create call failed!\n"); 240706f2543Smrg return BadValue; 241706f2543Smrg } 242706f2543Smrg 243706f2543Smrg return Success; 244706f2543Smrg} 245706f2543Smrg 246706f2543Smrg 247706f2543Smrg/* 248706f2543Smrg * Libselinux Callbacks 249706f2543Smrg */ 250706f2543Smrg 251706f2543Smrgstatic int 252706f2543SmrgSELinuxAudit(void *auditdata, 253706f2543Smrg security_class_t class, 254706f2543Smrg char *msgbuf, 255706f2543Smrg size_t msgbufsize) 256706f2543Smrg{ 257706f2543Smrg SELinuxAuditRec *audit = auditdata; 258706f2543Smrg ClientPtr client = audit->client; 259706f2543Smrg char idNum[16]; 260706f2543Smrg const char *propertyName, *selectionName; 261706f2543Smrg int major = -1, minor = -1; 262706f2543Smrg 263706f2543Smrg if (client) { 264706f2543Smrg REQUEST(xReq); 265706f2543Smrg if (stuff) { 266706f2543Smrg major = stuff->reqType; 267706f2543Smrg minor = MinorOpcodeOfRequest(client); 268706f2543Smrg } 269706f2543Smrg } 270706f2543Smrg if (audit->id) 271706f2543Smrg snprintf(idNum, 16, "%x", audit->id); 272706f2543Smrg 273706f2543Smrg propertyName = audit->property ? NameForAtom(audit->property) : NULL; 274706f2543Smrg selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; 275706f2543Smrg 276706f2543Smrg return snprintf(msgbuf, msgbufsize, 277706f2543Smrg "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 278706f2543Smrg (major >= 0) ? "request=" : "", 279706f2543Smrg (major >= 0) ? LookupRequestName(major, minor) : "", 280706f2543Smrg audit->command ? " comm=" : "", 281706f2543Smrg audit->command ? audit->command : "", 282706f2543Smrg audit->dev ? " xdevice=\"" : "", 283706f2543Smrg audit->dev ? audit->dev->name : "", 284706f2543Smrg audit->dev ? "\"" : "", 285706f2543Smrg audit->id ? " resid=" : "", 286706f2543Smrg audit->id ? idNum : "", 287706f2543Smrg audit->restype ? " restype=" : "", 288706f2543Smrg audit->restype ? LookupResourceName(audit->restype) : "", 289706f2543Smrg audit->event ? " event=" : "", 290706f2543Smrg audit->event ? LookupEventName(audit->event & 127) : "", 291706f2543Smrg audit->property ? " property=" : "", 292706f2543Smrg audit->property ? propertyName : "", 293706f2543Smrg audit->selection ? " selection=" : "", 294706f2543Smrg audit->selection ? selectionName : "", 295706f2543Smrg audit->extension ? " extension=" : "", 296706f2543Smrg audit->extension ? audit->extension : ""); 297706f2543Smrg} 298706f2543Smrg 299706f2543Smrgstatic int 300706f2543SmrgSELinuxLog(int type, const char *fmt, ...) 301706f2543Smrg{ 302706f2543Smrg va_list ap; 303706f2543Smrg char buf[MAX_AUDIT_MESSAGE_LENGTH]; 304706f2543Smrg int rc, aut; 305706f2543Smrg 306706f2543Smrg switch (type) { 307706f2543Smrg case SELINUX_INFO: 308706f2543Smrg aut = AUDIT_USER_MAC_POLICY_LOAD; 309706f2543Smrg break; 310706f2543Smrg case SELINUX_AVC: 311706f2543Smrg aut = AUDIT_USER_AVC; 312706f2543Smrg break; 313706f2543Smrg default: 314706f2543Smrg aut = AUDIT_USER_SELINUX_ERR; 315706f2543Smrg break; 316706f2543Smrg } 317706f2543Smrg 318706f2543Smrg va_start(ap, fmt); 319706f2543Smrg vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); 320706f2543Smrg rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); 321706f2543Smrg va_end(ap); 322706f2543Smrg LogMessageVerb(X_WARNING, 0, "%s", buf); 323706f2543Smrg return 0; 324706f2543Smrg} 325706f2543Smrg 326706f2543Smrg/* 327706f2543Smrg * XACE Callbacks 328706f2543Smrg */ 329706f2543Smrg 330706f2543Smrgstatic void 331706f2543SmrgSELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) 332706f2543Smrg{ 333706f2543Smrg XaceDeviceAccessRec *rec = calldata; 334706f2543Smrg SELinuxSubjectRec *subj; 335706f2543Smrg SELinuxObjectRec *obj; 336706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; 337706f2543Smrg security_class_t cls; 338706f2543Smrg int rc; 339706f2543Smrg 340706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 341706f2543Smrg obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); 342706f2543Smrg 343706f2543Smrg /* If this is a new object that needs labeling, do it now */ 344706f2543Smrg if (rec->access_mode & DixCreateAccess) { 345706f2543Smrg SELinuxSubjectRec *dsubj; 346706f2543Smrg dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); 347706f2543Smrg 348706f2543Smrg if (subj->dev_create_sid) { 349706f2543Smrg /* Label the device with the create context */ 350706f2543Smrg obj->sid = subj->dev_create_sid; 351706f2543Smrg dsubj->sid = subj->dev_create_sid; 352706f2543Smrg } else { 353706f2543Smrg /* Label the device directly with the process SID */ 354706f2543Smrg obj->sid = subj->sid; 355706f2543Smrg dsubj->sid = subj->sid; 356706f2543Smrg } 357706f2543Smrg } 358706f2543Smrg 359706f2543Smrg cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD; 360706f2543Smrg rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata); 361706f2543Smrg if (rc != Success) 362706f2543Smrg rec->status = rc; 363706f2543Smrg} 364706f2543Smrg 365706f2543Smrgstatic void 366706f2543SmrgSELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) 367706f2543Smrg{ 368706f2543Smrg XaceSendAccessRec *rec = calldata; 369706f2543Smrg SELinuxSubjectRec *subj; 370706f2543Smrg SELinuxObjectRec *obj, ev_sid; 371706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; 372706f2543Smrg security_class_t class; 373706f2543Smrg int rc, i, type; 374706f2543Smrg 375706f2543Smrg if (rec->dev) 376706f2543Smrg subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); 377706f2543Smrg else 378706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 379706f2543Smrg 380706f2543Smrg obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); 381706f2543Smrg 382706f2543Smrg /* Check send permission on window */ 383706f2543Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, 384706f2543Smrg &auditdata); 385706f2543Smrg if (rc != Success) 386706f2543Smrg goto err; 387706f2543Smrg 388706f2543Smrg /* Check send permission on specific event types */ 389706f2543Smrg for (i = 0; i < rec->count; i++) { 390706f2543Smrg type = rec->events[i].u.u.type; 391706f2543Smrg class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; 392706f2543Smrg 393706f2543Smrg rc = SELinuxEventToSID(type, obj->sid, &ev_sid); 394706f2543Smrg if (rc != Success) 395706f2543Smrg goto err; 396706f2543Smrg 397706f2543Smrg auditdata.event = type; 398706f2543Smrg rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); 399706f2543Smrg if (rc != Success) 400706f2543Smrg goto err; 401706f2543Smrg } 402706f2543Smrg return; 403706f2543Smrgerr: 404706f2543Smrg rec->status = rc; 405706f2543Smrg} 406706f2543Smrg 407706f2543Smrgstatic void 408706f2543SmrgSELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) 409706f2543Smrg{ 410706f2543Smrg XaceReceiveAccessRec *rec = calldata; 411706f2543Smrg SELinuxSubjectRec *subj; 412706f2543Smrg SELinuxObjectRec *obj, ev_sid; 413706f2543Smrg SELinuxAuditRec auditdata = { .client = NULL }; 414706f2543Smrg security_class_t class; 415706f2543Smrg int rc, i, type; 416706f2543Smrg 417706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 418706f2543Smrg obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); 419706f2543Smrg 420706f2543Smrg /* Check receive permission on window */ 421706f2543Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, 422706f2543Smrg &auditdata); 423706f2543Smrg if (rc != Success) 424706f2543Smrg goto err; 425706f2543Smrg 426706f2543Smrg /* Check receive permission on specific event types */ 427706f2543Smrg for (i = 0; i < rec->count; i++) { 428706f2543Smrg type = rec->events[i].u.u.type; 429706f2543Smrg class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; 430706f2543Smrg 431706f2543Smrg rc = SELinuxEventToSID(type, obj->sid, &ev_sid); 432706f2543Smrg if (rc != Success) 433706f2543Smrg goto err; 434706f2543Smrg 435706f2543Smrg auditdata.event = type; 436706f2543Smrg rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); 437706f2543Smrg if (rc != Success) 438706f2543Smrg goto err; 439706f2543Smrg } 440706f2543Smrg return; 441706f2543Smrgerr: 442706f2543Smrg rec->status = rc; 443706f2543Smrg} 444706f2543Smrg 445706f2543Smrgstatic void 446706f2543SmrgSELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) 447706f2543Smrg{ 448706f2543Smrg XaceExtAccessRec *rec = calldata; 449706f2543Smrg SELinuxSubjectRec *subj, *serv; 450706f2543Smrg SELinuxObjectRec *obj; 451706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 452706f2543Smrg int rc; 453706f2543Smrg 454706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 455706f2543Smrg obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); 456706f2543Smrg 457706f2543Smrg /* If this is a new object that needs labeling, do it now */ 458706f2543Smrg /* XXX there should be a separate callback for this */ 459706f2543Smrg if (obj->sid == NULL) { 460706f2543Smrg security_id_t sid; 461706f2543Smrg 462706f2543Smrg serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); 463706f2543Smrg rc = SELinuxExtensionToSID(rec->ext->name, &sid); 464706f2543Smrg if (rc != Success) { 465706f2543Smrg rec->status = rc; 466706f2543Smrg return; 467706f2543Smrg } 468706f2543Smrg 469706f2543Smrg /* Perform a transition to obtain the final SID */ 470706f2543Smrg if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, 471706f2543Smrg &obj->sid) < 0) { 472706f2543Smrg ErrorF("SELinux: a SID transition call failed!\n"); 473706f2543Smrg rec->status = BadValue; 474706f2543Smrg return; 475706f2543Smrg } 476706f2543Smrg } 477706f2543Smrg 478706f2543Smrg /* Perform the security check */ 479706f2543Smrg auditdata.extension = rec->ext->name; 480706f2543Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, 481706f2543Smrg &auditdata); 482706f2543Smrg if (rc != Success) 483706f2543Smrg rec->status = rc; 484706f2543Smrg} 485706f2543Smrg 486706f2543Smrgstatic void 487706f2543SmrgSELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) 488706f2543Smrg{ 489706f2543Smrg XaceSelectionAccessRec *rec = calldata; 490706f2543Smrg SELinuxSubjectRec *subj; 491706f2543Smrg SELinuxObjectRec *obj, *data; 492706f2543Smrg Selection *pSel = *rec->ppSel; 493706f2543Smrg Atom name = pSel->selection; 494706f2543Smrg Mask access_mode = rec->access_mode; 495706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; 496706f2543Smrg security_id_t tsid; 497706f2543Smrg int rc; 498706f2543Smrg 499706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 500706f2543Smrg obj = dixLookupPrivate(&pSel->devPrivates, objectKey); 501706f2543Smrg 502706f2543Smrg /* If this is a new object that needs labeling, do it now */ 503706f2543Smrg if (access_mode & DixCreateAccess) { 504706f2543Smrg rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); 505706f2543Smrg if (rc != Success) 506706f2543Smrg obj->sid = unlabeled_sid; 507706f2543Smrg access_mode = DixSetAttrAccess; 508706f2543Smrg } 509706f2543Smrg /* If this is a polyinstantiated object, find the right instance */ 510706f2543Smrg else if (obj->poly) { 511706f2543Smrg rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); 512706f2543Smrg if (rc != Success) { 513706f2543Smrg rec->status = rc; 514706f2543Smrg return; 515706f2543Smrg } 516706f2543Smrg while (pSel->selection != name || obj->sid != tsid) { 517706f2543Smrg if ((pSel = pSel->next) == NULL) 518706f2543Smrg break; 519706f2543Smrg obj = dixLookupPrivate(&pSel->devPrivates, objectKey); 520706f2543Smrg } 521706f2543Smrg 522706f2543Smrg if (pSel) 523706f2543Smrg *rec->ppSel = pSel; 524706f2543Smrg else { 525706f2543Smrg rec->status = BadMatch; 526706f2543Smrg return; 527706f2543Smrg } 528706f2543Smrg } 529706f2543Smrg 530706f2543Smrg /* Perform the security check */ 531706f2543Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, 532706f2543Smrg &auditdata); 533706f2543Smrg if (rc != Success) 534706f2543Smrg rec->status = rc; 535706f2543Smrg 536706f2543Smrg /* Label the content (advisory only) */ 537706f2543Smrg if (access_mode & DixSetAttrAccess) { 538706f2543Smrg data = dixLookupPrivate(&pSel->devPrivates, dataKey); 539706f2543Smrg if (subj->sel_create_sid) 540706f2543Smrg data->sid = subj->sel_create_sid; 541706f2543Smrg else 542706f2543Smrg data->sid = obj->sid; 543706f2543Smrg } 544706f2543Smrg} 545706f2543Smrg 546706f2543Smrgstatic void 547706f2543SmrgSELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) 548706f2543Smrg{ 549706f2543Smrg XacePropertyAccessRec *rec = calldata; 550706f2543Smrg SELinuxSubjectRec *subj; 551706f2543Smrg SELinuxObjectRec *obj, *data; 552706f2543Smrg PropertyPtr pProp = *rec->ppProp; 553706f2543Smrg Atom name = pProp->propertyName; 554706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; 555706f2543Smrg security_id_t tsid; 556706f2543Smrg int rc; 557706f2543Smrg 558706f2543Smrg /* Don't care about the new content check */ 559706f2543Smrg if (rec->access_mode & DixPostAccess) 560706f2543Smrg return; 561706f2543Smrg 562706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 563706f2543Smrg obj = dixLookupPrivate(&pProp->devPrivates, objectKey); 564706f2543Smrg 565706f2543Smrg /* If this is a new object that needs labeling, do it now */ 566706f2543Smrg if (rec->access_mode & DixCreateAccess) { 567706f2543Smrg rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); 568706f2543Smrg if (rc != Success) { 569706f2543Smrg rec->status = rc; 570706f2543Smrg return; 571706f2543Smrg } 572706f2543Smrg } 573706f2543Smrg /* If this is a polyinstantiated object, find the right instance */ 574706f2543Smrg else if (obj->poly) { 575706f2543Smrg rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); 576706f2543Smrg if (rc != Success) { 577706f2543Smrg rec->status = rc; 578706f2543Smrg return; 579706f2543Smrg } 580706f2543Smrg while (pProp->propertyName != name || obj->sid != tsid) { 581706f2543Smrg if ((pProp = pProp->next) == NULL) 582706f2543Smrg break; 583706f2543Smrg obj = dixLookupPrivate(&pProp->devPrivates, objectKey); 584706f2543Smrg } 585706f2543Smrg 586706f2543Smrg if (pProp) 587706f2543Smrg *rec->ppProp = pProp; 588706f2543Smrg else { 589706f2543Smrg rec->status = BadMatch; 590706f2543Smrg return; 591706f2543Smrg } 592706f2543Smrg } 593706f2543Smrg 594706f2543Smrg /* Perform the security check */ 595706f2543Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, 596706f2543Smrg &auditdata); 597706f2543Smrg if (rc != Success) 598706f2543Smrg rec->status = rc; 599706f2543Smrg 600706f2543Smrg /* Label the content (advisory only) */ 601706f2543Smrg if (rec->access_mode & DixWriteAccess) { 602706f2543Smrg data = dixLookupPrivate(&pProp->devPrivates, dataKey); 603706f2543Smrg if (subj->prp_create_sid) 604706f2543Smrg data->sid = subj->prp_create_sid; 605706f2543Smrg else 606706f2543Smrg data->sid = obj->sid; 607706f2543Smrg } 608706f2543Smrg} 609706f2543Smrg 610706f2543Smrgstatic void 611706f2543SmrgSELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) 612706f2543Smrg{ 613706f2543Smrg XaceResourceAccessRec *rec = calldata; 614706f2543Smrg SELinuxSubjectRec *subj; 615706f2543Smrg SELinuxObjectRec *obj; 616706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 617706f2543Smrg Mask access_mode = rec->access_mode; 618706f2543Smrg PrivateRec **privatePtr; 619706f2543Smrg security_class_t class; 620706f2543Smrg int rc, offset; 621706f2543Smrg 622706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 623706f2543Smrg 624706f2543Smrg /* Determine if the resource object has a devPrivates field */ 625706f2543Smrg offset = dixLookupPrivateOffset(rec->rtype); 626706f2543Smrg if (offset < 0) { 627706f2543Smrg /* No: use the SID of the owning client */ 628706f2543Smrg class = SECCLASS_X_RESOURCE; 629706f2543Smrg privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates; 630706f2543Smrg obj = dixLookupPrivate(privatePtr, objectKey); 631706f2543Smrg } else { 632706f2543Smrg /* Yes: use the SID from the resource object itself */ 633706f2543Smrg class = SELinuxTypeToClass(rec->rtype); 634706f2543Smrg privatePtr = DEVPRIV_AT(rec->res, offset); 635706f2543Smrg obj = dixLookupPrivate(privatePtr, objectKey); 636706f2543Smrg } 637706f2543Smrg 638706f2543Smrg /* If this is a new object that needs labeling, do it now */ 639706f2543Smrg if (access_mode & DixCreateAccess && offset >= 0) { 640706f2543Smrg rc = SELinuxLabelResource(rec, subj, obj, class); 641706f2543Smrg if (rc != Success) { 642706f2543Smrg rec->status = rc; 643706f2543Smrg return; 644706f2543Smrg } 645706f2543Smrg } 646706f2543Smrg 647706f2543Smrg /* Collapse generic resource permissions down to read/write */ 648706f2543Smrg if (class == SECCLASS_X_RESOURCE) { 649706f2543Smrg access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ 650706f2543Smrg access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ 651706f2543Smrg } 652706f2543Smrg 653706f2543Smrg /* Perform the security check */ 654706f2543Smrg auditdata.restype = rec->rtype; 655706f2543Smrg auditdata.id = rec->id; 656706f2543Smrg rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); 657706f2543Smrg if (rc != Success) 658706f2543Smrg rec->status = rc; 659706f2543Smrg 660706f2543Smrg /* Perform the background none check on windows */ 661706f2543Smrg if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { 662706f2543Smrg rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); 663706f2543Smrg if (rc != Success) 664706f2543Smrg ((WindowPtr)rec->res)->forcedBG = TRUE; 665706f2543Smrg } 666706f2543Smrg} 667706f2543Smrg 668706f2543Smrgstatic void 669706f2543SmrgSELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) 670706f2543Smrg{ 671706f2543Smrg XaceScreenAccessRec *rec = calldata; 672706f2543Smrg SELinuxSubjectRec *subj; 673706f2543Smrg SELinuxObjectRec *obj; 674706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 675706f2543Smrg Mask access_mode = rec->access_mode; 676706f2543Smrg int rc; 677706f2543Smrg 678706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 679706f2543Smrg obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); 680706f2543Smrg 681706f2543Smrg /* If this is a new object that needs labeling, do it now */ 682706f2543Smrg if (access_mode & DixCreateAccess) { 683706f2543Smrg /* Perform a transition to obtain the final SID */ 684706f2543Smrg if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, 685706f2543Smrg &obj->sid) < 0) { 686706f2543Smrg ErrorF("SELinux: a compute_create call failed!\n"); 687706f2543Smrg rec->status = BadValue; 688706f2543Smrg return; 689706f2543Smrg } 690706f2543Smrg } 691706f2543Smrg 692706f2543Smrg if (is_saver) 693706f2543Smrg access_mode <<= 2; 694706f2543Smrg 695706f2543Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); 696706f2543Smrg if (rc != Success) 697706f2543Smrg rec->status = rc; 698706f2543Smrg} 699706f2543Smrg 700706f2543Smrgstatic void 701706f2543SmrgSELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) 702706f2543Smrg{ 703706f2543Smrg XaceClientAccessRec *rec = calldata; 704706f2543Smrg SELinuxSubjectRec *subj; 705706f2543Smrg SELinuxObjectRec *obj; 706706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 707706f2543Smrg int rc; 708706f2543Smrg 709706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 710706f2543Smrg obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); 711706f2543Smrg 712706f2543Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, 713706f2543Smrg &auditdata); 714706f2543Smrg if (rc != Success) 715706f2543Smrg rec->status = rc; 716706f2543Smrg} 717706f2543Smrg 718706f2543Smrgstatic void 719706f2543SmrgSELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) 720706f2543Smrg{ 721706f2543Smrg XaceServerAccessRec *rec = calldata; 722706f2543Smrg SELinuxSubjectRec *subj; 723706f2543Smrg SELinuxObjectRec *obj; 724706f2543Smrg SELinuxAuditRec auditdata = { .client = rec->client }; 725706f2543Smrg int rc; 726706f2543Smrg 727706f2543Smrg subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); 728706f2543Smrg obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); 729706f2543Smrg 730706f2543Smrg rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, 731706f2543Smrg &auditdata); 732706f2543Smrg if (rc != Success) 733706f2543Smrg rec->status = rc; 734706f2543Smrg} 735706f2543Smrg 736706f2543Smrg 737706f2543Smrg/* 738706f2543Smrg * DIX Callbacks 739706f2543Smrg */ 740706f2543Smrg 741706f2543Smrgstatic void 742706f2543SmrgSELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) 743706f2543Smrg{ 744706f2543Smrg NewClientInfoRec *pci = calldata; 745706f2543Smrg 746706f2543Smrg switch (pci->client->clientState) { 747706f2543Smrg case ClientStateInitial: 748706f2543Smrg SELinuxLabelClient(pci->client); 749706f2543Smrg break; 750706f2543Smrg 751706f2543Smrg default: 752706f2543Smrg break; 753706f2543Smrg } 754706f2543Smrg} 755706f2543Smrg 756706f2543Smrgstatic void 757706f2543SmrgSELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) 758706f2543Smrg{ 759706f2543Smrg ResourceStateInfoRec *rec = calldata; 760706f2543Smrg SELinuxSubjectRec *subj; 761706f2543Smrg SELinuxObjectRec *obj; 762706f2543Smrg WindowPtr pWin; 763706f2543Smrg 764706f2543Smrg if (rec->type != RT_WINDOW) 765706f2543Smrg return; 766706f2543Smrg if (rec->state != ResourceStateAdding) 767706f2543Smrg return; 768706f2543Smrg 769706f2543Smrg pWin = (WindowPtr)rec->value; 770706f2543Smrg subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); 771706f2543Smrg 772706f2543Smrg if (subj->sid) { 773706f2543Smrg security_context_t ctx; 774706f2543Smrg int rc = avc_sid_to_context_raw(subj->sid, &ctx); 775706f2543Smrg if (rc < 0) 776706f2543Smrg FatalError("SELinux: Failed to get security context!\n"); 777706f2543Smrg rc = dixChangeWindowProperty(serverClient, 778706f2543Smrg pWin, atom_client_ctx, XA_STRING, 8, 779706f2543Smrg PropModeReplace, strlen(ctx), ctx, FALSE); 780706f2543Smrg if (rc != Success) 781706f2543Smrg FatalError("SELinux: Failed to set label property on window!\n"); 782706f2543Smrg freecon(ctx); 783706f2543Smrg } else 784706f2543Smrg FatalError("SELinux: Unexpected unlabeled client found\n"); 785706f2543Smrg 786706f2543Smrg obj = dixLookupPrivate(&pWin->devPrivates, objectKey); 787706f2543Smrg 788706f2543Smrg if (obj->sid) { 789706f2543Smrg security_context_t ctx; 790706f2543Smrg int rc = avc_sid_to_context_raw(obj->sid, &ctx); 791706f2543Smrg if (rc < 0) 792706f2543Smrg FatalError("SELinux: Failed to get security context!\n"); 793706f2543Smrg rc = dixChangeWindowProperty(serverClient, 794706f2543Smrg pWin, atom_ctx, XA_STRING, 8, 795706f2543Smrg PropModeReplace, strlen(ctx), ctx, FALSE); 796706f2543Smrg if (rc != Success) 797706f2543Smrg FatalError("SELinux: Failed to set label property on window!\n"); 798706f2543Smrg freecon(ctx); 799706f2543Smrg } else 800706f2543Smrg FatalError("SELinux: Unexpected unlabeled window found\n"); 801706f2543Smrg} 802706f2543Smrg 803706f2543Smrg 804706f2543Smrgstatic int netlink_fd; 805706f2543Smrg 806706f2543Smrgstatic void 807706f2543SmrgSELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) 808706f2543Smrg{ 809706f2543Smrg} 810706f2543Smrg 811706f2543Smrgstatic void 812706f2543SmrgSELinuxWakeupHandler(void *data, int err, void *read_mask) 813706f2543Smrg{ 814706f2543Smrg if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) 815706f2543Smrg avc_netlink_check_nb(); 816706f2543Smrg} 817706f2543Smrg 818706f2543Smrgvoid 819706f2543SmrgSELinuxFlaskReset(void) 820706f2543Smrg{ 821706f2543Smrg /* Unregister callbacks */ 822706f2543Smrg DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); 823706f2543Smrg DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); 824706f2543Smrg 825706f2543Smrg XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); 826706f2543Smrg XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); 827706f2543Smrg XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); 828706f2543Smrg XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); 829706f2543Smrg XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); 830706f2543Smrg XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); 831706f2543Smrg XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); 832706f2543Smrg XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); 833706f2543Smrg XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); 834706f2543Smrg XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); 835706f2543Smrg XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); 836706f2543Smrg XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); 837706f2543Smrg 838706f2543Smrg /* Tear down SELinux stuff */ 839706f2543Smrg audit_close(audit_fd); 840706f2543Smrg avc_netlink_release_fd(); 841706f2543Smrg RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, 842706f2543Smrg NULL); 843706f2543Smrg RemoveGeneralSocket(netlink_fd); 844706f2543Smrg 845706f2543Smrg avc_destroy(); 846706f2543Smrg} 847706f2543Smrg 848706f2543Smrgvoid 849706f2543SmrgSELinuxFlaskInit(void) 850706f2543Smrg{ 851706f2543Smrg struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; 852706f2543Smrg security_context_t ctx; 853706f2543Smrg int ret = TRUE; 854706f2543Smrg 855706f2543Smrg switch(selinuxEnforcingState) { 856706f2543Smrg case SELINUX_MODE_ENFORCING: 857706f2543Smrg LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); 858706f2543Smrg avc_option.value = (char *)1; 859706f2543Smrg break; 860706f2543Smrg case SELINUX_MODE_PERMISSIVE: 861706f2543Smrg LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); 862706f2543Smrg avc_option.value = (char *)0; 863706f2543Smrg break; 864706f2543Smrg default: 865706f2543Smrg avc_option.type = AVC_OPT_UNUSED; 866706f2543Smrg break; 867706f2543Smrg } 868706f2543Smrg 869706f2543Smrg /* Set up SELinux stuff */ 870706f2543Smrg selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); 871706f2543Smrg selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); 872706f2543Smrg 873706f2543Smrg if (selinux_set_mapping(map) < 0) { 874706f2543Smrg if (errno == EINVAL) { 875706f2543Smrg ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n"); 876706f2543Smrg return; 877706f2543Smrg } 878706f2543Smrg FatalError("SELinux: Failed to set up security class mapping\n"); 879706f2543Smrg } 880706f2543Smrg 881706f2543Smrg if (avc_open(&avc_option, 1) < 0) 882706f2543Smrg FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); 883706f2543Smrg 884706f2543Smrg if (security_get_initial_context_raw("unlabeled", &ctx) < 0) 885706f2543Smrg FatalError("SELinux: Failed to look up unlabeled context\n"); 886706f2543Smrg if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) 887706f2543Smrg FatalError("SELinux: a context_to_SID call failed!\n"); 888706f2543Smrg freecon(ctx); 889706f2543Smrg 890706f2543Smrg /* Prepare for auditing */ 891706f2543Smrg audit_fd = audit_open(); 892706f2543Smrg if (audit_fd < 0) 893706f2543Smrg FatalError("SELinux: Failed to open the system audit log\n"); 894706f2543Smrg 895706f2543Smrg /* Allocate private storage */ 896706f2543Smrg if (!dixRegisterPrivateKey(subjectKey, PRIVATE_XSELINUX, sizeof(SELinuxSubjectRec)) || 897706f2543Smrg !dixRegisterPrivateKey(objectKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)) || 898706f2543Smrg !dixRegisterPrivateKey(dataKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec))) 899706f2543Smrg FatalError("SELinux: Failed to allocate private storage.\n"); 900706f2543Smrg 901706f2543Smrg /* Create atoms for doing window labeling */ 902706f2543Smrg atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); 903706f2543Smrg if (atom_ctx == BAD_RESOURCE) 904706f2543Smrg FatalError("SELinux: Failed to create atom\n"); 905706f2543Smrg atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); 906706f2543Smrg if (atom_client_ctx == BAD_RESOURCE) 907706f2543Smrg FatalError("SELinux: Failed to create atom\n"); 908706f2543Smrg 909706f2543Smrg netlink_fd = avc_netlink_acquire_fd(); 910706f2543Smrg AddGeneralSocket(netlink_fd); 911706f2543Smrg RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, 912706f2543Smrg NULL); 913706f2543Smrg 914706f2543Smrg /* Register callbacks */ 915706f2543Smrg ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); 916706f2543Smrg ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); 917706f2543Smrg 918706f2543Smrg ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); 919706f2543Smrg ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); 920706f2543Smrg ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); 921706f2543Smrg ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); 922706f2543Smrg ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); 923706f2543Smrg ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); 924706f2543Smrg ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); 925706f2543Smrg ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); 926706f2543Smrg ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); 927706f2543Smrg ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); 928706f2543Smrg ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); 929706f2543Smrg ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); 930706f2543Smrg if (!ret) 931706f2543Smrg FatalError("SELinux: Failed to register one or more callbacks\n"); 932706f2543Smrg 933706f2543Smrg /* Label objects that were created before we could register ourself */ 934706f2543Smrg SELinuxLabelInitial(); 935706f2543Smrg} 936