Skip to content

Commit ea5f1cd

Browse files
committed
x86/ioperm: Remove bitmap if all permissions dropped
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 <[email protected]> Acked-by: Andy Lutomirski <[email protected]>
1 parent 22fe5b0 commit ea5f1cd

File tree

3 files changed

+23
-15
lines changed

3 files changed

+23
-15
lines changed

arch/x86/include/asm/io_bitmap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ struct io_bitmap {
1111
unsigned long bitmap[IO_BITMAP_LONGS];
1212
};
1313

14+
void io_bitmap_exit(void);
15+
1416
void tss_update_io_bitmap(void);
1517

1618
#endif

arch/x86/kernel/ioport.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616

1717
static atomic64_t io_bitmap_sequence;
1818

19+
void io_bitmap_exit(void)
20+
{
21+
struct io_bitmap *iobm = current->thread.io_bitmap;
22+
23+
current->thread.io_bitmap = NULL;
24+
clear_thread_flag(TIF_IO_BITMAP);
25+
preempt_disable();
26+
tss_update_io_bitmap();
27+
preempt_enable();
28+
kfree(iobm);
29+
}
30+
1931
/*
2032
* this changes the io permissions bitmap in the current task.
2133
*/
@@ -61,11 +73,16 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
6173
* Search for a (possibly new) maximum. This is simple and stupid,
6274
* to keep it obviously correct:
6375
*/
64-
max_long = 0;
76+
max_long = UINT_MAX;
6577
for (i = 0; i < IO_BITMAP_LONGS; i++) {
6678
if (iobm->bitmap[i] != ~0UL)
6779
max_long = i;
6880
}
81+
/* All permissions dropped? */
82+
if (max_long == UINT_MAX) {
83+
io_bitmap_exit();
84+
return 0;
85+
}
6986

7087
iobm->max = (max_long + 1) * sizeof(unsigned long);
7188

arch/x86/kernel/process.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,10 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
102102
void exit_thread(struct task_struct *tsk)
103103
{
104104
struct thread_struct *t = &tsk->thread;
105-
struct io_bitmap *iobm = t->io_bitmap;
106105
struct fpu *fpu = &t->fpu;
107-
struct tss_struct *tss;
108-
109-
if (iobm) {
110-
preempt_disable();
111-
tss = this_cpu_ptr(&cpu_tss_rw);
112-
113-
t->io_bitmap = NULL;
114-
clear_thread_flag(TIF_IO_BITMAP);
115-
/* Invalidate the io bitmap base in the TSS */
116-
tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET_INVALID;
117-
preempt_enable();
118-
kfree(iobm);
119-
}
106+
107+
if (test_thread_flag(TIF_IO_BITMAP))
108+
io_bitmap_exit();
120109

121110
free_vm86(t);
122111

0 commit comments

Comments
 (0)