summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 11:26:35 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 11:26:35 -0700
commite24dd9ee5399747b71c1d982a484fc7601795f31 (patch)
tree14fcec8728916092a9f6dbeb0f2b8d5c5a4e5c9a /security
parent7391786a64dcfe9c609a1f8e2204c1abf42ded23 (diff)
parentc4758fa59285fe4dbfeab4364a6957936d040fbf (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer updates from James Morris: - a major update for AppArmor. From JJ: * several bug fixes and cleanups * the patch to add symlink support to securityfs that was floated on the list earlier and the apparmorfs changes that make use of securityfs symlinks * it introduces the domain labeling base code that Ubuntu has been carrying for several years, with several cleanups applied. And it converts the current mediation over to using the domain labeling base, which brings domain stacking support with it. This finally will bring the base upstream code in line with Ubuntu and provide a base to upstream the new feature work that Ubuntu carries. * This does _not_ contain any of the newer apparmor mediation features/controls (mount, signals, network, keys, ...) that Ubuntu is currently carrying, all of which will be RFC'd on top of this. - Notable also is the Infiniband work in SELinux, and the new file:map permission. From Paul: "While we're down to 21 patches for v4.13 (it was 31 for v4.12), the diffstat jumps up tremendously with over 2k of line changes. Almost all of these changes are the SELinux/IB work done by Daniel Jurgens; some other noteworthy changes include a NFS v4.2 labeling fix, a new file:map permission, and reporting of policy capabilities on policy load" There's also now genfscon labeling support for tracefs, which was lost in v4.1 with the separation from debugfs. - Smack incorporates a safer socket check in file_receive, and adds a cap_capable call in privilege check. - TPM as usual has a bunch of fixes and enhancements. - Multiple calls to security_add_hooks() can now be made for the same LSM, to allow LSMs to have hook declarations across multiple files. - IMA now supports different "ima_appraise=" modes (eg. log, fix) from the boot command line. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (126 commits) apparmor: put back designators in struct initialisers seccomp: Switch from atomic_t to recount_t seccomp: Adjust selftests to avoid double-join seccomp: Clean up core dump logic IMA: update IMA policy documentation to include pcr= option ima: Log the same audit cause whenever a file has no signature ima: Simplify policy_func_show. integrity: Small code improvements ima: fix get_binary_runtime_size() ima: use ima_parse_buf() to parse template data ima: use ima_parse_buf() to parse measurements headers ima: introduce ima_parse_buf() ima: Add cgroups2 to the defaults list ima: use memdup_user_nul ima: fix up #endif comments IMA: Correct Kconfig dependencies for hash selection ima: define is_ima_appraise_enabled() ima: define Kconfig IMA_APPRAISE_BOOTPARAM option ima: define a set of appraisal rules requiring file signatures ima: extend the "ima_policy" boot command line to support multiple policies ...
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig11
-rw-r--r--security/apparmor/Makefile8
-rw-r--r--security/apparmor/apparmorfs.c1672
-rw-r--r--security/apparmor/audit.c27
-rw-r--r--security/apparmor/capability.c61
-rw-r--r--security/apparmor/context.c87
-rw-r--r--security/apparmor/domain.c1393
-rw-r--r--security/apparmor/file.c517
-rw-r--r--security/apparmor/include/apparmor.h6
-rw-r--r--security/apparmor/include/apparmorfs.h67
-rw-r--r--security/apparmor/include/audit.h17
-rw-r--r--security/apparmor/include/capability.h8
-rw-r--r--security/apparmor/include/context.h201
-rw-r--r--security/apparmor/include/domain.h13
-rw-r--r--security/apparmor/include/file.h114
-rw-r--r--security/apparmor/include/ipc.h16
-rw-r--r--security/apparmor/include/label.h441
-rw-r--r--security/apparmor/include/lib.h120
-rw-r--r--security/apparmor/include/path.h7
-rw-r--r--security/apparmor/include/perms.h155
-rw-r--r--security/apparmor/include/policy.h131
-rw-r--r--security/apparmor/include/policy_ns.h21
-rw-r--r--security/apparmor/include/policy_unpack.h68
-rw-r--r--security/apparmor/include/procattr.h8
-rw-r--r--security/apparmor/include/resource.h6
-rw-r--r--security/apparmor/ipc.c140
-rw-r--r--security/apparmor/label.c2120
-rw-r--r--security/apparmor/lib.c368
-rw-r--r--security/apparmor/lsm.c245
-rw-r--r--security/apparmor/path.c130
-rw-r--r--security/apparmor/policy.c392
-rw-r--r--security/apparmor/policy_ns.c80
-rw-r--r--security/apparmor/policy_unpack.c96
-rw-r--r--security/apparmor/procattr.c71
-rw-r--r--security/apparmor/resource.c116
-rw-r--r--security/inode.c144
-rw-r--r--security/integrity/digsig_asymmetric.c4
-rw-r--r--security/integrity/iint.c2
-rw-r--r--security/integrity/ima/Kconfig16
-rw-r--r--security/integrity/ima/ima.h31
-rw-r--r--security/integrity/ima/ima_appraise.c16
-rw-r--r--security/integrity/ima/ima_fs.c13
-rw-r--r--security/integrity/ima/ima_policy.c106
-rw-r--r--security/integrity/ima/ima_queue.c2
-rw-r--r--security/integrity/ima/ima_template.c124
-rw-r--r--security/integrity/ima/ima_template_lib.c61
-rw-r--r--security/integrity/ima/ima_template_lib.h6
-rw-r--r--security/integrity/integrity.h7
-rw-r--r--security/lsm_audit.c16
-rw-r--r--security/security.c74
-rw-r--r--security/selinux/Makefile2
-rw-r--r--security/selinux/hooks.c212
-rw-r--r--security/selinux/ibpkey.c245
-rw-r--r--security/selinux/include/classmap.h6
-rw-r--r--security/selinux/include/ibpkey.h31
-rw-r--r--security/selinux/include/objsec.h11
-rw-r--r--security/selinux/include/security.h9
-rw-r--r--security/selinux/selinuxfs.c15
-rw-r--r--security/selinux/ss/ebitmap.c26
-rw-r--r--security/selinux/ss/ebitmap.h3
-rw-r--r--security/selinux/ss/policydb.c127
-rw-r--r--security/selinux/ss/policydb.h27
-rw-r--r--security/selinux/ss/services.c108
-rw-r--r--security/selinux/ss/sidtab.c27
-rw-r--r--security/smack/smack.h2
-rw-r--r--security/smack/smack_access.c19
-rw-r--r--security/smack/smack_lsm.c2
-rw-r--r--security/smack/smack_netfilter.c26
68 files changed, 8342 insertions, 2111 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 93027fdf47d1..d540bfe73190 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -54,6 +54,15 @@ config SECURITY_NETWORK
implement socket and networking access controls.
If you are unsure how to answer this question, answer N.
+config SECURITY_INFINIBAND
+ bool "Infiniband Security Hooks"
+ depends on SECURITY && INFINIBAND
+ help
+ This enables the Infiniband security hooks.
+ If enabled, a security module can use these hooks to
+ implement Infiniband access controls.
+ If you are unsure how to answer this question, answer N.
+
config SECURITY_NETWORK_XFRM
bool "XFRM (IPSec) Networking Security Hooks"
depends on XFRM && SECURITY_NETWORK
@@ -139,7 +148,7 @@ config HARDENED_USERCOPY
copying memory to/from the kernel (via copy_to_user() and
copy_from_user() functions) by rejecting memory ranges that
are larger than the specified heap object, span multiple
- separately allocates pages, are not on the process stack,
+ separately allocated pages, are not on the process stack,
or are part of the kernel text. This kills entire classes
of heap overflow exploits and similar kernel memory exposures.
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index ad369a7aac24..a16b195274de 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o secid.o file.o policy_ns.o
+ resource.o secid.o file.o policy_ns.o label.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
clean-files := capability_names.h rlim_names.h
@@ -20,7 +20,7 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \
-e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
echo "};" >> $@ ;\
- echo -n '\#define AA_FS_CAPS_MASK "' >> $@ ;\
+ printf '%s' '\#define AA_SFS_CAPS_MASK "' >> $@ ;\
sed $< -r -n -e '/CAP_FS_MASK/d' \
-e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \
tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
@@ -46,7 +46,7 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
# #define RLIMIT_FSIZE 1 /* Maximum filesize */
# #define RLIMIT_STACK 3 /* max stack size */
# to
-# #define AA_FS_RLIMIT_MASK "fsize stack"
+# #define AA_SFS_RLIMIT_MASK "fsize stack"
quiet_cmd_make-rlim = GEN $@
cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
> $@ ;\
@@ -56,7 +56,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\
sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
echo "};" >> $@ ; \
- echo -n '\#define AA_FS_RLIMIT_MASK "' >> $@ ;\
+ printf '%s' '\#define AA_SFS_RLIMIT_MASK "' >> $@ ;\
sed -r -n 's/^\# ?define[ \t]+RLIMIT_([A-Z0-9_]+).*/\L\1/p' $< | \
tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 4f6ac9dbc65d..853c2ec8e0c9 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -22,19 +22,52 @@
#include <linux/namei.h>
#include <linux/capability.h>
#include <linux/rcupdate.h>
-#include <uapi/linux/major.h>
#include <linux/fs.h>
+#include <linux/poll.h>
+#include <uapi/linux/major.h>
+#include <uapi/linux/magic.h>
#include "include/apparmor.h"
#include "include/apparmorfs.h"
#include "include/audit.h"
#include "include/context.h"
#include "include/crypto.h"
+#include "include/policy_ns.h"
+#include "include/label.h"
#include "include/policy.h"
#include "include/policy_ns.h"
#include "include/resource.h"
#include "include/policy_unpack.h"
+/*
+ * The apparmor filesystem interface used for policy load and introspection
+ * The interface is split into two main components based on their function
+ * a securityfs component:
+ * used for static files that are always available, and which allows
+ * userspace to specificy the location of the security filesystem.
+ *
+ * fns and data are prefixed with
+ * aa_sfs_
+ *
+ * an apparmorfs component:
+ * used loaded policy content and introspection. It is not part of a
+ * regular mounted filesystem and is available only through the magic
+ * policy symlink in the root of the securityfs apparmor/ directory.
+ * Tasks queries will be magically redirected to the correct portion
+ * of the policy tree based on their confinement.
+ *
+ * fns and data are prefixed with
+ * aafs_
+ *
+ * The aa_fs_ prefix is used to indicate the fn is used by both the
+ * securityfs and apparmorfs filesystems.
+ */
+
+
+/*
+ * support fns
+ */
+
/**
* aa_mangle_name - mangle a profile name to std profile layout form
* @name: profile name to mangle (NOT NULL)
@@ -74,6 +107,265 @@ static int mangle_name(const char *name, char *target)
return t - target;
}
+
+/*
+ * aafs - core fns and data for the policy tree
+ */
+
+#define AAFS_NAME "apparmorfs"
+static struct vfsmount *aafs_mnt;
+static int aafs_count;
+
+
+static int aafs_show_path(struct seq_file *seq, struct dentry *dentry)
+{
+ struct inode *inode = d_inode(dentry);
+
+ seq_printf(seq, "%s:[%lu]", AAFS_NAME, inode->i_ino);
+ return 0;
+}
+
+static void aafs_evict_inode(struct inode *inode)
+{
+ truncate_inode_pages_final(&inode->i_data);
+ clear_inode(inode);
+ if (S_ISLNK(inode->i_mode))
+ kfree(inode->i_link);
+}
+
+static const struct super_operations aafs_super_ops = {
+ .statfs = simple_statfs,
+ .evict_inode = aafs_evict_inode,
+ .show_path = aafs_show_path,
+};
+
+static int fill_super(struct super_block *sb, void *data, int silent)
+{
+ static struct tree_descr files[] = { {""} };
+ int error;
+
+ error = simple_fill_super(sb, AAFS_MAGIC, files);
+ if (error)
+ return error;
+ sb->s_op = &aafs_super_ops;
+
+ return 0;
+}
+
+static struct dentry *aafs_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data)
+{
+ return mount_single(fs_type, flags, data, fill_super);
+}
+
+static struct file_system_type aafs_ops = {
+ .owner = THIS_MODULE,
+ .name = AAFS_NAME,
+ .mount = aafs_mount,
+ .kill_sb = kill_anon_super,
+};
+
+/**
+ * __aafs_setup_d_inode - basic inode setup for apparmorfs
+ * @dir: parent directory for the dentry
+ * @dentry: dentry we are seting the inode up for
+ * @mode: permissions the file should have
+ * @data: data to store on inode.i_private, available in open()
+ * @link: if symlink, symlink target string
+ * @fops: struct file_operations that should be used
+ * @iops: struct of inode_operations that should be used
+ */
+static int __aafs_setup_d_inode(struct inode *dir, struct dentry *dentry,
+ umode_t mode, void *data, char *link,
+ const struct file_operations *fops,
+ const struct inode_operations *iops)
+{
+ struct inode *inode = new_inode(dir->i_sb);
+
+ AA_BUG(!dir);
+ AA_BUG(!dentry);
+
+ if (!inode)
+ return -ENOMEM;
+
+ inode->i_ino = get_next_ino();
+ inode->i_mode = mode;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
+ inode->i_private = data;
+ if (S_ISDIR(mode)) {
+ inode->i_op = iops ? iops : &simple_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+ inc_nlink(inode);
+ inc_nlink(dir);
+ } else if (S_ISLNK(mode)) {
+ inode->i_op = iops ? iops : &simple_symlink_inode_operations;
+ inode->i_link = link;
+ } else {
+ inode->i_fop = fops;
+ }
+ d_instantiate(dentry, inode);
+ dget(dentry);
+
+ return 0;
+}
+
+/**
+ * aafs_create - create a dentry in the apparmorfs filesystem
+ *
+ * @name: name of dentry to create
+ * @mode: permissions the file should have
+ * @parent: parent directory for this dentry
+ * @data: data to store on inode.i_private, available in open()
+ * @link: if symlink, symlink target string
+ * @fops: struct file_operations that should be used for
+ * @iops: struct of inode_operations that should be used
+ *
+ * This is the basic "create a xxx" function for apparmorfs.
+ *
+ * Returns a pointer to a dentry if it succeeds, that must be free with
+ * aafs_remove(). Will return ERR_PTR on failure.
+ */
+static struct dentry *aafs_create(const char *name, umode_t mode,
+ struct dentry *parent, void *data, void *link,
+ const struct file_operations *fops,
+ const struct inode_operations *iops)
+{
+ struct dentry *dentry;
+ struct inode *dir;
+ int error;
+
+ AA_BUG(!name);
+ AA_BUG(!parent);
+
+ if (!(mode & S_IFMT))
+ mode = (mode & S_IALLUGO) | S_IFREG;
+
+ error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count);
+ if (error)
+ return ERR_PTR(error);
+
+ dir = d_inode(parent);
+
+ inode_lock(dir);
+ dentry = lookup_one_len(name, parent, strlen(name));
+ if (IS_ERR(dentry))
+ goto fail_lock;
+
+ if (d_really_is_positive(dentry)) {
+ error = -EEXIST;
+ goto fail_dentry;
+ }
+
+ error = __aafs_setup_d_inode(dir, dentry, mode, data, link, fops, iops);
+ if (error)
+ goto fail_dentry;
+ inode_unlock(dir);
+
+ return dentry;
+
+fail_dentry:
+ dput(dentry);
+
+fail_lock:
+ inode_unlock(dir);
+ simple_release_fs(&aafs_mnt, &aafs_count);
+
+ return ERR_PTR(error);
+}
+
+/**
+ * aafs_create_file - create a file in the apparmorfs filesystem
+ *
+ * @name: name of dentry to create
+ * @mode: permissions the file should have
+ * @parent: parent directory for this dentry
+ * @data: data to store on inode.i_private, available in open()
+ * @fops: struct file_operations that should be used for
+ *
+ * see aafs_create
+ */
+static struct dentry *aafs_create_file(const char *name, umode_t mode,
+ struct dentry *parent, void *data,
+ const struct file_operations *fops)
+{
+ return aafs_create(name, mode, parent, data, NULL, fops, NULL);
+}
+
+/**
+ * aafs_create_dir - create a directory in the apparmorfs filesystem
+ *
+ * @name: name of dentry to create
+ * @parent: parent directory for this dentry
+ *
+ * see aafs_create
+ */
+static struct dentry *aafs_create_dir(const char *name, struct dentry *parent)
+{
+ return aafs_create(name, S_IFDIR | 0755, parent, NULL, NULL, NULL,
+ NULL);
+}
+
+/**
+ * aafs_create_symlink - create a symlink in the apparmorfs filesystem
+ * @name: name of dentry to create
+ * @parent: parent directory for this dentry
+ * @target: if symlink, symlink target string
+ * @iops: struct of inode_operations that should be used
+ *
+ * If @target parameter is %NULL, then the @iops parameter needs to be
+ * setup to handle .readlink and .get_link inode_operations.
+ */
+static struct dentry *aafs_create_symlink(const char *name,
+ struct dentry *parent,
+ const char *target,
+ const struct inode_operations *iops)
+{
+ struct dentry *dent;
+ char *link = NULL;
+
+ if (target) {
+ link = kstrdup(target, GFP_KERNEL);
+ if (!link)
+ return ERR_PTR(-ENOMEM);
+ }
+ dent = aafs_create(name, S_IFLNK | 0444, parent, NULL, link, NULL,
+ iops);
+ if (IS_ERR(dent))
+ kfree(link);
+
+ return dent;
+}
+
+/**
+ * aafs_remove - removes a file or directory from the apparmorfs filesystem
+ *
+ * @dentry: dentry of the file/directory/symlink to removed.
+ */
+static void aafs_remove(struct dentry *dentry)
+{
+ struct inode *dir;
+
+ if (!dentry || IS_ERR(dentry))
+ return;
+
+ dir = d_inode(dentry->d_parent);
+ inode_lock(dir);
+ if (simple_positive(dentry)) {
+ if (d_is_dir(dentry))
+ simple_rmdir(dir, dentry);
+ else
+ simple_unlink(dir, dentry);
+ dput(dentry);
+ }
+ inode_unlock(dir);
+ simple_release_fs(&aafs_mnt, &aafs_count);
+}
+
+
+/*
+ * aa_fs - policy load/replace/remove
+ */
+
/**
* aa_simple_write_to_buffer - common routine for getting policy from user
* @userbuf: user buffer to copy data from (NOT NULL)
@@ -98,14 +390,11 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,
return ERR_PTR(-ESPIPE);
/* freed by caller to simple_write_to_buffer */
- data = kvmalloc(sizeof(*data) + alloc_size, GFP_KERNEL);
- if (data == NULL)
- return ERR_PTR(-ENOMEM);
- kref_init(&data->count);
- data->size = copy_size;
- data->hash = NULL;
- data->abi = 0;
+ data = aa_loaddata_alloc(alloc_size);
+ if (IS_ERR(data))
+ return data;
+ data->size = copy_size;
if (copy_from_user(data->data, userbuf, copy_size)) {
kvfree(data);
return ERR_PTR(-EFAULT);
@@ -114,27 +403,29 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,
return data;
}
-static ssize_t policy_update(int binop, const char __user *buf, size_t size,
+static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
loff_t *pos, struct aa_ns *ns)
{
- ssize_t error;
struct aa_loaddata *data;
- struct aa_profile *profile = aa_current_profile();
- const char *op = binop == PROF_ADD ? OP_PROF_LOAD : OP_PROF_REPL;
+ struct aa_label *label;
+ ssize_t error;
+
+ label = begin_current_label_crit_section();
+
/* high level check about policy management - fine grained in
* below after unpack
*/
- error = aa_may_manage_policy(profile, ns, op);
+ error = aa_may_manage_policy(label, ns, mask);
if (error)
return error;
data = aa_simple_write_to_buffer(buf, size, size, pos);
error = PTR_ERR(data);
if (!IS_ERR(data)) {
- error = aa_replace_profiles(ns ? ns : profile->ns, profile,
- binop, data);
+ error = aa_replace_profiles(ns, label, mask, data);
aa_put_loaddata(data);
}
+ end_current_label_crit_section(label);
return error;
}
@@ -144,7 +435,7 @@ static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
loff_t *pos)
{
struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
- int error = policy_update(PROF_ADD, buf, size, pos, ns);
+ int error = policy_update(AA_MAY_LOAD_POLICY, buf, size, pos, ns);
aa_put_ns(ns);
@@ -161,8 +452,8 @@ static ssize_t profile_replace(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
{
struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
- int error = policy_update(PROF_REPLACE, buf, size, pos, ns);
-
+ int error = policy_update(AA_MAY_LOAD_POLICY | AA_MAY_REPLACE_POLICY,
+ buf, size, pos, ns);
aa_put_ns(ns);
return error;
@@ -178,15 +469,15 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
{
struct aa_loaddata *data;
- struct aa_profile *profile;
+ struct aa_label *label;
ssize_t error;