diff options
author | John Johansen <john.johansen@canonical.com> | 2017-01-16 00:42:45 -0800 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2017-01-16 01:18:35 -0800 |
commit | a71ada305801e940ff69c2c58489778760e5148b (patch) | |
tree | 4fc18f426bff2471c50b87c5b5c6df4749deee11 /security | |
parent | 34c426acb75cc21bdf84685e106db0c1a3565057 (diff) | |
download | linux-a71ada305801e940ff69c2c58489778760e5148b.tar.bz2 |
apparmor: add special .null file used to "close" fds at exec
Borrow the special null device file from selinux to "close" fds that
don't have sufficient permissions at exec time.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/apparmorfs.c | 78 | ||||
-rw-r--r-- | security/apparmor/include/apparmorfs.h | 2 | ||||
-rw-r--r-- | security/apparmor/include/policy_ns.h | 2 |
3 files changed, 81 insertions, 1 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 5c000cb7ef8e..2501a65fe7d3 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -18,9 +18,12 @@ #include <linux/module.h> #include <linux/seq_file.h> #include <linux/uaccess.h> +#include <linux/mount.h> #include <linux/namei.h> #include <linux/capability.h> #include <linux/rcupdate.h> +#include <uapi/linux/major.h> +#include <linux/fs.h> #include "include/apparmor.h" #include "include/apparmorfs.h" @@ -352,6 +355,28 @@ static const struct file_operations aa_fs_seq_hash_fops = { .release = single_release, }; +static int aa_fs_seq_show_ns_level(struct seq_file *seq, void *v) +{ + struct aa_ns *ns = aa_current_profile()->ns; + + seq_printf(seq, "%d\n", ns->level); + + return 0; +} + +static int aa_fs_seq_open_ns_level(struct inode *inode, struct file *file) +{ + return single_open(file, aa_fs_seq_show_ns_level, inode->i_private); +} + +static const struct file_operations aa_fs_ns_level = { + .owner = THIS_MODULE, + .open = aa_fs_seq_open_ns_level, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /** fns to setup dynamic per profile/namespace files **/ void __aa_fs_profile_rmdir(struct aa_profile *profile) { @@ -825,6 +850,7 @@ static struct aa_fs_entry aa_fs_entry_apparmor[] = { AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load), AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace), AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove), + AA_FS_FILE_FOPS(".ns_level", 0666, &aa_fs_ns_level), AA_FS_FILE_FOPS("profiles", 0640, &aa_fs_profiles_fops), AA_FS_DIR("features", aa_fs_entry_features), { } @@ -934,6 +960,52 @@ void __init aa_destroy_aafs(void) aafs_remove_dir(&aa_fs_entry); } + +#define NULL_FILE_NAME ".null" +struct path aa_null; + +static int aa_mk_null_file(struct dentry *parent) +{ + struct vfsmount *mount = NULL; + struct dentry *dentry; + struct inode *inode; + int count = 0; + int error = simple_pin_fs(parent->d_sb->s_type, &mount, &count); + + if (error) + return error; + + inode_lock(d_inode(parent)); + dentry = lookup_one_len(NULL_FILE_NAME, parent, strlen(NULL_FILE_NAME)); + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto out; + } + inode = new_inode(parent->d_inode->i_sb); + if (!inode) { + error = -ENOMEM; + goto out1; + } + + inode->i_ino = get_next_ino(); + inode->i_mode = S_IFCHR | S_IRUGO | S_IWUGO; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, + MKDEV(MEM_MAJOR, 3)); + d_instantiate(dentry, inode); + aa_null.dentry = dget(dentry); + aa_null.mnt = mntget(mount); + + error = 0; + +out1: + dput(dentry); +out: + inode_unlock(d_inode(parent)); + simple_release_fs(&mount, &count); + return error; +} + /** * aa_create_aafs - create the apparmor security filesystem * @@ -962,7 +1034,11 @@ static int __init aa_create_aafs(void) if (error) goto error; - /* TODO: add support for apparmorfs_null and apparmorfs_mnt */ + error = aa_mk_null_file(aa_fs_entry.dentry); + if (error) + goto error; + + /* TODO: add default profile to apparmorfs */ /* Report that AppArmor fs is enabled */ aa_info_message("AppArmor Filesystem Enabled"); diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h index 5626bd48d7cb..eeeae5b0cc36 100644 --- a/security/apparmor/include/apparmorfs.h +++ b/security/apparmor/include/apparmorfs.h @@ -15,6 +15,8 @@ #ifndef __AA_APPARMORFS_H #define __AA_APPARMORFS_H +extern struct path aa_null; + enum aa_fs_type { AA_FS_TYPE_BOOLEAN, AA_FS_TYPE_STRING, diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h index 820d86d266fe..89cffddd7e75 100644 --- a/security/apparmor/include/policy_ns.h +++ b/security/apparmor/include/policy_ns.h @@ -44,6 +44,7 @@ struct aa_ns_acct { * @sub_ns: list of namespaces under the current namespace. * @uniq_null: uniq value used for null learning profiles * @uniq_id: a unique id count for the profiles in the namespace + * @level: level of ns within the tree hierarchy * @dents: dentries for the namespaces file entries in apparmorfs * * An aa_ns defines the set profiles that are searched to determine which @@ -66,6 +67,7 @@ struct aa_ns { struct list_head sub_ns; atomic_t uniq_null; long uniq_id; + int level; struct dentry *dents[AAFS_NS_SIZEOF]; }; |