VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp@ 11725

最後變更 在這個檔案從11725是 11725,由 vboxsync 提交於 17 年 前

#3076: Merged in the branch with the alternate driver authentication method. (34468:HEAD)

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 7.2 KB
 
1/* $Id: SUPLib-linux.cpp 11725 2008-08-27 22:21:47Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - GNU/Linux specific parts.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#define LOG_GROUP LOG_GROUP_SUP
35#ifdef IN_SUP_HARDENED_R3
36# undef DEBUG /* Warning: disables RT_STRICT */
37# define LOG_DISABLED
38 /** @todo RTLOGREL_DISABLED */
39# include <iprt/log.h>
40# undef LogRelIt
41# define LogRelIt(pvInst, fFlags, iGroup, fmtargs) do { } while (0)
42#endif
43
44#include <sys/fcntl.h>
45#include <sys/ioctl.h>
46#include <sys/mman.h>
47#include <errno.h>
48#include <unistd.h>
49#include <stdlib.h>
50#include <malloc.h>
51
52#include <VBox/log.h>
53#include <VBox/sup.h>
54#include <iprt/path.h>
55#include <iprt/assert.h>
56#include <VBox/types.h>
57#include <iprt/string.h>
58#include <VBox/err.h>
59#include <VBox/param.h>
60#include "../SUPLibInternal.h"
61#include "../SUPDrvIOC.h"
62
63
64/*******************************************************************************
65* Defined Constants And Macros *
66*******************************************************************************/
67/** Unix Device name. */
68#define DEVICE_NAME "/dev/vboxdrv"
69
70/* define MADV_DONTFORK if it's missing from the system headers. */
71#ifndef MADV_DONTFORK
72# define MADV_DONTFORK 10
73#endif
74
75
76
77int suplibOsInit(PSUPLIBDATA pThis, bool fPreInited)
78{
79 /*
80 * Nothing to do if pre-inited.
81 */
82 if (fPreInited)
83 return VINF_SUCCESS;
84
85 /*
86 * Check if madvise works.
87 */
88 void *pv = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
89 if (pv == MAP_FAILED)
90 return VERR_NO_MEMORY;
91 pThis->fSysMadviseWorks = (0 == madvise(pv, PAGE_SIZE, MADV_DONTFORK));
92 munmap(pv, PAGE_SIZE);
93
94 /*
95 * Try open the device.
96 */
97 pThis->hDevice = open(DEVICE_NAME, O_RDWR, 0);
98 if (pThis->hDevice < 0)
99 {
100 /*
101 * Try load the device.
102 */
103 pThis->hDevice = open(DEVICE_NAME, O_RDWR, 0);
104 if (pThis->hDevice < 0)
105 {
106 int rc;
107 switch (errno)
108 {
109 case ENXIO: /* see man 2 open, ENODEV is actually a kernel bug */
110 case ENODEV: rc = VERR_VM_DRIVER_LOAD_ERROR; break;
111 case EPERM:
112 case EACCES: rc = VERR_VM_DRIVER_NOT_ACCESSIBLE; break;
113 case ENOENT: rc = VERR_VM_DRIVER_NOT_INSTALLED; break;
114 default: rc = VERR_VM_DRIVER_OPEN_ERROR; break;
115 }
116 LogRel(("Failed to open \"%s\", errno=%d, rc=%Vrc\n", DEVICE_NAME, errno, rc));
117 return rc;
118 }
119 }
120
121 /*
122 * Mark the file handle close on exec.
123 */
124 if (fcntl(pThis->hDevice, F_SETFD, FD_CLOEXEC) == -1)
125 {
126 close(pThis->hDevice);
127 pThis->hDevice = -1;
128#ifdef IN_SUP_HARDENED_R3
129 return VERR_INTERNAL_ERROR;
130#else
131 return RTErrConvertFromErrno(errno);
132#endif
133 }
134
135 /*
136 * We're done.
137 */
138 return VINF_SUCCESS;
139}
140
141
142#ifndef IN_SUP_HARDENED_R3
143
144int suplibOsTerm(PSUPLIBDATA pThis)
145{
146 /*
147 * Check if we're initited at all.
148 */
149 if (pThis->hDevice >= 0)
150 {
151 if (close(pThis->hDevice))
152 AssertFailed();
153 pThis->hDevice = -1;
154 }
155
156 return 0;
157}
158
159
160int suplibOsInstall(void)
161{
162 // nothing to do on Linux
163 return VERR_NOT_IMPLEMENTED;
164}
165
166
167int suplibOsUninstall(void)
168{
169 // nothing to do on Linux
170 return VERR_NOT_IMPLEMENTED;
171}
172
173
174int suplibOsIOCtl(PSUPLIBDATA pThis, uintptr_t uFunction, void *pvReq, size_t cbReq)
175{
176 AssertMsg(pThis->hDevice != NIL_RTFILE, ("SUPLIB not initiated successfully!\n"));
177
178 /*
179 * Issue device iocontrol.
180 */
181 if (RT_LIKELY(ioctl(pThis->hDevice, uFunction, pvReq) >= 0))
182 return VINF_SUCCESS;
183
184 /* This is the reverse operation of the one found in SUPDrv-linux.c */
185 switch (errno)
186 {
187 case EACCES: return VERR_GENERAL_FAILURE;
188 case EINVAL: return VERR_INVALID_PARAMETER;
189 case EILSEQ: return VERR_INVALID_MAGIC;
190 case ENXIO: return VERR_INVALID_HANDLE;
191 case EFAULT: return VERR_INVALID_POINTER;
192 case ENOLCK: return VERR_LOCK_FAILED;
193 case EEXIST: return VERR_ALREADY_LOADED;
194 case EPERM: return VERR_PERMISSION_DENIED;
195 case ENOSYS: return VERR_VERSION_MISMATCH;
196 case 1000: return VERR_IDT_FAILED;
197 }
198
199 return RTErrConvertFromErrno(errno);
200}
201
202
203int suplibOsIOCtlFast(PSUPLIBDATA pThis, uintptr_t uFunction)
204{
205 int rc = ioctl(pThis->hDevice, uFunction, NULL);
206 if (rc == -1)
207 rc = -errno;
208 return rc;
209}
210
211
212int suplibOsPageAlloc(PSUPLIBDATA pThis, size_t cPages, void **ppvPages)
213{
214 size_t cbMmap = (pThis->fSysMadviseWorks ? cPages : cPages + 2) << PAGE_SHIFT;
215 char *pvPages = (char *)mmap(NULL, cbMmap, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
216 if (pvPages == MAP_FAILED)
217 return VERR_NO_MEMORY;
218
219 if (pThis->fSysMadviseWorks)
220 {
221 /*
222 * It is not fatal if we fail here but a forked child (e.g. the ALSA sound server)
223 * could crash. Linux < 2.6.16 does not implement madvise(MADV_DONTFORK) but the
224 * kernel seems to split bigger VMAs and that is all that we want -- later we set the
225 * VM_DONTCOPY attribute in supdrvOSLockMemOne().
226 */
227 if (madvise (pvPages, cbMmap, MADV_DONTFORK))
228 LogRel(("SUPLib: madvise %p-%p failed\n", pvPages, cbMmap));
229 *ppvPages = pvPages;
230 }
231 else
232 {
233 /*
234 * madvise(MADV_DONTFORK) is not available (most probably Linux 2.4). Enclose any
235 * mmapped region by two unmapped pages to guarantee that there is exactly one VM
236 * area struct of the very same size as the mmap area.
237 */
238 mprotect(pvPages, PAGE_SIZE, PROT_NONE);
239 mprotect(pvPages + cbMmap - PAGE_SIZE, PAGE_SIZE, PROT_NONE);
240 *ppvPages = pvPages + PAGE_SIZE;
241 }
242 memset(*ppvPages, 0, cPages << PAGE_SHIFT);
243 return VINF_SUCCESS;
244}
245
246
247int suplibOsPageFree(PSUPLIBDATA pThis, void *pvPages, size_t cPages)
248{
249 munmap(pvPages, cPages << PAGE_SHIFT);
250 return VINF_SUCCESS;
251}
252
253#endif /* !IN_SUP_HARDENED_R3 */
254
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette