VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/krnlmod-linux.cpp@ 98103

Last change on this file since 98103 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.6 KB
Line 
1/* $Id: krnlmod-linux.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/linux/sysfs.h>
44#include <iprt/asm.h>
45#include <iprt/assert.h>
46#include <iprt/dir.h>
47#include <iprt/err.h>
48#include <iprt/mem.h>
49#include <iprt/string.h>
50#include <iprt/types.h>
51
52
53/**
54 * Internal kernel information record state.
55 */
56typedef struct RTKRNLMODINFOINT
57{
58 /** Reference counter. */
59 volatile uint32_t cRefs;
60 /** Reference count for the kernel module. */
61 uint32_t cRefKrnlMod;
62 /** Load address of the kernel module. */
63 RTR0UINTPTR uLoadAddr;
64 /** Size of the kernel module. */
65 size_t cbKrnlMod;
66 /** Size of the name in characters including the zero terminator. */
67 size_t cchName;
68 /** Module name - variable in size. */
69 char achName[1];
70} RTKRNLMODINFOINT;
71/** Pointer to the internal kernel module information record. */
72typedef RTKRNLMODINFOINT *PRTKRNLMODINFOINT;
73/** Pointer to a const internal kernel module information record. */
74typedef const RTKRNLMODINFOINT *PCRTKRNLMODINFOINT;
75
76
77
78/**
79 * Destroy the given kernel module information record.
80 *
81 * @returns nothing.
82 * @param pThis The record to destroy.
83 */
84static void rtKrnlModInfoDestroy(PRTKRNLMODINFOINT pThis)
85{
86 RTMemFree(pThis);
87}
88
89
90static int rtKrnlModLinuxReadIntFileDef(unsigned uBase, int64_t *pi64, int64_t i64Def,
91 const char *pszName, const char *pszPath)
92{
93 int rc = RTLinuxSysFsReadIntFile(uBase, pi64, "module/%s/%s", pszName, pszPath);
94 if (rc == VERR_FILE_NOT_FOUND)
95 {
96 *pi64 = i64Def;
97 rc = VINF_SUCCESS;
98 }
99
100 return rc;
101}
102
103/**
104 * Creates a new kernel module information record for the given module.
105 *
106 * @returns IPRT status code.
107 * @param pszName The kernel module name.
108 * @param phKrnlModInfo Where to store the handle to the kernel module information record
109 * on success.
110 */
111static int rtKrnlModLinuxInfoCreate(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
112{
113 int rc = VINF_SUCCESS;
114 size_t cchName = strlen(pszName) + 1;
115 PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTKRNLMODINFOINT, achName[cchName]));
116 if (RT_LIKELY(pThis))
117 {
118 memcpy(&pThis->achName[0], pszName, cchName);
119 pThis->cchName = cchName;
120 pThis->cRefs = 1;
121
122 int64_t iTmp = 0;
123 rc = rtKrnlModLinuxReadIntFileDef(10, &iTmp, 0, pszName, "refcnt");
124 if (RT_SUCCESS(rc))
125 pThis->cRefKrnlMod = (uint32_t)iTmp;
126
127 rc = rtKrnlModLinuxReadIntFileDef(10, &iTmp, 0, pszName, "coresize");
128 if (RT_SUCCESS(rc))
129 pThis->cbKrnlMod = iTmp;
130
131 rc = rtKrnlModLinuxReadIntFileDef(16, &iTmp, 0, pszName, "sections/.text");
132 if (RT_SUCCESS(rc))
133 pThis->uLoadAddr = iTmp;
134
135 if (RT_SUCCESS(rc))
136 *phKrnlModInfo = pThis;
137 else
138 RTMemFree(pThis);
139 }
140 else
141 rc = VERR_NO_MEMORY;
142
143 return rc;
144}
145
146
147RTDECL(int) RTKrnlModQueryLoaded(const char *pszName, bool *pfLoaded)
148{
149 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
150 AssertPtrReturn(pfLoaded, VERR_INVALID_POINTER);
151
152 int rc = RTLinuxSysFsExists("module/%s", pszName);
153 if (rc == VINF_SUCCESS)
154 *pfLoaded = true;
155 else if (rc == VERR_FILE_NOT_FOUND)
156 {
157 *pfLoaded = false;
158 rc = VINF_SUCCESS;
159 }
160
161 return rc;
162}
163
164
165RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
166{
167 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
168 AssertPtrReturn(phKrnlModInfo, VERR_INVALID_POINTER);
169
170 int rc = RTLinuxSysFsExists("module/%s", pszName);
171 if (rc == VINF_SUCCESS)
172 rc = rtKrnlModLinuxInfoCreate(pszName, phKrnlModInfo);
173 else if (rc == VERR_FILE_NOT_FOUND)
174 rc = VERR_NOT_FOUND;
175
176 return rc;
177}
178
179
180RTDECL(uint32_t) RTKrnlModLoadedGetCount(void)
181{
182 uint32_t cKmodsLoaded = 0;
183
184 RTDIR hDir = NULL;
185 int rc = RTDirOpen(&hDir, "/sys/module");
186 if (RT_SUCCESS(rc))
187 {
188 RTDIRENTRY DirEnt;
189 rc = RTDirRead(hDir, &DirEnt, NULL);
190 while (RT_SUCCESS(rc))
191 {
192 if (!RTDirEntryIsStdDotLink(&DirEnt))
193 cKmodsLoaded++;
194 rc = RTDirRead(hDir, &DirEnt, NULL);
195 }
196
197 RTDirClose(hDir);
198 }
199
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 RTDIR hDir = NULL;
220 int rc = RTDirOpen(&hDir, "/sys/module");
221 if (RT_SUCCESS(rc))
222 {
223 unsigned idxKrnlModInfo = 0;
224 RTDIRENTRY DirEnt;
225
226 rc = RTDirRead(hDir, &DirEnt, NULL);
227 while (RT_SUCCESS(rc))
228 {
229 if (!RTDirEntryIsStdDotLink(&DirEnt))
230 {
231 rc = rtKrnlModLinuxInfoCreate(DirEnt.szName, &pahKrnlModInfo[idxKrnlModInfo]);
232 if (RT_SUCCESS(rc))
233 idxKrnlModInfo++;
234 }
235
236 if (RT_SUCCESS(rc))
237 rc = RTDirRead(hDir, &DirEnt, NULL);
238 }
239
240 if (rc == VERR_NO_MORE_FILES)
241 rc = VINF_SUCCESS;
242 else if (RT_FAILURE(rc))
243 {
244 /* Rollback */
245 while (idxKrnlModInfo-- > 0)
246 RTKrnlModInfoRelease(pahKrnlModInfo[idxKrnlModInfo]);
247 }
248
249 if (*pcEntries)
250 *pcEntries = cKmodsLoaded;
251
252 RTDirClose(hDir);
253 }
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 pThis->cRefKrnlMod;
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