linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: jjohansen@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 41/45] add simple network toggles to apparmor
Date: Thu, 25 Oct 2007 23:41:05 -0700	[thread overview]
Message-ID: <20071026064052.704759677@suse.de> (raw)
In-Reply-To: 20071026064024.243943043@suse.de

[-- Attachment #1: apparmor-network.diff --]
[-- Type: text/plain, Size: 10877 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              |  147 ++++++++++++++++++++++++++++++++++-
 security/apparmor/main.c             |   96 ++++++++++++++++++++++
 security/apparmor/module_interface.c |   20 ++++
 5 files changed, 273 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
@@ -174,6 +176,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;
@@ -220,6 +223,7 @@ struct aa_audit {
 	int request_mask, denied_mask;
 	struct iattr *iattr;
 	pid_t task, parent;
+	int family, type, protocol;
 	int error_code;
 };
 
@@ -281,6 +285,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"
@@ -617,6 +618,133 @@ 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_socket_getpeersec_stream(struct socket *sock,
+			char __user *optval, int __user *optlen, unsigned len)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_getpeersec_stream");
+}
+
+static int apparmor_socket_getpeersec_dgram(struct socket *sock,
+					struct sk_buff *skb, u32 *secid)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_getpeersec_dgram");
+}
+
 static int apparmor_getprocattr(struct task_struct *task, char *name,
 				char **value)
 {
@@ -717,9 +845,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,
@@ -755,6 +880,22 @@ 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,
+	.socket_getpeersec_stream =	apparmor_socket_getpeersec_stream,
+	.socket_getpeersec_dgram =	apparmor_socket_getpeersec_dgram,
 };
 
 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"
 
@@ -344,6 +347,24 @@ static void aa_audit_file_mask(struct au
 	audit_log_format(ab, " %s=\"%s:%s:%s\"", name, user, group, 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
@@ -409,6 +430,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) {
@@ -730,6 +769,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-10-26  7:14 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-26  6:40 [AppArmor 00/45] AppArmor security module overview jjohansen
2007-10-26  6:40 ` [AppArmor 01/45] Pass struct vfsmount to the inode_create LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 02/45] Pass struct path down to remove_suid and children jjohansen
2007-10-26  6:40 ` [AppArmor 03/45] Add a vfsmount parameter to notify_change() jjohansen
2007-10-26  6:40 ` [AppArmor 04/45] Pass struct vfsmount to the inode_setattr LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 05/45] Add struct vfsmount parameter to vfs_mkdir() jjohansen
2007-10-26  6:40 ` [AppArmor 06/45] Pass struct vfsmount to the inode_mkdir LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 07/45] Add a struct vfsmount parameter to vfs_mknod() jjohansen
2007-10-26  6:40 ` [AppArmor 08/45] Pass struct vfsmount to the inode_mknod LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 09/45] Add a struct vfsmount parameter to vfs_symlink() jjohansen
2007-10-26  6:40 ` [AppArmor 10/45] Pass struct vfsmount to the inode_symlink LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 11/45] Pass struct vfsmount to the inode_readlink " jjohansen
2007-10-26  6:40 ` [AppArmor 12/45] Add struct vfsmount parameters to vfs_link() jjohansen
2007-10-26  6:40 ` [AppArmor 13/45] Pass the struct vfsmounts to the inode_link LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 14/45] Add a struct vfsmount parameter to vfs_rmdir() jjohansen
2007-10-26  6:40 ` [AppArmor 15/45] Pass struct vfsmount to the inode_rmdir LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 16/45] Call lsm hook before unhashing dentry in vfs_rmdir() jjohansen
2007-10-26  6:40 ` [AppArmor 17/45] Add a struct vfsmount parameter to vfs_unlink() jjohansen
2007-10-26  6:40 ` [AppArmor 18/45] Pass struct vfsmount to the inode_unlink LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 19/45] Add struct vfsmount parameters to vfs_rename() jjohansen
2007-10-26  7:37   ` Al Viro
2007-10-26 18:23     ` John Johansen
2007-10-26 20:33       ` Al Viro
2007-10-26  6:40 ` [AppArmor 20/45] Pass struct vfsmount to the inode_rename LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 21/45] Add a struct vfsmount parameter to vfs_setxattr() jjohansen
2007-10-26  6:40 ` [AppArmor 22/45] Pass struct vfsmount to the inode_setxattr LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 23/45] Add a struct vfsmount parameter to vfs_getxattr() jjohansen
2007-10-26  6:40 ` [AppArmor 24/45] Pass struct vfsmount to the inode_getxattr LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 25/45] Add a struct vfsmount parameter to vfs_listxattr() jjohansen
2007-10-26  6:40 ` [AppArmor 26/45] Pass struct vfsmount to the inode_listxattr LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 27/45] Add a struct vfsmount parameter to vfs_removexattr() jjohansen
2007-10-26  6:40 ` [AppArmor 28/45] Pass struct vfsmount to the inode_removexattr LSM hook jjohansen
2007-10-26  6:40 ` [AppArmor 29/45] Fix __d_path() for lazy unmounts and make it unambiguous jjohansen
2007-10-26  6:40 ` [AppArmor 30/45] Make d_path() consistent across mount operations jjohansen
2007-10-26  6:40 ` [AppArmor 31/45] Add d_namespace_path() to compute namespace relative pathnames jjohansen
2007-10-26  6:40 ` [AppArmor 32/45] Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames jjohansen
2007-10-26 11:30   ` Miklos Szeredi
2007-10-26 11:45     ` Miklos Szeredi
2007-10-26 18:49     ` John Johansen
2007-10-26 20:24     ` Andreas Gruenbacher
2007-10-26 20:58       ` Miklos Szeredi
2007-10-26 21:56         ` Andreas Gruenbacher
2007-10-26  6:40 ` [AppArmor 33/45] Pass struct file down the inode_*xattr security LSM hooks jjohansen
2007-10-26  6:40 ` [AppArmor 34/45] Factor out sysctl pathname code jjohansen
2007-10-26  9:24   ` James Morris
2007-10-26  6:40 ` [AppArmor 35/45] Allow permission functions to tell between parent and leaf checks jjohansen
2007-10-26 12:32   ` Stephen Smalley
2007-10-26 18:26     ` John Johansen
2007-10-26  6:41 ` [AppArmor 36/45] Export audit subsystem for use by modules jjohansen
2007-10-26  6:41 ` [AppArmor 37/45] AppArmor: Main Part jjohansen
2007-10-26  6:41 ` [AppArmor 38/45] AppArmor: Module and LSM hooks jjohansen
2007-10-26  6:41 ` [AppArmor 39/45] AppArmor: Profile loading and manipulation, pathname matching jjohansen
2007-10-26  6:41 ` [AppArmor 40/45] AppArmor: all the rest jjohansen
2007-10-26  6:41 ` jjohansen [this message]
2007-10-26  6:41 ` [AppArmor 42/45] Add AppArmor LSM to security/Makefile jjohansen
2007-10-26  6:41 ` [AppArmor 43/45] Switch to vfs_permission() in do_path_lookup() jjohansen
2007-10-26  6:41 ` [AppArmor 44/45] Switch to vfs_permission() in sys_fchdir() jjohansen
2007-10-26  6:41 ` [AppArmor 45/45] Fix file_permission() jjohansen
2007-10-26  7:04 ` [AppArmor 00/45] AppArmor security module overview John Johansen
2007-10-26 14:37 ` Arjan van de Ven
2007-10-26 18:34   ` John Johansen
2007-10-26 20:15     ` Arjan van de Ven
2007-10-26 20:44   ` Andreas Gruenbacher
2007-10-26 21:13     ` Arjan van de Ven
2007-10-26 21:24       ` Andreas Gruenbacher
2007-10-26 22:16       ` Crispin Cowan
2007-10-26 22:23         ` Arjan van de Ven
2007-10-27 20:47   ` Christoph Hellwig
2007-10-28 14:25     ` Andreas Gruenbacher

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=20071026064052.704759677@suse.de \
    --to=jjohansen@suse.de \
    --cc=akpm@linux-foundation.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).