Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6:
ima: always maintain counters
AppArmor: Fix locking from removal of profile namespace
AppArmor: Fix splitting an fqname into separate namespace and profile names
AppArmor: Fix security_task_setrlimit logic for 2.6.36 changes
AppArmor: Drop hack to remove appended " (deleted)" string

+40 -45
+2 -2
security/apparmor/include/resource.h
··· 33 }; 34 35 int aa_map_resource(int resource); 36 - int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, 37 - struct rlimit *new_rlim); 38 39 void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); 40
··· 33 }; 34 35 int aa_map_resource(int resource); 36 + int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, 37 + unsigned int resource, struct rlimit *new_rlim); 38 39 void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); 40
+1 -1
security/apparmor/lib.c
··· 40 *ns_name = NULL; 41 if (name[0] == ':') { 42 char *split = strchr(&name[1], ':'); 43 if (split) { 44 /* overwrite ':' with \0 */ 45 *split = 0; ··· 48 } else 49 /* a ns name without a following profile is allowed */ 50 name = NULL; 51 - *ns_name = &name[1]; 52 } 53 if (name && *name == 0) 54 name = NULL;
··· 40 *ns_name = NULL; 41 if (name[0] == ':') { 42 char *split = strchr(&name[1], ':'); 43 + *ns_name = skip_spaces(&name[1]); 44 if (split) { 45 /* overwrite ':' with \0 */ 46 *split = 0; ··· 47 } else 48 /* a ns name without a following profile is allowed */ 49 name = NULL; 50 } 51 if (name && *name == 0) 52 name = NULL;
+1 -1
security/apparmor/lsm.c
··· 614 int error = 0; 615 616 if (!unconfined(profile)) 617 - error = aa_task_setrlimit(profile, resource, new_rlim); 618 619 return error; 620 }
··· 614 int error = 0; 615 616 if (!unconfined(profile)) 617 + error = aa_task_setrlimit(profile, task, resource, new_rlim); 618 619 return error; 620 }
+11 -27
security/apparmor/path.c
··· 59 { 60 struct path root, tmp; 61 char *res; 62 - int deleted, connected; 63 - int error = 0; 64 65 /* Get the root we want to resolve too, released below */ 66 if (flags & PATH_CHROOT_REL) { ··· 73 } 74 75 spin_lock(&dcache_lock); 76 - /* There is a race window between path lookup here and the 77 - * need to strip the " (deleted) string that __d_path applies 78 - * Detect the race and relookup the path 79 - * 80 - * The stripping of (deleted) is a hack that could be removed 81 - * with an updated __d_path 82 - */ 83 - do { 84 - tmp = root; 85 - deleted = d_unlinked(path->dentry); 86 - res = __d_path(path, &tmp, buf, buflen); 87 - 88 - } while (deleted != d_unlinked(path->dentry)); 89 spin_unlock(&dcache_lock); 90 91 *name = res; ··· 86 *name = buf; 87 goto out; 88 } 89 - if (deleted) { 90 - /* On some filesystems, newly allocated dentries appear to the 91 - * security_path hooks as a deleted dentry except without an 92 - * inode allocated. 93 - * 94 - * Remove the appended deleted text and return as string for 95 - * normal mediation, or auditing. The (deleted) string is 96 - * guaranteed to be added in this case, so just strip it. 97 - */ 98 - buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */ 99 100 - if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) { 101 error = -ENOENT; 102 goto out; 103 - } 104 } 105 106 /* Determine if the path is connected to the expected root */
··· 59 { 60 struct path root, tmp; 61 char *res; 62 + int connected, error = 0; 63 64 /* Get the root we want to resolve too, released below */ 65 if (flags & PATH_CHROOT_REL) { ··· 74 } 75 76 spin_lock(&dcache_lock); 77 + tmp = root; 78 + res = __d_path(path, &tmp, buf, buflen); 79 spin_unlock(&dcache_lock); 80 81 *name = res; ··· 98 *name = buf; 99 goto out; 100 } 101 102 + /* Handle two cases: 103 + * 1. A deleted dentry && profile is not allowing mediation of deleted 104 + * 2. On some filesystems, newly allocated dentries appear to the 105 + * security_path hooks as a deleted dentry except without an inode 106 + * allocated. 107 + */ 108 + if (d_unlinked(path->dentry) && path->dentry->d_inode && 109 + !(flags & PATH_MEDIATE_DELETED)) { 110 error = -ENOENT; 111 goto out; 112 } 113 114 /* Determine if the path is connected to the expected root */
+4 -2
security/apparmor/policy.c
··· 1151 /* released below */ 1152 ns = aa_get_namespace(root); 1153 1154 - write_lock(&ns->lock); 1155 if (!name) { 1156 /* remove namespace - can only happen if fqname[0] == ':' */ 1157 __remove_namespace(ns); 1158 } else { 1159 /* remove profile */ 1160 profile = aa_get_profile(__lookup_profile(&ns->base, name)); 1161 if (!profile) { 1162 error = -ENOENT; ··· 1167 } 1168 name = profile->base.hname; 1169 __remove_profile(profile); 1170 } 1171 - write_unlock(&ns->lock); 1172 1173 /* don't fail removal if audit fails */ 1174 (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
··· 1151 /* released below */ 1152 ns = aa_get_namespace(root); 1153 1154 if (!name) { 1155 /* remove namespace - can only happen if fqname[0] == ':' */ 1156 + write_lock(&ns->parent->lock); 1157 __remove_namespace(ns); 1158 + write_unlock(&ns->parent->lock); 1159 } else { 1160 /* remove profile */ 1161 + write_lock(&ns->lock); 1162 profile = aa_get_profile(__lookup_profile(&ns->base, name)); 1163 if (!profile) { 1164 error = -ENOENT; ··· 1165 } 1166 name = profile->base.hname; 1167 __remove_profile(profile); 1168 + write_unlock(&ns->lock); 1169 } 1170 1171 /* don't fail removal if audit fails */ 1172 (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
+12 -8
security/apparmor/resource.c
··· 72 /** 73 * aa_task_setrlimit - test permission to set an rlimit 74 * @profile - profile confining the task (NOT NULL) 75 * @resource - the resource being set 76 * @new_rlim - the new resource limit (NOT NULL) 77 * ··· 80 * 81 * Returns: 0 or error code if setting resource failed 82 */ 83 - int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, 84 - struct rlimit *new_rlim) 85 { 86 int error = 0; 87 88 - if (profile->rlimits.mask & (1 << resource) && 89 - new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) 90 91 - error = audit_resource(profile, resource, new_rlim->rlim_max, 92 - -EACCES); 93 - 94 - return error; 95 } 96 97 /**
··· 72 /** 73 * aa_task_setrlimit - test permission to set an rlimit 74 * @profile - profile confining the task (NOT NULL) 75 + * @task - task the resource is being set on 76 * @resource - the resource being set 77 * @new_rlim - the new resource limit (NOT NULL) 78 * ··· 79 * 80 * Returns: 0 or error code if setting resource failed 81 */ 82 + int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, 83 + unsigned int resource, struct rlimit *new_rlim) 84 { 85 int error = 0; 86 87 + /* TODO: extend resource control to handle other (non current) 88 + * processes. AppArmor rules currently have the implicit assumption 89 + * that the task is setting the resource of the current process 90 + */ 91 + if ((task != current->group_leader) || 92 + (profile->rlimits.mask & (1 << resource) && 93 + new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) 94 + error = -EACCES; 95 96 + return audit_resource(profile, resource, new_rlim->rlim_max, error); 97 } 98 99 /**
+1
security/integrity/ima/ima.h
··· 35 #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) 36 37 /* set during initialization */ 38 extern int ima_initialized; 39 extern int ima_used_chip; 40 extern char *ima_hash;
··· 35 #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) 36 37 /* set during initialization */ 38 + extern int iint_initialized; 39 extern int ima_initialized; 40 extern int ima_used_chip; 41 extern char *ima_hash;
+3 -1
security/integrity/ima/ima_iint.c
··· 22 23 RADIX_TREE(ima_iint_store, GFP_ATOMIC); 24 DEFINE_SPINLOCK(ima_iint_lock); 25 - 26 static struct kmem_cache *iint_cache __read_mostly; 27 28 /* ima_iint_find_get - return the iint associated with an inode 29 * ··· 142 iint_cache = 143 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, 144 SLAB_PANIC, init_once); 145 return 0; 146 } 147 security_initcall(ima_iintcache_init);
··· 22 23 RADIX_TREE(ima_iint_store, GFP_ATOMIC); 24 DEFINE_SPINLOCK(ima_iint_lock); 25 static struct kmem_cache *iint_cache __read_mostly; 26 + 27 + int iint_initialized = 0; 28 29 /* ima_iint_find_get - return the iint associated with an inode 30 * ··· 141 iint_cache = 142 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, 143 SLAB_PANIC, init_once); 144 + iint_initialized = 1; 145 return 0; 146 } 147 security_initcall(ima_iintcache_init);
+5 -3
security/integrity/ima/ima_main.c
··· 148 struct ima_iint_cache *iint; 149 int rc; 150 151 - if (!ima_initialized || !S_ISREG(inode->i_mode)) 152 return; 153 iint = ima_iint_find_get(inode); 154 if (!iint) 155 return; 156 mutex_lock(&iint->mutex); 157 rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); 158 if (rc < 0) 159 goto out; ··· 215 struct inode *inode = file->f_dentry->d_inode; 216 struct ima_iint_cache *iint; 217 218 - if (!ima_initialized || !S_ISREG(inode->i_mode)) 219 return; 220 iint = ima_iint_find_get(inode); 221 if (!iint) ··· 232 { 233 struct inode *inode = file->f_dentry->d_inode; 234 struct ima_iint_cache *iint; 235 - int rc; 236 237 if (!ima_initialized || !S_ISREG(inode->i_mode)) 238 return 0;
··· 148 struct ima_iint_cache *iint; 149 int rc; 150 151 + if (!iint_initialized || !S_ISREG(inode->i_mode)) 152 return; 153 iint = ima_iint_find_get(inode); 154 if (!iint) 155 return; 156 mutex_lock(&iint->mutex); 157 + if (!ima_initialized) 158 + goto out; 159 rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); 160 if (rc < 0) 161 goto out; ··· 213 struct inode *inode = file->f_dentry->d_inode; 214 struct ima_iint_cache *iint; 215 216 + if (!iint_initialized || !S_ISREG(inode->i_mode)) 217 return; 218 iint = ima_iint_find_get(inode); 219 if (!iint) ··· 230 { 231 struct inode *inode = file->f_dentry->d_inode; 232 struct ima_iint_cache *iint; 233 + int rc = 0; 234 235 if (!ima_initialized || !S_ISREG(inode->i_mode)) 236 return 0;