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