1cdff2642SJohn Johansen /* 2cdff2642SJohn Johansen * AppArmor security module 3cdff2642SJohn Johansen * 4cdff2642SJohn Johansen * This file contains basic common functions used in AppArmor 5cdff2642SJohn Johansen * 6cdff2642SJohn Johansen * Copyright (C) 1998-2008 Novell/SUSE 7cdff2642SJohn Johansen * Copyright 2009-2010 Canonical Ltd. 8cdff2642SJohn Johansen * 9cdff2642SJohn Johansen * This program is free software; you can redistribute it and/or 10cdff2642SJohn Johansen * modify it under the terms of the GNU General Public License as 11cdff2642SJohn Johansen * published by the Free Software Foundation, version 2 of the 12cdff2642SJohn Johansen * License. 13cdff2642SJohn Johansen */ 14cdff2642SJohn Johansen 15b7f080cfSAlexey Dobriyan #include <linux/mm.h> 16cdff2642SJohn Johansen #include <linux/slab.h> 17cdff2642SJohn Johansen #include <linux/string.h> 18cdff2642SJohn Johansen #include <linux/vmalloc.h> 19cdff2642SJohn Johansen 20cdff2642SJohn Johansen #include "include/audit.h" 2132c3df63SJames Morris #include "include/apparmor.h" 22cdff2642SJohn Johansen 23cdff2642SJohn Johansen 24cdff2642SJohn Johansen /** 25cdff2642SJohn Johansen * aa_split_fqname - split a fqname into a profile and namespace name 26cdff2642SJohn Johansen * @fqname: a full qualified name in namespace profile format (NOT NULL) 27cdff2642SJohn Johansen * @ns_name: pointer to portion of the string containing the ns name (NOT NULL) 28cdff2642SJohn Johansen * 29cdff2642SJohn Johansen * Returns: profile name or NULL if one is not specified 30cdff2642SJohn Johansen * 31cdff2642SJohn Johansen * Split a namespace name from a profile name (see policy.c for naming 32cdff2642SJohn Johansen * description). If a portion of the name is missing it returns NULL for 33cdff2642SJohn Johansen * that portion. 34cdff2642SJohn Johansen * 35cdff2642SJohn Johansen * NOTE: may modify the @fqname string. The pointers returned point 36cdff2642SJohn Johansen * into the @fqname string. 37cdff2642SJohn Johansen */ 38cdff2642SJohn Johansen char *aa_split_fqname(char *fqname, char **ns_name) 39cdff2642SJohn Johansen { 40cdff2642SJohn Johansen char *name = strim(fqname); 41cdff2642SJohn Johansen 42cdff2642SJohn Johansen *ns_name = NULL; 43cdff2642SJohn Johansen if (name[0] == ':') { 44cdff2642SJohn Johansen char *split = strchr(&name[1], ':'); 4504ccd53fSJohn Johansen *ns_name = skip_spaces(&name[1]); 46cdff2642SJohn Johansen if (split) { 47cdff2642SJohn Johansen /* overwrite ':' with \0 */ 48*2654bfbcSJohn Johansen *split++ = 0; 49*2654bfbcSJohn Johansen if (strncmp(split, "//", 2) == 0) 50*2654bfbcSJohn Johansen split += 2; 51*2654bfbcSJohn Johansen name = skip_spaces(split); 52cdff2642SJohn Johansen } else 53cdff2642SJohn Johansen /* a ns name without a following profile is allowed */ 54cdff2642SJohn Johansen name = NULL; 55cdff2642SJohn Johansen } 56cdff2642SJohn Johansen if (name && *name == 0) 57cdff2642SJohn Johansen name = NULL; 58cdff2642SJohn Johansen 59cdff2642SJohn Johansen return name; 60cdff2642SJohn Johansen } 61cdff2642SJohn Johansen 62cdff2642SJohn Johansen /** 63cdff2642SJohn Johansen * aa_info_message - log a none profile related status message 64cdff2642SJohn Johansen * @str: message to log 65cdff2642SJohn Johansen */ 66cdff2642SJohn Johansen void aa_info_message(const char *str) 67cdff2642SJohn Johansen { 68cdff2642SJohn Johansen if (audit_enabled) { 69cdff2642SJohn Johansen struct common_audit_data sa; 703b3b0e4fSEric Paris struct apparmor_audit_data aad = {0,}; 7150c205f5SEric Paris sa.type = LSM_AUDIT_DATA_NONE; 723b3b0e4fSEric Paris sa.aad = &aad; 733b3b0e4fSEric Paris aad.info = str; 74cdff2642SJohn Johansen aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); 75cdff2642SJohn Johansen } 76cdff2642SJohn Johansen printk(KERN_INFO "AppArmor: %s\n", str); 77cdff2642SJohn Johansen } 78cdff2642SJohn Johansen 79cdff2642SJohn Johansen /** 800ca554b9SJohn Johansen * __aa_kvmalloc - do allocation preferring kmalloc but falling back to vmalloc 810ca554b9SJohn Johansen * @size: how many bytes of memory are required 820ca554b9SJohn Johansen * @flags: the type of memory to allocate (see kmalloc). 83cdff2642SJohn Johansen * 84cdff2642SJohn Johansen * Return: allocated buffer or NULL if failed 85cdff2642SJohn Johansen * 86cdff2642SJohn Johansen * It is possible that policy being loaded from the user is larger than 87cdff2642SJohn Johansen * what can be allocated by kmalloc, in those cases fall back to vmalloc. 88cdff2642SJohn Johansen */ 890ca554b9SJohn Johansen void *__aa_kvmalloc(size_t size, gfp_t flags) 90cdff2642SJohn Johansen { 91cdff2642SJohn Johansen void *buffer = NULL; 92cdff2642SJohn Johansen 93cdff2642SJohn Johansen if (size == 0) 94cdff2642SJohn Johansen return NULL; 95cdff2642SJohn Johansen 96cdff2642SJohn Johansen /* do not attempt kmalloc if we need more than 16 pages at once */ 97cdff2642SJohn Johansen if (size <= (16*PAGE_SIZE)) 980ca554b9SJohn Johansen buffer = kmalloc(size, flags | GFP_NOIO | __GFP_NOWARN); 99cdff2642SJohn Johansen if (!buffer) { 100cdff2642SJohn Johansen /* see kvfree for why size must be at least work_struct size 101cdff2642SJohn Johansen * when allocated via vmalloc 102cdff2642SJohn Johansen */ 103cdff2642SJohn Johansen if (size < sizeof(struct work_struct)) 104cdff2642SJohn Johansen size = sizeof(struct work_struct); 1050ca554b9SJohn Johansen if (flags & __GFP_ZERO) 1060ca554b9SJohn Johansen buffer = vzalloc(size); 1070ca554b9SJohn Johansen else 108cdff2642SJohn Johansen buffer = vmalloc(size); 109cdff2642SJohn Johansen } 110cdff2642SJohn Johansen return buffer; 111cdff2642SJohn Johansen } 112cdff2642SJohn Johansen 113cdff2642SJohn Johansen /** 114cdff2642SJohn Johansen * do_vfree - workqueue routine for freeing vmalloced memory 115cdff2642SJohn Johansen * @work: data to be freed 116cdff2642SJohn Johansen * 117cdff2642SJohn Johansen * The work_struct is overlaid to the data being freed, as at the point 118cdff2642SJohn Johansen * the work is scheduled the data is no longer valid, be its freeing 119cdff2642SJohn Johansen * needs to be delayed until safe. 120cdff2642SJohn Johansen */ 121cdff2642SJohn Johansen static void do_vfree(struct work_struct *work) 122cdff2642SJohn Johansen { 123cdff2642SJohn Johansen vfree(work); 124cdff2642SJohn Johansen } 125cdff2642SJohn Johansen 126cdff2642SJohn Johansen /** 127cdff2642SJohn Johansen * kvfree - free an allocation do by kvmalloc 128cdff2642SJohn Johansen * @buffer: buffer to free (MAYBE_NULL) 129cdff2642SJohn Johansen * 130cdff2642SJohn Johansen * Free a buffer allocated by kvmalloc 131cdff2642SJohn Johansen */ 132cdff2642SJohn Johansen void kvfree(void *buffer) 133cdff2642SJohn Johansen { 134cdff2642SJohn Johansen if (is_vmalloc_addr(buffer)) { 135cdff2642SJohn Johansen /* Data is no longer valid so just use the allocated space 136cdff2642SJohn Johansen * as the work_struct 137cdff2642SJohn Johansen */ 138cdff2642SJohn Johansen struct work_struct *work = (struct work_struct *) buffer; 139cdff2642SJohn Johansen INIT_WORK(work, do_vfree); 140cdff2642SJohn Johansen schedule_work(work); 141cdff2642SJohn Johansen } else 142cdff2642SJohn Johansen kfree(buffer); 143cdff2642SJohn Johansen } 144