aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/mod/modpost.c71
-rw-r--r--scripts/mod/modpost.h1
2 files changed, 70 insertions, 2 deletions
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? */
18int modversions = 0; 19int 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
496static char *get_modinfo(void *modinfo, unsigned long modinfo_len, 498static 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
517static 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
1082void 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);
100struct module { 100struct 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;