My favorites | Sign in
Project Home Downloads Wiki Issues Source
Repository:
Checkout   Browse   Changes   Clones  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* module_ms_alloc.c - API to allocate and deallocate memory in the
* module mapping space. */

/* ========================================================================
* Copyright (C) 2012, KEDR development team
* Authors:
* Eugene A. Shatokhin <spectre@ispras.ru>
* Andrey V. Tsyvarev <tsyvarev@ispras.ru>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
======================================================================== */

#include <linux/kernel.h>
#include <linux/kallsyms.h>
#include <linux/errno.h>
#include <linux/string.h>

#include "core_impl.h"
#include "module_ms_alloc.h"

/* ====================================================================== */
/* It is needed to allocate memory close enough to the areas occupied by
* the kernel modules (within +/- 2Gb). Otherwise, RIP-relative addressing
* could be a problem on x86-64. It is used, for example, when the module
* accesses its global data.
*
* For now, I cannot see a good way to ensure the memory is allocated
* properly.
* It seems from the memory layout (Documentation/x86/x86_64/mm.txt) that
* the only way is to use memory mapped to exactly the same region of
* addresses where the modules reside. The most clear way I currently see is
* to use module_alloc() like the module loader and kernel probes do.
*
* Of course, that function is not exported and was never meant to. I look
* for its address via kallsyms subsystem and use this address then. This
* is an "ugly hack" and will definitely be frowned upon by kernel
* developers.
* I hope I will find a better way in the future. */

void *(*module_alloc_func)(unsigned long) = NULL;
void (*module_free_func)(struct module *, void *) = NULL;
/* ====================================================================== */

/* This function will be called for each symbol known to the system.
* We need to find only the particular functions.
*
* If this function returns 0, kallsyms_on_each_symbol() will continue
* walking the symbols. If non-zero - it will stop. */
static int
symbol_walk_callback(void *data, const char *name, struct module *mod,
unsigned long addr)
{
/* Skip the symbol if it belongs to a module rather than to
* the kernel proper. */
if (mod != NULL)
return 0;

if (strcmp(name, "module_alloc") == 0) {
if (module_alloc_func != NULL) {
pr_warning(KEDR_MSG_PREFIX
"Found two \"module_alloc\" symbols in the kernel, unable to continue\n");
return -EFAULT;
}
module_alloc_func = (void *(*)(unsigned long))addr;
} else if (strcmp(name, "module_free") == 0) {
if (module_free_func != NULL) {
pr_warning(KEDR_MSG_PREFIX
"Found two \"module_free\" symbols in the kernel, unable to continue\n");
return -EFAULT;
}
module_free_func = (void (*)(struct module *, void *))addr;
}
return 0;
}

/* ====================================================================== */
int
kedr_init_module_ms_alloc(void)
{
int ret = kallsyms_on_each_symbol(symbol_walk_callback, NULL);
if (ret)
return ret;

if (module_alloc_func == NULL) {
pr_warning(KEDR_MSG_PREFIX
"Unable to find \"module_alloc\" function\n");
return -EFAULT;
}

if (module_free_func == NULL) {
pr_warning(KEDR_MSG_PREFIX
"Unable to find \"module_free\" function\n");
return -EFAULT;
}

return 0; /* success */
}

void
kedr_cleanup_module_ms_alloc(void)
{
module_alloc_func = NULL;
module_free_func = NULL;
}

void *
kedr_module_alloc(unsigned long size)
{
BUG_ON(module_alloc_func == NULL);
return module_alloc_func(size);
}

void
kedr_module_free(void *buf)
{
BUG_ON(module_free_func == NULL);
if (buf != NULL)
module_free_func(NULL, buf);
}
/* ====================================================================== */

Change log

75110e40c6c0 by Eugene A. Shatokhin <euspectre> on Mar 28, 2012   Diff
core: Added a simple event reporter module
for testing and debugging
Go to: 

Older revisions

408faeb33f84 by Eugene A. Shatokhin <euspectre> on Feb 9, 2012   Diff
core: Added the subsystem for memory
allocation from module mapping space
All revisions of this file

File info

Size: 3887 bytes, 122 lines
Powered by Google Project Hosting