[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