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 * @str_size: size of the @str buffer 202 * @chrs: NUL-terminated character buffer of permission characters 203 * @mask: permission mask to convert 204 */ 205 void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs, u32 mask) 206 { 207 unsigned int i, perm = 1; 208 size_t num_chrs = strlen(chrs); 209 210 for (i = 0; i < num_chrs; perm <<= 1, i++) { 211 if (mask & perm) { 212 /* Ensure that one byte is left for NUL-termination */ 213 if (WARN_ON_ONCE(str_size <= 1)) 214 break; 215 216 *str++ = chrs[i]; 217 str_size--; 218 } 219 } 220 *str = '\0'; 221 } 222 223 void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names, 224 u32 mask) 225 { 226 const char *fmt = "%s"; 227 unsigned int i, perm = 1; 228 bool prev = false; 229 230 for (i = 0; i < 32; perm <<= 1, i++) { 231 if (mask & perm) { 232 audit_log_format(ab, fmt, names[i]); 233 if (!prev) { 234 prev = true; 235 fmt = " %s"; 236 } 237 } 238 } 239 } 240 241 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 242 u32 chrsmask, const char * const *names, u32 namesmask) 243 { 244 char str[33]; 245 246 audit_log_format(ab, "\""); 247 if ((mask & chrsmask) && chrs) { 248 aa_perm_mask_to_str(str, sizeof(str), chrs, mask & chrsmask); 249 mask &= ~chrsmask; 250 audit_log_format(ab, "%s", str); 251 if (mask & namesmask) 252 audit_log_format(ab, " "); 253 } 254 if ((mask & namesmask) && names) 255 aa_audit_perm_names(ab, names, mask & namesmask); 256 audit_log_format(ab, "\""); 257 } 258 259 /** 260 * aa_audit_perms_cb - generic callback fn for auditing perms 261 * @ab: audit buffer (NOT NULL) 262 * @va: audit struct to audit values of (NOT NULL) 263 */ 264 static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) 265 { 266 struct common_audit_data *sa = va; 267 268 if (aad(sa)->request) { 269 audit_log_format(ab, " requested_mask="); 270 aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, 271 PERMS_CHRS_MASK, aa_file_perm_names, 272 PERMS_NAMES_MASK); 273 } 274 if (aad(sa)->denied) { 275 audit_log_format(ab, "denied_mask="); 276 aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, 277 PERMS_CHRS_MASK, aa_file_perm_names, 278 PERMS_NAMES_MASK); 279 } 280 audit_log_format(ab, " peer="); 281 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 282 FLAGS_NONE, GFP_ATOMIC); 283 } 284 285 /** 286 * aa_apply_modes_to_perms - apply namespace and profile flags to perms 287 * @profile: that perms where computed from 288 * @perms: perms to apply mode modifiers to 289 * 290 * TODO: split into profile and ns based flags for when accumulating perms 291 */ 292 void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms) 293 { 294 switch (AUDIT_MODE(profile)) { 295 case AUDIT_ALL: 296 perms->audit = ALL_PERMS_MASK; 297 /* fall through */ 298 case AUDIT_NOQUIET: 299 perms->quiet = 0; 300 break; 301 case AUDIT_QUIET: 302 perms->audit = 0; 303 /* fall through */ 304 case AUDIT_QUIET_DENIED: 305 perms->quiet = ALL_PERMS_MASK; 306 break; 307 } 308 309 if (KILL_MODE(profile)) 310 perms->kill = ALL_PERMS_MASK; 311 else if (COMPLAIN_MODE(profile)) 312 perms->complain = ALL_PERMS_MASK; 313 /* 314 * TODO: 315 * else if (PROMPT_MODE(profile)) 316 * perms->prompt = ALL_PERMS_MASK; 317 */ 318 } 319 320 static u32 map_other(u32 x) 321 { 322 return ((x & 0x3) << 8) | /* SETATTR/GETATTR */ 323 ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */ 324 ((x & 0x60) << 19); /* SETOPT/GETOPT */ 325 } 326 327 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, 328 struct aa_perms *perms) 329 { 330 *perms = (struct aa_perms) { 331 .allow = dfa_user_allow(dfa, state), 332 .audit = dfa_user_audit(dfa, state), 333 .quiet = dfa_user_quiet(dfa, state), 334 }; 335 336 /* for v5 perm mapping in the policydb, the other set is used 337 * to extend the general perm set 338 */ 339 perms->allow |= map_other(dfa_other_allow(dfa, state)); 340 perms->audit |= map_other(dfa_other_audit(dfa, state)); 341 perms->quiet |= map_other(dfa_other_quiet(dfa, state)); 342 // perms->xindex = dfa_user_xindex(dfa, state); 343 } 344 345 /** 346 * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms 347 * @accum - perms struct to accumulate into 348 * @addend - perms struct to add to @accum 349 */ 350 void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend) 351 { 352 accum->deny |= addend->deny; 353 accum->allow &= addend->allow & ~addend->deny; 354 accum->audit |= addend->audit & addend->allow; 355 accum->quiet &= addend->quiet & ~addend->allow; 356 accum->kill |= addend->kill & ~addend->allow; 357 accum->stop |= addend->stop & ~addend->allow; 358 accum->complain |= addend->complain & ~addend->allow & ~addend->deny; 359 accum->cond |= addend->cond & ~addend->allow & ~addend->deny; 360 accum->hide &= addend->hide & ~addend->allow; 361 accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny; 362 } 363 364 /** 365 * aa_perms_accum - accumulate perms, masking off overlapping perms 366 * @accum - perms struct to accumulate into 367 * @addend - perms struct to add to @accum 368 */ 369 void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend) 370 { 371 accum->deny |= addend->deny; 372 accum->allow &= addend->allow & ~accum->deny; 373 accum->audit |= addend->audit & accum->allow; 374 accum->quiet &= addend->quiet & ~accum->allow; 375 accum->kill |= addend->kill & ~accum->allow; 376 accum->stop |= addend->stop & ~accum->allow; 377 accum->complain |= addend->complain & ~accum->allow & ~accum->deny; 378 accum->cond |= addend->cond & ~accum->allow & ~accum->deny; 379 accum->hide &= addend->hide & ~accum->allow; 380 accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny; 381 } 382 383 void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, 384 int type, u32 request, struct aa_perms *perms) 385 { 386 /* TODO: doesn't yet handle extended types */ 387 unsigned int state; 388 389 state = aa_dfa_next(profile->policy.dfa, 390 profile->policy.start[AA_CLASS_LABEL], 391 type); 392 aa_label_match(profile, label, state, false, request, perms); 393 } 394 395 396 /* currently unused */ 397 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, 398 u32 request, int type, u32 *deny, 399 struct common_audit_data *sa) 400 { 401 struct aa_perms perms; 402 403 aad(sa)->label = &profile->label; 404 aad(sa)->peer = &target->label; 405 aad(sa)->request = request; 406 407 aa_profile_match_label(profile, &target->label, type, request, &perms); 408 aa_apply_modes_to_perms(profile, &perms); 409 *deny |= request & perms.deny; 410 return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb); 411 } 412 413 /** 414 * aa_check_perms - do audit mode selection based on perms set 415 * @profile: profile being checked 416 * @perms: perms computed for the request 417 * @request: requested perms 418 * @deny: Returns: explicit deny set 419 * @sa: initialized audit structure (MAY BE NULL if not auditing) 420 * @cb: callback fn for type specific fields (MAY BE NULL) 421 * 422 * Returns: 0 if permission else error code 423 * 424 * Note: profile audit modes need to be set before calling by setting the 425 * perm masks appropriately. 426 * 427 * If not auditing then complain mode is not enabled and the 428 * error code will indicate whether there was an explicit deny 429 * with a positive value. 430 */ 431 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, 432 u32 request, struct common_audit_data *sa, 433 void (*cb)(struct audit_buffer *, void *)) 434 { 435 int type, error; 436 u32 denied = request & (~perms->allow | perms->deny); 437 438 if (likely(!denied)) { 439 /* mask off perms that are not being force audited */ 440 request &= perms->audit; 441 if (!request || !sa) 442 return 0; 443 444 type = AUDIT_APPARMOR_AUDIT; 445 error = 0; 446 } else { 447 error = -EACCES; 448 449 if (denied & perms->kill) 450 type = AUDIT_APPARMOR_KILL; 451 else if (denied == (denied & perms->complain)) 452 type = AUDIT_APPARMOR_ALLOWED; 453 else 454 type = AUDIT_APPARMOR_DENIED; 455 456 if (denied == (denied & perms->hide)) 457 error = -ENOENT; 458 459 denied &= ~perms->quiet; 460 if (!sa || !denied) 461 return error; 462 } 463 464 if (sa) { 465 aad(sa)->label = &profile->label; 466 aad(sa)->request = request; 467 aad(sa)->denied = denied; 468 aad(sa)->error = error; 469 aa_audit_msg(type, sa, cb); 470 } 471 472 if (type == AUDIT_APPARMOR_ALLOWED) 473 error = 0; 474 475 return error; 476 } 477 478 479 /** 480 * aa_policy_init - initialize a policy structure 481 * @policy: policy to initialize (NOT NULL) 482 * @prefix: prefix name if any is required. (MAYBE NULL) 483 * @name: name of the policy, init will make a copy of it (NOT NULL) 484 * @gfp: allocation mode 485 * 486 * Note: this fn creates a copy of strings passed in 487 * 488 * Returns: true if policy init successful 489 */ 490 bool aa_policy_init(struct aa_policy *policy, const char *prefix, 491 const char *name, gfp_t gfp) 492 { 493 char *hname; 494 495 /* freed by policy_free */ 496 if (prefix) { 497 hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp); 498 if (hname) 499 sprintf(hname, "%s//%s", prefix, name); 500 } else { 501 hname = aa_str_alloc(strlen(name) + 1, gfp); 502 if (hname) 503 strcpy(hname, name); 504 } 505 if (!hname) 506 return false; 507 policy->hname = hname; 508 /* base.name is a substring of fqname */ 509 policy->name = basename(policy->hname); 510 INIT_LIST_HEAD(&policy->list); 511 INIT_LIST_HEAD(&policy->profiles); 512 513 return true; 514 } 515 516 /** 517 * aa_policy_destroy - free the elements referenced by @policy 518 * @policy: policy that is to have its elements freed (NOT NULL) 519 */ 520 void aa_policy_destroy(struct aa_policy *policy) 521 { 522 AA_BUG(on_list_rcu(&policy->profiles)); 523 AA_BUG(on_list_rcu(&policy->list)); 524 525 /* don't free name as its a subset of hname */ 526 aa_put_str(policy->hname); 527 } 528