[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Fix iopl/iobitmap interfaces. Control tools can set per-domain
ChangeSet 1.1353, 2005/03/23 13:35:24+00:00, kaf24@xxxxxxxxxxxxxxxxxxxx Fix iopl/iobitmap interfaces. Control tools can set per-domain access limits via DOM0_IOPL_PERMISSION/DOM0_IOPORT_PERMISSION. Guests can set current permissions per VCPU via physdev ops. These will always succeed -- checking against admin-set limits is done at access time. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> linux-2.4.29-xen-sparse/arch/xen/kernel/ioport.c | 43 +++ linux-2.4.29-xen-sparse/arch/xen/kernel/process.c | 15 - linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c | 17 - linux-2.4.29-xen-sparse/mkbuildtree | 1 linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c | 116 ++++++++- linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c | 75 +----- linux-2.6.11-xen-sparse/arch/xen/i386/kernel/setup.c | 20 - xen/arch/x86/dom0_ops.c | 55 ++++ xen/arch/x86/domain.c | 47 --- xen/arch/x86/setup.c | 1 xen/arch/x86/traps.c | 75 ++++-- xen/common/domain.c | 7 xen/common/physdev.c | 202 ++++++----------- xen/include/asm-x86/domain.h | 11 xen/include/asm-x86/processor.h | 8 xen/include/public/dom0_ops.h | 26 +- xen/include/public/physdev.h | 17 + 17 files changed, 430 insertions(+), 306 deletions(-) diff -Nru a/linux-2.4.29-xen-sparse/arch/xen/kernel/ioport.c b/linux-2.4.29-xen-sparse/arch/xen/kernel/ioport.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/linux-2.4.29-xen-sparse/arch/xen/kernel/ioport.c 2005-03-23 09:02:50 -05:00 @@ -0,0 +1,43 @@ +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/ioport.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/stddef.h> +#include <linux/slab.h> +#include <asm-xen/xen-public/physdev.h> + +asmlinkage long sys_iopl(unsigned int new_io_pl) +{ + unsigned int old_io_pl = current->thread.io_pl; + physdev_op_t op; + + if (new_io_pl > 3) + return -EINVAL; + + /* Need "raw I/O" privileges for direct port access. */ + if ((new_io_pl > old_io_pl) && !capable(CAP_SYS_RAWIO)) + return -EPERM; + + /* Maintain OS privileges even if user attempts to relinquish them. */ + if (new_io_pl == 0) + new_io_pl = 1; + + /* Change our version of the privilege levels. */ + current->thread.io_pl = new_io_pl; + + /* Force the change at ring 0. */ + op.cmd = PHYSDEVOP_SET_IOPL; + op.u.set_iopl.iopl = new_io_pl; + HYPERVISOR_physdev_op(&op); + + return 0; +} + +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) +{ + return turn_on ? sys_iopl(3) : 0; +} diff -Nru a/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c b/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c --- a/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c 2005-03-23 09:02:49 -05:00 +++ b/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c 2005-03-23 09:02:49 -05:00 @@ -44,7 +44,7 @@ #include <asm/desc.h> #include <asm/mmu_context.h> #include <asm/multicall.h> -#include <asm-xen/xen-public/dom0_ops.h> +#include <asm-xen/xen-public/physdev.h> #include <linux/irq.h> @@ -304,6 +304,7 @@ void fastcall __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *next = &next_p->thread; + physdev_op_t op; __cli(); @@ -335,14 +336,12 @@ } queue_multicall2(__HYPERVISOR_stack_switch, __KERNEL_DS, next->esp0); - if ( xen_start_info.flags & SIF_PRIVILEGED ) + + if ( prev_p->thread.io_pl != next->io_pl ) { - dom0_op_t op; - op.cmd = DOM0_IOPL; - op.u.iopl.domain = DOMID_SELF; - op.u.iopl.iopl = next->io_pl; - op.interface_version = DOM0_INTERFACE_VERSION; - queue_multicall1(__HYPERVISOR_dom0_op, (unsigned long)&op); + op.cmd = PHYSDEVOP_SET_IOPL; + op.u.set_iopl.iopl = next->io_pl; + queue_multicall1(__HYPERVISOR_physdev_op, (unsigned long)&op); } /* EXECUTE ALL TASK SWITCH XEN SYSCALLS AT THIS POINT. */ diff -Nru a/linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c b/linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c --- a/linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c 2005-03-23 09:02:49 -05:00 +++ b/linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c 2005-03-23 09:02:50 -05:00 @@ -48,7 +48,7 @@ #include <asm/mmu_context.h> #include <asm/ctrl_if.h> #include <asm/hypervisor.h> -#include <asm-xen/xen-public/dom0_ops.h> +#include <asm-xen/xen-public/physdev.h> #include <linux/netdevice.h> #include <linux/rtnetlink.h> #include <linux/tqueue.h> @@ -206,6 +206,7 @@ unsigned long bootmap_size, start_pfn, lmax_low_pfn; int mem_param; /* user specified memory size in pages */ int boot_pfn; /* low pages available for bootmem */ + physdev_op_t op; extern void hypervisor_callback(void); extern void failsafe_callback(void); @@ -416,17 +417,9 @@ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list = virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT; - /* If we are a privileged guest OS then we should request IO privileges. */ - if ( xen_start_info.flags & SIF_PRIVILEGED ) - { - dom0_op_t op; - op.cmd = DOM0_IOPL; - op.u.iopl.domain = DOMID_SELF; - op.u.iopl.iopl = 1; - if( HYPERVISOR_dom0_op(&op) != 0 ) - panic("Unable to obtain IOPL, despite being SIF_PRIVILEGED"); - current->thread.io_pl = 1; - } + op.cmd = PHYSDEVOP_SET_IOPL; + op.u.set_iopl.iopl = current->thread.io_pl = 1; + HYPERVISOR_physdev_op(&op); if (xen_start_info.flags & SIF_INITDOMAIN ) { diff -Nru a/linux-2.4.29-xen-sparse/mkbuildtree b/linux-2.4.29-xen-sparse/mkbuildtree --- a/linux-2.4.29-xen-sparse/mkbuildtree 2005-03-23 09:02:50 -05:00 +++ b/linux-2.4.29-xen-sparse/mkbuildtree 2005-03-23 09:02:50 -05:00 @@ -232,7 +232,6 @@ ln -sf ../../../${LINUX_26}/arch/xen/kernel/gnttab.c ln -sf ../../../${LINUX_26}/arch/xen/kernel/reboot.c ln -sf ../../../${LINUX_26}/arch/xen/kernel/skbuff.c -ln -sf ../../../${LINUX_26}/arch/xen/i386/kernel/ioport.c ln -sf ../../../${LINUX_26}/arch/xen/i386/kernel/pci-dma.c cd ${AD}/arch/xen/lib diff -Nru a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c 2005-03-23 09:02:49 -05:00 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c 2005-03-23 09:02:49 -05:00 @@ -1,19 +1,110 @@ +/* + * linux/arch/i386/kernel/ioport.c + * + * This contains the io-permission bitmap code - written by obz, with changes + * by Linus. + */ + #include <linux/sched.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/ioport.h> -#include <linux/mm.h> #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/stddef.h> #include <linux/slab.h> -#include <asm-xen/xen-public/dom0_ops.h> +#include <linux/thread_info.h> +#include <asm-xen/xen-public/physdev.h> + +/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ +static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value) +{ + unsigned long mask; + unsigned long *bitmap_base = bitmap + (base / BITS_PER_LONG); + unsigned int low_index = base & (BITS_PER_LONG-1); + int length = low_index + extent; + + if (low_index != 0) { + mask = (~0UL << low_index); + if (length < BITS_PER_LONG) + mask &= ~(~0UL << length); + if (new_value) + *bitmap_base++ |= mask; + else + *bitmap_base++ &= ~mask; + length -= BITS_PER_LONG; + } + + mask = (new_value ? ~0UL : 0UL); + while (length >= BITS_PER_LONG) { + *bitmap_base++ = mask; + length -= BITS_PER_LONG; + } + + if (length > 0) { + mask = ~(~0UL << length); + if (new_value) + *bitmap_base++ |= mask; + else + *bitmap_base++ &= ~mask; + } +} + + +/* + * this changes the io permissions bitmap in the current task. + */ +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) +{ + struct thread_struct * t = ¤t->thread; + unsigned long *bitmap; + physdev_op_t op; + + if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) + return -EINVAL; + if (turn_on && !capable(CAP_SYS_RAWIO)) + return -EPERM; + + /* + * If it's the first ioperm() call in this thread's lifetime, set the + * IO bitmap up. ioperm() is much less timing critical than clone(), + * this is why we delay this operation until now: + */ + if (!t->io_bitmap_ptr) { + bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); + if (!bitmap) + return -ENOMEM; + + memset(bitmap, 0xff, IO_BITMAP_BYTES); + t->io_bitmap_ptr = bitmap; + + op.cmd = PHYSDEVOP_SET_IOBITMAP; + op.u.set_iobitmap.bitmap = (unsigned long)bitmap; + op.u.set_iobitmap.nr_ports = IO_BITMAP_BITS; + HYPERVISOR_physdev_op(&op); + } + + set_bitmap(t->io_bitmap_ptr, from, num, !turn_on); + + return 0; +} + +/* + * sys_iopl has to be used when you want to access the IO ports + * beyond the 0x3ff range: to get the full 65536 ports bitmapped + * you'd need 8kB of bitmaps/process, which is a bit excessive. + * + * Here we just change the eflags value on the stack: we allow + * only the super-user to do it. This depends on the stack-layout + * on system-call entry - see also fork() and the signal handling + * code. + */ asmlinkage long sys_iopl(unsigned int new_io_pl) { ------------------------------------------------------- This SF.net email is sponsored by: 2005 Windows Mobile Application Contest Submit applications for Windows Mobile(tm)-based Pocket PCs or Smartphones for the chance to win $25,000 and application distribution. Enter today at http://ads.osdn.com/?ad_id=6882&alloc_id=15148&op=click _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxxxx https://lists.sourceforge.net/lists/listinfo/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |