diff options
-rw-r--r-- | include/linux/license.h | 14 | ||||
-rw-r--r-- | kernel/module.c | 11 | ||||
-rw-r--r-- | scripts/mod/modpost.c | 71 | ||||
-rw-r--r-- | scripts/mod/modpost.h | 1 |
4 files changed, 85 insertions, 12 deletions
diff --git a/include/linux/license.h b/include/linux/license.h new file mode 100644 index 000000000000..decdbf43cb5c --- /dev/null +++ b/include/linux/license.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef __LICENSE_H | ||
2 | #define __LICENSE_H | ||
3 | |||
4 | static inline int license_is_gpl_compatible(const char *license) | ||
5 | { | ||
6 | return (strcmp(license, "GPL") == 0 | ||
7 | || strcmp(license, "GPL v2") == 0 | ||
8 | || strcmp(license, "GPL and additional rights") == 0 | ||
9 | || strcmp(license, "Dual BSD/GPL") == 0 | ||
10 | || strcmp(license, "Dual MIT/GPL") == 0 | ||
11 | || strcmp(license, "Dual MPL/GPL") == 0); | ||
12 | } | ||
13 | |||
14 | #endif | ||
diff --git a/kernel/module.c b/kernel/module.c index bbe04862e1b0..690381508d09 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
44 | #include <asm/semaphore.h> | 44 | #include <asm/semaphore.h> |
45 | #include <asm/cacheflush.h> | 45 | #include <asm/cacheflush.h> |
46 | #include <linux/license.h> | ||
46 | 47 | ||
47 | #if 0 | 48 | #if 0 |
48 | #define DEBUGP printk | 49 | #define DEBUGP printk |
@@ -1248,16 +1249,6 @@ static void layout_sections(struct module *mod, | |||
1248 | } | 1249 | } |
1249 | } | 1250 | } |
1250 | 1251 | ||
1251 | static inline int license_is_gpl_compatible(const char *license) | ||
1252 | { | ||
1253 | return (strcmp(license, "GPL") == 0 | ||
1254 | || strcmp(license, "GPL v2") == 0 | ||
1255 | || strcmp(license, "GPL and additional rights") == 0 | ||
1256 | || strcmp(license, "Dual BSD/GPL") == 0 | ||
1257 | || strcmp(license, "Dual MIT/GPL") == 0 | ||
1258 | || strcmp(license, "Dual MPL/GPL") == 0); | ||
1259 | } | ||
1260 | |||
1261 | static void set_license(struct module *mod, const char *license) | 1252 | static void set_license(struct module *mod, const char *license) |
1262 | { | 1253 | { |
1263 | if (!license) | 1254 | if (!license) |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index ba2e4fc2af20..baa4d83d29a8 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <ctype.h> | 14 | #include <ctype.h> |
15 | #include "modpost.h" | 15 | #include "modpost.h" |
16 | #include "../../include/linux/license.h" | ||
16 | 17 | ||
17 | /* Are we using CONFIG_MODVERSIONS? */ | 18 | /* Are we using CONFIG_MODVERSIONS? */ |
18 | int modversions = 0; | 19 | int modversions = 0; |
@@ -99,6 +100,7 @@ static struct module *new_module(char *modname) | |||
99 | 100 | ||
100 | /* add to list */ | 101 | /* add to list */ |
101 | mod->name = p; | 102 | mod->name = p; |
103 | mod->gpl_compatible = -1; | ||
102 | mod->next = modules; | 104 | mod->next = modules; |
103 | modules = mod; | 105 | modules = mod; |
104 | 106 | ||
@@ -493,13 +495,18 @@ static char *next_string(char *string, unsigned long *secsize) | |||
493 | return string; | 495 | return string; |
494 | } | 496 | } |
495 | 497 | ||
496 | static char *get_modinfo(void *modinfo, unsigned long modinfo_len, | 498 | static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len, |
497 | const char *tag) | 499 | const char *tag, char *info) |
498 | { | 500 | { |
499 | char *p; | 501 | char *p; |
500 | unsigned int taglen = strlen(tag); | 502 | unsigned int taglen = strlen(tag); |
501 | unsigned long size = modinfo_len; | 503 | unsigned long size = modinfo_len; |
502 | 504 | ||
505 | if (info) { | ||
506 | size -= info - (char *)modinfo; | ||
507 | modinfo = next_string(info, &size); | ||
508 | } | ||
509 | |||
503 | for (p = modinfo; p; p = next_string(p, &size)) { | 510 | for (p = modinfo; p; p = next_string(p, &size)) { |
504 | if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') | 511 | if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') |
505 | return p + taglen + 1; | 512 | return p + taglen + 1; |
@@ -507,6 +514,13 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, | |||
507 | return NULL; | 514 | return NULL; |
508 | } | 515 | } |
509 | 516 | ||
517 | static char *get_modinfo(void *modinfo, unsigned long modinfo_len, | ||
518 | const char *tag) | ||
519 | |||
520 | { | ||
521 | return get_next_modinfo(modinfo, modinfo_len, tag, NULL); | ||
522 | } | ||
523 | |||
510 | /** | 524 | /** |
511 | * Test if string s ends in string sub | 525 | * Test if string s ends in string sub |
512 | * return 0 if match | 526 | * return 0 if match |
@@ -981,6 +995,7 @@ static void read_symbols(char *modname) | |||
981 | { | 995 | { |
982 | const char *symname; | 996 | const char *symname; |
983 | char *version; | 997 | char *version; |
998 | char *license; | ||
984 | struct module *mod; | 999 | struct module *mod; |
985 | struct elf_info info = { }; | 1000 | struct elf_info info = { }; |
986 | Elf_Sym *sym; | 1001 | Elf_Sym *sym; |
@@ -996,6 +1011,18 @@ static void read_symbols(char *modname) | |||
996 | mod->skip = 1; | 1011 | mod->skip = 1; |
997 | } | 1012 | } |
998 | 1013 | ||
1014 | license = get_modinfo(info.modinfo, info.modinfo_len, "license"); | ||
1015 | while (license) { | ||
1016 | if (license_is_gpl_compatible(license)) | ||
1017 | mod->gpl_compatible = 1; | ||
1018 | else { | ||
1019 | mod->gpl_compatible = 0; | ||
1020 | break; | ||
1021 | } | ||
1022 | license = get_next_modinfo(info.modinfo, info.modinfo_len, | ||
1023 | "license", license); | ||
1024 | } | ||
1025 | |||
999 | for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { | 1026 | for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { |
1000 | symname = info.strtab + sym->st_name; | 1027 | symname = info.strtab + sym->st_name; |
1001 | 1028 | ||
@@ -1052,6 +1079,40 @@ void buf_write(struct buffer *buf, const char *s, int len) | |||
1052 | buf->pos += len; | 1079 | buf->pos += len; |
1053 | } | 1080 | } |
1054 | 1081 | ||
1082 | void check_license(struct module *mod) | ||
1083 | { | ||
1084 | struct symbol *s, *exp; | ||
1085 | |||
1086 | for (s = mod->unres; s; s = s->next) { | ||
1087 | if (mod->gpl_compatible == 1) { | ||
1088 | /* GPL-compatible modules may use all symbols */ | ||
1089 | continue; | ||
1090 | } | ||
1091 | exp = find_symbol(s->name); | ||
1092 | if (!exp || exp->module == mod) | ||
1093 | continue; | ||
1094 | const char *basename = strrchr(mod->name, '/'); | ||
1095 | if (basename) | ||
1096 | basename++; | ||
1097 | switch (exp->export) { | ||
1098 | case export_gpl: | ||
1099 | fatal("modpost: GPL-incompatible module %s " | ||
1100 | "uses GPL-only symbol '%s'\n", | ||
1101 | basename ? basename : mod->name, | ||
1102 | exp->name); | ||
1103 | break; | ||
1104 | case export_gpl_future: | ||
1105 | warn("modpost: GPL-incompatible module %s " | ||
1106 | "uses future GPL-only symbol '%s'\n", | ||
1107 | basename ? basename : mod->name, | ||
1108 | exp->name); | ||
1109 | break; | ||
1110 | case export_plain: /* ignore */ break; | ||
1111 | case export_unknown: /* ignore */ break; | ||
1112 | } | ||
1113 | } | ||
1114 | } | ||
1115 | |||
1055 | /** | 1116 | /** |
1056 | * Header for the generated file | 1117 | * Header for the generated file |
1057 | **/ | 1118 | **/ |
@@ -1328,6 +1389,12 @@ int main(int argc, char **argv) | |||
1328 | for (mod = modules; mod; mod = mod->next) { | 1389 | for (mod = modules; mod; mod = mod->next) { |
1329 | if (mod->skip) | 1390 | if (mod->skip) |
1330 | continue; | 1391 | continue; |
1392 | check_license(mod); | ||
1393 | } | ||
1394 | |||
1395 | for (mod = modules; mod; mod = mod->next) { | ||
1396 | if (mod->skip) | ||
1397 | continue; | ||
1331 | 1398 | ||
1332 | buf.pos = 0; | 1399 | buf.pos = 0; |
1333 | 1400 | ||
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index f7ee3a3fde14..2b00c6062844 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
@@ -100,6 +100,7 @@ buf_write(struct buffer *buf, const char *s, int len); | |||
100 | struct module { | 100 | struct module { |
101 | struct module *next; | 101 | struct module *next; |
102 | const char *name; | 102 | const char *name; |
103 | int gpl_compatible; | ||
103 | struct symbol *unres; | 104 | struct symbol *unres; |
104 | int seen; | 105 | int seen; |
105 | int skip; | 106 | int skip; |