Based on some of the initial design[1] discussions, here is a stab at the
simple static portion of the new apparmorfs interface.

[1] https://lists.ubuntu.com/archives/apparmor/2010-November/000491.html

Signed-off-by: Kees Cook <[email protected]>
---
 security/apparmor/apparmorfs.c |  114 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 104 insertions(+), 10 deletions(-)
---

diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 0848292..8990316 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -146,11 +146,67 @@ static const struct file_operations aa_fs_profile_remove 
= {
 
 static struct dentry *aa_fs_dentry __initdata;
 
-static void __init aafs_remove(const char *name)
+struct aa_fs_file {
+       char *name;
+       char *value;
+       const struct file_operations *file_ops;
+};
+
+struct aa_fs_dir {
+       const char *name;
+       struct dentry *dentry;
+       struct aa_fs_file *files;
+};
+
+static int aa_fs_seq_show(struct seq_file *seq, void *v)
+{
+       struct aa_fs_file *fs_file = seq->private;
+
+       if (fs_file)
+               seq_printf(seq, "%s\n", fs_file->value);
+
+       return 0;
+}
+
+static int aa_fs_seq_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, aa_fs_seq_show, inode->i_private);
+}
+
+static const struct file_operations aa_fs_seq_file_ops = {
+       .owner          = THIS_MODULE,
+       .open           = aa_fs_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct aa_fs_file aa_fs_features_files[] = {
+       { "capability",         "2.0",  &aa_fs_seq_file_ops },
+       { "change_hat",         "1.5",  &aa_fs_seq_file_ops },
+       { "change_hatv",        "1.0",  &aa_fs_seq_file_ops },
+       { "change_onexec",      "1.0",  &aa_fs_seq_file_ops },
+       { "change_profile",     "1.1",  &aa_fs_seq_file_ops },
+       { "file",               "3.1",  &aa_fs_seq_file_ops },
+       { "namespaces",         "1.1",  &aa_fs_seq_file_ops },
+       { "network",            "1.0",  &aa_fs_seq_file_ops },
+       { "rlimit",             "1.1",  &aa_fs_seq_file_ops },
+       { NULL,                 NULL,   NULL },
+};
+
+static struct aa_fs_dir aa_fs_dirs[] = {
+       { "features", NULL, aa_fs_features_files },
+       { NULL, NULL, NULL }
+};
+
+static void __init aafs_remove(const char *name, struct dentry *dir_dentry)
 {
        struct dentry *dentry;
 
-       dentry = lookup_one_len(name, aa_fs_dentry, strlen(name));
+       if (!dir_dentry)
+               return;
+
+       dentry = lookup_one_len(name, dir_dentry, strlen(name));
        if (!IS_ERR(dentry)) {
                securityfs_remove(dentry);
                dput(dentry);
@@ -166,12 +222,14 @@ static void __init aafs_remove(const char *name)
  * Used aafs_remove to remove entries created with this fn.
  */
 static int __init aafs_create(const char *name, int mask,
+                             struct dentry *dir_dentry,
+                             void *data,
                              const struct file_operations *fops)
 {
        struct dentry *dentry;
 
-       dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry,
-                                       NULL, fops);
+       dentry = securityfs_create_file(name, S_IFREG | mask, dir_dentry,
+                                       data, fops);
 
        return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
 }
@@ -184,9 +242,21 @@ static int __init aafs_create(const char *name, int mask,
 void __init aa_destroy_aafs(void)
 {
        if (aa_fs_dentry) {
-               aafs_remove(".remove");
-               aafs_remove(".replace");
-               aafs_remove(".load");
+               struct aa_fs_dir *fs_dir;
+
+               aafs_remove(".remove", aa_fs_dentry);
+               aafs_remove(".replace", aa_fs_dentry);
+               aafs_remove(".load", aa_fs_dentry);
+
+               for (fs_dir = aa_fs_dirs; fs_dir->name; ++fs_dir) {
+                       struct aa_fs_file *fs_file;
+
+                       for (fs_file = fs_dir->files; fs_file->name; ++fs_file)
+                               aafs_remove(fs_file->name, fs_dir->dentry);
+
+                       aafs_remove(fs_dir->name, aa_fs_dentry);
+                       fs_dir->dentry = NULL;
+               }
 
                securityfs_remove(aa_fs_dentry);
                aa_fs_dentry = NULL;
@@ -203,6 +273,7 @@ void __init aa_destroy_aafs(void)
 int __init aa_create_aafs(void)
 {
        int error;
+       struct aa_fs_dir *fs_dir;
 
        if (!apparmor_initialized)
                return 0;
@@ -219,16 +290,39 @@ int __init aa_create_aafs(void)
                goto error;
        }
 
-       error = aafs_create(".load", 0640, &aa_fs_profile_load);
+       error = aafs_create(".load", 0640, aa_fs_dentry, NULL,
+                           &aa_fs_profile_load);
        if (error)
                goto error;
-       error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
+       error = aafs_create(".replace", 0640, aa_fs_dentry, NULL,
+                           &aa_fs_profile_replace);
        if (error)
                goto error;
-       error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
+       error = aafs_create(".remove", 0640, aa_fs_dentry, NULL,
+                           &aa_fs_profile_remove);
        if (error)
                goto error;
 
+       for (fs_dir = aa_fs_dirs; fs_dir->name; ++fs_dir) {
+               struct aa_fs_file *fs_file;
+
+               fs_dir->dentry = securityfs_create_dir(fs_dir->name,
+                                                      aa_fs_dentry);
+               if (IS_ERR(fs_dir->dentry)) {
+                       error = PTR_ERR(fs_dir->dentry);
+                       fs_dir->dentry = NULL;
+                       goto error;
+               }
+
+               for (fs_file = fs_dir->files; fs_file->name; ++fs_file) {
+                       error = aafs_create(fs_file->name, 0444,
+                                           fs_dir->dentry, fs_file,
+                                           fs_file->file_ops);
+                       if (error)
+                               goto error;
+               }
+       }
+
        /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
 
        /* Report that AppArmor fs is enabled */

-- 
Kees Cook

-- 
AppArmor mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to