Skip to content

Commit

Permalink
x86/ioperm: Remove bitmap if all permissions dropped
Browse files Browse the repository at this point in the history
If ioperm() results in a bitmap with all bits set (no permissions to any
I/O port), then handling that bitmap on context switch and exit to user
mode is pointless. Drop it.

Move the bitmap exit handling to the ioport code and reuse it for both the
thread exit path and dropping it. This allows to reuse this code for the
upcoming iopl() emulation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Andy Lutomirski <luto@kernel.org>
  • Loading branch information
Thomas Gleixner committed Nov 16, 2019
1 parent 22fe5b0 commit ea5f1cd
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 15 deletions.
2 changes: 2 additions & 0 deletions arch/x86/include/asm/io_bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
19 changes: 18 additions & 1 deletion arch/x86/kernel/ioport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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);

Expand Down
17 changes: 3 additions & 14 deletions arch/x86/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit ea5f1cd

Please sign in to comment.