Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * AppArmor security module
0004  *
0005  * This file contains AppArmor mediation of files
0006  *
0007  * Copyright (C) 1998-2008 Novell/SUSE
0008  * Copyright 2009-2017 Canonical Ltd.
0009  */
0010 
0011 #include <linux/fs.h>
0012 #include <linux/mount.h>
0013 #include <linux/namei.h>
0014 #include <uapi/linux/mount.h>
0015 
0016 #include "include/apparmor.h"
0017 #include "include/audit.h"
0018 #include "include/cred.h"
0019 #include "include/domain.h"
0020 #include "include/file.h"
0021 #include "include/match.h"
0022 #include "include/mount.h"
0023 #include "include/path.h"
0024 #include "include/policy.h"
0025 
0026 
0027 static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
0028 {
0029     if (flags & MS_RDONLY)
0030         audit_log_format(ab, "ro");
0031     else
0032         audit_log_format(ab, "rw");
0033     if (flags & MS_NOSUID)
0034         audit_log_format(ab, ", nosuid");
0035     if (flags & MS_NODEV)
0036         audit_log_format(ab, ", nodev");
0037     if (flags & MS_NOEXEC)
0038         audit_log_format(ab, ", noexec");
0039     if (flags & MS_SYNCHRONOUS)
0040         audit_log_format(ab, ", sync");
0041     if (flags & MS_REMOUNT)
0042         audit_log_format(ab, ", remount");
0043     if (flags & MS_MANDLOCK)
0044         audit_log_format(ab, ", mand");
0045     if (flags & MS_DIRSYNC)
0046         audit_log_format(ab, ", dirsync");
0047     if (flags & MS_NOATIME)
0048         audit_log_format(ab, ", noatime");
0049     if (flags & MS_NODIRATIME)
0050         audit_log_format(ab, ", nodiratime");
0051     if (flags & MS_BIND)
0052         audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
0053     if (flags & MS_MOVE)
0054         audit_log_format(ab, ", move");
0055     if (flags & MS_SILENT)
0056         audit_log_format(ab, ", silent");
0057     if (flags & MS_POSIXACL)
0058         audit_log_format(ab, ", acl");
0059     if (flags & MS_UNBINDABLE)
0060         audit_log_format(ab, flags & MS_REC ? ", runbindable" :
0061                  ", unbindable");
0062     if (flags & MS_PRIVATE)
0063         audit_log_format(ab, flags & MS_REC ? ", rprivate" :
0064                  ", private");
0065     if (flags & MS_SLAVE)
0066         audit_log_format(ab, flags & MS_REC ? ", rslave" :
0067                  ", slave");
0068     if (flags & MS_SHARED)
0069         audit_log_format(ab, flags & MS_REC ? ", rshared" :
0070                  ", shared");
0071     if (flags & MS_RELATIME)
0072         audit_log_format(ab, ", relatime");
0073     if (flags & MS_I_VERSION)
0074         audit_log_format(ab, ", iversion");
0075     if (flags & MS_STRICTATIME)
0076         audit_log_format(ab, ", strictatime");
0077     if (flags & MS_NOUSER)
0078         audit_log_format(ab, ", nouser");
0079 }
0080 
0081 /**
0082  * audit_cb - call back for mount specific audit fields
0083  * @ab: audit_buffer  (NOT NULL)
0084  * @va: audit struct to audit values of  (NOT NULL)
0085  */
0086 static void audit_cb(struct audit_buffer *ab, void *va)
0087 {
0088     struct common_audit_data *sa = va;
0089 
0090     if (aad(sa)->mnt.type) {
0091         audit_log_format(ab, " fstype=");
0092         audit_log_untrustedstring(ab, aad(sa)->mnt.type);
0093     }
0094     if (aad(sa)->mnt.src_name) {
0095         audit_log_format(ab, " srcname=");
0096         audit_log_untrustedstring(ab, aad(sa)->mnt.src_name);
0097     }
0098     if (aad(sa)->mnt.trans) {
0099         audit_log_format(ab, " trans=");
0100         audit_log_untrustedstring(ab, aad(sa)->mnt.trans);
0101     }
0102     if (aad(sa)->mnt.flags) {
0103         audit_log_format(ab, " flags=\"");
0104         audit_mnt_flags(ab, aad(sa)->mnt.flags);
0105         audit_log_format(ab, "\"");
0106     }
0107     if (aad(sa)->mnt.data) {
0108         audit_log_format(ab, " options=");
0109         audit_log_untrustedstring(ab, aad(sa)->mnt.data);
0110     }
0111 }
0112 
0113 /**
0114  * audit_mount - handle the auditing of mount operations
0115  * @profile: the profile being enforced  (NOT NULL)
0116  * @op: operation being mediated (NOT NULL)
0117  * @name: name of object being mediated (MAYBE NULL)
0118  * @src_name: src_name of object being mediated (MAYBE_NULL)
0119  * @type: type of filesystem (MAYBE_NULL)
0120  * @trans: name of trans (MAYBE NULL)
0121  * @flags: filesystem independent mount flags
0122  * @data: filesystem mount flags
0123  * @request: permissions requested
0124  * @perms: the permissions computed for the request (NOT NULL)
0125  * @info: extra information message (MAYBE NULL)
0126  * @error: 0 if operation allowed else failure error code
0127  *
0128  * Returns: %0 or error on failure
0129  */
0130 static int audit_mount(struct aa_profile *profile, const char *op,
0131                const char *name, const char *src_name,
0132                const char *type, const char *trans,
0133                unsigned long flags, const void *data, u32 request,
0134                struct aa_perms *perms, const char *info, int error)
0135 {
0136     int audit_type = AUDIT_APPARMOR_AUTO;
0137     DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
0138 
0139     if (likely(!error)) {
0140         u32 mask = perms->audit;
0141 
0142         if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
0143             mask = 0xffff;
0144 
0145         /* mask off perms that are not being force audited */
0146         request &= mask;
0147 
0148         if (likely(!request))
0149             return 0;
0150         audit_type = AUDIT_APPARMOR_AUDIT;
0151     } else {
0152         /* only report permissions that were denied */
0153         request = request & ~perms->allow;
0154 
0155         if (request & perms->kill)
0156             audit_type = AUDIT_APPARMOR_KILL;
0157 
0158         /* quiet known rejects, assumes quiet and kill do not overlap */
0159         if ((request & perms->quiet) &&
0160             AUDIT_MODE(profile) != AUDIT_NOQUIET &&
0161             AUDIT_MODE(profile) != AUDIT_ALL)
0162             request &= ~perms->quiet;
0163 
0164         if (!request)
0165             return error;
0166     }
0167 
0168     aad(&sa)->name = name;
0169     aad(&sa)->mnt.src_name = src_name;
0170     aad(&sa)->mnt.type = type;
0171     aad(&sa)->mnt.trans = trans;
0172     aad(&sa)->mnt.flags = flags;
0173     if (data && (perms->audit & AA_AUDIT_DATA))
0174         aad(&sa)->mnt.data = data;
0175     aad(&sa)->info = info;
0176     aad(&sa)->error = error;
0177 
0178     return aa_audit(audit_type, profile, &sa, audit_cb);
0179 }
0180 
0181 /**
0182  * match_mnt_flags - Do an ordered match on mount flags
0183  * @dfa: dfa to match against
0184  * @state: state to start in
0185  * @flags: mount flags to match against
0186  *
0187  * Mount flags are encoded as an ordered match. This is done instead of
0188  * checking against a simple bitmask, to allow for logical operations
0189  * on the flags.
0190  *
0191  * Returns: next state after flags match
0192  */
0193 static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
0194                     unsigned long flags)
0195 {
0196     unsigned int i;
0197 
0198     for (i = 0; i <= 31 ; ++i) {
0199         if ((1 << i) & flags)
0200             state = aa_dfa_next(dfa, state, i + 1);
0201     }
0202 
0203     return state;
0204 }
0205 
0206 /**
0207  * compute_mnt_perms - compute mount permission associated with @state
0208  * @dfa: dfa to match against (NOT NULL)
0209  * @state: state match finished in
0210  *
0211  * Returns: mount permissions
0212  */
0213 static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa,
0214                        unsigned int state)
0215 {
0216     struct aa_perms perms = {
0217         .allow = dfa_user_allow(dfa, state),
0218         .audit = dfa_user_audit(dfa, state),
0219         .quiet = dfa_user_quiet(dfa, state),
0220     };
0221 
0222     return perms;
0223 }
0224 
0225 static const char * const mnt_info_table[] = {
0226     "match succeeded",
0227     "failed mntpnt match",
0228     "failed srcname match",
0229     "failed type match",
0230     "failed flags match",
0231     "failed data match",
0232     "failed perms check"
0233 };
0234 
0235 /*
0236  * Returns 0 on success else element that match failed in, this is the
0237  * index into the mnt_info_table above
0238  */
0239 static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
0240             const char *mntpnt, const char *devname,
0241             const char *type, unsigned long flags,
0242             void *data, bool binary, struct aa_perms *perms)
0243 {
0244     unsigned int state;
0245 
0246     AA_BUG(!dfa);
0247     AA_BUG(!perms);
0248 
0249     state = aa_dfa_match(dfa, start, mntpnt);
0250     state = aa_dfa_null_transition(dfa, state);
0251     if (!state)
0252         return 1;
0253 
0254     if (devname)
0255         state = aa_dfa_match(dfa, state, devname);
0256     state = aa_dfa_null_transition(dfa, state);
0257     if (!state)
0258         return 2;
0259 
0260     if (type)
0261         state = aa_dfa_match(dfa, state, type);
0262     state = aa_dfa_null_transition(dfa, state);
0263     if (!state)
0264         return 3;
0265 
0266     state = match_mnt_flags(dfa, state, flags);
0267     if (!state)
0268         return 4;
0269     *perms = compute_mnt_perms(dfa, state);
0270     if (perms->allow & AA_MAY_MOUNT)
0271         return 0;
0272 
0273     /* only match data if not binary and the DFA flags data is expected */
0274     if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
0275         state = aa_dfa_null_transition(dfa, state);
0276         if (!state)
0277             return 4;
0278 
0279         state = aa_dfa_match(dfa, state, data);
0280         if (!state)
0281             return 5;
0282         *perms = compute_mnt_perms(dfa, state);
0283         if (perms->allow & AA_MAY_MOUNT)
0284             return 0;
0285     }
0286 
0287     /* failed at perms check, don't confuse with flags match */
0288     return 6;
0289 }
0290 
0291 
0292 static int path_flags(struct aa_profile *profile, const struct path *path)
0293 {
0294     AA_BUG(!profile);
0295     AA_BUG(!path);
0296 
0297     return profile->path_flags |
0298         (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0);
0299 }
0300 
0301 /**
0302  * match_mnt_path_str - handle path matching for mount
0303  * @profile: the confining profile
0304  * @mntpath: for the mntpnt (NOT NULL)
0305  * @buffer: buffer to be used to lookup mntpath
0306  * @devname: string for the devname/src_name (MAY BE NULL OR ERRPTR)
0307  * @type: string for the dev type (MAYBE NULL)
0308  * @flags: mount flags to match
0309  * @data: fs mount data (MAYBE NULL)
0310  * @binary: whether @data is binary
0311  * @devinfo: error str if (IS_ERR(@devname))
0312  *
0313  * Returns: 0 on success else error
0314  */
0315 static int match_mnt_path_str(struct aa_profile *profile,
0316                   const struct path *mntpath, char *buffer,
0317                   const char *devname, const char *type,
0318                   unsigned long flags, void *data, bool binary,
0319                   const char *devinfo)
0320 {
0321     struct aa_perms perms = { };
0322     const char *mntpnt = NULL, *info = NULL;
0323     int pos, error;
0324 
0325     AA_BUG(!profile);
0326     AA_BUG(!mntpath);
0327     AA_BUG(!buffer);
0328 
0329     if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
0330         return 0;
0331 
0332     error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
0333                  &mntpnt, &info, profile->disconnected);
0334     if (error)
0335         goto audit;
0336     if (IS_ERR(devname)) {
0337         error = PTR_ERR(devname);
0338         devname = NULL;
0339         info = devinfo;
0340         goto audit;
0341     }
0342 
0343     error = -EACCES;
0344     pos = do_match_mnt(profile->policy.dfa,
0345                profile->policy.start[AA_CLASS_MOUNT],
0346                mntpnt, devname, type, flags, data, binary, &perms);
0347     if (pos) {
0348         info = mnt_info_table[pos];
0349         goto audit;
0350     }
0351     error = 0;
0352 
0353 audit:
0354     return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL,
0355                flags, data, AA_MAY_MOUNT, &perms, info, error);
0356 }
0357 
0358 /**
0359  * match_mnt - handle path matching for mount
0360  * @profile: the confining profile
0361  * @path: for the mntpnt (NOT NULL)
0362  * @buffer: buffer to be used to lookup mntpath
0363  * @devpath: path devname/src_name (MAYBE NULL)
0364  * @devbuffer: buffer to be used to lookup devname/src_name
0365  * @type: string for the dev type (MAYBE NULL)
0366  * @flags: mount flags to match
0367  * @data: fs mount data (MAYBE NULL)
0368  * @binary: whether @data is binary
0369  *
0370  * Returns: 0 on success else error
0371  */
0372 static int match_mnt(struct aa_profile *profile, const struct path *path,
0373              char *buffer, const struct path *devpath, char *devbuffer,
0374              const char *type, unsigned long flags, void *data,
0375              bool binary)
0376 {
0377     const char *devname = NULL, *info = NULL;
0378     int error = -EACCES;
0379 
0380     AA_BUG(!profile);
0381     AA_BUG(devpath && !devbuffer);
0382 
0383     if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
0384         return 0;
0385 
0386     if (devpath) {
0387         error = aa_path_name(devpath, path_flags(profile, devpath),
0388                      devbuffer, &devname, &info,
0389                      profile->disconnected);
0390         if (error)
0391             devname = ERR_PTR(error);
0392     }
0393 
0394     return match_mnt_path_str(profile, path, buffer, devname, type, flags,
0395                   data, binary, info);
0396 }
0397 
0398 int aa_remount(struct aa_label *label, const struct path *path,
0399            unsigned long flags, void *data)
0400 {
0401     struct aa_profile *profile;
0402     char *buffer = NULL;
0403     bool binary;
0404     int error;
0405 
0406     AA_BUG(!label);
0407     AA_BUG(!path);
0408 
0409     binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
0410 
0411     buffer = aa_get_buffer(false);
0412     if (!buffer)
0413         return -ENOMEM;
0414     error = fn_for_each_confined(label, profile,
0415             match_mnt(profile, path, buffer, NULL, NULL, NULL,
0416                   flags, data, binary));
0417     aa_put_buffer(buffer);
0418 
0419     return error;
0420 }
0421 
0422 int aa_bind_mount(struct aa_label *label, const struct path *path,
0423           const char *dev_name, unsigned long flags)
0424 {
0425     struct aa_profile *profile;
0426     char *buffer = NULL, *old_buffer = NULL;
0427     struct path old_path;
0428     int error;
0429 
0430     AA_BUG(!label);
0431     AA_BUG(!path);
0432 
0433     if (!dev_name || !*dev_name)
0434         return -EINVAL;
0435 
0436     flags &= MS_REC | MS_BIND;
0437 
0438     error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
0439     if (error)
0440         return error;
0441 
0442     buffer = aa_get_buffer(false);
0443     old_buffer = aa_get_buffer(false);
0444     error = -ENOMEM;
0445     if (!buffer || !old_buffer)
0446         goto out;
0447 
0448     error = fn_for_each_confined(label, profile,
0449             match_mnt(profile, path, buffer, &old_path, old_buffer,
0450                   NULL, flags, NULL, false));
0451 out:
0452     aa_put_buffer(buffer);
0453     aa_put_buffer(old_buffer);
0454     path_put(&old_path);
0455 
0456     return error;
0457 }
0458 
0459 int aa_mount_change_type(struct aa_label *label, const struct path *path,
0460              unsigned long flags)
0461 {
0462     struct aa_profile *profile;
0463     char *buffer = NULL;
0464     int error;
0465 
0466     AA_BUG(!label);
0467     AA_BUG(!path);
0468 
0469     /* These are the flags allowed by do_change_type() */
0470     flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
0471           MS_UNBINDABLE);
0472 
0473     buffer = aa_get_buffer(false);
0474     if (!buffer)
0475         return -ENOMEM;
0476     error = fn_for_each_confined(label, profile,
0477             match_mnt(profile, path, buffer, NULL, NULL, NULL,
0478                   flags, NULL, false));
0479     aa_put_buffer(buffer);
0480 
0481     return error;
0482 }
0483 
0484 int aa_move_mount(struct aa_label *label, const struct path *path,
0485           const char *orig_name)
0486 {
0487     struct aa_profile *profile;
0488     char *buffer = NULL, *old_buffer = NULL;
0489     struct path old_path;
0490     int error;
0491 
0492     AA_BUG(!label);
0493     AA_BUG(!path);
0494 
0495     if (!orig_name || !*orig_name)
0496         return -EINVAL;
0497 
0498     error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
0499     if (error)
0500         return error;
0501 
0502     buffer = aa_get_buffer(false);
0503     old_buffer = aa_get_buffer(false);
0504     error = -ENOMEM;
0505     if (!buffer || !old_buffer)
0506         goto out;
0507     error = fn_for_each_confined(label, profile,
0508             match_mnt(profile, path, buffer, &old_path, old_buffer,
0509                   NULL, MS_MOVE, NULL, false));
0510 out:
0511     aa_put_buffer(buffer);
0512     aa_put_buffer(old_buffer);
0513     path_put(&old_path);
0514 
0515     return error;
0516 }
0517 
0518 int aa_new_mount(struct aa_label *label, const char *dev_name,
0519          const struct path *path, const char *type, unsigned long flags,
0520          void *data)
0521 {
0522     struct aa_profile *profile;
0523     char *buffer = NULL, *dev_buffer = NULL;
0524     bool binary = true;
0525     int error;
0526     int requires_dev = 0;
0527     struct path tmp_path, *dev_path = NULL;
0528 
0529     AA_BUG(!label);
0530     AA_BUG(!path);
0531 
0532     if (type) {
0533         struct file_system_type *fstype;
0534 
0535         fstype = get_fs_type(type);
0536         if (!fstype)
0537             return -ENODEV;
0538         binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
0539         requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
0540         put_filesystem(fstype);
0541 
0542         if (requires_dev) {
0543             if (!dev_name || !*dev_name)
0544                 return -ENOENT;
0545 
0546             error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path);
0547             if (error)
0548                 return error;
0549             dev_path = &tmp_path;
0550         }
0551     }
0552 
0553     buffer = aa_get_buffer(false);
0554     if (!buffer) {
0555         error = -ENOMEM;
0556         goto out;
0557     }
0558     if (dev_path) {
0559         dev_buffer = aa_get_buffer(false);
0560         if (!dev_buffer) {
0561             error = -ENOMEM;
0562             goto out;
0563         }
0564         error = fn_for_each_confined(label, profile,
0565             match_mnt(profile, path, buffer, dev_path, dev_buffer,
0566                   type, flags, data, binary));
0567     } else {
0568         error = fn_for_each_confined(label, profile,
0569             match_mnt_path_str(profile, path, buffer, dev_name,
0570                        type, flags, data, binary, NULL));
0571     }
0572 
0573 out:
0574     aa_put_buffer(buffer);
0575     aa_put_buffer(dev_buffer);
0576     if (dev_path)
0577         path_put(dev_path);
0578 
0579     return error;
0580 }
0581 
0582 static int profile_umount(struct aa_profile *profile, const struct path *path,
0583               char *buffer)
0584 {
0585     struct aa_perms perms = { };
0586     const char *name = NULL, *info = NULL;
0587     unsigned int state;
0588     int error;
0589 
0590     AA_BUG(!profile);
0591     AA_BUG(!path);
0592 
0593     if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
0594         return 0;
0595 
0596     error = aa_path_name(path, path_flags(profile, path), buffer, &name,
0597                  &info, profile->disconnected);
0598     if (error)
0599         goto audit;
0600 
0601     state = aa_dfa_match(profile->policy.dfa,
0602                  profile->policy.start[AA_CLASS_MOUNT],
0603                  name);
0604     perms = compute_mnt_perms(profile->policy.dfa, state);
0605     if (AA_MAY_UMOUNT & ~perms.allow)
0606         error = -EACCES;
0607 
0608 audit:
0609     return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
0610                AA_MAY_UMOUNT, &perms, info, error);
0611 }
0612 
0613 int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
0614 {
0615     struct aa_profile *profile;
0616     char *buffer = NULL;
0617     int error;
0618     struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
0619 
0620     AA_BUG(!label);
0621     AA_BUG(!mnt);
0622 
0623     buffer = aa_get_buffer(false);
0624     if (!buffer)
0625         return -ENOMEM;
0626 
0627     error = fn_for_each_confined(label, profile,
0628             profile_umount(profile, &path, buffer));
0629     aa_put_buffer(buffer);
0630 
0631     return error;
0632 }
0633 
0634 /* helper fn for transition on pivotroot
0635  *
0636  * Returns: label for transition or ERR_PTR. Does not return NULL
0637  */
0638 static struct aa_label *build_pivotroot(struct aa_profile *profile,
0639                     const struct path *new_path,
0640                     char *new_buffer,
0641                     const struct path *old_path,
0642                     char *old_buffer)
0643 {
0644     const char *old_name, *new_name = NULL, *info = NULL;
0645     const char *trans_name = NULL;
0646     struct aa_perms perms = { };
0647     unsigned int state;
0648     int error;
0649 
0650     AA_BUG(!profile);
0651     AA_BUG(!new_path);
0652     AA_BUG(!old_path);
0653 
0654     if (profile_unconfined(profile) ||
0655         !PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
0656         return aa_get_newest_label(&profile->label);
0657 
0658     error = aa_path_name(old_path, path_flags(profile, old_path),
0659                  old_buffer, &old_name, &info,
0660                  profile->disconnected);
0661     if (error)
0662         goto audit;
0663     error = aa_path_name(new_path, path_flags(profile, new_path),
0664                  new_buffer, &new_name, &info,
0665                  profile->disconnected);
0666     if (error)
0667         goto audit;
0668 
0669     error = -EACCES;
0670     state = aa_dfa_match(profile->policy.dfa,
0671                  profile->policy.start[AA_CLASS_MOUNT],
0672                  new_name);
0673     state = aa_dfa_null_transition(profile->policy.dfa, state);
0674     state = aa_dfa_match(profile->policy.dfa, state, old_name);
0675     perms = compute_mnt_perms(profile->policy.dfa, state);
0676 
0677     if (AA_MAY_PIVOTROOT & perms.allow)
0678         error = 0;
0679 
0680 audit:
0681     error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
0682                 NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
0683                 &perms, info, error);
0684     if (error)
0685         return ERR_PTR(error);
0686 
0687     return aa_get_newest_label(&profile->label);
0688 }
0689 
0690 int aa_pivotroot(struct aa_label *label, const struct path *old_path,
0691          const struct path *new_path)
0692 {
0693     struct aa_profile *profile;
0694     struct aa_label *target = NULL;
0695     char *old_buffer = NULL, *new_buffer = NULL, *info = NULL;
0696     int error;
0697 
0698     AA_BUG(!label);
0699     AA_BUG(!old_path);
0700     AA_BUG(!new_path);
0701 
0702     old_buffer = aa_get_buffer(false);
0703     new_buffer = aa_get_buffer(false);
0704     error = -ENOMEM;
0705     if (!old_buffer || !new_buffer)
0706         goto out;
0707     target = fn_label_build(label, profile, GFP_KERNEL,
0708             build_pivotroot(profile, new_path, new_buffer,
0709                     old_path, old_buffer));
0710     if (!target) {
0711         info = "label build failed";
0712         error = -ENOMEM;
0713         goto fail;
0714     } else if (!IS_ERR(target)) {
0715         error = aa_replace_current_label(target);
0716         if (error) {
0717             /* TODO: audit target */
0718             aa_put_label(target);
0719             goto out;
0720         }
0721         aa_put_label(target);
0722     } else
0723         /* already audited error */
0724         error = PTR_ERR(target);
0725 out:
0726     aa_put_buffer(old_buffer);
0727     aa_put_buffer(new_buffer);
0728 
0729     return error;
0730 
0731 fail:
0732     /* TODO: add back in auditing of new_name and old_name */
0733     error = fn_for_each(label, profile,
0734             audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */,
0735                     NULL /* old_name */,
0736                     NULL, NULL,
0737                     0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
0738                     error));
0739     goto out;
0740 }