1
From 883574b10ad78766ca48a7eb11082dc21597c583 Mon Sep 17 00:00:00 2001
2
From: John Johansen <john.johansen@canonical.com>
3
Date: Wed, 16 May 2012 10:58:05 -0700
4
Subject: [PATCH 4/4] UBUNTU: SAUCE: apparmor: Add the ability to mediate mount
6
Add the ability for apparmor to do mediation of mount operations. Mount
7
rules require an updated apparmor_parser (2.8 series) for policy compilation.
9
The basic form of the rules are.
11
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
12
[audit] [deny] remount [conds]* [path],
13
[audit] [deny] umount [conds]* [path],
14
[audit] [deny] pivotroot [oldroot=<value>] <path>
16
remount is just a short cut for mount options=remount
22
Example mount commands
23
mount, # allow all mounts, but not umount or pivotroot
25
mount fstype=procfs, # allow mounting procfs anywhere
27
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
29
mount /dev/sda -> /mnt,
31
mount /dev/sd** -> /mnt/**,
33
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/
39
See the apparmor userspace for full documentation
41
Signed-off-by: John Johansen <john.johansen@canonical.com>
42
Acked-by: Kees Cook <kees@ubuntu.com>
44
security/apparmor/Makefile | 2 +-
45
security/apparmor/apparmorfs.c | 13 +
46
security/apparmor/audit.c | 4 +
47
security/apparmor/domain.c | 2 +-
48
security/apparmor/include/apparmor.h | 3 +-
49
security/apparmor/include/audit.h | 11 +
50
security/apparmor/include/domain.h | 2 +
51
security/apparmor/include/mount.h | 54 +++
52
security/apparmor/lsm.c | 59 ++++
53
security/apparmor/mount.c | 620 +++++++++++++++++++++++++++++++++++
54
10 files changed, 767 insertions(+), 3 deletions(-)
55
create mode 100644 security/apparmor/include/mount.h
56
create mode 100644 security/apparmor/mount.c
58
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
59
index e270692..9b44e1a 100644
60
--- a/security/apparmor/Makefile
61
+++ b/security/apparmor/Makefile
62
@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
64
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
65
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
66
- resource.o sid.o file.o net.o
67
+ resource.o sid.o file.o net.o mount.o
69
clean-files := capability_names.h rlim_names.h net_names.h
71
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
72
index 114fb23..ee77ec9 100644
73
--- a/security/apparmor/apparmorfs.c
74
+++ b/security/apparmor/apparmorfs.c
75
@@ -426,10 +426,23 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
79
+static struct aa_fs_entry aa_fs_entry_mount[] = {
80
+ AA_FS_FILE_STRING("mask", "mount umount"),
84
+static struct aa_fs_entry aa_fs_entry_namespaces[] = {
85
+ AA_FS_FILE_BOOLEAN("profile", 1),
86
+ AA_FS_FILE_BOOLEAN("pivot_root", 1),
90
static struct aa_fs_entry aa_fs_entry_features[] = {
91
AA_FS_DIR("domain", aa_fs_entry_domain),
92
AA_FS_DIR("file", aa_fs_entry_file),
93
AA_FS_DIR("network", aa_fs_entry_network),
94
+ AA_FS_DIR("mount", aa_fs_entry_mount),
95
+ AA_FS_DIR("namespaces", aa_fs_entry_namespaces),
96
AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
97
AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
99
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
100
index 3ae28db..e267963 100644
101
--- a/security/apparmor/audit.c
102
+++ b/security/apparmor/audit.c
103
@@ -44,6 +44,10 @@ const char *const op_table[] = {
114
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
115
index 859abda..3fee1fe 100644
116
--- a/security/apparmor/domain.c
117
+++ b/security/apparmor/domain.c
118
@@ -242,7 +242,7 @@ static const char *next_name(int xtype, const char *name)
120
* Returns: refcounted profile, or NULL on failure (MAYBE NULL)
122
-static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
123
+struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
125
struct aa_profile *new_profile = NULL;
126
struct aa_namespace *ns = profile->ns;
127
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
128
index 40aedd9..e243d96 100644
129
--- a/security/apparmor/include/apparmor.h
130
+++ b/security/apparmor/include/apparmor.h
132
#define AA_CLASS_NET 4
133
#define AA_CLASS_RLIMITS 5
134
#define AA_CLASS_DOMAIN 6
135
+#define AA_CLASS_MOUNT 7
137
-#define AA_CLASS_LAST AA_CLASS_DOMAIN
138
+#define AA_CLASS_LAST AA_CLASS_MOUNT
140
/* Control parameters settable through module/boot flags */
141
extern enum audit_mode aa_g_audit;
142
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
143
index 4af6523..ada004d 100644
144
--- a/security/apparmor/include/audit.h
145
+++ b/security/apparmor/include/audit.h
146
@@ -73,6 +73,10 @@ enum aa_ops {
157
@@ -122,6 +126,13 @@ struct apparmor_audit_data {
161
+ const char *src_name;
165
+ unsigned long flags;
171
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
172
index de04464..a3f70c5 100644
173
--- a/security/apparmor/include/domain.h
174
+++ b/security/apparmor/include/domain.h
175
@@ -23,6 +23,8 @@ struct aa_domain {
179
+struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
181
int apparmor_bprm_set_creds(struct linux_binprm *bprm);
182
int apparmor_bprm_secureexec(struct linux_binprm *bprm);
183
void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
184
diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
186
index 0000000..bc17a53
188
+++ b/security/apparmor/include/mount.h
191
+ * AppArmor security module
193
+ * This file contains AppArmor file mediation function definitions.
195
+ * Copyright 2012 Canonical Ltd.
197
+ * This program is free software; you can redistribute it and/or
198
+ * modify it under the terms of the GNU General Public License as
199
+ * published by the Free Software Foundation, version 2 of the
203
+#ifndef __AA_MOUNT_H
204
+#define __AA_MOUNT_H
206
+#include <linux/fs.h>
207
+#include <linux/path.h>
213
+#define AA_MAY_PIVOTROOT 0x01
214
+#define AA_MAY_MOUNT 0x02
215
+#define AA_MAY_UMOUNT 0x04
216
+#define AA_AUDIT_DATA 0x40
217
+#define AA_CONT_MATCH 0x40
219
+#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
221
+int aa_remount(struct aa_profile *profile, struct path *path,
222
+ unsigned long flags, void *data);
224
+int aa_bind_mount(struct aa_profile *profile, struct path *path,
225
+ const char *old_name, unsigned long flags);
228
+int aa_mount_change_type(struct aa_profile *profile, struct path *path,
229
+ unsigned long flags);
231
+int aa_move_mount(struct aa_profile *profile, struct path *path,
232
+ const char *old_name);
234
+int aa_new_mount(struct aa_profile *profile, const char *dev_name,
235
+ struct path *path, const char *type, unsigned long flags,
238
+int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
240
+int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
241
+ struct path *new_path);
243
+#endif /* __AA_MOUNT_H */
244
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
245
index 1bce440..6750673 100644
246
--- a/security/apparmor/lsm.c
247
+++ b/security/apparmor/lsm.c
249
#include "include/path.h"
250
#include "include/policy.h"
251
#include "include/procattr.h"
252
+#include "include/mount.h"
254
/* Flag indicating whether initialization completed */
255
int apparmor_initialized __initdata;
256
@@ -504,6 +505,60 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
257
!(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
260
+static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
261
+ unsigned long flags, void *data)
263
+ struct aa_profile *profile;
266
+ /* Discard magic */
267
+ if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
268
+ flags &= ~MS_MGC_MSK;
270
+ flags &= ~AA_MS_IGNORE_MASK;
272
+ profile = __aa_current_profile();
273
+ if (!unconfined(profile)) {
274
+ if (flags & MS_REMOUNT)
275
+ error = aa_remount(profile, path, flags, data);
276
+ else if (flags & MS_BIND)
277
+ error = aa_bind_mount(profile, path, dev_name, flags);
278
+ else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
280
+ error = aa_mount_change_type(profile, path, flags);
281
+ else if (flags & MS_MOVE)
282
+ error = aa_move_mount(profile, path, dev_name);
284
+ error = aa_new_mount(profile, dev_name, path, type,
290
+static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
292
+ struct aa_profile *profile;
295
+ profile = __aa_current_profile();
296
+ if (!unconfined(profile))
297
+ error = aa_umount(profile, mnt, flags);
302
+static int apparmor_sb_pivotroot(struct path *old_path, struct path *new_path)
304
+ struct aa_profile *profile;
307
+ profile = __aa_current_profile();
308
+ if (!unconfined(profile))
309
+ error = aa_pivotroot(profile, old_path, new_path);
314
static int apparmor_getprocattr(struct task_struct *task, char *name,
317
@@ -721,6 +776,10 @@ static struct security_operations apparmor_ops = {
318
.capget = apparmor_capget,
319
.capable = apparmor_capable,
321
+ .sb_mount = apparmor_sb_mount,
322
+ .sb_umount = apparmor_sb_umount,
323
+ .sb_pivotroot = apparmor_sb_pivotroot,
325
.path_link = apparmor_path_link,
326
.path_unlink = apparmor_path_unlink,
327
.path_symlink = apparmor_path_symlink,
328
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
330
index 0000000..478aa4d
332
+++ b/security/apparmor/mount.c
335
+ * AppArmor security module
337
+ * This file contains AppArmor mediation of files
339
+ * Copyright (C) 1998-2008 Novell/SUSE
340
+ * Copyright 2009-2012 Canonical Ltd.
342
+ * This program is free software; you can redistribute it and/or
343
+ * modify it under the terms of the GNU General Public License as
344
+ * published by the Free Software Foundation, version 2 of the
348
+#include <linux/fs.h>
349
+#include <linux/mount.h>
350
+#include <linux/namei.h>
352
+#include "include/apparmor.h"
353
+#include "include/audit.h"
354
+#include "include/context.h"
355
+#include "include/domain.h"
356
+#include "include/file.h"
357
+#include "include/match.h"
358
+#include "include/mount.h"
359
+#include "include/path.h"
360
+#include "include/policy.h"
363
+static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
365
+ if (flags & MS_RDONLY)
366
+ audit_log_format(ab, "ro");
368
+ audit_log_format(ab, "rw");
369
+ if (flags & MS_NOSUID)
370
+ audit_log_format(ab, ", nosuid");
371
+ if (flags & MS_NODEV)
372
+ audit_log_format(ab, ", nodev");
373
+ if (flags & MS_NOEXEC)
374
+ audit_log_format(ab, ", noexec");
375
+ if (flags & MS_SYNCHRONOUS)
376
+ audit_log_format(ab, ", sync");
377
+ if (flags & MS_REMOUNT)
378
+ audit_log_format(ab, ", remount");
379
+ if (flags & MS_MANDLOCK)
380
+ audit_log_format(ab, ", mand");
381
+ if (flags & MS_DIRSYNC)
382
+ audit_log_format(ab, ", dirsync");
383
+ if (flags & MS_NOATIME)
384
+ audit_log_format(ab, ", noatime");
385
+ if (flags & MS_NODIRATIME)
386
+ audit_log_format(ab, ", nodiratime");
387
+ if (flags & MS_BIND)
388
+ audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
389
+ if (flags & MS_MOVE)
390
+ audit_log_format(ab, ", move");
391
+ if (flags & MS_SILENT)
392
+ audit_log_format(ab, ", silent");
393
+ if (flags & MS_POSIXACL)
394
+ audit_log_format(ab, ", acl");
395
+ if (flags & MS_UNBINDABLE)
396
+ audit_log_format(ab, flags & MS_REC ? ", runbindable" :
398
+ if (flags & MS_PRIVATE)
399
+ audit_log_format(ab, flags & MS_REC ? ", rprivate" :
401
+ if (flags & MS_SLAVE)
402
+ audit_log_format(ab, flags & MS_REC ? ", rslave" :
404
+ if (flags & MS_SHARED)
405
+ audit_log_format(ab, flags & MS_REC ? ", rshared" :
407
+ if (flags & MS_RELATIME)
408
+ audit_log_format(ab, ", relatime");
409
+ if (flags & MS_I_VERSION)
410
+ audit_log_format(ab, ", iversion");
411
+ if (flags & MS_STRICTATIME)
412
+ audit_log_format(ab, ", strictatime");
413
+ if (flags & MS_NOUSER)
414
+ audit_log_format(ab, ", nouser");
418
+ * audit_cb - call back for mount specific audit fields
419
+ * @ab: audit_buffer (NOT NULL)
420
+ * @va: audit struct to audit values of (NOT NULL)
422
+static void audit_cb(struct audit_buffer *ab, void *va)
424
+ struct common_audit_data *sa = va;
426
+ if (sa->aad->mnt.type) {
427
+ audit_log_format(ab, " fstype=");
428
+ audit_log_untrustedstring(ab, sa->aad->mnt.type);
430
+ if (sa->aad->mnt.src_name) {
431
+ audit_log_format(ab, " srcname=");
432
+ audit_log_untrustedstring(ab, sa->aad->mnt.src_name);
434
+ if (sa->aad->mnt.trans) {
435
+ audit_log_format(ab, " trans=");
436
+ audit_log_untrustedstring(ab, sa->aad->mnt.trans);
438
+ if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) {
439
+ audit_log_format(ab, " flags=\"");
440
+ audit_mnt_flags(ab, sa->aad->mnt.flags);
441
+ audit_log_format(ab, "\"");
443
+ if (sa->aad->mnt.data) {
444
+ audit_log_format(ab, " options=");
445
+ audit_log_untrustedstring(ab, sa->aad->mnt.data);
450
+ * audit_mount - handle the auditing of mount operations
451
+ * @profile: the profile being enforced (NOT NULL)
452
+ * @gfp: allocation flags
453
+ * @op: operation being mediated (NOT NULL)
454
+ * @name: name of object being mediated (MAYBE NULL)
455
+ * @src_name: src_name of object being mediated (MAYBE_NULL)
456
+ * @type: type of filesystem (MAYBE_NULL)
457
+ * @trans: name of trans (MAYBE NULL)
458
+ * @flags: filesystem idependent mount flags
459
+ * @data: filesystem mount flags
460
+ * @request: permissions requested
461
+ * @perms: the permissions computed for the request (NOT NULL)
462
+ * @info: extra information message (MAYBE NULL)
463
+ * @error: 0 if operation allowed else failure error code
465
+ * Returns: %0 or error on failure
467
+static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op,
468
+ const char *name, const char *src_name,
469
+ const char *type, const char *trans,
470
+ unsigned long flags, const void *data, u32 request,
471
+ struct file_perms *perms, const char *info, int error)
473
+ int audit_type = AUDIT_APPARMOR_AUTO;
474
+ struct common_audit_data sa = { };
475
+ struct apparmor_audit_data aad = { };
477
+ if (likely(!error)) {
478
+ u32 mask = perms->audit;
480
+ if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
483
+ /* mask off perms that are not being force audited */
486
+ if (likely(!request))
488
+ audit_type = AUDIT_APPARMOR_AUDIT;
490
+ /* only report permissions that were denied */
491
+ request = request & ~perms->allow;
493
+ if (request & perms->kill)
494
+ audit_type = AUDIT_APPARMOR_KILL;
496
+ /* quiet known rejects, assumes quiet and kill do not overlap */
497
+ if ((request & perms->quiet) &&
498
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
499
+ AUDIT_MODE(profile) != AUDIT_ALL)
500
+ request &= ~perms->quiet;
503
+ return COMPLAIN_MODE(profile) ?
504
+ complain_error(error) : error;
507
+ sa.type = LSM_AUDIT_DATA_NONE;
510
+ sa.aad->name = name;
511
+ sa.aad->mnt.src_name = src_name;
512
+ sa.aad->mnt.type = type;
513
+ sa.aad->mnt.trans = trans;
514
+ sa.aad->mnt.flags = flags;
515
+ if (data && (perms->audit & AA_AUDIT_DATA))
516
+ sa.aad->mnt.data = data;
517
+ sa.aad->info = info;
518
+ sa.aad->error = error;
520
+ return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
524
+ * match_mnt_flags - Do an ordered match on mount flags
525
+ * @dfa: dfa to match against
526
+ * @state: state to start in
527
+ * @flags: mount flags to match against
529
+ * Mount flags are encoded as an ordered match. This is done instead of
530
+ * checking against a simple bitmask, to allow for logical operations
533
+ * Returns: next state after flags match
535
+static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
536
+ unsigned long flags)
540
+ for (i = 0; i <= 31 ; ++i) {
541
+ if ((1 << i) & flags)
542
+ state = aa_dfa_next(dfa, state, i + 1);
549
+ * compute_mnt_perms - compute mount permission associated with @state
550
+ * @dfa: dfa to match against (NOT NULL)
551
+ * @state: state match finished in
553
+ * Returns: mount permissions
555
+static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
556
+ unsigned int state)
558
+ struct file_perms perms;
561
+ perms.allow = dfa_user_allow(dfa, state);
562
+ perms.audit = dfa_user_audit(dfa, state);
563
+ perms.quiet = dfa_user_quiet(dfa, state);
564
+ perms.xindex = dfa_user_xindex(dfa, state);
569
+static const char const *mnt_info_table[] = {
571
+ "failed mntpnt match",
572
+ "failed srcname match",
573
+ "failed type match",
574
+ "failed flags match",
575
+ "failed data match"
579
+ * Returns 0 on success else element that match failed in, this is the
580
+ * index into the mnt_info_table above
582
+static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
583
+ const char *mntpnt, const char *devname,
584
+ const char *type, unsigned long flags,
585
+ void *data, bool binary, struct file_perms *perms)
587
+ unsigned int state;
589
+ state = aa_dfa_match(dfa, start, mntpnt);
590
+ state = aa_dfa_null_transition(dfa, state);
595
+ state = aa_dfa_match(dfa, state, devname);
596
+ state = aa_dfa_null_transition(dfa, state);
601
+ state = aa_dfa_match(dfa, state, type);
602
+ state = aa_dfa_null_transition(dfa, state);
606
+ state = match_mnt_flags(dfa, state, flags);
609
+ *perms = compute_mnt_perms(dfa, state);
610
+ if (perms->allow & AA_MAY_MOUNT)
613
+ /* only match data if not binary and the DFA flags data is expected */
614
+ if (data && !binary && (perms->allow & AA_CONT_MATCH)) {
615
+ state = aa_dfa_null_transition(dfa, state);
619
+ state = aa_dfa_match(dfa, state, data);
622
+ *perms = compute_mnt_perms(dfa, state);
623
+ if (perms->allow & AA_MAY_MOUNT)
627
+ /* failed at end of flags match */
632
+ * match_mnt - handle path matching for mount
633
+ * @profile: the confining profile
634
+ * @mntpnt: string for the mntpnt (NOT NULL)
635
+ * @devname: string for the devname/src_name (MAYBE NULL)
636
+ * @type: string for the dev type (MAYBE NULL)
637
+ * @flags: mount flags to match
638
+ * @data: fs mount data (MAYBE NULL)
639
+ * @binary: whether @data is binary
640
+ * @perms: Returns: permission found by the match
641
+ * @info: Returns: infomation string about the match for logging
643
+ * Returns: 0 on success else error
645
+static int match_mnt(struct aa_profile *profile, const char *mntpnt,
646
+ const char *devname, const char *type,
647
+ unsigned long flags, void *data, bool binary,
648
+ struct file_perms *perms, const char **info)
652
+ if (!profile->policy.dfa)
655
+ pos = do_match_mnt(profile->policy.dfa,
656
+ profile->policy.start[AA_CLASS_MOUNT],
657
+ mntpnt, devname, type, flags, data, binary, perms);
659
+ *info = mnt_info_table[pos];
666
+static int path_flags(struct aa_profile *profile, struct path *path)
668
+ return profile->path_flags |
669
+ S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
672
+int aa_remount(struct aa_profile *profile, struct path *path,
673
+ unsigned long flags, void *data)
675
+ struct file_perms perms = { };
676
+ const char *name, *info = NULL;
677
+ char *buffer = NULL;
680
+ binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
682
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
687
+ error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
691
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
692
+ NULL, flags, data, AA_MAY_MOUNT, &perms, info,
699
+int aa_bind_mount(struct aa_profile *profile, struct path *path,
700
+ const char *dev_name, unsigned long flags)
702
+ struct file_perms perms = { };
703
+ char *buffer = NULL, *old_buffer = NULL;
704
+ const char *name, *old_name = NULL, *info = NULL;
705
+ struct path old_path;
708
+ if (!dev_name || !*dev_name)
711
+ flags &= MS_REC | MS_BIND;
713
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
718
+ error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
722
+ error = aa_path_name(&old_path, path_flags(profile, &old_path),
723
+ &old_buffer, &old_name, &info);
724
+ path_put(&old_path);
728
+ error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
732
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
733
+ NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
741
+int aa_mount_change_type(struct aa_profile *profile, struct path *path,
742
+ unsigned long flags)
744
+ struct file_perms perms = { };
745
+ char *buffer = NULL;
746
+ const char *name, *info = NULL;
749
+ /* These are the flags allowed by do_change_type() */
750
+ flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
753
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
758
+ error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
762
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
763
+ NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
770
+int aa_move_mount(struct aa_profile *profile, struct path *path,
771
+ const char *orig_name)
773
+ struct file_perms perms = { };
774
+ char *buffer = NULL, *old_buffer = NULL;
775
+ const char *name, *old_name = NULL, *info = NULL;
776
+ struct path old_path;
779
+ if (!orig_name || !*orig_name)
782
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
787
+ error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
791
+ error = aa_path_name(&old_path, path_flags(profile, &old_path),
792
+ &old_buffer, &old_name, &info);
793
+ path_put(&old_path);
797
+ error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
801
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
802
+ NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
810
+int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name,
811
+ struct path *path, const char *type, unsigned long flags,
814
+ struct file_perms perms = { };
815
+ char *buffer = NULL, *dev_buffer = NULL;
816
+ const char *name = NULL, *dev_name = NULL, *info = NULL;
820
+ dev_name = orig_dev_name;
823
+ struct file_system_type *fstype = get_fs_type(type);
827
+ binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
828
+ requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
829
+ put_filesystem(fstype);
831
+ if (requires_dev) {
832
+ struct path dev_path;
834
+ if (!dev_name || !*dev_name) {
839
+ error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
843
+ error = aa_path_name(&dev_path,
844
+ path_flags(profile, &dev_path),
845
+ &dev_buffer, &dev_name, &info);
846
+ path_put(&dev_path);
852
+ error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
857
+ error = match_mnt(profile, name, dev_name, type, flags, data, binary,
861
+ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, dev_name,
862
+ type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
872
+int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
874
+ struct file_perms perms = { };
875
+ char *buffer = NULL;
876
+ const char *name, *info = NULL;
879
+ struct path path = { mnt, mnt->mnt_root };
880
+ error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
885
+ if (!error && profile->policy.dfa) {
886
+ unsigned int state;
887
+ state = aa_dfa_match(profile->policy.dfa,
888
+ profile->policy.start[AA_CLASS_MOUNT],
890
+ perms = compute_mnt_perms(profile->policy.dfa, state);
893
+ if (AA_MAY_UMOUNT & ~perms.allow)
897
+ error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
898
+ NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
904
+int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
905
+ struct path *new_path)
907
+ struct file_perms perms = { };
908
+ struct aa_profile *target = NULL;
909
+ char *old_buffer = NULL, *new_buffer = NULL;
910
+ const char *old_name, *new_name = NULL, *info = NULL;
913
+ error = aa_path_name(old_path, path_flags(profile, old_path),
914
+ &old_buffer, &old_name, &info);
918
+ error = aa_path_name(new_path, path_flags(profile, new_path),
919
+ &new_buffer, &new_name, &info);
923
+ if (profile->policy.dfa) {
924
+ unsigned int state;
925
+ state = aa_dfa_match(profile->policy.dfa,
926
+ profile->policy.start[AA_CLASS_MOUNT],
928
+ state = aa_dfa_null_transition(profile->policy.dfa, state);
929
+ state = aa_dfa_match(profile->policy.dfa, state, old_name);
930
+ perms = compute_mnt_perms(profile->policy.dfa, state);
933
+ if (AA_MAY_PIVOTROOT & perms.allow) {
934
+ if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
935
+ target = x_table_lookup(profile, perms.xindex);
939
+ error = aa_replace_current_profile(target);
945
+ error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
946
+ old_name, NULL, target ? target->base.name : NULL,
947
+ 0, NULL, AA_MAY_PIVOTROOT, &perms, info, error);
948
+ aa_put_profile(target);