From patchwork Tue May 22 15:22:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Johansen X-Patchwork-Id: 160660 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id D5C0CB6FA5 for ; Wed, 23 May 2012 01:22:47 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SWqv0-0006E5-HW; Tue, 22 May 2012 15:22:38 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SWqux-0006DT-0o for kernel-team@lists.ubuntu.com; Tue, 22 May 2012 15:22:35 +0000 Received: from static-50-53-53-239.bvtn.or.frontiernet.net ([50.53.53.239] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1SWquv-00060f-Mq for kernel-team@lists.ubuntu.com; Tue, 22 May 2012 15:22:34 +0000 From: John Johansen To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/5] Revert "UBUNTU: SAUCE: AppArmor: Add the ability to mediate mount" Date: Tue, 22 May 2012 08:22:17 -0700 Message-Id: <1337700142-13370-2-git-send-email-john.johansen@canonical.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1337700142-13370-1-git-send-email-john.johansen@canonical.com> References: <1337700142-13370-1-git-send-email-john.johansen@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com This reverts commit 2448934c6b2b518b46fa360d6f49f4e78cf03d11. Revert in prepartion for refreshed/updated patch Signed-off-by: John Johansen --- security/apparmor/Makefile | 3 +- security/apparmor/apparmorfs.c | 13 - security/apparmor/audit.c | 4 - security/apparmor/domain.c | 2 +- security/apparmor/include/apparmor.h | 3 +- security/apparmor/include/audit.h | 11 - security/apparmor/include/domain.h | 2 - security/apparmor/include/mount.h | 54 --- security/apparmor/lsm.c | 59 ---- security/apparmor/mount.c | 618 ---------------------------------- 10 files changed, 4 insertions(+), 765 deletions(-) delete mode 100644 security/apparmor/include/mount.h delete mode 100644 security/apparmor/mount.c diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile index f6c51c0..806bd19 100644 --- a/security/apparmor/Makefile +++ b/security/apparmor/Makefile @@ -4,10 +4,11 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ - resource.o sid.o file.o mount.o + resource.o sid.o file.o clean-files := capability_names.h rlim_names.h + # Build a lower case string table of capability names # Transforms lines from # #define CAP_DAC_OVERRIDE 1 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index fbedacb..89bdc62 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -424,22 +424,9 @@ static struct aa_fs_entry aa_fs_entry_domain[] = { { } }; -static struct aa_fs_entry aa_fs_entry_mount[] = { - AA_FS_FILE_STRING("mask", "mount umount"), - { } -}; - -static struct aa_fs_entry aa_fs_entry_namespaces[] = { - AA_FS_FILE_BOOLEAN("profile", 1), - AA_FS_FILE_BOOLEAN("pivot_root", 1), - { } -}; - static struct aa_fs_entry aa_fs_entry_features[] = { AA_FS_DIR("domain", aa_fs_entry_domain), AA_FS_DIR("file", aa_fs_entry_file), - AA_FS_DIR("mount", aa_fs_entry_mount), - AA_FS_DIR("namespaces", aa_fs_entry_namespaces), AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), AA_FS_DIR("rlimit", aa_fs_entry_rlimit), { } diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index b9f5ee9..cc3520d 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -44,10 +44,6 @@ const char *const op_table[] = { "file_mmap", "file_mprotect", - "pivotroot", - "mount", - "umount", - "create", "post_create", "bind", diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index afa8671..b81ea10 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -242,7 +242,7 @@ static const char *next_name(int xtype, const char *name) * * Returns: refcounted profile, or NULL on failure (MAYBE NULL) */ -struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex) +static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex) { struct aa_profile *new_profile = NULL; struct aa_namespace *ns = profile->ns; diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h index e243d96..40aedd9 100644 --- a/security/apparmor/include/apparmor.h +++ b/security/apparmor/include/apparmor.h @@ -29,9 +29,8 @@ #define AA_CLASS_NET 4 #define AA_CLASS_RLIMITS 5 #define AA_CLASS_DOMAIN 6 -#define AA_CLASS_MOUNT 7 -#define AA_CLASS_LAST AA_CLASS_MOUNT +#define AA_CLASS_LAST AA_CLASS_DOMAIN /* Control parameters settable through module/boot flags */ extern enum audit_mode aa_g_audit; diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index 0a04152..3868b1e 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -73,10 +73,6 @@ enum aa_ops { OP_FMMAP, OP_FMPROT, - OP_PIVOTROOT, - OP_MOUNT, - OP_UMOUNT, - OP_CREATE, OP_POST_CREATE, OP_BIND, @@ -125,13 +121,6 @@ struct apparmor_audit_data { unsigned long max; } rlim; struct { - const char *src_name; - const char *type; - const char *trans; - const char *data; - unsigned long flags; - } mnt; - struct { const char *target; u32 request; u32 denied; diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h index a3f70c5..de04464 100644 --- a/security/apparmor/include/domain.h +++ b/security/apparmor/include/domain.h @@ -23,8 +23,6 @@ struct aa_domain { char **table; }; -struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex); - int apparmor_bprm_set_creds(struct linux_binprm *bprm); int apparmor_bprm_secureexec(struct linux_binprm *bprm); void apparmor_bprm_committing_creds(struct linux_binprm *bprm); diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h deleted file mode 100644 index bc17a53..0000000 --- a/security/apparmor/include/mount.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor file mediation function definitions. - * - * Copyright 2012 Canonical Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - */ - -#ifndef __AA_MOUNT_H -#define __AA_MOUNT_H - -#include -#include - -#include "domain.h" -#include "policy.h" - -/* mount perms */ -#define AA_MAY_PIVOTROOT 0x01 -#define AA_MAY_MOUNT 0x02 -#define AA_MAY_UMOUNT 0x04 -#define AA_AUDIT_DATA 0x40 -#define AA_CONT_MATCH 0x40 - -#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN) - -int aa_remount(struct aa_profile *profile, struct path *path, - unsigned long flags, void *data); - -int aa_bind_mount(struct aa_profile *profile, struct path *path, - const char *old_name, unsigned long flags); - - -int aa_mount_change_type(struct aa_profile *profile, struct path *path, - unsigned long flags); - -int aa_move_mount(struct aa_profile *profile, struct path *path, - const char *old_name); - -int aa_new_mount(struct aa_profile *profile, const char *dev_name, - struct path *path, const char *type, unsigned long flags, - void *data); - -int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags); - -int aa_pivotroot(struct aa_profile *profile, struct path *old_path, - struct path *new_path); - -#endif /* __AA_MOUNT_H */ diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 4ef0211..ad05d39 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -35,7 +35,6 @@ #include "include/path.h" #include "include/policy.h" #include "include/procattr.h" -#include "include/mount.h" /* Flag indicating whether initialization completed */ int apparmor_initialized __initdata; @@ -512,60 +511,6 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma, !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); } -static int apparmor_sb_mount(char *dev_name, struct path *path, char *type, - unsigned long flags, void *data) -{ - struct aa_profile *profile; - int error = 0; - - /* Discard magic */ - if ((flags & MS_MGC_MSK) == MS_MGC_VAL) - flags &= ~MS_MGC_MSK; - - flags &= ~AA_MS_IGNORE_MASK; - - profile = __aa_current_profile(); - if (!unconfined(profile)) { - if (flags & MS_REMOUNT) - error = aa_remount(profile, path, flags, data); - else if (flags & MS_BIND) - error = aa_bind_mount(profile, path, dev_name, flags); - else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | - MS_UNBINDABLE)) - error = aa_mount_change_type(profile, path, flags); - else if (flags & MS_MOVE) - error = aa_move_mount(profile, path, dev_name); - else - error = aa_new_mount(profile, dev_name, path, type, - flags, data); - } - return error; -} - -static int apparmor_sb_umount(struct vfsmount *mnt, int flags) -{ - struct aa_profile *profile; - int error = 0; - - profile = __aa_current_profile(); - if (!unconfined(profile)) - error = aa_umount(profile, mnt, flags); - - return error; -} - -static int apparmor_sb_pivotroot(struct path *old_path, struct path *new_path) -{ - struct aa_profile *profile; - int error = 0; - - profile = __aa_current_profile(); - if (!unconfined(profile)) - error = aa_pivotroot(profile, old_path, new_path); - - return error; -} - static int apparmor_getprocattr(struct task_struct *task, char *name, char **value) { @@ -685,10 +630,6 @@ static struct security_operations apparmor_ops = { .capget = apparmor_capget, .capable = apparmor_capable, - .sb_mount = apparmor_sb_mount, - .sb_umount = apparmor_sb_umount, - .sb_pivotroot = apparmor_sb_pivotroot, - .path_link = apparmor_path_link, .path_unlink = apparmor_path_unlink, .path_symlink = apparmor_path_symlink, diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c deleted file mode 100644 index 6523056..0000000 --- a/security/apparmor/mount.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * AppArmor security module - * - * This file contains AppArmor mediation of files - * - * Copyright (C) 1998-2008 Novell/SUSE - * Copyright 2009-2012 Canonical Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - */ - -#include -#include -#include - -#include "include/apparmor.h" -#include "include/audit.h" -#include "include/context.h" -#include "include/domain.h" -#include "include/file.h" -#include "include/match.h" -#include "include/mount.h" -#include "include/path.h" -#include "include/policy.h" - - -static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags) -{ - if (flags & MS_RDONLY) - audit_log_format(ab, "ro"); - else - audit_log_format(ab, "rw"); - if (flags & MS_NOSUID) - audit_log_format(ab, ", nosuid"); - if (flags & MS_NODEV) - audit_log_format(ab, ", nodev"); - if (flags & MS_NOEXEC) - audit_log_format(ab, ", noexec"); - if (flags & MS_SYNCHRONOUS) - audit_log_format(ab, ", sync"); - if (flags & MS_REMOUNT) - audit_log_format(ab, ", remount"); - if (flags & MS_MANDLOCK) - audit_log_format(ab, ", mand"); - if (flags & MS_DIRSYNC) - audit_log_format(ab, ", dirsync"); - if (flags & MS_NOATIME) - audit_log_format(ab, ", noatime"); - if (flags & MS_NODIRATIME) - audit_log_format(ab, ", nodiratime"); - if (flags & MS_BIND) - audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind"); - if (flags & MS_MOVE) - audit_log_format(ab, ", move"); - if (flags & MS_SILENT) - audit_log_format(ab, ", silent"); - if (flags & MS_POSIXACL) - audit_log_format(ab, ", acl"); - if (flags & MS_UNBINDABLE) - audit_log_format(ab, flags & MS_REC ? ", runbindable" : - ", unbindable"); - if (flags & MS_PRIVATE) - audit_log_format(ab, flags & MS_REC ? ", rprivate" : - ", private"); - if (flags & MS_SLAVE) - audit_log_format(ab, flags & MS_REC ? ", rslave" : - ", slave"); - if (flags & MS_SHARED) - audit_log_format(ab, flags & MS_REC ? ", rshared" : - ", shared"); - if (flags & MS_RELATIME) - audit_log_format(ab, ", relatime"); - if (flags & MS_I_VERSION) - audit_log_format(ab, ", iversion"); - if (flags & MS_STRICTATIME) - audit_log_format(ab, ", strictatime"); - if (flags & MS_NOUSER) - audit_log_format(ab, ", nouser"); -} - -/** - * audit_cb - call back for mount specific audit fields - * @ab: audit_buffer (NOT NULL) - * @va: audit struct to audit values of (NOT NULL) - */ -static void audit_cb(struct audit_buffer *ab, void *va) -{ - struct common_audit_data *sa = va; - - if (sa->aad->mnt.type) { - audit_log_format(ab, " fstype="); - audit_log_untrustedstring(ab, sa->aad->mnt.type); - } - if (sa->aad->mnt.src_name) { - audit_log_format(ab, " srcname="); - audit_log_untrustedstring(ab, sa->aad->mnt.src_name); - } - if (sa->aad->mnt.trans) { - audit_log_format(ab, " trans="); - audit_log_untrustedstring(ab, sa->aad->mnt.trans); - } - if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) { - audit_log_format(ab, " flags=\""); - audit_mnt_flags(ab, sa->aad->mnt.flags); - audit_log_format(ab, "\""); - } - if (sa->aad->mnt.data) { - audit_log_format(ab, " options="); - audit_log_untrustedstring(ab, sa->aad->mnt.data); - } -} - -/** - * audit_mount - handle the auditing of mount operations - * @profile: the profile being enforced (NOT NULL) - * @gfp: allocation flags - * @op: operation being mediated (NOT NULL) - * @name: name of object being mediated (MAYBE NULL) - * @src_name: src_name of object being mediated (MAYBE_NULL) - * @type: type of filesystem (MAYBE_NULL) - * @trans: name of trans (MAYBE NULL) - * @flags: filesystem idependent mount flags - * @data: filesystem mount flags - * @request: permissions requested - * @perms: the permissions computed for the request (NOT NULL) - * @info: extra information message (MAYBE NULL) - * @error: 0 if operation allowed else failure error code - * - * Returns: %0 or error on failure - */ -static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op, - const char *name, const char *src_name, - const char *type, const char *trans, - unsigned long flags, const void *data, u32 request, - struct file_perms *perms, const char *info, int error) -{ - int audit_type = AUDIT_APPARMOR_AUTO; - struct common_audit_data sa; - - if (likely(!error)) { - u32 mask = perms->audit; - - if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) - mask = 0xffff; - - /* mask off perms that are not being force audited */ - request &= mask; - - if (likely(!request)) - return 0; - audit_type = AUDIT_APPARMOR_AUDIT; - } else { - /* only report permissions that were denied */ - request = request & ~perms->allow; - - if (request & perms->kill) - audit_type = AUDIT_APPARMOR_KILL; - - /* quiet known rejects, assumes quiet and kill do not overlap */ - if ((request & perms->quiet) && - AUDIT_MODE(profile) != AUDIT_NOQUIET && - AUDIT_MODE(profile) != AUDIT_ALL) - request &= ~perms->quiet; - - if (!request) - return COMPLAIN_MODE(profile) ? - complain_error(error) : error; - } - - COMMON_AUDIT_DATA_INIT(&sa, NONE); - sa.aad->op = op; - sa.aad->name = name; - sa.aad->mnt.src_name = src_name; - sa.aad->mnt.type = type; - sa.aad->mnt.trans = trans; - sa.aad->mnt.flags = flags; - if (data && (perms->audit & AA_AUDIT_DATA)) - sa.aad->mnt.data = data; - sa.aad->info = info; - sa.aad->error = error; - - return aa_audit(audit_type, profile, gfp, &sa, audit_cb); -} - -/** - * match_mnt_flags - Do an ordered match on mount flags - * @dfa: dfa to match against - * @state: state to start in - * @flags: mount flags to match against - * - * Mount flags are encoded as an ordered match. This is done instead of - * checking against a simple bitmask, to allow for logical operations - * on the flags. - * - * Returns: next state after flags match - */ -static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state, - unsigned long flags) -{ - unsigned int i; - - for (i = 0; i <= 31 ; ++i) { - if ((1 << i) & flags) - state = aa_dfa_next(dfa, state, i + 1); - } - - return state; -} - -/** - * compute_mnt_perms - compute mount permission associated with @state - * @dfa: dfa to match against (NOT NULL) - * @state: state match finished in - * - * Returns: mount permissions - */ -static struct file_perms compute_mnt_perms(struct aa_dfa *dfa, - unsigned int state) -{ - struct file_perms perms; - - perms.kill = 0; - perms.allow = dfa_user_allow(dfa, state); - perms.audit = dfa_user_audit(dfa, state); - perms.quiet = dfa_user_quiet(dfa, state); - perms.xindex = dfa_user_xindex(dfa, state); - - return perms; -} - -static const char const *mnt_info_table[] = { - "match succeeded", - "failed mntpnt match", - "failed srcname match", - "failed type match", - "failed flags match", - "failed data match" -}; - -/* - * Returns 0 on success else element that match failed in, this is the - * index into the mnt_info_table above - */ -static int do_match_mnt(struct aa_dfa *dfa, unsigned int start, - const char *mntpnt, const char *devname, - const char *type, unsigned long flags, - void *data, bool binary, struct file_perms *perms) -{ - unsigned int state; - - state = aa_dfa_match(dfa, start, mntpnt); - state = aa_dfa_null_transition(dfa, state); - if (!state) - return 1; - - if (devname) - state = aa_dfa_match(dfa, state, devname); - state = aa_dfa_null_transition(dfa, state); - if (!state) - return 2; - - if (type) - state = aa_dfa_match(dfa, state, type); - state = aa_dfa_null_transition(dfa, state); - if (!state) - return 3; - - state = match_mnt_flags(dfa, state, flags); - if (!state) - return 4; - *perms = compute_mnt_perms(dfa, state); - if (perms->allow & AA_MAY_MOUNT) - return 0; - - /* only match data if not binary and the DFA flags data is expected */ - if (data && !binary && (perms->allow & AA_CONT_MATCH)) { - state = aa_dfa_null_transition(dfa, state); - if (!state) - return 4; - - state = aa_dfa_match(dfa, state, data); - if (!state) - return 5; - *perms = compute_mnt_perms(dfa, state); - if (perms->allow & AA_MAY_MOUNT) - return 0; - } - - /* failed at end of flags match */ - return 4; -} - -/** - * match_mnt - handle path matching for mount - * @profile: the confining profile - * @mntpnt: string for the mntpnt (NOT NULL) - * @devname: string for the devname/src_name (MAYBE NULL) - * @type: string for the dev type (MAYBE NULL) - * @flags: mount flags to match - * @data: fs mount data (MAYBE NULL) - * @binary: whether @data is binary - * @perms: Returns: permission found by the match - * @info: Returns: infomation string about the match for logging - * - * Returns: 0 on success else error - */ -static int match_mnt(struct aa_profile *profile, const char *mntpnt, - const char *devname, const char *type, - unsigned long flags, void *data, bool binary, - struct file_perms *perms, const char **info) -{ - int pos; - - if (!profile->policy.dfa) - return -EACCES; - - pos = do_match_mnt(profile->policy.dfa, - profile->policy.start[AA_CLASS_MOUNT], - mntpnt, devname, type, flags, data, binary, perms); - if (pos) { - *info = mnt_info_table[pos]; - return -EACCES; - } - - return 0; -} - -static int path_flags(struct aa_profile *profile, struct path *path) -{ - return profile->path_flags | - S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0; -} - -int aa_remount(struct aa_profile *profile, struct path *path, - unsigned long flags, void *data) -{ - struct file_perms perms = { }; - const char *name, *info = NULL; - char *buffer = NULL; - int binary, 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 = match_mnt(profile, name, NULL, NULL, flags, data, binary, - &perms, &info); - -audit: - error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL, - NULL, flags, data, AA_MAY_MOUNT, &perms, info, - error); - kfree(buffer); - - return error; -} - -int aa_bind_mount(struct aa_profile *profile, struct path *path, - const char *dev_name, unsigned long flags) -{ - struct file_perms perms = { }; - char *buffer = NULL, *old_buffer = NULL; - const char *name, *old_name = NULL, *info = NULL; - struct path old_path; - int error; - - if (!dev_name || !*dev_name) - return -EINVAL; - - flags &= MS_REC | MS_BIND; - - error = aa_path_name(path, path_flags(profile, path), &buffer, &name, - &info); - if (error) - goto audit; - - error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path); - if (error) - goto audit; - - error = aa_path_name(&old_path, path_flags(profile, &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); - -audit: - error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name, - NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms, - info, error); - kfree(buffer); - kfree(old_buffer); - - return error; -} - -int aa_mount_change_type(struct aa_profile *profile, struct path *path, - unsigned long flags) -{ - struct file_perms perms = { }; - char *buffer = NULL; - const char *name, *info = NULL; - int 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 = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms, - &info); - -audit: - error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL, - NULL, flags, NULL, AA_MAY_MOUNT, &perms, info, - error); - kfree(buffer); - - return error; -} - -int aa_move_mount(struct aa_profile *profile, struct path *path, - const char *orig_name) -{ - struct file_perms perms = { }; - char *buffer = NULL, *old_buffer = NULL; - const char *name, *old_name = NULL, *info = NULL; - struct path old_path; - int error; - - if (!orig_name || !*orig_name) - return -EINVAL; - - error = aa_path_name(path, path_flags(profile, path), &buffer, &name, - &info); - if (error) - goto audit; - - error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); - if (error) - goto audit; - - error = aa_path_name(&old_path, path_flags(profile, &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); - -audit: - error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name, - NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms, - info, error); - kfree(buffer); - kfree(old_buffer); - - return error; -} - -int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name, - struct path *path, const char *type, unsigned long flags, - void *data) -{ - struct file_perms perms = { }; - char *buffer = NULL, *dev_buffer = NULL; - const char *name = NULL, *dev_name = NULL, *info = NULL; - int binary = 1; - int error; - - dev_name = orig_dev_name; - if (type) { - int requires_dev; - struct file_system_type *fstype = get_fs_type(type); - if (!fstype) - return -ENODEV; - - binary = fstype->fs_flags & FS_BINARY_MOUNTDATA; - requires_dev = fstype->fs_flags & FS_REQUIRES_DEV; - put_filesystem(fstype); - - if (requires_dev) { - struct path dev_path; - - if (!dev_name || !*dev_name) { - error = -ENOENT; - goto out; - } - - error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path); - if (error) - goto audit; - - error = aa_path_name(&dev_path, - path_flags(profile, &dev_path), - &dev_buffer, &dev_name, &info); - path_put(&dev_path); - if (error) - goto audit; - } - } - - error = aa_path_name(path, path_flags(profile, path), &buffer, &name, - &info); - if (error) - goto audit; - - error = match_mnt(profile, name, dev_name, type, flags, data, binary, - &perms, &info); - -audit: - error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, dev_name, - type, NULL, flags, data, AA_MAY_MOUNT, &perms, info, - error); - kfree(buffer); - kfree(dev_buffer); - -out: - return error; - -} - -int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags) -{ - struct file_perms perms = { }; - char *buffer = NULL; - const char *name, *info = NULL; - int 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); - } - - if (AA_MAY_UMOUNT & ~perms.allow) - error = -EACCES; - -audit: - error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL, - NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error); - kfree(buffer); - - return error; -} - -int aa_pivotroot(struct aa_profile *profile, struct path *old_path, - struct path *new_path) -{ - 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; - - error = aa_path_name(old_path, path_flags(profile, old_path), - &old_buffer, &old_name, &info); - if (error) - goto audit; - - error = aa_path_name(new_path, path_flags(profile, 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); - } - - 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_profile(target); - } - } 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); - aa_put_profile(target); - kfree(old_buffer); - kfree(new_buffer); - - return error; -}