lkml.org 
[lkml]   [2008]   [Apr]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH 2/3] x86: Implement prctl PR_GET_TSC and PR_SET_TSC
    Erik,

    Could you CC me please on kernel-userland API changes.

    Also it would be helpful if you could provide a short paragraph
    (plaintext is fine) that describes the new commands and would be
    suitable for inclusion in the prctl.2 (
    http://www.kernel.org/doc/man-pages/online/pages/man2/prctl.2.html )
    man page -- would that be possible?

    Cheers,

    Michael

    On 4/11/08, Erik Bosman <ebn310@few.vu.nl> wrote:
    >
    > x86: Implement prctl PR_GET_TSC and PR_SET_TSC
    >
    > This patch adds a configure option CONFIG_DISABLE_TSC
    > (off by default) for the x86 platform to enable the
    > PR_GET_TSC and PR_SET_TSC commands. These control the
    > ability to use the timestamp counter from userspace
    > (the RDTSC instruction.)
    >
    > This patch uses code earlier used to disable the
    > timestamp counter for the SECCOMP framework. It used
    > to disable the RDTSC on 32 bit kernels, but allow it
    > on x86_64. This patch makes SECCOMP disable the
    > timestamp counter whenever CONFIG_DISABLE_TSC is
    > enabled.
    >
    > Signed-off-by: Erik Bosman <ejbosman@cs.vu.nl>
    > ---
    > arch/x86/Kconfig | 15 ++++++++
    > arch/x86/kernel/process_32.c | 46 ++++++++++++++++++++++--
    > arch/x86/kernel/process_64.c | 72 ++++++++++++++++++++++++++++++++++++++
    > include/asm-x86/processor.h | 11 ++++++
    > include/asm-x86/thread_info_64.h | 4 ++-
    > include/asm-x86/tsc.h | 3 ++
    > kernel/seccomp.c | 2 +-
    > 7 files changed, 148 insertions(+), 5 deletions(-)
    >
    > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
    > index 56bef39..8b79203 100644
    > --- a/arch/x86/Kconfig
    > +++ b/arch/x86/Kconfig
    > @@ -1122,6 +1122,21 @@ config IRQBALANCE
    > The default yes will allow the kernel to do irq load balancing.
    > Saying no will keep the kernel from doing irq load balancing.
    >
    > +config DISABLE_TSC
    > + def_bool n
    > + prompt "Make availability of the RDTSC instruction configurable"
    > + depends on (X86_32 || X86_64) && EXPERIMENTAL
    > + help
    > + While the RDTSC instruction allows for very precise time
    > + measurements, it is also a source for non-determinism
    > + during the execution of a process which can be a problem in some
    > + security contexts. This option adds prctl commands to configure
    > + and test the availability of the RDTSC instruction on a
    > + per-process basis. Choosing this option may cause a small
    > + performance hit during context switching.
    > +
    > + If unsure, say N.
    > +
    > config SECCOMP
    > def_bool y
    > prompt "Enable seccomp to safely compute untrusted bytecode"
    > diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
    > index 6496344..e6a861f 100644
    > --- a/arch/x86/kernel/process_32.c
    > +++ b/arch/x86/kernel/process_32.c
    > @@ -36,6 +36,7 @@
    > #include <linux/personality.h>
    > #include <linux/tick.h>
    > #include <linux/percpu.h>
    > +#include <linux/prctl.h>
    >
    > #include <asm/uaccess.h>
    > #include <asm/pgtable.h>
    > @@ -528,11 +529,12 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
    > }
    > EXPORT_SYMBOL_GPL(start_thread);
    >
    > -#ifdef CONFIG_SECCOMP
    > +#ifdef CONFIG_DISABLE_TSC
    > static void hard_disable_TSC(void)
    > {
    > write_cr4(read_cr4() | X86_CR4_TSD);
    > }
    > +
    > void disable_TSC(void)
    > {
    > preempt_disable();
    > @@ -544,11 +546,48 @@ void disable_TSC(void)
    > hard_disable_TSC();
    > preempt_enable();
    > }
    > +
    > static void hard_enable_TSC(void)
    > {
    > write_cr4(read_cr4() & ~X86_CR4_TSD);
    > }
    > -#endif /* CONFIG_SECCOMP */
    > +
    > +void enable_TSC(void)
    > +{
    > + preempt_disable();
    > + if (test_and_clear_thread_flag(TIF_NOTSC))
    > + /*
    > + * Must flip the CPU state synchronously with
    > + * TIF_NOTSC in the current running context.
    > + */
    > + hard_enable_TSC();
    > + preempt_enable();
    > +}
    > +
    > +int get_tsc_mode(unsigned long adr)
    > +{
    > + unsigned int val;
    > +
    > + if (test_thread_flag(TIF_NOTSC))
    > + val = PR_TSC_SIGSEGV;
    > + else
    > + val = PR_TSC_ENABLE;
    > +
    > + return put_user(val, (unsigned int __user *)adr);
    > +}
    > +
    > +int set_tsc_mode(unsigned int val)
    > +{
    > + if (val == PR_TSC_SIGSEGV)
    > + disable_TSC();
    > + else if (val == PR_TSC_ENABLE)
    > + enable_TSC();
    > + else
    > + return -EINVAL;
    > +
    > + return 0;
    > +}
    > +#endif /* CONFIG_DISABLE_TSC */
    >
    > static noinline void
    > __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
    > @@ -582,7 +621,7 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
    > set_debugreg(next->debugreg7, 7);
    > }
    >
    > -#ifdef CONFIG_SECCOMP
    > +#ifdef CONFIG_DISABLE_TSC
    > if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
    > test_tsk_thread_flag(next_p, TIF_NOTSC)) {
    > /* prev and next are different */
    > @@ -839,3 +878,4 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
    > unsigned long range_end = mm->brk + 0x02000000;
    > return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
    > }
    > +
    > diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
    > index 043a0c8..8ef8a2f 100644
    > --- a/arch/x86/kernel/process_64.c
    > +++ b/arch/x86/kernel/process_64.c
    > @@ -37,6 +37,7 @@
    > #include <linux/kprobes.h>
    > #include <linux/kdebug.h>
    > #include <linux/tick.h>
    > +#include <linux/prctl.h>
    >
    > #include <asm/uaccess.h>
    > #include <asm/pgtable.h>
    > @@ -555,6 +556,66 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
    > }
    > EXPORT_SYMBOL_GPL(start_thread);
    >
    > +#ifdef CONFIG_DISABLE_TSC
    > +static void hard_disable_TSC(void)
    > +{
    > + write_cr4(read_cr4() | X86_CR4_TSD);
    > +}
    > +
    > +void disable_TSC(void)
    > +{
    > + preempt_disable();
    > + if (!test_and_set_thread_flag(TIF_NOTSC))
    > + /*
    > + * Must flip the CPU state synchronously with
    > + * TIF_NOTSC in the current running context.
    > + */
    > + hard_disable_TSC();
    > + preempt_enable();
    > +}
    > +
    > +static void hard_enable_TSC(void)
    > +{
    > + write_cr4(read_cr4() & ~X86_CR4_TSD);
    > +}
    > +
    > +void enable_TSC(void)
    > +{
    > + preempt_disable();
    > + if (test_and_clear_thread_flag(TIF_NOTSC))
    > + /*
    > + * Must flip the CPU state synchronously with
    > + * TIF_NOTSC in the current running context.
    > + */
    > + hard_enable_TSC();
    > + preempt_enable();
    > +}
    > +
    > +int get_tsc_mode(unsigned long adr)
    > +{
    > + unsigned int val;
    > +
    > + if (test_thread_flag(TIF_NOTSC))
    > + val = PR_TSC_SIGSEGV;
    > + else
    > + val = PR_TSC_ENABLE;
    > +
    > + return put_user(val, (unsigned int __user *)adr);
    > +}
    > +
    > +int set_tsc_mode(unsigned int val)
    > +{
    > + if (val == PR_TSC_SIGSEGV)
    > + disable_TSC();
    > + else if (val == PR_TSC_ENABLE)
    > + enable_TSC();
    > + else
    > + return -EINVAL;
    > +
    > + return 0;
    > +}
    > +#endif /* CONFIG_DISABLE_TSC */
    > +
    > /*
    > * This special macro can be used to load a debugging register
    > */
    > @@ -592,6 +653,17 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
    > loaddebug(next, 7);
    > }
    >
    > +#ifdef CONFIG_DISABLE_TSC
    > + if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
    > + test_tsk_thread_flag(next_p, TIF_NOTSC)) {
    > + /* prev and next are different */
    > + if (test_tsk_thread_flag(next_p, TIF_NOTSC))
    > + hard_disable_TSC();
    > + else
    > + hard_enable_TSC();
    > + }
    > +#endif
    > +
    > if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
    > /*
    > * Copy the relevant range of the IO bitmap.
    > diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
    > index 7b1e3a8..64eea62 100644
    > --- a/include/asm-x86/processor.h
    > +++ b/include/asm-x86/processor.h
    > @@ -921,4 +921,15 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
    >
    > #define KSTK_EIP(task) (task_pt_regs(task)->ip)
    >
    > +#ifdef CONFIG_DISABLE_TSC
    > +
    > +/* Get/set a process' ability to use the timestamp counter instruction */
    > +#define GET_TSC_CTL(adr) get_tsc_mode((adr))
    > +#define SET_TSC_CTL(val) set_tsc_mode((val))
    > +
    > +extern int get_tsc_mode(unsigned long adr);
    > +extern int set_tsc_mode(unsigned int val);
    > +
    > +#endif
    > +
    > #endif
    > diff --git a/include/asm-x86/thread_info_64.h b/include/asm-x86/thread_info_64.h
    > index f23fefc..ed664e8 100644
    > --- a/include/asm-x86/thread_info_64.h
    > +++ b/include/asm-x86/thread_info_64.h
    > @@ -124,6 +124,7 @@ static inline struct thread_info *stack_thread_info(void)
    > #define TIF_DEBUGCTLMSR 25 /* uses thread_struct.debugctlmsr */
    > #define TIF_DS_AREA_MSR 26 /* uses thread_struct.ds_area_msr */
    > #define TIF_BTS_TRACE_TS 27 /* record scheduling event timestamps */
    > +#define TIF_NOTSC 28 /* TSC is not accessible in userland */
    >
    > #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
    > #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
    > @@ -145,6 +146,7 @@ static inline struct thread_info *stack_thread_info(void)
    > #define _TIF_DEBUGCTLMSR (1 << TIF_DEBUGCTLMSR)
    > #define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR)
    > #define _TIF_BTS_TRACE_TS (1 << TIF_BTS_TRACE_TS)
    > +#define _TIF_NOTSC (1 << TIF_NOTSC)
    >
    > /* work to do on interrupt/exception return */
    > #define _TIF_WORK_MASK \
    > @@ -158,7 +160,7 @@ static inline struct thread_info *stack_thread_info(void)
    >
    > /* flags to check in __switch_to() */
    > #define _TIF_WORK_CTXSW \
    > - (_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_BTS_TRACE_TS)
    > + (_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_BTS_TRACE_TS|_TIF_NOTSC)
    > #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
    > #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
    >
    > diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h
    > index d2d8eb5..3281e21 100644
    > --- a/include/asm-x86/tsc.h
    > +++ b/include/asm-x86/tsc.h
    > @@ -17,7 +17,10 @@ typedef unsigned long long cycles_t;
    > extern unsigned int cpu_khz;
    > extern unsigned int tsc_khz;
    >
    > +#ifdef CONFIG_DISABLE_TSC
    > extern void disable_TSC(void);
    > +extern void enable_TSC(void);
    > +#endif
    >
    > static inline cycles_t get_cycles(void)
    > {
    > diff --git a/kernel/seccomp.c b/kernel/seccomp.c
    > index ad64fcb..0e0c7f0 100644
    > --- a/kernel/seccomp.c
    > +++ b/kernel/seccomp.c
    > @@ -74,7 +74,7 @@ long prctl_set_seccomp(unsigned long seccomp_mode)
    > if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
    > current->seccomp.mode = seccomp_mode;
    > set_thread_flag(TIF_SECCOMP);
    > -#ifdef TIF_NOTSC
    > +#ifdef CONFIG_DISABLE_TSC
    > disable_TSC();
    > #endif
    > ret = 0;
    >
    > --
    > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    > the body of a message to majordomo@vger.kernel.org
    > More majordomo info at http://vger.kernel.org/majordomo-info.html
    > Please read the FAQ at http://www.tux.org/lkml/
    >


    --
    I'll likely only see replies if they are CCed to mtk.manpages at gmail dot com


    \
     
     \ /
      Last update: 2008-04-14 12:59    [W:2.515 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site