summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/io_bitmap.h2
-rw-r--r--arch/x86/kernel/ioport.c19
-rw-r--r--arch/x86/kernel/process.c17
3 files changed, 23 insertions, 15 deletions
diff --git a/arch/x86/include/asm/io_bitmap.h b/arch/x86/include/asm/io_bitmap.h
index 6d82a37cb17c..784a88edb25d 100644
--- a/arch/x86/include/asm/io_bitmap.h
+++ b/arch/x86/include/asm/io_bitmap.h
@@ -11,6 +11,8 @@ struct io_bitmap {
unsigned long bitmap[IO_BITMAP_LONGS];
};
+void io_bitmap_exit(void);
+
void tss_update_io_bitmap(void);
#endif
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 198beadb3732..f9fc69aeb033 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -16,6 +16,18 @@
static atomic64_t io_bitmap_sequence;
+void io_bitmap_exit(void)
+{
+ struct io_bitmap *iobm = current->thread.io_bitmap;
+
+ current->thread.io_bitmap = NULL;
+ clear_thread_flag(TIF_IO_BITMAP);
+ preempt_disable();
+ tss_update_io_bitmap();
+ preempt_enable();
+ kfree(iobm);
+}
+
/*
* this changes the io permissions bitmap in the current task.
*/
@@ -61,11 +73,16 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
* Search for a (possibly new) maximum. This is simple and stupid,
* to keep it obviously correct:
*/
- max_long = 0;
+ max_long = UINT_MAX;
for (i = 0; i < IO_BITMAP_LONGS; i++) {
if (iobm->bitmap[i] != ~0UL)
max_long = i;
}
+ /* All permissions dropped? */
+ if (max_long == UINT_MAX) {
+ io_bitmap_exit();
+ return 0;
+ }
iobm->max = (max_long + 1) * sizeof(unsigned long);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 108af913ab3c..7ba4d54aec17 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -102,21 +102,10 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
void exit_thread(struct task_struct *tsk)
{
struct thread_struct *t = &tsk->thread;
- struct io_bitmap *iobm = t->io_bitmap;
struct fpu *fpu = &t->fpu;
- struct tss_struct *tss;
-
- if (iobm) {
- preempt_disable();
- tss = this_cpu_ptr(&cpu_tss_rw);
-
- t->io_bitmap = NULL;
- clear_thread_flag(TIF_IO_BITMAP);
- /* Invalidate the io bitmap base in the TSS */
- tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET_INVALID;
- preempt_enable();
- kfree(iobm);
- }
+
+ if (test_thread_flag(TIF_IO_BITMAP))
+ io_bitmap_exit();
free_vm86(t);