
5 changed files with 1265 additions and 23 deletions
@ -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 |
||||
|
@ -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\&. |
@ -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 |
||||
|
Loading…
Reference in new issue