Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.2
module-init-tools
module-init-tools-suse.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File module-init-tools-suse.diff of Package module-init-tools
This patch contains suse-specific changes against upstream commit 9a1c905651a38d1f2c6d4d836f81b5e06a503521 diff --git a/depmod.c b/depmod.c index 4c8caa0..b4e52b4 100644 --- a/depmod.c +++ b/depmod.c @@ -193,7 +193,7 @@ static void load_module_symvers(const char *filename) /* eg. "0xb352177e\tfind_first_bit\tvmlinux\tEXPORT_SYMBOL" */ while (fgets(line, sizeof(line)-1, module_symvers)) { - const char *ver, *sym, *where; + const char *ver, *sym, *where, *slash; ver = strtok(line, " \t"); sym = strtok(NULL, " \t"); @@ -201,7 +201,9 @@ static void load_module_symvers(const char *filename) if (!ver || !sym || !where) continue; - if (streq(where, "vmlinux")) + if (streq(where, "vmlinux") || + (((slash = strrchr(where, '/'))) && + streq(slash, "/built-in"))) add_symbol(sym, strtoull(ver, NULL, 16), NULL); } @@ -434,7 +436,7 @@ static const char *compress_path(const char *path, const char *basedir) return path; } -static void output_deps(struct module *modules, +static int output_deps(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -453,12 +455,13 @@ static void output_deps(struct module *modules, } fprintf(out, "\n"); } + return 1; } /* warn whenever duplicate module aliases, deps, or symbols are found. */ int warn_dups = 0; -static void output_deps_bin(struct module *modules, +static int output_deps_bin(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -495,6 +498,8 @@ static void output_deps_bin(struct module *modules, index_write(index, out); index_destroy(index); + + return 1; } @@ -769,7 +774,7 @@ static struct module *parse_modules(struct module *list) } /* Simply dump hash table. */ -static void output_symbols(struct module *unused, FILE *out, char *dirname) +static int output_symbols(struct module *unused, FILE *out, char *dirname) { unsigned int i; @@ -786,9 +791,10 @@ static void output_symbols(struct module *unused, FILE *out, char *dirname) } } } + return 1; } -static void output_symbols_bin(struct module *unused, FILE *out, char *dirname) +static int output_symbols_bin(struct module *unused, FILE *out, char *dirname) { struct index_node *index; unsigned int i; @@ -817,9 +823,54 @@ static void output_symbols_bin(struct module *unused, FILE *out, char *dirname) index_write(index, out); index_destroy(index); + + return 1; } -static void output_aliases(struct module *modules, FILE *out, char *dirname) +static int output_builtin_bin(struct module *unused, FILE *out, char *dirname) +{ + struct index_node *index; + char *textfile, *line; + unsigned int linenum; + FILE *f; + + nofail_asprintf(&textfile, "%s/modules.builtin", dirname); + if (!(f = fopen(textfile, "r"))) { + if (errno != ENOENT) + fatal("Could not open '%s': %s\n", + textfile, strerror(errno)); + free(textfile); + return 0; + } + free(textfile); + index = index_create(); + + while ((line = getline_wrapped(f, &linenum)) != NULL) { + char *module = strrchr(line, '/'); + + if (!*line || *line == '#') { + free(line); + continue; + } + module = strrchr(line, '/'); + if (module) + module++; + else + module = line; + if (ends_in(module, ".ko")) + module[strlen(module) - 3] = '\0'; + underscores(module); + index_insert(index, module, "", 0); + free(line); + } + fclose(f); + index_write(index, out); + index_destroy(index); + + return 1; +} + +static int output_aliases(struct module *modules, FILE *out, char *dirname) { struct module *i; struct elf_file *file; @@ -849,9 +900,10 @@ static void output_aliases(struct module *modules, FILE *out, char *dirname) } strtbl_free(tbl); } + return 1; } -static void output_aliases_bin(struct module *modules, FILE *out, char *dirname) +static int output_aliases_bin(struct module *modules, FILE *out, char *dirname) { struct module *i; struct elf_file *file; @@ -901,11 +953,13 @@ static void output_aliases_bin(struct module *modules, FILE *out, char *dirname) index_write(index, out); index_destroy(index); + + return 1; } struct depfile { char *name; - void (*func)(struct module *, FILE *, char *dirname); + int (*func)(struct module *, FILE *, char *dirname); int map_file; }; @@ -923,7 +977,8 @@ static struct depfile depfiles[] = { { "modules.alias", output_aliases, 0 }, { "modules.alias.bin", output_aliases_bin, 0 }, { "modules.symbols", output_symbols, 0 }, - { "modules.symbols.bin", output_symbols_bin, 0 } + { "modules.symbols.bin", output_symbols_bin, 0 }, + { "modules.builtin.bin", output_builtin_bin, 0 }, }; /* If we can't figure it out, it's safe to say "true". */ @@ -1368,6 +1423,7 @@ int main(int argc, char *argv[]) for (i = 0; i < sizeof(depfiles)/sizeof(depfiles[0]); i++) { FILE *out; + int res; struct depfile *d = &depfiles[i]; char depname[strlen(dirname) + 1 + strlen(d->name) + 1]; char tmpname[strlen(dirname) + 1 + strlen(d->name) + @@ -1388,12 +1444,18 @@ int main(int argc, char *argv[]) if (ends_in(depname, ".bin")) continue; } - d->func(list, out, dirname); - if (!doing_stdout) { - fclose(out); + res = d->func(list, out, dirname); + if (doing_stdout) + continue; + fclose(out); + if (res) { if (rename(tmpname, depname) < 0) fatal("Could not rename %s into %s: %s\n", tmpname, depname, strerror(errno)); + } else { + if (unlink(tmpname) < 0) + warn("Could not delete %s: %s\n", + tmpname, strerror(errno)); } } diff --git a/doc/modprobe.conf.sgml b/doc/modprobe.conf.sgml index cacc006..cd94511 100644 --- a/doc/modprobe.conf.sgml +++ b/doc/modprobe.conf.sgml @@ -176,6 +176,19 @@ </para> </listitem> </varlistentry> + <varlistentry> + <term>allow_unsupported_modules <replaceable>[0|1]</replaceable> + </term> + <listitem> + <para> + In SUSE kernels, every kernel module has a flag 'supported'. If + this flag is not set loading this module will taint your kernel. + Setting this option to 0 disables loading of unsupported modules + and avoids tainting the kernel. This is typically set in + <filename>/etc/modprobe.d/unsupported-modules</filename>. + </para> + </listitem> + </varlistentry> </variablelist> </refsect1> <refsect1> diff --git a/doc/modprobe.sgml b/doc/modprobe.sgml index fde8ca7..01ee9e1 100644 --- a/doc/modprobe.sgml +++ b/doc/modprobe.sgml @@ -430,9 +430,28 @@ </para> </listitem> </varlistentry> + <varlistentry> + <term><option>--allow-unsupported-modules</option> + </term> + <listitem> + <para> + Load unsupported modules even if disabled in configuration. + </para> + </listitem> + </varlistentry> </variablelist> </refsect1> <refsect1> + <title>RETURN VALUE</title> + + <para> + <command>modprobe</command> returns 0 on success, 1 on an unspecified + error and 2 if the module is not supported. Use the + <option>--allow-unsupported-modules</option> option to force + using an unsupported module. + </para> + </refsect1> + <refsect1> <title>ENVIRONMENT</title> <para> The MODPROBE_OPTIONS environment variable can also be used to diff --git a/logging.c b/logging.c index 4330269..46257ff 100644 --- a/logging.c +++ b/logging.c @@ -57,13 +57,15 @@ void error(const char *fmt, ...) va_end(arglist); } +/* can be overriden for different kinds of errors */ +int fatal_exit_code = 1; void fatal(const char *fmt, ...) { va_list arglist; va_start(arglist, fmt); message("FATAL: ", fmt, &arglist); va_end(arglist); - exit(1); + exit(fatal_exit_code); } /* If we don't flush, then child processes print before we do */ diff --git a/logging.h b/logging.h index c01187b..7445ab4 100644 --- a/logging.h +++ b/logging.h @@ -10,6 +10,9 @@ extern int quiet; /* Do we want informative messages as well as errors? */ extern int verbose; +/* Exit code returned by fatal() */ +extern int fatal_exit_code; + extern void fatal(const char *fmt, ...); extern void error(const char *fmt, ...); extern void warn(const char *fmt, ...); diff --git a/modprobe.c b/modprobe.c index 21a3111..72d9c10 100644 --- a/modprobe.c +++ b/modprobe.c @@ -51,6 +51,9 @@ int use_binary_indexes = 1; /* default to enabled. */ +/* Allow loading of unsupported modules? */ +static int allow_unsupported = 1; + extern long init_module(void *, unsigned long, const char *); extern long delete_module(const char *, unsigned int); @@ -69,8 +72,9 @@ typedef enum mit_ignore_commands = 16, mit_ignore_loaded = 32, mit_strip_vermagic = 64, - mit_strip_modversion = 128 + mit_strip_modversion = 128, + mit_force_allow_unsupported = 1<<20, } modprobe_flags_t; #ifndef MODULE_DIR @@ -354,6 +358,23 @@ static void clear_magic(struct elf_file *module) } } +static int module_supported(struct elf_file *module) +{ + struct string_table *tbl; + int j; + + /* Grab from new-style .modinfo section. */ + tbl = module->ops->load_strings(module, ".modinfo", NULL, fatal); + for (j = 0; tbl && j < tbl->cnt; j++) { + const char *p = tbl->str[j]; + if (streq(p, "supported=yes") || + streq(p, "supported=external")) { + return 1; + } + } + return 0; +} + struct module_options { struct module_options *next; @@ -537,6 +558,24 @@ static int read_attribute(const char *filename, char *buf, size_t buflen) return (s == NULL) ? -1 : 1; } +/* is this a built-in module? + * 0: no, 1: yes, -1: don't know + */ +static int module_builtin(const char *dirname, const char *modname) +{ + struct index_file *index; + char *filename, *value; + + nofail_asprintf(&filename, "%s/modules.builtin.bin", dirname); + index = index_file_open(filename); + free(filename); + if (!index) + return -1; + value = index_search(index, modname); + free(value); + return value ? 1 : 0; +} + /* Is module in /sys/module? If so, fill in usecount if not NULL. 0 means no, 1 means yes, -1 means unknown. */ @@ -787,6 +826,16 @@ static int parse_config_file(const char *filename, if (streq(tmp, "no")) use_binary_indexes = 0; } + } else if (strcmp(cmd, "allow_unsupported_modules") == 0) { + const char *option = strsep_skipspace(&ptr, "\t "); + if (!option) + grammar(cmd, filename, linenum); + else if (streq(option, "yes") || streq(option, "1")) + allow_unsupported = 1; + else if (streq(option, "no") || streq(option, "0")) + allow_unsupported = 0; + else + grammar(cmd, filename, linenum); } else grammar(cmd, filename, linenum); @@ -1144,6 +1193,17 @@ static int insmod(struct list_head *list, strerror(errno)); goto out_unlock; } + /* Supported? */ + if (!allow_unsupported && !module_supported(module)) { + if (error == fatal) + fatal_exit_code = 2; + error("module '%s' is unsupported\n" + "Use --allow-unsupported or set allow_unsupported_modules to 1 in\n" + "/etc/modprobe.d/10-unsupported-modules.conf\n", + mod->filename); + goto out; + } + if (newname) rename_module(module, mod->modname, newname); if (flags & mit_strip_modversion) @@ -1309,6 +1369,16 @@ int do_modprobe(char *modname, /* Returns the resolved alias, options */ parse_toplevel_config(configname, modname, 0, flags & mit_remove, &modoptions, &commands, &aliases, &blacklist); + if (flags & mit_force_allow_unsupported) + allow_unsupported = 1; + /* Be nice to people running non-suse kernels and allow + * unsupported modules */ + if (!allow_unsupported) { + if (access("/proc/sys/kernel/", F_OK) == 0 && + access("/proc/sys/kernel/unsupported", F_OK) == -1 && + errno == ENOENT) + allow_unsupported = 1; + } /* Read module options from kernel command line */ parse_kcmdline(0, &modoptions); @@ -1331,6 +1401,11 @@ int do_modprobe(char *modname, modname, 0, flags & mit_remove, &modoptions, &commands, &aliases, &blacklist); + /* builtin module? */ + if (!aliases && module_builtin(dirname, modname) == 1) { + info("builtin %s\n", modname); + return 0; + } } } @@ -1390,6 +1465,8 @@ static struct option options[] = { { "version", 0, NULL, 'V' }, { "force-modversion", 0, NULL, 2 }, { "first-time", 0, NULL, 3 }, { "dump-modversions", 0, NULL, 4 }, + { "allow-unsupported-modules", 0, NULL, 128 }, + { "use-blacklist", 0, NULL, 'b' }, { NULL, 0, NULL, 0 } }; int main(int argc, char *argv[]) @@ -1494,6 +1571,9 @@ int main(int argc, char *argv[]) case 4: dump_modver = 1; break; + case 128: + flags |= mit_force_allow_unsupported; + break; default: print_usage(argv[0]); } diff --git a/tables.c b/tables.c index 2f44450..c862920 100644 --- a/tables.c +++ b/tables.c @@ -34,7 +34,7 @@ static void output_pci_entry(struct pci_device_id *pci, char *name, FILE *out, END(pci->class_mask, conv)); } -void output_pci_table(struct module *modules, FILE *out, char *dirname) +int output_pci_table(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -53,6 +53,7 @@ void output_pci_table(struct module *modules, FILE *out, char *dirname) for (e = t->pci_table; e->vendor; e = (void *)e + t->pci_size) output_pci_entry(e, shortname, out, i->file->conv); } + return 1; } /* We set driver_info to zero */ @@ -78,7 +79,7 @@ static void output_usb_entry(struct usb_device_id *usb, char *name, FILE *out, END(usb->bInterfaceProtocol, conv)); } -void output_usb_table(struct module *modules, FILE *out, char *dirname) +int output_usb_table(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -104,6 +105,7 @@ void output_usb_table(struct module *modules, FILE *out, char *dirname) e = (void *)e + t->usb_size) output_usb_entry(e, shortname, out, i->file->conv); } + return 1; } static void output_ieee1394_entry(struct ieee1394_device_id *fw, char *name, @@ -118,7 +120,7 @@ static void output_ieee1394_entry(struct ieee1394_device_id *fw, char *name, END(fw->version, conv)); } -void output_ieee1394_table(struct module *modules, FILE *out, char *dirname) +int output_ieee1394_table(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -138,6 +140,7 @@ void output_ieee1394_table(struct module *modules, FILE *out, char *dirname) fw = (void *) fw + t->ieee1394_size) output_ieee1394_entry(fw, shortname, out, i->file->conv); } + return 1; } @@ -151,7 +154,7 @@ static void output_ccw_entry(struct ccw_device_id *ccw, char *name, FILE *out, END(ccw->dev_type, conv), END(ccw->dev_model, conv)); } -void output_ccw_table(struct module *modules, FILE *out, char *dirname) +int output_ccw_table(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -172,6 +175,7 @@ void output_ccw_table(struct module *modules, FILE *out, char *dirname) e = (void *) e + t->ccw_size) output_ccw_entry(e, shortname, out, i->file->conv); } + return 1; } #define ISAPNP_VENDOR(a,b,c) (((((a)-'A'+1)&0x3f)<<2)|\ @@ -192,7 +196,7 @@ static void put_isapnp_id(FILE *out, const char *id) fprintf(out, " 0x%04x 0x%04x ", vendor, device); } -void output_isapnp_table(struct module *modules, FILE *out, char *dirname) +int output_isapnp_table(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -238,6 +242,7 @@ void output_isapnp_table(struct module *modules, FILE *out, char *dirname) } } } + return 1; } #define MATCH_bustype 1 @@ -412,7 +417,7 @@ static int output_input_entry_64_old(struct input_device_id_old_64 *input, return 0; } -void output_input_table(struct module *modules, FILE *out, char *dirname) +int output_input_table(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -468,6 +473,7 @@ void output_input_table(struct module *modules, FILE *out, char *dirname) } } } + return 1; } static void output_serio_entry(struct serio_device_id *serio, char *name, FILE *out) @@ -482,7 +488,7 @@ static void output_serio_entry(struct serio_device_id *serio, char *name, FILE * } -void output_serio_table(struct module *modules, FILE *out, char *dirname) +int output_serio_table(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -500,6 +506,7 @@ void output_serio_table(struct module *modules, FILE *out, char *dirname) for (e = t->serio_table; e->type || e->proto; e = (void *)e + t->serio_size) output_serio_entry(e, shortname, out); } + return 1; } @@ -542,7 +549,7 @@ static void output_of_entry(struct of_device_id *dev, char *name, FILE *out) free(compatible); } -void output_of_table(struct module *modules, FILE *out, char *dirname) +int output_of_table(struct module *modules, FILE *out, char *dirname) { struct module *i; @@ -560,4 +567,5 @@ void output_of_table(struct module *modules, FILE *out, char *dirname) e = (void *)e + t->of_size) output_of_entry(e, shortname, out); } + return 1; } diff --git a/tables.h b/tables.h index 8a1420f..920e8df 100644 --- a/tables.h +++ b/tables.h @@ -175,13 +175,13 @@ struct of_device_id { /* Functions provided by tables.c */ struct module; -void output_usb_table(struct module *modules, FILE *out, char *dirname); -void output_ieee1394_table(struct module *modules, FILE *out, char *dirname); -void output_pci_table(struct module *modules, FILE *out, char *dirname); -void output_ccw_table(struct module *modules, FILE *out, char *dirname); -void output_isapnp_table(struct module *modules, FILE *out, char *dirname); -void output_input_table(struct module *modules, FILE *out, char *dirname); -void output_serio_table(struct module *modules, FILE *out, char *dirname); -void output_of_table(struct module *modules, FILE *out, char *dirname); +int output_usb_table(struct module *modules, FILE *out, char *dirname); +int output_ieee1394_table(struct module *modules, FILE *out, char *dirname); +int output_pci_table(struct module *modules, FILE *out, char *dirname); +int output_ccw_table(struct module *modules, FILE *out, char *dirname); +int output_isapnp_table(struct module *modules, FILE *out, char *dirname); +int output_input_table(struct module *modules, FILE *out, char *dirname); +int output_serio_table(struct module *modules, FILE *out, char *dirname); +int output_of_table(struct module *modules, FILE *out, char *dirname); #endif /* MODINITTOOLS_TABLES_H */ diff --git a/zlibsupport.c b/zlibsupport.c index b159765..0f78524 100644 --- a/zlibsupport.c +++ b/zlibsupport.c @@ -12,6 +12,8 @@ #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> +#include <stdio.h> +#include <string.h> #include "zlibsupport.h" #include "logging.h" @@ -19,69 +21,35 @@ #ifdef CONFIG_USE_ZLIB #include <zlib.h> +#endif -void *grab_contents(gzFile *gzfd, unsigned long *size) +#ifdef CONFIG_USE_ZLIB +static int check_gz_magic(int fd) { - unsigned int max = 16384; - void *buffer = NOFAIL(malloc(max)); - int ret; - - *size = 0; - while ((ret = gzread(gzfd, buffer + *size, max - *size)) > 0) { - *size += ret; - if (*size == max) - buffer = NOFAIL(realloc(buffer, max *= 2)); - } - if (ret < 0) { - free(buffer); - buffer = NULL; - } - - return buffer; + unsigned char magic[2]; + + if (read(fd, magic, 2) != 2) + return -1; + lseek(fd, 0, SEEK_SET); + if (magic[0] == 0x1f && magic[1] == 0x8b) + return 1; + return 0; } -void *grab_fd(int fd, unsigned long *size) +static char *tmpdir(void) { - gzFile gzfd; - - gzfd = gzdopen(fd, "rb"); - if (!gzfd) { - if (errno == ENOMEM) - fatal("Memory allocation failure in gzdopen\n"); - return NULL; - } - - /* gzclose(gzfd) would close fd, which would drop locks. - Don't blame zlib: POSIX locking semantics are so horribly - broken that they should be ripped out. */ - return grab_contents(gzfd, size); + static char *TMPDIR; + + if (TMPDIR) + return TMPDIR; + TMPDIR = getenv("TMPDIR"); + if (!TMPDIR) + TMPDIR = "/tmp"; + return TMPDIR; } +#endif -/* gzopen handles uncompressed files transparently. */ -void *grab_file(const char *filename, unsigned long *size) -{ - gzFile gzfd; - void *buffer; - - errno = 0; - gzfd = gzopen(filename, "rb"); - if (!gzfd) { - if (errno == ENOMEM) - fatal("Memory allocation failure in gzopen\n"); - return NULL; - } - buffer = grab_contents(gzfd, size); - gzclose(gzfd); - return buffer; -} - -void release_file(void *data, unsigned long size) -{ - free(data); -} -#else /* ... !CONFIG_USE_ZLIB */ - -void *grab_fd(int fd, unsigned long *size) +void *do_grab_fd(int fd, unsigned long *size) { struct stat st; void *map; @@ -97,6 +65,60 @@ void *grab_fd(int fd, unsigned long *size) return map; } +void *grab_fd(int fd, unsigned long *size) +{ +#ifdef CONFIG_USE_ZLIB + int magic = check_gz_magic(fd); + if (magic == -1) + return NULL; + if (magic) { + gzFile gzfd; + int tmp; + char buffer[4096]; + char *template; + int r, w; + void *ret = NULL; + + template = NOFAIL(malloc(strlen(tmpdir()) + sizeof("/m-i-t.XXXXXX"))); + sprintf(template, "%s/m-i-t.XXXXXX", tmpdir()); + gzfd = gzdopen(dup(fd), "rb"); + if (!gzfd) { + if (errno == ENOMEM) + fatal("Memory allocation failure in gzdopen\n"); + goto out_template; + } + tmp = mkstemp(template); + if (tmp == -1) + goto out_template; + + while ((r = gzread(gzfd, buffer, sizeof(buffer))) > 0) { + char *p = buffer; + do { + w = write(tmp, p, r); + if (w > 0) { + r -= w; + p += w; + } + } while (w > 0 || (w == -1 && errno == EINTR)); + if (w == -1) + goto out; + } + if (r < 0) + goto out; + gzclose(gzfd); + ret = do_grab_fd(tmp, size); +out: + close(tmp); + unlink(template); +out_template: + free(template); + return ret; + } else +#endif + return do_grab_fd(fd, size); +} + + void *grab_file(const char *filename, unsigned long *size) { int fd; @@ -114,4 +136,4 @@ void release_file(void *data, unsigned long size) { munmap(data, size); } -#endif +
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor