Skip to content

Commit

Permalink
apparmor: add mount mediation
Browse files Browse the repository at this point in the history
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: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
  • Loading branch information
John Johansen committed Sep 22, 2017
1 parent cd1dbf7 commit 2ea3ffb
Show file tree
Hide file tree
Showing 9 changed files with 841 additions and 4 deletions.
2 changes: 1 addition & 1 deletion security/apparmor/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
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

clean-files := capability_names.h rlim_names.h
Expand Down
8 changes: 7 additions & 1 deletion security/apparmor/apparmorfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
AA_SFS_FILE_BOOLEAN("profile", 1),
AA_SFS_FILE_BOOLEAN("pivot_root", 1),
AA_SFS_FILE_BOOLEAN("pivot_root", 0),
{ }
};

Expand All @@ -2180,6 +2185,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
AA_SFS_DIR("policy", aa_sfs_entry_policy),
AA_SFS_DIR("domain", aa_sfs_entry_domain),
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_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit),
Expand Down
4 changes: 2 additions & 2 deletions security/apparmor/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ static const char *next_name(int xtype, const char *name)
*
* Returns: refcounted label, or NULL on failure (MAYBE NULL)
*/
static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
const char **name)
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
const char **name)
{
struct aa_label *label = NULL;
u32 xtype = xindex & AA_X_TYPE_MASK;
Expand Down
1 change: 1 addition & 0 deletions security/apparmor/include/apparmor.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define AA_CLASS_NET 4
#define AA_CLASS_RLIMITS 5
#define AA_CLASS_DOMAIN 6
#define AA_CLASS_MOUNT 7
#define AA_CLASS_PTRACE 9
#define AA_CLASS_SIGNAL 10
#define AA_CLASS_LABEL 16
Expand Down
11 changes: 11 additions & 0 deletions security/apparmor/include/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ enum audit_type {
#define OP_FMPROT "file_mprotect"
#define OP_INHERIT "file_inherit"

#define OP_PIVOTROOT "pivotroot"
#define OP_MOUNT "mount"
#define OP_UMOUNT "umount"

#define OP_CREATE "create"
#define OP_POST_CREATE "post_create"
#define OP_BIND "bind"
Expand Down Expand Up @@ -132,6 +136,13 @@ struct apparmor_audit_data {
int rlim;
unsigned long max;
} rlim;
struct {
const char *src_name;
const char *type;
const char *trans;
const char *data;
unsigned long flags;
} mnt;
};
};

Expand Down
5 changes: 5 additions & 0 deletions security/apparmor/include/domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <linux/binfmts.h>
#include <linux/types.h>

#include "label.h"

#ifndef __AA_DOMAIN_H
#define __AA_DOMAIN_H

Expand All @@ -29,6 +31,9 @@ struct aa_domain {
#define AA_CHANGE_ONEXEC 4
#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_secureexec(struct linux_binprm *bprm);

Expand Down
54 changes: 54 additions & 0 deletions security/apparmor/include/mount.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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 */
64 changes: 64 additions & 0 deletions security/apparmor/lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "include/policy.h"
#include "include/policy_ns.h"
#include "include/procattr.h"
#include "include/mount.h"

/* Flag indicating whether initialization completed */
int apparmor_initialized;
Expand Down Expand Up @@ -511,6 +512,65 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
!(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,
char **value)
{
Expand Down Expand Up @@ -682,6 +742,10 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(capget, apparmor_capget),
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_unlink, apparmor_path_unlink),
LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
Expand Down
Loading

0 comments on commit 2ea3ffb

Please sign in to comment.