Browse Source

added kmod package

Signed-off-by: basebuilder_pel7x64builder0 <basebuilder@powerel.org>
master
basebuilder_pel7x64builder0 6 years ago
parent
commit
6f2641cce8
  1. 93
      SOURCES/kmod-0004-libkmod-elf-resolve-CRC-if-module-is-built-with-MODU.patch
  2. 920
      SOURCES/kmod-0005-depmod-backport-external-directories-support.patch
  3. 56
      SOURCES/kmod-0006-depmod-module_is_higher_priority-fix-modname-length-.patch
  4. 176
      SOURCES/weak-modules
  5. 43
      SPECS/kmod.spec

93
SOURCES/kmod-0004-libkmod-elf-resolve-CRC-if-module-is-built-with-MODU.patch

@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
From 1e48901166efd65c574de9f6a2b7139721b72623 Mon Sep 17 00:00:00 2001
From: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Wed, 19 Jul 2017 17:56:49 +0300
Subject: [PATCH] libkmod-elf: resolve CRC if module is built with
MODULE_REL_CRCS

Normally exported symbol's crc is stored as absolute (SHN_ABS)
value of special named symbol __crc_<symbol name>.

When the kernel and modules are built with the config option
CONFIG_MODULE_REL_CRCS, all the CRCs are put in a special section
and the __crc_<symbol name> symbols values are offsets in the
section. See patch description of the commit:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=56067812d5b0e737ac2063e94a50f76b810d6ca3

Add kmod support of this configuration.

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
---
libkmod/libkmod-elf.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/libkmod/libkmod-elf.c b/libkmod/libkmod-elf.c
index 90da89aebbaf..ef4a8a3142a1 100644
--- a/libkmod/libkmod-elf.c
+++ b/libkmod/libkmod-elf.c
@@ -747,6 +747,31 @@ static inline uint8_t kmod_symbol_bind_from_elf(uint8_t elf_value)
}
}
+static uint64_t kmod_elf_resolve_crc(const struct kmod_elf *elf, uint64_t crc, uint16_t shndx)
+{
+ int err;
+ uint64_t off, size;
+ uint32_t nameoff;
+
+ if (shndx == SHN_ABS || shndx == SHN_UNDEF)
+ return crc;
+
+ err = elf_get_section_info(elf, shndx, &off, &size, &nameoff);
+ if (err < 0) {
+ ELFDBG("Cound not find section index %"PRIu16" for crc", shndx);
+ return (uint64_t)-1;
+ }
+
+ if (crc > (size - sizeof(uint32_t))) {
+ ELFDBG("CRC offset %"PRIu64" is too big, section %"PRIu16" size is %"PRIu64"\n",
+ crc, shndx, size);
+ return (uint64_t)-1;
+ }
+
+ crc = elf_get_uint(elf, off + crc, sizeof(uint32_t));
+ return crc;
+}
+
/* array will be allocated with strings in a single malloc, just free *array */
int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **array)
{
@@ -830,6 +855,7 @@ int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **ar
uint32_t name_off;
uint64_t crc;
uint8_t info, bind;
+ uint16_t shndx;
#define READV(field) \
elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\
@@ -839,11 +865,13 @@ int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **ar
name_off = READV(st_name);
crc = READV(st_value);
info = READV(st_info);
+ shndx = READV(st_shndx);
} else {
Elf64_Sym *s;
name_off = READV(st_name);
crc = READV(st_value);
info = READV(st_info);
+ shndx = READV(st_shndx);
}
#undef READV
name = elf_get_mem(elf, str_off + name_off);
@@ -856,7 +884,7 @@ int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **ar
else
bind = ELF64_ST_BIND(info);
- a[count].crc = crc;
+ a[count].crc = kmod_elf_resolve_crc(elf, crc, shndx);
a[count].bind = kmod_symbol_bind_from_elf(bind);
a[count].symbol = itr;
slen = strlen(name);
--
2.14.0.rc0

920
SOURCES/kmod-0005-depmod-backport-external-directories-support.patch

@ -0,0 +1,920 @@ @@ -0,0 +1,920 @@
From e91ce48303e37b92f123a91acfa9cbda17035d7c Mon Sep 17 00:00:00 2001
From: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Thu, 17 Aug 2017 15:09:06 +0300
Subject: [PATCH] depmod: backport external directories support

Requires to backport scratchbuf implementation

Squashed commit of the following:

commit 92ab2321a4b761eb2822d77dc235dd543b021c69
Author: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Thu Jul 20 17:09:52 2017 +0300

man/depmod.d: add external keyword description

The commit 'depmod: implement external directories support' added
external directories support (see
7da6884e7357ac05772e90f6d7e63b1948103fc4).

This patch documents the extention in the manpage.

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>

commit 01673c9b8dbe580634604808f831b735aa7fe298
Author: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Tue May 9 22:09:23 2017 +0300

depmod: implement external directories support

The idea is to add a configuration keyword, external, which
will list directories for scanning for particular kernel version
mask:

external 4.10 /the/modules/dir /second/modules/dir

And extend "search" keyword to set it's priority with pseudo dir
"external" (as it's done for built-in):

search subdir external subdir2 built-in subdir3

(actually, the version is the same as for override keyword: * or
posix regexp, so example above is a bit incorrect).

All other logic left the same: if there are duplicates, only one
is under consideration and it is unloadable if it is bad.

The resulting modules.dep will contain entries a-la:

/the/modules/dir/module1.ko:
kernel/module2.ko: /the/modules/dir/module1.ko

(here /lib/modules/$(uname -r)/kernel/module2.ko depends of
symbols, provided by /the/modules/dir/module1.ko and external has
higher priority).

modprobe and modinfo understand it out of box.

This is a pretty simple extention of existing logic, since now
depmod already is able to:

a) scan modules with full path from command line without -a
switch;
b) detects broken symbol dependencies and broken modversions,
what assumes, that modules are already are not built for the
existing kernel.

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>

commit 5274ad44377ad5998b9f4b3c5c180d407ed68fb9
Author: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Tue May 9 22:09:22 2017 +0300

depmod: rewrite depmod modules search with scratchbuf

The recursive search code used used pretty big, PATH_MAX,
automatic storage buffer for the module directory scanning. Some
time ago there was scratchbuf implemented, which dynamically
reallocates its buffer on demand. The patch takes it in use for
the scanning code also. The initial size is hardcoded to 256
bytes which sounds good enough for most usecases so there should
be not many reallocations.

(add #include <shared/scratchbuf.h> which in upstream
comes from 3b4c684c125d depmod: fix string overflow)

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>

commit 88f47f04df80dd80065d2811f3a7bae25dd98a79
Author: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Tue May 9 22:09:21 2017 +0300

depmod: create depmod dir independent search function

Prepare to implement external directories support.

The patch splits depmod_modules_search() function to two
functions: depmod_modules_search(), called by the high level with
intention to search all possible modules, and
depmod_module_search_path(), which takes path as a parameter and
scans modules under the path only. Initially it is used to scan
the same depmod->cfg->dirname path only.

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>

commit 6488110e07ad49a0dc4da7bbf79dd00a50bd9cc5
Author: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Wed Nov 23 17:23:38 2016 +0200

depmod: search key: move builtin detection under the add function

Prepare to implement external directories support.

It's better to isolate behaviour difference under the
cfg_search_add() call, then make the client code aware of it.

In case of external modules/directories support, there will be
one more keyword added, so making the clients aware of it makes
even less sense.

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>

commit 183465f82e0157b7facba9e100d0e822163ca951
Author: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Wed Nov 9 08:52:26 2016 +0200

shared: make scratchbuf_str static

It fixes linking problem

tools/depmod.o: In function `output_symbols_bin':
depmod.c:(.text.output_symbols_bin+0x135): undefined reference to `scratchbuf_str'

for -O0 build, where gcc doesn't actually inline it.

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>

commit 4d202380a16b273a641b3c9e85a6d80d9f367c68
Author: Lucas De Marchi <lucas.demarchi@intel.com>
Date: Wed Aug 10 14:51:57 2016 -0300

testsuite: include stdio.h

It's used in the log macros so include it.

commit c226d66c43c7550247c76e7285aeb338dce2ea34
Author: Lucas De Marchi <lucas.demarchi@intel.com>
Date: Wed Aug 10 14:20:32 2016 -0300

Add scratchbuf implementation

This should fill the requirements for "we need to loop over a lot of
strings that usually are small enough to remain on stack, but we want to
protect ourselves against huge strings not fitting in the static
buffer we estimated as sufficient"

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
---
Makefile.am | 5 +
man/depmod.d.xml | 20 ++++
shared/scratchbuf.c | 60 +++++++++++
shared/scratchbuf.h | 31 ++++++
testsuite/.gitignore | 3 +
testsuite/test-scratchbuf.c | 89 +++++++++++++++++
testsuite/testsuite.h | 1 +
tools/depmod.c | 239 ++++++++++++++++++++++++++++++++++++--------
8 files changed, 404 insertions(+), 44 deletions(-)
create mode 100644 shared/scratchbuf.c
create mode 100644 shared/scratchbuf.h
create mode 100644 testsuite/test-scratchbuf.c

diff --git a/Makefile.am b/Makefile.am
index 896ae6366f45..407efe3f93c2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,6 +51,7 @@ shared_libshared_la_SOURCES = \
shared/array.h \
shared/hash.c \
shared/hash.h \
+ shared/scratchbuf.c \
shared/strbuf.c \
shared/strbuf.h \
shared/util.c \
@@ -307,6 +308,7 @@ testsuite_libtestsuite_la_LIBADD = -lrt
TESTSUITE = \
testsuite/test-hash \
testsuite/test-array \
+ testsuite/test-scratchbuf \
testsuite/test-strbuf \
testsuite/test-init \
testsuite/test-initstate \
@@ -329,6 +331,9 @@ testsuite_test_hash_CPPFLAGS = $(TESTSUITE_CPPFLAGS)
testsuite_test_array_LDADD = $(TESTSUITE_LDADD)
testsuite_test_array_CPPFLAGS = $(TESTSUITE_CPPFLAGS)
+testsuite_test_scratchbuf_LDADD = $(TESTSUITE_LDADD)
+testsuite_test_scratchbuf_CPPFLAGS = $(TESTSUITE_CPPFLAGS)
+
testsuite_test_strbuf_LDADD = $(TESTSUITE_LDADD)
testsuite_test_strbuf_CPPFLAGS = $(TESTSUITE_CPPFLAGS)
diff --git a/man/depmod.d.xml b/man/depmod.d.xml
index c30c06c5b605..4341a568e8a0 100644
--- a/man/depmod.d.xml
+++ b/man/depmod.d.xml
@@ -75,6 +75,9 @@
first listed directory and the lowest priority given to the last
directory listed. The special keyword <command>built-in</command>
refers to the standard module directories installed by the kernel.
+ Another special keyword <command>external</command> refers to the
+ list of external directories, defined by the
+ <command>external</command> command.
</para>
<para>
By default, depmod will give a higher priority to
@@ -110,6 +113,23 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>external <replaceable>kernelversion</replaceable>
+ <replaceable>absolutemodulesdirectory...</replaceable>
+ </term>
+ <listitem>
+ <para>
+ This specifies a list of directories, which will be checked
+ according to the priorities in the <command>search</command>
+ command. The order matters also, the first directory has the higher
+ priority.
+ </para>
+ <para>
+ The <replaceable>kernelversion</replaceable> is a POSIX regular
+ expression or * wildcard, like in the <command>override</command>.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/shared/scratchbuf.c b/shared/scratchbuf.c
new file mode 100644
index 000000000000..8d9eb83f30c1
--- /dev/null
+++ b/shared/scratchbuf.c
@@ -0,0 +1,60 @@
+/*
+ * kmod - interface to kernel module operations
+ *
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "scratchbuf.h"
+
+#include <errno.h>
+#include <string.h>
+
+void scratchbuf_init(struct scratchbuf *buf, char *stackbuf, size_t size)
+{
+ buf->bytes = stackbuf;
+ buf->size = size;
+ buf->need_free = false;
+}
+
+int scratchbuf_alloc(struct scratchbuf *buf, size_t size)
+{
+ char *tmp;
+
+ if (size <= buf->size)
+ return 0;
+
+ if (buf->need_free) {
+ tmp = realloc(buf->bytes, size);
+ if (tmp == NULL)
+ return -ENOMEM;
+ } else {
+ tmp = malloc(size);
+ if (tmp == NULL)
+ return -ENOMEM;
+ memcpy(tmp, buf->bytes, buf->size);
+ }
+
+ buf->size = size;
+ buf->bytes = tmp;
+ buf->need_free = true;
+
+ return 0;
+}
+
+void scratchbuf_release(struct scratchbuf *buf)
+{
+ if (buf->need_free)
+ free(buf->bytes);
+}
diff --git a/shared/scratchbuf.h b/shared/scratchbuf.h
new file mode 100644
index 000000000000..27ea9d9f6008
--- /dev/null
+++ b/shared/scratchbuf.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <shared/macro.h>
+
+/*
+ * Buffer abstract data type
+ */
+struct scratchbuf {
+ char *bytes;
+ size_t size;
+ bool need_free;
+};
+
+void scratchbuf_init(struct scratchbuf *buf, char *stackbuf, size_t size);
+int scratchbuf_alloc(struct scratchbuf *buf, size_t sz);
+void scratchbuf_release(struct scratchbuf *buf);
+
+/* Return a C string */
+static inline char *scratchbuf_str(struct scratchbuf *buf)
+{
+ return buf->bytes;
+}
+
+#define SCRATCHBUF_INITIALIZER(buf_) { \
+ .bytes = buf_, \
+ .size = sizeof(buf_) + _array_size_chk(buf_), \
+ .need_free = false, \
+}
diff --git a/testsuite/test-scratchbuf.c b/testsuite/test-scratchbuf.c
new file mode 100644
index 000000000000..6d86957cefb8
--- /dev/null
+++ b/testsuite/test-scratchbuf.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <shared/scratchbuf.h>
+
+#include "testsuite.h"
+
+static int test_scratchbuf_onlystack(const struct test *t)
+{
+ struct scratchbuf sbuf;
+ const char *smallstr = "xyz";
+ char buf[3 + 2];
+ char buf2[3 + 1];
+
+ scratchbuf_init(&sbuf, buf, sizeof(buf));
+ assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == false, EXIT_FAILURE);
+ scratchbuf_release(&sbuf);
+
+ scratchbuf_init(&sbuf, buf2, sizeof(buf2));
+ assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == false, EXIT_FAILURE);
+ scratchbuf_release(&sbuf);
+
+ memcpy(scratchbuf_str(&sbuf), smallstr, strlen(smallstr) + 1);
+ assert_return(strcmp(scratchbuf_str(&sbuf), smallstr) == 0, EXIT_FAILURE);
+
+ return 0;
+}
+DEFINE_TEST(test_scratchbuf_onlystack,
+ .description = "test scratchbuf for buffer on stack only");
+
+
+static int test_scratchbuf_heap(const struct test *t)
+{
+ struct scratchbuf sbuf;
+ const char *smallstr = "xyz";
+ const char *largestr = "xyzxyzxyz";
+ const char *largestr2 = "xyzxyzxyzxyzxyz";
+ char buf[3 + 1];
+
+ scratchbuf_init(&sbuf, buf, sizeof(buf));
+
+ /* Initially only on stack */
+ assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == false, EXIT_FAILURE);
+ memcpy(scratchbuf_str(&sbuf), smallstr, strlen(smallstr) + 1);
+
+ /* Grow once to heap */
+ assert_return(scratchbuf_alloc(&sbuf, strlen(largestr) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == true, EXIT_FAILURE);
+ assert_return(sbuf.size == strlen(largestr) + 1, EXIT_FAILURE);
+ assert_return(strcmp(scratchbuf_str(&sbuf), smallstr) == 0, EXIT_FAILURE);
+ memcpy(scratchbuf_str(&sbuf), largestr, strlen(largestr) + 1);
+ assert_return(strcmp(scratchbuf_str(&sbuf), largestr) == 0, EXIT_FAILURE);
+
+ /* Grow again - realloc should take place */
+ assert_return(scratchbuf_alloc(&sbuf, strlen(largestr2) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == true, EXIT_FAILURE);
+ assert_return(sbuf.size == strlen(largestr2) + 1, EXIT_FAILURE);
+ memcpy(scratchbuf_str(&sbuf), largestr2, strlen(largestr2) + 1);
+ assert_return(strcmp(scratchbuf_str(&sbuf), largestr2) == 0, EXIT_FAILURE);
+
+ scratchbuf_release(&sbuf);
+
+ return 0;
+}
+DEFINE_TEST(test_scratchbuf_heap,
+ .description = "test scratchbuf for buffer on that grows to heap");
+
+TESTSUITE_MAIN();
diff --git a/testsuite/testsuite.h b/testsuite/testsuite.h
index 3bd74f34ca7e..bb0eb507ac2f 100644
--- a/testsuite/testsuite.h
+++ b/testsuite/testsuite.h
@@ -19,6 +19,7 @@
#include <stdbool.h>
#include <stdarg.h>
+#include <stdio.h>
#include <shared/macro.h>
diff --git a/tools/depmod.c b/tools/depmod.c
index 7b9583249018..79fd14354266 100644
--- a/tools/depmod.c
+++ b/tools/depmod.c
@@ -35,6 +35,7 @@
#include <shared/hash.h>
#include <shared/macro.h>
#include <shared/util.h>
+#include <shared/scratchbuf.h>
#include <libkmod/libkmod.h>
@@ -44,6 +45,7 @@
static int verbose = DEFAULT_VERBOSE;
static const char CFG_BUILTIN_KEY[] = "built-in";
+static const char CFG_EXTERNAL_KEY[] = "external";
static const char *default_cfg_paths[] = {
"/run/depmod.d",
SYSCONFDIR "/depmod.d",
@@ -432,9 +434,21 @@ struct cfg_override {
char path[];
};
+enum search_type {
+ SEARCH_PATH,
+ SEARCH_BUILTIN,
+ SEARCH_EXTERNAL
+};
+
struct cfg_search {
struct cfg_search *next;
- uint8_t builtin;
+ enum search_type type;
+ size_t len;
+ char path[];
+};
+
+struct cfg_external {
+ struct cfg_external *next;
size_t len;
char path[];
};
@@ -449,14 +463,27 @@ struct cfg {
uint8_t warn_dups;
struct cfg_override *overrides;
struct cfg_search *searches;
+ struct cfg_external *externals;
};
-static int cfg_search_add(struct cfg *cfg, const char *path, uint8_t builtin)
+static enum search_type cfg_define_search_type(const char *path)
+{
+ if (streq(path, CFG_BUILTIN_KEY))
+ return SEARCH_BUILTIN;
+ if (streq(path, CFG_EXTERNAL_KEY))
+ return SEARCH_EXTERNAL;
+ return SEARCH_PATH;
+}
+
+static int cfg_search_add(struct cfg *cfg, const char *path)
{
struct cfg_search *s;
size_t len;
+ enum search_type type;
- if (builtin)
+ type = cfg_define_search_type(path);
+
+ if (type != SEARCH_PATH)
len = 0;
else
len = strlen(path) + 1;
@@ -466,15 +493,15 @@ static int cfg_search_add(struct cfg *cfg, const char *path, uint8_t builtin)
ERR("search add: out of memory\n");
return -ENOMEM;
}
- s->builtin = builtin;
- if (builtin)
+ s->type = type;
+ if (type != SEARCH_PATH)
s->len = 0;
else {
s->len = len - 1;
memcpy(s->path, path, len);
}
- DBG("search add: %s, builtin=%hhu\n", path, builtin);
+ DBG("search add: %s, search type=%hhu\n", path, type);
s->next = cfg->searches;
cfg->searches = s;
@@ -522,6 +549,32 @@ static void cfg_override_free(struct cfg_override *o)
free(o);
}
+static int cfg_external_add(struct cfg *cfg, const char *path)
+{
+ struct cfg_external *ext;
+ size_t len = strlen(path);
+
+ ext = malloc(sizeof(struct cfg_external) + len + 1);
+ if (ext == NULL) {
+ ERR("external add: out of memory\n");
+ return -ENOMEM;
+ }
+
+ strcpy(ext->path, path);
+ ext->len = len;
+
+ DBG("external add: %s\n", ext->path);
+
+ ext->next = cfg->externals;
+ cfg->externals = ext;
+ return 0;
+}
+
+static void cfg_external_free(struct cfg_external *ext)
+{
+ free(ext);
+}
+
static int cfg_kernel_matches(const struct cfg *cfg, const char *pattern)
{
regex_t re;
@@ -567,8 +620,7 @@ static int cfg_file_parse(struct cfg *cfg, const char *filename)
if (streq(cmd, "search")) {
const char *sp;
while ((sp = strtok_r(NULL, "\t ", &saveptr)) != NULL) {
- uint8_t builtin = streq(sp, CFG_BUILTIN_KEY);
- cfg_search_add(cfg, sp, builtin);
+ cfg_search_add(cfg, sp);
}
} else if (streq(cmd, "override")) {
const char *modname = strtok_r(NULL, "\t ", &saveptr);
@@ -586,6 +638,20 @@ static int cfg_file_parse(struct cfg *cfg, const char *filename)
}
cfg_override_add(cfg, modname, subdir);
+ } else if (streq(cmd, "external")) {
+ const char *version = strtok_r(NULL, "\t ", &saveptr);
+ const char *dir = strtok_r(NULL, "\t ", &saveptr);
+
+ if (version == NULL || dir == NULL)
+ goto syntax_error;
+
+ if (!cfg_kernel_matches(cfg, version)) {
+ INF("%s:%u: external directory did not match %s\n",
+ filename, linenum, version);
+ goto done_next;
+ }
+
+ cfg_external_add(cfg, dir);
} else if (streq(cmd, "include")
|| streq(cmd, "make_map_files")) {
INF("%s:%u: command %s not implemented yet\n",
@@ -762,7 +828,7 @@ static int cfg_load(struct cfg *cfg, const char * const *cfg_paths)
* list here. But only if there was no "search" option specified.
*/
if (cfg->searches == NULL)
- cfg_search_add(cfg, "updates", 0);
+ cfg_search_add(cfg, "updates");
return 0;
}
@@ -780,6 +846,12 @@ static void cfg_free(struct cfg *cfg)
cfg->searches = cfg->searches->next;
cfg_search_free(tmp);
}
+
+ while (cfg->externals) {
+ struct cfg_external *tmp = cfg->externals;
+ cfg->externals = cfg->externals->next;
+ cfg_external_free(tmp);
+ }
}
@@ -987,6 +1059,33 @@ static int depmod_module_del(struct depmod *depmod, struct mod *mod)
return 0;
}
+static const char *search_to_string(const struct cfg_search *s)
+{
+ switch(s->type) {
+ case SEARCH_EXTERNAL:
+ return "external";
+ case SEARCH_BUILTIN:
+ return "built-in";
+ default:
+ return s->path;
+ }
+}
+
+static bool depmod_is_path_starts_with(const char *path,
+ size_t pathlen,
+ const char *prefix,
+ size_t prefix_len)
+{
+ if (pathlen <= prefix_len)
+ return false;
+ if (path[prefix_len] != '/')
+ return false;
+ if (memcmp(path, prefix, prefix_len) != 0)
+ return false;
+
+ return true;
+}
+
/* returns if existing module @mod is higher priority than newpath.
* note this is the inverse of module-init-tools is_higher_priority()
*/
@@ -995,6 +1094,7 @@ static int depmod_module_is_higher_priority(const struct depmod *depmod, const s
const struct cfg *cfg = depmod->cfg;
const struct cfg_override *ov;
const struct cfg_search *se;
+ const struct cfg_external *ext;
/* baselen includes the last '/' and mod->baselen doesn't. So it's
* actually correct to use modnamelen in the first and modnamesz in
@@ -1003,35 +1103,55 @@ static int depmod_module_is_higher_priority(const struct depmod *depmod, const s
size_t oldlen = mod->baselen + mod->modnamesz;
const char *oldpath = mod->path;
int i, bprio = -1, oldprio = -1, newprio = -1;
-
- assert(strncmp(newpath, cfg->dirname, cfg->dirnamelen) == 0);
- assert(strncmp(oldpath, cfg->dirname, cfg->dirnamelen) == 0);
-
- newpath += cfg->dirnamelen + 1;
- newlen -= cfg->dirnamelen + 1;
- oldpath += cfg->dirnamelen + 1;
- oldlen -= cfg->dirnamelen + 1;
+ size_t relnewlen = 0;
+ size_t reloldlen = 0;
+ const char *relnewpath = NULL;
+ const char *reloldpath = NULL;
DBG("comparing priorities of %s and %s\n",
oldpath, newpath);
+ if (strncmp(newpath, cfg->dirname, cfg->dirnamelen) == 0) {
+ relnewpath = newpath + cfg->dirnamelen + 1;
+ relnewlen = newlen - cfg->dirnamelen + 1;
+ }
+ if (strncmp(oldpath, cfg->dirname, cfg->dirnamelen) == 0) {
+ reloldpath = oldpath + cfg->dirnamelen + 1;
+ reloldlen = oldlen - cfg->dirnamelen + 1;
+ }
+
for (ov = cfg->overrides; ov != NULL; ov = ov->next) {
DBG("override %s\n", ov->path);
- if (newlen == ov->len && memcmp(ov->path, newpath, newlen) == 0)
+ if (relnewlen == ov->len &&
+ memcmp(ov->path, relnewpath, relnewlen) == 0)
return 0;
- if (oldlen == ov->len && memcmp(ov->path, oldpath, oldlen) == 0)
+ if (reloldlen == ov->len &&
+ memcmp(ov->path, reloldpath, reloldlen) == 0)
return 1;
}
for (i = 0, se = cfg->searches; se != NULL; se = se->next, i++) {
- DBG("search %s\n", se->builtin ? "built-in" : se->path);
- if (se->builtin)
+ DBG("search %s\n", search_to_string(se));
+ if (se->type == SEARCH_BUILTIN)
bprio = i;
- else if (newlen > se->len && newpath[se->len] == '/' &&
- memcmp(se->path, newpath, se->len) == 0)
+ else if (se->type == SEARCH_EXTERNAL) {
+ for (ext = cfg->externals; ext != NULL; ext = ext->next, i++) {
+ if (depmod_is_path_starts_with(newpath,
+ newlen,
+ ext->path,
+ ext->len))
+ newprio = i;
+ if (depmod_is_path_starts_with(oldpath,
+ oldlen,
+ ext->path,
+ ext->len))
+ oldprio = i;
+ }
+ } else if (relnewlen > se->len && relnewpath[se->len] == '/' &&
+ memcmp(se->path, relnewpath, se->len) == 0)
newprio = i;
- else if (oldlen > se->len && oldpath[se->len] == '/' &&
- memcmp(se->path, oldpath, se->len) == 0)
+ else if (reloldlen > se->len && reloldpath[se->len] == '/' &&
+ memcmp(se->path, reloldpath, se->len) == 0)
oldprio = i;
}
@@ -1102,10 +1222,11 @@ add:
return 0;
}
-static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t baselen, char *path)
+static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t baselen, struct scratchbuf *s_path)
{
struct dirent *de;
int err = 0, dfd = dirfd(d);
+ char *path;
while ((de = readdir(d)) != NULL) {
const char *name = de->d_name;
@@ -1118,11 +1239,13 @@ static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t basel
if (streq(name, "build") || streq(name, "source"))
continue;
namelen = strlen(name);
- if (baselen + namelen + 2 >= PATH_MAX) {
- path[baselen] = '\0';
- ERR("path is too long %s%s\n", path, name);
+ if (scratchbuf_alloc(s_path, baselen + namelen + 2) < 0) {
+ err = -ENOMEM;
+ ERR("No memory\n");
continue;
}
+
+ path = scratchbuf_str(s_path);
memcpy(path + baselen, name, namelen + 1);
if (de->d_type == DT_REG)
@@ -1148,10 +1271,6 @@ static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t basel
if (is_dir) {
int fd;
DIR *subdir;
- if (baselen + namelen + 2 + NAME_MAX >= PATH_MAX) {
- ERR("directory path is too long %s\n", path);
- continue;
- }
fd = openat(dfd, name, O_RDONLY);
if (fd < 0) {
ERR("openat(%d, %s, O_RDONLY): %m\n",
@@ -1168,7 +1287,7 @@ static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t basel
path[baselen + namelen + 1] = '\0';
err = depmod_modules_search_dir(depmod, subdir,
baselen + namelen + 1,
- path);
+ s_path);
closedir(subdir);
} else {
err = depmod_modules_search_file(depmod, baselen,
@@ -1181,33 +1300,65 @@ static int depmod_modules_search_dir(struct depmod *depmod, DIR *d, size_t basel
err = 0; /* ignore errors */
}
}
-
return err;
}
-static int depmod_modules_search(struct depmod *depmod)
+static int depmod_modules_search_path(struct depmod *depmod,
+ const char *path)
{
- char path[PATH_MAX];
- DIR *d = opendir(depmod->cfg->dirname);
+ char buf[256];
+ _cleanup_(scratchbuf_release) struct scratchbuf s_path_buf =
+ SCRATCHBUF_INITIALIZER(buf);
+ char *path_buf;
+ DIR *d;
size_t baselen;
int err;
+
+ d = opendir(path);
if (d == NULL) {
err = -errno;
- ERR("could not open directory %s: %m\n", depmod->cfg->dirname);
+ ERR("could not open directory %s: %m\n", path);
return err;
}
- baselen = depmod->cfg->dirnamelen;
- memcpy(path, depmod->cfg->dirname, baselen);
- path[baselen] = '/';
+ baselen = strlen(path);
+
+ if (scratchbuf_alloc(&s_path_buf, baselen + 2) < 0) {
+ err = -ENOMEM;
+ goto out;
+ }
+ path_buf = scratchbuf_str(&s_path_buf);
+
+ memcpy(path_buf, path, baselen);
+ path_buf[baselen] = '/';
baselen++;
- path[baselen] = '\0';
+ path_buf[baselen] = '\0';
- err = depmod_modules_search_dir(depmod, d, baselen, path);
+ err = depmod_modules_search_dir(depmod, d, baselen, &s_path_buf);
+out:
closedir(d);
return err;
}
+static int depmod_modules_search(struct depmod *depmod)
+{
+ int err;
+ struct cfg_external *ext;
+
+ err = depmod_modules_search_path(depmod, depmod->cfg->dirname);
+ if (err < 0)
+ return err;
+
+ for (ext = depmod->cfg->externals; ext != NULL; ext = ext->next) {
+ err = depmod_modules_search_path(depmod, ext->path);
+ if (err < 0 && err == -ENOENT)
+ /* ignore external dir absense */
+ continue;
+ }
+
+ return 0;
+}
+
static int mod_cmp(const void *pa, const void *pb) {
const struct mod *a = *(const struct mod **)pa;
const struct mod *b = *(const struct mod **)pb;
--
2.14.1

--- kmod-20/man/depmod.d.5.orig 2017-08-17 16:01:34.330058135 +0300
+++ kmod-20/man/depmod.d.5 2017-08-17 16:01:37.901058086 +0300
@@ -1,13 +1,13 @@
'\" t
.\" Title: depmod.d
.\" Author: Jon Masters <jcm@jonmasters.org>
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 03/01/2015
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\" Date: 08/17/2017
.\" Manual: depmod.d
.\" Source: kmod
.\" Language: English
.\"
-.TH "DEPMOD\&.D" "5" "03/01/2015" "kmod" "depmod.d"
+.TH "DEPMOD\&.D" "5" "08/17/2017" "kmod" "depmod.d"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -52,7 +52,11 @@
This allows you to specify the order in which /lib/modules (or other configured module location) subdirectories will be processed by
\fBdepmod\fR\&. Directories are listed in order, with the highest priority given to the first listed directory and the lowest priority given to the last directory listed\&. The special keyword
\fBbuilt\-in\fR
-refers to the standard module directories installed by the kernel\&.
+refers to the standard module directories installed by the kernel\&. Another special keyword
+\fBexternal\fR
+refers to the list of external directories, defined by the
+\fBexternal\fR
+command\&.
.sp
By default, depmod will give a higher priority to a directory with the name
\fBupdates\fR
@@ -73,6 +77,18 @@
\fBextra\fR
subdirectory within /lib/modules (or other module location) will take priority over any likenamed module already provided by the kernel\&.
.RE
+.PP
+external \fIkernelversion\fR \fIabsolutemodulesdirectory\&.\&.\&.\fR
+.RS 4
+This specifies a list of directories, which will be checked according to the priorities in the
+\fBsearch\fR
+command\&. The order matters also, the first directory has the higher priority\&.
+.sp
+The
+\fIkernelversion\fR
+is a POSIX regular expression or * wildcard, like in the
+\fBoverride\fR\&.
+.RE
.SH "COPYRIGHT"
.PP
This manual page Copyright 2006\-2010, Jon Masters, Red Hat, Inc\&.

56
SOURCES/kmod-0006-depmod-module_is_higher_priority-fix-modname-length-.patch

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
From dd73c8a2f5e8da3c38f6e16c63f249071d440378 Mon Sep 17 00:00:00 2001
From: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
Date: Thu, 7 Dec 2017 20:59:54 +0200
Subject: [PATCH 2/2] depmod: module_is_higher_priority: fix modname length
calculation

depmod_module_is_higher_priority checks module's path if it is under
module root directory and if so uses relative to the root path to
lookup the module in override and search lists.

Originally only relative path was used in the function, so the
variables with full path and and path length were changed:

newpath += cfg->dirnamelen + 1;
newlen -= cfg->dirnamelen + 1;
oldpath += cfg->dirnamelen + 1;
oldlen -= cfg->dirnamelen + 1;

Commit 7da6884e7357ac05772e90f6d7e63b1948103fc4 (depmod: implement
external directories support) changed the logic since it need the
full path to the module for comparations as well.

Unfortunately, it introduce a mistake in calculation of the relative
paths replacing '-=' with assignment to a new variable -- the
'cfg->dirnamelen + 1' value must be substracted all together. It
breaks, for example, overrides lookup.

Fix the calculation by putting braces around the value in the
subsctuction expression.

Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@redhat.com>
---
tools/depmod.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/depmod.c b/tools/depmod.c
index 7ff3e9ed191e..921dc5cc93eb 100644
--- a/tools/depmod.c
+++ b/tools/depmod.c
@@ -1118,11 +1118,11 @@ static int depmod_module_is_higher_priority(const struct depmod *depmod, const s
if (strncmp(newpath, cfg->dirname, cfg->dirnamelen) == 0) {
relnewpath = newpath + cfg->dirnamelen + 1;
- relnewlen = newlen - cfg->dirnamelen + 1;
+ relnewlen = newlen - (cfg->dirnamelen + 1);
}
if (strncmp(oldpath, cfg->dirname, cfg->dirnamelen) == 0) {
reloldpath = oldpath + cfg->dirnamelen + 1;
- reloldlen = oldlen - cfg->dirnamelen + 1;
+ reloldlen = oldlen - (cfg->dirnamelen + 1);
}
for (ov = cfg->overrides; ov != NULL; ov = ov->next) {
--
2.15.1

176
SOURCES/weak-modules

@ -20,8 +20,11 @@ unset ${!changed_modules_*} ${!changed_initramfs_*} @@ -20,8 +20,11 @@ unset ${!changed_modules_*} ${!changed_initramfs_*}

unset BASEDIR
unset CHECK_INITRAMFS
weak_updates_dir_override=""
default_initramfs_prefix="/boot" # will be combined with BASEDIR
dracut="/sbin/dracut"
depmod="/sbin/depmod"
depmod_orig="$depmod"
declare -a modules
declare -A module_krels
declare -A weak_modules_before
@ -89,6 +92,19 @@ krel_of_module_modinfo() { @@ -89,6 +92,19 @@ krel_of_module_modinfo() {
/sbin/modinfo -F vermagic "$module" | awk '{print $1}'
}

# weak_updates_dir:
# gives the root directory for the weak-updates
# We need some flexibility here because of dry-run.
weak_updates_dir() {
local krel="$1"

if [[ -z "$weak_updates_dir_override" ]]; then
echo "$BASEDIR/lib/modules/$krel/weak-updates"
else
echo "$weak_updates_dir_override"
fi
}

# read_modules_list:
# Read in a list of modules from standard input. Convert the filenames into
# absolute paths and compute the kernel release for each module (either using
@ -286,7 +302,14 @@ module_weak_link() { @@ -286,7 +302,14 @@ module_weak_link() {
module_krel="$(krel_of_module "$module")"
subpath=$(echo $module | sed -nre "s:$BASEDIR(/usr)?/lib/modules/$module_krel/([^/]*)/(.*):\3:p")

echo "$BASEDIR/lib/modules/$krel/weak-updates/${subpath#/}"
if [[ -z $subpath ]]; then
# module is not in /lib/modules/$krel?
# It's possible for example for Oracle ACFS compatibility check
# Install it with its full path as a /lib/modules subpath
subpath="$module"
fi

echo "$(weak_updates_dir $krel)/${subpath#/}"
}

# module_short_name:
@ -321,7 +344,7 @@ is_weak_link() { @@ -321,7 +344,7 @@ is_weak_link() {
local link="$1"
local krel="$2"

echo $link | grep -q "lib/modules/$krel/weak-updates" || return 1
echo $link | grep -q "$(weak_updates_dir $krel)" || return 1
[[ -L $link ]]
}

@ -359,6 +382,17 @@ find_modules() { @@ -359,6 +382,17 @@ find_modules() {
done
}

# find_modules_dirs:
# Takes a list of directories.
# Produces list of module files in the subdirectories
find_modules_dirs() {
local dirs="$*"

for dir in $dirs; do
find $dir -name '*.ko' 2>/dev/null
done
}

# find_installed_kernels:
# Produces list of kernels, which modules are still installed
find_installed_kernels() {
@ -385,13 +419,52 @@ find_kernels_with_extra() { @@ -385,13 +419,52 @@ find_kernels_with_extra() {
remove_weak_link_quiet() {
local link="$1"
local krel="$2"
local subpath="${link#*/lib/modules/$krel/weak-updates}"
local subpath="${link#*$(weak_updates_dir $krel)}"

rm -f $link
( cd "$(weak_updates_dir $krel)" && \
rmdir --parents --ignore-fail-on-non-empty "$(dirname "${subpath#/}")" 2>/dev/null )
}

# prepare_for_dry_run:
# Takes kernel release, creates temporary weak-modules directory for it
# and depmod config to operate on it.
# Sets the global state accordingly

prepare_for_dry_run() {
local krel="$1"
local orig_dir
local dir
local conf="$tmpdir/depmod.conf"

[[ -z "$dry_run" ]] && return

#directory
orig_dir=$(weak_updates_dir $krel)
dir="$tmpdir/$krel/weak-updates"

mkdir -p "$dir"
# the orig_dir can be empty
cp -R "$orig_dir/*" "$dir" 2>/dev/null

weak_updates_dir_override="$dir"

#config
echo "search external extra built-in weak-updates" >"$conf"
echo "external $krel $dir" >>"$conf"

depmod="$depmod_orig -C $conf"
}

doit rm -f $link
( cd "$BASEDIR/lib/modules/$krel/weak-updates" && \
doit rmdir --parents --ignore-fail-on-non-empty "$(dirname "${subpath#/}")" 2>/dev/null )

# finish_dry_run:
# restore global state after dry_run changes
finish_dry_run() {
weak_updates_dir_override=""
depmod="$depmod_orig"
}


#### Main logic

# update_modules_for_krel:
@ -409,13 +482,30 @@ remove_weak_link_quiet() { @@ -409,13 +482,30 @@ remove_weak_link_quiet() {
update_modules_for_krel() {
local krel="$1"
local func="$2"
local do_fallback="$3"

[[ -r "$BASEDIR/boot/symvers-$krel.gz" ]] || return

prepare_for_dry_run $krel

global_link_state_save $krel
$func $krel
validate_weak_links $krel
if ! validate_weak_links $krel && [[ -n "$do_fallback" ]]; then
global_link_state_restore $krel

finish_dry_run

return;
fi

global_link_state_announce_changes $krel

if [[ -n "$dry_run" ]]; then
pr_verbose "Dry run: restoring configuration"
global_link_state_restore $krel
fi

finish_dry_run
}

# update_modules:
@ -426,13 +516,14 @@ update_modules_for_krel() { @@ -426,13 +516,14 @@ update_modules_for_krel() {
# Triggers initrd rebuild for the kernels, which modules are installed.
update_modules() {
local func="$1"
local do_fallback="$2"
local module_krel

read_modules_list || exit 1
[[ ${#modules[@]} -gt 0 ]] || return

for krel in $(find_installed_kernels); do
update_modules_for_krel $krel $func
update_modules_for_krel $krel $func $do_fallback
done

for module in "${modules[@]}"; do
@ -456,7 +547,11 @@ add_weak_links() { @@ -456,7 +547,11 @@ add_weak_links() {
for module in "${modules[@]}"; do
module_krel="$(krel_of_module $module)"

[[ "$module_krel" == "$krel" ]] && continue
case "$module" in
/lib/modules/$krel/*)
# Module already installed to the current kernel
continue ;;
esac

if is_extra_exists $module $module_krel $krel; then
pr_verbose "found $(module_short_name $module) for $krel while installing for $module_krel, update case?"
@ -472,8 +567,8 @@ add_weak_links() { @@ -472,8 +567,8 @@ add_weak_links() {

weak_link="$(module_weak_link $module $krel)"

doit mkdir -p "$(dirname $weak_link)"
doit ln -sf $module $weak_link
mkdir -p "$(dirname $weak_link)"
ln -sf $module $weak_link

done
}
@ -493,8 +588,6 @@ remove_weak_links() { @@ -493,8 +588,6 @@ remove_weak_links() {
for module in "${modules[@]}"; do
module_krel="$(krel_of_module $module)"

[[ "$module_krel" == "$krel" ]] && continue

weak_link="$(module_weak_link $module $krel)"
target="$(readlink $weak_link)"

@ -520,6 +613,9 @@ remove_weak_links() { @@ -520,6 +613,9 @@ remove_weak_links() {
# accroding to the priority list in its configuration, but without symbol
# check and doesn't amend the list during the check, the function runs it
# in a loop in which it removes discovered incompatible symlinks
#
# Returns 0 (success) if proposal is fine or
# 1 (false) if some incompatible symlinks were removed
validate_weak_links() {
local krel="$1"
local basedir=${BASEDIR:+-b $BASEDIR}
@ -532,6 +628,9 @@ validate_weak_links() { @@ -532,6 +628,9 @@ validate_weak_links() {
local modpath
local symbol
local weak_link
# to return to caller that original proposal is not valid
# here 0 is true, 1 is false, since it will be the return code
local is_configuration_valid=0

tmp=$(mktemp -p $tmpdir)

@ -545,7 +644,10 @@ validate_weak_links() { @@ -545,7 +644,10 @@ validate_weak_links() {

# again $tmp because of subshell, see read_modules_list() comment
# create incompatibility report by depmod
/sbin/depmod $basedir -aeE $tmpdir/symvers-$krel -e $krel >$tmp 2>&1
# Shorcut if depmod finds a lot of incompatible modules elsewhere,
# we care only about weak-updates
$depmod $basedir -naeE $tmpdir/symvers-$krel $krel 2>&1 1>/dev/null | \
grep "$(weak_updates_dir $krel)" 2>/dev/null >$tmp
# parse it into symbols[] associative array in form a-la
# symbols["/path/to/the/module"]="list of bad symbols"
while read line; do
@ -578,6 +680,7 @@ validate_weak_links() { @@ -578,6 +680,7 @@ validate_weak_links() {

pr_verbose "Module $(module_short_name $modpath) from kernel $module_krel is not compatible with kernel $krel in symbols: ${symbols[$modpath]}"
is_updates_changed=1
is_configuration_valid=1 # inversed value
done
done
rm -f $tmp
@ -595,6 +698,7 @@ validate_weak_links() { @@ -595,6 +698,7 @@ validate_weak_links() {
pr_verbose "Module ${module##*/} from kernel $module_krel is compatible with kernel $krel"
fi
done
return $is_configuration_valid
}

# global_link_state_save:
@ -607,12 +711,33 @@ global_link_state_save() { @@ -607,12 +711,33 @@ global_link_state_save() {
local target

weak_modules_before=()
for link in $(find_modules $krel weak-updates | xargs); do
for link in $(find_modules_dirs $(weak_updates_dir $krel) | xargs); do
target=$(readlink $link)
weak_modules_before[$link]=$target
done
}

# global_link_state_restore:
# Takes kernel release
# Restores the previous weak links state
# (for example, if incompatible modules were installed)
global_link_state_restore() {
local krel="$1"
local link
local target

pr_verbose "Falling back weak-modules state for kernel $krel"

( cd "$(weak_updates_dir $krel)" 2>/dev/null && rm -rf * )

for link in "${!weak_modules_before[@]}"; do
target=${weak_modules_before[$link]}

mkdir -p "$(dirname $link)"
ln -sf $target $link
done
}

# global_link_state_announce_changes:
# Takes kernel release
# Reads the given kernel's weak symlinks state, compares to the saved,
@ -625,7 +750,7 @@ global_link_state_announce_changes() { @@ -625,7 +750,7 @@ global_link_state_announce_changes() {
local new_target
declare -A weak_modules_after

for link in $(find_modules $krel weak-updates | xargs); do
for link in $(find_modules_dirs $(weak_updates_dir $krel) | xargs); do
target=${weak_modules_before[$link]}
new_target=$(readlink $link)
weak_modules_after[$link]=$new_target
@ -653,19 +778,22 @@ global_link_state_announce_changes() { @@ -653,19 +778,22 @@ global_link_state_announce_changes() {
# to the current requirements RPM will track existing of only one version
# of extra/ module (no same extra/ modules for different kernels).
remove_modules() {
update_modules remove_weak_links
local no_fallback=""

update_modules remove_weak_links $no_fallback
}

# add_modules:
# Read in a list of modules from stdinput and process them for compatibility
# with installed kernels under /lib/modules.
add_modules() {
update_modules add_weak_links
update_modules add_weak_links do_fallback
}

add_kernel() {
local krel=${1:-$(uname -r)}
local tmp
local no_fallback=""

tmp=$(mktemp -p $tmpdir)

@ -675,7 +803,7 @@ add_kernel() { @@ -675,7 +803,7 @@ add_kernel() {
exit 1
fi

for k in $(find_kernels_with_extra | rpmsort -r); do
for k in $(find_kernels_with_extra | rpmsort); do
[[ "$krel" == "$k" ]] && continue
find_modules $k extra >> $tmp
done
@ -684,12 +812,12 @@ add_kernel() { @@ -684,12 +812,12 @@ add_kernel() {
read_modules_list < $tmp
rm -f $tmp

update_modules_for_krel $krel add_weak_links
update_modules_for_krel $krel add_weak_links $no_fallback
}

remove_kernel() {
remove_krel=${1:-$(uname -r)}
weak_modules="$BASEDIR/lib/modules/$remove_krel/weak-updates"
weak_modules="$(weak_updates_dir $remove_krel)"
module_has_changed $weak_modules $remove_krel

# Remove everything beneath the weak-updates directory
@ -725,6 +853,10 @@ while :; do @@ -725,6 +853,10 @@ while :; do
;;
--dry-run)
dry_run=1
# --dry-run option is not pure dry run anymore,
# because of depmod used internally.
# For add/remove modules we have to add/remove the symlinks
# and just restore the original configuration afterwards.
;;
--no-initramfs)
no_initramfs=1
@ -795,7 +927,7 @@ for krel in ${!changed_modules_*}; do @@ -795,7 +927,7 @@ for krel in ${!changed_modules_*}; do
basedir=${BASEDIR:+-b $BASEDIR}

if is_kernel_installed $krel; then
doit /sbin/depmod $basedir -ae -F $BASEDIR/boot/System.map-$krel $krel
doit $depmod $basedir -ae -F $BASEDIR/boot/System.map-$krel $krel
else
pr_verbose "Skipping depmod for non-installed kernel $krel"
fi

43
SPECS/kmod.spec

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
Name: kmod
Version: 20
Release: 15%{?dist}
Release: 15%{?dist}.7
Summary: Linux kernel module management utilities

Group: System Environment/Kernel
@ -16,11 +16,16 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) @@ -16,11 +16,16 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
Patch01: kmod-0001-depmod-Don-t-fall-back-to-uname-on-bad-version.patch
Patch02: kmod-0002-depmod-Ignore-PowerPC64-ABIv2-.TOC.-symbol.patch
Patch03: kmod-0003-libkmod-Handle-long-lines-in-proc-modules.patch
Patch04: kmod-0004-libkmod-elf-resolve-CRC-if-module-is-built-with-MODU.patch
Patch05: kmod-0005-depmod-backport-external-directories-support.patch
Patch06: kmod-0006-depmod-module_is_higher_priority-fix-modname-length-.patch

BuildRequires: chrpath
BuildRequires: zlib-devel
BuildRequires: xz-devel
BuildRequires: libxslt
# Remove it as soon as no need for Patch05 anymore (Makefile.am updated)
BuildRequires: automake autoconf libtool

Provides: module-init-tools = 4.0-1
Obsoletes: module-init-tools < 4.0-1
@ -63,9 +68,14 @@ applications that wish to load or unload Linux kernel modules. @@ -63,9 +68,14 @@ applications that wish to load or unload Linux kernel modules.
%patch01 -p1 -b .0001-depmod-Don-t-fall-back-to-uname-on-bad-version
%patch02 -p1 -b .0002-depmod-Ignore-PowerPC64-ABIv2-.TOC.-symbol
%patch03 -p1 -b .0003-libkmod-Handle-long-lines-in-proc-modules
%patch04 -p1 -b .0004-libkmod-elf-resolve-CRC-if-module-is-built-with-MODU
%patch05 -p1 -b .0005-depmod-backport-external-directories-support
%patch06 -p1 -b .0006-depmod-module_is_higher_priority-fix-modname-length-.patch

%build
export V=1
aclocal
autoreconf --install --symlink
%configure \
--with-zlib \
--with-xz
@ -128,6 +138,37 @@ install -m 0644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/depmod.d/dist.conf @@ -128,6 +138,37 @@ install -m 0644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/depmod.d/dist.conf
%{_libdir}/libkmod.so

%changelog
* Wed Dec 13 2017 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-15.el7_4.7
- depmod: module_is_higher_priority: fix modname length calculation.
Resolves: rhbz#1525364.

* Thu Nov 16 2017 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-15.el7_4.6
- Backport external directories support.
Related: rhbz#1511943.

* Fri Nov 10 2017 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-15.el7_4.5
- weak-modules: use function to generate weak_updates_dir
- weak-modules: implement dry-run on the tempdir
Resolves: rhbz#1511943.

* Fri Sep 15 2017 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-15.el7_4.4
- bump up version for internal reasons.
Related: rhbz#1489696.

* Thu Sep 14 2017 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-15.el7_4.3
- weak-modules: implement dry run by symlink restoration.
- weak-modules: fix dry-run for non-lib-modules installation.
Resolves: rhbz#1489696.

* Thu Aug 17 2017 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-15.el7_4.2
- libkmod-elf: resolve CRC if module is built with MODULE_REL_CRCS.
- weak-modules: process only weak-updates related depmod output.
Resolves: rhbz#1482385

* Wed Jul 12 2017 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-15.el7_4.1
- weak-modules: fallback weak-modules state if incompatible installed
Resolves: rhbz#1469990

* Fri May 12 2017 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-15
- weak-modules: install weak link even if there is same name in extra.
Resolves: rhbz#1450003

Loading…
Cancel
Save