]>
Commit | Line | Data |
---|---|---|
056a1eb7 SF |
1 | /* $Id: memuserkernel-r0drv-linux.c $ */ |
2 | /** @file | |
3 | * IPRT - User & Kernel Memory, Ring-0 Driver, Linux. | |
4 | */ | |
5 | ||
6 | /* | |
6d209b23 | 7 | * Copyright (C) 2009-2017 Oracle Corporation |
056a1eb7 SF |
8 | * |
9 | * This file is part of VirtualBox Open Source Edition (OSE), as | |
10 | * available from http://www.virtualbox.org. This file is free software; | |
11 | * you can redistribute it and/or modify it under the terms of the GNU | |
12 | * General Public License (GPL) as published by the Free Software | |
13 | * Foundation, in version 2 as it comes in the "COPYING" file of the | |
14 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the | |
15 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. | |
16 | * | |
17 | * The contents of this file may alternatively be used under the terms | |
18 | * of the Common Development and Distribution License Version 1.0 | |
19 | * (CDDL) only, as it comes in the "COPYING.CDDL" file of the | |
20 | * VirtualBox OSE distribution, in which case the provisions of the | |
21 | * CDDL are applicable instead of those of the GPL. | |
22 | * | |
23 | * You may elect to license modified versions of this file under the | |
24 | * terms and conditions of either the GPL or the CDDL or both. | |
25 | */ | |
26 | ||
27 | ||
28 | /********************************************************************************************************************************* | |
29 | * Header Files * | |
30 | *********************************************************************************************************************************/ | |
31 | #include "the-linux-kernel.h" | |
32 | #include "internal/iprt.h" | |
33 | ||
34 | #include <iprt/mem.h> | |
35 | #include <iprt/err.h> | |
36 | ||
37 | ||
38 | RTR0DECL(int) RTR0MemUserCopyFrom(void *pvDst, RTR3PTR R3PtrSrc, size_t cb) | |
39 | { | |
40 | IPRT_LINUX_SAVE_EFL_AC(); | |
41 | if (RT_LIKELY(copy_from_user(pvDst, (void *)R3PtrSrc, cb) == 0)) | |
42 | { | |
43 | IPRT_LINUX_RESTORE_EFL_AC(); | |
44 | return VINF_SUCCESS; | |
45 | } | |
46 | IPRT_LINUX_RESTORE_EFL_AC(); | |
47 | return VERR_ACCESS_DENIED; | |
48 | } | |
49 | RT_EXPORT_SYMBOL(RTR0MemUserCopyFrom); | |
50 | ||
51 | ||
52 | RTR0DECL(int) RTR0MemUserCopyTo(RTR3PTR R3PtrDst, void const *pvSrc, size_t cb) | |
53 | { | |
54 | IPRT_LINUX_SAVE_EFL_AC(); | |
55 | if (RT_LIKELY(copy_to_user((void *)R3PtrDst, pvSrc, cb) == 0)) | |
56 | { | |
57 | IPRT_LINUX_RESTORE_EFL_AC(); | |
58 | return VINF_SUCCESS; | |
59 | } | |
60 | IPRT_LINUX_RESTORE_EFL_AC(); | |
61 | return VERR_ACCESS_DENIED; | |
62 | } | |
63 | RT_EXPORT_SYMBOL(RTR0MemUserCopyTo); | |
64 | ||
65 | ||
66 | RTR0DECL(bool) RTR0MemUserIsValidAddr(RTR3PTR R3Ptr) | |
67 | { | |
68 | IPRT_LINUX_SAVE_EFL_AC(); | |
69 | bool fRc = access_ok(VERIFY_READ, (void *)R3Ptr, 1); | |
70 | IPRT_LINUX_RESTORE_EFL_AC(); | |
71 | return fRc; | |
72 | } | |
73 | RT_EXPORT_SYMBOL(RTR0MemUserIsValidAddr); | |
74 | ||
75 | ||
76 | RTR0DECL(bool) RTR0MemKernelIsValidAddr(void *pv) | |
77 | { | |
78 | /* Couldn't find a straight forward way of doing this... */ | |
79 | #if defined(RT_ARCH_X86) && defined(CONFIG_X86_HIGH_ENTRY) | |
80 | return true; /* ?? */ | |
81 | #elif defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64) | |
82 | return (uintptr_t)pv >= PAGE_OFFSET; | |
83 | #else | |
84 | # error "PORT ME" | |
85 | return !access_ok(VERIFY_READ, pv, 1); | |
86 | #endif | |
87 | } | |
88 | RT_EXPORT_SYMBOL(RTR0MemKernelIsValidAddr); | |
89 | ||
90 | ||
91 | RTR0DECL(bool) RTR0MemAreKrnlAndUsrDifferent(void) | |
92 | { | |
93 | #if defined(RT_ARCH_X86) && defined(CONFIG_X86_HIGH_ENTRY) /* ?? */ | |
94 | return false; | |
95 | #else | |
96 | return true; | |
97 | #endif | |
98 | } | |
99 | RT_EXPORT_SYMBOL(RTR0MemAreKrnlAndUsrDifferent); | |
100 | ||
101 | ||
102 | /** | |
103 | * Treats both source and destination as unsafe buffers. | |
104 | */ | |
105 | static int rtR0MemKernelCopyLnxWorker(void *pvDst, void const *pvSrc, size_t cb) | |
106 | { | |
107 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 55) | |
108 | /* _ASM_EXTABLE was introduced in 2.6.25 from what I can tell. Using #ifndef | |
109 | here since it has to be a macro and you never know what someone might have | |
110 | backported to an earlier kernel release. */ | |
111 | # ifndef _ASM_EXTABLE | |
112 | # if ARCH_BITS == 32 | |
113 | # define _ASM_EXTABLE(a_Instr, a_Resume) \ | |
114 | ".section __ex_table,\"a\"\n" \ | |
115 | ".balign 4\n" \ | |
116 | ".long " #a_Instr "\n" \ | |
117 | ".long " #a_Resume "\n" \ | |
118 | ".previous\n" | |
119 | # else | |
120 | # define _ASM_EXTABLE(a_Instr, a_Resume) \ | |
121 | ".section __ex_table,\"a\"\n" \ | |
122 | ".balign 8\n" \ | |
123 | ".quad " #a_Instr "\n" \ | |
124 | ".quad " #a_Resume "\n" \ | |
125 | ".previous\n" | |
126 | # endif | |
127 | # endif /* !_ASM_EXTABLE */ | |
128 | int rc; | |
129 | IPRT_LINUX_SAVE_EFL_AC(); /* paranoia */ | |
130 | if (!cb) | |
131 | return VINF_SUCCESS; | |
132 | ||
133 | __asm__ __volatile__ ("cld\n" | |
134 | "1:\n\t" | |
135 | "rep; movsb\n" | |
136 | "2:\n\t" | |
137 | ".section .fixup,\"ax\"\n" | |
138 | "3:\n\t" | |
139 | "movl %4, %0\n" | |
140 | ".previous\n" | |
141 | _ASM_EXTABLE(1b, 3b) | |
142 | : "=r" (rc), | |
143 | "=D" (pvDst), | |
144 | "=S" (pvSrc), | |
145 | "=c" (cb) | |
146 | : "i" (VERR_ACCESS_DENIED), | |
147 | "0" (VINF_SUCCESS), | |
148 | "1" (pvDst), | |
149 | "2" (pvSrc), | |
150 | "3" (cb) | |
151 | : "memory"); | |
152 | IPRT_LINUX_RESTORE_EFL_AC(); | |
153 | return rc; | |
154 | #else | |
155 | return VERR_NOT_SUPPORTED; | |
156 | #endif | |
157 | } | |
158 | ||
159 | ||
160 | RTR0DECL(int) RTR0MemKernelCopyFrom(void *pvDst, void const *pvSrc, size_t cb) | |
161 | { | |
162 | return rtR0MemKernelCopyLnxWorker(pvDst, pvSrc, cb); | |
163 | } | |
164 | RT_EXPORT_SYMBOL(RTR0MemKernelCopyFrom); | |
165 | ||
166 | ||
167 | RTR0DECL(int) RTR0MemKernelCopyTo(void *pvDst, void const *pvSrc, size_t cb) | |
168 | { | |
169 | return rtR0MemKernelCopyLnxWorker(pvDst, pvSrc, cb); | |
170 | } | |
171 | RT_EXPORT_SYMBOL(RTR0MemKernelCopyTo); | |
172 |