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