Skip to content

Commit a24ca99

Browse files
committed
x86/iopl: Remove legacy IOPL option
The IOPL emulation via the I/O bitmap is sufficient. Remove the legacy cruft dealing with the (e)flags based IOPL mechanism. Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Juergen Gross <[email protected]> (Paravirt and Xen parts) Acked-by: Andy Lutomirski <[email protected]>
1 parent c8137ac commit a24ca99

File tree

10 files changed

+17
-119
lines changed

10 files changed

+17
-119
lines changed

arch/x86/Kconfig

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,12 +1254,9 @@ config X86_VSYSCALL_EMULATION
12541254
Disabling this option saves about 7K of kernel size and
12551255
possibly 4K of additional runtime pagetable memory.
12561256

1257-
choice
1258-
prompt "IOPL"
1259-
default X86_IOPL_EMULATION
1260-
12611257
config X86_IOPL_EMULATION
12621258
bool "IOPL Emulation"
1259+
default y
12631260
---help---
12641261
Legacy IOPL support is an overbroad mechanism which allows user
12651262
space aside of accessing all 65536 I/O ports also to disable
@@ -1269,22 +1266,8 @@ config X86_IOPL_EMULATION
12691266

12701267
The emulation restricts the functionality of the syscall to
12711268
only allowing the full range I/O port access, but prevents the
1272-
ability to disable interrupts from user space.
1273-
1274-
config X86_IOPL_LEGACY
1275-
bool "IOPL Legacy"
1276-
---help---
1277-
Allow the full IOPL permissions, i.e. user space access to all
1278-
65536 I/O ports and also the ability to disable interrupts, which
1279-
is overbroad and can result in system lockups.
1280-
1281-
config X86_IOPL_NONE
1282-
bool "IOPL None"
1283-
---help---
1284-
Disable the IOPL permission syscall. That's the safest option as
1285-
no sane application should depend on this functionality.
1286-
1287-
endchoice
1269+
ability to disable interrupts from user space which would be
1270+
granted if the hardware IOPL mechanism would be used.
12881271

12891272
config TOSHIBA
12901273
tristate "Toshiba Laptop support"

arch/x86/include/asm/paravirt.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,6 @@ static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
294294
{
295295
PVOP_VCALL3(cpu.write_idt_entry, dt, entry, g);
296296
}
297-
static inline void set_iopl_mask(unsigned mask)
298-
{
299-
PVOP_VCALL1(cpu.set_iopl_mask, mask);
300-
}
301297

302298
static inline void paravirt_activate_mm(struct mm_struct *prev,
303299
struct mm_struct *next)

arch/x86/include/asm/paravirt_types.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,6 @@ struct pv_cpu_ops {
140140

141141
void (*load_sp0)(unsigned long sp0);
142142

143-
void (*set_iopl_mask)(unsigned mask);
144-
145143
void (*wbinvd)(void);
146144

147145
/* cpuid emulation, mostly so that caps bits can be disabled */

arch/x86/include/asm/processor.h

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -516,10 +516,10 @@ struct thread_struct {
516516
struct io_bitmap *io_bitmap;
517517

518518
/*
519-
* IOPL. Priviledge level dependent I/O permission which includes
520-
* user space CLI/STI when granted.
519+
* IOPL. Priviledge level dependent I/O permission which is
520+
* emulated via the I/O bitmap to prevent user space from disabling
521+
* interrupts.
521522
*/
522-
unsigned long iopl;
523523
unsigned long iopl_emul;
524524

525525
mm_segment_t addr_limit;
@@ -552,25 +552,6 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
552552
*/
553553
#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/
554554

555-
/*
556-
* Set IOPL bits in EFLAGS from given mask
557-
*/
558-
static inline void native_set_iopl_mask(unsigned mask)
559-
{
560-
#ifdef CONFIG_X86_32
561-
unsigned int reg;
562-
563-
asm volatile ("pushfl;"
564-
"popl %0;"
565-
"andl %1, %0;"
566-
"orl %2, %0;"
567-
"pushl %0;"
568-
"popfl"
569-
: "=&r" (reg)
570-
: "i" (~X86_EFLAGS_IOPL), "r" (mask));
571-
#endif
572-
}
573-
574555
static inline void
575556
native_load_sp0(unsigned long sp0)
576557
{
@@ -610,7 +591,6 @@ static inline void load_sp0(unsigned long sp0)
610591
native_load_sp0(sp0);
611592
}
612593

613-
#define set_iopl_mask native_set_iopl_mask
614594
#endif /* CONFIG_PARAVIRT_XXL */
615595

616596
/* Free all resources held by a thread. */

arch/x86/include/asm/xen/hypervisor.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,4 @@ void xen_arch_register_cpu(int num);
6262
void xen_arch_unregister_cpu(int num);
6363
#endif
6464

65-
extern void xen_set_iopl_mask(unsigned mask);
66-
6765
#endif /* _ASM_X86_XEN_HYPERVISOR_H */

arch/x86/kernel/ioport.c

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -153,28 +153,23 @@ SYSCALL_DEFINE3(ioperm, unsigned long, from, unsigned long, num, int, turn_on)
153153

154154
/*
155155
* The sys_iopl functionality depends on the level argument, which if
156-
* granted for the task is used by the CPU to check I/O instruction and
157-
* CLI/STI against the current priviledge level (CPL). If CPL is less than
158-
* or equal the tasks IOPL level the instructions take effect. If not a #GP
159-
* is raised. The default IOPL is 0, i.e. no permissions.
156+
* granted for the task is used to enable access to all 65536 I/O ports.
160157
*
161-
* Setting IOPL to level 0-2 is disabling the userspace access. Only level
162-
* 3 enables it. If set it allows the user space thread:
158+
* This does not use the IOPL mechanism provided by the CPU as that would
159+
* also allow the user space task to use the CLI/STI instructions.
163160
*
164-
* - Unrestricted access to all 65535 I/O ports
165-
* - The usage of CLI/STI instructions
161+
* Disabling interrupts in a user space task is dangerous as it might lock
162+
* up the machine and the semantics vs. syscalls and exceptions is
163+
* undefined.
166164
*
167-
* The advantage over ioperm is that the context switch does not require to
168-
* update the I/O bitmap which is especially true when a large number of
169-
* ports is accessed. But the allowance of CLI/STI in userspace is
170-
* considered a major problem.
165+
* Setting IOPL to level 0-2 is disabling I/O permissions. Level 3
166+
* 3 enables them.
171167
*
172168
* IOPL is strictly per thread and inherited on fork.
173169
*/
174170
SYSCALL_DEFINE1(iopl, unsigned int, level)
175171
{
176172
struct thread_struct *t = &current->thread;
177-
struct pt_regs *regs = current_pt_regs();
178173
unsigned int old;
179174

180175
/*
@@ -187,10 +182,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
187182
if (level > 3)
188183
return -EINVAL;
189184

190-
if (IS_ENABLED(CONFIG_X86_IOPL_EMULATION))
191-
old = t->iopl_emul;
192-
else
193-
old = t->iopl >> X86_EFLAGS_IOPL_BIT;
185+
old = t->iopl_emul;
194186

195187
/* No point in going further if nothing changes */
196188
if (level == old)
@@ -203,25 +195,8 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
203195
return -EPERM;
204196
}
205197

206-
if (IS_ENABLED(CONFIG_X86_IOPL_EMULATION)) {
207-
t->iopl_emul = level;
208-
task_update_io_bitmap();
209-
} else {
210-
/*
211-
* Change the flags value on the return stack, which has
212-
* been set up on system-call entry. See also the fork and
213-
* signal handling code how this is handled.
214-
*/
215-
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |
216-
(level << X86_EFLAGS_IOPL_BIT);
217-
/* Store the new level in the thread struct */
218-
t->iopl = level << X86_EFLAGS_IOPL_BIT;
219-
/*
220-
* X86_32 switches immediately and XEN handles it via
221-
* emulation.
222-
*/
223-
set_iopl_mask(t->iopl);
224-
}
198+
t->iopl_emul = level;
199+
task_update_io_bitmap();
225200

226201
return 0;
227202
}

arch/x86/kernel/paravirt.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,6 @@ struct paravirt_patch_template pv_ops = {
341341
.cpu.iret = native_iret,
342342
.cpu.swapgs = native_swapgs,
343343

344-
.cpu.set_iopl_mask = native_set_iopl_mask,
345-
346344
.cpu.start_context_switch = paravirt_nop,
347345
.cpu.end_context_switch = paravirt_nop,
348346

arch/x86/kernel/process_32.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
187187
*/
188188
load_TLS(next, cpu);
189189

190-
/*
191-
* Restore IOPL if needed. In normal use, the flags restore
192-
* in the switch assembly will handle this. But if the kernel
193-
* is running virtualized at a non-zero CPL, the popf will
194-
* not restore flags, so it must be done in a separate step.
195-
*/
196-
if (get_kernel_rpl() && unlikely(prev->iopl != next->iopl))
197-
set_iopl_mask(next->iopl);
198-
199190
switch_to_extra(prev_p, next_p);
200191

201192
/*

arch/x86/kernel/process_64.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -497,17 +497,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
497497

498498
switch_to_extra(prev_p, next_p);
499499

500-
#ifdef CONFIG_XEN_PV
501-
/*
502-
* On Xen PV, IOPL bits in pt_regs->flags have no effect, and
503-
* current_pt_regs()->flags may not match the current task's
504-
* intended IOPL. We need to switch it manually.
505-
*/
506-
if (unlikely(static_cpu_has(X86_FEATURE_XENPV) &&
507-
prev->iopl != next->iopl))
508-
xen_set_iopl_mask(next->iopl);
509-
#endif
510-
511500
if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) {
512501
/*
513502
* AMD CPUs have a misfeature: SYSRET sets the SS selector but

arch/x86/xen/enlighten_pv.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -837,15 +837,6 @@ static void xen_load_sp0(unsigned long sp0)
837837
this_cpu_write(cpu_tss_rw.x86_tss.sp0, sp0);
838838
}
839839

840-
void xen_set_iopl_mask(unsigned mask)
841-
{
842-
struct physdev_set_iopl set_iopl;
843-
844-
/* Force the change at ring 0. */
845-
set_iopl.iopl = (mask == 0) ? 1 : (mask >> 12) & 3;
846-
HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
847-
}
848-
849840
static void xen_io_delay(void)
850841
{
851842
}
@@ -1055,7 +1046,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
10551046
.write_idt_entry = xen_write_idt_entry,
10561047
.load_sp0 = xen_load_sp0,
10571048

1058-
.set_iopl_mask = xen_set_iopl_mask,
10591049
.io_delay = xen_io_delay,
10601050

10611051
/* Xen takes care of %gs when switching to usermode for us */

0 commit comments

Comments
 (0)