5 |
* |
* |
6 |
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
7 |
*/ |
*/ |
|
|
|
8 |
#include "modutils.h" |
#include "modutils.h" |
9 |
|
|
10 |
#ifdef __UCLIBC__ |
#ifdef __UCLIBC__ |
16 |
# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) |
# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) |
17 |
#endif |
#endif |
18 |
|
|
|
USE_FEATURE_2_4_MODULES(char *insmod_outputname); |
|
|
|
|
|
/* |
|
|
a libbb candidate from ice age! |
|
|
*/ |
|
|
llist_t FAST_FUNC *llist_find(llist_t *first, const char *str) |
|
|
{ |
|
|
while (first != NULL) { |
|
|
if (strcmp(first->data, str) == 0) |
|
|
return first; |
|
|
first = first->link; |
|
|
} |
|
|
return NULL; |
|
|
} |
|
|
|
|
19 |
void FAST_FUNC replace(char *s, char what, char with) |
void FAST_FUNC replace(char *s, char what, char with) |
20 |
{ |
{ |
21 |
while (*s) { |
while (*s) { |
25 |
} |
} |
26 |
} |
} |
27 |
|
|
28 |
char * FAST_FUNC replace_underscores(char *s) |
char* FAST_FUNC replace_underscores(char *s) |
29 |
{ |
{ |
30 |
replace(s, '-', '_'); |
replace(s, '-', '_'); |
31 |
return s; |
return s; |
45 |
return len; |
return len; |
46 |
} |
} |
47 |
|
|
48 |
char * FAST_FUNC filename2modname(const char *filename, char *modname) |
char* FAST_FUNC filename2modname(const char *filename, char *modname) |
49 |
{ |
{ |
50 |
int i; |
int i; |
51 |
char *from; |
char *from; |
57 |
from = bb_get_last_path_component_nostrip(filename); |
from = bb_get_last_path_component_nostrip(filename); |
58 |
for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) |
for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) |
59 |
modname[i] = (from[i] == '-') ? '_' : from[i]; |
modname[i] = (from[i] == '-') ? '_' : from[i]; |
60 |
modname[i] = 0; |
modname[i] = '\0'; |
61 |
|
|
62 |
return modname; |
return modname; |
63 |
} |
} |
64 |
|
|
65 |
const char * FAST_FUNC moderror(int err) |
char* FAST_FUNC parse_cmdline_module_options(char **argv) |
|
{ |
|
|
switch (err) { |
|
|
case -1: |
|
|
return "no such module"; |
|
|
case ENOEXEC: |
|
|
return "invalid module format"; |
|
|
case ENOENT: |
|
|
return "unknown symbol in module, or unknown parameter"; |
|
|
case ESRCH: |
|
|
return "module has wrong symbol version"; |
|
|
case ENOSYS: |
|
|
return "kernel does not support requested operation"; |
|
|
default: |
|
|
return strerror(err); |
|
|
} |
|
|
} |
|
|
|
|
|
char * FAST_FUNC parse_cmdline_module_options(char **argv) |
|
66 |
{ |
{ |
67 |
char *options; |
char *options; |
68 |
int optlen; |
int optlen; |
77 |
return options; |
return options; |
78 |
} |
} |
79 |
|
|
80 |
|
#if ENABLE_FEATURE_INSMOD_TRY_MMAP |
81 |
|
void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p) |
82 |
|
{ |
83 |
|
/* We have user reports of failure to load 3MB module |
84 |
|
* on a 16MB RAM machine. Apparently even a transient |
85 |
|
* memory spike to 6MB during module load |
86 |
|
* is too big for that system. */ |
87 |
|
void *image; |
88 |
|
struct stat st; |
89 |
|
int fd; |
90 |
|
|
91 |
|
fd = xopen(filename, O_RDONLY); |
92 |
|
fstat(fd, &st); |
93 |
|
image = NULL; |
94 |
|
/* st.st_size is off_t, we can't just pass it to mmap */ |
95 |
|
if (st.st_size <= *image_size_p) { |
96 |
|
size_t image_size = st.st_size; |
97 |
|
image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0); |
98 |
|
if (image == MAP_FAILED) { |
99 |
|
image = NULL; |
100 |
|
} else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) { |
101 |
|
/* No ELF signature. Compressed module? */ |
102 |
|
munmap(image, image_size); |
103 |
|
image = NULL; |
104 |
|
} else { |
105 |
|
/* Success. Report the size */ |
106 |
|
*image_size_p = image_size; |
107 |
|
} |
108 |
|
} |
109 |
|
close(fd); |
110 |
|
return image; |
111 |
|
} |
112 |
|
#endif |
113 |
|
|
114 |
|
/* Return: |
115 |
|
* 0 on success, |
116 |
|
* -errno on open/read error, |
117 |
|
* errno on init_module() error |
118 |
|
*/ |
119 |
int FAST_FUNC bb_init_module(const char *filename, const char *options) |
int FAST_FUNC bb_init_module(const char *filename, const char *options) |
120 |
{ |
{ |
121 |
size_t len = MAXINT(ssize_t); |
size_t image_size; |
122 |
char *image; |
char *image; |
123 |
int rc = ENOENT; |
int rc; |
124 |
|
bool mmaped; |
125 |
|
|
126 |
|
if (!options) |
127 |
|
options = ""; |
128 |
|
|
129 |
|
//TODO: audit bb_init_module_24 to match error code convention |
130 |
#if ENABLE_FEATURE_2_4_MODULES |
#if ENABLE_FEATURE_2_4_MODULES |
131 |
if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) |
if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) |
132 |
return bb_init_module_24(filename, options); |
return bb_init_module_24(filename, options); |
133 |
#endif |
#endif |
134 |
|
|
135 |
/* Use the 2.6 way */ |
image_size = INT_MAX - 4095; |
136 |
image = xmalloc_open_zipped_read_close(filename, &len); |
mmaped = 0; |
137 |
|
image = try_to_mmap_module(filename, &image_size); |
138 |
if (image) { |
if (image) { |
139 |
if (init_module(image, len, options) != 0) |
mmaped = 1; |
140 |
rc = errno; |
} else { |
141 |
else |
errno = ENOMEM; /* may be changed by e.g. open errors below */ |
142 |
rc = 0; |
image = xmalloc_open_zipped_read_close(filename, &image_size); |
143 |
free(image); |
if (!image) |
144 |
|
return -errno; |
145 |
} |
} |
146 |
|
|
147 |
|
errno = 0; |
148 |
|
init_module(image, image_size, options); |
149 |
|
rc = errno; |
150 |
|
if (mmaped) |
151 |
|
munmap(image, image_size); |
152 |
|
else |
153 |
|
free(image); |
154 |
return rc; |
return rc; |
155 |
} |
} |
156 |
|
|
157 |
int FAST_FUNC bb_delete_module(const char *module, unsigned int flags) |
int FAST_FUNC bb_delete_module(const char *module, unsigned int flags) |
158 |
{ |
{ |
159 |
return delete_module(module, flags); |
errno = 0; |
160 |
|
delete_module(module, flags); |
161 |
|
return errno; |
162 |
|
} |
163 |
|
|
164 |
|
const char* FAST_FUNC moderror(int err) |
165 |
|
{ |
166 |
|
switch (err) { |
167 |
|
case -1: /* btw: it's -EPERM */ |
168 |
|
return "no such module"; |
169 |
|
case ENOEXEC: |
170 |
|
return "invalid module format"; |
171 |
|
case ENOENT: |
172 |
|
return "unknown symbol in module, or unknown parameter"; |
173 |
|
case ESRCH: |
174 |
|
return "module has wrong symbol version"; |
175 |
|
case ENOSYS: |
176 |
|
return "kernel does not support requested operation"; |
177 |
|
} |
178 |
|
if (err < 0) /* should always be */ |
179 |
|
err = -err; |
180 |
|
return strerror(err); |
181 |
} |
} |