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

Reply via email to