All of lore.kernel.org
 help / color / mirror / Atom feed
* [Adeos-main] [PATCH 7/7] Detect illicit cross-domain calls (i386/x86_64)
@ 2007-04-26 18:42 Jan Kiszka
       [not found] ` <b647ffbd0704270306h21a41eadr850567f6c8d58c22@domain.hid>
  2007-04-30 14:06 ` Jan Kiszka
  0 siblings, 2 replies; 3+ messages in thread
From: Jan Kiszka @ 2007-04-26 18:42 UTC (permalink / raw)
  To: adeos-main; +Cc: Philippe Gerum


[-- 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 --]

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

end of thread, other threads:[~2007-04-30 14:06 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-26 18:42 [Adeos-main] [PATCH 7/7] Detect illicit cross-domain calls (i386/x86_64) Jan Kiszka
     [not found] ` <b647ffbd0704270306h21a41eadr850567f6c8d58c22@domain.hid>
2007-04-27 10:21   ` Jan Kiszka
2007-04-30 14:06 ` Jan Kiszka

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.