Support module tainting
-Erik
This commit is contained in:
parent
061c900176
commit
166fa4684f
@ -71,6 +71,7 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include "busybox.h"
|
||||
|
||||
@ -233,7 +234,7 @@
|
||||
#ifndef MODUTILS_MODULE_H
|
||||
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.
|
||||
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
|
||||
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. */
|
||||
|
||||
@ -3421,7 +3422,117 @@ static void hide_special_symbols(struct obj_file *f)
|
||||
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)
|
||||
{
|
||||
@ -3657,6 +3768,7 @@ extern int insmod_main( int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
obj_allocate_commons(f);
|
||||
check_tainted_module(f, m_name);
|
||||
|
||||
/* done with the module name, on to the optional var=value arguments */
|
||||
++optind;
|
||||
|
@ -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
|
||||
|
||||
struct module_info
|
||||
@ -99,7 +125,10 @@ extern int lsmod_main(int argc, char **argv)
|
||||
}
|
||||
|
||||
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++) {
|
||||
if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
|
||||
if (errno == ENOENT) {
|
||||
@ -149,7 +178,8 @@ extern int lsmod_main(int argc, char **argv)
|
||||
int fd, i;
|
||||
char line[128];
|
||||
|
||||
puts("Module Size Used by");
|
||||
printf("Module Size Used by");
|
||||
check_tainted();
|
||||
fflush(stdout);
|
||||
|
||||
if ((fd = open("/proc/modules", O_RDONLY)) >= 0 ) {
|
||||
|
Loading…
Reference in New Issue
Block a user