^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * This contains the io-permission bitmap code - written by obz, with changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * by Linus. 32/64 bits code unification by Miguel Botón.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/io_bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/desc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #ifdef CONFIG_X86_IOPL_IOPERM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static atomic64_t io_bitmap_sequence;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) void io_bitmap_share(struct task_struct *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* Can be NULL when current->thread.iopl_emul == 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (current->thread.io_bitmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Take a refcount on current's bitmap. It can be used by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * both tasks as long as none of them changes the bitmap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) refcount_inc(¤t->thread.io_bitmap->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) tsk->thread.io_bitmap = current->thread.io_bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) set_tsk_thread_flag(tsk, TIF_IO_BITMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void task_update_io_bitmap(struct task_struct *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct thread_struct *t = &tsk->thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (t->iopl_emul == 3 || t->io_bitmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* TSS update is handled on exit to user space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) set_tsk_thread_flag(tsk, TIF_IO_BITMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) clear_tsk_thread_flag(tsk, TIF_IO_BITMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Invalidate TSS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) tss_update_io_bitmap();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void io_bitmap_exit(struct task_struct *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct io_bitmap *iobm = tsk->thread.io_bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) tsk->thread.io_bitmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) task_update_io_bitmap(tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (iobm && refcount_dec_and_test(&iobm->refcnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) kfree(iobm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * This changes the io permissions bitmap in the current task.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct thread_struct *t = ¤t->thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned int i, max_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct io_bitmap *iobm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (turn_on && (!capable(CAP_SYS_RAWIO) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) security_locked_down(LOCKDOWN_IOPORT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * If it's the first ioperm() call in this thread's lifetime, set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * IO bitmap up. ioperm() is much less timing critical than clone(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * this is why we delay this operation until now:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) iobm = t->io_bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!iobm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* No point to allocate a bitmap just to clear permissions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!turn_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) iobm = kmalloc(sizeof(*iobm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!iobm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) memset(iobm->bitmap, 0xff, sizeof(iobm->bitmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) refcount_set(&iobm->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * If the bitmap is not shared, then nothing can take a refcount as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * current can obviously not fork at the same time. If it's shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * duplicate it and drop the refcount on the original one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (refcount_read(&iobm->refcnt) > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) iobm = kmemdup(iobm, sizeof(*iobm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!iobm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) refcount_set(&iobm->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) io_bitmap_exit(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Store the bitmap pointer (might be the same if the task already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * head one). Must be done here so freeing the bitmap when all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * permissions are dropped has the pointer set up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) t->io_bitmap = iobm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Mark it active for context switching and exit to user mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) set_thread_flag(TIF_IO_BITMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * Update the tasks bitmap. The update of the TSS bitmap happens on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * exit to user mode. So this needs no protection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (turn_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) bitmap_clear(iobm->bitmap, from, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) bitmap_set(iobm->bitmap, from, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * Search for a (possibly new) maximum. This is simple and stupid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * to keep it obviously correct:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) max_long = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (i = 0; i < IO_BITMAP_LONGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (iobm->bitmap[i] != ~0UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) max_long = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* All permissions dropped? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (max_long == UINT_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) io_bitmap_exit(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) iobm->max = (max_long + 1) * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * Update the sequence number to force a TSS update on return to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * user mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) iobm->sequence = atomic64_add_return(1, &io_bitmap_sequence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) SYSCALL_DEFINE3(ioperm, unsigned long, from, unsigned long, num, int, turn_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return ksys_ioperm(from, num, turn_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * The sys_iopl functionality depends on the level argument, which if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * granted for the task is used to enable access to all 65536 I/O ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * This does not use the IOPL mechanism provided by the CPU as that would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * also allow the user space task to use the CLI/STI instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * Disabling interrupts in a user space task is dangerous as it might lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * up the machine and the semantics vs. syscalls and exceptions is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * undefined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Setting IOPL to level 0-2 is disabling I/O permissions. Level 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * 3 enables them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * IOPL is strictly per thread and inherited on fork.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) SYSCALL_DEFINE1(iopl, unsigned int, level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct thread_struct *t = ¤t->thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned int old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (level > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) old = t->iopl_emul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* No point in going further if nothing changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (level == old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* Trying to gain more privileges? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (level > old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (!capable(CAP_SYS_RAWIO) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) security_locked_down(LOCKDOWN_IOPORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) t->iopl_emul = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) task_update_io_bitmap(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #else /* CONFIG_X86_IOPL_IOPERM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) SYSCALL_DEFINE3(ioperm, unsigned long, from, unsigned long, num, int, turn_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) SYSCALL_DEFINE1(iopl, unsigned int, level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #endif