VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/solaris/krnlmod-solaris.cpp@ 98126

Last change on this file since 98126 was 98103, checked in by vboxsync, 22 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1/* $Id: krnlmod-solaris.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Kernel module, Linux.
4 */
5
6/*
7 * Copyright (C) 2017-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_SYSTEM
42#include <iprt/krnlmod.h>
43#include <iprt/asm.h>
44#include <iprt/assert.h>
45#include <iprt/dir.h>
46#include <iprt/errcore.h>
47#include <iprt/mem.h>
48#include <iprt/string.h>
49#include <iprt/types.h>
50
51#include <iprt/stream.h>
52
53#include <sys/modctl.h>
54#include <errno.h>
55
56/**
57 * Internal kernel information record state.
58 */
59typedef struct RTKRNLMODINFOINT
60{
61 /** Reference counter. */
62 volatile uint32_t cRefs;
63 /** Load address of the kernel module. */
64 RTR0UINTPTR uLoadAddr;
65 /** Size of the kernel module. */
66 size_t cbKrnlMod;
67 /** Size of the name in characters including the zero terminator. */
68 size_t cchName;
69 /** Module name - variable in size. */
70 char achName[1];
71} RTKRNLMODINFOINT;
72/** Pointer to the internal kernel module information record. */
73typedef RTKRNLMODINFOINT *PRTKRNLMODINFOINT;
74/** Pointer to a const internal kernel module information record. */
75typedef const RTKRNLMODINFOINT *PCRTKRNLMODINFOINT;
76
77
78
79/**
80 * Destroy the given kernel module information record.
81 *
82 * @returns nothing.
83 * @param pThis The record to destroy.
84 */
85static void rtKrnlModInfoDestroy(PRTKRNLMODINFOINT pThis)
86{
87 RTMemFree(pThis);
88}
89
90
91/**
92 * Creates a new kernel module information record for the given module.
93 *
94 * @returns IPRT status code.
95 * @param pModInfo The Solaris kernel module information.
96 * @param phKrnlModInfo Where to store the handle to the kernel module information record
97 * on success.
98 */
99static int rtKrnlModSolInfoCreate(struct modinfo *pModInfo, PRTKRNLMODINFO phKrnlModInfo)
100{
101 int rc = VINF_SUCCESS;
102 size_t cchName = strlen(&pModInfo->mi_name[0]) + 1;
103 PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTKRNLMODINFOINT, achName[cchName]));
104 if (RT_LIKELY(pThis))
105 {
106 memcpy(&pThis->achName[0], &pModInfo->mi_name[0], cchName);
107 pThis->cchName = cchName;
108 pThis->cRefs = 1;
109 pThis->cbKrnlMod = pModInfo->mi_size;
110 pThis->uLoadAddr = (RTR0UINTPTR)pModInfo->mi_base;
111
112 *phKrnlModInfo = pThis;
113 }
114 else
115 rc = VERR_NO_MEMORY;
116
117 return rc;
118}
119
120
121RTDECL(int) RTKrnlModQueryLoaded(const char *pszName, bool *pfLoaded)
122{
123 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
124 AssertPtrReturn(pfLoaded, VERR_INVALID_POINTER);
125
126 RTKRNLMODINFO hKrnlModInfo = NIL_RTKRNLMODINFO;
127 int rc = RTKrnlModLoadedQueryInfo(pszName, &hKrnlModInfo);
128 if (RT_SUCCESS(rc))
129 {
130 *pfLoaded = true;
131 RTKrnlModInfoRelease(hKrnlModInfo);
132 }
133 else if (rc == VERR_NOT_FOUND)
134 {
135 *pfLoaded = false;
136 rc = VINF_SUCCESS;
137 }
138
139 return rc;
140}
141
142
143RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
144{
145 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
146 AssertPtrReturn(phKrnlModInfo, VERR_INVALID_POINTER);
147
148 int rc = VERR_NOT_FOUND;
149 int iId = -1;
150 struct modinfo ModInfo;
151
152 ModInfo.mi_info = MI_INFO_ALL | MI_INFO_CNT;
153 ModInfo.mi_id = iId;
154 ModInfo.mi_nextid = iId;
155 do
156 {
157 int rcSol = modctl(MODINFO, iId, &ModInfo);
158 if (rcSol < 0)
159 {
160 rc = RTErrConvertFromErrno(errno);
161 break;
162 }
163
164 if (ModInfo.mi_id != -1)
165 {
166 ModInfo.mi_name[MODMAXNAMELEN - 1] = '\0'; /* Paranoia. */
167 if (!RTStrCmp(pszName, &ModInfo.mi_name[0]))
168 {
169 rc = rtKrnlModSolInfoCreate(&ModInfo, phKrnlModInfo);
170 break;
171 }
172 }
173
174 iId = ModInfo.mi_id;
175 } while (iId != -1);
176
177 return rc;
178}
179
180
181RTDECL(uint32_t) RTKrnlModLoadedGetCount(void)
182{
183 uint32_t cKmodsLoaded = 0;
184 int iId = -1;
185 struct modinfo ModInfo;
186
187 ModInfo.mi_info = MI_INFO_ALL | MI_INFO_CNT;
188 ModInfo.mi_id = iId;
189 ModInfo.mi_nextid = iId;
190 do
191 {
192 int rcSol = modctl(MODINFO, iId, &ModInfo);
193 if (rcSol < 0)
194 break;
195
196 cKmodsLoaded++;
197
198 iId = ModInfo.mi_id;
199 } while (iId != -1);
200
201 return cKmodsLoaded;
202}
203
204
205RTDECL(int) RTKrnlModLoadedQueryInfoAll(PRTKRNLMODINFO pahKrnlModInfo, uint32_t cEntriesMax,
206 uint32_t *pcEntries)
207{
208 if (cEntriesMax > 0)
209 AssertPtrReturn(pahKrnlModInfo, VERR_INVALID_POINTER);
210
211 uint32_t cKmodsLoaded = RTKrnlModLoadedGetCount();
212 if (cEntriesMax < cKmodsLoaded)
213 {
214 if (*pcEntries)
215 *pcEntries = cKmodsLoaded;
216 return VERR_BUFFER_OVERFLOW;
217 }
218
219 int rc = VINF_SUCCESS;
220 int iId = -1;
221 unsigned idxKrnlModInfo = 0;
222 struct modinfo ModInfo;
223
224 ModInfo.mi_info = MI_INFO_ALL | MI_INFO_CNT;
225 ModInfo.mi_id = iId;
226 ModInfo.mi_nextid = iId;
227 do
228 {
229 int rcSol = modctl(MODINFO, iId, &ModInfo);
230 if (rcSol < 0)
231 {
232 rc = RTErrConvertFromErrno(errno);
233 if (rc == VERR_INVALID_PARAMETER && idxKrnlModInfo > 0)
234 rc = VINF_SUCCESS;
235 break;
236 }
237
238 ModInfo.mi_name[MODMAXNAMELEN - 1] = '\0'; /* Paranoia. */
239 rc = rtKrnlModSolInfoCreate(&ModInfo, &pahKrnlModInfo[idxKrnlModInfo]);
240 if (RT_SUCCESS(rc))
241 idxKrnlModInfo++;
242
243 iId = ModInfo.mi_id;
244 } while (iId != -1);
245
246 if (RT_FAILURE(rc))
247 {
248 /* Rollback */
249 while (idxKrnlModInfo-- > 0)
250 RTKrnlModInfoRelease(pahKrnlModInfo[idxKrnlModInfo]);
251 }
252 else if (pcEntries)
253 *pcEntries = idxKrnlModInfo;
254
255 return rc;
256}
257
258
259RTDECL(uint32_t) RTKrnlModInfoRetain(RTKRNLMODINFO hKrnlModInfo)
260{
261 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
262 AssertPtrReturn(pThis, UINT32_MAX);
263
264 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
265 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
266 return cRefs;
267}
268
269
270RTDECL(uint32_t) RTKrnlModInfoRelease(RTKRNLMODINFO hKrnlModInfo)
271{
272 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
273 if (!pThis)
274 return 0;
275 AssertPtrReturn(pThis, UINT32_MAX);
276
277 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
278 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
279 if (cRefs == 0)
280 rtKrnlModInfoDestroy(pThis);
281 return cRefs;
282}
283
284
285RTDECL(uint32_t) RTKrnlModInfoGetRefCnt(RTKRNLMODINFO hKrnlModInfo)
286{
287 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
288 AssertPtrReturn(pThis, 0);
289
290 return 0;
291}
292
293
294RTDECL(const char *) RTKrnlModInfoGetName(RTKRNLMODINFO hKrnlModInfo)
295{
296 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
297 AssertPtrReturn(pThis, NULL);
298
299 return &pThis->achName[0];
300}
301
302
303RTDECL(const char *) RTKrnlModInfoGetFilePath(RTKRNLMODINFO hKrnlModInfo)
304{
305 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
306 AssertPtrReturn(pThis, NULL);
307
308 return NULL;
309}
310
311
312RTDECL(size_t) RTKrnlModInfoGetSize(RTKRNLMODINFO hKrnlModInfo)
313{
314 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
315 AssertPtrReturn(pThis, 0);
316
317 return pThis->cbKrnlMod;
318}
319
320
321RTDECL(RTR0UINTPTR) RTKrnlModInfoGetLoadAddr(RTKRNLMODINFO hKrnlModInfo)
322{
323 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
324 AssertPtrReturn(pThis, 0);
325
326 return pThis->uLoadAddr;
327}
328
329
330RTDECL(int) RTKrnlModInfoQueryRefModInfo(RTKRNLMODINFO hKrnlModInfo, uint32_t idx,
331 PRTKRNLMODINFO phKrnlModInfoRef)
332{
333 RT_NOREF3(hKrnlModInfo, idx, phKrnlModInfoRef);
334 return VERR_NOT_IMPLEMENTED;
335}
336
337
338RTDECL(int) RTKrnlModLoadByName(const char *pszName)
339{
340 AssertPtrReturn(pszName, VERR_INVALID_PARAMETER);
341
342 return VERR_NOT_SUPPORTED;
343}
344
345
346RTDECL(int) RTKrnlModLoadByPath(const char *pszPath)
347{
348 AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);
349
350 return VERR_NOT_SUPPORTED;
351}
352
353
354RTDECL(int) RTKrnlModUnloadByName(const char *pszName)
355{
356 AssertPtrReturn(pszName, VERR_INVALID_PARAMETER);
357
358 return VERR_NOT_SUPPORTED;
359}
Note: See TracBrowser for help on using the repository browser.

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