Skip to content

Commit 2ea3ffb

Browse files
committed
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: John Johansen <john.johansen@canonical.com> Acked-by: Seth Arnold <seth.arnold@canonical.com>
1 parent cd1dbf7 commit 2ea3ffb

File tree

9 files changed

+841
-4
lines changed

9 files changed

+841
-4
lines changed

security/apparmor/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
44

55
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
66
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
7-
resource.o secid.o file.o policy_ns.o label.o
7+
resource.o secid.o file.o policy_ns.o label.o mount.o
88
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
99

1010
clean-files := capability_names.h rlim_names.h

security/apparmor/apparmorfs.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2159,9 +2159,14 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
21592159
{ }
21602160
};
21612161

2162+
static struct aa_sfs_entry aa_sfs_entry_mount[] = {
2163+
AA_SFS_FILE_STRING("mask", "mount umount pivot_root"),
2164+
{ }
2165+
};
2166+
21622167
static struct aa_sfs_entry aa_sfs_entry_ns[] = {
21632168
AA_SFS_FILE_BOOLEAN("profile", 1),
2164-
AA_SFS_FILE_BOOLEAN("pivot_root", 1),
2169+
AA_SFS_FILE_BOOLEAN("pivot_root", 0),
21652170
{ }
21662171
};
21672172

@@ -2180,6 +2185,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
21802185
AA_SFS_DIR("policy", aa_sfs_entry_policy),
21812186
AA_SFS_DIR("domain", aa_sfs_entry_domain),
21822187
AA_SFS_DIR("file", aa_sfs_entry_file),
2188+
AA_SFS_DIR("mount", aa_sfs_entry_mount),
21832189
AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
21842190
AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
21852191
AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit),

security/apparmor/domain.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,8 @@ static const char *next_name(int xtype, const char *name)
374374
*
375375
* Returns: refcounted label, or NULL on failure (MAYBE NULL)
376376
*/
377-
static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
378-
const char **name)
377+
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
378+
const char **name)
379379
{
380380
struct aa_label *label = NULL;
381381
u32 xtype = xindex & AA_X_TYPE_MASK;

security/apparmor/include/apparmor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define AA_CLASS_NET 4
2828
#define AA_CLASS_RLIMITS 5
2929
#define AA_CLASS_DOMAIN 6
30+
#define AA_CLASS_MOUNT 7
3031
#define AA_CLASS_PTRACE 9
3132
#define AA_CLASS_SIGNAL 10
3233
#define AA_CLASS_LABEL 16

security/apparmor/include/audit.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ enum audit_type {
7171
#define OP_FMPROT "file_mprotect"
7272
#define OP_INHERIT "file_inherit"
7373

74+
#define OP_PIVOTROOT "pivotroot"
75+
#define OP_MOUNT "mount"
76+
#define OP_UMOUNT "umount"
77+
7478
#define OP_CREATE "create"
7579
#define OP_POST_CREATE "post_create"
7680
#define OP_BIND "bind"
@@ -132,6 +136,13 @@ struct apparmor_audit_data {
132136
int rlim;
133137
unsigned long max;
134138
} rlim;
139+
struct {
140+
const char *src_name;
141+
const char *type;
142+
const char *trans;
143+
const char *data;
144+
unsigned long flags;
145+
} mnt;
135146
};
136147
};
137148

security/apparmor/include/domain.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <linux/binfmts.h>
1616
#include <linux/types.h>
1717

18+
#include "label.h"
19+
1820
#ifndef __AA_DOMAIN_H
1921
#define __AA_DOMAIN_H
2022

@@ -29,6 +31,9 @@ struct aa_domain {
2931
#define AA_CHANGE_ONEXEC 4
3032
#define AA_CHANGE_STACK 8
3133

34+
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
35+
const char **name);
36+
3237
int apparmor_bprm_set_creds(struct linux_binprm *bprm);
3338
int apparmor_bprm_secureexec(struct linux_binprm *bprm);
3439

security/apparmor/include/mount.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* AppArmor security module
3+
*
4+
* This file contains AppArmor file mediation function definitions.
5+
*
6+
* Copyright 2017 Canonical Ltd.
7+
*
8+
* This program is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU General Public License as
10+
* published by the Free Software Foundation, version 2 of the
11+
* License.
12+
*/
13+
14+
#ifndef __AA_MOUNT_H
15+
#define __AA_MOUNT_H
16+
17+
#include <linux/fs.h>
18+
#include <linux/path.h>
19+
20+
#include "domain.h"
21+
#include "policy.h"
22+
23+
/* mount perms */
24+
#define AA_MAY_PIVOTROOT 0x01
25+
#define AA_MAY_MOUNT 0x02
26+
#define AA_MAY_UMOUNT 0x04
27+
#define AA_AUDIT_DATA 0x40
28+
#define AA_MNT_CONT_MATCH 0x40
29+
30+
#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
31+
32+
int aa_remount(struct aa_label *label, const struct path *path,
33+
unsigned long flags, void *data);
34+
35+
int aa_bind_mount(struct aa_label *label, const struct path *path,
36+
const char *old_name, unsigned long flags);
37+
38+
39+
int aa_mount_change_type(struct aa_label *label, const struct path *path,
40+
unsigned long flags);
41+
42+
int aa_move_mount(struct aa_label *label, const struct path *path,
43+
const char *old_name);
44+
45+
int aa_new_mount(struct aa_label *label, const char *dev_name,
46+
const struct path *path, const char *type, unsigned long flags,
47+
void *data);
48+
49+
int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags);
50+
51+
int aa_pivotroot(struct aa_label *label, const struct path *old_path,
52+
const struct path *new_path);
53+
54+
#endif /* __AA_MOUNT_H */

security/apparmor/lsm.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "include/policy.h"
3939
#include "include/policy_ns.h"
4040
#include "include/procattr.h"
41+
#include "include/mount.h"
4142

4243
/* Flag indicating whether initialization completed */
4344
int apparmor_initialized;
@@ -511,6 +512,65 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
511512
!(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
512513
}
513514

515+
static int apparmor_sb_mount(const char *dev_name, const struct path *path,
516+
const char *type, unsigned long flags, void *data)
517+
{
518+
struct aa_label *label;
519+
int error = 0;
520+
521+
/* Discard magic */
522+
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
523+
flags &= ~MS_MGC_MSK;
524+
525+
flags &= ~AA_MS_IGNORE_MASK;
526+
527+
label = __begin_current_label_crit_section();
528+
if (!unconfined(label)) {
529+
if (flags & MS_REMOUNT)
530+
error = aa_remount(label, path, flags, data);
531+
else if (flags & MS_BIND)
532+
error = aa_bind_mount(label, path, dev_name, flags);
533+
else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
534+
MS_UNBINDABLE))
535+
error = aa_mount_change_type(label, path, flags);
536+
else if (flags & MS_MOVE)
537+
error = aa_move_mount(label, path, dev_name);
538+
else
539+
error = aa_new_mount(label, dev_name, path, type,
540+
flags, data);
541+
}
542+
__end_current_label_crit_section(label);
543+
544+
return error;
545+
}
546+
547+
static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
548+
{
549+
struct aa_label *label;
550+
int error = 0;
551+
552+
label = __begin_current_label_crit_section();
553+
if (!unconfined(label))
554+
error = aa_umount(label, mnt, flags);
555+
__end_current_label_crit_section(label);
556+
557+
return error;
558+
}
559+
560+
static int apparmor_sb_pivotroot(const struct path *old_path,
561+
const struct path *new_path)
562+
{
563+
struct aa_label *label;
564+
int error = 0;
565+
566+
label = aa_get_current_label();
567+
if (!unconfined(label))
568+
error = aa_pivotroot(label, old_path, new_path);
569+
aa_put_label(label);
570+
571+
return error;
572+
}
573+
514574
static int apparmor_getprocattr(struct task_struct *task, char *name,
515575
char **value)
516576
{
@@ -682,6 +742,10 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
682742
LSM_HOOK_INIT(capget, apparmor_capget),
683743
LSM_HOOK_INIT(capable, apparmor_capable),
684744

745+
LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
746+
LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
747+
LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
748+
685749
LSM_HOOK_INIT(path_link, apparmor_path_link),
686750
LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
687751
LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),

0 commit comments

Comments
 (0)