Add support for chroot rules, which allow a profile to specify where a chroot can be made.
chroot /tmp/example, Signed-off-by: John Johansen <[email protected]> --- security/apparmor/apparmorfs.c | 1 + security/apparmor/audit.c | 1 + security/apparmor/include/apparmor.h | 3 +- security/apparmor/include/audit.h | 1 + security/apparmor/include/mount.h | 4 +++ security/apparmor/lsm.c | 13 ++++++++++ security/apparmor/mount.c | 42 ++++++++++++++++++++++++++++++++++ 7 files changed, 64 insertions(+), 1 deletions(-) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index d30aa11..32c1394 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -437,6 +437,7 @@ static struct aa_fs_entry aa_fs_entry_mount[] = { static struct aa_fs_entry aa_fs_entry_namespaces[] = { AA_FS_FILE_BOOLEAN("profile", 1), AA_FS_FILE_BOOLEAN("pivot_root", 1), + AA_FS_FILE_BOOLEAN("chroot", 1), }; static struct aa_fs_entry aa_fs_entry_features[] = { diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 64e9442..4c80d4f 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -47,6 +47,7 @@ const char *op_table[] = { "pivotroot", "mount", "umount", + "chroot", "create", "post_create", diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h index d615726..5f4b32e 100644 --- a/security/apparmor/include/apparmor.h +++ b/security/apparmor/include/apparmor.h @@ -30,8 +30,9 @@ #define AA_CLASS_RLIMITS 5 #define AA_CLASS_DOMAIN 6 #define AA_CLASS_MOUNT 7 +#define AA_CLASS_CHROOT 8 -#define AA_CLASS_LAST AA_CLASS_MOUNT +#define AA_CLASS_LAST AA_CLASS_CHROOT /* Control parameters settable through module/boot flags */ extern enum audit_mode aa_g_audit; diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index 0e8689d..693f37f 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -76,6 +76,7 @@ enum aa_ops { OP_PIVOTROOT, OP_MOUNT, OP_UMOUNT, + OP_CHROOT, OP_CREATE, OP_POST_CREATE, diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h index 6f936bc..a1c5026 100644 --- a/security/apparmor/include/mount.h +++ b/security/apparmor/include/mount.h @@ -27,6 +27,8 @@ #define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN) +/* chroot permissions */ +#define AA_MAY_CHROOT 0x01 int aa_remount(struct aa_profile *profile, struct path *path, unsigned long flags, void *data); @@ -50,4 +52,6 @@ int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags); int aa_pivotroot(struct aa_profile *profile, struct path *old_path, struct path *new_path); +int aa_chroot(struct aa_profile *profile, struct path *path); + #endif /* __AA_MOUNT_H */ diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 3aec025..507ba44 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -544,6 +544,18 @@ static int apparmor_sb_mount(char *dev_name, struct path *path, char *type, return error; } +static int apparmor_path_chroot(struct path *path) +{ + struct aa_profile *profile; + int error = 0; + + profile = __aa_current_profile(); + if (!unconfined(profile)) + error = aa_chroot(profile, path); + + return error; +} + static int apparmor_sb_umount(struct vfsmount *mnt, int flags) { struct aa_profile *profile; @@ -786,6 +798,7 @@ static struct security_operations apparmor_ops = { .sb_mount = apparmor_sb_mount, .sb_umount = apparmor_sb_umount, .sb_pivotroot = apparmor_sb_pivotroot, + .path_chroot = apparmor_path_chroot, .path_link = apparmor_path_link, .path_unlink = apparmor_path_unlink, diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c index 1572bf6..86f6102 100644 --- a/security/apparmor/mount.c +++ b/security/apparmor/mount.c @@ -587,3 +587,45 @@ audit: return error; } + +int aa_chroot(struct aa_profile *profile, struct path *path) +{ + struct file_perms perms = { }; + struct aa_profile *target = NULL; + char *buffer = NULL; + const char *name, *info = NULL; + int error; + + error = aa_path_name(path, profile->path_flags, &buffer, &name, &info); + if (error) + goto audit; + + if (profile->policy.dfa) { + unsigned int state; + state = aa_dfa_match(profile->policy.dfa, + profile->policy.start[AA_CLASS_CHROOT], + name); + perms = compute_mnt_perms(profile->policy.dfa, state); + } + + if (AA_MAY_MOUNT & perms.allow) { + if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) { + target = x_table_lookup(profile, perms.xindex); + if (!target) + error = -ENOENT; + else + error = aa_replace_current_profile(target); + } + } else + error = -EACCES; + +audit: + error = aa_audit_mount(profile, GFP_KERNEL, OP_CHROOT, name, + NULL, NULL, target ? target->base.name : NULL, + 0, NULL, AA_MAY_CHROOT, &perms, info, error); + + aa_put_profile(target); + kfree(buffer); + + return error; +} -- 1.7.9 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
