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