summaryrefslogtreecommitdiffstats
path: root/security/apparmor
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-01-16 09:42:45 +0100
committerJohn Johansen <john.johansen@canonical.com>2017-01-16 10:18:35 +0100
commita71ada305801e940ff69c2c58489778760e5148b (patch)
tree4fc18f426bff2471c50b87c5b5c6df4749deee11 /security/apparmor
parentapparmor: provide userspace flag indicating binfmt_elf_mmap change (diff)
downloadlinux-a71ada305801e940ff69c2c58489778760e5148b.tar.xz
linux-a71ada305801e940ff69c2c58489778760e5148b.zip
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/apparmor')
-rw-r--r--security/apparmor/apparmorfs.c78
-rw-r--r--security/apparmor/include/apparmorfs.h2
-rw-r--r--security/apparmor/include/policy_ns.h2
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];
};