Support module tainting

-Erik
This commit is contained in:
Eric Andersen 2002-09-16 05:30:24 +00:00
parent 061c900176
commit 166fa4684f
2 changed files with 146 additions and 4 deletions

View File

@ -71,6 +71,7 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <getopt.h> #include <getopt.h>
#include <fcntl.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include "busybox.h" #include "busybox.h"
@ -233,7 +234,7 @@
#ifndef MODUTILS_MODULE_H #ifndef MODUTILS_MODULE_H
static const int MODUTILS_MODULE_H = 1; static const int MODUTILS_MODULE_H = 1;
#ident "$Id: insmod.c,v 1.89 2002/07/21 17:33:26 sandman Exp $" #ident "$Id: insmod.c,v 1.90 2002/09/16 05:30:24 andersen Exp $"
/* This file contains the structures used by the 2.0 and 2.1 kernels. /* This file contains the structures used by the 2.0 and 2.1 kernels.
We do not use the kernel headers directly because we do not wish We do not use the kernel headers directly because we do not wish
@ -454,7 +455,7 @@ int delete_module(const char *);
#ifndef MODUTILS_OBJ_H #ifndef MODUTILS_OBJ_H
static const int MODUTILS_OBJ_H = 1; static const int MODUTILS_OBJ_H = 1;
#ident "$Id: insmod.c,v 1.89 2002/07/21 17:33:26 sandman Exp $" #ident "$Id: insmod.c,v 1.90 2002/09/16 05:30:24 andersen Exp $"
/* The relocatable object is manipulated using elfin types. */ /* The relocatable object is manipulated using elfin types. */
@ -3421,7 +3422,117 @@ static void hide_special_symbols(struct obj_file *f)
ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info)); ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
} }
static int obj_gpl_license(struct obj_file *f, const char **license)
{
struct obj_section *sec;
/* This list must match *exactly* the list of allowable licenses in
* linux/include/linux/module.h. Checking for leading "GPL" will not
* work, somebody will use "GPL sucks, this is proprietary".
*/
static const char *gpl_licenses[] = {
"GPL",
"GPL v2",
"GPL and additional rights",
"Dual BSD/GPL",
"Dual MPL/GPL",
};
if ((sec = obj_find_section(f, ".modinfo"))) {
const char *value, *ptr, *endptr;
ptr = sec->contents;
endptr = ptr + sec->header.sh_size;
while (ptr < endptr) {
if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
int i;
if (license)
*license = value+1;
for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
if (strcmp(value+1, gpl_licenses[i]) == 0)
return(0);
}
return(2);
}
if (strchr(ptr, '\0'))
ptr = strchr(ptr, '\0') + 1;
else
ptr = endptr;
}
}
return(1);
}
#define TAINT_FILENAME "/proc/sys/kernel/tainted"
#define TAINT_PROPRIETORY_MODULE (1<<0)
#define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2)
#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
static void set_tainted(struct obj_file *f, int fd, char *m_name,
int kernel_has_tainted, int taint, const char *text1, const char *text2)
{
char buf[80];
int oldval;
static int first = 1;
if (fd < 0 && !kernel_has_tainted)
return; /* New modutils on old kernel */
printf("Warning: loading %s will taint the kernel: %s%s\n",
m_name, text1, text2);
if (first) {
printf(" See %s for information about tainted modules\n", TAINT_URL);
first = 0;
}
if (fd >= 0) {
read(fd, buf, sizeof(buf)-1);
buf[sizeof(buf)-1] = '\0';
oldval = strtoul(buf, NULL, 10);
sprintf(buf, "%d\n", oldval | taint);
write(fd, buf, strlen(buf));
}
}
/* Check if loading this module will taint the kernel. */
static void check_tainted_module(struct obj_file *f, char *m_name)
{
static const char tainted_file[] = TAINT_FILENAME;
int fd, kernel_has_tainted;
const char *ptr;
kernel_has_tainted = 1;
if ((fd = open(tainted_file, O_RDWR)) < 0) {
if (errno == ENOENT)
kernel_has_tainted = 0;
else if (errno == EACCES)
kernel_has_tainted = 1;
else {
perror(tainted_file);
kernel_has_tainted = 0;
}
}
switch (obj_gpl_license(f, &ptr)) {
case 0:
break;
case 1:
set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
break;
case 2:
/* The module has a non-GPL license so we pretend that the
* kernel always has a taint flag to get a warning even on
* kernels without the proc flag.
*/
set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
break;
default:
set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
break;
}
if (flag_force_load)
set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
if (fd >= 0)
close(fd);
}
extern int insmod_main( int argc, char **argv) extern int insmod_main( int argc, char **argv)
{ {
@ -3657,6 +3768,7 @@ extern int insmod_main( int argc, char **argv)
goto out; goto out;
} }
obj_allocate_commons(f); obj_allocate_commons(f);
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;

View File

@ -41,6 +41,32 @@
#define TAINT_FILENAME "/proc/sys/kernel/tainted"
#define TAINT_PROPRIETORY_MODULE (1<<0)
#define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2)
void check_tainted(void)
{
int tainted;
FILE *f;
tainted = 0;
if ((f = fopen(TAINT_FILENAME, "r"))) {
fscanf(f, "%d", &tainted);
fclose(f);
}
if (f && tainted) {
printf(" Tainted: %c%c%c",
tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
}
else {
printf(" Not tainted");
}
}
#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE #ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
struct module_info struct module_info
@ -99,7 +125,10 @@ extern int lsmod_main(int argc, char **argv)
} }
deps = xmalloc(depsize = 256); deps = xmalloc(depsize = 256);
printf("Module Size Used by\n"); printf("Module Size Used by");
check_tainted();
printf("\n");
for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) { for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) { if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
if (errno == ENOENT) { if (errno == ENOENT) {
@ -149,7 +178,8 @@ extern int lsmod_main(int argc, char **argv)
int fd, i; int fd, i;
char line[128]; char line[128];
puts("Module Size Used by"); printf("Module Size Used by");
check_tainted();
fflush(stdout); fflush(stdout);
if ((fd = open("/proc/modules", O_RDONLY)) >= 0 ) { if ((fd = open("/proc/modules", O_RDONLY)) >= 0 ) {