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