lkml.org 
[lkml]   [2003]   [Jan]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectRe: [PATCH] [RFC] Module licence and EXPORT_SYMBOL_GPL
Date
> In message <Pine.LNX.4.44.0301022025200.1700-100000@home.transmeta.com> you w
ri
> te:
> Just call it ".init.license" instead of ".license" and you're done:
> it's never used at runtime (well, setting the mod->license field to
> NULL after init to make sure noone abuses it might make sense).

OK, made it a flag, too (thanks rth).

Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

Name: MODULE_LICENSE support for modules
Author: Rusty Russell
Status: Tested in 2.5.54

D: This implements EXPORT_SYMBOL_GPL and MODULE_LICENSE properly (so
D: restrictions are enforced). Also fixes "proprietory" spelling.

diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5-bk/include/linux/kernel.h working-2.5-bk-module-license/include/linux/kernel.h
--- linux-2.5-bk/include/linux/kernel.h Thu Jan 2 14:48:00 2003
+++ working-2.5-bk-module-license/include/linux/kernel.h Fri Jan 3 16:32:18 2003
@@ -105,7 +105,7 @@ extern int oops_in_progress; /* If set,

extern int tainted;
extern const char *print_tainted(void);
-#define TAINT_PROPRIETORY_MODULE (1<<0)
+#define TAINT_PROPRIETARY_MODULE (1<<0)
#define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2)
#define TAINT_FORCED_RMMOD (1<<3)
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5-bk/include/linux/module.h working-2.5-bk-module-license/include/linux/module.h
--- linux-2.5-bk/include/linux/module.h Thu Jan 2 14:48:00 2003
+++ working-2.5-bk-module-license/include/linux/module.h Fri Jan 3 17:12:33 2003
@@ -21,7 +21,6 @@
#include <asm/uaccess.h> /* For struct exception_table_entry */

/* Not Yet Implemented */
-#define MODULE_LICENSE(name)
#define MODULE_AUTHOR(name)
#define MODULE_DESCRIPTION(desc)
#define MODULE_SUPPORTED_DEVICE(name)
@@ -57,11 +56,41 @@ extern const struct gtype##_id __mod_##g

#define THIS_MODULE (&__this_module)

+/*
+ * The following license idents are currently accepted as indicating free
+ * software modules
+ *
+ * "GPL" [GNU Public License v2 or later]
+ * "GPL v2" [GNU Public License v2]
+ * "GPL and additional rights" [GNU Public License v2 rights and more]
+ * "Dual BSD/GPL" [GNU Public License v2
+ * or BSD license choice]
+ * "Dual MPL/GPL" [GNU Public License v2
+ * or Mozilla license choice]
+ *
+ * The following other idents are available
+ *
+ * "Proprietary" [Non free products]
+ *
+ * There are dual licensed components, but when running with Linux it is the
+ * GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
+ * is a GPL combined work.
+ *
+ * This exists for several reasons
+ * 1. So modinfo can show license info for users wanting to vet their setup
+ * is free
+ * 2. So the community can ignore bug reports including proprietary modules
+ * 3. So vendors can do likewise based on their own policies
+ */
+#define MODULE_LICENSE(license) \
+ static const char __module_license[] \
+ __attribute__((section(".init.license"))) = license
+
#else /* !MODULE */

#define MODULE_GENERIC_TABLE(gtype,name)
#define THIS_MODULE ((struct module *)0)
-
+#define MODULE_LICENSE(license)
#endif

#define MODULE_DEVICE_TABLE(type,name) \
@@ -75,6 +104,9 @@ struct kernel_symbol_group
/* Module which owns it (if any) */
struct module *owner;

+ /* Are we internal use only? */
+ int gplonly;
+
unsigned int num_syms;
const struct kernel_symbol *syms;
};
@@ -101,7 +133,11 @@ void *__symbol_get_gpl(const char *symbo
= { (unsigned long)&sym, MODULE_SYMBOL_PREFIX #sym }

#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym)
-#define EXPORT_SYMBOL_GPL(sym) EXPORT_SYMBOL(sym)
+
+#define EXPORT_SYMBOL_GPL(sym) \
+ const struct kernel_symbol __ksymtab_##sym \
+ __attribute__((section("__gpl_ksymtab"))) \
+ = { (unsigned long)&sym, #sym }

struct module_ref
{
@@ -128,6 +164,9 @@ struct module
/* Exported symbols */
struct kernel_symbol_group symbols;

+ /* GPL-only exported symbols. */
+ struct kernel_symbol_group gpl_symbols;
+
/* Exception tables */
struct exception_table extable;

@@ -149,6 +188,9 @@ struct module
/* Am I unsafe to unload? */
int unsafe;

+ /* Am I GPL-compatible */
+ int license_gplok;
+
#ifdef CONFIG_MODULE_UNLOAD
/* Reference counts */
struct module_ref ref[NR_CPUS];
@@ -293,6 +335,7 @@ struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = __stringify(KBUILD_MODNAME),
.symbols = { .owner = &__this_module },
+ .gpl_symbols = { .owner = &__this_module, .gplonly = 1 },
.init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
.exit = cleanup_module,
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5-bk/kernel/extable.c working-2.5-bk-module-license/kernel/extable.c
--- linux-2.5-bk/kernel/extable.c Thu Jan 2 12:36:08 2003
+++ working-2.5-bk-module-license/kernel/extable.c Fri Jan 3 16:29:26 2003
@@ -24,6 +24,8 @@ extern const struct exception_table_entr
extern const struct exception_table_entry __stop___ex_table[];
extern const struct kernel_symbol __start___ksymtab[];
extern const struct kernel_symbol __stop___ksymtab[];
+extern const struct kernel_symbol __start___gpl_ksymtab[];
+extern const struct kernel_symbol __stop___gpl_ksymtab[];

/* Protects extables and symbol tables */
spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
@@ -34,13 +36,20 @@ LIST_HEAD(symbols);

static struct exception_table kernel_extable;
static struct kernel_symbol_group kernel_symbols;
+static struct kernel_symbol_group kernel_gpl_symbols;

void __init extable_init(void)
{
/* Add kernel symbols to symbol table */
kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab);
kernel_symbols.syms = __start___ksymtab;
+ kernel_symbols.gplonly = 0;
list_add(&kernel_symbols.list, &symbols);
+ kernel_gpl_symbols.num_syms = (__stop___gpl_ksymtab
+ - __start___gpl_ksymtab);
+ kernel_gpl_symbols.syms = __start___gpl_ksymtab;
+ kernel_gpl_symbols.gplonly = 1;
+ list_add(&kernel_gpl_symbols.list, &symbols);

/* Add kernel exception table to exception tables */
kernel_extable.num_entries = (__stop___ex_table -__start___ex_table);
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5-bk/kernel/module.c working-2.5-bk-module-license/kernel/module.c
--- linux-2.5-bk/kernel/module.c Thu Jan 2 14:48:01 2003
+++ working-2.5-bk-module-license/kernel/module.c Fri Jan 3 16:47:20 2003
@@ -72,13 +72,16 @@ EXPORT_SYMBOL(init_module);

/* Find a symbol, return value and the symbol group */
static unsigned long __find_symbol(const char *name,
- struct kernel_symbol_group **group)
+ struct kernel_symbol_group **group,
+ int gplok)
{
struct kernel_symbol_group *ks;

list_for_each_entry(ks, &symbols, list) {
unsigned int i;

+ if (ks->gplonly && !gplok)
+ continue;
for (i = 0; i < ks->num_syms; i++) {
if (strcmp(ks->syms[i].name, name) == 0) {
*group = ks;
@@ -502,7 +505,7 @@ void __symbol_put(const char *symbol)
unsigned long flags;

spin_lock_irqsave(&modlist_lock, flags);
- if (!__find_symbol(symbol, &ksg))
+ if (!__find_symbol(symbol, &ksg, 1))
BUG();
module_put(ksg->owner);
spin_unlock_irqrestore(&modlist_lock, flags);
@@ -721,7 +724,7 @@ unsigned long find_symbol_internal(Elf_S
}
/* Look in other modules... */
spin_lock_irq(&modlist_lock);
- ret = __find_symbol(name, ksg);
+ ret = __find_symbol(name, ksg, mod->license_gplok);
if (ret) {
/* This can fail due to OOM, or module unloading */
if (!use_module(mod, (*ksg)->owner))
@@ -738,6 +741,7 @@ static void free_module(struct module *m
list_del(&mod->list);
spin_lock_irq(&modlist_lock);
list_del(&mod->symbols.list);
+ list_del(&mod->gpl_symbols.list);
list_del(&mod->extable.list);
spin_unlock_irq(&modlist_lock);

@@ -758,7 +762,7 @@ void *__symbol_get(const char *symbol)
unsigned long value, flags;

spin_lock_irqsave(&modlist_lock, flags);
- value = __find_symbol(symbol, &ksg);
+ value = __find_symbol(symbol, &ksg, 1);
if (value && !strong_try_module_get(ksg->owner))
value = 0;
spin_unlock_irqrestore(&modlist_lock, flags);
@@ -930,7 +934,34 @@ static void layout_sections(struct modul
}
}

-/* Allocate and load the module */
+static inline int license_is_gpl_compatible(const char *license)
+{
+ return (strcmp(license, "GPL") == 0
+ || strcmp(license, "GPL v2") == 0
+ || strcmp(license, "GPL and additional rights") == 0
+ || strcmp(license, "Dual BSD/GPL") == 0
+ || strcmp(license, "Dual MPL/GPL") == 0);
+}
+
+static void set_license(struct module *mod, Elf_Shdr *sechdrs, int licenseidx)
+{
+ char *license;
+
+ if (licenseidx)
+ license = (char *)sechdrs[licenseidx].sh_addr;
+ else
+ license = "unspecified";
+
+ mod->license_gplok = license_is_gpl_compatible(license);
+ if (!mod->license_gplok) {
+ printk(KERN_WARNING "%s: module license '%s' taints kernel.\n",
+ mod->name, license);
+ tainted |= TAINT_PROPRIETARY_MODULE;
+ }
+}
+
+/* Allocate and load the module: note that size of section 0 is always
+ zero, and we rely on this for optional sections. */
static struct module *load_module(void *umod,
unsigned long len,
const char *uargs)
@@ -939,7 +970,7 @@ static struct module *load_module(void *
Elf_Shdr *sechdrs;
char *secstrings, *args;
unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
- modindex, obsparmindex;
+ modindex, obsparmindex, licenseindex, gplindex;
long arglen;
struct module *mod;
long err = 0;
@@ -975,7 +1006,7 @@ static struct module *load_module(void *

/* May not export symbols, or have setup params, so these may
not exist */
- exportindex = setupindex = obsparmindex = 0;
+ exportindex = setupindex = obsparmindex = gplindex = licenseindex = 0;

/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = exindex = modindex = 0;
@@ -1018,6 +1049,16 @@ static struct module *load_module(void *
/* Obsolete MODULE_PARM() table */
DEBUGP("Obsolete param found in section %u\n", i);
obsparmindex = i;
+ } else if (strcmp(secstrings+sechdrs[i].sh_name,".init.license")
+ == 0) {
+ /* MODULE_LICENSE() */
+ DEBUGP("Licence found in section %u\n", i);
+ licenseindex = i;
+ } else if (strcmp(secstrings+sechdrs[i].sh_name,
+ "__gpl_ksymtab") == 0) {
+ /* EXPORT_SYMBOL_GPL() */
+ DEBUGP("GPL symbols found in section %u\n", i);
+ gplindex = i;
}
#ifdef CONFIG_KALLSYMS
/* symbol and string tables for decoding later. */
@@ -1113,17 +1154,21 @@ static struct module *load_module(void *
/* Now we've moved module, initialize linked lists, etc. */
module_unload_init(mod);

+ /* Set up license info based on contents of section */
+ set_license(mod, sechdrs, licenseindex);
+
/* Fix up syms, so that st_value is a pointer to location. */
err = simplify_symbols(sechdrs, symindex, strindex, mod);
if (err < 0)
goto cleanup;

- /* Set up EXPORTed symbols */
- if (exportindex) {
- mod->symbols.num_syms = (sechdrs[exportindex].sh_size
- / sizeof(*mod->symbols.syms));
- mod->symbols.syms = (void *)sechdrs[exportindex].sh_addr;
- }
+ /* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */
+ mod->symbols.num_syms = (sechdrs[exportindex].sh_size
+ / sizeof(*mod->symbols.syms));
+ mod->symbols.syms = (void *)sechdrs[exportindex].sh_addr;
+ mod->gpl_symbols.num_syms = (sechdrs[gplindex].sh_size
+ / sizeof(*mod->symbols.syms));
+ mod->gpl_symbols.syms = (void *)sechdrs[gplindex].sh_addr;

/* Set up exception table */
if (exindex) {
@@ -1228,6 +1273,7 @@ sys_init_module(void *umod,
spin_lock_irq(&modlist_lock);
list_add(&mod->extable.list, &extables);
list_add_tail(&mod->symbols.list, &symbols);
+ list_add_tail(&mod->gpl_symbols.list, &symbols);
spin_unlock_irq(&modlist_lock);
list_add(&mod->list, &modules);

diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5-bk/kernel/panic.c working-2.5-bk-module-license/kernel/panic.c
--- linux-2.5-bk/kernel/panic.c Thu Jan 2 12:25:16 2003
+++ working-2.5-bk-module-license/kernel/panic.c Fri Jan 3 16:32:55 2003
@@ -103,7 +103,7 @@ NORET_TYPE void panic(const char * fmt,
/**
* print_tainted - return a string to represent the kernel taint state.
*
- * 'P' - Proprietory module has been loaded.
+ * 'P' - Proprietary module has been loaded.
* 'F' - Module has been forcibly loaded.
* 'S' - SMP with CPUs not designed for SMP.
*
@@ -115,7 +115,7 @@ const char *print_tainted()
static char buf[20];
if (tainted) {
snprintf(buf, sizeof(buf), "Tainted: %c%c%c",
- tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
+ tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 13:32    [W:0.040 / U:0.708 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site