diff options
| author | Robert Richter <robert.richter@amd.com> | 2010-10-11 13:26:50 -0400 |
|---|---|---|
| committer | Robert Richter <robert.richter@amd.com> | 2010-10-11 13:26:50 -0400 |
| commit | ad0f7cfaa85fc033523a09ab1f3dd6b8ded3dff5 (patch) | |
| tree | 2565121e4b9945d953e02c77a2e53065b3789aa4 /security/apparmor | |
| parent | 86c8c04792f152c5469023885510140dd34817bc (diff) | |
| parent | c7a27aa4652c63172489a73f3961455650a79a7f (diff) | |
Merge branch 'oprofile/urgent' (early part) into oprofile/perf
Diffstat (limited to 'security/apparmor')
| -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 |
6 files changed, 31 insertions, 41 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 | /** |
