Commit 2ea3ffb7 authored by John Johansen's avatar John Johansen

apparmor: add mount mediation

Add basic mount mediation. That allows controlling based on basic
mount parameters. It does not include special mount parameters for
apparmor, super block labeling, or any triggers for apparmor namespace
parameter modifications on pivot root.

default userspace policy rules have the form of
  MOUNT RULE = ( MOUNT | REMOUNT | UMOUNT )

  MOUNT = [ QUALIFIERS ] 'mount' [ MOUNT CONDITIONS ] [ SOURCE FILEGLOB ]
          [ '->' MOUNTPOINT FILEGLOB ]

  REMOUNT = [ QUALIFIERS ] 'remount' [ MOUNT CONDITIONS ]
            MOUNTPOINT FILEGLOB

  UMOUNT = [ QUALIFIERS ] 'umount' [ MOUNT CONDITIONS ] MOUNTPOINT FILEGLOB

  MOUNT CONDITIONS = [ ( 'fstype' | 'vfstype' ) ( '=' | 'in' )
                       MOUNT FSTYPE EXPRESSION ]
		       [ 'options' ( '=' | 'in' ) MOUNT FLAGS EXPRESSION ]

  MOUNT FSTYPE EXPRESSION = ( MOUNT FSTYPE LIST | MOUNT EXPRESSION )

  MOUNT FSTYPE LIST = Comma separated list of valid filesystem and
                      virtual filesystem types (eg ext4, debugfs, etc)

  MOUNT FLAGS EXPRESSION = ( MOUNT FLAGS LIST | MOUNT EXPRESSION )

  MOUNT FLAGS LIST = Comma separated list of MOUNT FLAGS.

  MOUNT FLAGS = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' |
                  'noexec' | 'exec' | 'sync' | 'async' | 'remount' |
		  'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' |
		  'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' |
		  'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' |
		  'unbindable' | 'runbindable' | 'private' | 'rprivate' |
		  'slave' | 'rslave' | 'shared' | 'rshared' |
		  'relatime' | 'norelatime' | 'iversion' | 'noiversion' |
		  'strictatime' | 'nouser' | 'user' )

  MOUNT EXPRESSION = ( ALPHANUMERIC | AARE ) ...

  PIVOT ROOT RULE = [ QUALIFIERS ] pivot_root [ oldroot=OLD PUT FILEGLOB ]
                    [ NEW ROOT FILEGLOB ]

  SOURCE FILEGLOB = FILEGLOB

  MOUNTPOINT FILEGLOB = FILEGLOB

eg.
  mount,
  mount /dev/foo,
  mount options=ro /dev/foo -> /mnt/,
  mount options in (ro,atime) /dev/foo -> /mnt/,
  mount options=ro options=atime,
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
Acked-by: default avatarSeth Arnold <seth.arnold@canonical.com>
parent cd1dbf76
...@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o ...@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.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 \ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
resource.o secid.o file.o policy_ns.o label.o resource.o secid.o file.o policy_ns.o label.o mount.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
clean-files := capability_names.h rlim_names.h clean-files := capability_names.h rlim_names.h
......
...@@ -2159,9 +2159,14 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = { ...@@ -2159,9 +2159,14 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
{ } { }
}; };
static struct aa_sfs_entry aa_sfs_entry_mount[] = {
AA_SFS_FILE_STRING("mask", "mount umount pivot_root"),
{ }
};
static struct aa_sfs_entry aa_sfs_entry_ns[] = { static struct aa_sfs_entry aa_sfs_entry_ns[] = {
AA_SFS_FILE_BOOLEAN("profile", 1), AA_SFS_FILE_BOOLEAN("profile", 1),
AA_SFS_FILE_BOOLEAN("pivot_root", 1), AA_SFS_FILE_BOOLEAN("pivot_root", 0),
{ } { }
}; };
...@@ -2180,6 +2185,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { ...@@ -2180,6 +2185,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
AA_SFS_DIR("policy", aa_sfs_entry_policy), AA_SFS_DIR("policy", aa_sfs_entry_policy),
AA_SFS_DIR("domain", aa_sfs_entry_domain), AA_SFS_DIR("domain", aa_sfs_entry_domain),
AA_SFS_DIR("file", aa_sfs_entry_file), AA_SFS_DIR("file", aa_sfs_entry_file),
AA_SFS_DIR("mount", aa_sfs_entry_mount),
AA_SFS_DIR("namespaces", aa_sfs_entry_ns), AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit),
......
...@@ -374,7 +374,7 @@ static const char *next_name(int xtype, const char *name) ...@@ -374,7 +374,7 @@ static const char *next_name(int xtype, const char *name)
* *
* Returns: refcounted label, or NULL on failure (MAYBE NULL) * Returns: refcounted label, or NULL on failure (MAYBE NULL)
*/ */
static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
const char **name) const char **name)
{ {
struct aa_label *label = NULL; struct aa_label *label = NULL;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define AA_CLASS_NET 4 #define AA_CLASS_NET 4
#define AA_CLASS_RLIMITS 5 #define AA_CLASS_RLIMITS 5
#define AA_CLASS_DOMAIN 6 #define AA_CLASS_DOMAIN 6
#define AA_CLASS_MOUNT 7
#define AA_CLASS_PTRACE 9 #define AA_CLASS_PTRACE 9
#define AA_CLASS_SIGNAL 10 #define AA_CLASS_SIGNAL 10
#define AA_CLASS_LABEL 16 #define AA_CLASS_LABEL 16
......
...@@ -71,6 +71,10 @@ enum audit_type { ...@@ -71,6 +71,10 @@ enum audit_type {
#define OP_FMPROT "file_mprotect" #define OP_FMPROT "file_mprotect"
#define OP_INHERIT "file_inherit" #define OP_INHERIT "file_inherit"
#define OP_PIVOTROOT "pivotroot"
#define OP_MOUNT "mount"
#define OP_UMOUNT "umount"
#define OP_CREATE "create" #define OP_CREATE "create"
#define OP_POST_CREATE "post_create" #define OP_POST_CREATE "post_create"
#define OP_BIND "bind" #define OP_BIND "bind"
...@@ -132,6 +136,13 @@ struct apparmor_audit_data { ...@@ -132,6 +136,13 @@ struct apparmor_audit_data {
int rlim; int rlim;
unsigned long max; unsigned long max;
} rlim; } rlim;
struct {
const char *src_name;
const char *type;
const char *trans;
const char *data;
unsigned long flags;
} mnt;
}; };
}; };
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/binfmts.h> #include <linux/binfmts.h>
#include <linux/types.h> #include <linux/types.h>
#include "label.h"
#ifndef __AA_DOMAIN_H #ifndef __AA_DOMAIN_H
#define __AA_DOMAIN_H #define __AA_DOMAIN_H
...@@ -29,6 +31,9 @@ struct aa_domain { ...@@ -29,6 +31,9 @@ struct aa_domain {
#define AA_CHANGE_ONEXEC 4 #define AA_CHANGE_ONEXEC 4
#define AA_CHANGE_STACK 8 #define AA_CHANGE_STACK 8
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
const char **name);
int apparmor_bprm_set_creds(struct linux_binprm *bprm); int apparmor_bprm_set_creds(struct linux_binprm *bprm);
int apparmor_bprm_secureexec(struct linux_binprm *bprm); int apparmor_bprm_secureexec(struct linux_binprm *bprm);
......
/*
* AppArmor security module
*
* This file contains AppArmor file mediation function definitions.
*
* Copyright 2017 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 <linux/fs.h>
#include <linux/path.h>
#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_MNT_CONT_MATCH 0x40
#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
int aa_remount(struct aa_label *label, const struct path *path,
unsigned long flags, void *data);
int aa_bind_mount(struct aa_label *label, const struct path *path,
const char *old_name, unsigned long flags);
int aa_mount_change_type(struct aa_label *label, const struct path *path,
unsigned long flags);
int aa_move_mount(struct aa_label *label, const struct path *path,
const char *old_name);
int aa_new_mount(struct aa_label *label, const char *dev_name,
const struct path *path, const char *type, unsigned long flags,
void *data);
int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags);
int aa_pivotroot(struct aa_label *label, const struct path *old_path,
const struct path *new_path);
#endif /* __AA_MOUNT_H */
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "include/policy.h" #include "include/policy.h"
#include "include/policy_ns.h" #include "include/policy_ns.h"
#include "include/procattr.h" #include "include/procattr.h"
#include "include/mount.h"
/* Flag indicating whether initialization completed */ /* Flag indicating whether initialization completed */
int apparmor_initialized; int apparmor_initialized;
...@@ -511,6 +512,65 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma, ...@@ -511,6 +512,65 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
!(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
} }
static int apparmor_sb_mount(const char *dev_name, const struct path *path,
const char *type, unsigned long flags, void *data)
{
struct aa_label *label;
int error = 0;
/* Discard magic */
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
flags &= ~MS_MGC_MSK;
flags &= ~AA_MS_IGNORE_MASK;
label = __begin_current_label_crit_section();
if (!unconfined(label)) {
if (flags & MS_REMOUNT)
error = aa_remount(label, path, flags, data);
else if (flags & MS_BIND)
error = aa_bind_mount(label, path, dev_name, flags);
else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
MS_UNBINDABLE))
error = aa_mount_change_type(label, path, flags);
else if (flags & MS_MOVE)
error = aa_move_mount(label, path, dev_name);
else
error = aa_new_mount(label, dev_name, path, type,
flags, data);
}
__end_current_label_crit_section(label);
return error;
}
static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
{
struct aa_label *label;
int error = 0;
label = __begin_current_label_crit_section();
if (!unconfined(label))
error = aa_umount(label, mnt, flags);
__end_current_label_crit_section(label);
return error;
}
static int apparmor_sb_pivotroot(const struct path *old_path,
const struct path *new_path)
{
struct aa_label *label;
int error = 0;
label = aa_get_current_label();
if (!unconfined(label))
error = aa_pivotroot(label, old_path, new_path);
aa_put_label(label);
return error;
}
static int apparmor_getprocattr(struct task_struct *task, char *name, static int apparmor_getprocattr(struct task_struct *task, char *name,
char **value) char **value)
{ {
...@@ -682,6 +742,10 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { ...@@ -682,6 +742,10 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(capget, apparmor_capget), LSM_HOOK_INIT(capget, apparmor_capget),
LSM_HOOK_INIT(capable, apparmor_capable), LSM_HOOK_INIT(capable, apparmor_capable),
LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
LSM_HOOK_INIT(path_link, apparmor_path_link), LSM_HOOK_INIT(path_link, apparmor_path_link),
LSM_HOOK_INIT(path_unlink, apparmor_path_unlink), LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
LSM_HOOK_INIT(path_symlink, apparmor_path_symlink), LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment