162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AppArmor security module 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This file contains AppArmor mediation of files 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 1998-2008 Novell/SUSE 862306a36Sopenharmony_ci * Copyright 2009-2017 Canonical Ltd. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/fs.h> 1262306a36Sopenharmony_ci#include <linux/mount.h> 1362306a36Sopenharmony_ci#include <linux/namei.h> 1462306a36Sopenharmony_ci#include <uapi/linux/mount.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "include/apparmor.h" 1762306a36Sopenharmony_ci#include "include/audit.h" 1862306a36Sopenharmony_ci#include "include/cred.h" 1962306a36Sopenharmony_ci#include "include/domain.h" 2062306a36Sopenharmony_ci#include "include/file.h" 2162306a36Sopenharmony_ci#include "include/match.h" 2262306a36Sopenharmony_ci#include "include/mount.h" 2362306a36Sopenharmony_ci#include "include/path.h" 2462306a36Sopenharmony_ci#include "include/policy.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci if (flags & MS_RDONLY) 3062306a36Sopenharmony_ci audit_log_format(ab, "ro"); 3162306a36Sopenharmony_ci else 3262306a36Sopenharmony_ci audit_log_format(ab, "rw"); 3362306a36Sopenharmony_ci if (flags & MS_NOSUID) 3462306a36Sopenharmony_ci audit_log_format(ab, ", nosuid"); 3562306a36Sopenharmony_ci if (flags & MS_NODEV) 3662306a36Sopenharmony_ci audit_log_format(ab, ", nodev"); 3762306a36Sopenharmony_ci if (flags & MS_NOEXEC) 3862306a36Sopenharmony_ci audit_log_format(ab, ", noexec"); 3962306a36Sopenharmony_ci if (flags & MS_SYNCHRONOUS) 4062306a36Sopenharmony_ci audit_log_format(ab, ", sync"); 4162306a36Sopenharmony_ci if (flags & MS_REMOUNT) 4262306a36Sopenharmony_ci audit_log_format(ab, ", remount"); 4362306a36Sopenharmony_ci if (flags & MS_MANDLOCK) 4462306a36Sopenharmony_ci audit_log_format(ab, ", mand"); 4562306a36Sopenharmony_ci if (flags & MS_DIRSYNC) 4662306a36Sopenharmony_ci audit_log_format(ab, ", dirsync"); 4762306a36Sopenharmony_ci if (flags & MS_NOATIME) 4862306a36Sopenharmony_ci audit_log_format(ab, ", noatime"); 4962306a36Sopenharmony_ci if (flags & MS_NODIRATIME) 5062306a36Sopenharmony_ci audit_log_format(ab, ", nodiratime"); 5162306a36Sopenharmony_ci if (flags & MS_BIND) 5262306a36Sopenharmony_ci audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind"); 5362306a36Sopenharmony_ci if (flags & MS_MOVE) 5462306a36Sopenharmony_ci audit_log_format(ab, ", move"); 5562306a36Sopenharmony_ci if (flags & MS_SILENT) 5662306a36Sopenharmony_ci audit_log_format(ab, ", silent"); 5762306a36Sopenharmony_ci if (flags & MS_POSIXACL) 5862306a36Sopenharmony_ci audit_log_format(ab, ", acl"); 5962306a36Sopenharmony_ci if (flags & MS_UNBINDABLE) 6062306a36Sopenharmony_ci audit_log_format(ab, flags & MS_REC ? ", runbindable" : 6162306a36Sopenharmony_ci ", unbindable"); 6262306a36Sopenharmony_ci if (flags & MS_PRIVATE) 6362306a36Sopenharmony_ci audit_log_format(ab, flags & MS_REC ? ", rprivate" : 6462306a36Sopenharmony_ci ", private"); 6562306a36Sopenharmony_ci if (flags & MS_SLAVE) 6662306a36Sopenharmony_ci audit_log_format(ab, flags & MS_REC ? ", rslave" : 6762306a36Sopenharmony_ci ", slave"); 6862306a36Sopenharmony_ci if (flags & MS_SHARED) 6962306a36Sopenharmony_ci audit_log_format(ab, flags & MS_REC ? ", rshared" : 7062306a36Sopenharmony_ci ", shared"); 7162306a36Sopenharmony_ci if (flags & MS_RELATIME) 7262306a36Sopenharmony_ci audit_log_format(ab, ", relatime"); 7362306a36Sopenharmony_ci if (flags & MS_I_VERSION) 7462306a36Sopenharmony_ci audit_log_format(ab, ", iversion"); 7562306a36Sopenharmony_ci if (flags & MS_STRICTATIME) 7662306a36Sopenharmony_ci audit_log_format(ab, ", strictatime"); 7762306a36Sopenharmony_ci if (flags & MS_NOUSER) 7862306a36Sopenharmony_ci audit_log_format(ab, ", nouser"); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/** 8262306a36Sopenharmony_ci * audit_cb - call back for mount specific audit fields 8362306a36Sopenharmony_ci * @ab: audit_buffer (NOT NULL) 8462306a36Sopenharmony_ci * @va: audit struct to audit values of (NOT NULL) 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_cistatic void audit_cb(struct audit_buffer *ab, void *va) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct common_audit_data *sa = va; 8962306a36Sopenharmony_ci struct apparmor_audit_data *ad = aad(sa); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (ad->mnt.type) { 9262306a36Sopenharmony_ci audit_log_format(ab, " fstype="); 9362306a36Sopenharmony_ci audit_log_untrustedstring(ab, ad->mnt.type); 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci if (ad->mnt.src_name) { 9662306a36Sopenharmony_ci audit_log_format(ab, " srcname="); 9762306a36Sopenharmony_ci audit_log_untrustedstring(ab, ad->mnt.src_name); 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci if (ad->mnt.trans) { 10062306a36Sopenharmony_ci audit_log_format(ab, " trans="); 10162306a36Sopenharmony_ci audit_log_untrustedstring(ab, ad->mnt.trans); 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci if (ad->mnt.flags) { 10462306a36Sopenharmony_ci audit_log_format(ab, " flags=\""); 10562306a36Sopenharmony_ci audit_mnt_flags(ab, ad->mnt.flags); 10662306a36Sopenharmony_ci audit_log_format(ab, "\""); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci if (ad->mnt.data) { 10962306a36Sopenharmony_ci audit_log_format(ab, " options="); 11062306a36Sopenharmony_ci audit_log_untrustedstring(ab, ad->mnt.data); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/** 11562306a36Sopenharmony_ci * audit_mount - handle the auditing of mount operations 11662306a36Sopenharmony_ci * @subj_cred: cred of the subject 11762306a36Sopenharmony_ci * @profile: the profile being enforced (NOT NULL) 11862306a36Sopenharmony_ci * @op: operation being mediated (NOT NULL) 11962306a36Sopenharmony_ci * @name: name of object being mediated (MAYBE NULL) 12062306a36Sopenharmony_ci * @src_name: src_name of object being mediated (MAYBE_NULL) 12162306a36Sopenharmony_ci * @type: type of filesystem (MAYBE_NULL) 12262306a36Sopenharmony_ci * @trans: name of trans (MAYBE NULL) 12362306a36Sopenharmony_ci * @flags: filesystem independent mount flags 12462306a36Sopenharmony_ci * @data: filesystem mount flags 12562306a36Sopenharmony_ci * @request: permissions requested 12662306a36Sopenharmony_ci * @perms: the permissions computed for the request (NOT NULL) 12762306a36Sopenharmony_ci * @info: extra information message (MAYBE NULL) 12862306a36Sopenharmony_ci * @error: 0 if operation allowed else failure error code 12962306a36Sopenharmony_ci * 13062306a36Sopenharmony_ci * Returns: %0 or error on failure 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_cistatic int audit_mount(const struct cred *subj_cred, 13362306a36Sopenharmony_ci struct aa_profile *profile, const char *op, 13462306a36Sopenharmony_ci const char *name, const char *src_name, 13562306a36Sopenharmony_ci const char *type, const char *trans, 13662306a36Sopenharmony_ci unsigned long flags, const void *data, u32 request, 13762306a36Sopenharmony_ci struct aa_perms *perms, const char *info, int error) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci int audit_type = AUDIT_APPARMOR_AUTO; 14062306a36Sopenharmony_ci DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (likely(!error)) { 14362306a36Sopenharmony_ci u32 mask = perms->audit; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) 14662306a36Sopenharmony_ci mask = 0xffff; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* mask off perms that are not being force audited */ 14962306a36Sopenharmony_ci request &= mask; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (likely(!request)) 15262306a36Sopenharmony_ci return 0; 15362306a36Sopenharmony_ci audit_type = AUDIT_APPARMOR_AUDIT; 15462306a36Sopenharmony_ci } else { 15562306a36Sopenharmony_ci /* only report permissions that were denied */ 15662306a36Sopenharmony_ci request = request & ~perms->allow; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (request & perms->kill) 15962306a36Sopenharmony_ci audit_type = AUDIT_APPARMOR_KILL; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* quiet known rejects, assumes quiet and kill do not overlap */ 16262306a36Sopenharmony_ci if ((request & perms->quiet) && 16362306a36Sopenharmony_ci AUDIT_MODE(profile) != AUDIT_NOQUIET && 16462306a36Sopenharmony_ci AUDIT_MODE(profile) != AUDIT_ALL) 16562306a36Sopenharmony_ci request &= ~perms->quiet; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (!request) 16862306a36Sopenharmony_ci return error; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci ad.subj_cred = subj_cred; 17262306a36Sopenharmony_ci ad.name = name; 17362306a36Sopenharmony_ci ad.mnt.src_name = src_name; 17462306a36Sopenharmony_ci ad.mnt.type = type; 17562306a36Sopenharmony_ci ad.mnt.trans = trans; 17662306a36Sopenharmony_ci ad.mnt.flags = flags; 17762306a36Sopenharmony_ci if (data && (perms->audit & AA_AUDIT_DATA)) 17862306a36Sopenharmony_ci ad.mnt.data = data; 17962306a36Sopenharmony_ci ad.info = info; 18062306a36Sopenharmony_ci ad.error = error; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci return aa_audit(audit_type, profile, &ad, audit_cb); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/** 18662306a36Sopenharmony_ci * match_mnt_flags - Do an ordered match on mount flags 18762306a36Sopenharmony_ci * @dfa: dfa to match against 18862306a36Sopenharmony_ci * @state: state to start in 18962306a36Sopenharmony_ci * @flags: mount flags to match against 19062306a36Sopenharmony_ci * 19162306a36Sopenharmony_ci * Mount flags are encoded as an ordered match. This is done instead of 19262306a36Sopenharmony_ci * checking against a simple bitmask, to allow for logical operations 19362306a36Sopenharmony_ci * on the flags. 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * Returns: next state after flags match 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_cistatic aa_state_t match_mnt_flags(struct aa_dfa *dfa, aa_state_t state, 19862306a36Sopenharmony_ci unsigned long flags) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci unsigned int i; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci for (i = 0; i <= 31 ; ++i) { 20362306a36Sopenharmony_ci if ((1 << i) & flags) 20462306a36Sopenharmony_ci state = aa_dfa_next(dfa, state, i + 1); 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci return state; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic const char * const mnt_info_table[] = { 21162306a36Sopenharmony_ci "match succeeded", 21262306a36Sopenharmony_ci "failed mntpnt match", 21362306a36Sopenharmony_ci "failed srcname match", 21462306a36Sopenharmony_ci "failed type match", 21562306a36Sopenharmony_ci "failed flags match", 21662306a36Sopenharmony_ci "failed data match", 21762306a36Sopenharmony_ci "failed perms check" 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci/* 22162306a36Sopenharmony_ci * Returns 0 on success else element that match failed in, this is the 22262306a36Sopenharmony_ci * index into the mnt_info_table above 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_cistatic int do_match_mnt(struct aa_policydb *policy, aa_state_t start, 22562306a36Sopenharmony_ci const char *mntpnt, const char *devname, 22662306a36Sopenharmony_ci const char *type, unsigned long flags, 22762306a36Sopenharmony_ci void *data, bool binary, struct aa_perms *perms) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci aa_state_t state; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci AA_BUG(!policy); 23262306a36Sopenharmony_ci AA_BUG(!policy->dfa); 23362306a36Sopenharmony_ci AA_BUG(!policy->perms); 23462306a36Sopenharmony_ci AA_BUG(!perms); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci state = aa_dfa_match(policy->dfa, start, mntpnt); 23762306a36Sopenharmony_ci state = aa_dfa_null_transition(policy->dfa, state); 23862306a36Sopenharmony_ci if (!state) 23962306a36Sopenharmony_ci return 1; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (devname) 24262306a36Sopenharmony_ci state = aa_dfa_match(policy->dfa, state, devname); 24362306a36Sopenharmony_ci state = aa_dfa_null_transition(policy->dfa, state); 24462306a36Sopenharmony_ci if (!state) 24562306a36Sopenharmony_ci return 2; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (type) 24862306a36Sopenharmony_ci state = aa_dfa_match(policy->dfa, state, type); 24962306a36Sopenharmony_ci state = aa_dfa_null_transition(policy->dfa, state); 25062306a36Sopenharmony_ci if (!state) 25162306a36Sopenharmony_ci return 3; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci state = match_mnt_flags(policy->dfa, state, flags); 25462306a36Sopenharmony_ci if (!state) 25562306a36Sopenharmony_ci return 4; 25662306a36Sopenharmony_ci *perms = *aa_lookup_perms(policy, state); 25762306a36Sopenharmony_ci if (perms->allow & AA_MAY_MOUNT) 25862306a36Sopenharmony_ci return 0; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci /* only match data if not binary and the DFA flags data is expected */ 26162306a36Sopenharmony_ci if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) { 26262306a36Sopenharmony_ci state = aa_dfa_null_transition(policy->dfa, state); 26362306a36Sopenharmony_ci if (!state) 26462306a36Sopenharmony_ci return 4; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci state = aa_dfa_match(policy->dfa, state, data); 26762306a36Sopenharmony_ci if (!state) 26862306a36Sopenharmony_ci return 5; 26962306a36Sopenharmony_ci *perms = *aa_lookup_perms(policy, state); 27062306a36Sopenharmony_ci if (perms->allow & AA_MAY_MOUNT) 27162306a36Sopenharmony_ci return 0; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* failed at perms check, don't confuse with flags match */ 27562306a36Sopenharmony_ci return 6; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic int path_flags(struct aa_profile *profile, const struct path *path) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci AA_BUG(!profile); 28262306a36Sopenharmony_ci AA_BUG(!path); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci return profile->path_flags | 28562306a36Sopenharmony_ci (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/** 28962306a36Sopenharmony_ci * match_mnt_path_str - handle path matching for mount 29062306a36Sopenharmony_ci * @subj_cred: cred of confined subject 29162306a36Sopenharmony_ci * @profile: the confining profile 29262306a36Sopenharmony_ci * @mntpath: for the mntpnt (NOT NULL) 29362306a36Sopenharmony_ci * @buffer: buffer to be used to lookup mntpath 29462306a36Sopenharmony_ci * @devname: string for the devname/src_name (MAY BE NULL OR ERRPTR) 29562306a36Sopenharmony_ci * @type: string for the dev type (MAYBE NULL) 29662306a36Sopenharmony_ci * @flags: mount flags to match 29762306a36Sopenharmony_ci * @data: fs mount data (MAYBE NULL) 29862306a36Sopenharmony_ci * @binary: whether @data is binary 29962306a36Sopenharmony_ci * @devinfo: error str if (IS_ERR(@devname)) 30062306a36Sopenharmony_ci * 30162306a36Sopenharmony_ci * Returns: 0 on success else error 30262306a36Sopenharmony_ci */ 30362306a36Sopenharmony_cistatic int match_mnt_path_str(const struct cred *subj_cred, 30462306a36Sopenharmony_ci struct aa_profile *profile, 30562306a36Sopenharmony_ci const struct path *mntpath, char *buffer, 30662306a36Sopenharmony_ci const char *devname, const char *type, 30762306a36Sopenharmony_ci unsigned long flags, void *data, bool binary, 30862306a36Sopenharmony_ci const char *devinfo) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci struct aa_perms perms = { }; 31162306a36Sopenharmony_ci const char *mntpnt = NULL, *info = NULL; 31262306a36Sopenharmony_ci struct aa_ruleset *rules = list_first_entry(&profile->rules, 31362306a36Sopenharmony_ci typeof(*rules), list); 31462306a36Sopenharmony_ci int pos, error; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci AA_BUG(!profile); 31762306a36Sopenharmony_ci AA_BUG(!mntpath); 31862306a36Sopenharmony_ci AA_BUG(!buffer); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT)) 32162306a36Sopenharmony_ci return 0; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer, 32462306a36Sopenharmony_ci &mntpnt, &info, profile->disconnected); 32562306a36Sopenharmony_ci if (error) 32662306a36Sopenharmony_ci goto audit; 32762306a36Sopenharmony_ci if (IS_ERR(devname)) { 32862306a36Sopenharmony_ci error = PTR_ERR(devname); 32962306a36Sopenharmony_ci devname = NULL; 33062306a36Sopenharmony_ci info = devinfo; 33162306a36Sopenharmony_ci goto audit; 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci error = -EACCES; 33562306a36Sopenharmony_ci pos = do_match_mnt(&rules->policy, 33662306a36Sopenharmony_ci rules->policy.start[AA_CLASS_MOUNT], 33762306a36Sopenharmony_ci mntpnt, devname, type, flags, data, binary, &perms); 33862306a36Sopenharmony_ci if (pos) { 33962306a36Sopenharmony_ci info = mnt_info_table[pos]; 34062306a36Sopenharmony_ci goto audit; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci error = 0; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ciaudit: 34562306a36Sopenharmony_ci return audit_mount(subj_cred, profile, OP_MOUNT, mntpnt, devname, 34662306a36Sopenharmony_ci type, NULL, 34762306a36Sopenharmony_ci flags, data, AA_MAY_MOUNT, &perms, info, error); 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci/** 35162306a36Sopenharmony_ci * match_mnt - handle path matching for mount 35262306a36Sopenharmony_ci * @subj_cred: cred of the subject 35362306a36Sopenharmony_ci * @profile: the confining profile 35462306a36Sopenharmony_ci * @path: for the mntpnt (NOT NULL) 35562306a36Sopenharmony_ci * @buffer: buffer to be used to lookup mntpath 35662306a36Sopenharmony_ci * @devpath: path devname/src_name (MAYBE NULL) 35762306a36Sopenharmony_ci * @devbuffer: buffer to be used to lookup devname/src_name 35862306a36Sopenharmony_ci * @type: string for the dev type (MAYBE NULL) 35962306a36Sopenharmony_ci * @flags: mount flags to match 36062306a36Sopenharmony_ci * @data: fs mount data (MAYBE NULL) 36162306a36Sopenharmony_ci * @binary: whether @data is binary 36262306a36Sopenharmony_ci * 36362306a36Sopenharmony_ci * Returns: 0 on success else error 36462306a36Sopenharmony_ci */ 36562306a36Sopenharmony_cistatic int match_mnt(const struct cred *subj_cred, 36662306a36Sopenharmony_ci struct aa_profile *profile, const struct path *path, 36762306a36Sopenharmony_ci char *buffer, const struct path *devpath, char *devbuffer, 36862306a36Sopenharmony_ci const char *type, unsigned long flags, void *data, 36962306a36Sopenharmony_ci bool binary) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci const char *devname = NULL, *info = NULL; 37262306a36Sopenharmony_ci struct aa_ruleset *rules = list_first_entry(&profile->rules, 37362306a36Sopenharmony_ci typeof(*rules), list); 37462306a36Sopenharmony_ci int error = -EACCES; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci AA_BUG(!profile); 37762306a36Sopenharmony_ci AA_BUG(devpath && !devbuffer); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT)) 38062306a36Sopenharmony_ci return 0; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (devpath) { 38362306a36Sopenharmony_ci error = aa_path_name(devpath, path_flags(profile, devpath), 38462306a36Sopenharmony_ci devbuffer, &devname, &info, 38562306a36Sopenharmony_ci profile->disconnected); 38662306a36Sopenharmony_ci if (error) 38762306a36Sopenharmony_ci devname = ERR_PTR(error); 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci return match_mnt_path_str(subj_cred, profile, path, buffer, devname, 39162306a36Sopenharmony_ci type, flags, data, binary, info); 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ciint aa_remount(const struct cred *subj_cred, 39562306a36Sopenharmony_ci struct aa_label *label, const struct path *path, 39662306a36Sopenharmony_ci unsigned long flags, void *data) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci struct aa_profile *profile; 39962306a36Sopenharmony_ci char *buffer = NULL; 40062306a36Sopenharmony_ci bool binary; 40162306a36Sopenharmony_ci int error; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci AA_BUG(!label); 40462306a36Sopenharmony_ci AA_BUG(!path); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci buffer = aa_get_buffer(false); 40962306a36Sopenharmony_ci if (!buffer) 41062306a36Sopenharmony_ci return -ENOMEM; 41162306a36Sopenharmony_ci error = fn_for_each_confined(label, profile, 41262306a36Sopenharmony_ci match_mnt(subj_cred, profile, path, buffer, NULL, 41362306a36Sopenharmony_ci NULL, NULL, 41462306a36Sopenharmony_ci flags, data, binary)); 41562306a36Sopenharmony_ci aa_put_buffer(buffer); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci return error; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ciint aa_bind_mount(const struct cred *subj_cred, 42162306a36Sopenharmony_ci struct aa_label *label, const struct path *path, 42262306a36Sopenharmony_ci const char *dev_name, unsigned long flags) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci struct aa_profile *profile; 42562306a36Sopenharmony_ci char *buffer = NULL, *old_buffer = NULL; 42662306a36Sopenharmony_ci struct path old_path; 42762306a36Sopenharmony_ci int error; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci AA_BUG(!label); 43062306a36Sopenharmony_ci AA_BUG(!path); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (!dev_name || !*dev_name) 43362306a36Sopenharmony_ci return -EINVAL; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci flags &= MS_REC | MS_BIND; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path); 43862306a36Sopenharmony_ci if (error) 43962306a36Sopenharmony_ci return error; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci buffer = aa_get_buffer(false); 44262306a36Sopenharmony_ci old_buffer = aa_get_buffer(false); 44362306a36Sopenharmony_ci error = -ENOMEM; 44462306a36Sopenharmony_ci if (!buffer || !old_buffer) 44562306a36Sopenharmony_ci goto out; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci error = fn_for_each_confined(label, profile, 44862306a36Sopenharmony_ci match_mnt(subj_cred, profile, path, buffer, &old_path, 44962306a36Sopenharmony_ci old_buffer, NULL, flags, NULL, false)); 45062306a36Sopenharmony_ciout: 45162306a36Sopenharmony_ci aa_put_buffer(buffer); 45262306a36Sopenharmony_ci aa_put_buffer(old_buffer); 45362306a36Sopenharmony_ci path_put(&old_path); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci return error; 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ciint aa_mount_change_type(const struct cred *subj_cred, 45962306a36Sopenharmony_ci struct aa_label *label, const struct path *path, 46062306a36Sopenharmony_ci unsigned long flags) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci struct aa_profile *profile; 46362306a36Sopenharmony_ci char *buffer = NULL; 46462306a36Sopenharmony_ci int error; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci AA_BUG(!label); 46762306a36Sopenharmony_ci AA_BUG(!path); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci /* These are the flags allowed by do_change_type() */ 47062306a36Sopenharmony_ci flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE | 47162306a36Sopenharmony_ci MS_UNBINDABLE); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci buffer = aa_get_buffer(false); 47462306a36Sopenharmony_ci if (!buffer) 47562306a36Sopenharmony_ci return -ENOMEM; 47662306a36Sopenharmony_ci error = fn_for_each_confined(label, profile, 47762306a36Sopenharmony_ci match_mnt(subj_cred, profile, path, buffer, NULL, 47862306a36Sopenharmony_ci NULL, NULL, 47962306a36Sopenharmony_ci flags, NULL, false)); 48062306a36Sopenharmony_ci aa_put_buffer(buffer); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci return error; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ciint aa_move_mount(const struct cred *subj_cred, 48662306a36Sopenharmony_ci struct aa_label *label, const struct path *from_path, 48762306a36Sopenharmony_ci const struct path *to_path) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci struct aa_profile *profile; 49062306a36Sopenharmony_ci char *to_buffer = NULL, *from_buffer = NULL; 49162306a36Sopenharmony_ci int error; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci AA_BUG(!label); 49462306a36Sopenharmony_ci AA_BUG(!from_path); 49562306a36Sopenharmony_ci AA_BUG(!to_path); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci to_buffer = aa_get_buffer(false); 49862306a36Sopenharmony_ci from_buffer = aa_get_buffer(false); 49962306a36Sopenharmony_ci error = -ENOMEM; 50062306a36Sopenharmony_ci if (!to_buffer || !from_buffer) 50162306a36Sopenharmony_ci goto out; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (!our_mnt(from_path->mnt)) 50462306a36Sopenharmony_ci /* moving a mount detached from the namespace */ 50562306a36Sopenharmony_ci from_path = NULL; 50662306a36Sopenharmony_ci error = fn_for_each_confined(label, profile, 50762306a36Sopenharmony_ci match_mnt(subj_cred, profile, to_path, to_buffer, 50862306a36Sopenharmony_ci from_path, from_buffer, 50962306a36Sopenharmony_ci NULL, MS_MOVE, NULL, false)); 51062306a36Sopenharmony_ciout: 51162306a36Sopenharmony_ci aa_put_buffer(to_buffer); 51262306a36Sopenharmony_ci aa_put_buffer(from_buffer); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return error; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ciint aa_move_mount_old(const struct cred *subj_cred, struct aa_label *label, 51862306a36Sopenharmony_ci const struct path *path, const char *orig_name) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci struct path old_path; 52162306a36Sopenharmony_ci int error; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci if (!orig_name || !*orig_name) 52462306a36Sopenharmony_ci return -EINVAL; 52562306a36Sopenharmony_ci error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); 52662306a36Sopenharmony_ci if (error) 52762306a36Sopenharmony_ci return error; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci error = aa_move_mount(subj_cred, label, &old_path, path); 53062306a36Sopenharmony_ci path_put(&old_path); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci return error; 53362306a36Sopenharmony_ci} 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ciint aa_new_mount(const struct cred *subj_cred, struct aa_label *label, 53662306a36Sopenharmony_ci const char *dev_name, const struct path *path, 53762306a36Sopenharmony_ci const char *type, unsigned long flags, void *data) 53862306a36Sopenharmony_ci{ 53962306a36Sopenharmony_ci struct aa_profile *profile; 54062306a36Sopenharmony_ci char *buffer = NULL, *dev_buffer = NULL; 54162306a36Sopenharmony_ci bool binary = true; 54262306a36Sopenharmony_ci int error; 54362306a36Sopenharmony_ci int requires_dev = 0; 54462306a36Sopenharmony_ci struct path tmp_path, *dev_path = NULL; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci AA_BUG(!label); 54762306a36Sopenharmony_ci AA_BUG(!path); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci if (type) { 55062306a36Sopenharmony_ci struct file_system_type *fstype; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci fstype = get_fs_type(type); 55362306a36Sopenharmony_ci if (!fstype) 55462306a36Sopenharmony_ci return -ENODEV; 55562306a36Sopenharmony_ci binary = fstype->fs_flags & FS_BINARY_MOUNTDATA; 55662306a36Sopenharmony_ci requires_dev = fstype->fs_flags & FS_REQUIRES_DEV; 55762306a36Sopenharmony_ci put_filesystem(fstype); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci if (requires_dev) { 56062306a36Sopenharmony_ci if (!dev_name || !*dev_name) 56162306a36Sopenharmony_ci return -ENOENT; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path); 56462306a36Sopenharmony_ci if (error) 56562306a36Sopenharmony_ci return error; 56662306a36Sopenharmony_ci dev_path = &tmp_path; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci buffer = aa_get_buffer(false); 57162306a36Sopenharmony_ci if (!buffer) { 57262306a36Sopenharmony_ci error = -ENOMEM; 57362306a36Sopenharmony_ci goto out; 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci if (dev_path) { 57662306a36Sopenharmony_ci dev_buffer = aa_get_buffer(false); 57762306a36Sopenharmony_ci if (!dev_buffer) { 57862306a36Sopenharmony_ci error = -ENOMEM; 57962306a36Sopenharmony_ci goto out; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci error = fn_for_each_confined(label, profile, 58262306a36Sopenharmony_ci match_mnt(subj_cred, profile, path, buffer, 58362306a36Sopenharmony_ci dev_path, dev_buffer, 58462306a36Sopenharmony_ci type, flags, data, binary)); 58562306a36Sopenharmony_ci } else { 58662306a36Sopenharmony_ci error = fn_for_each_confined(label, profile, 58762306a36Sopenharmony_ci match_mnt_path_str(subj_cred, profile, path, 58862306a36Sopenharmony_ci buffer, dev_name, 58962306a36Sopenharmony_ci type, flags, data, binary, NULL)); 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ciout: 59362306a36Sopenharmony_ci aa_put_buffer(buffer); 59462306a36Sopenharmony_ci aa_put_buffer(dev_buffer); 59562306a36Sopenharmony_ci if (dev_path) 59662306a36Sopenharmony_ci path_put(dev_path); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci return error; 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_cistatic int profile_umount(const struct cred *subj_cred, 60262306a36Sopenharmony_ci struct aa_profile *profile, const struct path *path, 60362306a36Sopenharmony_ci char *buffer) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci struct aa_ruleset *rules = list_first_entry(&profile->rules, 60662306a36Sopenharmony_ci typeof(*rules), list); 60762306a36Sopenharmony_ci struct aa_perms perms = { }; 60862306a36Sopenharmony_ci const char *name = NULL, *info = NULL; 60962306a36Sopenharmony_ci aa_state_t state; 61062306a36Sopenharmony_ci int error; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci AA_BUG(!profile); 61362306a36Sopenharmony_ci AA_BUG(!path); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT)) 61662306a36Sopenharmony_ci return 0; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci error = aa_path_name(path, path_flags(profile, path), buffer, &name, 61962306a36Sopenharmony_ci &info, profile->disconnected); 62062306a36Sopenharmony_ci if (error) 62162306a36Sopenharmony_ci goto audit; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci state = aa_dfa_match(rules->policy.dfa, 62462306a36Sopenharmony_ci rules->policy.start[AA_CLASS_MOUNT], 62562306a36Sopenharmony_ci name); 62662306a36Sopenharmony_ci perms = *aa_lookup_perms(&rules->policy, state); 62762306a36Sopenharmony_ci if (AA_MAY_UMOUNT & ~perms.allow) 62862306a36Sopenharmony_ci error = -EACCES; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ciaudit: 63162306a36Sopenharmony_ci return audit_mount(subj_cred, profile, OP_UMOUNT, name, NULL, NULL, 63262306a36Sopenharmony_ci NULL, 0, NULL, 63362306a36Sopenharmony_ci AA_MAY_UMOUNT, &perms, info, error); 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ciint aa_umount(const struct cred *subj_cred, struct aa_label *label, 63762306a36Sopenharmony_ci struct vfsmount *mnt, int flags) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci struct aa_profile *profile; 64062306a36Sopenharmony_ci char *buffer = NULL; 64162306a36Sopenharmony_ci int error; 64262306a36Sopenharmony_ci struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci AA_BUG(!label); 64562306a36Sopenharmony_ci AA_BUG(!mnt); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci buffer = aa_get_buffer(false); 64862306a36Sopenharmony_ci if (!buffer) 64962306a36Sopenharmony_ci return -ENOMEM; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci error = fn_for_each_confined(label, profile, 65262306a36Sopenharmony_ci profile_umount(subj_cred, profile, &path, buffer)); 65362306a36Sopenharmony_ci aa_put_buffer(buffer); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci return error; 65662306a36Sopenharmony_ci} 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci/* helper fn for transition on pivotroot 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * Returns: label for transition or ERR_PTR. Does not return NULL 66162306a36Sopenharmony_ci */ 66262306a36Sopenharmony_cistatic struct aa_label *build_pivotroot(const struct cred *subj_cred, 66362306a36Sopenharmony_ci struct aa_profile *profile, 66462306a36Sopenharmony_ci const struct path *new_path, 66562306a36Sopenharmony_ci char *new_buffer, 66662306a36Sopenharmony_ci const struct path *old_path, 66762306a36Sopenharmony_ci char *old_buffer) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct aa_ruleset *rules = list_first_entry(&profile->rules, 67062306a36Sopenharmony_ci typeof(*rules), list); 67162306a36Sopenharmony_ci const char *old_name, *new_name = NULL, *info = NULL; 67262306a36Sopenharmony_ci const char *trans_name = NULL; 67362306a36Sopenharmony_ci struct aa_perms perms = { }; 67462306a36Sopenharmony_ci aa_state_t state; 67562306a36Sopenharmony_ci int error; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci AA_BUG(!profile); 67862306a36Sopenharmony_ci AA_BUG(!new_path); 67962306a36Sopenharmony_ci AA_BUG(!old_path); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci if (profile_unconfined(profile) || 68262306a36Sopenharmony_ci !RULE_MEDIATES(rules, AA_CLASS_MOUNT)) 68362306a36Sopenharmony_ci return aa_get_newest_label(&profile->label); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci error = aa_path_name(old_path, path_flags(profile, old_path), 68662306a36Sopenharmony_ci old_buffer, &old_name, &info, 68762306a36Sopenharmony_ci profile->disconnected); 68862306a36Sopenharmony_ci if (error) 68962306a36Sopenharmony_ci goto audit; 69062306a36Sopenharmony_ci error = aa_path_name(new_path, path_flags(profile, new_path), 69162306a36Sopenharmony_ci new_buffer, &new_name, &info, 69262306a36Sopenharmony_ci profile->disconnected); 69362306a36Sopenharmony_ci if (error) 69462306a36Sopenharmony_ci goto audit; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci error = -EACCES; 69762306a36Sopenharmony_ci state = aa_dfa_match(rules->policy.dfa, 69862306a36Sopenharmony_ci rules->policy.start[AA_CLASS_MOUNT], 69962306a36Sopenharmony_ci new_name); 70062306a36Sopenharmony_ci state = aa_dfa_null_transition(rules->policy.dfa, state); 70162306a36Sopenharmony_ci state = aa_dfa_match(rules->policy.dfa, state, old_name); 70262306a36Sopenharmony_ci perms = *aa_lookup_perms(&rules->policy, state); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci if (AA_MAY_PIVOTROOT & perms.allow) 70562306a36Sopenharmony_ci error = 0; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ciaudit: 70862306a36Sopenharmony_ci error = audit_mount(subj_cred, profile, OP_PIVOTROOT, new_name, 70962306a36Sopenharmony_ci old_name, 71062306a36Sopenharmony_ci NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT, 71162306a36Sopenharmony_ci &perms, info, error); 71262306a36Sopenharmony_ci if (error) 71362306a36Sopenharmony_ci return ERR_PTR(error); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci return aa_get_newest_label(&profile->label); 71662306a36Sopenharmony_ci} 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ciint aa_pivotroot(const struct cred *subj_cred, struct aa_label *label, 71962306a36Sopenharmony_ci const struct path *old_path, 72062306a36Sopenharmony_ci const struct path *new_path) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci struct aa_profile *profile; 72362306a36Sopenharmony_ci struct aa_label *target = NULL; 72462306a36Sopenharmony_ci char *old_buffer = NULL, *new_buffer = NULL, *info = NULL; 72562306a36Sopenharmony_ci int error; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci AA_BUG(!label); 72862306a36Sopenharmony_ci AA_BUG(!old_path); 72962306a36Sopenharmony_ci AA_BUG(!new_path); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci old_buffer = aa_get_buffer(false); 73262306a36Sopenharmony_ci new_buffer = aa_get_buffer(false); 73362306a36Sopenharmony_ci error = -ENOMEM; 73462306a36Sopenharmony_ci if (!old_buffer || !new_buffer) 73562306a36Sopenharmony_ci goto out; 73662306a36Sopenharmony_ci target = fn_label_build(label, profile, GFP_KERNEL, 73762306a36Sopenharmony_ci build_pivotroot(subj_cred, profile, new_path, 73862306a36Sopenharmony_ci new_buffer, 73962306a36Sopenharmony_ci old_path, old_buffer)); 74062306a36Sopenharmony_ci if (!target) { 74162306a36Sopenharmony_ci info = "label build failed"; 74262306a36Sopenharmony_ci error = -ENOMEM; 74362306a36Sopenharmony_ci goto fail; 74462306a36Sopenharmony_ci } else if (!IS_ERR(target)) { 74562306a36Sopenharmony_ci error = aa_replace_current_label(target); 74662306a36Sopenharmony_ci if (error) { 74762306a36Sopenharmony_ci /* TODO: audit target */ 74862306a36Sopenharmony_ci aa_put_label(target); 74962306a36Sopenharmony_ci goto out; 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci aa_put_label(target); 75262306a36Sopenharmony_ci } else 75362306a36Sopenharmony_ci /* already audited error */ 75462306a36Sopenharmony_ci error = PTR_ERR(target); 75562306a36Sopenharmony_ciout: 75662306a36Sopenharmony_ci aa_put_buffer(old_buffer); 75762306a36Sopenharmony_ci aa_put_buffer(new_buffer); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci return error; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_cifail: 76262306a36Sopenharmony_ci /* TODO: add back in auditing of new_name and old_name */ 76362306a36Sopenharmony_ci error = fn_for_each(label, profile, 76462306a36Sopenharmony_ci audit_mount(subj_cred, profile, OP_PIVOTROOT, 76562306a36Sopenharmony_ci NULL /*new_name */, 76662306a36Sopenharmony_ci NULL /* old_name */, 76762306a36Sopenharmony_ci NULL, NULL, 76862306a36Sopenharmony_ci 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info, 76962306a36Sopenharmony_ci error)); 77062306a36Sopenharmony_ci goto out; 77162306a36Sopenharmony_ci} 772