From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: <4630F284.6040103@domain.hid> Date: Thu, 26 Apr 2007 20:42:12 +0200 From: Jan Kiszka MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enig46318CD6D95CA5023005D912" Sender: jan.kiszka@domain.hid Subject: [Adeos-main] [PATCH 7/7] Detect illicit cross-domain calls (i386/x86_64) List-Id: General discussion about Adeos List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: adeos-main Cc: Philippe Gerum This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig46318CD6D95CA5023005D912 Content-Type: multipart/mixed; boundary="------------080907050307010602030605" This is a multi-part message in MIME format. --------------080907050307010602030605 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: quoted-printable [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 --------------080907050307010602030605 Content-Type: text/plain; name="debug-dom-violation-v3.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="debug-dom-violation-v3.patch" --- 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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); =20 void __ipipe_restore_root(unsigned long x); =20 +#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 */ =20 #endif /* !__LINUX_IPIPE_BASE_H */ Index: linux-2.6.20/include/linux/kernel.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/include/linux/kernel.h +++ linux-2.6.20/include/linux/kernel.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include =20 @@ -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 =20 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP Index: linux-2.6.20/include/linux/preempt.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/include/linux/preempt.h +++ linux-2.6.20/include/linux/preempt.h @@ -8,6 +8,7 @@ =20 #include #include +#include =20 #ifdef CONFIG_DEBUG_PREEMPT extern void fastcall add_preempt_count(int val); @@ -26,52 +27,40 @@ =20 asmlinkage void preempt_schedule(void); =20 -#ifdef CONFIG_IPIPE -#include -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_proces= sor_id()) =3D=3D &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) =20 -#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) =20 -#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) =20 -#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) =20 #else =20 -#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_domai= n) +#define preempt_enable() ipipe_check_context(ipipe_root_domain) +#define preempt_check_resched() ipipe_check_context(ipipe_root_domain) =20 #endif =20 Index: linux-2.6.20/kernel/ipipe/Kconfig.debug =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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 =20 +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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/kernel/ipipe/core.c +++ linux-2.6.20/kernel/ipipe/core.c @@ -33,6 +33,9 @@ #include #include #endif /* CONFIG_PROC_FS */ +#ifdef CONFIG_IPIPE_TRACE_MCOUNT +#include +#endif /* CONFIG_IPIPE_TRACE_MCOUNT */ =20 static int __ipipe_ptd_key_count; =20 @@ -1383,6 +1386,34 @@ void __init ipipe_init_proc(void) =20 #endif /* CONFIG_PROC_FS */ =20 +#ifdef CONFIG_IPIPE_DEBUG_CONTEXT +void ipipe_check_context(struct ipipe_domain *border_ipd) +{ + static int check_hit; + + if (likely(ipipe_current_domain->priority <=3D border_ipd->priority) ||= + check_hit) + return; + + check_hit =3D 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); --------------080907050307010602030605 Content-Type: text/plain; name="debug-dom-violation-i386.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="debug-dom-violation-i386.patch" --- 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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) =3D __raw_local_save_flags(); } while (0) =20 -#define raw_local_irq_save(flags) \ - do { (flags) =3D __raw_local_irq_save(); } while (0) +#define raw_local_irq_save(flags) do { \ + ipipe_check_context(ipipe_root_domain); \ + (flags) =3D __raw_local_irq_save(); \ + } while (0) =20 static inline int raw_irqs_disabled_flags(unsigned long flags) { Index: linux-2.6.20/include/asm-i386/i387.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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 } =20 #define __unlazy_fpu( tsk ) do { \ - if (task_thread_info(tsk)->status & TS_USEDFPU) \ - save_init_fpu( tsk ); \ - else \ - tsk->fpu_counter =3D 0; \ + if (task_thread_info(tsk)->status & TS_USEDFPU) { \ + __save_init_fpu(tsk); \ + stts(); \ + } else \ + tsk->fpu_counter =3D 0; \ } while (0) =20 #define __clear_fpu( tsk ) \ --------------080907050307010602030605 Content-Type: text/plain; name="debug-dom-violation-x86_64.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="debug-dom-violation-x86_64.patch" --- 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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; } =20 -#define raw_local_irq_save(flags) \ - do { (flags) =3D __raw_local_irq_save(); } while (0) +#define raw_local_irq_save(flags) do { \ + ipipe_check_context(ipipe_root_domain); \ + (flags) =3D __raw_local_irq_save(); \ + } while (0) =20 static inline int raw_irqs_disabled(void) { --------------080907050307010602030605-- --------------enig46318CD6D95CA5023005D912 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGMPKEniDOoMHTA+kRAqPfAKCB4ySQYRj1N2zcVkz13y8VrXvLIACeNzjs PSDm1hLvxmGh+kI+1SYULQY= =Y/wF -----END PGP SIGNATURE----- --------------enig46318CD6D95CA5023005D912--