1 /* 2 * AppArmor security module 3 * 4 * This file contains basic common functions used in AppArmor 5 * 6 * Copyright (C) 1998-2008 Novell/SUSE 7 * Copyright 2009-2010 Canonical Ltd. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation, version 2 of the 12 * License. 13 */ 14 15 #include <linux/ctype.h> 16 #include <linux/mm.h> 17 #include <linux/slab.h> 18 #include <linux/string.h> 19 #include <linux/vmalloc.h> 20 21 #include "include/audit.h" 22 #include "include/apparmor.h" 23 #include "include/lib.h" 24 #include "include/perms.h" 25 #include "include/policy.h" 26 27 struct aa_perms nullperms; 28 struct aa_perms allperms = { .allow = ALL_PERMS_MASK, 29 .quiet = ALL_PERMS_MASK, 30 .hide = ALL_PERMS_MASK }; 31 32 /** 33 * aa_split_fqname - split a fqname into a profile and namespace name 34 * @fqname: a full qualified name in namespace profile format (NOT NULL) 35 * @ns_name: pointer to portion of the string containing the ns name (NOT NULL) 36 * 37 * Returns: profile name or NULL if one is not specified 38 * 39 * Split a namespace name from a profile name (see policy.c for naming 40 * description). If a portion of the name is missing it returns NULL for 41 * that portion. 42 * 43 * NOTE: may modify the @fqname string. The pointers returned point 44 * into the @fqname string. 45 */ 46 char *aa_split_fqname(char *fqname, char **ns_name) 47 { 48 char *name = strim(fqname); 49 50 *ns_name = NULL; 51 if (name[0] == ':') { 52 char *split = strchr(&name[1], ':'); 53 *ns_name = skip_spaces(&name[1]); 54 if (split) { 55 /* overwrite ':' with \0 */ 56 *split++ = 0; 57 if (strncmp(split, "//", 2) == 0) 58 split += 2; 59 name = skip_spaces(split); 60 } else 61 /* a ns name without a following profile is allowed */ 62 name = NULL; 63 } 64 if (name && *name == 0) 65 name = NULL; 66 67 return name; 68 } 69 70 /** 71 * skipn_spaces - Removes leading whitespace from @str. 72 * @str: The string to be stripped. 73 * 74 * Returns a pointer to the first non-whitespace character in @str. 75 * if all whitespace will return NULL 76 */ 77 78 const char *skipn_spaces(const char *str, size_t n) 79 { 80 for (; n && isspace(*str); --n) 81 ++str; 82 if (n) 83 return (char *)str; 84 return NULL; 85 } 86 87 const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, 88 size_t *ns_len) 89 { 90 const char *end = fqname + n; 91 const char *name = skipn_spaces(fqname, n); 92 93 if (!name) 94 return NULL; 95 *ns_name = NULL; 96 *ns_len = 0; 97 if (name[0] == ':') { 98 char *split = strnchr(&name[1], end - &name[1], ':'); 99 *ns_name = skipn_spaces(&name[1], end - &name[1]); 100 if (!*ns_name) 101 return NULL; 102 if (split) { 103 *ns_len = split - *ns_name; 104 if (*ns_len == 0) 105 *ns_name = NULL; 106 split++; 107 if (end - split > 1 && strncmp(split, "//", 2) == 0) 108 split += 2; 109 name = skipn_spaces(split, end - split); 110 } else { 111 /* a ns name without a following profile is allowed */ 112 name = NULL; 113 *ns_len = end - *ns_name; 114 } 115 } 116 if (name && *name == 0) 117 name = NULL; 118 119 return name; 120 } 121 122 /** 123 * aa_info_message - log a none profile related status message 124 * @str: message to log 125 */ 126 void aa_info_message(const char *str) 127 { 128 if (audit_enabled) { 129 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL); 130 131 aad(&sa)->info = str; 132 aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); 133 } 134 printk(KERN_INFO "AppArmor: %s\n", str); 135 } 136 137 __counted char *aa_str_alloc(int size, gfp_t gfp) 138 { 139 struct counted_str *str; 140 141 str = kmalloc(sizeof(struct counted_str) + size, gfp); 142 if (!str) 143 return NULL; 144 145 kref_init(&str->count); 146 return str->name; 147 } 148 149 void aa_str_kref(struct kref *kref) 150 { 151 kfree(container_of(kref, struct counted_str, count)); 152 } 153 154 155 const char aa_file_perm_chrs[] = "xwracd km l "; 156 const char *aa_file_perm_names[] = { 157 "exec", 158 "write", 159 "read", 160 "append", 161 162 "create", 163 "delete", 164 "open", 165 "rename", 166 167 "setattr", 168 "getattr", 169 "setcred", 170 "getcred", 171 172 "chmod", 173 "chown", 174 "chgrp", 175 "lock", 176 177 "mmap", 178 "mprot", 179 "link", 180 "snapshot", 181 182 "unknown", 183 "unknown", 184 "unknown", 185 "unknown", 186 187 "unknown", 188 "unknown", 189 "unknown", 190 "unknown", 191 192 "stack", 193 "change_onexec", 194 "change_profile", 195 "change_hat", 196 }; 197 198 /** 199 * aa_perm_mask_to_str - convert a perm mask to its short string 200 * @str: character buffer to store string in (at least 10 characters) 201 * @mask: permission mask to convert 202 */ 203 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask) 204 { 205 unsigned int i, perm = 1; 206 207 for (i = 0; i < 32; perm <<= 1, i++) { 208 if (mask & perm) 209 *str++ = chrs[i]; 210 } 211 *str = '\0'; 212 } 213 214 void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names, 215 u32 mask) 216 { 217 const char *fmt = "%s"; 218 unsigned int i, perm = 1; 219 bool prev = false; 220 221 for (i = 0; i < 32; perm <<= 1, i++) { 222 if (mask & perm) { 223 audit_log_format(ab, fmt, names[i]); 224 if (!prev) { 225 prev = true; 226 fmt = " %s"; 227 } 228 } 229 } 230 } 231 232 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 233 u32 chrsmask, const char * const *names, u32 namesmask) 234 { 235 char str[33]; 236 237 audit_log_format(ab, "\""); 238 if ((mask & chrsmask) && chrs) { 239 aa_perm_mask_to_str(str, chrs, mask & chrsmask); 240 mask &= ~chrsmask; 241 audit_log_format(ab, "%s", str); 242 if (mask & namesmask) 243 audit_log_format(ab, " "); 244 } 245 if ((mask & namesmask) && names) 246 aa_audit_perm_names(ab, names, mask & namesmask); 247 audit_log_format(ab, "\""); 248 } 249 250 /** 251 * aa_audit_perms_cb - generic callback fn for auditing perms 252 * @ab: audit buffer (NOT NULL) 253 * @va: audit struct to audit values of (NOT NULL) 254 */ 255 static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) 256 { 257 struct common_audit_data *sa = va; 258 259 if (aad(sa)->request) { 260 audit_log_format(ab, " requested_mask="); 261 aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, 262 PERMS_CHRS_MASK, aa_file_perm_names, 263 PERMS_NAMES_MASK); 264 } 265 if (aad(sa)->denied) { 266 audit_log_format(ab, "denied_mask="); 267 aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, 268 PERMS_CHRS_MASK, aa_file_perm_names, 269 PERMS_NAMES_MASK); 270 } 271 audit_log_format(ab, " peer="); 272 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 273 FLAGS_NONE, GFP_ATOMIC); 274 } 275 276 /** 277 * aa_apply_modes_to_perms - apply namespace and profile flags to perms 278 * @profile: that perms where computed from 279 * @perms: perms to apply mode modifiers to 280 * 281 * TODO: split into profile and ns based flags for when accumulating perms 282 */ 283 void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms) 284 { 285 switch (AUDIT_MODE(profile)) { 286 case AUDIT_ALL: 287 perms->audit = ALL_PERMS_MASK; 288 /* fall through */ 289 case AUDIT_NOQUIET: 290 perms->quiet = 0; 291 break; 292 case AUDIT_QUIET: 293 perms->audit = 0; 294 /* fall through */ 295 case AUDIT_QUIET_DENIED: 296 perms->quiet = ALL_PERMS_MASK; 297 break; 298 } 299 300 if (KILL_MODE(profile)) 301 perms->kill = ALL_PERMS_MASK; 302 else if (COMPLAIN_MODE(profile)) 303 perms->complain = ALL_PERMS_MASK; 304 /* 305 * TODO: 306 * else if (PROMPT_MODE(profile)) 307 * perms->prompt = ALL_PERMS_MASK; 308 */ 309 } 310 311 static u32 map_other(u32 x) 312 { 313 return ((x & 0x3) << 8) | /* SETATTR/GETATTR */ 314 ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */ 315 ((x & 0x60) << 19); /* SETOPT/GETOPT */ 316 } 317 318 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, 319 struct aa_perms *perms) 320 { 321 *perms = (struct aa_perms) { 322 .allow = dfa_user_allow(dfa, state), 323 .audit = dfa_user_audit(dfa, state), 324 .quiet = dfa_user_quiet(dfa, state), 325 }; 326 327 /* for v5 perm mapping in the policydb, the other set is used 328 * to extend the general perm set 329 */ 330 perms->allow |= map_other(dfa_other_allow(dfa, state)); 331 perms->audit |= map_other(dfa_other_audit(dfa, state)); 332 perms->quiet |= map_other(dfa_other_quiet(dfa, state)); 333 // perms->xindex = dfa_user_xindex(dfa, state); 334 } 335 336 /** 337 * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms 338 * @accum - perms struct to accumulate into 339 * @addend - perms struct to add to @accum 340 */ 341 void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend) 342 { 343 accum->deny |= addend->deny; 344 accum->allow &= addend->allow & ~addend->deny; 345 accum->audit |= addend->audit & addend->allow; 346 accum->quiet &= addend->quiet & ~addend->allow; 347 accum->kill |= addend->kill & ~addend->allow; 348 accum->stop |= addend->stop & ~addend->allow; 349 accum->complain |= addend->complain & ~addend->allow & ~addend->deny; 350 accum->cond |= addend->cond & ~addend->allow & ~addend->deny; 351 accum->hide &= addend->hide & ~addend->allow; 352 accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny; 353 } 354 355 /** 356 * aa_perms_accum - accumulate perms, masking off overlapping perms 357 * @accum - perms struct to accumulate into 358 * @addend - perms struct to add to @accum 359 */ 360 void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend) 361 { 362 accum->deny |= addend->deny; 363 accum->allow &= addend->allow & ~accum->deny; 364 accum->audit |= addend->audit & accum->allow; 365 accum->quiet &= addend->quiet & ~accum->allow; 366 accum->kill |= addend->kill & ~accum->allow; 367 accum->stop |= addend->stop & ~accum->allow; 368 accum->complain |= addend->complain & ~accum->allow & ~accum->deny; 369 accum->cond |= addend->cond & ~accum->allow & ~accum->deny; 370 accum->hide &= addend->hide & ~accum->allow; 371 accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny; 372 } 373 374 void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, 375 int type, u32 request, struct aa_perms *perms) 376 { 377 /* TODO: doesn't yet handle extended types */ 378 unsigned int state; 379 380 state = aa_dfa_next(profile->policy.dfa, 381 profile->policy.start[AA_CLASS_LABEL], 382 type); 383 aa_label_match(profile, label, state, false, request, perms); 384 } 385 386 387 /* currently unused */ 388 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, 389 u32 request, int type, u32 *deny, 390 struct common_audit_data *sa) 391 { 392 struct aa_perms perms; 393 394 aad(sa)->label = &profile->label; 395 aad(sa)->peer = &target->label; 396 aad(sa)->request = request; 397 398 aa_profile_match_label(profile, &target->label, type, request, &perms); 399 aa_apply_modes_to_perms(profile, &perms); 400 *deny |= request & perms.deny; 401 return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb); 402 } 403 404 /** 405 * aa_check_perms - do audit mode selection based on perms set 406 * @profile: profile being checked 407 * @perms: perms computed for the request 408 * @request: requested perms 409 * @deny: Returns: explicit deny set 410 * @sa: initialized audit structure (MAY BE NULL if not auditing) 411 * @cb: callback fn for tpye specific fields (MAY BE NULL) 412 * 413 * Returns: 0 if permission else error code 414 * 415 * Note: profile audit modes need to be set before calling by setting the 416 * perm masks appropriately. 417 * 418 * If not auditing then complain mode is not enabled and the 419 * error code will indicate whether there was an explicit deny 420 * with a positive value. 421 */ 422 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, 423 u32 request, struct common_audit_data *sa, 424 void (*cb)(struct audit_buffer *, void *)) 425 { 426 int type, error; 427 u32 denied = request & (~perms->allow | perms->deny); 428 429 if (likely(!denied)) { 430 /* mask off perms that are not being force audited */ 431 request &= perms->audit; 432 if (!request || !sa) 433 return 0; 434 435 type = AUDIT_APPARMOR_AUDIT; 436 error = 0; 437 } else { 438 error = -EACCES; 439 440 if (denied & perms->kill) 441 type = AUDIT_APPARMOR_KILL; 442 else if (denied == (denied & perms->complain)) 443 type = AUDIT_APPARMOR_ALLOWED; 444 else 445 type = AUDIT_APPARMOR_DENIED; 446 447 if (denied == (denied & perms->hide)) 448 error = -ENOENT; 449 450 denied &= ~perms->quiet; 451 if (!sa || !denied) 452 return error; 453 } 454 455 if (sa) { 456 aad(sa)->label = &profile->label; 457 aad(sa)->request = request; 458 aad(sa)->denied = denied; 459 aad(sa)->error = error; 460 aa_audit_msg(type, sa, cb); 461 } 462 463 if (type == AUDIT_APPARMOR_ALLOWED) 464 error = 0; 465 466 return error; 467 } 468 469 470 /** 471 * aa_policy_init - initialize a policy structure 472 * @policy: policy to initialize (NOT NULL) 473 * @prefix: prefix name if any is required. (MAYBE NULL) 474 * @name: name of the policy, init will make a copy of it (NOT NULL) 475 * @gfp: allocation mode 476 * 477 * Note: this fn creates a copy of strings passed in 478 * 479 * Returns: true if policy init successful 480 */ 481 bool aa_policy_init(struct aa_policy *policy, const char *prefix, 482 const char *name, gfp_t gfp) 483 { 484 char *hname; 485 486 /* freed by policy_free */ 487 if (prefix) { 488 hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp); 489 if (hname) 490 sprintf(hname, "%s//%s", prefix, name); 491 } else { 492 hname = aa_str_alloc(strlen(name) + 1, gfp); 493 if (hname) 494 strcpy(hname, name); 495 } 496 if (!hname) 497 return false; 498 policy->hname = hname; 499 /* base.name is a substring of fqname */ 500 policy->name = basename(policy->hname); 501 INIT_LIST_HEAD(&policy->list); 502 INIT_LIST_HEAD(&policy->profiles); 503 504 return true; 505 } 506 507 /** 508 * aa_policy_destroy - free the elements referenced by @policy 509 * @policy: policy that is to have its elements freed (NOT NULL) 510 */ 511 void aa_policy_destroy(struct aa_policy *policy) 512 { 513 AA_BUG(on_list_rcu(&policy->profiles)); 514 AA_BUG(on_list_rcu(&policy->list)); 515 516 /* don't free name as its a subset of hname */ 517 aa_put_str(policy->hname); 518 } 519