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