aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Ravnborg <sam@mars.ravnborg.org>2006-06-09 15:53:55 -0400
committerSam Ravnborg <sam@mars.ravnborg.org>2006-06-09 15:53:55 -0400
commitb817f6feff4a565b08f0e699a5790b4008b8f494 (patch)
treeb33ca0f4477c500380bc409cc272ab7f207ed77b
parentbd5cbcedf446e2f37cf2a37f533a7e1d7dff9312 (diff)
kbuild: check license compatibility when building modules
Modules that uses GPL symbols can no longer be build with kbuild, the build will fail during the modpost step. When a GPL-incompatible module uses a EXPORT_SYMBOL_GPL_FUTURE symbol then warn during modpost so author are actually notified. The actual license compatibility check is shared with the kernel to make sure it is in sync. Patch originally from: Andreas Gruenbacher <agruen@suse.de> and Ram Pai <linuxram@us.ibm.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
-rw-r--r--include/linux/license.h14
-rw-r--r--kernel/module.c11
-rw-r--r--scripts/mod/modpost.c71
-rw-r--r--scripts/mod/modpost.h1
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
4static 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
1251static 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
1261static void set_license(struct module *mod, const char *license) 1252static 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? */
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;