From: Jan Kiszka <jan.kiszka@domain.hid>
To: adeos-main <adeos-main@gna.org>
Cc: Philippe Gerum <rpm@xenomai.org>
Subject: [Adeos-main] [PATCH 7/7] Detect illicit cross-domain calls (i386/x86_64)
Date: Thu, 26 Apr 2007 20:42:12 +0200 [thread overview]
Message-ID: <4630F284.6040103@domain.hid> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 1049 bytes --]
[This patch is a remake of
https://mail.gna.org/public/adeos-main/2006-09/msg00037.html]
Actually, this patch does more than the subject suggests. First it gets
rid of ipipe_preempt_guard by fixing the remaining invocation of
preempt_xxx over non-root domains. At least it appears so for i386 and
x86_64 based on simple tests.
But - here is its main contribution - this patch also comes with means
to detect remaining or to-be-introduced illicit calls. It introduces
ipipe_check_context(border_ipd) that checks (CONFIG_IPIPE_DEBUG_CONTEXT)
if the caller runs over the same or a lower-priority domain than
border_ipd. If not, the kernel will bark loudly.
There are already three major instrumentation points for Linux included:
- preempt_xxx()
- might_resched()
- raw_local_irq_save/disable()
That /should/ catch almost all evil invocations of Linux services from
non root-domains without hurting performance too much.
@everyone on other archs: please port and test for remaining
ipipe_preempt_guard wreckages!
Jan
[-- Attachment #1.2: debug-dom-violation-v3.patch --]
[-- Type: text/plain, Size: 6607 bytes --]
---
include/linux/ipipe_base.h | 6 ++++
include/linux/kernel.h | 8 ++++--
include/linux/preempt.h | 59 ++++++++++++++++++---------------------------
kernel/ipipe/Kconfig.debug | 9 ++++++
kernel/ipipe/core.c | 31 +++++++++++++++++++++++
5 files changed, 76 insertions(+), 37 deletions(-)
Index: linux-2.6.20/include/linux/ipipe_base.h
===================================================================
--- linux-2.6.20.orig/include/linux/ipipe_base.h
+++ linux-2.6.20/include/linux/ipipe_base.h
@@ -75,6 +75,12 @@ void __ipipe_unstall_root(void);
void __ipipe_restore_root(unsigned long x);
+#ifdef CONFIG_IPIPE_DEBUG_CONTEXT
+void ipipe_check_context(struct ipipe_domain *border_ipd);
+#else /* !CONFIG_IPIPE_DEBUG_CONTEXT */
+static inline void ipipe_check_context(struct ipipe_domain *border_ipd) { }
+#endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */
+
#endif /* CONFIG_IPIPE */
#endif /* !__LINUX_IPIPE_BASE_H */
Index: linux-2.6.20/include/linux/kernel.h
===================================================================
--- linux-2.6.20.orig/include/linux/kernel.h
+++ linux-2.6.20/include/linux/kernel.h
@@ -14,6 +14,7 @@
#include <linux/compiler.h>
#include <linux/bitops.h>
#include <linux/log2.h>
+#include <linux/ipipe_base.h>
#include <asm/byteorder.h>
#include <asm/bug.h>
@@ -72,9 +73,12 @@ struct user;
*/
#ifdef CONFIG_PREEMPT_VOLUNTARY
extern int cond_resched(void);
-# define might_resched() cond_resched()
+# define might_resched() do { \
+ ipipe_check_context(ipipe_root_domain); \
+ cond_resched(); \
+ } while (0)
#else
-# define might_resched() do { } while (0)
+# define might_resched() ipipe_check_context(ipipe_root_domain)
#endif
#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
Index: linux-2.6.20/include/linux/preempt.h
===================================================================
--- linux-2.6.20.orig/include/linux/preempt.h
+++ linux-2.6.20/include/linux/preempt.h
@@ -8,6 +8,7 @@
#include <linux/thread_info.h>
#include <linux/linkage.h>
+#include <linux/preempt.h>
#ifdef CONFIG_DEBUG_PREEMPT
extern void fastcall add_preempt_count(int val);
@@ -26,52 +27,40 @@
asmlinkage void preempt_schedule(void);
-#ifdef CONFIG_IPIPE
-#include <asm/ipipe.h>
-DECLARE_PER_CPU(struct ipipe_domain *, ipipe_percpu_domain);
-extern struct ipipe_domain ipipe_root;
-#define ipipe_preempt_guard() (per_cpu(ipipe_percpu_domain, ipipe_processor_id()) == &ipipe_root)
-#else /* !CONFIG_IPIPE */
-#define ipipe_preempt_guard() 1
-#endif /* CONFIG_IPIPE */
-
-#define preempt_disable() \
-do { \
- if (ipipe_preempt_guard()) { \
- inc_preempt_count(); \
- barrier(); \
- } \
+#define preempt_disable() \
+do { \
+ ipipe_check_context(ipipe_root_domain); \
+ inc_preempt_count(); \
+ barrier(); \
} while (0)
-#define preempt_enable_no_resched() \
-do { \
- if (ipipe_preempt_guard()) { \
- barrier(); \
- dec_preempt_count(); \
- } \
+#define preempt_enable_no_resched() \
+do { \
+ ipipe_check_context(ipipe_root_domain); \
+ barrier(); \
+ dec_preempt_count(); \
} while (0)
-#define preempt_check_resched() \
-do { \
- if (ipipe_preempt_guard()) { \
- if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
- preempt_schedule(); \
- } \
+#define preempt_check_resched() \
+do { \
+ ipipe_check_context(ipipe_root_domain); \
+ if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
+ preempt_schedule(); \
} while (0)
-#define preempt_enable() \
-do { \
- preempt_enable_no_resched(); \
+#define preempt_enable() \
+do { \
+ preempt_enable_no_resched(); \
barrier(); \
- preempt_check_resched(); \
+ preempt_check_resched(); \
} while (0)
#else
-#define preempt_disable() do { } while (0)
-#define preempt_enable_no_resched() do { } while (0)
-#define preempt_enable() do { } while (0)
-#define preempt_check_resched() do { } while (0)
+#define preempt_disable() ipipe_check_context(ipipe_root_domain)
+#define preempt_enable_no_resched() ipipe_check_context(ipipe_root_domain)
+#define preempt_enable() ipipe_check_context(ipipe_root_domain)
+#define preempt_check_resched() ipipe_check_context(ipipe_root_domain)
#endif
Index: linux-2.6.20/kernel/ipipe/Kconfig.debug
===================================================================
--- linux-2.6.20.orig/kernel/ipipe/Kconfig.debug
+++ linux-2.6.20/kernel/ipipe/Kconfig.debug
@@ -2,6 +2,15 @@ config IPIPE_DEBUG
bool "I-pipe debugging"
depends on IPIPE
+config IPIPE_DEBUG_CONTEXT
+ bool "Check for illicit cross-domain calls"
+ depends on IPIPE_DEBUG
+ ---help---
+ Enable this feature to arm checkpoints in the kernel that
+ verify the correct invocation context. On entry of critical
+ Linux services a warning is issued if the caller is not
+ running over the root domain.
+
config IPIPE_TRACE
bool "Latency tracing"
depends on IPIPE_DEBUG
Index: linux-2.6.20/kernel/ipipe/core.c
===================================================================
--- linux-2.6.20.orig/kernel/ipipe/core.c
+++ linux-2.6.20/kernel/ipipe/core.c
@@ -33,6 +33,9 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#endif /* CONFIG_PROC_FS */
+#ifdef CONFIG_IPIPE_TRACE_MCOUNT
+#include <linux/ipipe_trace.h>
+#endif /* CONFIG_IPIPE_TRACE_MCOUNT */
static int __ipipe_ptd_key_count;
@@ -1383,6 +1386,34 @@ void __init ipipe_init_proc(void)
#endif /* CONFIG_PROC_FS */
+#ifdef CONFIG_IPIPE_DEBUG_CONTEXT
+void ipipe_check_context(struct ipipe_domain *border_ipd)
+{
+ static int check_hit;
+
+ if (likely(ipipe_current_domain->priority <= border_ipd->priority) ||
+ check_hit)
+ return;
+
+ check_hit = 1;
+
+#ifdef CONFIG_IPIPE_TRACE_MCOUNT
+ ipipe_trace_panic_freeze();
+#endif /* CONFIG_IPIPE_TRACE_MCOUNT */
+ ipipe_set_printk_sync(ipipe_current_domain);
+ printk(KERN_ERR "I-pipe: Detected illicit call from domain '%s'\n"
+ KERN_ERR " into a service reserved for domain '%s' and "
+ "below.\n",
+ ipipe_current_domain->name, border_ipd->name);
+ show_stack(NULL, NULL);
+#ifdef CONFIG_IPIPE_TRACE_MCOUNT
+ ipipe_trace_panic_dump();
+#endif /* CONFIG_IPIPE_TRACE_MCOUNT */
+}
+
+EXPORT_SYMBOL(ipipe_check_context);
+#endif /* CONFIG_IPIPE_DEBUG_CONTEXT */
+
EXPORT_SYMBOL(ipipe_virtualize_irq);
EXPORT_SYMBOL(ipipe_control_irq);
EXPORT_SYMBOL(ipipe_suspend_domain);
[-- Attachment #1.3: debug-dom-violation-i386.patch --]
[-- Type: text/plain, Size: 1710 bytes --]
---
include/asm-i386/i387.h | 9 +++++----
include/asm-i386/irqflags.h | 7 +++++--
2 files changed, 10 insertions(+), 6 deletions(-)
Index: linux-2.6.20/include/asm-i386/irqflags.h
===================================================================
--- linux-2.6.20.orig/include/asm-i386/irqflags.h
+++ linux-2.6.20/include/asm-i386/irqflags.h
@@ -54,6 +54,7 @@ static inline void raw_local_irq_restore
static inline void raw_local_irq_disable(void)
{
#ifdef CONFIG_IPIPE
+ ipipe_check_context(ipipe_root_domain);
__ipipe_stall_root();
barrier();
#else
@@ -144,8 +145,10 @@ static inline unsigned long __raw_local_
#define raw_local_save_flags(flags) \
do { (flags) = __raw_local_save_flags(); } while (0)
-#define raw_local_irq_save(flags) \
- do { (flags) = __raw_local_irq_save(); } while (0)
+#define raw_local_irq_save(flags) do { \
+ ipipe_check_context(ipipe_root_domain); \
+ (flags) = __raw_local_irq_save(); \
+ } while (0)
static inline int raw_irqs_disabled_flags(unsigned long flags)
{
Index: linux-2.6.20/include/asm-i386/i387.h
===================================================================
--- linux-2.6.20.orig/include/asm-i386/i387.h
+++ linux-2.6.20/include/asm-i386/i387.h
@@ -75,10 +75,11 @@ static inline void __save_init_fpu( stru
}
#define __unlazy_fpu( tsk ) do { \
- if (task_thread_info(tsk)->status & TS_USEDFPU) \
- save_init_fpu( tsk ); \
- else \
- tsk->fpu_counter = 0; \
+ if (task_thread_info(tsk)->status & TS_USEDFPU) { \
+ __save_init_fpu(tsk); \
+ stts(); \
+ } else \
+ tsk->fpu_counter = 0; \
} while (0)
#define __clear_fpu( tsk ) \
[-- Attachment #1.4: debug-dom-violation-x86_64.patch --]
[-- Type: text/plain, Size: 939 bytes --]
---
include/asm-x86_64/irqflags.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
Index: linux-2.6.20-x64/include/asm-x86_64/irqflags.h
===================================================================
--- linux-2.6.20-x64.orig/include/asm-x86_64/irqflags.h
+++ linux-2.6.20-x64/include/asm-x86_64/irqflags.h
@@ -86,6 +86,7 @@ static inline int raw_irqs_disabled_flag
static inline void raw_local_irq_disable(void)
{
#ifdef CONFIG_IPIPE
+ ipipe_check_context(ipipe_root_domain);
__ipipe_stall_root();
barrier();
#else
@@ -128,8 +129,10 @@ static inline unsigned long __raw_local_
return flags;
}
-#define raw_local_irq_save(flags) \
- do { (flags) = __raw_local_irq_save(); } while (0)
+#define raw_local_irq_save(flags) do { \
+ ipipe_check_context(ipipe_root_domain); \
+ (flags) = __raw_local_irq_save(); \
+ } while (0)
static inline int raw_irqs_disabled(void)
{
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]
next reply other threads:[~2007-04-26 18:42 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-26 18:42 Jan Kiszka [this message]
[not found] ` <b647ffbd0704270306h21a41eadr850567f6c8d58c22@domain.hid>
2007-04-27 10:21 ` [Adeos-main] [PATCH 7/7] Detect illicit cross-domain calls (i386/x86_64) Jan Kiszka
2007-04-30 14:06 ` Jan Kiszka
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=4630F284.6040103@domain.hid \
--to=jan.kiszka@domain.hid \
--cc=adeos-main@gna.org \
--cc=rpm@xenomai.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 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.