^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * AppArmor security module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file contains AppArmor mediation of files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 1998-2008 Novell/SUSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright 2009-2017 Canonical Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <uapi/linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "include/apparmor.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "include/audit.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "include/cred.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "include/domain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "include/file.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "include/match.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "include/mount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "include/path.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "include/policy.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (flags & MS_RDONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) audit_log_format(ab, "ro");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) audit_log_format(ab, "rw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (flags & MS_NOSUID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) audit_log_format(ab, ", nosuid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (flags & MS_NODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) audit_log_format(ab, ", nodev");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (flags & MS_NOEXEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) audit_log_format(ab, ", noexec");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (flags & MS_SYNCHRONOUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) audit_log_format(ab, ", sync");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (flags & MS_REMOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) audit_log_format(ab, ", remount");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (flags & MS_MANDLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) audit_log_format(ab, ", mand");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (flags & MS_DIRSYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) audit_log_format(ab, ", dirsync");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (flags & MS_NOATIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) audit_log_format(ab, ", noatime");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (flags & MS_NODIRATIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) audit_log_format(ab, ", nodiratime");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (flags & MS_BIND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (flags & MS_MOVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) audit_log_format(ab, ", move");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (flags & MS_SILENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) audit_log_format(ab, ", silent");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (flags & MS_POSIXACL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) audit_log_format(ab, ", acl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (flags & MS_UNBINDABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) audit_log_format(ab, flags & MS_REC ? ", runbindable" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ", unbindable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (flags & MS_PRIVATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) audit_log_format(ab, flags & MS_REC ? ", rprivate" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ", private");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (flags & MS_SLAVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) audit_log_format(ab, flags & MS_REC ? ", rslave" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ", slave");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (flags & MS_SHARED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) audit_log_format(ab, flags & MS_REC ? ", rshared" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ", shared");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (flags & MS_RELATIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) audit_log_format(ab, ", relatime");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (flags & MS_I_VERSION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) audit_log_format(ab, ", iversion");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (flags & MS_STRICTATIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) audit_log_format(ab, ", strictatime");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (flags & MS_NOUSER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) audit_log_format(ab, ", nouser");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * audit_cb - call back for mount specific audit fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * @ab: audit_buffer (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @va: audit struct to audit values of (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static void audit_cb(struct audit_buffer *ab, void *va)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct common_audit_data *sa = va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (aad(sa)->mnt.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) audit_log_format(ab, " fstype=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) audit_log_untrustedstring(ab, aad(sa)->mnt.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (aad(sa)->mnt.src_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) audit_log_format(ab, " srcname=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) audit_log_untrustedstring(ab, aad(sa)->mnt.src_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (aad(sa)->mnt.trans) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) audit_log_format(ab, " trans=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) audit_log_untrustedstring(ab, aad(sa)->mnt.trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (aad(sa)->mnt.flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) audit_log_format(ab, " flags=\"");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) audit_mnt_flags(ab, aad(sa)->mnt.flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) audit_log_format(ab, "\"");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (aad(sa)->mnt.data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) audit_log_format(ab, " options=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) audit_log_untrustedstring(ab, aad(sa)->mnt.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * audit_mount - handle the auditing of mount operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @profile: the profile being enforced (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @op: operation being mediated (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @name: name of object being mediated (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @src_name: src_name of object being mediated (MAYBE_NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @type: type of filesystem (MAYBE_NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * @trans: name of trans (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * @flags: filesystem independent mount flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @data: filesystem mount flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @request: permissions requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @perms: the permissions computed for the request (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @info: extra information message (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @error: 0 if operation allowed else failure error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * Returns: %0 or error on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int audit_mount(struct aa_profile *profile, const char *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) const char *name, const char *src_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) const char *type, const char *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned long flags, const void *data, u32 request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct aa_perms *perms, const char *info, int error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int audit_type = AUDIT_APPARMOR_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (likely(!error)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u32 mask = perms->audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) mask = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* mask off perms that are not being force audited */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) request &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (likely(!request))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) audit_type = AUDIT_APPARMOR_AUDIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* only report permissions that were denied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) request = request & ~perms->allow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (request & perms->kill)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) audit_type = AUDIT_APPARMOR_KILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* quiet known rejects, assumes quiet and kill do not overlap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if ((request & perms->quiet) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) AUDIT_MODE(profile) != AUDIT_NOQUIET &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) AUDIT_MODE(profile) != AUDIT_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) request &= ~perms->quiet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) aad(&sa)->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) aad(&sa)->mnt.src_name = src_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) aad(&sa)->mnt.type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) aad(&sa)->mnt.trans = trans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) aad(&sa)->mnt.flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (data && (perms->audit & AA_AUDIT_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) aad(&sa)->mnt.data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) aad(&sa)->info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) aad(&sa)->error = error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return aa_audit(audit_type, profile, &sa, audit_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * match_mnt_flags - Do an ordered match on mount flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * @dfa: dfa to match against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @state: state to start in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * @flags: mount flags to match against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * Mount flags are encoded as an ordered match. This is done instead of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * checking against a simple bitmask, to allow for logical operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * on the flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * Returns: next state after flags match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (i = 0; i <= 31 ; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if ((1 << i) & flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) state = aa_dfa_next(dfa, state, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * compute_mnt_perms - compute mount permission associated with @state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * @dfa: dfa to match against (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @state: state match finished in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * Returns: mount permissions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) unsigned int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct aa_perms perms = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .allow = dfa_user_allow(dfa, state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .audit = dfa_user_audit(dfa, state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .quiet = dfa_user_quiet(dfa, state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .xindex = dfa_user_xindex(dfa, state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return perms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static const char * const mnt_info_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) "match succeeded",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) "failed mntpnt match",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) "failed srcname match",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) "failed type match",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "failed flags match",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) "failed data match"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * Returns 0 on success else element that match failed in, this is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * index into the mnt_info_table above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) const char *mntpnt, const char *devname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) const char *type, unsigned long flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) void *data, bool binary, struct aa_perms *perms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) AA_BUG(!dfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) AA_BUG(!perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) state = aa_dfa_match(dfa, start, mntpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) state = aa_dfa_null_transition(dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (devname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) state = aa_dfa_match(dfa, state, devname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) state = aa_dfa_null_transition(dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) state = aa_dfa_match(dfa, state, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) state = aa_dfa_null_transition(dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) state = match_mnt_flags(dfa, state, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *perms = compute_mnt_perms(dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (perms->allow & AA_MAY_MOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* only match data if not binary and the DFA flags data is expected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) state = aa_dfa_null_transition(dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) state = aa_dfa_match(dfa, state, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *perms = compute_mnt_perms(dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (perms->allow & AA_MAY_MOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /* failed at end of flags match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int path_flags(struct aa_profile *profile, const struct path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) AA_BUG(!path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return profile->path_flags |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * match_mnt_path_str - handle path matching for mount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * @profile: the confining profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * @mntpath: for the mntpnt (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * @buffer: buffer to be used to lookup mntpath
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * @type: string for the dev type (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * @flags: mount flags to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * @data: fs mount data (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * @binary: whether @data is binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * @devinfo: error str if (IS_ERR(@devname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * Returns: 0 on success else error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int match_mnt_path_str(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) const struct path *mntpath, char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) const char *devname, const char *type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) unsigned long flags, void *data, bool binary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) const char *devinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct aa_perms perms = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) const char *mntpnt = NULL, *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int pos, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) AA_BUG(!mntpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) AA_BUG(!buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) &mntpnt, &info, profile->disconnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (IS_ERR(devname)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) error = PTR_ERR(devname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) devname = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) info = devinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) pos = do_match_mnt(profile->policy.dfa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) profile->policy.start[AA_CLASS_MOUNT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) mntpnt, devname, type, flags, data, binary, &perms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) info = mnt_info_table[pos];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) audit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) flags, data, AA_MAY_MOUNT, &perms, info, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * match_mnt - handle path matching for mount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * @profile: the confining profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * @mntpath: for the mntpnt (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * @buffer: buffer to be used to lookup mntpath
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * @devpath: path devname/src_name (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * @devbuffer: buffer to be used to lookup devname/src_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * @type: string for the dev type (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * @flags: mount flags to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * @data: fs mount data (MAYBE NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * @binary: whether @data is binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * Returns: 0 on success else error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static int match_mnt(struct aa_profile *profile, const struct path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) char *buffer, struct path *devpath, char *devbuffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) const char *type, unsigned long flags, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) bool binary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) const char *devname = NULL, *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) AA_BUG(devpath && !devbuffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (devpath) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) error = aa_path_name(devpath, path_flags(profile, devpath),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) devbuffer, &devname, &info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) profile->disconnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) devname = ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return match_mnt_path_str(profile, path, buffer, devname, type, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) data, binary, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int aa_remount(struct aa_label *label, const struct path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned long flags, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) char *buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) bool binary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) AA_BUG(!path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) error = fn_for_each_confined(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) match_mnt(profile, path, buffer, NULL, NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) flags, data, binary));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) aa_put_buffer(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int aa_bind_mount(struct aa_label *label, const struct path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) const char *dev_name, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) char *buffer = NULL, *old_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct path old_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) AA_BUG(!path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (!dev_name || !*dev_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) flags &= MS_REC | MS_BIND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) old_buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!buffer || !old_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) error = fn_for_each_confined(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) match_mnt(profile, path, buffer, &old_path, old_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) NULL, flags, NULL, false));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) aa_put_buffer(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) aa_put_buffer(old_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) path_put(&old_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) int aa_mount_change_type(struct aa_label *label, const struct path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) char *buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) AA_BUG(!path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* These are the flags allowed by do_change_type() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) MS_UNBINDABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) error = fn_for_each_confined(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) match_mnt(profile, path, buffer, NULL, NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) flags, NULL, false));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) aa_put_buffer(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int aa_move_mount(struct aa_label *label, const struct path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) const char *orig_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) char *buffer = NULL, *old_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct path old_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) AA_BUG(!path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (!orig_name || !*orig_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) old_buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!buffer || !old_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) error = fn_for_each_confined(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) match_mnt(profile, path, buffer, &old_path, old_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) NULL, MS_MOVE, NULL, false));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) aa_put_buffer(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) aa_put_buffer(old_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) path_put(&old_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) int aa_new_mount(struct aa_label *label, const char *dev_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) const struct path *path, const char *type, unsigned long flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) char *buffer = NULL, *dev_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) bool binary = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) int requires_dev = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct path tmp_path, *dev_path = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) AA_BUG(!path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct file_system_type *fstype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) fstype = get_fs_type(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (!fstype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) put_filesystem(fstype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (requires_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (!dev_name || !*dev_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) dev_path = &tmp_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (!buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (dev_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) dev_buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (!dev_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) error = fn_for_each_confined(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) match_mnt(profile, path, buffer, dev_path, dev_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) type, flags, data, binary));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) error = fn_for_each_confined(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) match_mnt_path_str(profile, path, buffer, dev_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) type, flags, data, binary, NULL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) aa_put_buffer(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) aa_put_buffer(dev_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (dev_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) path_put(dev_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int profile_umount(struct aa_profile *profile, struct path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) char *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct aa_perms perms = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) const char *name = NULL, *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) unsigned int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) AA_BUG(!path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) error = aa_path_name(path, path_flags(profile, path), buffer, &name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) &info, profile->disconnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) state = aa_dfa_match(profile->policy.dfa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) profile->policy.start[AA_CLASS_MOUNT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) perms = compute_mnt_perms(profile->policy.dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (AA_MAY_UMOUNT & ~perms.allow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) audit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) AA_MAY_UMOUNT, &perms, info, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) char *buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) AA_BUG(!mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) error = fn_for_each_confined(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) profile_umount(profile, &path, buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) aa_put_buffer(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* helper fn for transition on pivotroot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * Returns: label for transition or ERR_PTR. Does not return NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static struct aa_label *build_pivotroot(struct aa_profile *profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) const struct path *new_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) char *new_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) const struct path *old_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) char *old_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) const char *old_name, *new_name = NULL, *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) const char *trans_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct aa_perms perms = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) unsigned int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) AA_BUG(!profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) AA_BUG(!new_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) AA_BUG(!old_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (profile_unconfined(profile) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) !PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return aa_get_newest_label(&profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) error = aa_path_name(old_path, path_flags(profile, old_path),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) old_buffer, &old_name, &info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) profile->disconnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) error = aa_path_name(new_path, path_flags(profile, new_path),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) new_buffer, &new_name, &info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) profile->disconnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) goto audit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) error = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) state = aa_dfa_match(profile->policy.dfa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) profile->policy.start[AA_CLASS_MOUNT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) new_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) state = aa_dfa_null_transition(profile->policy.dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) state = aa_dfa_match(profile->policy.dfa, state, old_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) perms = compute_mnt_perms(profile->policy.dfa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (AA_MAY_PIVOTROOT & perms.allow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) audit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) &perms, info, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return aa_get_newest_label(&profile->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) int aa_pivotroot(struct aa_label *label, const struct path *old_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) const struct path *new_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct aa_profile *profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct aa_label *target = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) char *old_buffer = NULL, *new_buffer = NULL, *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) AA_BUG(!old_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) AA_BUG(!new_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) old_buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) new_buffer = aa_get_buffer(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (!old_buffer || !new_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) target = fn_label_build(label, profile, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) build_pivotroot(profile, new_path, new_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) old_path, old_buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (!target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) info = "label build failed";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) } else if (!IS_ERR(target)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) error = aa_replace_current_label(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* TODO: audit target */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) aa_put_label(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /* already audited error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) error = PTR_ERR(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) aa_put_buffer(old_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) aa_put_buffer(new_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* TODO: add back in auditing of new_name and old_name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) error = fn_for_each(label, profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) NULL /* old_name */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) error));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }