Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79444df4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'apparmor-pr-2017-09-22' of...

Merge tag 'apparmor-pr-2017-09-22' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor

Pull apparmor updates from John Johansen:
 "This is the apparmor pull request, similar to SELinux and seccomp.

  It's the same series that I was sent to James' security tree + one
  regression fix that was found after the series was sent to James and
  would have been sent for v4.14-rc2.

  Features:
  - in preparation for secid mapping add support for absolute root view
    based labels
  - add base infastructure for socket mediation
  - add mount mediation
  - add signal mediation

  minor cleanups and changes:
  - be defensive, ensure unconfined profiles have dfas initialized
  - add more debug asserts to apparmorfs
  - enable policy unpacking to audit different reasons for failure
  - cleanup conditional check for label in label_print
  - Redundant condition: prev_ns. in [label.c:1498]

  Bug Fixes:
  - fix regression in apparmorfs DAC access permissions
  - fix build failure on sparc caused by undeclared signals
  - fix sparse report of incorrect type assignment when freeing label proxies
  - fix race condition in null profile creation
  - Fix an error code in aafs_create()
  - Fix logical error in verify_header()
  - Fix shadowed local variable in unpack_trans_table()"

* tag 'apparmor-pr-2017-09-22' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
  apparmor: fix apparmorfs DAC access permissions
  apparmor: fix build failure on sparc caused by undeclared signals
  apparmor: fix incorrect type assignment when freeing proxies
  apparmor: ensure unconfined profiles have dfas initialized
  apparmor: fix race condition in null profile creation
  apparmor: move new_null_profile to after profile lookup fns()
  apparmor: add base infastructure for socket mediation
  apparmor: add more debug asserts to apparmorfs
  apparmor: make policy_unpack able to audit different info messages
  apparmor: add support for absolute root view based labels
  apparmor: cleanup conditional check for label in label_print
  apparmor: add mount mediation
  apparmor: add the ability to mediate signals
  apparmor: Redundant condition: prev_ns. in [label.c:1498]
  apparmor: Fix an error code in aafs_create()
  apparmor: Fix logical error in verify_header()
  apparmor: Fix shadowed local variable in unpack_trans_table()
parents c65da8e2 bf81100f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
#
# Generated include files
#
net_names.h
capability_names.h
rlim_names.h
+41 −2
Original line number Diff line number Diff line
@@ -4,11 +4,44 @@ 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 label.o
              resource.o secid.o file.o policy_ns.o label.o mount.o net.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o

clean-files := capability_names.h rlim_names.h
clean-files := capability_names.h rlim_names.h net_names.h

# Build a lower case string table of address family names
# Transform lines from
#    #define AF_LOCAL		1	/* POSIX name for AF_UNIX	*/
#    #define AF_INET		2	/* Internet IP Protocol 	*/
# to
#    [1] = "local",
#    [2] = "inet",
#
# and build the securityfs entries for the mapping.
# Transforms lines from
#    #define AF_INET		2	/* Internet IP Protocol 	*/
# to
#    #define AA_SFS_AF_MASK "local inet"
quiet_cmd_make-af = GEN     $@
cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
	sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
	 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
	echo "};" >> $@ ;\
	printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
	sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
	 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
	 $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@

# Build a lower case string table of sock type names
# Transform lines from
#    SOCK_STREAM	= 1,
# to
#    [1] = "stream",
quiet_cmd_make-sock = GEN     $@
cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
	sed $^ >>$@ -r -n \
	-e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
	echo "};" >> $@

# Build a lower case string table of capability names
# Transforms lines from
@@ -61,6 +94,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
	    tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@

$(obj)/capability.o : $(obj)/capability_names.h
$(obj)/net.o : $(obj)/net_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
			    $(src)/Makefile
@@ -68,3 +102,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
		      $(src)/Makefile
	$(call cmd,make-rlim)
$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
		     $(srctree)/include/linux/net.h \
		     $(src)/Makefile
	$(call cmd,make-af)
	$(call cmd,make-sock)
+39 −6
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include "include/audit.h"
#include "include/context.h"
#include "include/crypto.h"
#include "include/ipc.h"
#include "include/policy_ns.h"
#include "include/label.h"
#include "include/policy.h"
@@ -248,8 +249,10 @@ static struct dentry *aafs_create(const char *name, umode_t mode,

	inode_lock(dir);
	dentry = lookup_one_len(name, parent, strlen(name));
	if (IS_ERR(dentry))
	if (IS_ERR(dentry)) {
		error = PTR_ERR(dentry);
		goto fail_lock;
	}

	if (d_really_is_positive(dentry)) {
		error = -EEXIST;
@@ -1443,6 +1446,10 @@ void __aafs_profile_migrate_dents(struct aa_profile *old,
{
	int i;

	AA_BUG(!old);
	AA_BUG(!new);
	AA_BUG(!mutex_is_locked(&profiles_ns(old)->lock));

	for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
		new->dents[i] = old->dents[i];
		if (new->dents[i])
@@ -1506,6 +1513,9 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
	struct dentry *dent = NULL, *dir;
	int error;

	AA_BUG(!profile);
	AA_BUG(!mutex_is_locked(&profiles_ns(profile)->lock));

	if (!parent) {
		struct aa_profile *p;
		p = aa_deref_parent(profile);
@@ -1731,6 +1741,7 @@ void __aafs_ns_rmdir(struct aa_ns *ns)

	if (!ns)
		return;
	AA_BUG(!mutex_is_locked(&ns->lock));

	list_for_each_entry(child, &ns->base.profiles, base.list)
		__aafs_profile_rmdir(child);
@@ -1903,6 +1914,10 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
{
	struct aa_ns *parent, *next;

	AA_BUG(!root);
	AA_BUG(!ns);
	AA_BUG(ns != root && !mutex_is_locked(&ns->parent->lock));

	/* is next namespace a child */
	if (!list_empty(&ns->sub_ns)) {
		next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
@@ -1937,6 +1952,9 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
static struct aa_profile *__first_profile(struct aa_ns *root,
					  struct aa_ns *ns)
{
	AA_BUG(!root);
	AA_BUG(ns && !mutex_is_locked(&ns->lock));

	for (; ns; ns = __next_ns(root, ns)) {
		if (!list_empty(&ns->base.profiles))
			return list_first_entry(&ns->base.profiles,
@@ -1959,6 +1977,8 @@ static struct aa_profile *__next_profile(struct aa_profile *p)
	struct aa_profile *parent;
	struct aa_ns *ns = p->ns;

	AA_BUG(!mutex_is_locked(&profiles_ns(p)->lock));

	/* is next profile a child */
	if (!list_empty(&p->base.profiles))
		return list_first_entry(&p->base.profiles, typeof(*p),
@@ -2127,6 +2147,11 @@ static struct aa_sfs_entry aa_sfs_entry_ptrace[] = {
	{ }
};

static struct aa_sfs_entry aa_sfs_entry_signal[] = {
	AA_SFS_FILE_STRING("mask", AA_SFS_SIG_MASK),
	{ }
};

static struct aa_sfs_entry aa_sfs_entry_domain[] = {
	AA_SFS_FILE_BOOLEAN("change_hat",	1),
	AA_SFS_FILE_BOOLEAN("change_hatv",	1),
@@ -2151,9 +2176,14 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
	{ }
};

static struct aa_sfs_entry aa_sfs_entry_mount[] = {
	AA_SFS_FILE_STRING("mask", "mount umount pivot_root"),
	{ }
};

static struct aa_sfs_entry aa_sfs_entry_ns[] = {
	AA_SFS_FILE_BOOLEAN("profile",		1),
	AA_SFS_FILE_BOOLEAN("pivot_root",	1),
	AA_SFS_FILE_BOOLEAN("pivot_root",	0),
	{ }
};

@@ -2172,22 +2202,25 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
	AA_SFS_DIR("policy",			aa_sfs_entry_policy),
	AA_SFS_DIR("domain",			aa_sfs_entry_domain),
	AA_SFS_DIR("file",			aa_sfs_entry_file),
	AA_SFS_DIR("network",			aa_sfs_entry_network),
	AA_SFS_DIR("mount",			aa_sfs_entry_mount),
	AA_SFS_DIR("namespaces",		aa_sfs_entry_ns),
	AA_SFS_FILE_U64("capability",		VFS_CAP_FLAGS_MASK),
	AA_SFS_DIR("rlimit",			aa_sfs_entry_rlimit),
	AA_SFS_DIR("caps",			aa_sfs_entry_caps),
	AA_SFS_DIR("ptrace",			aa_sfs_entry_ptrace),
	AA_SFS_DIR("signal",			aa_sfs_entry_signal),
	AA_SFS_DIR("query",			aa_sfs_entry_query),
	{ }
};

static struct aa_sfs_entry aa_sfs_entry_apparmor[] = {
	AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access),
	AA_SFS_FILE_FOPS(".access", 0666, &aa_sfs_access),
	AA_SFS_FILE_FOPS(".stacked", 0444, &seq_ns_stacked_fops),
	AA_SFS_FILE_FOPS(".ns_stacked", 0444, &seq_ns_nsstacked_fops),
	AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops),
	AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops),
	AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops),
	AA_SFS_FILE_FOPS(".ns_level", 0444, &seq_ns_level_fops),
	AA_SFS_FILE_FOPS(".ns_name", 0444, &seq_ns_name_fops),
	AA_SFS_FILE_FOPS("profiles", 0444, &aa_sfs_profiles_fops),
	AA_SFS_DIR("features", aa_sfs_entry_features),
	{ }
};
+2 −2
Original line number Diff line number Diff line
@@ -374,7 +374,7 @@ static const char *next_name(int xtype, const char *name)
 *
 * Returns: refcounted label, or NULL on failure (MAYBE NULL)
 */
static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
				const char **name)
{
	struct aa_label *label = NULL;
+30 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "include/context.h"
#include "include/file.h"
#include "include/match.h"
#include "include/net.h"
#include "include/path.h"
#include "include/policy.h"
#include "include/label.h"
@@ -566,6 +567,32 @@ static int __file_path_perm(const char *op, struct aa_label *label,
	return error;
}

static int __file_sock_perm(const char *op, struct aa_label *label,
			    struct aa_label *flabel, struct file *file,
			    u32 request, u32 denied)
{
	struct socket *sock = (struct socket *) file->private_data;
	int error;

	AA_BUG(!sock);

	/* revalidation due to label out of date. No revocation at this time */
	if (!denied && aa_label_is_subset(flabel, label))
		return 0;

	/* TODO: improve to skip profiles cached in flabel */
	error = aa_sock_file_perm(label, op, request, sock);
	if (denied) {
		/* TODO: improve to skip profiles checked above */
		/* check every profile in file label to is cached */
		last_error(error, aa_sock_file_perm(flabel, op, request, sock));
	}
	if (!error)
		update_file_ctx(file_ctx(file), label, request);

	return error;
}

/**
 * aa_file_perm - do permission revalidation check & audit for @file
 * @op: operation being checked
@@ -610,6 +637,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
		error = __file_path_perm(op, label, flabel, file, request,
					 denied);

	else if (S_ISSOCK(file_inode(file)->i_mode))
		error = __file_sock_perm(op, label, flabel, file, request,
					 denied);
done:
	rcu_read_unlock();

Loading