|
|
Message-Id: <1458788042-26173-4-git-send-email-mic@digikod.net>
Date: Thu, 24 Mar 2016 03:53:57 +0100
From: Mickaël Salaün <mic@...ikod.net>
To: linux-security-module@...r.kernel.org
Cc: Mickaël Salaün <mic@...ikod.net>,
Andreas Gruenbacher <agruenba@...hat.com>,
Andy Lutomirski <luto@...capital.net>,
Andy Lutomirski <luto@...nel.org>,
Arnd Bergmann <arnd@...db.de>,
Casey Schaufler <casey@...aufler-ca.com>,
Daniel Borkmann <daniel@...earbox.net>,
David Drysdale <drysdale@...gle.com>,
Eric Paris <eparis@...hat.com>,
James Morris <james.l.morris@...cle.com>,
Jeff Dike <jdike@...toit.com>,
Julien Tinnes <jln@...gle.com>,
Kees Cook <keescook@...omium.org>,
Michael Kerrisk <mtk@...7.org>,
Paul Moore <pmoore@...hat.com>,
Richard Weinberger <richard@....at>,
"Serge E . Hallyn" <serge@...lyn.com>,
Stephen Smalley <sds@...ho.nsa.gov>,
Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>,
Will Drewry <wad@...omium.org>,
linux-api@...r.kernel.org,
kernel-hardening@...ts.openwall.com
Subject: [RFC v1 12/17] audit,seccomp: Extend audit with seccomp state
Extend the audit framework to known if we are in a seccomp filter
evaluation or not.
Signed-off-by: Mickaël Salaün <mic@...ikod.net>
Cc: Andy Lutomirski <luto@...nel.org>
Cc: Eric Paris <eparis@...hat.com>
Cc: Kees Cook <keescook@...omium.org>
Cc: Paul Moore <pmoore@...hat.com>
Cc: Will Drewry <wad@...omium.org>
---
include/linux/audit.h | 25 +++++++++++++++++++++++++
kernel/audit.h | 3 +++
kernel/auditsc.c | 36 ++++++++++++++++++++++++++++++++++--
kernel/seccomp.c | 21 ++++++++++++++++++---
4 files changed, 80 insertions(+), 5 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index b40ed5df5542..480df19473d9 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -230,6 +230,8 @@ extern void __audit_free(struct task_struct *task);
extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3);
extern void __audit_syscall_exit(int ret_success, long ret_value);
+extern void __audit_seccomp_entry(void);
+extern void __audit_seccomp_exit(int do_free);
extern struct filename *__audit_reusename(const __user char *uptr);
extern void __audit_getname(struct filename *name);
@@ -270,17 +272,40 @@ static inline void audit_syscall_exit(void *pt_regs)
__audit_syscall_exit(success, return_code);
}
}
+
+static inline void audit_seccomp_entry(void)
+{
+ if (unlikely(current->audit_context))
+ __audit_seccomp_entry();
+}
+
+static inline void audit_seccomp_exit(int do_free)
+{
+ if (unlikely(current->audit_context))
+ __audit_seccomp_exit(do_free);
+}
+
static inline struct filename *audit_reusename(const __user char *name)
{
if (unlikely(!audit_dummy_context()))
return __audit_reusename(name);
+#ifdef CONFIG_SECURITY_SECCOMP
+ if (current->audit_context)
+ return __audit_reusename(name);
+#endif /* CONFIG_SECURITY_SECCOMP */
return NULL;
}
+
static inline void audit_getname(struct filename *name)
{
if (unlikely(!audit_dummy_context()))
__audit_getname(name);
+#ifdef CONFIG_SECURITY_SECCOMP
+ else if (current->audit_context)
+ __audit_getname(name);
+#endif /* CONFIG_SECURITY_SECCOMP */
}
+
static inline void audit_inode(struct filename *name,
const struct dentry *dentry,
unsigned int parent) {
diff --git a/kernel/audit.h b/kernel/audit.h
index cbbe6bb6496e..c63ce77b44ae 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -108,6 +108,9 @@ struct audit_proctitle {
struct audit_context {
int dummy; /* must be the first element */
int in_syscall; /* 1 if task is in a syscall */
+#ifdef CONFIG_SECURITY_SECCOMP
+ int in_seccomp; /* 1 if task is in seccomp */
+#endif
enum audit_state state, current_state;
unsigned int serial; /* serial number for record */
int major; /* syscall number */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 195ffaee50b9..dd1d9f4b1c61 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1501,7 +1501,10 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
if (!context)
return;
- BUG_ON(context->in_syscall || context->name_count);
+ BUG_ON(context->in_syscall);
+#ifndef CONFIG_SECURITY_SECCOMP
+ BUG_ON(context->name_count);
+#endif /* CONFIG_SECURITY_SECCOMP */
if (!audit_enabled)
return;
@@ -1580,6 +1583,35 @@ void __audit_syscall_exit(int success, long return_code)
tsk->audit_context = context;
}
+void __audit_seccomp_entry(void)
+{
+ struct audit_context *context = current->audit_context;
+
+ if (!context)
+ return;
+ BUG_ON(context->in_seccomp || context->name_count);
+ if (!audit_enabled)
+ return;
+
+ context->in_seccomp = 1;
+}
+
+void __audit_seccomp_exit(int do_free)
+{
+ struct audit_context *context = current->audit_context;
+
+ if (!context)
+ return;
+ BUG_ON(!context->in_seccomp);
+ if (!audit_enabled)
+ return;
+
+ BUG_ON(!context->in_seccomp);
+ context->in_seccomp = 0;
+ if (do_free)
+ audit_free_names(context);
+}
+
static inline void handle_one(const struct inode *inode)
{
#ifdef CONFIG_AUDIT_TREE
@@ -1728,7 +1760,7 @@ void __audit_getname(struct filename *name)
struct audit_context *context = current->audit_context;
struct audit_names *n;
- if (!context->in_syscall)
+ if (!context->in_syscall && !context->in_seccomp)
return;
n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 60e11863857e..a8a6ba31ecc4 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -881,7 +881,7 @@ int __secure_computing(void)
static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd)
{
u32 filter_ret, action;
- int data;
+ int data, ret;
/*
* Make sure that any changes to mode from another thread have
@@ -889,6 +889,9 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd)
*/
rmb();
+ /* Enable caching */
+ audit_seccomp_entry();
+
filter_ret = seccomp_run_filters(sd);
data = filter_ret & SECCOMP_RET_DATA;
action = filter_ret & SECCOMP_RET_ACTION;
@@ -910,13 +913,15 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd)
goto skip;
case SECCOMP_RET_TRACE:
- return filter_ret; /* Save the rest for phase 2. */
+ ret = filter_ret; /* Save the rest for phase 2. */
+ goto audit_exit;
case SECCOMP_RET_ARGEVAL:
/* Handled in seccomp_run_filters() */
BUG();
case SECCOMP_RET_ALLOW:
- return SECCOMP_PHASE1_OK;
+ ret = SECCOMP_PHASE1_OK;
+ goto audit_exit;
case SECCOMP_RET_KILL:
default:
@@ -926,7 +931,12 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd)
unreachable();
+audit_exit:
+ audit_seccomp_exit(0);
+ return ret;
+
skip:
+ audit_seccomp_exit(1);
audit_seccomp(this_syscall, 0, action);
return SECCOMP_PHASE1_SKIP;
}
@@ -1139,6 +1149,11 @@ static long seccomp_add_checker_group(unsigned int flags, const char __user *gro
unsigned long group_size, kcheckers_size, full_group_size;
long result;
+ /* FIXME: Deny unsecure path evaluation (i.e. without audit_names) for
+ * the entire task life.
+ */
+ if (!current->audit_context)
+ return -EPERM;
if (!task_no_new_privs(current) &&
security_capable_noaudit(current_cred(),
current_user_ns(), CAP_SYS_ADMIN) != 0)
--
2.8.0.rc3
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.