[apparmor] [PATCH 32/36] apparmor: treat mount as if each task may have multi-profile labels
John Johansen
john.johansen at canonical.com
Wed May 1 21:31:17 UTC 2013
Signed-off-by: John Johansen <john.johansen at canonical.com>
---
security/apparmor/mount.c | 311 +++++++++++++++++++++++++++++-----------------
1 file changed, 194 insertions(+), 117 deletions(-)
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
index b3e019b..7188a82 100644
--- a/security/apparmor/mount.c
+++ b/security/apparmor/mount.c
@@ -233,7 +233,7 @@ static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
return perms;
}
-static const char const *mnt_info_table[] = {
+static const char *mnt_info_table[] = {
"match succeeded",
"failed mntpnt match",
"failed srcname match",
@@ -339,26 +339,34 @@ static int path_flags(struct aa_profile *profile, struct path *path)
int aa_remount(struct aa_label *label, struct path *path, unsigned long flags,
void *data)
{
- struct aa_profile *profile = labels_profile(label);
+ struct aa_profile *profile;
struct file_perms perms = { };
const char *name, *info = NULL;
char *buffer = NULL;
- int binary, error;
+ int binary, i, error;
binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
- error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
- &info);
- if (error)
- goto audit;
+ error = aa_path_name(path, path_flags(labels_profile(label), path),
+ &buffer, &name, &info);
+ if (error) {
+ error = audit_mount(labels_profile(label), GFP_KERNEL, OP_MOUNT, name, NULL,
+ NULL, NULL, flags, data, AA_MAY_MOUNT,
+ &perms, info, error);
+ goto out;
+ }
- error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
- &perms, &info);
+ label_for_each_confined(i, label, profile) {
+ error = match_mnt(profile, name, NULL, NULL, flags, data,
+ binary, &perms, &info);
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL,
+ NULL, NULL, flags, data, AA_MAY_MOUNT,
+ &perms, info, error);
+ if (error)
+ break;
+ }
-audit:
- error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
- NULL, flags, data, AA_MAY_MOUNT, &perms, info,
- error);
+out:
kfree(buffer);
return error;
@@ -367,71 +375,90 @@ audit:
int aa_bind_mount(struct aa_label *label, struct path *path,
const char *dev_name, unsigned long flags)
{
- struct aa_profile *profile = labels_profile(label);
+ struct aa_profile *profile;
struct file_perms perms = { };
char *buffer = NULL, *old_buffer = NULL;
const char *name, *old_name = NULL, *info = NULL;
struct path old_path;
- int error;
+ int i, error;
if (!dev_name || !*dev_name)
return -EINVAL;
flags &= MS_REC | MS_BIND;
- error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
+ error = aa_path_name(path, path_flags(labels_profile(label), path), &buffer, &name,
&info);
if (error)
- goto audit;
+ goto error;
error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
if (error)
- goto audit;
+ goto error;
- error = aa_path_name(&old_path, path_flags(profile, &old_path),
+ error = aa_path_name(&old_path, path_flags(labels_profile(label),
+ &old_path),
&old_buffer, &old_name, &info);
path_put(&old_path);
if (error)
- goto audit;
-
- error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
- &perms, &info);
+ goto error;
+
+ label_for_each_confined(i, label, profile) {
+ error = match_mnt(profile, name, old_name, NULL, flags, NULL,
+ 0, &perms, &info);
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name,
+ old_name, NULL, NULL, flags, NULL,
+ AA_MAY_MOUNT, &perms, info, error);
+ if (error)
+ break;
+ }
-audit:
- error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
- NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
- info, error);
+out:
kfree(buffer);
kfree(old_buffer);
return error;
+
+error:
+ error = audit_mount(labels_profile(label), GFP_KERNEL, OP_MOUNT, name, old_name,
+ NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
+ info, error);
+ goto out;
}
int aa_mount_change_type(struct aa_label *label, struct path *path,
unsigned long flags)
{
- struct aa_profile *profile = labels_profile(label);
+ struct aa_profile *profile;
struct file_perms perms = { };
char *buffer = NULL;
const char *name, *info = NULL;
- int error;
+ int i, error;
/* These are the flags allowed by do_change_type() */
flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
MS_UNBINDABLE);
- error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
- &info);
- if (error)
- goto audit;
+ error = aa_path_name(path, path_flags(labels_profile(label), path),
+ &buffer, &name, &info);
+ if (error) {
+ error = audit_mount(labels_profile(label), GFP_KERNEL, OP_MOUNT, name, NULL,
+ NULL, NULL, flags, NULL, AA_MAY_MOUNT,
+ &perms, info, error);
+ goto out;
+ }
- error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
- &info);
+ label_for_each_confined(i, label, profile) {
+ error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0,
+ &perms, &info);
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL,
+ NULL, NULL, flags, NULL, AA_MAY_MOUNT,
+ &perms, info, error);
+ if (error)
+ break;
+ }
-audit:
- error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
- NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
- error);
+out:
kfree(buffer);
return error;
@@ -440,54 +467,65 @@ audit:
int aa_move_mount(struct aa_label *label, struct path *path,
const char *orig_name)
{
- struct aa_profile *profile = labels_profile(label);
+ struct aa_profile *profile;
struct file_perms perms = { };
char *buffer = NULL, *old_buffer = NULL;
const char *name, *old_name = NULL, *info = NULL;
struct path old_path;
- int error;
+ int i, error;
if (!orig_name || !*orig_name)
return -EINVAL;
- error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
- &info);
+ error = aa_path_name(path, path_flags(labels_profile(label), path),
+ &buffer, &name, &info);
if (error)
- goto audit;
+ goto error;
error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
if (error)
- goto audit;
+ goto error;
- error = aa_path_name(&old_path, path_flags(profile, &old_path),
+ error = aa_path_name(&old_path, path_flags(labels_profile(label),
+ &old_path),
&old_buffer, &old_name, &info);
path_put(&old_path);
if (error)
- goto audit;
-
- error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
- &perms, &info);
+ goto error;
+
+ label_for_each_confined(i, label, profile) {
+ error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL,
+ 0, &perms, &info);
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name,
+ old_name, NULL, NULL, MS_MOVE, NULL,
+ AA_MAY_MOUNT, &perms, info, error);
+ if (error)
+ break;
+ }
-audit:
- error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
- NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
- info, error);
+out:
kfree(buffer);
kfree(old_buffer);
return error;
+
+error:
+ error = audit_mount(labels_profile(label), GFP_KERNEL, OP_MOUNT, name, old_name,
+ NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
+ info, error);
+ goto out;
}
int aa_new_mount(struct aa_label *label, const char *orig_dev_name,
struct path *path, const char *type, unsigned long flags,
void *data)
{
- struct aa_profile *profile = labels_profile(label);
+ struct aa_profile *profile;
struct file_perms perms = { };
char *buffer = NULL, *dev_buffer = NULL;
const char *name = NULL, *dev_name = NULL, *info = NULL;
int binary = 1;
- int error;
+ int i, error;
dev_name = orig_dev_name;
if (type) {
@@ -510,65 +548,86 @@ int aa_new_mount(struct aa_label *label, const char *orig_dev_name,
error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
if (error)
- goto audit;
+ goto error;
error = aa_path_name(&dev_path,
- path_flags(profile, &dev_path),
+ path_flags(labels_profile(label),
+ &dev_path),
&dev_buffer, &dev_name, &info);
path_put(&dev_path);
if (error)
- goto audit;
+ goto error;
}
}
- error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
- &info);
+ error = aa_path_name(path, path_flags(labels_profile(label), path),
+ &buffer, &name, &info);
if (error)
- goto audit;
-
- error = match_mnt(profile, name, dev_name, type, flags, data, binary,
- &perms, &info);
+ goto error;
+
+ label_for_each_confined(i, label, profile) {
+ error = match_mnt(profile, name, dev_name, type, flags, data,
+ binary, &perms, &info);
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name,
+ dev_name, type, NULL, flags, data,
+ AA_MAY_MOUNT, &perms, info, error);
+ if (error)
+ break;
+ }
-audit:
- error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, dev_name,
- type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
- error);
+cleanup:
kfree(buffer);
kfree(dev_buffer);
out:
return error;
+error:
+ error = audit_mount(labels_profile(label), GFP_KERNEL, OP_MOUNT, name, dev_name,
+ type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
+ error);
+ goto cleanup;
}
int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
{
- struct aa_profile *profile = labels_profile(label);
+ struct aa_profile *profile;
struct file_perms perms = { };
char *buffer = NULL;
const char *name, *info = NULL;
- int error;
+ int i, error;
struct path path = { mnt, mnt->mnt_root };
- error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
- &info);
- if (error)
- goto audit;
-
- if (!error && profile->policy.dfa) {
- unsigned int state;
- state = aa_dfa_match(profile->policy.dfa,
- profile->policy.start[AA_CLASS_MOUNT],
- name);
- perms = compute_mnt_perms(profile->policy.dfa, state);
+ error = aa_path_name(&path, path_flags(labels_profile(label), &path),
+ &buffer, &name, &info);
+ if (error) {
+ error = audit_mount(labels_profile(label), GFP_KERNEL,
+ OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
+ AA_MAY_UMOUNT, &perms, info, error);
+ goto out;
}
- if (AA_MAY_UMOUNT & ~perms.allow)
- error = -EACCES;
+ label_for_each_confined(i, label, profile) {
+ if (profile->policy.dfa) {
+ unsigned int state;
+ state = aa_dfa_match(profile->policy.dfa,
+ profile->policy.start[AA_CLASS_MOUNT],
+ name);
+ perms = compute_mnt_perms(profile->policy.dfa, state);
+ if (AA_MAY_UMOUNT & ~perms.allow)
+ error = -EACCES;
+ } else
+ error = -EACCES;
+ error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL,
+ NULL, NULL, 0, NULL, AA_MAY_UMOUNT, &perms,
+ info, error);
+ if (error)
+ break;
+
+ memset(&perms, 0, sizeof(perms));
+ }
-audit:
- error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
- NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
+out:
kfree(buffer);
return error;
@@ -577,51 +636,69 @@ audit:
int aa_pivotroot(struct aa_label *label, struct path *old_path,
struct path *new_path)
{
- struct aa_profile *profile = labels_profile(label);
+ struct aa_profile *profile;
struct file_perms perms = { };
struct aa_profile *target = NULL;
char *old_buffer = NULL, *new_buffer = NULL;
const char *old_name, *new_name = NULL, *info = NULL;
- int error;
+ int i, error;
- error = aa_path_name(old_path, path_flags(profile, old_path),
+ error = aa_path_name(old_path, path_flags(labels_profile(label),
+ old_path),
&old_buffer, &old_name, &info);
if (error)
- goto audit;
+ goto error;
- error = aa_path_name(new_path, path_flags(profile, new_path),
+ error = aa_path_name(new_path, path_flags(labels_profile(label),
+ new_path),
&new_buffer, &new_name, &info);
if (error)
- goto audit;
-
- if (profile->policy.dfa) {
- unsigned int state;
- state = aa_dfa_match(profile->policy.dfa,
- profile->policy.start[AA_CLASS_MOUNT],
- new_name);
- state = aa_dfa_null_transition(profile->policy.dfa, state);
- state = aa_dfa_match(profile->policy.dfa, state, old_name);
- perms = compute_mnt_perms(profile->policy.dfa, state);
+ goto error;
+
+ label_for_each(i, label, profile) {
+ /* TODO: actual domain transition computation for multiple
+ * profiles
+ */
+ if (profile->policy.dfa) {
+ unsigned int state;
+ state = aa_dfa_match(profile->policy.dfa,
+ profile->policy.start[AA_CLASS_MOUNT],
+ new_name);
+ state = aa_dfa_null_transition(profile->policy.dfa, state);
+ state = aa_dfa_match(profile->policy.dfa, state, old_name);
+ perms = compute_mnt_perms(profile->policy.dfa, state);
+
+ if (AA_MAY_PIVOTROOT & perms.allow) {
+ if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
+ target = x_table_lookup(profile, perms.xindex);
+ if (!target)
+ error = -ENOENT;
+ else
+ error = aa_replace_current_label(&target->label);
+ }
+ }
+ } else
+ error = -EACCES;
+
+ error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
+ old_name, NULL,
+ target ? target->base.name : NULL,
+ 0, NULL, AA_MAY_PIVOTROOT, &perms, info,
+ error);
+ if (error)
+ break;
}
- if (AA_MAY_PIVOTROOT & perms.allow) {
- if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
- target = x_table_lookup(profile, perms.xindex);
- if (!target)
- error = -ENOENT;
- else
- error = aa_replace_current_label(&target->label);
- }
- } else
- error = -EACCES;
-
-audit:
- error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
- old_name, NULL, target ? target->base.name : NULL,
- 0, NULL, AA_MAY_PIVOTROOT, &perms, info, error);
+out:
aa_put_profile(target);
kfree(old_buffer);
kfree(new_buffer);
return error;
+
+error:
+ error = audit_mount(labels_profile(label), GFP_KERNEL, OP_PIVOTROOT, new_name,
+ old_name, NULL, target ? target->base.name : NULL,
+ 0, NULL, AA_MAY_PIVOTROOT, &perms, info, error);
+ goto out;
}
--
1.8.1.2
More information about the AppArmor
mailing list