From: Alexander Wuerstlein <arw@arw.name>
To: linux-kernel@vger.kernel.org
Cc: Alexander Wuerstlein <arw@arw.name>,
Johannes Schlumberger <spjsschl@stud.informatik.uni-erlangen.de>
Subject: [PATCH] Check files' signatures before doing suid/sgid [2/4]
Date: Fri, 22 Jun 2007 20:25:27 +0200 [thread overview]
Message-ID: <1182536729847-git-send-email-arw@arw.name> (raw)
In-Reply-To: <20070621155516.GA6838@faui01.informatik.uni-erlangen.de>
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
next prev parent reply other threads:[~2007-06-22 18:25 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-21 15:55 [PATCH] signed binaries support [0/4] Johannes Schlumberger
2007-06-21 16:17 ` Adrian Bunk
2007-06-21 16:29 ` Alexander Wuerstlein
2007-06-21 17:23 ` Adrian Bunk
2007-06-21 17:34 ` Alexander Wuerstlein
2007-06-21 18:05 ` Adrian Bunk
2007-06-21 18:21 ` Johannes Schlumberger
2007-06-22 18:25 ` [PATCH] export xattr_resolve_name_sns [1/4] Alexander Wuerstlein
2007-06-22 18:25 ` Alexander Wuerstlein [this message]
2007-06-22 19:36 ` [PATCH] Check files' signatures before doing suid/sgid [2/4] 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
2007-06-22 18:25 ` [PATCH] sns: check related executable memory of binaries [3/4] Alexander Wuerstlein
2007-06-22 18:25 ` [PATCH] sns: add syscall to check signed state of a process [4/4] Alexander Wuerstlein
-- strict thread matches above, loose matches on Subject: below --
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
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=1182536729847-git-send-email-arw@arw.name \
--to=arw@arw.name \
--cc=linux-kernel@vger.kernel.org \
--cc=spjsschl@stud.informatik.uni-erlangen.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.