mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Tony Jones <tonyj@suse.de>
To: linux-kernel@vger.kernel.org
Cc: chrisw@sous-sol.org, Tony Jones <tonyj@suse.de>,
	linux-security-module@vger.kernel.org
Subject: [RFC][PATCH 5/11] security: AppArmor - Filesystem
Date: Wed, 19 Apr 2006 10:49:46 -0700	[thread overview]
Message-ID: <20060419174946.29149.40949.sendpatchset@ermintrude.int.wirex.com> (raw)
In-Reply-To: <20060419174905.29149.67649.sendpatchset@ermintrude.int.wirex.com>

This patch implements the AppArmor file structure underneath securityfs.
Securityfs is normally mounted as /sys/kernel/security

The following files are created under /sys/kernel/security/apparmor
	control
		audit	   - Controls the global setting for auditing all
			     accesses.
		complain   - Controls the global setting for learning mode
			     (usually this is set per profile rather than
			     globally)
		debug	   - Controls whether debugging is enabled.
			     This needs to be made more fine grained
		logsyscall - Controls whether when logging to the audit 
			     subsystem full syscall auditing is enabled.

		The values by default for all of the above are 0.

	matching - Returns the features of the installed matching submodule
	profiles - Returns the profiles currently loaded and for each whether
		   it is in complain (learning) or enforce mode.
	.load
	.remove
	.replace - Used by userspace tools to load, remove and replace new 
		   profiles.


Signed-off-by: Tony Jones <tonyj@suse.de>

---
 security/apparmor/apparmorfs.c |  432 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 432 insertions(+)

--- /dev/null
+++ linux-2.6.17-rc1/security/apparmor/apparmorfs.c
@@ -0,0 +1,432 @@
+/*
+ *	Copyright (C) 2005 Novell/SUSE
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation, version 2 of the
+ *	License.
+ *
+ *	AppArmor filesystem (part of securityfs)
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+
+#include "apparmor.h"
+#include "inline.h"
+#include "match/match.h"
+
+#define SECFS_AA "apparmor"
+static struct dentry *aafs_dentry = NULL;
+
+/* profile */
+extern struct seq_operations apparmorfs_profiles_op;
+static int aa_prof_open(struct inode *inode, struct file *file);
+static int aa_prof_release(struct inode *inode, struct file *file);
+
+static struct file_operations apparmorfs_profiles_fops = {
+	.open =		aa_prof_open,
+	.read =		seq_read,
+	.llseek =	seq_lseek,
+	.release =	aa_prof_release,
+};
+
+/* matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+			       size_t size, loff_t *ppos);
+
+static struct file_operations apparmorfs_matching_fops = {
+	.read = 	aa_matching_read,
+};
+
+
+/* interface */
+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
+			       size_t size, loff_t *pos);
+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
+				  size_t size, loff_t *pos);
+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
+				 size_t size, loff_t *pos);
+
+static struct file_operations apparmorfs_profile_load = {
+	.write = aa_profile_load
+};
+
+static struct file_operations apparmorfs_profile_replace = {
+	.write = aa_profile_replace
+};
+
+static struct file_operations apparmorfs_profile_remove = {
+	.write = aa_profile_remove
+};
+
+
+/* control */
+static u64 aa_control_get(void *data);
+static void aa_control_set(void *data, u64 val);
+
+DEFINE_SIMPLE_ATTRIBUTE(apparmorfs_control_fops, aa_control_get,
+			aa_control_set, "%lld\n");
+
+
+
+/* table of static entries */
+
+static struct root_entry {
+	const char *name;
+	int mode;
+	int access;
+	struct file_operations *fops;
+	void *data;
+
+	/* internal fields */
+	struct dentry *dentry;
+	int parent_index;
+} root_entries[] = {
+	/* our root, normally /sys/kernel/security/apparmor */
+	{SECFS_AA, 	S_IFDIR, 0550},	/* DO NOT EDIT/MOVE */
+
+	/* interface for obtaining list of profiles currently loaded */
+	{"profiles", 	S_IFREG, 0440, &apparmorfs_profiles_fops,
+				       NULL},
+
+	/* interface for obtaining matching features supported */
+	{"matching",  	S_IFREG, 0440, &apparmorfs_matching_fops,
+				       NULL},
+
+	/* interface for loading/removing/replacing profiles */
+	{".load",    	S_IFREG, 0640, &apparmorfs_profile_load,
+				       NULL},
+	{".replace", 	S_IFREG, 0640, &apparmorfs_profile_replace,
+				       NULL},
+	{".remove",  	S_IFREG, 0640, &apparmorfs_profile_remove,
+				       NULL},
+
+	/* interface for setting binary config values */
+	{"control",  	S_IFDIR, 0550},
+	{"complain", 	S_IFREG, 0640, &apparmorfs_control_fops,
+				       &apparmor_complain},
+	{"audit",    	S_IFREG, 0640, &apparmorfs_control_fops,
+				       &apparmor_audit},
+	{"debug",    	S_IFREG, 0640, &apparmorfs_control_fops,
+				       &apparmor_debug},
+	{"logsyscall", 	S_IFREG, 0640, &apparmorfs_control_fops,
+				       &apparmor_logsyscall},
+	{NULL,       	S_IFDIR, 0},
+
+	/* root end */
+	{NULL,       	S_IFDIR, 0}
+};
+
+#define AAFS_DENTRY root_entries[0].dentry
+
+static const unsigned int num_entries =
+	sizeof(root_entries) / sizeof(struct root_entry);
+
+
+
+static int aa_prof_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &apparmorfs_profiles_op);
+}
+
+
+static int aa_prof_release(struct inode *inode, struct file *file)
+{
+	return seq_release(inode, file);
+}
+
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+			       size_t size, loff_t *ppos)
+{
+	const char *matching = aamatch_features();
+
+	return simple_read_from_buffer(buf, size, ppos, matching,
+				       strlen(matching));
+}
+
+static char *aa_simple_write_to_buffer(const char __user *userbuf,
+				       size_t alloc_size, size_t copy_size,
+				       loff_t *pos, const char *msg)
+{
+	struct aaprofile *active;
+	char *data;
+
+	if (*pos != 0) {
+		/* only writes from pos 0, that is complete writes */
+		data = ERR_PTR(-ESPIPE);
+		goto out;
+	}
+
+	/* Don't allow confined processes to load/replace/remove profiles.
+	 * No sane person would add rules allowing this to a profile
+	 * but we enforce the restriction anyways.
+	 */
+	rcu_read_lock();
+	active = get_activeptr_rcu();
+	if (active) {
+		AA_WARN("REJECTING access to profile %s (%s(%d) "
+			"profile %s active %s)\n",
+			msg, current->comm, current->pid,
+			BASE_PROFILE(active)->name, active->name);
+
+		data = ERR_PTR(-EPERM);
+		goto out;
+	}
+	rcu_read_unlock();
+
+	data = vmalloc(alloc_size);
+	if (data == NULL) {
+		data = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	if (copy_from_user(data, userbuf, copy_size)) {
+		vfree(data);
+		data = ERR_PTR(-EFAULT);
+		goto out;
+	}
+
+out:
+	return data;
+}
+
+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
+			       size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	data = aa_simple_write_to_buffer(buf, size, size, pos, "load");
+
+	if (!IS_ERR(data)) {
+		error = aa_file_prof_add(data, size);
+		vfree(data);
+	} else {
+		error = PTR_ERR(data);
+	}
+
+	return error;
+}
+
+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
+				  size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	data = aa_simple_write_to_buffer(buf, size, size, pos, "replacement");
+
+	if (!IS_ERR(data)) {
+		error = aa_file_prof_repl(data, size);
+		vfree(data);
+	} else {
+		error = PTR_ERR(data);
+	}
+
+	return error;
+}
+
+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
+				  size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	/* aa_file_prof_remove needs a null terminated string so 1 extra
+	 * byte is allocated and null the copied data is then null terminated
+	 */
+	data = aa_simple_write_to_buffer(buf, size+1, size, pos, "removal");
+
+	if (!IS_ERR(data)) {
+		data[size] = 0;
+		error = aa_file_prof_remove(data, size);
+		vfree(data);
+	} else {
+		error = PTR_ERR(data);
+	}
+
+	return error;
+}
+
+static u64 aa_control_get(void *data)
+{
+	return *(int *)data;
+}
+
+static void aa_control_set(void *data, u64 val)
+{
+	if (val > 1)
+		val = 1;
+
+	*(int*)data = (int)val;
+}
+
+static void clear_apparmorfs(void)
+{
+	unsigned int i;
+
+	for (i=0; i < num_entries;i++) {
+		unsigned int index;
+
+		if (root_entries[i].mode == S_IFDIR) {
+			if (root_entries[i].name)
+				/* defer dir free till all sub-entries freed */
+				continue;
+			else
+				/* cleanup parent */
+				index = root_entries[i].parent_index;
+		} else {
+			index = i;
+		}
+
+		if (root_entries[index].dentry) {
+			securityfs_remove(root_entries[index].dentry);
+
+			AA_DEBUG("%s: deleted apparmorfs entry name=%s "
+				 "dentry=%p\n",
+				__FUNCTION__,
+				root_entries[index].name,
+				root_entries[index].dentry);
+
+			root_entries[index].dentry = NULL;
+			root_entries[index].parent_index = 0;
+		}
+	}
+}
+
+static int populate_apparmorfs(struct dentry *root)
+{
+	unsigned int i, parent_index, depth;
+
+	for (i = 0; i < num_entries; i++) {
+		root_entries[i].dentry = NULL;
+		root_entries[i].parent_index = 0;
+	}
+
+	/* 1. Verify entry 0 is valid [sanity check] */
+	if (num_entries == 0 ||
+	    !root_entries[0].name ||
+	    strcmp(root_entries[0].name, SECFS_AA) != 0 ||
+	    root_entries[0].mode != S_IFDIR) {
+		AA_ERROR("%s: root entry 0 is not SECFS_AA/dir\n",
+			__FUNCTION__);
+		goto error;
+	}
+
+	/* 2. Build back pointers */
+	parent_index = 0;
+	depth = 1;
+
+	for (i = 1; i < num_entries; i++) {
+		root_entries[i].parent_index = parent_index;
+
+		if (root_entries[i].name &&
+		    root_entries[i].mode == S_IFDIR) {
+			depth++;
+			parent_index = i;
+		} else if (!root_entries[i].name) {
+			if (root_entries[i].mode != S_IFDIR || depth == 0) {
+				AA_ERROR("%s: root_entry %d invalid (%u %d)",
+					 __FUNCTION__, i,
+					 root_entries[i].mode,
+					 root_entries[i].parent_index);
+				goto error;
+			}
+
+			depth--;
+			parent_index = root_entries[parent_index].parent_index;
+		}
+	}
+
+	if (depth != 0) {
+		AA_ERROR("%s: root_entry table not correctly terminated\n",
+			__FUNCTION__);
+		goto error;
+	}
+
+	/* 3. Create root (parent=NULL) */
+	root_entries[0].dentry = securityfs_create_file(
+					root_entries[0].name,
+					root_entries[0].mode |
+						root_entries[0].access,
+					NULL, NULL, NULL);
+
+	if (IS_ERR(root_entries[0].dentry))
+		goto error;
+	else
+		AA_DEBUG("%s: created securityfs/apparmor [dentry=%p]\n",
+			__FUNCTION__, root_entries[0].dentry);
+
+
+	/* 4. create remaining nodes */
+	for (i = 1; i < num_entries; i++) {
+		struct dentry *parent;
+		void *data = NULL;
+		struct file_operations *fops = NULL;
+
+		/* end of directory ? */
+		if (!root_entries[i].name)
+			continue;
+
+		parent = root_entries[root_entries[i].parent_index].dentry;
+
+		if (root_entries[i].mode != S_IFDIR) {
+			data = root_entries[i].data;
+			fops = root_entries[i].fops;
+		}
+
+		root_entries[i].dentry = securityfs_create_file(
+						root_entries[i].name,
+						root_entries[i].mode |
+							root_entries[i].access,
+						parent,
+						data,
+						fops);
+
+		if (IS_ERR(root_entries[i].dentry))
+			goto cleanup_error;
+
+		AA_DEBUG("%s: added apparmorfs entry "
+			 "name=%s mode=%x dentry=%p [parent %p]\n",
+			__FUNCTION__, root_entries[i].name,
+			root_entries[i].mode|root_entries[i].access,
+			root_entries[i].dentry, parent);
+	}
+
+	return 0;
+
+cleanup_error:
+	clear_apparmorfs();
+
+error:
+	return -EINVAL;
+}
+
+int create_apparmorfs(void)
+{
+	int error = 0;
+
+	if (AAFS_DENTRY) {
+		error = -EEXIST;
+		AA_ERROR("%s: Subdomain securityfs already exists\n",
+			__FUNCTION__);
+	} else {
+		error = populate_apparmorfs(aafs_dentry);
+		if (error != 0) {
+			AA_ERROR("%s: Error populating Subdomain securityfs\n",
+				__FUNCTION__);
+		}
+	}
+
+	return error;
+}
+
+void destroy_apparmorfs(void)
+{
+	if (AAFS_DENTRY)
+		clear_apparmorfs();
+}

  parent reply	other threads:[~2006-04-19 17:54 UTC|newest]

Thread overview: 173+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-04-19 17:49 [RFC][PATCH 0/11] security: AppArmor - Overview Tony Jones
2006-04-19 17:49 ` [RFC][PATCH 1/11] security: AppArmor - Integrate into kbuild Tony Jones
2006-04-19 17:57   ` Arjan van de Ven
2006-04-19 18:10     ` Tony Jones
2006-04-19 18:35   ` Valdis.Kletnieks
2006-04-19 19:55   ` Adrian Bunk
2006-04-19 20:52     ` Tony Jones
2006-04-19 17:49 ` [RFC][PATCH 2/11] security: AppArmor - Core headers Tony Jones
2006-04-19 18:01   ` Arjan van de Ven
2006-04-20 17:43     ` Tony Jones
2006-04-19 17:49 ` [RFC][PATCH 3/11] security: AppArmor - LSM interface Tony Jones
2006-04-19 18:05   ` Arjan van de Ven
2006-04-19 17:49 ` [RFC][PATCH 4/11] security: AppArmor - Core access controls Tony Jones
2006-04-19 18:10   ` Arjan van de Ven
2006-04-19 18:57     ` Crispin Cowan
2006-04-19 23:05       ` Rik van Riel
2006-04-19 23:18         ` Seth Arnold
2006-04-19 23:21           ` Rik van Riel
2006-04-19 23:50             ` Crispin Cowan
2006-04-20 12:33       ` Stephen Smalley
2006-04-20 16:27         ` Lars Marowsky-Bree
2006-04-20 17:39     ` Tony Jones
2006-04-19 19:32   ` Jan Engelhardt
2006-04-19 19:50   ` Stephen Smalley
2006-04-20  9:40   ` Al Viro
2006-04-20 11:40     ` Serge E. Hallyn
2006-04-20 21:39       ` Tony Jones
2006-04-19 17:49 ` Tony Jones [this message]
2006-04-21 21:13   ` [RFC][PATCH 5/11] security: AppArmor - Filesystem Amy Griffis
2006-04-19 17:49 ` [RFC][PATCH 6/11] security: AppArmor - Userspace interface Tony Jones
2006-04-20 21:39   ` Pavel Machek
2006-04-21 18:01     ` Tony Jones
2006-04-21 18:41       ` Pavel Machek
2006-04-19 17:50 ` [RFC][PATCH 7/11] security: AppArmor - Misc (capabilities, data structures) Tony Jones
2006-04-19 18:16   ` Stephen Hemminger
2006-04-19 17:50 ` [RFC][PATCH 8/11] security: AppArmor - Pathname matching submodule Tony Jones
2006-04-19 17:50 ` [RFC][PATCH 9/11] security: AppArmor - Audit changes Tony Jones
2006-04-21 21:21   ` Amy Griffis
2006-04-22  0:13     ` Steve Grubb
2006-04-22  0:19       ` Tony Jones
2006-04-19 17:50 ` [RFC][PATCH 10/11] security: AppArmor - Add flags to d_path Tony Jones
2006-04-19 22:12   ` Christoph Hellwig
2006-04-20  5:36     ` Tony Jones
2006-04-20  8:26       ` Arjan van de Ven
2006-04-20 16:43         ` Tony Jones
2006-04-20 17:04           ` Christoph Hellwig
2006-04-20 17:50             ` Tony Jones
2006-04-21 12:16               ` Stephen Smalley
2006-04-24 13:05       ` Alan Cox
2006-04-19 17:50 ` [RFC][PATCH 11/11] security: AppArmor - Export namespace semaphore Tony Jones
2006-04-19 22:10   ` Christoph Hellwig
2006-04-20 12:39   ` Stephen Smalley
2006-04-20 12:46     ` Serge E. Hallyn
2006-04-20 12:05       ` Stephen Smalley
2006-04-20 13:21         ` Serge E. Hallyn
2006-04-20 12:48           ` Stephen Smalley
2006-04-20 12:58             ` Stephen Smalley
2006-04-20 22:11             ` Linda A. Walsh
2006-04-20 23:05               ` Christoph Hellwig
2006-04-21  1:29                 ` Linda A. Walsh
2006-04-21  2:09                   ` Chris Wright
2006-04-21  5:10                     ` Linda Walsh
2006-04-23 12:11                       ` Arjan van de Ven
2006-04-21 14:02               ` Stephen Smalley
2006-04-20 19:45           ` Tony Jones
2006-04-20 20:16             ` Serge E. Hallyn
2006-04-20 20:22             ` James Morris
2006-04-20 21:50     ` Linda Walsh
2006-04-20 21:56       ` Al Viro
2006-04-20 23:54         ` James Morris
2006-04-21 13:59       ` Stephen Smalley
2006-04-19 18:14 ` [RFC][PATCH 0/11] security: AppArmor - Overview Arjan van de Ven
2006-04-19 22:32   ` Andi Kleen
2006-04-19 23:00     ` grundig
2006-04-19 23:38       ` Andi Kleen
2006-04-20  1:32         ` Crispin Cowan
2006-04-20 13:00           ` grundig
2006-04-20 13:09             ` Serge E. Hallyn
2006-04-20 13:15               ` Al Viro
2006-04-21  0:11               ` Tony Jones
2006-04-24 13:01             ` Alan Cox
2006-04-20  8:42     ` Arjan van de Ven
2006-04-20 19:26       ` Crispin Cowan
2006-04-20 19:27       ` Chris Wright
2006-04-21 12:18         ` Stephen Smalley
2006-04-21 17:30           ` Chris Wright
2006-04-21 18:07             ` Stephen Smalley
2006-04-21 20:06               ` Valdis.Kletnieks
2006-04-21 20:35                 ` Stephen Smalley
2006-04-21 20:44                   ` Stephen Smalley
2006-04-21 21:38                   ` Dave Neuer
2006-04-22 10:01                     ` Thomas Bleher
2006-04-24  4:18               ` Neil Brown
2006-04-24  7:03                 ` Theodore Ts'o
2006-04-24 13:04                   ` Pavel Machek
2006-04-24 13:43                     ` Joshua Brindle
2006-04-24 21:07                   ` Stephen Smalley
2006-04-24 23:52                     ` Theodore Ts'o
2006-04-25  6:22                       ` Arjan van de Ven
2006-04-25 16:45                       ` Stephen Smalley
2006-04-25 16:52                         ` Arjan van de Ven
2006-04-25 17:43                           ` Seth Arnold
2006-04-25 18:34                         ` Valdis.Kletnieks
2006-04-25 18:48                           ` Stephen Smalley
2006-04-25 18:56                             ` Valdis.Kletnieks
2006-04-25  4:25                     ` Casey Schaufler
2006-04-25  7:50                       ` James Morris
2006-04-25 12:46                         ` Theodore Ts'o
2006-04-25 15:06                           ` Stephen Smalley
2006-04-25 16:00                         ` Casey Schaufler
2006-04-25 16:21                           ` Randy.Dunlap
2006-04-26  3:42                             ` Casey Schaufler
2006-04-26 12:15                               ` Stephen Smalley
2006-04-27  0:21                                 ` Casey Schaufler
2006-04-27 14:47                                   ` Karl MacMillan
2006-04-25 17:29                           ` Stephen Smalley
2006-04-26  3:56                             ` Casey Schaufler
2006-04-26 11:32                               ` Stephen Smalley
2006-04-25 16:47                       ` Stephen Smalley
2006-04-24  7:14                 ` Arjan van de Ven
2006-04-24  8:11                   ` Lars Marowsky-Bree
2006-04-25 19:27                   ` Seth Arnold
2006-04-24 13:11                 ` Joshua Brindle
2006-04-24 13:26                   ` Andi Kleen
2006-04-24 13:39                     ` Joshua Brindle
2006-04-24 15:16                       ` Joshua Brindle
2006-04-24 15:50                         ` Tony Jones
2006-04-24 17:03                           ` Joshua Brindle
2006-04-25 17:12                         ` Valdis.Kletnieks
2006-04-25 17:34                           ` Tony Jones
2006-04-24 13:52                     ` Alan Cox
2006-04-24 14:09                       ` Andi Kleen
2006-04-24 20:45                 ` Stephen Smalley
2006-04-25  8:10                   ` Neil Brown
2006-04-25  8:28                     ` Al Viro
2006-04-25 12:42                     ` James Carter
2006-04-25 12:43                       ` Andi Kleen
2006-04-25 14:50                         ` James Carter
2006-04-25 15:01                         ` Stephen Smalley
2006-04-25 18:11                           ` Tony Jones
2006-04-25 21:25                             ` Stephen Smalley
2006-04-25 17:07                     ` Stephen Smalley
2006-04-26 22:15                       ` Some Concrete AppArmor Questions - was " Neil Brown
2006-04-26 23:06                         ` Ken Brush
2006-04-27  4:15                           ` Andi Kleen
2006-04-27  6:52                             ` Arjan van de Ven
2006-04-27  7:40                               ` Chris Wright
2006-04-27 10:17                             ` Chris Wright
2006-04-27 14:42                               ` Karl MacMillan
2006-04-27 23:44                                 ` Chris Wright
2006-04-28 13:02                                   ` Stephen Smalley
2006-04-28 15:49                                     ` Casey Schaufler
2006-04-28 16:04                                       ` Stephen Hemminger
2006-04-28 21:49                                         ` James Morris
2006-04-28 16:56                                       ` Karl MacMillan
2006-04-27 16:03                               ` Stephen Smalley
2006-04-27 22:38                                 ` Chris Wright
2006-04-28 13:00                                   ` Stephen Smalley
2006-04-27 17:43                           ` Stephen Smalley
2006-04-27 17:58                             ` Ken Brush
2006-04-28 11:28                               ` Stephen Smalley
2006-04-28 11:47                                 ` Andi Kleen
2006-04-28 12:28                                   ` Stephen Smalley
2006-04-27 11:02                         ` Christoph Hellwig
2006-04-27 11:05                           ` Andi Kleen
2006-04-20 11:29     ` Serge E. Hallyn
2006-04-20 13:24     ` Christoph Hellwig
2006-04-20 22:32     ` Linda A. Walsh
2006-04-20 12:17 ` Stephen Smalley
2006-04-20 15:38   ` Joshua Brindle
2006-04-20 19:57   ` Crispin Cowan
2006-04-21 13:34     ` Stephen Smalley
2006-04-22 12:27 ` Pavel Machek

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=20060419174946.29149.40949.sendpatchset@ermintrude.int.wirex.com \
    --to=tonyj@suse.de \
    --cc=chrisw@sous-sol.org \
    --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

Powered by JetHome