insmod: code shrink, stop exporting insmod_ng_main.
function old new delta add_ksymoops_symbols - 421 +421 static.section_names 20 40 +20 lsmod_main 425 424 -1 set_tainted 153 150 -3 main_opts 4 - -4 obj_symbol_patch 47 42 -5 obj_string_patch 144 139 -5 already_loaded 144 138 -6 check_dep 348 341 -7 append_option 75 68 -7 obj_allocate_commons 515 501 -14 new_process_module_arguments 1039 1018 -21 arch_new_symbol 31 9 -22 check_module_name_match 85 61 -24 obj_create_alloced_section 164 136 -28 include_conf 930 902 -28 modprobe_main 1643 1535 -108 obj_load 924 777 -147 insmod_ng_main 245 - -245 insmod_main 4122 3794 -328 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 1/16 up/down: 441/-1003) Total: -562 bytes text data bss dec hex filename 776020 974 9420 786414 bffee busybox_old 775384 974 9420 785778 bfd72 busybox_unstripped
This commit is contained in:
parent
9d1afdb571
commit
b68979aefa
@ -18,7 +18,8 @@ char *xmalloc_readlink(const char *path)
|
|||||||
int bufsize = 0, readsize = 0;
|
int bufsize = 0, readsize = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
buf = xrealloc(buf, bufsize += GROWBY);
|
bufsize += GROWBY;
|
||||||
|
buf = xrealloc(buf, bufsize);
|
||||||
readsize = readlink(path, buf, bufsize);
|
readsize = readlink(path, buf, bufsize);
|
||||||
if (readsize == -1) {
|
if (readsize == -1) {
|
||||||
free(buf);
|
free(buf);
|
||||||
|
@ -67,17 +67,14 @@
|
|||||||
#define ENABLE_FEATURE_2_4_MODULES 1
|
#define ENABLE_FEATURE_2_4_MODULES 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !ENABLE_FEATURE_2_4_MODULES
|
/*
|
||||||
#define insmod_ng_main insmod_main
|
* Big piece of 2.4-specific code
|
||||||
#endif
|
*/
|
||||||
|
|
||||||
#if ENABLE_FEATURE_2_6_MODULES
|
|
||||||
extern int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_2_4_MODULES
|
#if ENABLE_FEATURE_2_4_MODULES
|
||||||
|
|
||||||
|
#if ENABLE_FEATURE_2_6_MODULES
|
||||||
|
static int insmod_ng_main(int argc, char **argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_FEATURE_INSMOD_LOADINKMEM
|
#if ENABLE_FEATURE_INSMOD_LOADINKMEM
|
||||||
#define LOADBITS 0
|
#define LOADBITS 0
|
||||||
@ -85,7 +82,6 @@ extern int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
|||||||
#define LOADBITS 1
|
#define LOADBITS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Alpha */
|
/* Alpha */
|
||||||
#if defined(__alpha__)
|
#if defined(__alpha__)
|
||||||
#define MATCH_MACHINE(x) (x == EM_ALPHA)
|
#define MATCH_MACHINE(x) (x == EM_ALPHA)
|
||||||
@ -627,13 +623,13 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
|
|||||||
|
|
||||||
static void *obj_extend_section(struct obj_section *sec, unsigned long more);
|
static void *obj_extend_section(struct obj_section *sec, unsigned long more);
|
||||||
|
|
||||||
static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
||||||
const char *string);
|
const char *string);
|
||||||
|
|
||||||
static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
||||||
struct obj_symbol *sym);
|
struct obj_symbol *sym);
|
||||||
|
|
||||||
static int obj_check_undefineds(struct obj_file *f);
|
static void obj_check_undefineds(struct obj_file *f);
|
||||||
|
|
||||||
static void obj_allocate_commons(struct obj_file *f);
|
static void obj_allocate_commons(struct obj_file *f);
|
||||||
|
|
||||||
@ -788,7 +784,6 @@ static size_t nksyms;
|
|||||||
static struct external_module *ext_modules;
|
static struct external_module *ext_modules;
|
||||||
static int n_ext_modules;
|
static int n_ext_modules;
|
||||||
static int n_ext_modules_used;
|
static int n_ext_modules_used;
|
||||||
extern int delete_module(const char *);
|
|
||||||
|
|
||||||
static char *m_filename;
|
static char *m_filename;
|
||||||
static char *m_fullName;
|
static char *m_fullName;
|
||||||
@ -801,19 +796,16 @@ static int check_module_name_match(const char *filename, struct stat *statbuf,
|
|||||||
void *userdata, int depth)
|
void *userdata, int depth)
|
||||||
{
|
{
|
||||||
char *fullname = (char *) userdata;
|
char *fullname = (char *) userdata;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
if (fullname[0] == '\0')
|
if (fullname[0] == '\0')
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else {
|
|
||||||
char *tmp, *tmp1 = xstrdup(filename);
|
tmp = bb_get_last_path_component_nostrip(filename);
|
||||||
tmp = bb_get_last_path_component_nostrip(tmp1);
|
if (strcmp(tmp, fullname) == 0) {
|
||||||
if (strcmp(tmp, fullname) == 0) {
|
/* Stop searching if we find a match */
|
||||||
free(tmp1);
|
m_filename = xstrdup(filename);
|
||||||
/* Stop searching if we find a match */
|
return FALSE;
|
||||||
m_filename = xstrdup(filename);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
free(tmp1);
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -824,25 +816,19 @@ static int check_module_name_match(const char *filename, struct stat *statbuf,
|
|||||||
static struct obj_file *arch_new_file(void)
|
static struct obj_file *arch_new_file(void)
|
||||||
{
|
{
|
||||||
struct arch_file *f;
|
struct arch_file *f;
|
||||||
f = xmalloc(sizeof(*f));
|
f = xzalloc(sizeof(*f));
|
||||||
|
return &f->root; /* it's a first member */
|
||||||
memset(f, 0, sizeof(*f));
|
|
||||||
|
|
||||||
return &f->root;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct obj_section *arch_new_section(void)
|
static struct obj_section *arch_new_section(void)
|
||||||
{
|
{
|
||||||
return xmalloc(sizeof(struct obj_section));
|
return xzalloc(sizeof(struct obj_section));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct obj_symbol *arch_new_symbol(void)
|
static struct obj_symbol *arch_new_symbol(void)
|
||||||
{
|
{
|
||||||
struct arch_symbol *sym;
|
struct arch_symbol *sym;
|
||||||
sym = xmalloc(sizeof(*sym));
|
sym = xzalloc(sizeof(*sym));
|
||||||
|
|
||||||
memset(sym, 0, sizeof(*sym));
|
|
||||||
|
|
||||||
return &sym->root;
|
return &sym->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2210,7 +2196,6 @@ static struct obj_section *obj_create_alloced_section(struct obj_file *f,
|
|||||||
f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
|
f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
|
||||||
f->sections[newidx] = sec = arch_new_section();
|
f->sections[newidx] = sec = arch_new_section();
|
||||||
|
|
||||||
memset(sec, 0, sizeof(*sec));
|
|
||||||
sec->header.sh_type = SHT_PROGBITS;
|
sec->header.sh_type = SHT_PROGBITS;
|
||||||
sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
|
sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
|
||||||
sec->header.sh_size = size;
|
sec->header.sh_size = size;
|
||||||
@ -2236,7 +2221,6 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
|
|||||||
f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
|
f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
|
||||||
f->sections[newidx] = sec = arch_new_section();
|
f->sections[newidx] = sec = arch_new_section();
|
||||||
|
|
||||||
memset(sec, 0, sizeof(*sec));
|
|
||||||
sec->header.sh_type = SHT_PROGBITS;
|
sec->header.sh_type = SHT_PROGBITS;
|
||||||
sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
|
sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
|
||||||
sec->header.sh_size = size;
|
sec->header.sh_size = size;
|
||||||
@ -2398,7 +2382,7 @@ static char *get_modinfo_value(struct obj_file *f, const char *key)
|
|||||||
/*======================================================================*/
|
/*======================================================================*/
|
||||||
/* Functions relating to module loading after 2.1.18. */
|
/* Functions relating to module loading after 2.1.18. */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
||||||
{
|
{
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
@ -2408,7 +2392,8 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
|||||||
int min, max, n;
|
int min, max, n;
|
||||||
|
|
||||||
p = *argv;
|
p = *argv;
|
||||||
if ((q = strchr(p, '=')) == NULL) {
|
q = strchr(p, '=');
|
||||||
|
if (q == NULL) {
|
||||||
argc--;
|
argc--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2421,8 +2406,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
|||||||
p = get_modinfo_value(f, key);
|
p = get_modinfo_value(f, key);
|
||||||
key += 5;
|
key += 5;
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
bb_error_msg("invalid parameter %s", key);
|
bb_error_msg_and_die("invalid parameter %s", key);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SYMBOL_PREFIX
|
#ifdef SYMBOL_PREFIX
|
||||||
@ -2436,8 +2420,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
|||||||
|
|
||||||
/* Also check that the parameter was not resolved from the kernel. */
|
/* Also check that the parameter was not resolved from the kernel. */
|
||||||
if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
|
if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
|
||||||
bb_error_msg("symbol for parameter %s not found", key);
|
bb_error_msg_and_die("symbol for parameter %s not found", key);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isdigit(*p)) {
|
if (isdigit(*p)) {
|
||||||
@ -2463,11 +2446,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
|||||||
|
|
||||||
str = alloca(strlen(q));
|
str = alloca(strlen(q));
|
||||||
for (r = str, q++; *q != '"'; ++q, ++r) {
|
for (r = str, q++; *q != '"'; ++q, ++r) {
|
||||||
if (*q == '\0') {
|
if (*q == '\0')
|
||||||
bb_error_msg("improperly terminated string argument for %s",
|
bb_error_msg_and_die("improperly terminated string argument for %s",
|
||||||
key);
|
key);
|
||||||
return 0;
|
if (*q == '\\')
|
||||||
} else if (*q == '\\')
|
|
||||||
switch (*++q) {
|
switch (*++q) {
|
||||||
case 'a':
|
case 'a':
|
||||||
*r = '\a';
|
*r = '\a';
|
||||||
@ -2513,8 +2495,9 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
|||||||
default:
|
default:
|
||||||
*r = *q;
|
*r = *q;
|
||||||
break;
|
break;
|
||||||
} else
|
}
|
||||||
*r = *q;
|
else
|
||||||
|
*r = *q;
|
||||||
}
|
}
|
||||||
*r = '\0';
|
*r = '\0';
|
||||||
++q;
|
++q;
|
||||||
@ -2558,17 +2541,15 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
|||||||
/* Get the size of each member */
|
/* Get the size of each member */
|
||||||
/* Probably we should do that outside the loop ? */
|
/* Probably we should do that outside the loop ? */
|
||||||
if (!isdigit(*(p + 1))) {
|
if (!isdigit(*(p + 1))) {
|
||||||
bb_error_msg("parameter type 'c' for %s must be followed by"
|
bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
|
||||||
" the maximum size", key);
|
" the maximum size", key);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
charssize = strtoul(p + 1, (char **) NULL, 10);
|
charssize = strtoul(p + 1, (char **) NULL, 10);
|
||||||
|
|
||||||
/* Check length */
|
/* Check length */
|
||||||
if (strlen(str) >= charssize) {
|
if (strlen(str) >= charssize) {
|
||||||
bb_error_msg("string too long for %s (max %ld)", key,
|
bb_error_msg_and_die("string too long for %s (max %ld)", key,
|
||||||
charssize - 1);
|
charssize - 1);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy to location */
|
/* Copy to location */
|
||||||
@ -2595,12 +2576,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bb_error_msg("unknown parameter type '%c' for %s", *p, key);
|
bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
retry_end_of_value:
|
||||||
retry_end_of_value:
|
|
||||||
switch (*q) {
|
switch (*q) {
|
||||||
case '\0':
|
case '\0':
|
||||||
goto end_of_arg;
|
goto end_of_arg;
|
||||||
@ -2614,28 +2593,23 @@ retry_end_of_value:
|
|||||||
|
|
||||||
case ',':
|
case ',':
|
||||||
if (++n > max) {
|
if (++n > max) {
|
||||||
bb_error_msg("too many values for %s (max %d)", key, max);
|
bb_error_msg_and_die("too many values for %s (max %d)", key, max);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
++q;
|
++q;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bb_error_msg("invalid argument syntax for %s", key);
|
bb_error_msg_and_die("invalid argument syntax for %s", key);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end_of_arg:
|
||||||
end_of_arg:
|
|
||||||
if (n < min) {
|
if (n < min) {
|
||||||
bb_error_msg("too few values for %s (min %d)", key, min);
|
bb_error_msg_and_die("too few values for %s (min %d)", key, min);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
argc--, argv++;
|
argc--;
|
||||||
|
argv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
|
#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
|
||||||
@ -2644,8 +2618,7 @@ static int new_is_module_checksummed(struct obj_file *f)
|
|||||||
const char *p = get_modinfo_value(f, "using_checksums");
|
const char *p = get_modinfo_value(f, "using_checksums");
|
||||||
if (p)
|
if (p)
|
||||||
return xatoi(p);
|
return xatoi(p);
|
||||||
else
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the module's kernel version in the canonical integer form. */
|
/* Get the module's kernel version in the canonical integer form. */
|
||||||
@ -2679,7 +2652,7 @@ new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
|
|||||||
|
|
||||||
/* Fetch the loaded modules, and all currently exported symbols. */
|
/* Fetch the loaded modules, and all currently exported symbols. */
|
||||||
|
|
||||||
static int new_get_kernel_symbols(void)
|
static void new_get_kernel_symbols(void)
|
||||||
{
|
{
|
||||||
char *module_names, *mn;
|
char *module_names, *mn;
|
||||||
struct external_module *modules, *m;
|
struct external_module *modules, *m;
|
||||||
@ -2688,15 +2661,17 @@ static int new_get_kernel_symbols(void)
|
|||||||
|
|
||||||
/* Collect the loaded modules. */
|
/* Collect the loaded modules. */
|
||||||
|
|
||||||
module_names = xmalloc(bufsize = 256);
|
bufsize = 256;
|
||||||
retry_modules_load:
|
module_names = xmalloc(bufsize);
|
||||||
|
|
||||||
|
retry_modules_load:
|
||||||
if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
|
if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
|
||||||
if (errno == ENOSPC && bufsize < ret) {
|
if (errno == ENOSPC && bufsize < ret) {
|
||||||
module_names = xrealloc(module_names, bufsize = ret);
|
bufsize = ret;
|
||||||
|
module_names = xrealloc(module_names, bufsize);
|
||||||
goto retry_modules_load;
|
goto retry_modules_load;
|
||||||
}
|
}
|
||||||
bb_perror_msg("QM_MODULES");
|
bb_perror_msg_and_die("QM_MODULES");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n_ext_modules = nmod = ret;
|
n_ext_modules = nmod = ret;
|
||||||
@ -2715,23 +2690,23 @@ retry_modules_load:
|
|||||||
/* The module was removed out from underneath us. */
|
/* The module was removed out from underneath us. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bb_perror_msg("query_module: QM_INFO: %s", mn);
|
bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
syms = xmalloc(bufsize = 1024);
|
bufsize = 1024;
|
||||||
retry_mod_sym_load:
|
syms = xmalloc(bufsize);
|
||||||
|
retry_mod_sym_load:
|
||||||
if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
|
if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case ENOSPC:
|
case ENOSPC:
|
||||||
syms = xrealloc(syms, bufsize = ret);
|
bufsize = ret;
|
||||||
|
syms = xrealloc(syms, bufsize);
|
||||||
goto retry_mod_sym_load;
|
goto retry_mod_sym_load;
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
/* The module was removed out from underneath us. */
|
/* The module was removed out from underneath us. */
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
|
bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nsyms = ret;
|
nsyms = ret;
|
||||||
@ -2750,14 +2725,13 @@ retry_mod_sym_load:
|
|||||||
/* Collect the kernel's symbols. */
|
/* Collect the kernel's symbols. */
|
||||||
|
|
||||||
syms = xmalloc(bufsize = 16 * 1024);
|
syms = xmalloc(bufsize = 16 * 1024);
|
||||||
retry_kern_sym_load:
|
retry_kern_sym_load:
|
||||||
if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
|
if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
|
||||||
if (errno == ENOSPC && bufsize < ret) {
|
if (errno == ENOSPC && bufsize < ret) {
|
||||||
syms = xrealloc(syms, bufsize = ret);
|
syms = xrealloc(syms, bufsize = ret);
|
||||||
goto retry_kern_sym_load;
|
goto retry_kern_sym_load;
|
||||||
}
|
}
|
||||||
bb_perror_msg("kernel: QM_SYMBOLS");
|
bb_perror_msg_and_die("kernel: QM_SYMBOLS");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
nksyms = nsyms = ret;
|
nksyms = nsyms = ret;
|
||||||
ksyms = syms;
|
ksyms = syms;
|
||||||
@ -2765,7 +2739,6 @@ retry_kern_sym_load:
|
|||||||
for (j = 0, s = syms; j < nsyms; ++j, ++s) {
|
for (j = 0, s = syms; j < nsyms; ++j, ++s) {
|
||||||
s->name += (unsigned long) syms;
|
s->name += (unsigned long) syms;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2786,7 +2759,7 @@ static int new_is_kernel_checksummed(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int new_create_this_module(struct obj_file *f, const char *m_name)
|
static void new_create_this_module(struct obj_file *f, const char *m_name)
|
||||||
{
|
{
|
||||||
struct obj_section *sec;
|
struct obj_section *sec;
|
||||||
|
|
||||||
@ -2800,8 +2773,6 @@ static int new_create_this_module(struct obj_file *f, const char *m_name)
|
|||||||
|
|
||||||
obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
|
obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
|
||||||
m_name);
|
m_name);
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
|
#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
|
||||||
@ -2985,7 +2956,7 @@ new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
|
|||||||
|
|
||||||
/*======================================================================*/
|
/*======================================================================*/
|
||||||
|
|
||||||
static int
|
static void
|
||||||
obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
||||||
const char *string)
|
const char *string)
|
||||||
{
|
{
|
||||||
@ -3010,11 +2981,9 @@ obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
|||||||
loc = obj_extend_section(strsec, len);
|
loc = obj_extend_section(strsec, len);
|
||||||
}
|
}
|
||||||
memcpy(loc, string, len);
|
memcpy(loc, string, len);
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
||||||
struct obj_symbol *sym)
|
struct obj_symbol *sym)
|
||||||
{
|
{
|
||||||
@ -3026,14 +2995,11 @@ obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
|
|||||||
p->reloc_offset = offset;
|
p->reloc_offset = offset;
|
||||||
p->sym = sym;
|
p->sym = sym;
|
||||||
f->symbol_patches = p;
|
f->symbol_patches = p;
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int obj_check_undefineds(struct obj_file *f)
|
static void obj_check_undefineds(struct obj_file *f)
|
||||||
{
|
{
|
||||||
unsigned long i;
|
unsigned i;
|
||||||
int ret = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < HASH_BUCKETS; ++i) {
|
for (i = 0; i < HASH_BUCKETS; ++i) {
|
||||||
struct obj_symbol *sym;
|
struct obj_symbol *sym;
|
||||||
@ -3043,15 +3009,11 @@ static int obj_check_undefineds(struct obj_file *f)
|
|||||||
sym->secidx = SHN_ABS;
|
sym->secidx = SHN_ABS;
|
||||||
sym->value = 0;
|
sym->value = 0;
|
||||||
} else {
|
} else {
|
||||||
if (!flag_quiet) {
|
if (!flag_quiet)
|
||||||
bb_error_msg("unresolved symbol %s", sym->name);
|
bb_error_msg_and_die("unresolved symbol %s", sym->name);
|
||||||
}
|
|
||||||
ret = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void obj_allocate_commons(struct obj_file *f)
|
static void obj_allocate_commons(struct obj_file *f)
|
||||||
@ -3114,7 +3076,6 @@ static void obj_allocate_commons(struct obj_file *f)
|
|||||||
f->sections[i] = sec = arch_new_section();
|
f->sections[i] = sec = arch_new_section();
|
||||||
f->header.e_shnum = i + 1;
|
f->header.e_shnum = i + 1;
|
||||||
|
|
||||||
memset(sec, 0, sizeof(*sec));
|
|
||||||
sec->header.sh_type = SHT_PROGBITS;
|
sec->header.sh_type = SHT_PROGBITS;
|
||||||
sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
|
sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
|
||||||
sec->name = ".bss";
|
sec->name = ".bss";
|
||||||
@ -3347,44 +3308,38 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
/* Read the file header. */
|
/* Read the file header. */
|
||||||
|
|
||||||
f = arch_new_file();
|
f = arch_new_file();
|
||||||
memset(f, 0, sizeof(*f));
|
|
||||||
f->symbol_cmp = strcmp;
|
f->symbol_cmp = strcmp;
|
||||||
f->symbol_hash = obj_elf_hash;
|
f->symbol_hash = obj_elf_hash;
|
||||||
f->load_order_search_start = &f->load_order;
|
f->load_order_search_start = &f->load_order;
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
fseek(fp, 0, SEEK_SET);
|
||||||
if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
|
if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
|
||||||
bb_perror_msg("error reading ELF header");
|
bb_perror_msg_and_die("error reading ELF header");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->header.e_ident[EI_MAG0] != ELFMAG0
|
if (f->header.e_ident[EI_MAG0] != ELFMAG0
|
||||||
|| f->header.e_ident[EI_MAG1] != ELFMAG1
|
|| f->header.e_ident[EI_MAG1] != ELFMAG1
|
||||||
|| f->header.e_ident[EI_MAG2] != ELFMAG2
|
|| f->header.e_ident[EI_MAG2] != ELFMAG2
|
||||||
|| f->header.e_ident[EI_MAG3] != ELFMAG3) {
|
|| f->header.e_ident[EI_MAG3] != ELFMAG3) {
|
||||||
bb_error_msg("not an ELF file");
|
bb_error_msg_and_die("not an ELF file");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (f->header.e_ident[EI_CLASS] != ELFCLASSM
|
if (f->header.e_ident[EI_CLASS] != ELFCLASSM
|
||||||
|| f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
|
|| f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
|
||||||
? ELFDATA2MSB : ELFDATA2LSB)
|
? ELFDATA2MSB : ELFDATA2LSB)
|
||||||
|| f->header.e_ident[EI_VERSION] != EV_CURRENT
|
|| f->header.e_ident[EI_VERSION] != EV_CURRENT
|
||||||
|| !MATCH_MACHINE(f->header.e_machine)) {
|
|| !MATCH_MACHINE(f->header.e_machine)) {
|
||||||
bb_error_msg("ELF file not for this architecture");
|
bb_error_msg_and_die("ELF file not for this architecture");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (f->header.e_type != ET_REL) {
|
if (f->header.e_type != ET_REL) {
|
||||||
bb_error_msg("ELF file not a relocatable object");
|
bb_error_msg_and_die("ELF file not a relocatable object");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the section headers. */
|
/* Read the section headers. */
|
||||||
|
|
||||||
if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
|
if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
|
||||||
bb_error_msg("section header size mismatch: %lu != %lu",
|
bb_error_msg_and_die("section header size mismatch: %lu != %lu",
|
||||||
(unsigned long) f->header.e_shentsize,
|
(unsigned long) f->header.e_shentsize,
|
||||||
(unsigned long) sizeof(ElfW(Shdr)));
|
(unsigned long) sizeof(ElfW(Shdr)));
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shnum = f->header.e_shnum;
|
shnum = f->header.e_shnum;
|
||||||
@ -3394,8 +3349,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
|
section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
|
||||||
fseek(fp, f->header.e_shoff, SEEK_SET);
|
fseek(fp, f->header.e_shoff, SEEK_SET);
|
||||||
if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
|
if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
|
||||||
bb_perror_msg("error reading ELF section headers");
|
bb_perror_msg_and_die("error reading ELF section headers");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the section data. */
|
/* Read the section data. */
|
||||||
@ -3404,7 +3358,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
struct obj_section *sec;
|
struct obj_section *sec;
|
||||||
|
|
||||||
f->sections[i] = sec = arch_new_section();
|
f->sections[i] = sec = arch_new_section();
|
||||||
memset(sec, 0, sizeof(*sec));
|
|
||||||
|
|
||||||
sec->header = section_headers[i];
|
sec->header = section_headers[i];
|
||||||
sec->idx = i;
|
sec->idx = i;
|
||||||
@ -3431,8 +3384,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
sec->contents = xmalloc(sec->header.sh_size);
|
sec->contents = xmalloc(sec->header.sh_size);
|
||||||
fseek(fp, sec->header.sh_offset, SEEK_SET);
|
fseek(fp, sec->header.sh_offset, SEEK_SET);
|
||||||
if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
|
if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
|
||||||
bb_perror_msg("error reading ELF section data");
|
bb_perror_msg_and_die("error reading ELF section data");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sec->contents = NULL;
|
sec->contents = NULL;
|
||||||
@ -3441,14 +3393,11 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
|
|
||||||
#if SHT_RELM == SHT_REL
|
#if SHT_RELM == SHT_REL
|
||||||
case SHT_RELA:
|
case SHT_RELA:
|
||||||
bb_error_msg("RELA relocations not supported on this architecture");
|
bb_error_msg_and_die("RELA relocations not supported on this architecture");
|
||||||
return NULL;
|
|
||||||
#else
|
#else
|
||||||
case SHT_REL:
|
case SHT_REL:
|
||||||
bb_error_msg("REL relocations not supported on this architecture");
|
bb_error_msg_and_die("REL relocations not supported on this architecture");
|
||||||
return NULL;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (sec->header.sh_type >= SHT_LOPROC) {
|
if (sec->header.sh_type >= SHT_LOPROC) {
|
||||||
/* Assume processor specific section types are debug
|
/* Assume processor specific section types are debug
|
||||||
@ -3458,9 +3407,8 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb_error_msg("can't handle sections of type %ld",
|
bb_error_msg_and_die("can't handle sections of type %ld",
|
||||||
(long) sec->header.sh_type);
|
(long) sec->header.sh_type);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3494,10 +3442,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
ElfW(Sym) * sym;
|
ElfW(Sym) * sym;
|
||||||
|
|
||||||
if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
|
if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
|
||||||
bb_error_msg("symbol size mismatch: %lu != %lu",
|
bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
|
||||||
(unsigned long) sec->header.sh_entsize,
|
(unsigned long) sec->header.sh_entsize,
|
||||||
(unsigned long) sizeof(ElfW(Sym)));
|
(unsigned long) sizeof(ElfW(Sym)));
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsym = sec->header.sh_size / sizeof(ElfW(Sym));
|
nsym = sec->header.sh_size / sizeof(ElfW(Sym));
|
||||||
@ -3528,7 +3475,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
*/
|
*/
|
||||||
val |= sym->st_other & 4;
|
val |= sym->st_other & 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
|
obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
|
||||||
val, sym->st_size);
|
val, sym->st_size);
|
||||||
}
|
}
|
||||||
@ -3537,10 +3483,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
|
|||||||
|
|
||||||
case SHT_RELM:
|
case SHT_RELM:
|
||||||
if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
|
if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
|
||||||
bb_error_msg("relocation entry size mismatch: %lu != %lu",
|
bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
|
||||||
(unsigned long) sec->header.sh_entsize,
|
(unsigned long) sec->header.sh_entsize,
|
||||||
(unsigned long) sizeof(ElfW(RelM)));
|
(unsigned long) sizeof(ElfW(RelM)));
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* XXX Relocation code from modutils-2.3.19 is not here.
|
/* XXX Relocation code from modutils-2.3.19 is not here.
|
||||||
@ -3638,8 +3583,9 @@ static int obj_gpl_license(struct obj_file *f, const char **license)
|
|||||||
}
|
}
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
if (strchr(ptr, '\0'))
|
ptr = strchr(ptr, '\0');
|
||||||
ptr = strchr(ptr, '\0') + 1;
|
if (ptr)
|
||||||
|
ptr++;
|
||||||
else
|
else
|
||||||
ptr = endptr;
|
ptr = endptr;
|
||||||
}
|
}
|
||||||
@ -3648,12 +3594,12 @@ static int obj_gpl_license(struct obj_file *f, const char **license)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define TAINT_FILENAME "/proc/sys/kernel/tainted"
|
#define TAINT_FILENAME "/proc/sys/kernel/tainted"
|
||||||
#define TAINT_PROPRIETORY_MODULE (1<<0)
|
#define TAINT_PROPRIETORY_MODULE (1 << 0)
|
||||||
#define TAINT_FORCED_MODULE (1<<1)
|
#define TAINT_FORCED_MODULE (1 << 1)
|
||||||
#define TAINT_UNSAFE_SMP (1<<2)
|
#define TAINT_UNSAFE_SMP (1 << 2)
|
||||||
#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
|
#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
|
||||||
|
|
||||||
static void set_tainted(struct obj_file *f, int fd, char *m_name,
|
static void set_tainted(int fd, char *m_name,
|
||||||
int kernel_has_tainted, int taint, const char *text1, const char *text2)
|
int kernel_has_tainted, int taint, const char *text1, const char *text2)
|
||||||
{
|
{
|
||||||
static smallint printed_info;
|
static smallint printed_info;
|
||||||
@ -3703,22 +3649,22 @@ static void check_tainted_module(struct obj_file *f, char *m_name)
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
|
set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
/* The module has a non-GPL license so we pretend that the
|
/* The module has a non-GPL license so we pretend that the
|
||||||
* kernel always has a taint flag to get a warning even on
|
* kernel always has a taint flag to get a warning even on
|
||||||
* kernels without the proc flag.
|
* kernels without the proc flag.
|
||||||
*/
|
*/
|
||||||
set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
|
set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
|
set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag_force_load)
|
if (flag_force_load)
|
||||||
set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
|
set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
|
||||||
|
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -3752,15 +3698,7 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
|
|||||||
const char *m_name)
|
const char *m_name)
|
||||||
{
|
{
|
||||||
static const char symprefix[] ALIGN1 = "__insmod_";
|
static const char symprefix[] ALIGN1 = "__insmod_";
|
||||||
|
static const char section_names[][8] = {
|
||||||
struct obj_section *sec;
|
|
||||||
struct obj_symbol *sym;
|
|
||||||
char *name, *absolute_filename;
|
|
||||||
char str[STRVERSIONLEN], real[PATH_MAX];
|
|
||||||
int i, l, lm_name, lfilename, use_ksymtab, version;
|
|
||||||
struct stat statbuf;
|
|
||||||
|
|
||||||
static const char *section_names[] = {
|
|
||||||
".text",
|
".text",
|
||||||
".rodata",
|
".rodata",
|
||||||
".data",
|
".data",
|
||||||
@ -3768,12 +3706,18 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
|
|||||||
".sbss"
|
".sbss"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (realpath(filename, real)) {
|
struct obj_section *sec;
|
||||||
absolute_filename = xstrdup(real);
|
struct obj_symbol *sym;
|
||||||
} else {
|
char *name, *absolute_filename;
|
||||||
bb_perror_msg("cannot get realpath for %s", filename);
|
char str[STRVERSIONLEN];
|
||||||
|
int i, l, lm_name, lfilename, use_ksymtab, version;
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
|
/* WARNING: was using realpath, but replaced by readlink to stop using
|
||||||
|
* lots of stack. But here it seems to be able to cause problems? */
|
||||||
|
absolute_filename = xmalloc_readlink(filename);
|
||||||
|
if (!absolute_filename)
|
||||||
absolute_filename = xstrdup(filename);
|
absolute_filename = xstrdup(filename);
|
||||||
}
|
|
||||||
|
|
||||||
lm_name = strlen(m_name);
|
lm_name = strlen(m_name);
|
||||||
lfilename = strlen(absolute_filename);
|
lfilename = strlen(absolute_filename);
|
||||||
@ -3791,22 +3735,22 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
|
|||||||
* is 0xffffff, decimal 16777215. putting all three fields in
|
* is 0xffffff, decimal 16777215. putting all three fields in
|
||||||
* one symbol is less readable but saves kernel space.
|
* one symbol is less readable but saves kernel space.
|
||||||
*/
|
*/
|
||||||
l = sizeof(symprefix)+ /* "__insmod_" */
|
l = sizeof(symprefix) + /* "__insmod_" */
|
||||||
lm_name+ /* module name */
|
lm_name + /* module name */
|
||||||
2+ /* "_O" */
|
2 + /* "_O" */
|
||||||
lfilename+ /* object filename */
|
lfilename + /* object filename */
|
||||||
2+ /* "_M" */
|
2 + /* "_M" */
|
||||||
2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
|
2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
|
||||||
2+ /* "_V" */
|
2 + /* "_V" */
|
||||||
8+ /* version in dec */
|
8 + /* version in dec */
|
||||||
1; /* nul */
|
1; /* nul */
|
||||||
name = xmalloc(l);
|
name = xmalloc(l);
|
||||||
if (stat(absolute_filename, &statbuf) != 0)
|
if (stat(absolute_filename, &statbuf) != 0)
|
||||||
statbuf.st_mtime = 0;
|
statbuf.st_mtime = 0;
|
||||||
version = get_module_version(f, str); /* -1 if not found */
|
version = get_module_version(f, str); /* -1 if not found */
|
||||||
snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
|
snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
|
||||||
symprefix, m_name, absolute_filename,
|
symprefix, m_name, absolute_filename,
|
||||||
(int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
|
(int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
|
||||||
version);
|
version);
|
||||||
sym = obj_add_symbol(f, name, -1,
|
sym = obj_add_symbol(f, name, -1,
|
||||||
ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
||||||
@ -3819,11 +3763,11 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
|
|||||||
/* record where the persistent data is going, same address as previous symbol */
|
/* record where the persistent data is going, same address as previous symbol */
|
||||||
|
|
||||||
if (f->persist) {
|
if (f->persist) {
|
||||||
l = sizeof(symprefix)+ /* "__insmod_" */
|
l = sizeof(symprefix) + /* "__insmod_" */
|
||||||
lm_name+ /* module name */
|
lm_name + /* module name */
|
||||||
2+ /* "_P" */
|
2 + /* "_P" */
|
||||||
strlen(f->persist)+ /* data store */
|
strlen(f->persist) + /* data store */
|
||||||
1; /* nul */
|
1; /* nul */
|
||||||
name = xmalloc(l);
|
name = xmalloc(l);
|
||||||
snprintf(name, l, "%s%s_P%s",
|
snprintf(name, l, "%s%s_P%s",
|
||||||
symprefix, m_name, f->persist);
|
symprefix, m_name, f->persist);
|
||||||
@ -3838,13 +3782,13 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename,
|
|||||||
for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
|
for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
|
||||||
sec = obj_find_section(f, section_names[i]);
|
sec = obj_find_section(f, section_names[i]);
|
||||||
if (sec && sec->header.sh_size) {
|
if (sec && sec->header.sh_size) {
|
||||||
l = sizeof(symprefix)+ /* "__insmod_" */
|
l = sizeof(symprefix) + /* "__insmod_" */
|
||||||
lm_name+ /* module name */
|
lm_name + /* module name */
|
||||||
2+ /* "_S" */
|
2 + /* "_S" */
|
||||||
strlen(sec->name)+ /* section name */
|
strlen(sec->name) + /* section name */
|
||||||
2+ /* "_L" */
|
2 + /* "_L" */
|
||||||
8+ /* length in dec */
|
8 + /* length in dec */
|
||||||
1; /* nul */
|
1; /* nul */
|
||||||
name = xmalloc(l);
|
name = xmalloc(l);
|
||||||
snprintf(name, l, "%s%s_S%s_L%ld",
|
snprintf(name, l, "%s%s_S%s_L%ld",
|
||||||
symprefix, m_name, sec->name,
|
symprefix, m_name, sec->name,
|
||||||
@ -3891,9 +3835,10 @@ static void print_load_map(struct obj_file *f)
|
|||||||
#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
|
#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
|
||||||
/* Quick reference which section indicies are loaded. */
|
/* Quick reference which section indicies are loaded. */
|
||||||
|
|
||||||
loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
|
i = f->header.e_shnum;
|
||||||
|
loaded = alloca(sizeof(int) * i);
|
||||||
while (--i >= 0)
|
while (--i >= 0)
|
||||||
loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
|
loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
|
||||||
|
|
||||||
/* Collect the symbols we'll be listing. */
|
/* Collect the symbols we'll be listing. */
|
||||||
|
|
||||||
@ -3963,7 +3908,7 @@ int insmod_main(int argc, char **argv)
|
|||||||
ElfW(Addr) m_addr;
|
ElfW(Addr) m_addr;
|
||||||
struct obj_file *f;
|
struct obj_file *f;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *m_name = 0;
|
char *m_name = NULL;
|
||||||
int exit_status = EXIT_FAILURE;
|
int exit_status = EXIT_FAILURE;
|
||||||
int m_has_modinfo;
|
int m_has_modinfo;
|
||||||
#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
|
#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
|
||||||
@ -4027,7 +3972,7 @@ int insmod_main(int argc, char **argv)
|
|||||||
m_name = tmp;
|
m_name = tmp;
|
||||||
} else {
|
} else {
|
||||||
free(tmp1);
|
free(tmp1);
|
||||||
tmp1 = 0; /* flag for free(m_name) before exit() */
|
tmp1 = NULL; /* flag for free(m_name) before exit() */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a filedesc for the module. Check that we have a complete path */
|
/* Get a filedesc for the module. Check that we have a complete path */
|
||||||
@ -4039,7 +3984,6 @@ int insmod_main(int argc, char **argv)
|
|||||||
if (k_version) { /* uname succeedd */
|
if (k_version) { /* uname succeedd */
|
||||||
char *module_dir;
|
char *module_dir;
|
||||||
char *tmdn;
|
char *tmdn;
|
||||||
char real_module_dir[FILENAME_MAX];
|
|
||||||
|
|
||||||
tmdn = concat_path_file(_PATH_MODULES, myuname.release);
|
tmdn = concat_path_file(_PATH_MODULES, myuname.release);
|
||||||
/* Jump through hoops in case /lib/modules/`uname -r`
|
/* Jump through hoops in case /lib/modules/`uname -r`
|
||||||
@ -4047,36 +3991,37 @@ int insmod_main(int argc, char **argv)
|
|||||||
* follow symlinks, but we do want to follow the
|
* follow symlinks, but we do want to follow the
|
||||||
* /lib/modules/`uname -r` dir, So resolve it ourselves
|
* /lib/modules/`uname -r` dir, So resolve it ourselves
|
||||||
* if it is a link... */
|
* if it is a link... */
|
||||||
if (realpath(tmdn, real_module_dir) == NULL)
|
module_dir = xmalloc_readlink(tmdn);
|
||||||
module_dir = tmdn;
|
if (!module_dir)
|
||||||
else
|
module_dir = xstrdup(tmdn);
|
||||||
module_dir = real_module_dir;
|
|
||||||
recursive_action(module_dir, ACTION_RECURSE,
|
recursive_action(module_dir, ACTION_RECURSE,
|
||||||
check_module_name_match, 0, m_fullName, 0);
|
check_module_name_match, NULL, m_fullName, 0);
|
||||||
|
free(module_dir);
|
||||||
free(tmdn);
|
free(tmdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have found anything yet */
|
/* Check if we have found anything yet */
|
||||||
if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
|
if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
|
||||||
char module_dir[FILENAME_MAX];
|
int r;
|
||||||
|
char *module_dir;
|
||||||
|
|
||||||
free(m_filename);
|
free(m_filename);
|
||||||
m_filename = NULL;
|
m_filename = NULL;
|
||||||
if (realpath(_PATH_MODULES, module_dir) == NULL)
|
module_dir = xmalloc_readlink(_PATH_MODULES);
|
||||||
strcpy(module_dir, _PATH_MODULES);
|
if (!module_dir)
|
||||||
|
module_dir = xstrdup(_PATH_MODULES);
|
||||||
/* No module found under /lib/modules/`uname -r`, this
|
/* No module found under /lib/modules/`uname -r`, this
|
||||||
* time cast the net a bit wider. Search /lib/modules/ */
|
* time cast the net a bit wider. Search /lib/modules/ */
|
||||||
if (!recursive_action(module_dir, ACTION_RECURSE,
|
r = recursive_action(module_dir, ACTION_RECURSE,
|
||||||
check_module_name_match, 0, m_fullName, 0)
|
check_module_name_match, NULL, m_fullName, 0);
|
||||||
) {
|
if (r)
|
||||||
if (m_filename == 0
|
|
||||||
|| ((fp = fopen(m_filename, "r")) == NULL)
|
|
||||||
) {
|
|
||||||
bb_error_msg("%s: module not found", m_fullName);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
bb_error_msg_and_die("%s: module not found", m_fullName);
|
bb_error_msg_and_die("%s: module not found", m_fullName);
|
||||||
|
free(module_dir);
|
||||||
|
if (m_filename == NULL
|
||||||
|
|| ((fp = fopen(m_filename, "r")) == NULL)
|
||||||
|
) {
|
||||||
|
bb_error_msg_and_die("%s: module not found", m_fullName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
m_filename = xstrdup(arg1);
|
m_filename = xstrdup(arg1);
|
||||||
@ -4093,8 +4038,6 @@ int insmod_main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
f = obj_load(fp, LOADBITS);
|
f = obj_load(fp, LOADBITS);
|
||||||
if (f == NULL)
|
|
||||||
bb_perror_msg_and_die("cannot load the module");
|
|
||||||
|
|
||||||
if (get_modinfo_value(f, "kernel_version") == NULL)
|
if (get_modinfo_value(f, "kernel_version") == NULL)
|
||||||
m_has_modinfo = 0;
|
m_has_modinfo = 0;
|
||||||
@ -4109,9 +4052,8 @@ int insmod_main(int argc, char **argv)
|
|||||||
if (m_has_modinfo) {
|
if (m_has_modinfo) {
|
||||||
m_version = new_get_module_version(f, m_strversion);
|
m_version = new_get_module_version(f, m_strversion);
|
||||||
if (m_version == -1) {
|
if (m_version == -1) {
|
||||||
bb_error_msg("cannot find the kernel version the module was "
|
bb_error_msg_and_die("cannot find the kernel version the module was "
|
||||||
"compiled for");
|
"compiled for");
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4128,14 +4070,10 @@ int insmod_main(int argc, char **argv)
|
|||||||
k_crcs = 0;
|
k_crcs = 0;
|
||||||
#endif /* FEATURE_INSMOD_VERSION_CHECKING */
|
#endif /* FEATURE_INSMOD_VERSION_CHECKING */
|
||||||
|
|
||||||
if (!query_module(NULL, 0, NULL, 0, NULL)) {
|
if (query_module(NULL, 0, NULL, 0, NULL))
|
||||||
if (!new_get_kernel_symbols())
|
bb_error_msg_and_die("not configured to support old kernels");
|
||||||
goto out;
|
new_get_kernel_symbols();
|
||||||
k_crcs = new_is_kernel_checksummed();
|
k_crcs = new_is_kernel_checksummed();
|
||||||
} else {
|
|
||||||
bb_error_msg("not configured to support old kernels");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
|
#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
|
||||||
m_crcs = 0;
|
m_crcs = 0;
|
||||||
@ -4151,22 +4089,15 @@ int insmod_main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Allocate common symbols, symbol tables, and string tables. */
|
/* Allocate common symbols, symbol tables, and string tables. */
|
||||||
|
|
||||||
if (!new_create_this_module(f, m_name)) {
|
new_create_this_module(f, m_name);
|
||||||
goto out;
|
obj_check_undefineds(f);
|
||||||
}
|
|
||||||
|
|
||||||
if (!obj_check_undefineds(f)) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
obj_allocate_commons(f);
|
obj_allocate_commons(f);
|
||||||
check_tainted_module(f, m_name);
|
check_tainted_module(f, m_name);
|
||||||
|
|
||||||
/* done with the module name, on to the optional var=value arguments */
|
/* done with the module name, on to the optional var=value arguments */
|
||||||
++optind;
|
++optind;
|
||||||
if (optind < argc) {
|
if (optind < argc) {
|
||||||
if (!new_process_module_arguments(f, argc - optind, argv + optind)) {
|
new_process_module_arguments(f, argc - optind, argv + optind);
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arch_create_got(f);
|
arch_create_got(f);
|
||||||
@ -4181,22 +4112,18 @@ int insmod_main(int argc, char **argv)
|
|||||||
/* Find current size of the module */
|
/* Find current size of the module */
|
||||||
m_size = obj_load_size(f);
|
m_size = obj_load_size(f);
|
||||||
|
|
||||||
|
|
||||||
m_addr = create_module(m_name, m_size);
|
m_addr = create_module(m_name, m_size);
|
||||||
if (m_addr == -1) switch (errno) {
|
if (m_addr == -1) switch (errno) {
|
||||||
case EEXIST:
|
case EEXIST:
|
||||||
bb_error_msg("a module named %s already exists", m_name);
|
bb_error_msg_and_die("a module named %s already exists", m_name);
|
||||||
goto out;
|
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
bb_error_msg("can't allocate kernel memory for module; needed %lu bytes",
|
bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
|
||||||
m_size);
|
m_size);
|
||||||
goto out;
|
|
||||||
default:
|
default:
|
||||||
bb_perror_msg("create_module: %s", m_name);
|
bb_perror_msg_and_die("create_module: %s", m_name);
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !LOADBITS
|
#if !LOADBITS
|
||||||
/*
|
/*
|
||||||
* the PROGBITS section was not loaded by the obj_load
|
* the PROGBITS section was not loaded by the obj_load
|
||||||
* now we can load them directly into the kernel memory
|
* now we can load them directly into the kernel memory
|
||||||
@ -4222,7 +4149,7 @@ int insmod_main(int argc, char **argv)
|
|||||||
|
|
||||||
exit_status = EXIT_SUCCESS;
|
exit_status = EXIT_SUCCESS;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
#if ENABLE_FEATURE_CLEAN_UP
|
#if ENABLE_FEATURE_CLEAN_UP
|
||||||
if (fp)
|
if (fp)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -4234,8 +4161,10 @@ out:
|
|||||||
return exit_status;
|
return exit_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ENABLE_FEATURE_2_4_MODULES */
|
||||||
#endif
|
/*
|
||||||
|
* End of big piece of 2.4-specific code
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_2_6_MODULES
|
#if ENABLE_FEATURE_2_6_MODULES
|
||||||
@ -4249,20 +4178,24 @@ static const char *moderror(int err)
|
|||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case ENOEXEC:
|
case ENOEXEC:
|
||||||
return "Invalid module format";
|
return "invalid module format";
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
return "Unknown symbol in module";
|
return "unknown symbol in module";
|
||||||
case ESRCH:
|
case ESRCH:
|
||||||
return "Module has wrong symbol version";
|
return "module has wrong symbol version";
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
return "Invalid parameters";
|
return "invalid parameters";
|
||||||
default:
|
default:
|
||||||
return strerror(err);
|
return strerror(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
#if !ENABLE_FEATURE_2_4_MODULES
|
||||||
int insmod_ng_main(int argc, char **argv)
|
int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
|
int insmod_main(int argc, char **argv)
|
||||||
|
#else
|
||||||
|
static int insmod_ng_main(int argc, char **argv)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
long ret;
|
long ret;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -28,17 +28,17 @@ static void check_tainted(void)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
tainted = 0;
|
tainted = 0;
|
||||||
if ((f = fopen(TAINT_FILENAME, "r"))) {
|
f = fopen(TAINT_FILENAME, "r");
|
||||||
|
if (f) {
|
||||||
fscanf(f, "%d", &tainted);
|
fscanf(f, "%d", &tainted);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
if (f && tainted) {
|
if (tainted) {
|
||||||
printf(" Tainted: %c%c%c\n",
|
printf(" Tainted: %c%c%c\n",
|
||||||
tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
|
tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
|
||||||
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
|
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
|
||||||
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
|
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
printf(" Not tainted\n");
|
printf(" Not tainted\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ int lsmod_main(int argc, char **argv)
|
|||||||
|
|
||||||
printf("Module Size Used by");
|
printf("Module Size Used by");
|
||||||
check_tainted();
|
check_tainted();
|
||||||
#if defined(CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT)
|
#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
|
||||||
{
|
{
|
||||||
char *line;
|
char *line;
|
||||||
while ((line = xmalloc_fgets(file)) != NULL) {
|
while ((line = xmalloc_fgets(file)) != NULL) {
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
|
|
||||||
|
#define line_buffer bb_common_bufsiz1
|
||||||
|
|
||||||
struct mod_opt_t { /* one-way list of options to pass to a module */
|
struct mod_opt_t { /* one-way list of options to pass to a module */
|
||||||
char * m_opt_val;
|
char * m_opt_val;
|
||||||
struct mod_opt_t * m_next;
|
struct mod_opt_t * m_next;
|
||||||
@ -48,7 +50,7 @@ struct mod_list_t { /* two-way list of modules to process */
|
|||||||
|
|
||||||
static struct dep_t *depend;
|
static struct dep_t *depend;
|
||||||
|
|
||||||
#define main_options "acdklnqrst:vVC:"
|
#define MAIN_OPT_STR "acdklnqrst:vVC:"
|
||||||
#define INSERT_ALL 1 /* a */
|
#define INSERT_ALL 1 /* a */
|
||||||
#define DUMP_CONF_EXIT 2 /* c */
|
#define DUMP_CONF_EXIT 2 /* c */
|
||||||
#define D_OPT_IGNORED 4 /* d */
|
#define D_OPT_IGNORED 4 /* d */
|
||||||
@ -63,14 +65,12 @@ static struct dep_t *depend;
|
|||||||
#define VERSION_ONLY 2048 /* V */
|
#define VERSION_ONLY 2048 /* V */
|
||||||
#define CONFIG_FILE 4096 /* C */
|
#define CONFIG_FILE 4096 /* C */
|
||||||
|
|
||||||
#define autoclean (main_opts & AUTOCLEAN_FLG)
|
#define autoclean (option_mask32 & AUTOCLEAN_FLG)
|
||||||
#define show_only (main_opts & SHOW_ONLY)
|
#define show_only (option_mask32 & SHOW_ONLY)
|
||||||
#define quiet (main_opts & QUIET)
|
#define quiet (option_mask32 & QUIET)
|
||||||
#define remove_opt (main_opts & REMOVE_OPT)
|
#define remove_opt (option_mask32 & REMOVE_OPT)
|
||||||
#define do_syslog (main_opts & DO_SYSLOG)
|
#define do_syslog (option_mask32 & DO_SYSLOG)
|
||||||
#define verbose (main_opts & VERBOSE)
|
#define verbose (option_mask32 & VERBOSE)
|
||||||
|
|
||||||
static int main_opts;
|
|
||||||
|
|
||||||
static int parse_tag_value(char *buffer, char **ptag, char **pvalue)
|
static int parse_tag_value(char *buffer, char **ptag, char **pvalue)
|
||||||
{
|
{
|
||||||
@ -78,12 +78,15 @@ static int parse_tag_value(char *buffer, char **ptag, char **pvalue)
|
|||||||
|
|
||||||
buffer = skip_whitespace(buffer);
|
buffer = skip_whitespace(buffer);
|
||||||
tag = value = buffer;
|
tag = value = buffer;
|
||||||
while (!isspace(*value))
|
while (!isspace(*value)) {
|
||||||
if (!*value) return 0;
|
if (!*value)
|
||||||
else value++;
|
return 0;
|
||||||
*value++ = 0;
|
value++;
|
||||||
|
}
|
||||||
|
*value++ = '\0';
|
||||||
value = skip_whitespace(value);
|
value = skip_whitespace(value);
|
||||||
if (!*value) return 0;
|
if (!*value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
*ptag = tag;
|
*ptag = tag;
|
||||||
*pvalue = value;
|
*pvalue = value;
|
||||||
@ -102,14 +105,14 @@ static struct mod_opt_t *append_option(struct mod_opt_t *opt_list, char *opt)
|
|||||||
while (ol->m_next) {
|
while (ol->m_next) {
|
||||||
ol = ol->m_next;
|
ol = ol->m_next;
|
||||||
}
|
}
|
||||||
ol->m_next = xmalloc(sizeof(struct mod_opt_t));
|
ol->m_next = xzalloc(sizeof(struct mod_opt_t));
|
||||||
ol = ol->m_next;
|
ol = ol->m_next;
|
||||||
} else {
|
} else {
|
||||||
ol = opt_list = xmalloc(sizeof(struct mod_opt_t));
|
ol = opt_list = xzalloc(sizeof(struct mod_opt_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
ol->m_opt_val = xstrdup(opt);
|
ol->m_opt_val = xstrdup(opt);
|
||||||
ol->m_next = NULL;
|
/*ol->m_next = NULL; - done by xzalloc*/
|
||||||
|
|
||||||
return opt_list;
|
return opt_list;
|
||||||
}
|
}
|
||||||
@ -190,7 +193,8 @@ static char *parse_command_string(char *src, char **dst)
|
|||||||
case '0':
|
case '0':
|
||||||
/* We escaped a special character. For now, keep
|
/* We escaped a special character. For now, keep
|
||||||
* both the back-slash and the following char. */
|
* both the back-slash and the following char. */
|
||||||
tmp_str++; src++;
|
tmp_str++;
|
||||||
|
src++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* We escaped a space or a single or double quote,
|
/* We escaped a space or a single or double quote,
|
||||||
@ -242,12 +246,12 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf
|
|||||||
|
|
||||||
p = strchr(buffer, '#');
|
p = strchr(buffer, '#');
|
||||||
if (p)
|
if (p)
|
||||||
*p = 0;
|
*p = '\0';
|
||||||
|
|
||||||
l = strlen(buffer);
|
l = strlen(buffer);
|
||||||
|
|
||||||
while (l && isspace(buffer[l-1])) {
|
while (l && isspace(buffer[l-1])) {
|
||||||
buffer[l-1] = 0;
|
buffer[l-1] = '\0';
|
||||||
l--;
|
l--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,66 +260,68 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!continuation_line) {
|
if (continuation_line)
|
||||||
if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) {
|
continue;
|
||||||
char *alias, *mod;
|
|
||||||
|
|
||||||
if (parse_tag_value(buffer + 6, &alias, &mod)) {
|
if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) {
|
||||||
/* handle alias as a module dependent on the aliased module */
|
char *alias, *mod;
|
||||||
if (!*current) {
|
|
||||||
(*first) = (*current) = xzalloc(sizeof(struct dep_t));
|
|
||||||
} else {
|
|
||||||
(*current)->m_next = xzalloc(sizeof(struct dep_t));
|
|
||||||
(*current) = (*current)->m_next;
|
|
||||||
}
|
|
||||||
(*current)->m_name = xstrdup(alias);
|
|
||||||
(*current)->m_isalias = 1;
|
|
||||||
|
|
||||||
if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) {
|
if (parse_tag_value(buffer + 6, &alias, &mod)) {
|
||||||
(*current)->m_depcnt = 0;
|
/* handle alias as a module dependent on the aliased module */
|
||||||
(*current)->m_deparr = 0;
|
if (!*current) {
|
||||||
} else {
|
(*first) = (*current) = xzalloc(sizeof(struct dep_t));
|
||||||
(*current)->m_depcnt = 1;
|
} else {
|
||||||
(*current)->m_deparr = xmalloc(1 * sizeof(char *));
|
(*current)->m_next = xzalloc(sizeof(struct dep_t));
|
||||||
(*current)->m_deparr[0] = xstrdup(mod);
|
(*current) = (*current)->m_next;
|
||||||
}
|
|
||||||
(*current)->m_next = 0;
|
|
||||||
}
|
}
|
||||||
} else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) {
|
(*current)->m_name = xstrdup(alias);
|
||||||
char *mod, *opt;
|
(*current)->m_isalias = 1;
|
||||||
|
|
||||||
/* split the line in the module/alias name, and options */
|
if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) {
|
||||||
if (parse_tag_value(buffer + 8, &mod, &opt)) {
|
/*(*current)->m_depcnt = 0; - done by xzalloc */
|
||||||
struct dep_t *dt;
|
/*(*current)->m_deparr = 0;*/
|
||||||
|
} else {
|
||||||
|
(*current)->m_depcnt = 1;
|
||||||
|
(*current)->m_deparr = xmalloc(sizeof(char *));
|
||||||
|
(*current)->m_deparr[0] = xstrdup(mod);
|
||||||
|
}
|
||||||
|
/*(*current)->m_next = NULL; - done by xzalloc */
|
||||||
|
}
|
||||||
|
} else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) {
|
||||||
|
char *mod, *opt;
|
||||||
|
|
||||||
/* find the corresponding module */
|
/* split the line in the module/alias name, and options */
|
||||||
for (dt = *first; dt; dt = dt->m_next) {
|
if (parse_tag_value(buffer + 8, &mod, &opt)) {
|
||||||
if (strcmp(dt->m_name, mod) == 0)
|
struct dep_t *dt;
|
||||||
break;
|
|
||||||
}
|
/* find the corresponding module */
|
||||||
if (dt) {
|
for (dt = *first; dt; dt = dt->m_next) {
|
||||||
if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {
|
if (strcmp(dt->m_name, mod) == 0)
|
||||||
char* new_opt = NULL;
|
break;
|
||||||
while ((opt = parse_command_string(opt, &new_opt))) {
|
}
|
||||||
dt->m_options = append_option(dt->m_options, new_opt);
|
if (dt) {
|
||||||
}
|
if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {
|
||||||
} else {
|
char* new_opt = NULL;
|
||||||
dt->m_options = append_option(dt->m_options, opt);
|
while ((opt = parse_command_string(opt, &new_opt))) {
|
||||||
|
dt->m_options = append_option(dt->m_options, new_opt);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
dt->m_options = append_option(dt->m_options, opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) {
|
}
|
||||||
int fdi; char *filename;
|
} else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) {
|
||||||
|
int fdi;
|
||||||
filename = skip_whitespace(buffer + 8);
|
char *filename;
|
||||||
|
|
||||||
if ((fdi = open(filename, O_RDONLY)) >= 0) {
|
filename = skip_whitespace(buffer + 8);
|
||||||
include_conf(first, current, buffer, buflen, fdi);
|
fdi = open(filename, O_RDONLY);
|
||||||
close(fdi);
|
if (fdi >= 0) {
|
||||||
}
|
include_conf(first, current, buffer, buflen, fdi);
|
||||||
|
close(fdi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} /* while (reads(...)) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -327,9 +333,8 @@ static struct dep_t *build_dep(void)
|
|||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
struct utsname un;
|
struct utsname un;
|
||||||
struct dep_t *first = 0;
|
struct dep_t *first = NULL;
|
||||||
struct dep_t *current = 0;
|
struct dep_t *current = NULL;
|
||||||
char buffer[2048];
|
|
||||||
char *filename;
|
char *filename;
|
||||||
int continuation_line = 0;
|
int continuation_line = 0;
|
||||||
int k_version;
|
int k_version;
|
||||||
@ -350,16 +355,16 @@ static struct dep_t *build_dep(void)
|
|||||||
/* Ok, that didn't work. Fall back to looking in /lib/modules */
|
/* Ok, that didn't work. Fall back to looking in /lib/modules */
|
||||||
fd = open("/lib/modules/modules.dep", O_RDONLY);
|
fd = open("/lib/modules/modules.dep", O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return 0;
|
bb_error_msg_and_die("cannot parse modules.dep");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (reads(fd, buffer, sizeof(buffer))) {
|
while (reads(fd, line_buffer, sizeof(line_buffer))) {
|
||||||
int l = strlen(buffer);
|
int l = strlen(line_buffer);
|
||||||
char *p = 0;
|
char *p = 0;
|
||||||
|
|
||||||
while (l > 0 && isspace(buffer[l-1])) {
|
while (l > 0 && isspace(line_buffer[l-1])) {
|
||||||
buffer[l-1] = 0;
|
line_buffer[l-1] = '\0';
|
||||||
l--;
|
l--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +376,7 @@ static struct dep_t *build_dep(void)
|
|||||||
/* Is this a new module dep description? */
|
/* Is this a new module dep description? */
|
||||||
if (!continuation_line) {
|
if (!continuation_line) {
|
||||||
/* find the dep beginning */
|
/* find the dep beginning */
|
||||||
char *col = strchr(buffer, ':');
|
char *col = strchr(line_buffer, ':');
|
||||||
char *dot = col;
|
char *dot = col;
|
||||||
|
|
||||||
if (col) {
|
if (col) {
|
||||||
@ -381,53 +386,52 @@ static struct dep_t *build_dep(void)
|
|||||||
char *mod;
|
char *mod;
|
||||||
|
|
||||||
/* Find the beginning of the module file name */
|
/* Find the beginning of the module file name */
|
||||||
*col = 0;
|
*col = '\0';
|
||||||
mods = bb_basename(buffer);
|
mods = bb_basename(line_buffer);
|
||||||
|
|
||||||
/* find the path of the module */
|
/* find the path of the module */
|
||||||
modpath = strchr(buffer, '/'); /* ... and this is the path */
|
modpath = strchr(line_buffer, '/'); /* ... and this is the path */
|
||||||
if (!modpath)
|
if (!modpath)
|
||||||
modpath = buffer; /* module with no path */
|
modpath = line_buffer; /* module with no path */
|
||||||
/* find the end of the module name in the file name */
|
/* find the end of the module name in the file name */
|
||||||
if (ENABLE_FEATURE_2_6_MODULES &&
|
if (ENABLE_FEATURE_2_6_MODULES &&
|
||||||
(k_version > 4) && (*(col-3) == '.') &&
|
(k_version > 4) && (col[-3] == '.') &&
|
||||||
(*(col-2) == 'k') && (*(col-1) == 'o'))
|
(col[-2] == 'k') && (col[-1] == 'o'))
|
||||||
dot = col - 3;
|
dot = col - 3;
|
||||||
else
|
else if ((col[-2] == '.') && (col[-1] == 'o'))
|
||||||
if ((*(col-2) == '.') && (*(col-1) == 'o'))
|
dot = col - 2;
|
||||||
dot = col - 2;
|
|
||||||
|
|
||||||
mod = xstrndup(mods, dot - mods);
|
mod = xstrndup(mods, dot - mods);
|
||||||
|
|
||||||
/* enqueue new module */
|
/* enqueue new module */
|
||||||
if (!current) {
|
if (!current) {
|
||||||
first = current = xmalloc(sizeof(struct dep_t));
|
first = current = xzalloc(sizeof(struct dep_t));
|
||||||
} else {
|
} else {
|
||||||
current->m_next = xmalloc(sizeof(struct dep_t));
|
current->m_next = xzalloc(sizeof(struct dep_t));
|
||||||
current = current->m_next;
|
current = current->m_next;
|
||||||
}
|
}
|
||||||
current->m_name = mod;
|
current->m_name = mod;
|
||||||
current->m_path = xstrdup(modpath);
|
current->m_path = xstrdup(modpath);
|
||||||
current->m_options = NULL;
|
/*current->m_options = NULL; - xzalloc did it*/
|
||||||
current->m_isalias = 0;
|
/*current->m_isalias = 0;*/
|
||||||
current->m_depcnt = 0;
|
/*current->m_depcnt = 0;*/
|
||||||
current->m_deparr = 0;
|
/*current->m_deparr = 0;*/
|
||||||
current->m_next = 0;
|
/*current->m_next = 0;*/
|
||||||
|
|
||||||
p = col + 1;
|
p = col + 1;
|
||||||
} else
|
} else
|
||||||
/* this line is not a dep description */
|
/* this line is not a dep description */
|
||||||
p = 0;
|
p = NULL;
|
||||||
} else
|
} else
|
||||||
/* It's a dep description continuation */
|
/* It's a dep description continuation */
|
||||||
p = buffer;
|
p = line_buffer;
|
||||||
|
|
||||||
while (p && *p && isblank(*p))
|
while (p && *p && isblank(*p))
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
/* p points to the first dependable module; if NULL, no dependable module */
|
/* p points to the first dependable module; if NULL, no dependable module */
|
||||||
if (p && *p) {
|
if (p && *p) {
|
||||||
char *end = &buffer[l-1];
|
char *end = &line_buffer[l-1];
|
||||||
const char *deps;
|
const char *deps;
|
||||||
char *dep;
|
char *dep;
|
||||||
char *next;
|
char *next;
|
||||||
@ -440,7 +444,7 @@ static struct dep_t *build_dep(void)
|
|||||||
/* search the end of the dependency */
|
/* search the end of the dependency */
|
||||||
next = strchr(p, ' ');
|
next = strchr(p, ' ');
|
||||||
if (next) {
|
if (next) {
|
||||||
*next = 0;
|
*next = '\0';
|
||||||
next--;
|
next--;
|
||||||
} else
|
} else
|
||||||
next = end;
|
next = end;
|
||||||
@ -454,12 +458,11 @@ static struct dep_t *build_dep(void)
|
|||||||
|
|
||||||
/* find the end of the module name in the file name */
|
/* find the end of the module name in the file name */
|
||||||
if (ENABLE_FEATURE_2_6_MODULES
|
if (ENABLE_FEATURE_2_6_MODULES
|
||||||
&& (k_version > 4) && (*(next-2) == '.')
|
&& (k_version > 4) && (next[-2] == '.')
|
||||||
&& (*(next-1) == 'k') && (*next == 'o'))
|
&& (next[-1] == 'k') && (next[0] == 'o'))
|
||||||
ext = 3;
|
ext = 3;
|
||||||
else
|
else if ((next[-1] == '.') && (next[0] == 'o'))
|
||||||
if ((*(next-1) == '.') && (*next == 'o'))
|
ext = 2;
|
||||||
ext = 2;
|
|
||||||
|
|
||||||
/* Cope with blank lines */
|
/* Cope with blank lines */
|
||||||
if ((next-deps-ext+1) <= 0)
|
if ((next-deps-ext+1) <= 0)
|
||||||
@ -477,11 +480,8 @@ static struct dep_t *build_dep(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* is there other dependable module(s) ? */
|
/* is there other dependable module(s) ? */
|
||||||
if (buffer[l-1] == '\\')
|
continuation_line = (line_buffer[l-1] == '\\');
|
||||||
continuation_line = 1;
|
} /* while (reads(...)) */
|
||||||
else
|
|
||||||
continuation_line = 0;
|
|
||||||
}
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -498,7 +498,7 @@ static struct dep_t *build_dep(void)
|
|||||||
fd = open("/etc/conf.modules", O_RDONLY);
|
fd = open("/etc/conf.modules", O_RDONLY);
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
include_conf(&first, ¤t, buffer, sizeof(buffer), fd);
|
include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,7 +515,7 @@ static struct dep_t *build_dep(void)
|
|||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
include_conf(&first, ¤t, buffer, sizeof(buffer), fd);
|
include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,7 +530,7 @@ static struct dep_t *build_dep(void)
|
|||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
include_conf(&first, ¤t, buffer, sizeof(buffer), fd);
|
include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,16 +542,15 @@ static struct dep_t *build_dep(void)
|
|||||||
static int already_loaded(const char *name)
|
static int already_loaded(const char *name)
|
||||||
{
|
{
|
||||||
int fd, ret = 0;
|
int fd, ret = 0;
|
||||||
char buffer[4096];
|
|
||||||
|
|
||||||
fd = open("/proc/modules", O_RDONLY);
|
fd = open("/proc/modules", O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (reads(fd, buffer, sizeof(buffer))) {
|
while (reads(fd, line_buffer, sizeof(line_buffer))) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = strchr (buffer, ' ');
|
p = strchr(line_buffer, ' ');
|
||||||
if (p) {
|
if (p) {
|
||||||
const char *n;
|
const char *n;
|
||||||
|
|
||||||
@ -559,8 +558,8 @@ static int already_loaded(const char *name)
|
|||||||
// the idiosyncrasy that _ and - are interchangeable because the
|
// the idiosyncrasy that _ and - are interchangeable because the
|
||||||
// 2.6 kernel does weird things.
|
// 2.6 kernel does weird things.
|
||||||
|
|
||||||
*p = 0;
|
*p = '\0';
|
||||||
for (p = buffer, n = name; ; p++, n++) {
|
for (p = line_buffer, n = name; ; p++, n++) {
|
||||||
if (*p != *n) {
|
if (*p != *n) {
|
||||||
if ((*p == '_' || *p == '-') && (*n == '_' || *n == '-'))
|
if ((*p == '_' || *p == '-') && (*n == '_' || *n == '-'))
|
||||||
continue;
|
continue;
|
||||||
@ -574,8 +573,8 @@ static int already_loaded(const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
close (fd);
|
close(fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +622,7 @@ static int mod_process(const struct mod_list_t *list, int do_insert)
|
|||||||
while (opts) {
|
while (opts) {
|
||||||
/* Add one more option */
|
/* Add one more option */
|
||||||
argc++;
|
argc++;
|
||||||
argv = xrealloc(argv,(argc + 1)* sizeof(char*));
|
argv = xrealloc(argv, (argc + 1) * sizeof(char*));
|
||||||
argv[argc-1] = opts->m_opt_val;
|
argv[argc-1] = opts->m_opt_val;
|
||||||
opts = opts->m_next;
|
opts = opts->m_next;
|
||||||
}
|
}
|
||||||
@ -698,9 +697,8 @@ static int check_pattern(const char* pat_src, const char* mod_src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
|
||||||
return fnmatch(pat_src, mod_src, 0);
|
|
||||||
}
|
}
|
||||||
|
return fnmatch(pat_src, mod_src, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -712,8 +710,8 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
|
|||||||
{
|
{
|
||||||
struct mod_list_t *find;
|
struct mod_list_t *find;
|
||||||
struct dep_t *dt;
|
struct dep_t *dt;
|
||||||
struct mod_opt_t *opt = 0;
|
struct mod_opt_t *opt = NULL;
|
||||||
char *path = 0;
|
char *path = NULL;
|
||||||
|
|
||||||
/* Search for the given module name amongst all dependency rules.
|
/* Search for the given module name amongst all dependency rules.
|
||||||
* The module name in a dependency rule can be a shell pattern,
|
* The module name in a dependency rule can be a shell pattern,
|
||||||
@ -765,8 +763,8 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
|
|||||||
|
|
||||||
// search for duplicates
|
// search for duplicates
|
||||||
for (find = *head; find; find = find->m_next) {
|
for (find = *head; find; find = find->m_next) {
|
||||||
if (!strcmp(mod, find->m_name)) {
|
if (strcmp(mod, find->m_name) == 0) {
|
||||||
// found ->dequeue it
|
// found -> dequeue it
|
||||||
|
|
||||||
if (find->m_prev)
|
if (find->m_prev)
|
||||||
find->m_prev->m_next = find->m_next;
|
find->m_prev->m_next = find->m_next;
|
||||||
@ -783,7 +781,7 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!find) { // did not find a duplicate
|
if (!find) { // did not find a duplicate
|
||||||
find = xmalloc(sizeof(struct mod_list_t));
|
find = xzalloc(sizeof(struct mod_list_t));
|
||||||
find->m_name = mod;
|
find->m_name = mod;
|
||||||
find->m_path = path;
|
find->m_path = path;
|
||||||
find->m_options = opt;
|
find->m_options = opt;
|
||||||
@ -793,7 +791,7 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
|
|||||||
if (*tail)
|
if (*tail)
|
||||||
(*tail)->m_next = find;
|
(*tail)->m_next = find;
|
||||||
find->m_prev = *tail;
|
find->m_prev = *tail;
|
||||||
find->m_next = 0;
|
/*find->m_next = NULL; - xzalloc did it */
|
||||||
|
|
||||||
if (!*head)
|
if (!*head)
|
||||||
*head = find;
|
*head = find;
|
||||||
@ -868,11 +866,11 @@ int modprobe_main(int argc, char **argv)
|
|||||||
char *unused;
|
char *unused;
|
||||||
|
|
||||||
opt_complementary = "?V-:q-v:v-q";
|
opt_complementary = "?V-:q-v:v-q";
|
||||||
main_opts = getopt32(argv, "acdklnqrst:vVC:",
|
getopt32(argv, MAIN_OPT_STR, &unused, &unused);
|
||||||
&unused, &unused);
|
|
||||||
if (main_opts & (DUMP_CONF_EXIT | LIST_ALL))
|
if (option_mask32 & (DUMP_CONF_EXIT | LIST_ALL))
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
if (main_opts & (RESTRICT_DIR | CONFIG_FILE))
|
if (option_mask32 & (RESTRICT_DIR | CONFIG_FILE))
|
||||||
bb_error_msg_and_die("-t and -C not supported");
|
bb_error_msg_and_die("-t and -C not supported");
|
||||||
|
|
||||||
depend = build_dep();
|
depend = build_dep();
|
||||||
@ -882,8 +880,8 @@ int modprobe_main(int argc, char **argv)
|
|||||||
|
|
||||||
if (remove_opt) {
|
if (remove_opt) {
|
||||||
do {
|
do {
|
||||||
if (mod_remove(optind < argc ?
|
/* argv[optind] can be NULL here */
|
||||||
argv[optind] : NULL)) {
|
if (mod_remove(argv[optind])) {
|
||||||
bb_error_msg("failed to remove module %s",
|
bb_error_msg("failed to remove module %s",
|
||||||
argv[optind]);
|
argv[optind]);
|
||||||
rc = EXIT_FAILURE;
|
rc = EXIT_FAILURE;
|
||||||
|
Loading…
Reference in New Issue
Block a user