diff options
-rw-r--r-- | modutils/insmod.c | 116 | ||||
-rw-r--r-- | modutils/lsmod.c | 34 |
2 files changed, 146 insertions, 4 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c index 856c12a63..b246d90af 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
@@ -71,6 +71,7 @@ | |||
71 | #include <assert.h> | 71 | #include <assert.h> |
72 | #include <string.h> | 72 | #include <string.h> |
73 | #include <getopt.h> | 73 | #include <getopt.h> |
74 | #include <fcntl.h> | ||
74 | #include <sys/utsname.h> | 75 | #include <sys/utsname.h> |
75 | #include "busybox.h" | 76 | #include "busybox.h" |
76 | 77 | ||
@@ -233,7 +234,7 @@ | |||
233 | #ifndef MODUTILS_MODULE_H | 234 | #ifndef MODUTILS_MODULE_H |
234 | static const int MODUTILS_MODULE_H = 1; | 235 | static const int MODUTILS_MODULE_H = 1; |
235 | 236 | ||
236 | #ident "$Id: insmod.c,v 1.89 2002/07/21 17:33:26 sandman Exp $" | 237 | #ident "$Id: insmod.c,v 1.90 2002/09/16 05:30:24 andersen Exp $" |
237 | 238 | ||
238 | /* This file contains the structures used by the 2.0 and 2.1 kernels. | 239 | /* This file contains the structures used by the 2.0 and 2.1 kernels. |
239 | We do not use the kernel headers directly because we do not wish | 240 | We do not use the kernel headers directly because we do not wish |
@@ -454,7 +455,7 @@ int delete_module(const char *); | |||
454 | #ifndef MODUTILS_OBJ_H | 455 | #ifndef MODUTILS_OBJ_H |
455 | static const int MODUTILS_OBJ_H = 1; | 456 | static const int MODUTILS_OBJ_H = 1; |
456 | 457 | ||
457 | #ident "$Id: insmod.c,v 1.89 2002/07/21 17:33:26 sandman Exp $" | 458 | #ident "$Id: insmod.c,v 1.90 2002/09/16 05:30:24 andersen Exp $" |
458 | 459 | ||
459 | /* The relocatable object is manipulated using elfin types. */ | 460 | /* The relocatable object is manipulated using elfin types. */ |
460 | 461 | ||
@@ -3421,7 +3422,117 @@ static void hide_special_symbols(struct obj_file *f) | |||
3421 | ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info)); | 3422 | ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info)); |
3422 | } | 3423 | } |
3423 | 3424 | ||
3425 | static int obj_gpl_license(struct obj_file *f, const char **license) | ||
3426 | { | ||
3427 | struct obj_section *sec; | ||
3428 | /* This list must match *exactly* the list of allowable licenses in | ||
3429 | * linux/include/linux/module.h. Checking for leading "GPL" will not | ||
3430 | * work, somebody will use "GPL sucks, this is proprietary". | ||
3431 | */ | ||
3432 | static const char *gpl_licenses[] = { | ||
3433 | "GPL", | ||
3434 | "GPL v2", | ||
3435 | "GPL and additional rights", | ||
3436 | "Dual BSD/GPL", | ||
3437 | "Dual MPL/GPL", | ||
3438 | }; | ||
3439 | |||
3440 | if ((sec = obj_find_section(f, ".modinfo"))) { | ||
3441 | const char *value, *ptr, *endptr; | ||
3442 | ptr = sec->contents; | ||
3443 | endptr = ptr + sec->header.sh_size; | ||
3444 | while (ptr < endptr) { | ||
3445 | if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) { | ||
3446 | int i; | ||
3447 | if (license) | ||
3448 | *license = value+1; | ||
3449 | for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) { | ||
3450 | if (strcmp(value+1, gpl_licenses[i]) == 0) | ||
3451 | return(0); | ||
3452 | } | ||
3453 | return(2); | ||
3454 | } | ||
3455 | if (strchr(ptr, '\0')) | ||
3456 | ptr = strchr(ptr, '\0') + 1; | ||
3457 | else | ||
3458 | ptr = endptr; | ||
3459 | } | ||
3460 | } | ||
3461 | return(1); | ||
3462 | } | ||
3463 | |||
3464 | #define TAINT_FILENAME "/proc/sys/kernel/tainted" | ||
3465 | #define TAINT_PROPRIETORY_MODULE (1<<0) | ||
3466 | #define TAINT_FORCED_MODULE (1<<1) | ||
3467 | #define TAINT_UNSAFE_SMP (1<<2) | ||
3468 | #define TAINT_URL "http://www.tux.org/lkml/#export-tainted" | ||
3469 | |||
3470 | static void set_tainted(struct obj_file *f, int fd, char *m_name, | ||
3471 | int kernel_has_tainted, int taint, const char *text1, const char *text2) | ||
3472 | { | ||
3473 | char buf[80]; | ||
3474 | int oldval; | ||
3475 | static int first = 1; | ||
3476 | if (fd < 0 && !kernel_has_tainted) | ||
3477 | return; /* New modutils on old kernel */ | ||
3478 | printf("Warning: loading %s will taint the kernel: %s%s\n", | ||
3479 | m_name, text1, text2); | ||
3480 | if (first) { | ||
3481 | printf(" See %s for information about tainted modules\n", TAINT_URL); | ||
3482 | first = 0; | ||
3483 | } | ||
3484 | if (fd >= 0) { | ||
3485 | read(fd, buf, sizeof(buf)-1); | ||
3486 | buf[sizeof(buf)-1] = '\0'; | ||
3487 | oldval = strtoul(buf, NULL, 10); | ||
3488 | sprintf(buf, "%d\n", oldval | taint); | ||
3489 | write(fd, buf, strlen(buf)); | ||
3490 | } | ||
3491 | } | ||
3492 | |||
3493 | /* Check if loading this module will taint the kernel. */ | ||
3494 | static void check_tainted_module(struct obj_file *f, char *m_name) | ||
3495 | { | ||
3496 | static const char tainted_file[] = TAINT_FILENAME; | ||
3497 | int fd, kernel_has_tainted; | ||
3498 | const char *ptr; | ||
3499 | |||
3500 | kernel_has_tainted = 1; | ||
3501 | if ((fd = open(tainted_file, O_RDWR)) < 0) { | ||
3502 | if (errno == ENOENT) | ||
3503 | kernel_has_tainted = 0; | ||
3504 | else if (errno == EACCES) | ||
3505 | kernel_has_tainted = 1; | ||
3506 | else { | ||
3507 | perror(tainted_file); | ||
3508 | kernel_has_tainted = 0; | ||
3509 | } | ||
3510 | } | ||
3424 | 3511 | ||
3512 | switch (obj_gpl_license(f, &ptr)) { | ||
3513 | case 0: | ||
3514 | break; | ||
3515 | case 1: | ||
3516 | set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); | ||
3517 | break; | ||
3518 | case 2: | ||
3519 | /* The module has a non-GPL license so we pretend that the | ||
3520 | * kernel always has a taint flag to get a warning even on | ||
3521 | * kernels without the proc flag. | ||
3522 | */ | ||
3523 | set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); | ||
3524 | break; | ||
3525 | default: | ||
3526 | set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); | ||
3527 | break; | ||
3528 | } | ||
3529 | |||
3530 | if (flag_force_load) | ||
3531 | set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); | ||
3532 | |||
3533 | if (fd >= 0) | ||
3534 | close(fd); | ||
3535 | } | ||
3425 | 3536 | ||
3426 | extern int insmod_main( int argc, char **argv) | 3537 | extern int insmod_main( int argc, char **argv) |
3427 | { | 3538 | { |
@@ -3657,6 +3768,7 @@ extern int insmod_main( int argc, char **argv) | |||
3657 | goto out; | 3768 | goto out; |
3658 | } | 3769 | } |
3659 | obj_allocate_commons(f); | 3770 | obj_allocate_commons(f); |
3771 | check_tainted_module(f, m_name); | ||
3660 | 3772 | ||
3661 | /* done with the module name, on to the optional var=value arguments */ | 3773 | /* done with the module name, on to the optional var=value arguments */ |
3662 | ++optind; | 3774 | ++optind; |
diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 5cb585bab..3618ebe0b 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c | |||
@@ -41,6 +41,32 @@ | |||
41 | 41 | ||
42 | 42 | ||
43 | 43 | ||
44 | #define TAINT_FILENAME "/proc/sys/kernel/tainted" | ||
45 | #define TAINT_PROPRIETORY_MODULE (1<<0) | ||
46 | #define TAINT_FORCED_MODULE (1<<1) | ||
47 | #define TAINT_UNSAFE_SMP (1<<2) | ||
48 | |||
49 | void check_tainted(void) | ||
50 | { | ||
51 | int tainted; | ||
52 | FILE *f; | ||
53 | |||
54 | tainted = 0; | ||
55 | if ((f = fopen(TAINT_FILENAME, "r"))) { | ||
56 | fscanf(f, "%d", &tainted); | ||
57 | fclose(f); | ||
58 | } | ||
59 | if (f && tainted) { | ||
60 | printf(" Tainted: %c%c%c", | ||
61 | tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G', | ||
62 | tainted & TAINT_FORCED_MODULE ? 'F' : ' ', | ||
63 | tainted & TAINT_UNSAFE_SMP ? 'S' : ' '); | ||
64 | } | ||
65 | else { | ||
66 | printf(" Not tainted"); | ||
67 | } | ||
68 | } | ||
69 | |||
44 | #ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE | 70 | #ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE |
45 | 71 | ||
46 | struct module_info | 72 | struct module_info |
@@ -99,7 +125,10 @@ extern int lsmod_main(int argc, char **argv) | |||
99 | } | 125 | } |
100 | 126 | ||
101 | deps = xmalloc(depsize = 256); | 127 | deps = xmalloc(depsize = 256); |
102 | printf("Module Size Used by\n"); | 128 | printf("Module Size Used by"); |
129 | check_tainted(); | ||
130 | printf("\n"); | ||
131 | |||
103 | for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) { | 132 | for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) { |
104 | if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) { | 133 | if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) { |
105 | if (errno == ENOENT) { | 134 | if (errno == ENOENT) { |
@@ -149,7 +178,8 @@ extern int lsmod_main(int argc, char **argv) | |||
149 | int fd, i; | 178 | int fd, i; |
150 | char line[128]; | 179 | char line[128]; |
151 | 180 | ||
152 | puts("Module Size Used by"); | 181 | printf("Module Size Used by"); |
182 | check_tainted(); | ||
153 | fflush(stdout); | 183 | fflush(stdout); |
154 | 184 | ||
155 | if ((fd = open("/proc/modules", O_RDONLY)) >= 0 ) { | 185 | if ((fd = open("/proc/modules", O_RDONLY)) >= 0 ) { |