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 <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;

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
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 ) {