linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Check files' signatures before doing suid/sgid [2/4]
@ 2007-06-21 16:02 Alexander Wuerstlein
  2007-06-21 17:17 ` Arjan van de Ven
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Wuerstlein @ 2007-06-21 16:02 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alexander Wuerstlein, Johannes Schlumberger

Modified task_struct to hold a 'signed flag' which is set on exec(), inherited
on fork() and checked during exec before giving the new process suid/sgid
privileges.

sns.c contains our helper functions to verify the signatures.
sns_secret_key.dat contains the 'secret key' which is used for HMAC.

Signed-off-by: Johannes Schlumberger <spjsschl@cip.informatik.uni-erlangen.de>
---
 fs/exec.c                   |   19 +++++++-
 include/linux/Kbuild        |    2 +
 include/linux/sched.h       |    3 +
 include/linux/sns.h         |    3 +
 kernel/fork.c               |    6 +++
 security/Kconfig            |   28 ++++++++++++
 security/Makefile           |    1 +
 security/sns.c              |  104 +++++++++++++++++++++++++++++++++++++++++++
 security/sns_secret_key.dat |    5 ++
 9 files changed, 169 insertions(+), 2 deletions(-)
 create mode 100644 include/linux/sns.h
 create mode 100644 security/sns.c
 create mode 100644 security/sns_secret_key.dat

diff --git a/fs/exec.c b/fs/exec.c
index f20561f..5dfa406 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -51,6 +51,9 @@
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
 #include <linux/signalfd.h>
+#ifdef CONFIG_SNS_SIGNED
+#include <linux/sns.h>
+#endif
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -928,13 +931,21 @@ int prepare_binprm(struct linux_binprm *bprm)
 	mode = inode->i_mode;
 	if (bprm->file->f_op == NULL)
 		return -EACCES;
+#ifdef CONFIG_SNS_SIGNED
+	if (mode & S_ISUID)
+		current->sns_valid_sig = sns_signature_valid(bprm->file);
+#endif
 
 	bprm->e_uid = current->euid;
 	bprm->e_gid = current->egid;
 
 	if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
 		/* Set-uid? */
-		if (mode & S_ISUID) {
+#ifdef CONFIG_SNS_SIGNED_SETUID
+               if (mode & S_ISUID && current->sns_valid_sig) {
+#else
+               if (mode & S_ISUID) {
+#endif /*SNS_SIGNED_SETUID*/
 			current->personality &= ~PER_CLEAR_ON_SETID;
 			bprm->e_uid = inode->i_uid;
 		}
@@ -945,7 +956,11 @@ int prepare_binprm(struct linux_binprm *bprm)
 		 * is a candidate for mandatory locking, not a setgid
 		 * executable.
 		 */
-		if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+#ifdef CONFIG_SNS_SIGNED_SETGID
+               if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && current->sns_valid_sig) {
+#else
+               if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+#endif /*SNS_SIGNED_SETGID*/
 			current->personality &= ~PER_CLEAR_ON_SETID;
 			bprm->e_gid = inode->i_gid;
 		}
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index f317c27..16df5f0 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -159,6 +159,7 @@ header-y += videotext.h
 header-y += vt.h
 header-y += wireless.h
 header-y += x25.h
+header-y += sns.h
 
 unifdef-y += acct.h
 unifdef-y += adb.h
@@ -347,5 +348,6 @@ unifdef-y += watchdog.h
 unifdef-y += wireless.h
 unifdef-y += xattr.h
 unifdef-y += xfrm.h
+unifdef-y += sns.h
 
 objhdr-y += version.h
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 693f0e6..36c58d6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1076,6 +1076,9 @@ struct task_struct {
 #ifdef CONFIG_FAULT_INJECTION
 	int make_it_fail;
 #endif
+#ifdef CONFIG_SNS_SIGNED
+	int sns_valid_sig;
+#endif
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
diff --git a/include/linux/sns.h b/include/linux/sns.h
new file mode 100644
index 0000000..ad15e4b
--- /dev/null
+++ b/include/linux/sns.h
@@ -0,0 +1,3 @@
+#ifdef CONFIG_SNS_SIGNED
+int sns_signature_valid(struct file *);
+#endif
diff --git a/kernel/fork.c b/kernel/fork.c
index 73ad5cd..c12cf61 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -156,6 +156,9 @@ void __init fork_init(unsigned long mempages)
 	init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
 	init_task.signal->rlim[RLIMIT_SIGPENDING] =
 		init_task.signal->rlim[RLIMIT_NPROC];
+#ifdef CONFIG_SNS_SIGNED
+	init_task.sns_valid_sig = 0;
+#endif
 }
 
 static struct task_struct *dup_task_struct(struct task_struct *orig)
@@ -182,6 +185,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 #ifdef CONFIG_CC_STACKPROTECTOR
 	tsk->stack_canary = get_random_int();
 #endif
+#ifdef CONFIG_SNS_SIGNED
+	tsk->sns_valid_sig = orig->sns_valid_sig;
+#endif
 
 	/* One for us, one for whoever does the "release_task()" (usually parent) */
 	atomic_set(&tsk->usage,2);
diff --git a/security/Kconfig b/security/Kconfig
index 460e5c9..bfaace7 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -4,6 +4,34 @@
 
 menu "Security options"
 
+config SNS_SIGNED
+	bool "Enable sns-signed binaries (EXPERIMENTAL)"
+	depends on (EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR || REISERFS_FS_XATTR || JFFS2_FS_XATTR || CIFS_XATTR) && (CRYPTO_SHA1 || CRYPTO_HMAC || CRYPTO_MD5) && MMU && EXPERIMENTAL
+	help
+	  This option turns on sns-signatures of binaries. Requires extended
+	  attributes and cryptographic hashes/HMAC support. HMAC is preferred.
+
+	  This will leave your system unusable without proper preparation of
+	  your sbit-files.
+
+	  If you don't know exactly what you are doing, answer N.
+
+config SNS_SIGNED_SETUID
+	bool "Enables sns-signed binaries mandatory for suid-bits"
+	depends on SNS_SIGNED
+	help
+	  Mandates signed binaries for suidbits.
+
+	  If you don't know exactly what you are doing, answer N.
+
+config SNS_SIGNED_SETGID
+	bool "Enables sns-signed binaries mandatory for sgid-bits"
+	depends on SNS_SIGNED
+	help
+	  Mandates signed binaries for sgidbits.
+
+	  If you don't know exactly what you are doing, answer N.
+
 config KEYS
 	bool "Enable access key retention support"
 	help
diff --git a/security/Makefile b/security/Makefile
index ef87df2..677b978 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_SECURITY)			+= security.o dummy.o inode.o
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+obj-$(CONFIG_SNS_SIGNED)		+= sns.o
diff --git a/security/sns.c b/security/sns.c
new file mode 100644
index 0000000..4403e5a
--- /dev/null
+++ b/security/sns.c
@@ -0,0 +1,104 @@
+#include <linux/crypto.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/scatterlist.h>
+#include <linux/xattr.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/sns.h>
+
+#include "sns_secret_key.dat"
+
+#define SNS_MAX_DIGEST_SIZE	64
+
+struct sns_attr {
+	char algname[CRYPTO_MAX_ALG_NAME+1];
+	char hash_value[SNS_MAX_DIGEST_SIZE];
+};
+
+
+static int sns_sig_reader(read_descriptor_t *desc, struct page *page, unsigned long offset, unsigned long nr)
+{
+	struct scatterlist s;
+	struct hash_desc *hash_desc = (struct hash_desc *) desc->arg.data;
+	unsigned int read;
+
+	s.page = page;
+	s.offset = offset;
+	s.length = nr;
+	read = nr - offset;
+	crypto_hash_update(hash_desc, &s, read);
+	desc->written += read;
+	desc->count -= read;
+	return read;
+}
+
+/*
+ * check file signature for setuid
+ */
+
+int sns_signature_valid(struct file *file)
+{
+	unsigned long i;
+	struct inode *inode = file->f_mapping->host;
+	struct crypto_hash *tfm;
+	struct hash_desc hash_desc;
+	struct sns_attr attrdata;
+	char hash_result[SNS_MAX_DIGEST_SIZE];
+	struct xattr_handler *handler;
+	const char *namespaces[2] = { "trusted.", NULL };
+	int ret = 0;
+	loff_t pos = 0;
+	read_descriptor_t read_desc;
+
+	handler = xattr_resolve_name_sns(inode->i_sb->s_xattr, namespaces);
+	if (unlikely(!handler)) {
+		printk(KERN_DEBUG "sns_signature_valid: xattr_resolve_name failed\n");
+		return 0;
+	}
+	memset(&attrdata, 0, sizeof(struct sns_attr));
+	i = handler->get(inode, "sns", &attrdata, sizeof(struct sns_attr));
+	if (i != sizeof(struct sns_attr)) {
+		printk(KERN_DEBUG "sns_signature_valid: invalid xattr found\n");
+		return 0;
+	}
+	attrdata.algname[CRYPTO_MAX_ALG_NAME] = '\0';
+	read_desc.count = i_size_read(inode);
+	if (unlikely(!read_desc.count)) {
+		printk(KERN_DEBUG "sns_signature_valid: inode of file has invalid size\n");
+		return 0;
+	}
+	tfm = crypto_alloc_hash(attrdata.algname, 0, CRYPTO_ALG_ASYNC);
+	if (unlikely(IS_ERR(tfm))) {
+		printk("sns_signature_valid: %s unavailable\n", attrdata.algname);
+		return 0;
+		/*FIXME: failure mode should be defined at build-time */
+	}
+	memset(hash_result, 0, SNS_MAX_DIGEST_SIZE); /*Needed?*/
+	hash_desc.tfm = tfm;
+	hash_desc.flags = 0;
+	read_desc.arg.data = &hash_desc;
+	read_desc.written = 0;
+	if (crypto_hash_setkey(tfm, sns_secret_key, SNS_SECRET_KEY_SIZE)) {
+		printk("sns_signature_valid: hash function did not accept setkey\n");
+		return 0;
+	}
+	crypto_hash_init(&hash_desc);
+	do_generic_file_read(file, &pos, &read_desc, sns_sig_reader);
+	crypto_hash_final(&hash_desc, hash_result);
+	BUG_ON(read_desc.written != i_size_read(inode));
+#ifdef SNS_SIGNED_DEBUG
+	printk("sns_signature_valid: attrdata.algname = %s\n", attrdata.algname);
+	printk("sns_signature_valid: attrib: ");
+	for (i = 0; i < SNS_MAX_DIGEST_SIZE; i++)
+		printk("%02x ", (unsigned char) attrdata.hash_value[i]);
+	printk("\n");
+	printk("sns_signature_valid: result: ");
+	for (i = 0; i < SNS_MAX_DIGEST_SIZE; i++)
+		printk("%02x ", (unsigned char) hash_result[i]);
+	printk("\n");
+#endif
+	ret = !memcmp(attrdata.hash_value, hash_result, SNS_MAX_DIGEST_SIZE);
+	crypto_free_hash(tfm);
+	return ret;
+}
diff --git a/security/sns_secret_key.dat b/security/sns_secret_key.dat
new file mode 100644
index 0000000..aec09da
--- /dev/null
+++ b/security/sns_secret_key.dat
@@ -0,0 +1,5 @@
+#define SNS_SECRET_KEY_SIZE 8
+static char sns_secret_key[SNS_SECRET_KEY_SIZE] =
+	{
+		'd', 'e', 'a', 'd', 'b', 'e', 'e', 'f'
+	};
-- 
1.5.2.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-21 16:02 [PATCH] Check files' signatures before doing suid/sgid [2/4] Alexander Wuerstlein
@ 2007-06-21 17:17 ` Arjan van de Ven
  2007-06-21 17:25   ` Alexander Wuerstlein
  0 siblings, 1 reply; 16+ messages in thread
From: Arjan van de Ven @ 2007-06-21 17:17 UTC (permalink / raw)
  To: Alexander Wuerstlein; +Cc: linux-kernel, Johannes Schlumberger

On Thu, 2007-06-21 at 18:02 +0200, Alexander Wuerstlein wrote:
> Modified task_struct to hold a 'signed flag' which is set on exec(), inherited
> on fork() and checked during exec before giving the new process suid/sgid
> privileges.
> 



do you also check the signature of glibc and every other shared library
that the app uses (or dlopens)? if not.. the entire exercise is rather
pointless...


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-21 17:17 ` Arjan van de Ven
@ 2007-06-21 17:25   ` Alexander Wuerstlein
  2007-06-21 17:29     ` Arjan van de Ven
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Wuerstlein @ 2007-06-21 17:25 UTC (permalink / raw)
  To: Arjan van de Ven
  Cc: Alexander Wuerstlein, linux-kernel, Johannes Schlumberger

On 070621 19:21, Arjan van de Ven <arjan@infradead.org> wrote:
> On Thu, 2007-06-21 at 18:02 +0200, Alexander Wuerstlein wrote:
> > Modified task_struct to hold a 'signed flag' which is set on exec(), inherited
> > on fork() and checked during exec before giving the new process suid/sgid
> > privileges.
> > 
> 
> 
> 
> do you also check the signature of glibc and every other shared library
> that the app uses (or dlopens)? if not.. the entire exercise is rather
> pointless...

We do check that, that is patch [3/4].

Of course we can only check mmap-ed files, if there is no file like with JIT
compilers we are out of luck.


Ciao,

Alexander Wuerstlein.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-21 17:25   ` Alexander Wuerstlein
@ 2007-06-21 17:29     ` Arjan van de Ven
  2007-06-21 17:46       ` Alexander Wuerstlein
  0 siblings, 1 reply; 16+ messages in thread
From: Arjan van de Ven @ 2007-06-21 17:29 UTC (permalink / raw)
  To: Alexander Wuerstlein
  Cc: Alexander Wuerstlein, linux-kernel, Johannes Schlumberger

On Thu, 2007-06-21 at 19:25 +0200, Alexander Wuerstlein wrote:
> On 070621 19:21, Arjan van de Ven <arjan@infradead.org> wrote:
> > On Thu, 2007-06-21 at 18:02 +0200, Alexander Wuerstlein wrote:
> > > Modified task_struct to hold a 'signed flag' which is set on exec(), inherited
> > > on fork() and checked during exec before giving the new process suid/sgid
> > > privileges.
> > > 
> > 
> > 
> > 
> > do you also check the signature of glibc and every other shared library
> > that the app uses (or dlopens)? if not.. the entire exercise is rather
> > pointless...
> 
> We do check that, that is patch [3/4].
> 
> Of course we can only check mmap-ed files, if there is no file like with JIT
> compilers we are out of luck.

or if the process uses read() not mmap().

or .. or ...


so if perl is signed and it's the perl script that is setuid, and then
it includes other perl libs... that's read() not mmap().

-- 
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-21 17:29     ` Arjan van de Ven
@ 2007-06-21 17:46       ` Alexander Wuerstlein
  2007-06-21 18:49         ` Arjan van de Ven
  2007-06-23 18:01         ` Jan Engelhardt
  0 siblings, 2 replies; 16+ messages in thread
From: Alexander Wuerstlein @ 2007-06-21 17:46 UTC (permalink / raw)
  To: Arjan van de Ven; +Cc: linux-kernel, arw

On 070621 19:33, Arjan van de Ven <arjan@infradead.org> wrote:
> On Thu, 2007-06-21 at 19:25 +0200, Alexander Wuerstlein wrote:
> > On 070621 19:21, Arjan van de Ven <arjan@infradead.org> wrote:
> > > On Thu, 2007-06-21 at 18:02 +0200, Alexander Wuerstlein wrote:
> > > > Modified task_struct to hold a 'signed flag' which is set on exec(), inherited
> > > > on fork() and checked during exec before giving the new process suid/sgid
> > > > privileges.
> > > > 
> > > 
> > > 
> > > 
> > > do you also check the signature of glibc and every other shared library
> > > that the app uses (or dlopens)? if not.. the entire exercise is rather
> > > pointless...
> > 
> > We do check that, that is patch [3/4].
> > 
> > Of course we can only check mmap-ed files, if there is no file like with JIT
> > compilers we are out of luck.
> 
> or if the process uses read() not mmap().

If a process uses read() it needs some executable and writable memory. We do
check for this in mprotect(). There is a problem with the i386-architecture,
because it allows execution of any readable page (except with newer
processors). But beyond that ugliness of i386, it should not be possible to
execute anything without us noticing it (hopefully).

Scripting languages are of course problematic. In the suid-case you could just
call anyone insane who wants to use a suid-shellscript. But in other cases one
might want signed binaries for, we do have a problem. With java or shell one
would need an interpreter/vm which is signed and reasonably trustworthy itself
and checks the signature of the shellscript or classfile it executes.  The
(probably not all too complicated) writing of such an interpreter is left as an
exercise to the reader ;)



Ciao,

Alexander Wuerstlein.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-21 17:46       ` Alexander Wuerstlein
@ 2007-06-21 18:49         ` Arjan van de Ven
  2007-06-21 21:40           ` Johannes Schlumberger
  2007-06-23 18:01         ` Jan Engelhardt
  1 sibling, 1 reply; 16+ messages in thread
From: Arjan van de Ven @ 2007-06-21 18:49 UTC (permalink / raw)
  To: Alexander Wuerstlein; +Cc: linux-kernel, arw

On Thu, 2007-06-21 at 19:46 +0200, Alexander Wuerstlein wrote:
> On 070621 19:33, Arjan van de Ven <arjan@infradead.org> wrote:
> > On Thu, 2007-06-21 at 19:25 +0200, Alexander Wuerstlein wrote:
> > > On 070621 19:21, Arjan van de Ven <arjan@infradead.org> wrote:
> > > > On Thu, 2007-06-21 at 18:02 +0200, Alexander Wuerstlein wrote:
> > > > > Modified task_struct to hold a 'signed flag' which is set on exec(), inherited
> > > > > on fork() and checked during exec before giving the new process suid/sgid
> > > > > privileges.
> > > > > 
> > > > 
> > > > 
> > > > 
> > > > do you also check the signature of glibc and every other shared library
> > > > that the app uses (or dlopens)? if not.. the entire exercise is rather
> > > > pointless...
> > > 
> > > We do check that, that is patch [3/4].
> > > 
> > > Of course we can only check mmap-ed files, if there is no file like with JIT
> > > compilers we are out of luck.
> > 
> > or if the process uses read() not mmap().
> 
> If a process uses read() it needs some executable and writable memory. We do
> check for this in mprotect(). There is a problem with the i386-architecture,
> because it allows execution of any readable page (except with newer
> processors). But beyond that ugliness of i386, it should not be possible to
> execute anything without us noticing it (hopefully).

welcome to mprotect() where the app can just change the permissions

-- 
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-21 18:49         ` Arjan van de Ven
@ 2007-06-21 21:40           ` Johannes Schlumberger
  0 siblings, 0 replies; 16+ messages in thread
From: Johannes Schlumberger @ 2007-06-21 21:40 UTC (permalink / raw)
  To: Arjan van de Ven; +Cc: Alexander Wuerstlein, linux-kernel, arw

Hi,

> > If a process uses read() it needs some executable and writable memory. We do
> > check for this in mprotect(). There is a problem with the i386-architecture,
> > because it allows execution of any readable page (except with newer
> > processors). But beyond that ugliness of i386, it should not be possible to
> > execute anything without us noticing it (hopefully).
> 
> welcome to mprotect() where the app can just change the permissions

We have mprotect covered. If a process tries to mprotect() some pages
executable, he had writable before, it is no longer trusted in our current
implementation.

We are beginning to feel like poeple do not look at our patches, because we
screwed up the msg-id, so our Patches are not visible as one clean thread. Sorry
for that.

regards,
	Johannes 

-- 
Johannes Schlumberger                      Department of Computer Science IV
Martensstrasse 1  D-91058 Erlangen Germany  University of Erlangen-Nuremberg
             http://wwwcip.informatik.uni-erlangen.de/~spjsschl

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-21 17:46       ` Alexander Wuerstlein
  2007-06-21 18:49         ` Arjan van de Ven
@ 2007-06-23 18:01         ` Jan Engelhardt
  2007-06-25 10:54           ` Johannes Schlumberger
  1 sibling, 1 reply; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-23 18:01 UTC (permalink / raw)
  To: Alexander Wuerstlein; +Cc: Arjan van de Ven, linux-kernel, arw


On Jun 21 2007 19:46, Alexander Wuerstlein wrote:
>
>If a process uses read() it needs some executable and writable memory. We do
>check for this in mprotect(). There is a problem with the i386-architecture,
>because it allows execution of any readable page (except with newer
>processors). But beyond that ugliness of i386, it should not be possible to
>execute anything without us noticing it (hopefully).

r and x together is not a problem IMHO.


	Jan
-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-23 18:01         ` Jan Engelhardt
@ 2007-06-25 10:54           ` Johannes Schlumberger
  0 siblings, 0 replies; 16+ messages in thread
From: Johannes Schlumberger @ 2007-06-25 10:54 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Alexander Wuerstlein, Arjan van de Ven, linux-kernel, arw


Hi,

> >If a process uses read() it needs some executable and writable memory. We do
> >check for this in mprotect(). There is a problem with the i386-architecture,
> >because it allows execution of any readable page (except with newer
> >processors). But beyond that ugliness of i386, it should not be possible to
> >execute anything without us noticing it (hopefully).
>
> r and x together is not a problem IMHO.

It is, if you would want to have rw but can only get rwx.
regards,
	Johannes

-- 
Johannes Schlumberger                      Department of Computer Science IV
Martensstrasse 1  D-91058 Erlangen Germany  University of Erlangen-Nuremberg
             http://wwwcip.informatik.uni-erlangen.de/~spjsschl

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-26  0:27         ` Alexander Wuerstlein
@ 2007-06-26  2:13           ` Satyam Sharma
  0 siblings, 0 replies; 16+ messages in thread
From: Satyam Sharma @ 2007-06-26  2:13 UTC (permalink / raw)
  To: Alexander Wuerstlein
  Cc: Alexander Wuerstlein, linux-kernel, Johannes Schlumberger, linux-crypto

On 6/26/07, Alexander Wuerstlein
<snalwuer@cip.informatik.uni-erlangen.de> wrote:
> [...]
> Nope. I unluckily wrote 'userspace' where I should have said something else:
> Chain-of-trust is handled in what I would label 'Adminspace' (Where we do the
> signing as in points 1 and 2). There is a very small number of signatures (in
> our example one) known to the kernel and only those are trusted, and those are
> applied to the binaries by the administrator in your point 2. The kernel does
> and should never rely on userspace to tell it which signatures are trustworthy.
> Only the administrator may do so by means of the signatures directly compiled
> into the kernel.
>
> So in short: Chain-of-trust is handled by the administrator in his secure
> central location.

Ok, so the "trust chain" you're talking about is simply the decision of the
admin to compile-in the (verified and trusted) public keys of known trusted
entities into the kernel at build time. That is not really scalable, but I guess
you might just as well impose such a restriction for sake of simplicity.

[ I initially thought a scenario where a given binary is signed by an
entity whose
corresponding public key is _not_ present in the kernel, but who does possess
a signature -- over its name, id and public key -- by another entity whose
corresponding public key _is_ built into the kernel). Then at the time of
verification there's really no other alternative to *build* the entire
chain at the
_point of verification_ (in-kernel) itself ... but this obviously
introduces huge and
ugly complexities that you'd have a hard time bringing into the kernel :-) That
"signature over name, id and public key" could be a _certificate_ (if you care
about following standards), and building their chains in-kernel ... well. But if
you really want to differentiate between kernel and userspace from security
perspective, and want to give such functionality, I don't see any easy
way out. ]

> >> So far for the initial idea. Perhaps it would be useful to have more than
> >> one
> >> key or some more complex scheme for obtaining the keys and checking their
> >> validity.  But as all of this would need to be part of the kernel we
> >> decided to
> >> rather keep it as simple as possible, anything complex is better and more
> >> flexibly done in userspace.
> >
> > Well, if you're trusting (privileged) userspace already, I'm suddenly not so
> > sure as to what new is this patchset bringing to the table in the first place
> > ...
>
> We do not trust any userspace application, see above.
>
> > could you also describe the attack vectors / threats that you had in mind
> > that get blocked with the proposed scheme?
>
> We focus on attacks where an attacker may alter some executable file, for
> example by altering a mounted nfs-share, manipulating disk-content by simply
> pulling a disk, mounting it and writing to it, etc.
>
> This relies on the kernel beeing trustworthy of course, so one would need to
> take special measures to protect the kernel-image from beeing similarly
> altered. One (somewhat not-so-secure method) would be supplying kernel images
> by PXE and forbidding local booting, another measure would be using a TPM
> and an appropriate bootloader to check the kernel for unwanted modifications.

Kernel-userspace differentiation from security perspective is always tricky
(so this is why I pointed you to the discussions whenever such stuff, such
as asymmetric crypto and modsign etc are proposed to be merged). It's
definitely not impossible to compromise a _running_ kernel from privileged
userspace, if it really wanted to do so ...

Satyam

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-25 23:53       ` Satyam Sharma
@ 2007-06-26  0:27         ` Alexander Wuerstlein
  2007-06-26  2:13           ` Satyam Sharma
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Wuerstlein @ 2007-06-26  0:27 UTC (permalink / raw)
  To: Satyam Sharma
  Cc: Alexander Wuerstlein, linux-kernel, Johannes Schlumberger, linux-crypto

[-- Attachment #1: Type: text/plain, Size: 4698 bytes --]

On 070626 01:56, Satyam Sharma <satyam.sharma@gmail.com> wrote:
> On 6/25/07, Alexander Wuerstlein
> <snalwuer@cip.informatik.uni-erlangen.de> wrote:
>> On 070622 21:40, Satyam Sharma <satyam.sharma@gmail.com> wrote:
>> > [...]
>> We decided against
>> altering the file itself for that and some other reasons.
>> The limitation to suid/sgid was only due to a limited amount of time we 
>> had for
>> implementing our patch. For the future we are planning further uses like
>> setting capabilities only for signed binaries.
>
> Ok, effectively what you have there is a signature on an entire file stored
> in one of its extended attributes, so I suspect you could think of few other
> applications for something like this too.

Yes, for example one could sign Java's classfiles and employ a special trusted
Java VM which checks the signatures before execution. Also, this is a more
general case of signing kernel modules (as you mentioned below). There are
really numerous applications one could imagine, we just don't really know which
ones are practical. We definitely appreciate further ideas on this.

Also the signature-in-ELF can be used complementary to our approach: for
example NFS is currently unable to handle real extended attributes (nfs does
only posix acls). So for binaries delivered over NFS our approach wouldn't
work.

> Ok, so:
>
> 1. Admin is trusted. [ This need not mean the same as: "superuser
> _account_ is trusted", but let's stay in the real world in for now. ]
> 2. Signing happens at some central, assumed-to-be-secure location (and say
> the private key never leaves that central secure location). And let's say the
> admin *repackages* the packages, this time such that the signed files get the
> signature-carrying-extended-attributes with them, so the installation
> automatically copies them correctly. => nothing wrong with this assumption.
> 3. Kernel verifies signatures at runtime. => kernel is trusted.
> 4. Public key needs to be *compiled into* the kernel ... so this is not 
> getting into mainline, but fair enough as something site administrators would
> patch in and build.

Correct up to here.

> 5. Chain-of-trust handled in userspace. => userspace is trusted.

Nope. I unluckily wrote 'userspace' where I should have said something else:
Chain-of-trust is handled in what I would label 'Adminspace' (Where we do the
signing as in points 1 and 2). There is a very small number of signatures (in
our example one) known to the kernel and only those are trusted, and those are
applied to the binaries by the administrator in your point 2. The kernel does
and should never rely on userspace to tell it which signatures are trustworthy.
Only the administrator may do so by means of the signatures directly compiled
into the kernel.

So in short: Chain-of-trust is handled by the administrator in his secure
central location.

>> So far for the initial idea. Perhaps it would be useful to have more than 
>> one
>> key or some more complex scheme for obtaining the keys and checking their
>> validity.  But as all of this would need to be part of the kernel we 
>> decided to
>> rather keep it as simple as possible, anything complex is better and more
>> flexibly done in userspace.
>
> Well, if you're trusting (privileged) userspace already, I'm suddenly not so
> sure as to what new is this patchset bringing to the table in the first place
> ...

We do not trust any userspace application, see above.

> could you also describe the attack vectors / threats that you had in mind
> that get blocked with the proposed scheme?

We focus on attacks where an attacker may alter some executable file, for
example by altering a mounted nfs-share, manipulating disk-content by simply
pulling a disk, mounting it and writing to it, etc.

This relies on the kernel beeing trustworthy of course, so one would need to
take special measures to protect the kernel-image from beeing similarly
altered. One (somewhat not-so-secure method) would be supplying kernel images
by PXE and forbidding local booting, another measure would be using a TPM
and an appropriate bootloader to check the kernel for unwanted modifications.

> Have a look at modsign (signed kernel modules) project too (just the key
> management part, specifically the asymmetric crypto and DSA implementation
> that they've already ported to the kernel). You could also go through the 
> lkml archives for whenever that was proposed for inclusion in mainline ...

We already thought about that. Using some existing code is definitely preferable
to inventing DSA again :)



Ciao,

Alexander Wuerstlein.

[-- Attachment #2: Type: application/pgp-signature, Size: 185 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-24 22:58     ` Alexander Wuerstlein
@ 2007-06-25 23:53       ` Satyam Sharma
  2007-06-26  0:27         ` Alexander Wuerstlein
  0 siblings, 1 reply; 16+ messages in thread
From: Satyam Sharma @ 2007-06-25 23:53 UTC (permalink / raw)
  To: Alexander Wuerstlein
  Cc: Alexander Wuerstlein, linux-kernel, Johannes Schlumberger, linux-crypto

On 6/25/07, Alexander Wuerstlein
<snalwuer@cip.informatik.uni-erlangen.de> wrote:
> On 070622 21:40, Satyam Sharma <satyam.sharma@gmail.com> wrote:
> > [...]
> > But first: Have you checked the digsig project? It's been doing
> > (for some time) what your current patchset proposes -- and
> > it uses public key cryptosystems for the key management,
> > which is decidedly better than using secret-keyed hashes
> > (HMAC, XCBC). Also, digsig aims to protect executable
> > binaries in general, and not just suid / sgid ones.
>
> We have not heard about digsig before, thanks for pointing it out. After a
> short look over the source (correct me if I'm wrong): The most important
> difference between our project and digsig is that digsig relies on storing
> signatures inside the ELF file structure. Therefore a handmade binary-loader or
> just COFF binaries could be used to circumvent digsig.

Yes, that's correct.

> We decided against
> altering the file itself for that and some other reasons.
> The limitation to suid/sgid was only due to a limited amount of time we had for
> implementing our patch. For the future we are planning further uses like
> setting capabilities only for signed binaries.

Ok, effectively what you have there is a signature on an entire file stored in
one of its extended attributes, so I suspect you could think of few other
applications for something like this too.

> > Second: Can we have some discussion on the security model /
> > threat model / trust model / cryptographic key management
> > scheme of your signing mechanism? [I had read through the
> > [0/4] mail you had sent yesterday, but found no relevant
> > discussion on these aspects there.]
> [...]
> An admin would verify the to-be-installed binaries (e.g. by reading the source,
> checking the distribution's package signatures), sign them in a central
> location.  He then distributes those signatures along with the installation
> packages onto his computers. There should only be one key in use at a site the
> public part of which is compiled into the kernel. Any kind of chain-of-trust
> should be handled in userspace by signing or not signing with the site-wide
> key depending on the earlier signatures in the chain.

Ok, so:

1. Admin is trusted. [ This need not mean the same as: "superuser
_account_ is trusted", but let's stay in the real world in for now. ]
2. Signing happens at some central, assumed-to-be-secure location (and say
the private key never leaves that central secure location). And let's say the
admin *repackages* the packages, this time such that the signed files get the
signature-carrying-extended-attributes with them, so the installation
automatically copies them correctly. => nothing wrong with this assumption.
3. Kernel verifies signatures at runtime. => kernel is trusted.
4. Public key needs to be *compiled into* the kernel ... so this is not getting
into mainline, but fair enough as something site administrators would patch in
and build.
5. Chain-of-trust handled in userspace. => userspace is trusted.

Let me know if I got the trust model / key management wrong.

> So far for the initial idea. Perhaps it would be useful to have more than one
> key or some more complex scheme for obtaining the keys and checking their
> validity.  But as all of this would need to be part of the kernel we decided to
> rather keep it as simple as possible, anything complex is better and more
> flexibly done in userspace.

Well, if you're trusting (privileged) userspace already, I'm suddenly
not so sure
as to what new is this patchset bringing to the table in the first
place ... could
you also describe the attack vectors / threats that you had in mind that get
blocked with the proposed scheme?

> > From the patchset, it appears you use a *common* secret key
> > for _all_ signed binaries, and it is set at kernel build-time itself:
> > [...]
> > Anyway, this is *totally* insecure and broken. Do you realize anybody
> > who lays hands on the kernel image can now _trivially_ extract the
> > should-have-been-a-secret key from it and use it to sign his own
> > binaries?
>
> We do realize that this is really really ugly, broken and nasty and nobody
> would or should ever want to use it for anything but playing around as it is
> atm. ;)
>
> We only used HMAC because it was already available inside the kernel, for
> implementing real asymetric cryptography there was simply no time. Of course
> our next objective is to implement that.

Have a look at modsign (signed kernel modules) project too (just the key
management part, specifically the asymmetric crypto and DSA implementation
that they've already ported to the kernel). You could also go through the lkml
archives for whenever that was proposed for inclusion in mainline ...

Satyam

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-22 19:36   ` Satyam Sharma
@ 2007-06-24 22:58     ` Alexander Wuerstlein
  2007-06-25 23:53       ` Satyam Sharma
  0 siblings, 1 reply; 16+ messages in thread
From: Alexander Wuerstlein @ 2007-06-24 22:58 UTC (permalink / raw)
  To: Satyam Sharma
  Cc: Alexander Wuerstlein, linux-kernel, Johannes Schlumberger, linux-crypto

[-- Attachment #1: Type: text/plain, Size: 3266 bytes --]

On 070622 21:40, Satyam Sharma <satyam.sharma@gmail.com> wrote:
> Hi Alexander, Johannes,
>
> But first: Have you checked the digsig project? It's been doing
> (for some time) what your current patchset proposes -- and
> it uses public key cryptosystems for the key management,
> which is decidedly better than using secret-keyed hashes
> (HMAC, XCBC). Also, digsig aims to protect executable
> binaries in general, and not just suid / sgid ones.

We have not heard about digsig before, thanks for pointing it out. After a
short look over the source (correct me if I'm wrong): The most important
difference between our project and digsig is that digsig relies on storing
signatures inside the ELF file structure. Therefore a handmade binary-loader or
just COFF binaries could be used to circumvent digsig. We decided against
altering the file itself for that and some other reasons.

The limitation to suid/sgid was only due to a limited amount of time we had for
implementing our patch. For the future we are planning further uses like
setting capabilities only for signed binaries.

> Second: Can we have some discussion on the security model /
> threat model / trust model / cryptographic key management
> scheme of your signing mechanism? [I had read through the
> [0/4] mail you had sent yesterday, but found no relevant
> discussion on these aspects there.]

Our scenario was as follows: Usually system administrators rely on cronjobs
checking their binaries for unwanted suid-bits. Because of the obvious problems
with this (time between cronjobs, performance) we wrote our patch to replace it.

An admin would verify the to-be-installed binaries (e.g. by reading the source,
checking the distribution's package signatures), sign them in a central
location.  He then distributes those signatures along with the installation
packages onto his computers. There should only be one key in use at a site the
public part of which is compiled into the kernel. Any kind of chain-of-trust
should be handled in userspace by signing or not signing with the site-wide
key depending on the earlier signatures in the chain.

So far for the initial idea. Perhaps it would be useful to have more than one
key or some more complex scheme for obtaining the keys and checking their
validity.  But as all of this would need to be part of the kernel we decided to
rather keep it as simple as possible, anything complex is better and more
flexibly done in userspace.

> From the patchset, it appears you use a *common* secret key
> for _all_ signed binaries, and it is set at kernel build-time itself:
> [...]
> Anyway, this is *totally* insecure and broken. Do you realize anybody
> who lays hands on the kernel image can now _trivially_ extract the
> should-have-been-a-secret key from it and use it to sign his own
> binaries?

We do realize that this is really really ugly, broken and nasty and nobody
would or should ever want to use it for anything but playing around as it is
atm. ;)

We only used HMAC because it was already available inside the kernel, for
implementing real asymetric cryptography there was simply no time. Of course
our next objective is to implement that. 


Ciao,

Alexander Wuerstlein.

[-- Attachment #2: Type: application/pgp-signature, Size: 185 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-22 18:25 ` [PATCH] Check files' signatures before doing suid/sgid [2/4] Alexander Wuerstlein
  2007-06-22 19:36   ` Satyam Sharma
@ 2007-06-23 17:54   ` Jan Engelhardt
  1 sibling, 0 replies; 16+ messages in thread
From: Jan Engelhardt @ 2007-06-23 17:54 UTC (permalink / raw)
  To: Alexander Wuerstlein; +Cc: linux-kernel, Johannes Schlumberger


On Jun 22 2007 20:25, Alexander Wuerstlein wrote:
>+#ifdef CONFIG_SNS_SIGNED
>+#include <linux/sns.h>
>+#endif
> 
> #include <asm/uaccess.h>
> #include <asm/mmu_context.h>
>@@ -928,13 +931,21 @@ int prepare_binprm(struct linux_binprm *bprm)
> 	mode = inode->i_mode;
> 	if (bprm->file->f_op == NULL)
> 		return -EACCES;
>+#ifdef CONFIG_SNS_SIGNED
>+	if (mode & S_ISUID)
>+		current->sns_valid_sig = sns_signature_valid(bprm->file);
>+#endif
> 
> 	bprm->e_uid = current->euid;
> 	bprm->e_gid = current->egid;
> 
> 	if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
> 		/* Set-uid? */
>-		if (mode & S_ISUID) {
>+#ifdef CONFIG_SNS_SIGNED_SETUID
>+               if (mode & S_ISUID && current->sns_valid_sig) {
>+#else
>+               if (mode & S_ISUID) {
>+#endif /*SNS_SIGNED_SETUID*/
> 			current->personality &= ~PER_CLEAR_ON_SETID;
> 			bprm->e_uid = inode->i_uid;
> 		}
>@@ -945,7 +956,11 @@ int prepare_binprm(struct linux_binprm *bprm)
> 		 * is a candidate for mandatory locking, not a setgid
> 		 * executable.
> 		 */
>-		if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
>+#ifdef CONFIG_SNS_SIGNED_SETGID
>+               if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && current->sns_valid_sig) {
>+#else
>+               if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
>+#endif /*SNS_SIGNED_SETGID*/
> 			current->personality &= ~PER_CLEAR_ON_SETID;
> 			bprm->e_gid = inode->i_gid;
> 		}

...
That's a lot of unwanted ifdefs!



	Jan
-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-22 18:25 ` [PATCH] Check files' signatures before doing suid/sgid [2/4] Alexander Wuerstlein
@ 2007-06-22 19:36   ` Satyam Sharma
  2007-06-24 22:58     ` Alexander Wuerstlein
  2007-06-23 17:54   ` Jan Engelhardt
  1 sibling, 1 reply; 16+ messages in thread
From: Satyam Sharma @ 2007-06-22 19:36 UTC (permalink / raw)
  To: Alexander Wuerstlein; +Cc: linux-kernel, Johannes Schlumberger, linux-crypto

Hi Alexander, Johannes,

[ Added linux-crypto to Cc: ]

Wow, this is _one_ *intrusive* patchset indeed :-)

But first: Have you checked the digsig project? It's been doing
(for some time) what your current patchset proposes -- and
it uses public key cryptosystems for the key management,
which is decidedly better than using secret-keyed hashes
(HMAC, XCBC). Also, digsig aims to protect executable
binaries in general, and not just suid / sgid ones.

Second: Can we have some discussion on the security model /
threat model / trust model / cryptographic key management
scheme of your signing mechanism? [I had read through the
[0/4] mail you had sent yesterday, but found no relevant
discussion on these aspects there.]

>From the patchset, it appears you use a *common* secret key
for _all_ signed binaries, and it is set at kernel build-time itself:

On 6/22/07, Alexander Wuerstlein <arw@arw.name> wrote:
> sns_secret_key.dat contains the 'secret key' which is used for HMAC.

Where:

> --- /dev/null
> +++ b/security/sns_secret_key.dat
> +#define SNS_SECRET_KEY_SIZE 8
> +static char sns_secret_key[SNS_SECRET_KEY_SIZE] =
> +       {
> +               'd', 'e', 'a', 'd', 'b', 'e', 'e', 'f'
> +       };

[ Ok, I won't nitpick as to why does this file look like a header,
is #include-d in the C source as a header, but still has a .dat
extension :-) ]

Anyway, this is *totally* insecure and broken. Do you realize anybody
who lays hands on the kernel image can now _trivially_ extract the
should-have-been-a-secret key from it and use it to sign his own
binaries?

Satyam

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH] Check files' signatures before doing suid/sgid [2/4]
  2007-06-21 15:55 [PATCH] signed binaries support [0/4] Johannes Schlumberger
@ 2007-06-22 18:25 ` Alexander Wuerstlein
  2007-06-22 19:36   ` Satyam Sharma
  2007-06-23 17:54   ` Jan Engelhardt
  0 siblings, 2 replies; 16+ messages in thread
From: Alexander Wuerstlein @ 2007-06-22 18:25 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alexander Wuerstlein, Johannes Schlumberger

Modified task_struct to hold a 'signed flag' which is set on exec(), inherited
on fork() and checked during exec before giving the new process suid/sgid
privileges.

sns.c contains our helper functions to verify the signatures.
sns_secret_key.dat contains the 'secret key' which is used for HMAC.

Signed-off-by: Johannes Schlumberger <spjsschl@cip.informatik.uni-erlangen.de>
---
 fs/exec.c                   |   19 +++++++-
 include/linux/Kbuild        |    2 +
 include/linux/sched.h       |    3 +
 include/linux/sns.h         |    3 +
 kernel/fork.c               |    6 +++
 security/Kconfig            |   28 ++++++++++++
 security/Makefile           |    1 +
 security/sns.c              |  104 +++++++++++++++++++++++++++++++++++++++++++
 security/sns_secret_key.dat |    5 ++
 9 files changed, 169 insertions(+), 2 deletions(-)
 create mode 100644 include/linux/sns.h
 create mode 100644 security/sns.c
 create mode 100644 security/sns_secret_key.dat

diff --git a/fs/exec.c b/fs/exec.c
index f20561f..5dfa406 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -51,6 +51,9 @@
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
 #include <linux/signalfd.h>
+#ifdef CONFIG_SNS_SIGNED
+#include <linux/sns.h>
+#endif
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -928,13 +931,21 @@ int prepare_binprm(struct linux_binprm *bprm)
 	mode = inode->i_mode;
 	if (bprm->file->f_op == NULL)
 		return -EACCES;
+#ifdef CONFIG_SNS_SIGNED
+	if (mode & S_ISUID)
+		current->sns_valid_sig = sns_signature_valid(bprm->file);
+#endif
 
 	bprm->e_uid = current->euid;
 	bprm->e_gid = current->egid;
 
 	if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
 		/* Set-uid? */
-		if (mode & S_ISUID) {
+#ifdef CONFIG_SNS_SIGNED_SETUID
+               if (mode & S_ISUID && current->sns_valid_sig) {
+#else
+               if (mode & S_ISUID) {
+#endif /*SNS_SIGNED_SETUID*/
 			current->personality &= ~PER_CLEAR_ON_SETID;
 			bprm->e_uid = inode->i_uid;
 		}
@@ -945,7 +956,11 @@ int prepare_binprm(struct linux_binprm *bprm)
 		 * is a candidate for mandatory locking, not a setgid
 		 * executable.
 		 */
-		if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+#ifdef CONFIG_SNS_SIGNED_SETGID
+               if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && current->sns_valid_sig) {
+#else
+               if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+#endif /*SNS_SIGNED_SETGID*/
 			current->personality &= ~PER_CLEAR_ON_SETID;
 			bprm->e_gid = inode->i_gid;
 		}
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index f317c27..16df5f0 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -159,6 +159,7 @@ header-y += videotext.h
 header-y += vt.h
 header-y += wireless.h
 header-y += x25.h
+header-y += sns.h
 
 unifdef-y += acct.h
 unifdef-y += adb.h
@@ -347,5 +348,6 @@ unifdef-y += watchdog.h
 unifdef-y += wireless.h
 unifdef-y += xattr.h
 unifdef-y += xfrm.h
+unifdef-y += sns.h
 
 objhdr-y += version.h
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 693f0e6..36c58d6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1076,6 +1076,9 @@ struct task_struct {
 #ifdef CONFIG_FAULT_INJECTION
 	int make_it_fail;
 #endif
+#ifdef CONFIG_SNS_SIGNED
+	int sns_valid_sig;
+#endif
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
diff --git a/include/linux/sns.h b/include/linux/sns.h
new file mode 100644
index 0000000..ad15e4b
--- /dev/null
+++ b/include/linux/sns.h
@@ -0,0 +1,3 @@
+#ifdef CONFIG_SNS_SIGNED
+int sns_signature_valid(struct file *);
+#endif
diff --git a/kernel/fork.c b/kernel/fork.c
index 73ad5cd..c12cf61 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -156,6 +156,9 @@ void __init fork_init(unsigned long mempages)
 	init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
 	init_task.signal->rlim[RLIMIT_SIGPENDING] =
 		init_task.signal->rlim[RLIMIT_NPROC];
+#ifdef CONFIG_SNS_SIGNED
+	init_task.sns_valid_sig = 0;
+#endif
 }
 
 static struct task_struct *dup_task_struct(struct task_struct *orig)
@@ -182,6 +185,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 #ifdef CONFIG_CC_STACKPROTECTOR
 	tsk->stack_canary = get_random_int();
 #endif
+#ifdef CONFIG_SNS_SIGNED
+	tsk->sns_valid_sig = orig->sns_valid_sig;
+#endif
 
 	/* One for us, one for whoever does the "release_task()" (usually parent) */
 	atomic_set(&tsk->usage,2);
diff --git a/security/Kconfig b/security/Kconfig
index 460e5c9..bfaace7 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -4,6 +4,34 @@
 
 menu "Security options"
 
+config SNS_SIGNED
+	bool "Enable sns-signed binaries (EXPERIMENTAL)"
+	depends on (EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR || REISERFS_FS_XATTR || JFFS2_FS_XATTR || CIFS_XATTR) && (CRYPTO_SHA1 || CRYPTO_HMAC || CRYPTO_MD5) && MMU && EXPERIMENTAL
+	help
+	  This option turns on sns-signatures of binaries. Requires extended
+	  attributes and cryptographic hashes/HMAC support. HMAC is preferred.
+
+	  This will leave your system unusable without proper preparation of
+	  your sbit-files.
+
+	  If you don't know exactly what you are doing, answer N.
+
+config SNS_SIGNED_SETUID
+	bool "Enables sns-signed binaries mandatory for suid-bits"
+	depends on SNS_SIGNED
+	help
+	  Mandates signed binaries for suidbits.
+
+	  If you don't know exactly what you are doing, answer N.
+
+config SNS_SIGNED_SETGID
+	bool "Enables sns-signed binaries mandatory for sgid-bits"
+	depends on SNS_SIGNED
+	help
+	  Mandates signed binaries for sgidbits.
+
+	  If you don't know exactly what you are doing, answer N.
+
 config KEYS
 	bool "Enable access key retention support"
 	help
diff --git a/security/Makefile b/security/Makefile
index ef87df2..677b978 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_SECURITY)			+= security.o dummy.o inode.o
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+obj-$(CONFIG_SNS_SIGNED)		+= sns.o
diff --git a/security/sns.c b/security/sns.c
new file mode 100644
index 0000000..4403e5a
--- /dev/null
+++ b/security/sns.c
@@ -0,0 +1,104 @@
+#include <linux/crypto.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/scatterlist.h>
+#include <linux/xattr.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/sns.h>
+
+#include "sns_secret_key.dat"
+
+#define SNS_MAX_DIGEST_SIZE	64
+
+struct sns_attr {
+	char algname[CRYPTO_MAX_ALG_NAME+1];
+	char hash_value[SNS_MAX_DIGEST_SIZE];
+};
+
+
+static int sns_sig_reader(read_descriptor_t *desc, struct page *page, unsigned long offset, unsigned long nr)
+{
+	struct scatterlist s;
+	struct hash_desc *hash_desc = (struct hash_desc *) desc->arg.data;
+	unsigned int read;
+
+	s.page = page;
+	s.offset = offset;
+	s.length = nr;
+	read = nr - offset;
+	crypto_hash_update(hash_desc, &s, read);
+	desc->written += read;
+	desc->count -= read;
+	return read;
+}
+
+/*
+ * check file signature for setuid
+ */
+
+int sns_signature_valid(struct file *file)
+{
+	unsigned long i;
+	struct inode *inode = file->f_mapping->host;
+	struct crypto_hash *tfm;
+	struct hash_desc hash_desc;
+	struct sns_attr attrdata;
+	char hash_result[SNS_MAX_DIGEST_SIZE];
+	struct xattr_handler *handler;
+	const char *namespaces[2] = { "trusted.", NULL };
+	int ret = 0;
+	loff_t pos = 0;
+	read_descriptor_t read_desc;
+
+	handler = xattr_resolve_name_sns(inode->i_sb->s_xattr, namespaces);
+	if (unlikely(!handler)) {
+		printk(KERN_DEBUG "sns_signature_valid: xattr_resolve_name failed\n");
+		return 0;
+	}
+	memset(&attrdata, 0, sizeof(struct sns_attr));
+	i = handler->get(inode, "sns", &attrdata, sizeof(struct sns_attr));
+	if (i != sizeof(struct sns_attr)) {
+		printk(KERN_DEBUG "sns_signature_valid: invalid xattr found\n");
+		return 0;
+	}
+	attrdata.algname[CRYPTO_MAX_ALG_NAME] = '\0';
+	read_desc.count = i_size_read(inode);
+	if (unlikely(!read_desc.count)) {
+		printk(KERN_DEBUG "sns_signature_valid: inode of file has invalid size\n");
+		return 0;
+	}
+	tfm = crypto_alloc_hash(attrdata.algname, 0, CRYPTO_ALG_ASYNC);
+	if (unlikely(IS_ERR(tfm))) {
+		printk("sns_signature_valid: %s unavailable\n", attrdata.algname);
+		return 0;
+		/*FIXME: failure mode should be defined at build-time */
+	}
+	memset(hash_result, 0, SNS_MAX_DIGEST_SIZE); /*Needed?*/
+	hash_desc.tfm = tfm;
+	hash_desc.flags = 0;
+	read_desc.arg.data = &hash_desc;
+	read_desc.written = 0;
+	if (crypto_hash_setkey(tfm, sns_secret_key, SNS_SECRET_KEY_SIZE)) {
+		printk("sns_signature_valid: hash function did not accept setkey\n");
+		return 0;
+	}
+	crypto_hash_init(&hash_desc);
+	do_generic_file_read(file, &pos, &read_desc, sns_sig_reader);
+	crypto_hash_final(&hash_desc, hash_result);
+	BUG_ON(read_desc.written != i_size_read(inode));
+#ifdef SNS_SIGNED_DEBUG
+	printk("sns_signature_valid: attrdata.algname = %s\n", attrdata.algname);
+	printk("sns_signature_valid: attrib: ");
+	for (i = 0; i < SNS_MAX_DIGEST_SIZE; i++)
+		printk("%02x ", (unsigned char) attrdata.hash_value[i]);
+	printk("\n");
+	printk("sns_signature_valid: result: ");
+	for (i = 0; i < SNS_MAX_DIGEST_SIZE; i++)
+		printk("%02x ", (unsigned char) hash_result[i]);
+	printk("\n");
+#endif
+	ret = !memcmp(attrdata.hash_value, hash_result, SNS_MAX_DIGEST_SIZE);
+	crypto_free_hash(tfm);
+	return ret;
+}
diff --git a/security/sns_secret_key.dat b/security/sns_secret_key.dat
new file mode 100644
index 0000000..aec09da
--- /dev/null
+++ b/security/sns_secret_key.dat
@@ -0,0 +1,5 @@
+#define SNS_SECRET_KEY_SIZE 8
+static char sns_secret_key[SNS_SECRET_KEY_SIZE] =
+	{
+		'd', 'e', 'a', 'd', 'b', 'e', 'e', 'f'
+	};
-- 
1.5.2.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2007-06-26  2:13 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-21 16:02 [PATCH] Check files' signatures before doing suid/sgid [2/4] Alexander Wuerstlein
2007-06-21 17:17 ` Arjan van de Ven
2007-06-21 17:25   ` Alexander Wuerstlein
2007-06-21 17:29     ` Arjan van de Ven
2007-06-21 17:46       ` Alexander Wuerstlein
2007-06-21 18:49         ` Arjan van de Ven
2007-06-21 21:40           ` Johannes Schlumberger
2007-06-23 18:01         ` Jan Engelhardt
2007-06-25 10:54           ` Johannes Schlumberger
  -- strict thread matches above, loose matches on Subject: below --
2007-06-21 15:55 [PATCH] signed binaries support [0/4] Johannes Schlumberger
2007-06-22 18:25 ` [PATCH] Check files' signatures before doing suid/sgid [2/4] Alexander Wuerstlein
2007-06-22 19:36   ` Satyam Sharma
2007-06-24 22:58     ` Alexander Wuerstlein
2007-06-25 23:53       ` Satyam Sharma
2007-06-26  0:27         ` Alexander Wuerstlein
2007-06-26  2:13           ` Satyam Sharma
2007-06-23 17:54   ` Jan Engelhardt

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).