All of lore.kernel.org
 help / color / mirror / Atom feed
From: John@suse.de, Johansen@suse.de
To: akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	John Johansen <jjohansen@suse.de>,
	Jesse Michael <jmichael@suse.de>
Subject: [AppArmor 46/47] add simple network toggles to apparmor
Date: Thu, 20 Dec 2007 06:09:56 -0800	[thread overview]
Message-ID: <20071220140948.672608897@suse.de> (raw)
In-Reply-To: 20071220140910.934607826@suse.de

[-- Attachment #1: apparmor-network.diff --]
[-- Type: text/plain, Size: 10300 bytes --]

Signed-off-by: John Johansen <jjohansen@suse.de>
Signed-off-by: Jesse Michael <jmichael@suse.de>

---
 security/apparmor/Makefile           |    7 +
 security/apparmor/apparmor.h         |    7 +
 security/apparmor/lsm.c              |  129 ++++++++++++++++++++++++++++++++++-
 security/apparmor/main.c             |   96 ++++++++++++++++++++++++++
 security/apparmor/module_interface.c |   20 +++++
 5 files changed, 255 insertions(+), 4 deletions(-)

--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -8,6 +8,11 @@ apparmor-y := main.o list.o procattr.o l
 quiet_cmd_make-caps = GEN     $@
 cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z > $@
 
-$(obj)/main.o : $(obj)/capability_names.h
+quiet_cmd_make-af = GEN     $@
+cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z > $@
+
+$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
 $(obj)/capability_names.h : $(srctree)/include/linux/capability.h
 	$(call cmd,make-caps)
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
+	$(call cmd,make-af)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -16,6 +16,8 @@
 #include <linux/fs.h>
 #include <linux/binfmts.h>
 #include <linux/rcupdate.h>
+#include <linux/socket.h>
+#include <net/sock.h>
 
 /*
  * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
@@ -169,6 +171,7 @@ struct aa_profile {
 	struct list_head task_contexts;
 	spinlock_t lock;
 	unsigned long int_flags;
+	u16 network_families[AF_MAX];
 };
 
 extern struct list_head profile_ns_list;
@@ -215,6 +218,7 @@ struct aa_audit {
 	int request_mask, denied_mask;
 	struct iattr *iattr;
 	pid_t task, parent;
+	int family, type, protocol;
 	int error_code;
 };
 
@@ -276,6 +280,9 @@ extern void aa_change_task_context(struc
 				   struct aa_profile *previous_profile);
 extern int aa_may_ptrace(struct aa_task_context *cxt,
 			 struct aa_profile *tracee);
+extern int aa_net_perm(struct aa_profile *profile, char *operation,
+			int family, int type, int protocol);
+extern int aa_revalidate_sk(struct sock *sk, char *operation);
 
 /* list.c */
 extern struct aa_namespace *__aa_find_namespace(const char *name,
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -18,6 +18,7 @@
 #include <linux/ctype.h>
 #include <linux/sysctl.h>
 #include <linux/audit.h>
+#include <net/sock.h>
 
 #include "apparmor.h"
 #include "inline.h"
@@ -616,6 +617,117 @@ static void apparmor_task_free_security(
 	aa_release(task);
 }
 
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if (kern)
+		return 0;
+
+	profile = aa_get_profile(current);
+	if (profile)
+		error = aa_net_perm(profile, "socket_create", family,
+							type, protocol);
+	aa_put_profile(profile);
+
+	return error;
+}
+
+static int apparmor_socket_post_create(struct socket *sock, int family,
+					int type, int protocol, int kern)
+{
+	struct sock *sk = sock->sk;
+
+	if (kern)
+		return 0;
+
+	return aa_revalidate_sk(sk, "socket_post_create");
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+				struct sockaddr *address, int addrlen)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_bind");
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+					struct sockaddr *address, int addrlen)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_connect");
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_listen");
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_accept");
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+					struct msghdr *msg, int size)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_sendmsg");
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+				   struct msghdr *msg, int size, int flags)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_recvmsg");
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_getsockname");
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_getpeername");
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+					int optname)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_getsockopt");
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+					int optname)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_setsockopt");
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_shutdown");
+}
+
 static int apparmor_getprocattr(struct task_struct *task, char *name,
 				char **value)
 {
@@ -716,9 +828,6 @@ struct security_operations apparmor_ops 
 	.capable =			apparmor_capable,
 	.syslog =			cap_syslog,
 
-	.netlink_send =			cap_netlink_send,
-	.netlink_recv =			cap_netlink_recv,
-
 	.bprm_apply_creds =		cap_bprm_apply_creds,
 	.bprm_set_security =		apparmor_bprm_set_security,
 	.bprm_secureexec =		apparmor_bprm_secureexec,
@@ -754,6 +863,20 @@ struct security_operations apparmor_ops 
 
 	.getprocattr =			apparmor_getprocattr,
 	.setprocattr =			apparmor_setprocattr,
+
+	.socket_create =		apparmor_socket_create,
+	.socket_post_create =		apparmor_socket_post_create,
+	.socket_bind =			apparmor_socket_bind,
+	.socket_connect =		apparmor_socket_connect,
+	.socket_listen =		apparmor_socket_listen,
+	.socket_accept =		apparmor_socket_accept,
+	.socket_sendmsg =		apparmor_socket_sendmsg,
+	.socket_recvmsg =		apparmor_socket_recvmsg,
+	.socket_getsockname =		apparmor_socket_getsockname,
+	.socket_getpeername =		apparmor_socket_getpeername,
+	.socket_getsockopt =		apparmor_socket_getsockopt,
+	.socket_setsockopt =		apparmor_socket_setsockopt,
+	.socket_shutdown =		apparmor_socket_shutdown,
 };
 
 static void info_message(const char *str)
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -14,6 +14,9 @@
 #include <linux/audit.h>
 #include <linux/mount.h>
 #include <linux/ptrace.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <net/sock.h>
 
 #include "apparmor.h"
 
@@ -341,6 +344,24 @@ static void aa_audit_file_mask(struct au
 	audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
 }
 
+static const char *address_families[] = {
+#include "af_names.h"
+};
+
+static const char *sock_types[] = {
+	"unknown(0)",
+	"stream",
+	"dgram",
+	"raw",
+	"rdm",
+	"seqpacket",
+	"dccp",
+	"unknown(7)",
+	"unknown(8)",
+	"unknown(9)",
+	"packet",
+};
+
 /**
  * aa_audit - Log an audit event to the audit subsystem
  * @profile: profile to check against
@@ -406,6 +427,24 @@ static int aa_audit_base(struct aa_profi
 		audit_log_untrustedstring(ab, sa->name2);
 	}
 
+	if (sa->family || sa->type) {
+		if (address_families[sa->family])
+			audit_log_format(ab, " family=\"%s\"",
+					 address_families[sa->family]);
+		else
+			audit_log_format(ab, " family=\"unknown(%d)\"",
+					 sa->family);
+
+		if (sock_types[sa->type])
+			audit_log_format(ab, " sock_type=\"%s\"",
+					 sock_types[sa->type]);
+		else
+			audit_log_format(ab, " sock_type=\"unknown(%d)\"",
+					 sa->type);
+
+		audit_log_format(ab, " protocol=%d", sa->protocol);
+	}
+
 	audit_log_format(ab, " pid=%d", current->pid);
 
 	if (profile) {
@@ -725,6 +764,63 @@ int aa_link(struct aa_profile *profile,
 	return error;
 }
 
+int aa_net_perm(struct aa_profile *profile, char *operation,
+		int family, int type, int protocol)
+{
+	struct aa_audit sa;
+	int error = 0;
+	u16 family_mask;
+
+	if ((family < 0) || (family >= AF_MAX))
+		return -EINVAL;
+
+	if ((type < 0) || (type >= SOCK_MAX))
+		return -EINVAL;
+
+	/* unix domain and netlink sockets are handled by ipc */
+	if (family == AF_UNIX || family == AF_NETLINK)
+		return 0;
+
+	family_mask = profile->network_families[family];
+
+	error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.operation = operation;
+	sa.gfp_mask = GFP_KERNEL;
+	sa.family = family;
+	sa.type = type;
+	sa.protocol = protocol;
+	sa.error_code = error;
+
+	error = aa_audit(profile, &sa);
+
+	return error;
+}
+
+int aa_revalidate_sk(struct sock *sk, char *operation)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	/* this is some debugging code to flush out the network hooks that
+	   that are called in interrupt context */
+	if (in_interrupt()) {
+		printk("AppArmor Debug: Hook being called from interrupt context\n");
+		dump_stack();
+		return 0;
+	}
+
+	profile = aa_get_profile(current);
+	if (profile)
+		error = aa_net_perm(profile, operation,
+				    sk->sk_family, sk->sk_type,
+				    sk->sk_protocol);
+	aa_put_profile(profile);
+
+	return error;
+}
+
 /*******************************
  * Global task related functions
  *******************************/
--- a/security/apparmor/module_interface.c
+++ b/security/apparmor/module_interface.c
@@ -283,6 +283,8 @@ static struct aa_profile *aa_unpack_prof
 {
 	struct aa_profile *profile = NULL;
 	struct aa_audit sa;
+	size_t size = 0;
+	int i;
 
 	int error = -EPROTO;
 
@@ -311,6 +313,24 @@ static struct aa_profile *aa_unpack_prof
 	if (!aa_is_u32(e, &(profile->capabilities), NULL))
 		goto fail;
 
+	size = aa_is_array(e, "net_allowed_af");
+	if (size) {
+		if (size > AF_MAX)
+			goto fail;
+
+		for (i = 0; i < size; i++) {
+			if (!aa_is_u16(e, &profile->network_families[i], NULL))
+				goto fail;
+		}
+		if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
+			goto fail;
+		/* allow unix domain and netlink sockets they are handled
+		 * by IPC
+		 */
+	}
+	profile->network_families[AF_UNIX] = 0xffff;
+	profile->network_families[AF_NETLINK] = 0xffff;
+
 	/* get file rules */
 	profile->file_rules = aa_unpack_dfa(e);
 	if (IS_ERR(profile->file_rules)) {

-- 


  parent reply	other threads:[~2007-12-20 14:33 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-20 14:09 [AppArmor 00/47] AppArmor security module overview John, Johansen
2007-12-20 14:09 ` [AppArmor 01/47] Pass struct vfsmount to the inode_create LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 02/47] Pass struct path down to remove_suid and children John, Johansen
2007-12-20 14:09 ` [AppArmor 03/47] Add a vfsmount parameter to notify_change() John, Johansen
2007-12-20 14:09 ` [AppArmor 04/47] Pass struct vfsmount to the inode_setattr LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 05/47] Add struct vfsmount parameter to vfs_mkdir() John, Johansen
2007-12-20 14:09 ` [AppArmor 06/47] Pass struct vfsmount to the inode_mkdir LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 07/47] Add a struct vfsmount parameter to vfs_mknod() John, Johansen
2007-12-20 14:09 ` [AppArmor 08/47] Pass struct vfsmount to the inode_mknod LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 09/47] Add a struct vfsmount parameter to vfs_symlink() John, Johansen
2007-12-20 14:09 ` [AppArmor 10/47] Pass struct vfsmount to the inode_symlink LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 11/47] Pass struct vfsmount to the inode_readlink " John, Johansen
2007-12-20 14:09 ` [AppArmor 12/47] Add struct vfsmount parameters to vfs_link() John, Johansen
2007-12-20 14:09 ` [AppArmor 13/47] Pass the struct vfsmounts to the inode_link LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 14/47] Add a struct vfsmount parameter to vfs_rmdir() John, Johansen
2007-12-20 14:09 ` [AppArmor 15/47] Pass struct vfsmount to the inode_rmdir LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 16/47] Call lsm hook before unhashing dentry in vfs_rmdir() John, Johansen
2007-12-20 14:09 ` [AppArmor 17/47] Add a struct vfsmount parameter to vfs_unlink() John, Johansen
2007-12-20 14:09 ` [AppArmor 18/47] Pass struct vfsmount to the inode_unlink LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 19/47] Add struct vfsmount parameters to vfs_rename() John, Johansen
2007-12-20 14:09 ` [AppArmor 20/47] Pass struct vfsmount to the inode_rename LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 21/47] Add a struct vfsmount parameter to vfs_setxattr() John, Johansen
2007-12-20 14:09 ` [AppArmor 22/47] Pass struct vfsmount to the inode_setxattr LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 23/47] Add a struct vfsmount parameter to vfs_getxattr() John, Johansen
2007-12-20 14:09 ` [AppArmor 24/47] Pass struct vfsmount to the inode_getxattr LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 25/47] Add a struct vfsmount parameter to vfs_listxattr() John, Johansen
2007-12-20 14:09 ` [AppArmor 26/47] Pass struct vfsmount to the inode_listxattr LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 27/47] Add a struct vfsmount parameter to vfs_removexattr() John, Johansen
2007-12-20 14:09 ` [AppArmor 28/47] Pass struct vfsmount to the inode_removexattr LSM hook John, Johansen
2007-12-20 14:09 ` [AppArmor 29/47] Fix __d_path() for lazy unmounts and make it unambiguous John, Johansen
2007-12-20 14:09 ` [AppArmor 30/47] Make d_path() consistent across mount operations John, Johansen
2007-12-20 14:09 ` [AppArmor 31/47] Add d_namespace_path() to compute namespace relative pathnames John, Johansen
2007-12-20 14:09 ` [AppArmor 32/47] From: Miklos Szeredi <mszeredi@suse.cz> John, Johansen
2007-12-20 14:09 ` [AppArmor 33/47] VFS: new fsetattr() file operation John, Johansen
2007-12-20 14:09 ` [AppArmor 34/47] Pass struct file down the inode_*xattr security LSM hooks John, Johansen
2007-12-20 14:09 ` [AppArmor 35/47] Factor out sysctl pathname code John, Johansen
2007-12-20 14:09 ` [AppArmor 36/47] Allow permission functions to tell between parent and leaf checks John, Johansen
2007-12-20 14:09 ` [AppArmor 37/47] Switch to vfs_permission() in do_path_lookup() John, Johansen
2007-12-20 14:09 ` [AppArmor 38/47] Switch to vfs_permission() in sys_fchdir() John, Johansen
2007-12-20 14:09 ` [AppArmor 39/47] Fix file_permission() John, Johansen
2007-12-20 14:09 ` [AppArmor 40/47] Export audit subsystem for use by modules John, Johansen
2007-12-20 14:09 ` [AppArmor 41/47] AppArmor: Main Part John, Johansen
2007-12-20 14:09 ` [AppArmor 42/47] AppArmor: Module and LSM hooks John, Johansen
2007-12-20 14:09 ` [AppArmor 43/47] AppArmor: Profile loading and manipulation, pathname matching John, Johansen
2007-12-20 14:09 ` [AppArmor 44/47] AppArmor: all the rest John, Johansen
2007-12-20 14:09 ` [AppArmor 45/47] Add AppArmor LSM to security/Makefile John, Johansen
2007-12-20 14:09 ` John, Johansen [this message]
2007-12-20 14:09 ` [AppArmor 47/47] --- Documentation/lsm/AppArmor-Security-Goal.txt | 134 +++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) John, Johansen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071220140948.672608897@suse.de \
    --to=john@suse.de \
    --cc=Johansen@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=jjohansen@suse.de \
    --cc=jmichael@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.