Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
x86
kernel
ioport.c
Go to the documentation of this file.
1
/*
2
* This contains the io-permission bitmap code - written by obz, with changes
3
* by Linus. 32/64 bits code unification by Miguel Botón.
4
*/
5
6
#include <linux/sched.h>
7
#include <linux/kernel.h>
8
#include <linux/capability.h>
9
#include <linux/errno.h>
10
#include <linux/types.h>
11
#include <
linux/ioport.h
>
12
#include <
linux/smp.h
>
13
#include <linux/stddef.h>
14
#include <linux/slab.h>
15
#include <
linux/thread_info.h
>
16
#include <
linux/syscalls.h
>
17
#include <linux/bitmap.h>
18
#include <asm/syscalls.h>
19
20
/*
21
* this changes the io permissions bitmap in the current task.
22
*/
23
asmlinkage
long
sys_ioperm
(
unsigned
long
from
,
unsigned
long
num,
int
turn_on)
24
{
25
struct
thread_struct
*
t
= &
current
->thread;
26
struct
tss_struct
*
tss
;
27
unsigned
int
i
, max_long,
bytes
, bytes_updated;
28
29
if
((from + num <= from) || (from + num >
IO_BITMAP_BITS
))
30
return
-
EINVAL
;
31
if
(turn_on && !
capable
(
CAP_SYS_RAWIO
))
32
return
-
EPERM
;
33
34
/*
35
* If it's the first ioperm() call in this thread's lifetime, set the
36
* IO bitmap up. ioperm() is much less timing critical than clone(),
37
* this is why we delay this operation until now:
38
*/
39
if
(!t->
io_bitmap_ptr
) {
40
unsigned
long
*
bitmap
=
kmalloc
(
IO_BITMAP_BYTES
,
GFP_KERNEL
);
41
42
if
(!bitmap)
43
return
-
ENOMEM
;
44
45
memset
(bitmap, 0xff,
IO_BITMAP_BYTES
);
46
t->
io_bitmap_ptr
=
bitmap
;
47
set_thread_flag(
TIF_IO_BITMAP
);
48
}
49
50
/*
51
* do it in the per-thread copy and in the TSS ...
52
*
53
* Disable preemption via get_cpu() - we must not switch away
54
* because the ->io_bitmap_max value must match the bitmap
55
* contents:
56
*/
57
tss = &
per_cpu
(init_tss,
get_cpu
());
58
59
if
(turn_on)
60
bitmap_clear
(t->
io_bitmap_ptr
, from, num);
61
else
62
bitmap_set
(t->
io_bitmap_ptr
, from, num);
63
64
/*
65
* Search for a (possibly new) maximum. This is simple and stupid,
66
* to keep it obviously correct:
67
*/
68
max_long = 0;
69
for
(i = 0; i <
IO_BITMAP_LONGS
; i++)
70
if
(t->
io_bitmap_ptr
[i] != ~0
UL
)
71
max_long =
i
;
72
73
bytes = (max_long + 1) *
sizeof
(
unsigned
long
);
74
bytes_updated =
max
(bytes, t->
io_bitmap_max
);
75
76
t->
io_bitmap_max
=
bytes
;
77
78
/* Update the TSS: */
79
memcpy
(tss->
io_bitmap
, t->
io_bitmap_ptr
, bytes_updated);
80
81
put_cpu
();
82
83
return
0;
84
}
85
86
/*
87
* sys_iopl has to be used when you want to access the IO ports
88
* beyond the 0x3ff range: to get the full 65536 ports bitmapped
89
* you'd need 8kB of bitmaps/process, which is a bit excessive.
90
*
91
* Here we just change the flags value on the stack: we allow
92
* only the super-user to do it. This depends on the stack-layout
93
* on system-call entry - see also fork() and the signal handling
94
* code.
95
*/
96
long
sys_iopl
(
unsigned
int
level
,
struct
pt_regs
*
regs
)
97
{
98
unsigned
int
old = (regs->
flags
>> 12) & 3;
99
struct
thread_struct
*
t
= &
current
->thread;
100
101
if
(level > 3)
102
return
-
EINVAL
;
103
/* Trying to gain more privileges? */
104
if
(level > old) {
105
if
(!
capable
(
CAP_SYS_RAWIO
))
106
return
-
EPERM
;
107
}
108
regs->
flags
= (regs->
flags
& ~
X86_EFLAGS_IOPL
) | (level << 12);
109
t->
iopl
= level << 12;
110
set_iopl_mask
(t->
iopl
);
111
112
return
0;
113
}
Generated on Thu Jan 10 2013 13:17:52 for Linux Kernel by
1.8.2