summaryrefslogtreecommitdiff
path: root/security/apparmor/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/mount.c')
-rw-r--r--security/apparmor/mount.c331
1 files changed, 197 insertions, 134 deletions
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
index 8c3787399356..523570aa1a5a 100644
--- a/security/apparmor/mount.c
+++ b/security/apparmor/mount.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* AppArmor security module
*
@@ -5,11 +6,6 @@
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-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.
*/
#include <linux/fs.h>
@@ -48,6 +44,8 @@ static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
audit_log_format(ab, ", mand");
if (flags & MS_DIRSYNC)
audit_log_format(ab, ", dirsync");
+ if (flags & MS_NOSYMFOLLOW)
+ audit_log_format(ab, ", nosymfollow");
if (flags & MS_NOATIME)
audit_log_format(ab, ", noatime");
if (flags & MS_NODIRATIME)
@@ -90,32 +88,34 @@ static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
static void audit_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
+ struct apparmor_audit_data *ad = aad(sa);
- if (aad(sa)->mnt.type) {
+ if (ad->mnt.type) {
audit_log_format(ab, " fstype=");
- audit_log_untrustedstring(ab, aad(sa)->mnt.type);
+ audit_log_untrustedstring(ab, ad->mnt.type);
}
- if (aad(sa)->mnt.src_name) {
+ if (ad->mnt.src_name) {
audit_log_format(ab, " srcname=");
- audit_log_untrustedstring(ab, aad(sa)->mnt.src_name);
+ audit_log_untrustedstring(ab, ad->mnt.src_name);
}
- if (aad(sa)->mnt.trans) {
+ if (ad->mnt.trans) {
audit_log_format(ab, " trans=");
- audit_log_untrustedstring(ab, aad(sa)->mnt.trans);
+ audit_log_untrustedstring(ab, ad->mnt.trans);
}
- if (aad(sa)->mnt.flags) {
+ if (ad->mnt.flags) {
audit_log_format(ab, " flags=\"");
- audit_mnt_flags(ab, aad(sa)->mnt.flags);
+ audit_mnt_flags(ab, ad->mnt.flags);
audit_log_format(ab, "\"");
}
- if (aad(sa)->mnt.data) {
+ if (ad->mnt.data) {
audit_log_format(ab, " options=");
- audit_log_untrustedstring(ab, aad(sa)->mnt.data);
+ audit_log_untrustedstring(ab, ad->mnt.data);
}
}
/**
* audit_mount - handle the auditing of mount operations
+ * @subj_cred: cred of the subject
* @profile: the profile being enforced (NOT NULL)
* @op: operation being mediated (NOT NULL)
* @name: name of object being mediated (MAYBE NULL)
@@ -131,14 +131,15 @@ static void audit_cb(struct audit_buffer *ab, void *va)
*
* Returns: %0 or error on failure
*/
-static int audit_mount(struct aa_profile *profile, const char *op,
+static int audit_mount(const struct cred *subj_cred,
+ struct aa_profile *profile, const char *op,
const char *name, const char *src_name,
const char *type, const char *trans,
unsigned long flags, const void *data, u32 request,
struct aa_perms *perms, const char *info, int error)
{
int audit_type = AUDIT_APPARMOR_AUTO;
- DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
+ DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op);
if (likely(!error)) {
u32 mask = perms->audit;
@@ -169,17 +170,18 @@ static int audit_mount(struct aa_profile *profile, const char *op,
return error;
}
- aad(&sa)->name = name;
- aad(&sa)->mnt.src_name = src_name;
- aad(&sa)->mnt.type = type;
- aad(&sa)->mnt.trans = trans;
- aad(&sa)->mnt.flags = flags;
+ ad.subj_cred = subj_cred;
+ ad.name = name;
+ ad.mnt.src_name = src_name;
+ ad.mnt.type = type;
+ ad.mnt.trans = trans;
+ ad.mnt.flags = flags;
if (data && (perms->audit & AA_AUDIT_DATA))
- aad(&sa)->mnt.data = data;
- aad(&sa)->info = info;
- aad(&sa)->error = error;
+ ad.mnt.data = data;
+ ad.info = info;
+ ad.error = error;
- return aa_audit(audit_type, profile, &sa, audit_cb);
+ return aa_audit(audit_type, profile, &ad, audit_cb);
}
/**
@@ -194,7 +196,7 @@ static int audit_mount(struct aa_profile *profile, const char *op,
*
* Returns: next state after flags match
*/
-static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
+static aa_state_t match_mnt_flags(struct aa_dfa *dfa, aa_state_t state,
unsigned long flags)
{
unsigned int i;
@@ -207,89 +209,72 @@ static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
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 aa_perms compute_mnt_perms(struct aa_dfa *dfa,
- unsigned int state)
-{
- struct aa_perms perms = {
- .allow = dfa_user_allow(dfa, state),
- .audit = dfa_user_audit(dfa, state),
- .quiet = dfa_user_quiet(dfa, state),
- .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"
+ "failed data match",
+ "failed perms check"
};
/*
* 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,
+static int do_match_mnt(struct aa_policydb *policy, aa_state_t start,
const char *mntpnt, const char *devname,
const char *type, unsigned long flags,
void *data, bool binary, struct aa_perms *perms)
{
- unsigned int state;
+ aa_state_t state;
- AA_BUG(!dfa);
+ AA_BUG(!policy);
+ AA_BUG(!policy->dfa);
+ AA_BUG(!policy->perms);
AA_BUG(!perms);
- state = aa_dfa_match(dfa, start, mntpnt);
- state = aa_dfa_null_transition(dfa, state);
+ state = aa_dfa_match(policy->dfa, start, mntpnt);
+ state = aa_dfa_null_transition(policy->dfa, state);
if (!state)
return 1;
if (devname)
- state = aa_dfa_match(dfa, state, devname);
- state = aa_dfa_null_transition(dfa, state);
+ state = aa_dfa_match(policy->dfa, state, devname);
+ state = aa_dfa_null_transition(policy->dfa, state);
if (!state)
return 2;
if (type)
- state = aa_dfa_match(dfa, state, type);
- state = aa_dfa_null_transition(dfa, state);
+ state = aa_dfa_match(policy->dfa, state, type);
+ state = aa_dfa_null_transition(policy->dfa, state);
if (!state)
return 3;
- state = match_mnt_flags(dfa, state, flags);
+ state = match_mnt_flags(policy->dfa, state, flags);
if (!state)
return 4;
- *perms = compute_mnt_perms(dfa, state);
+ *perms = *aa_lookup_perms(policy, 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_MNT_CONT_MATCH)) {
- state = aa_dfa_null_transition(dfa, state);
+ state = aa_dfa_null_transition(policy->dfa, state);
if (!state)
return 4;
- state = aa_dfa_match(dfa, state, data);
+ state = aa_dfa_match(policy->dfa, state, data);
if (!state)
return 5;
- *perms = compute_mnt_perms(dfa, state);
+ *perms = *aa_lookup_perms(policy, state);
if (perms->allow & AA_MAY_MOUNT)
return 0;
}
- /* failed at end of flags match */
- return 4;
+ /* failed at perms check, don't confuse with flags match */
+ return 6;
}
@@ -304,10 +289,11 @@ static int path_flags(struct aa_profile *profile, const struct path *path)
/**
* match_mnt_path_str - handle path matching for mount
+ * @subj_cred: cred of confined subject
* @profile: the confining profile
* @mntpath: for the mntpnt (NOT NULL)
* @buffer: buffer to be used to lookup mntpath
- * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR)
+ * @devname: string for the devname/src_name (MAY BE NULL OR ERRPTR)
* @type: string for the dev type (MAYBE NULL)
* @flags: mount flags to match
* @data: fs mount data (MAYBE NULL)
@@ -316,7 +302,8 @@ static int path_flags(struct aa_profile *profile, const struct path *path)
*
* Returns: 0 on success else error
*/
-static int match_mnt_path_str(struct aa_profile *profile,
+static int match_mnt_path_str(const struct cred *subj_cred,
+ struct aa_profile *profile,
const struct path *mntpath, char *buffer,
const char *devname, const char *type,
unsigned long flags, void *data, bool binary,
@@ -324,13 +311,14 @@ static int match_mnt_path_str(struct aa_profile *profile,
{
struct aa_perms perms = { };
const char *mntpnt = NULL, *info = NULL;
+ struct aa_ruleset *rules = profile->label.rules[0];
int pos, error;
AA_BUG(!profile);
AA_BUG(!mntpath);
AA_BUG(!buffer);
- if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
+ if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
return 0;
error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
@@ -345,8 +333,8 @@ static int match_mnt_path_str(struct aa_profile *profile,
}
error = -EACCES;
- pos = do_match_mnt(profile->policy.dfa,
- profile->policy.start[AA_CLASS_MOUNT],
+ pos = do_match_mnt(rules->policy,
+ rules->policy->start[AA_CLASS_MOUNT],
mntpnt, devname, type, flags, data, binary, &perms);
if (pos) {
info = mnt_info_table[pos];
@@ -355,14 +343,16 @@ static int match_mnt_path_str(struct aa_profile *profile,
error = 0;
audit:
- return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL,
+ return audit_mount(subj_cred, profile, OP_MOUNT, mntpnt, devname,
+ type, NULL,
flags, data, AA_MAY_MOUNT, &perms, info, error);
}
/**
* match_mnt - handle path matching for mount
+ * @subj_cred: cred of the subject
* @profile: the confining profile
- * @mntpath: for the mntpnt (NOT NULL)
+ * @path: for the mntpnt (NOT NULL)
* @buffer: buffer to be used to lookup mntpath
* @devpath: path devname/src_name (MAYBE NULL)
* @devbuffer: buffer to be used to lookup devname/src_name
@@ -373,18 +363,20 @@ audit:
*
* Returns: 0 on success else error
*/
-static int match_mnt(struct aa_profile *profile, const struct path *path,
- char *buffer, struct path *devpath, char *devbuffer,
+static int match_mnt(const struct cred *subj_cred,
+ struct aa_profile *profile, const struct path *path,
+ char *buffer, const struct path *devpath, char *devbuffer,
const char *type, unsigned long flags, void *data,
bool binary)
{
const char *devname = NULL, *info = NULL;
+ struct aa_ruleset *rules = profile->label.rules[0];
int error = -EACCES;
AA_BUG(!profile);
AA_BUG(devpath && !devbuffer);
- if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
+ if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
return 0;
if (devpath) {
@@ -395,11 +387,12 @@ static int match_mnt(struct aa_profile *profile, const struct path *path,
devname = ERR_PTR(error);
}
- return match_mnt_path_str(profile, path, buffer, devname, type, flags,
- data, binary, info);
+ return match_mnt_path_str(subj_cred, profile, path, buffer, devname,
+ type, flags, data, binary, info);
}
-int aa_remount(struct aa_label *label, const struct path *path,
+int aa_remount(const struct cred *subj_cred,
+ struct aa_label *label, const struct path *path,
unsigned long flags, void *data)
{
struct aa_profile *profile;
@@ -412,16 +405,20 @@ int aa_remount(struct aa_label *label, const struct path *path,
binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
- get_buffers(buffer);
+ buffer = aa_get_buffer(false);
+ if (!buffer)
+ return -ENOMEM;
error = fn_for_each_confined(label, profile,
- match_mnt(profile, path, buffer, NULL, NULL, NULL,
+ match_mnt(subj_cred, profile, path, buffer, NULL,
+ NULL, NULL,
flags, data, binary));
- put_buffers(buffer);
+ aa_put_buffer(buffer);
return error;
}
-int aa_bind_mount(struct aa_label *label, const struct path *path,
+int aa_bind_mount(const struct cred *subj_cred,
+ struct aa_label *label, const struct path *path,
const char *dev_name, unsigned long flags)
{
struct aa_profile *profile;
@@ -441,17 +438,25 @@ int aa_bind_mount(struct aa_label *label, const struct path *path,
if (error)
return error;
- get_buffers(buffer, old_buffer);
+ buffer = aa_get_buffer(false);
+ old_buffer = aa_get_buffer(false);
+ error = -ENOMEM;
+ if (!buffer || !old_buffer)
+ goto out;
+
error = fn_for_each_confined(label, profile,
- match_mnt(profile, path, buffer, &old_path, old_buffer,
- NULL, flags, NULL, false));
- put_buffers(buffer, old_buffer);
+ match_mnt(subj_cred, profile, path, buffer, &old_path,
+ old_buffer, NULL, flags, NULL, false));
+out:
+ aa_put_buffer(buffer);
+ aa_put_buffer(old_buffer);
path_put(&old_path);
return error;
}
-int aa_mount_change_type(struct aa_label *label, const struct path *path,
+int aa_mount_change_type(const struct cred *subj_cred,
+ struct aa_label *label, const struct path *path,
unsigned long flags)
{
struct aa_profile *profile;
@@ -465,46 +470,71 @@ int aa_mount_change_type(struct aa_label *label, const struct path *path,
flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
MS_UNBINDABLE);
- get_buffers(buffer);
+ buffer = aa_get_buffer(false);
+ if (!buffer)
+ return -ENOMEM;
error = fn_for_each_confined(label, profile,
- match_mnt(profile, path, buffer, NULL, NULL, NULL,
+ match_mnt(subj_cred, profile, path, buffer, NULL,
+ NULL, NULL,
flags, NULL, false));
- put_buffers(buffer);
+ aa_put_buffer(buffer);
return error;
}
-int aa_move_mount(struct aa_label *label, const struct path *path,
- const char *orig_name)
+int aa_move_mount(const struct cred *subj_cred,
+ struct aa_label *label, const struct path *from_path,
+ const struct path *to_path)
{
struct aa_profile *profile;
- char *buffer = NULL, *old_buffer = NULL;
- struct path old_path;
+ char *to_buffer = NULL, *from_buffer = NULL;
int error;
AA_BUG(!label);
- AA_BUG(!path);
+ AA_BUG(!from_path);
+ AA_BUG(!to_path);
+
+ to_buffer = aa_get_buffer(false);
+ from_buffer = aa_get_buffer(false);
+ error = -ENOMEM;
+ if (!to_buffer || !from_buffer)
+ goto out;
+
+ if (!our_mnt(from_path->mnt))
+ /* moving a mount detached from the namespace */
+ from_path = NULL;
+ error = fn_for_each_confined(label, profile,
+ match_mnt(subj_cred, profile, to_path, to_buffer,
+ from_path, from_buffer,
+ NULL, MS_MOVE, NULL, false));
+out:
+ aa_put_buffer(to_buffer);
+ aa_put_buffer(from_buffer);
+
+ return error;
+}
+
+int aa_move_mount_old(const struct cred *subj_cred, struct aa_label *label,
+ const struct path *path, const char *orig_name)
+{
+ struct path old_path;
+ int error;
if (!orig_name || !*orig_name)
return -EINVAL;
-
error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
if (error)
return error;
- get_buffers(buffer, old_buffer);
- error = fn_for_each_confined(label, profile,
- match_mnt(profile, path, buffer, &old_path, old_buffer,
- NULL, MS_MOVE, NULL, false));
- put_buffers(buffer, old_buffer);
+ error = aa_move_mount(subj_cred, label, &old_path, path);
path_put(&old_path);
return error;
}
-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_new_mount(const struct cred *subj_cred, struct aa_label *label,
+ const char *dev_name, const struct path *path,
+ const char *type, unsigned long flags, void *data)
{
struct aa_profile *profile;
char *buffer = NULL, *dev_buffer = NULL;
@@ -537,35 +567,51 @@ int aa_new_mount(struct aa_label *label, const char *dev_name,
}
}
- get_buffers(buffer, dev_buffer);
+ buffer = aa_get_buffer(false);
+ if (!buffer) {
+ error = -ENOMEM;
+ goto out;
+ }
if (dev_path) {
+ dev_buffer = aa_get_buffer(false);
+ if (!dev_buffer) {
+ error = -ENOMEM;
+ goto out;
+ }
error = fn_for_each_confined(label, profile,
- match_mnt(profile, path, buffer, dev_path, dev_buffer,
+ match_mnt(subj_cred, profile, path, buffer,
+ dev_path, dev_buffer,
type, flags, data, binary));
} else {
error = fn_for_each_confined(label, profile,
- match_mnt_path_str(profile, path, buffer, dev_name,
- type, flags, data, binary, NULL));
+ match_mnt_path_str(subj_cred, profile, path,
+ buffer, dev_name,
+ type, flags, data, binary, NULL));
}
- put_buffers(buffer, dev_buffer);
+
+out:
+ aa_put_buffer(buffer);
+ aa_put_buffer(dev_buffer);
if (dev_path)
path_put(dev_path);
return error;
}
-static int profile_umount(struct aa_profile *profile, struct path *path,
+static int profile_umount(const struct cred *subj_cred,
+ struct aa_profile *profile, const struct path *path,
char *buffer)
{
+ struct aa_ruleset *rules = profile->label.rules[0];
struct aa_perms perms = { };
const char *name = NULL, *info = NULL;
- unsigned int state;
+ aa_state_t state;
int error;
AA_BUG(!profile);
AA_BUG(!path);
- if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
+ if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
return 0;
error = aa_path_name(path, path_flags(profile, path), buffer, &name,
@@ -573,19 +619,21 @@ static int profile_umount(struct aa_profile *profile, struct path *path,
if (error)
goto audit;
- state = aa_dfa_match(profile->policy.dfa,
- profile->policy.start[AA_CLASS_MOUNT],
+ state = aa_dfa_match(rules->policy->dfa,
+ rules->policy->start[AA_CLASS_MOUNT],
name);
- perms = compute_mnt_perms(profile->policy.dfa, state);
+ perms = *aa_lookup_perms(rules->policy, state);
if (AA_MAY_UMOUNT & ~perms.allow)
error = -EACCES;
audit:
- return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
+ return audit_mount(subj_cred, profile, OP_UMOUNT, name, NULL, NULL,
+ NULL, 0, NULL,
AA_MAY_UMOUNT, &perms, info, error);
}
-int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
+int aa_umount(const struct cred *subj_cred, struct aa_label *label,
+ struct vfsmount *mnt, int flags)
{
struct aa_profile *profile;
char *buffer = NULL;
@@ -595,10 +643,13 @@ int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
AA_BUG(!label);
AA_BUG(!mnt);
- get_buffers(buffer);
+ buffer = aa_get_buffer(false);
+ if (!buffer)
+ return -ENOMEM;
+
error = fn_for_each_confined(label, profile,
- profile_umount(profile, &path, buffer));
- put_buffers(buffer);
+ profile_umount(subj_cred, profile, &path, buffer));
+ aa_put_buffer(buffer);
return error;
}
@@ -607,16 +658,18 @@ int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
*
* Returns: label for transition or ERR_PTR. Does not return NULL
*/
-static struct aa_label *build_pivotroot(struct aa_profile *profile,
+static struct aa_label *build_pivotroot(const struct cred *subj_cred,
+ struct aa_profile *profile,
const struct path *new_path,
char *new_buffer,
const struct path *old_path,
char *old_buffer)
{
+ struct aa_ruleset *rules = profile->label.rules[0];
const char *old_name, *new_name = NULL, *info = NULL;
const char *trans_name = NULL;
struct aa_perms perms = { };
- unsigned int state;
+ aa_state_t state;
int error;
AA_BUG(!profile);
@@ -624,7 +677,7 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile,
AA_BUG(!old_path);
if (profile_unconfined(profile) ||
- !PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
+ !RULE_MEDIATES(rules, AA_CLASS_MOUNT))
return aa_get_newest_label(&profile->label);
error = aa_path_name(old_path, path_flags(profile, old_path),
@@ -639,18 +692,19 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile,
goto audit;
error = -EACCES;
- state = aa_dfa_match(profile->policy.dfa,
- profile->policy.start[AA_CLASS_MOUNT],
+ state = aa_dfa_match(rules->policy->dfa,
+ rules->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);
+ state = aa_dfa_null_transition(rules->policy->dfa, state);
+ state = aa_dfa_match(rules->policy->dfa, state, old_name);
+ perms = *aa_lookup_perms(rules->policy, state);
if (AA_MAY_PIVOTROOT & perms.allow)
error = 0;
audit:
- error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
+ error = audit_mount(subj_cred, profile, OP_PIVOTROOT, new_name,
+ old_name,
NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
&perms, info, error);
if (error)
@@ -659,7 +713,8 @@ audit:
return aa_get_newest_label(&profile->label);
}
-int aa_pivotroot(struct aa_label *label, const struct path *old_path,
+int aa_pivotroot(const struct cred *subj_cred, struct aa_label *label,
+ const struct path *old_path,
const struct path *new_path)
{
struct aa_profile *profile;
@@ -671,9 +726,14 @@ int aa_pivotroot(struct aa_label *label, const struct path *old_path,
AA_BUG(!old_path);
AA_BUG(!new_path);
- get_buffers(old_buffer, new_buffer);
- target = fn_label_build(label, profile, GFP_ATOMIC,
- build_pivotroot(profile, new_path, new_buffer,
+ old_buffer = aa_get_buffer(false);
+ new_buffer = aa_get_buffer(false);
+ error = -ENOMEM;
+ if (!old_buffer || !new_buffer)
+ goto out;
+ target = fn_label_build(label, profile, GFP_KERNEL,
+ build_pivotroot(subj_cred, profile, new_path,
+ new_buffer,
old_path, old_buffer));
if (!target) {
info = "label build failed";
@@ -686,18 +746,21 @@ int aa_pivotroot(struct aa_label *label, const struct path *old_path,
aa_put_label(target);
goto out;
}
+ aa_put_label(target);
} else
/* already audited error */
error = PTR_ERR(target);
out:
- put_buffers(old_buffer, new_buffer);
+ aa_put_buffer(old_buffer);
+ aa_put_buffer(new_buffer);
return error;
fail:
/* TODO: add back in auditing of new_name and old_name */
error = fn_for_each(label, profile,
- audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */,
+ audit_mount(subj_cred, profile, OP_PIVOTROOT,
+ NULL /*new_name */,
NULL /* old_name */,
NULL, NULL,
0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,