|
@@ -13,6 +13,7 @@
|
|
|
|
|
|
#include <ctype.h>
|
|
#include <ctype.h>
|
|
#include "modpost.h"
|
|
#include "modpost.h"
|
|
|
|
+#include "../../include/linux/license.h"
|
|
|
|
|
|
/* Are we using CONFIG_MODVERSIONS? */
|
|
/* Are we using CONFIG_MODVERSIONS? */
|
|
int modversions = 0;
|
|
int modversions = 0;
|
|
@@ -99,6 +100,7 @@ static struct module *new_module(char *modname)
|
|
|
|
|
|
/* add to list */
|
|
/* add to list */
|
|
mod->name = p;
|
|
mod->name = p;
|
|
|
|
+ mod->gpl_compatible = -1;
|
|
mod->next = modules;
|
|
mod->next = modules;
|
|
modules = mod;
|
|
modules = mod;
|
|
|
|
|
|
@@ -493,13 +495,18 @@ static char *next_string(char *string, unsigned long *secsize)
|
|
return string;
|
|
return string;
|
|
}
|
|
}
|
|
|
|
|
|
-static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
|
|
|
|
- const char *tag)
|
|
|
|
|
|
+static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len,
|
|
|
|
+ const char *tag, char *info)
|
|
{
|
|
{
|
|
char *p;
|
|
char *p;
|
|
unsigned int taglen = strlen(tag);
|
|
unsigned int taglen = strlen(tag);
|
|
unsigned long size = modinfo_len;
|
|
unsigned long size = modinfo_len;
|
|
|
|
|
|
|
|
+ if (info) {
|
|
|
|
+ size -= info - (char *)modinfo;
|
|
|
|
+ modinfo = next_string(info, &size);
|
|
|
|
+ }
|
|
|
|
+
|
|
for (p = modinfo; p; p = next_string(p, &size)) {
|
|
for (p = modinfo; p; p = next_string(p, &size)) {
|
|
if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
|
|
if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
|
|
return p + taglen + 1;
|
|
return p + taglen + 1;
|
|
@@ -507,6 +514,13 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
|
|
|
|
+ const char *tag)
|
|
|
|
+
|
|
|
|
+{
|
|
|
|
+ return get_next_modinfo(modinfo, modinfo_len, tag, NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Test if string s ends in string sub
|
|
* Test if string s ends in string sub
|
|
* return 0 if match
|
|
* return 0 if match
|
|
@@ -981,6 +995,7 @@ static void read_symbols(char *modname)
|
|
{
|
|
{
|
|
const char *symname;
|
|
const char *symname;
|
|
char *version;
|
|
char *version;
|
|
|
|
+ char *license;
|
|
struct module *mod;
|
|
struct module *mod;
|
|
struct elf_info info = { };
|
|
struct elf_info info = { };
|
|
Elf_Sym *sym;
|
|
Elf_Sym *sym;
|
|
@@ -996,6 +1011,18 @@ static void read_symbols(char *modname)
|
|
mod->skip = 1;
|
|
mod->skip = 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ license = get_modinfo(info.modinfo, info.modinfo_len, "license");
|
|
|
|
+ while (license) {
|
|
|
|
+ if (license_is_gpl_compatible(license))
|
|
|
|
+ mod->gpl_compatible = 1;
|
|
|
|
+ else {
|
|
|
|
+ mod->gpl_compatible = 0;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ license = get_next_modinfo(info.modinfo, info.modinfo_len,
|
|
|
|
+ "license", license);
|
|
|
|
+ }
|
|
|
|
+
|
|
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
|
|
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
|
|
symname = info.strtab + sym->st_name;
|
|
symname = info.strtab + sym->st_name;
|
|
|
|
|
|
@@ -1052,6 +1079,40 @@ void buf_write(struct buffer *buf, const char *s, int len)
|
|
buf->pos += len;
|
|
buf->pos += len;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void check_license(struct module *mod)
|
|
|
|
+{
|
|
|
|
+ struct symbol *s, *exp;
|
|
|
|
+
|
|
|
|
+ for (s = mod->unres; s; s = s->next) {
|
|
|
|
+ if (mod->gpl_compatible == 1) {
|
|
|
|
+ /* GPL-compatible modules may use all symbols */
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ exp = find_symbol(s->name);
|
|
|
|
+ if (!exp || exp->module == mod)
|
|
|
|
+ continue;
|
|
|
|
+ const char *basename = strrchr(mod->name, '/');
|
|
|
|
+ if (basename)
|
|
|
|
+ basename++;
|
|
|
|
+ switch (exp->export) {
|
|
|
|
+ case export_gpl:
|
|
|
|
+ fatal("modpost: GPL-incompatible module %s "
|
|
|
|
+ "uses GPL-only symbol '%s'\n",
|
|
|
|
+ basename ? basename : mod->name,
|
|
|
|
+ exp->name);
|
|
|
|
+ break;
|
|
|
|
+ case export_gpl_future:
|
|
|
|
+ warn("modpost: GPL-incompatible module %s "
|
|
|
|
+ "uses future GPL-only symbol '%s'\n",
|
|
|
|
+ basename ? basename : mod->name,
|
|
|
|
+ exp->name);
|
|
|
|
+ break;
|
|
|
|
+ case export_plain: /* ignore */ break;
|
|
|
|
+ case export_unknown: /* ignore */ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Header for the generated file
|
|
* Header for the generated file
|
|
**/
|
|
**/
|
|
@@ -1325,6 +1386,12 @@ int main(int argc, char **argv)
|
|
read_symbols(argv[optind++]);
|
|
read_symbols(argv[optind++]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ for (mod = modules; mod; mod = mod->next) {
|
|
|
|
+ if (mod->skip)
|
|
|
|
+ continue;
|
|
|
|
+ check_license(mod);
|
|
|
|
+ }
|
|
|
|
+
|
|
for (mod = modules; mod; mod = mod->next) {
|
|
for (mod = modules; mod; mod = mod->next) {
|
|
if (mod->skip)
|
|
if (mod->skip)
|
|
continue;
|
|
continue;
|