aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2020-10-28 22:24:00 -0700
committerElliott Hughes <enh@google.com>2020-10-29 12:53:41 -0700
commitf9d235a152c633260a465729ab87e13529597200 (patch)
treefcb23160ed5b5444f85dedbb4e940df1ab74fa1a
parent3045ec0d51500aaecac4511d52571cb2a96f171d (diff)
parent819a125ca756003dce2d11624035b7fb605a8e99 (diff)
downloadkmod-f9d235a152c633260a465729ab87e13529597200.tar.gz
Upgrade kmod to v27
(Manually added the new source file to Android.bp.) Test: make Change-Id: I7621be93dce03f17a4989a949fd72ff8d6d29011
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml29
-rw-r--r--Android.bp1
-rw-r--r--METADATA8
-rw-r--r--Makefile.am16
-rw-r--r--NEWS49
-rw-r--r--configure.ac7
-rw-r--r--libkmod/libkmod-builtin.c329
-rw-r--r--libkmod/libkmod-config.c1
-rw-r--r--libkmod/libkmod-internal.h10
-rw-r--r--libkmod/libkmod-module.c90
-rw-r--r--libkmod/libkmod-signature.c37
-rw-r--r--libkmod/libkmod.c25
-rw-r--r--libkmod/libkmod.h1
-rw-r--r--m4/dolt.m4181
-rw-r--r--testsuite/module-playground/.gitignore5
-rw-r--r--tools/depmod.c63
-rw-r--r--tools/modinfo.c39
-rw-r--r--tools/modprobe.c20
-rw-r--r--tools/remove.c9
-rw-r--r--tools/rmmod.c9
21 files changed, 657 insertions, 274 deletions
diff --git a/.gitignore b/.gitignore
index aa02fbf..58ef42a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,8 +18,6 @@
/configure
/coverage
/cov-int
-/doltcompile
-/doltlibtool
/libtool
/stamp-h1
/test-suite.log
diff --git a/.travis.yml b/.travis.yml
index 4b36e1f..02c753e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,16 @@
language: c
+
+matrix:
+ include:
+ - compiler: gcc
+ env: MYCC=gcc
+ - compiler: gcc
+ env: MYCC=gcc-4.8
+ - compiler: gcc
+ env: MYCC=gcc-4.9
+ - compiler: clang
+ env: MYCC=clang
+
before_install:
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update -qq
@@ -9,20 +21,15 @@ before_install:
- sudo apt-get install -qq linux-headers-generic
- if [ "$MYCC" = "gcc-4.8" ]; then sudo apt-get install -qq gcc-4.8; sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 90; gcc --version; fi
- if [ "$MYCC" = "gcc-4.9" ]; then sudo apt-get install -qq gcc-4.9; sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 90; gcc --version; fi
+
before_script:
- unset PYTHON_CFLAGS # hack to broken travis setup
- export KDIR="$(find /lib/modules/* -maxdepth 1 -name build | sort -n --reverse | head -1)"
-matrix:
- include:
- - compiler: gcc
- env: MYCC=gcc
- - compiler: gcc
- env: MYCC=gcc-4.8
- - compiler: gcc
- env: MYCC=gcc-4.9
- - compiler: clang
- env: MYCC=clang
-script: ./autogen.sh c --without-openssl && make -j && make -j check
+
+script:
+ - ./autogen.sh c --without-openssl && make -j
+ - if [ "$MYCC" != "gcc-4.8" ]; then make -j check; fi
+
notifications:
irc:
channels:
diff --git a/Android.bp b/Android.bp
index f6edaa0..8034826 100644
--- a/Android.bp
+++ b/Android.bp
@@ -30,6 +30,7 @@ cc_library_static {
name: "libkmod",
srcs: [
"libkmod/libkmod.c",
+ "libkmod/libkmod-builtin.c",
"libkmod/libkmod-file.c",
"libkmod/libkmod-module.c",
"libkmod/libkmod-config.c",
diff --git a/METADATA b/METADATA
index a3b19be..eac483f 100644
--- a/METADATA
+++ b/METADATA
@@ -5,11 +5,11 @@ third_party {
type: GIT
value: "https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git"
}
- version: "v26"
+ version: "v27"
license_type: RESTRICTED
last_upgrade_date {
- year: 2019
- month: 2
- day: 7
+ year: 2020
+ month: 10
+ day: 28
}
}
diff --git a/Makefile.am b/Makefile.am
index ddb25f0..8eadb99 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,15 +35,15 @@ SED_PROCESS = \
-e 's,@liblzma_LIBS\@,${liblzma_LIBS},g' \
-e 's,@zlib_CFLAGS\@,${zlib_CFLAGS},g' \
-e 's,@zlib_LIBS\@,${zlib_LIBS},g' \
- -e 's,@openssl_CFLAGS\@,${openssl_CFLAGS},g' \
- -e 's,@openssl_LIBS\@,${openssl_LIBS},g' \
+ -e 's,@libcrypto_CFLAGS\@,${libcrypto_CFLAGS},g' \
+ -e 's,@libcrypto_LIBS\@,${libcrypto_LIBS},g' \
< $< > $@ || rm $@
%.pc: %.pc.in Makefile
$(SED_PROCESS)
LIBKMOD_CURRENT=5
-LIBKMOD_REVISION=4
+LIBKMOD_REVISION=5
LIBKMOD_AGE=3
noinst_LTLIBRARIES = shared/libshared.la
@@ -68,6 +68,7 @@ libkmod_libkmod_la_SOURCES = \
libkmod/libkmod.h \
libkmod/libkmod-internal.h \
libkmod/libkmod.c \
+ libkmod/libkmod-builtin.c \
libkmod/libkmod-list.c \
libkmod/libkmod-config.c \
libkmod/libkmod-index.c \
@@ -89,7 +90,7 @@ libkmod_libkmod_la_DEPENDENCIES = \
${top_srcdir}/libkmod/libkmod.sym
libkmod_libkmod_la_LIBADD = \
shared/libshared.la \
- ${liblzma_LIBS} ${zlib_LIBS} ${openssl_LIBS}
+ ${liblzma_LIBS} ${zlib_LIBS} ${libcrypto_LIBS}
noinst_LTLIBRARIES += libkmod/libkmod-internal.la
libkmod_libkmod_internal_la_SOURCES = $(libkmod_libkmod_la_SOURCES)
@@ -173,7 +174,10 @@ CPYTHON_MODULE_CFLAGS = \
$(AM_CFLAGS) -DCPYTHON_COMPILING_IN_PYPY=0 \
$(PYTHON_NOWARN) $(PYTHON_CFLAGS) \
-fvisibility=default
-CPYTHON_MODULE_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version -shared
+# Filter -Wl,--no-undefined to fix build with python 3.8
+comma = ,
+CPYTHON_MODULE_LDFLAGS = $(subst -Wl$(comma)--no-undefined,,$(AM_LDFLAGS))
+CPYTHON_MODULE_LDFLAGS += -module -avoid-version -shared
if BUILD_PYTHON
pkgpyexec_LTLIBRARIES = \
@@ -415,8 +419,6 @@ distclean-local: $(DISTCLEAN_LOCAL_HOOKS)
buildtest-TESTS:
$(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) $(check_PROGRAMS)
-DISTCLEANFILES += $(DOLT_CLEANFILES)
-
# ------------------------------------------------------------------------------
# coverage
# ------------------------------------------------------------------------------
diff --git a/NEWS b/NEWS
index 58c4e2f..1c80582 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,52 @@
+kmod 27
+=======
+
+- Improvements
+ - Link to libcrypto rather than requiring openssl
+
+ - Print a better error message when kernel doesn't support module unload
+
+ - Use PKCS#7 instead of CMS for parsing module signature to be
+ compatible with LibreSSL and OpenSSL < 1.1.0
+
+ - Teach modinfo to parse modules.builtin.modinfo. When using Linux kernel
+ >= v5.2-rc1 it's possible to get module information from this new file. Now
+ modinfo is able to show it instead of an error message that the module is
+ built-in:
+
+ Before:
+ $ modinfo ext4
+ modinfo: ERROR: Module ext4 not found.
+
+ After:
+ $ modinfo ext4
+ name: ext4
+ filename: (builtin)
+ softdep: pre: crc32c
+ license: GPL
+ description: Fourth Extended Filesystem
+ author: Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others
+ alias: fs-ext4
+ alias: ext3
+ alias: fs-ext3
+ alias: ext2
+ alias: fs-ext2
+
+- Bug fixes
+ - Do not link python bindings with libpython to be compatible with
+ python3.8
+
+ - Fix module removal with `modprobe -r` when a dependency is built-in.
+ Now it properly ignores them and proceed with removal of other
+ dependencies
+
+ - Fix propagation of return code from install/remove commands to the
+ the probe function. The return values of kmod_module_probe_insert_module()
+ have very specific meanings, do not confuse the caller by return codes
+ from system()
+
+ - Fix softdep config parsing leading to buffer overflow
+
kmod 26
=======
diff --git a/configure.ac b/configure.ac
index ee72283..4a65d6b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
AC_PREREQ(2.64)
AC_INIT([kmod],
- [26],
+ [27],
[linux-modules@vger.kernel.org],
[kmod],
[http://git.kernel.org/?p=utils/kernel/kmod/kmod.git])
@@ -17,7 +17,6 @@ AM_MAINTAINER_MODE([enable])
AM_INIT_AUTOMAKE([check-news foreign 1.11 silent-rules tar-pax no-dist-gzip dist-xz subdir-objects color-tests parallel-tests])
AM_SILENT_RULES([yes])
LT_INIT([disable-static pic-only])
-DOLT
AS_IF([test "x$enable_static" = "xyes"], [AC_MSG_ERROR([--enable-static is not supported by kmod])])
AS_IF([test "x$enable_largefile" = "xno"], [AC_MSG_ERROR([--disable-largefile is not supported by kmod])])
@@ -110,12 +109,12 @@ AC_ARG_WITH([openssl],
AS_HELP_STRING([--with-openssl], [handle PKCS7 signatures @<:@default=disabled@:>@]),
[], [with_openssl=no])
AS_IF([test "x$with_openssl" != "xno"], [
- PKG_CHECK_MODULES([openssl], [openssl >= 1.1.0])
+ PKG_CHECK_MODULES([libcrypto], [libcrypto >= 1.1.0])
AC_DEFINE([ENABLE_OPENSSL], [1], [Enable openssl for modinfo.])
], [
AC_MSG_NOTICE([openssl support not requested])
])
-CC_FEATURE_APPEND([with_features], [with_openssl], [OPENSSL])
+CC_FEATURE_APPEND([with_features], [with_openssl], [LIBCRYPTO])
AC_ARG_WITH([bashcompletiondir],
AS_HELP_STRING([--with-bashcompletiondir=DIR], [Bash completions directory]),
diff --git a/libkmod/libkmod-builtin.c b/libkmod/libkmod-builtin.c
new file mode 100644
index 0000000..aaec5dd
--- /dev/null
+++ b/libkmod/libkmod-builtin.c
@@ -0,0 +1,329 @@
+/*
+ * libkmod - interface to kernel built-in modules
+ *
+ * Copyright (C) 2019 Alexey Gladkov <gladkov.alexey@gmail.com>
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "libkmod.h"
+#include "libkmod-internal.h"
+
+#define MODULES_BUILTIN_MODINFO "modules.builtin.modinfo"
+
+struct kmod_builtin_iter {
+ struct kmod_ctx *ctx;
+
+ // The file descriptor.
+ int file;
+
+ // The total size in bytes.
+ ssize_t size;
+
+ // The offset of current module.
+ off_t pos;
+
+ // The offset at which the next module is located.
+ off_t next;
+
+ // Number of strings in the current block.
+ ssize_t nstrings;
+
+ // Internal buffer and its size.
+ size_t bufsz;
+ char *buf;
+};
+
+struct kmod_builtin_iter *kmod_builtin_iter_new(struct kmod_ctx *ctx)
+{
+ char path[PATH_MAX];
+ int file, sv_errno;
+ struct stat sb;
+ struct kmod_builtin_iter *iter = NULL;
+ const char *dirname = kmod_get_dirname(ctx);
+ size_t len = strlen(dirname);
+
+ file = -1;
+
+ if ((len + 1 + strlen(MODULES_BUILTIN_MODINFO) + 1) >= PATH_MAX) {
+ sv_errno = ENAMETOOLONG;
+ goto fail;
+ }
+
+ snprintf(path, PATH_MAX, "%s/%s", dirname, MODULES_BUILTIN_MODINFO);
+
+ file = open(path, O_RDONLY|O_CLOEXEC);
+ if (file < 0) {
+ sv_errno = errno;
+ goto fail;
+ }
+
+ if (fstat(file, &sb) < 0) {
+ sv_errno = errno;
+ goto fail;
+ }
+
+ iter = malloc(sizeof(*iter));
+ if (!iter) {
+ sv_errno = ENOMEM;
+ goto fail;
+ }
+
+ iter->ctx = ctx;
+ iter->file = file;
+ iter->size = sb.st_size;
+ iter->nstrings = 0;
+ iter->pos = 0;
+ iter->next = 0;
+ iter->bufsz = 0;
+ iter->buf = NULL;
+
+ return iter;
+fail:
+ if (file >= 0)
+ close(file);
+
+ errno = sv_errno;
+
+ return iter;
+}
+
+void kmod_builtin_iter_free(struct kmod_builtin_iter *iter)
+{
+ close(iter->file);
+ free(iter->buf);
+ free(iter);
+}
+
+static off_t get_string(struct kmod_builtin_iter *iter, off_t offset,
+ char **line, size_t *size)
+{
+ int sv_errno;
+ char *nullp = NULL;
+ size_t linesz = 0;
+
+ while (!nullp) {
+ char buf[BUFSIZ];
+ ssize_t sz;
+ size_t partsz;
+
+ sz = pread(iter->file, buf, BUFSIZ, offset);
+ if (sz < 0) {
+ sv_errno = errno;
+ goto fail;
+ } else if (sz == 0) {
+ offset = 0;
+ break;
+ }
+
+ nullp = memchr(buf, '\0', (size_t) sz);
+ partsz = (size_t)((nullp) ? (nullp - buf) + 1 : sz);
+ offset += (off_t) partsz;
+
+ if (iter->bufsz < linesz + partsz) {
+ iter->bufsz = linesz + partsz;
+ iter->buf = realloc(iter->buf, iter->bufsz);
+
+ if (!iter->buf) {
+ sv_errno = errno;
+ goto fail;
+ }
+ }
+
+ strncpy(iter->buf + linesz, buf, partsz);
+ linesz += partsz;
+ }
+
+ if (linesz) {
+ *line = iter->buf;
+ *size = linesz;
+ }
+
+ return offset;
+fail:
+ errno = sv_errno;
+ return -1;
+}
+
+bool kmod_builtin_iter_next(struct kmod_builtin_iter *iter)
+{
+ char *line, *modname;
+ size_t linesz;
+ off_t pos, offset, modlen;
+
+ modname = NULL;
+
+ iter->nstrings = 0;
+ offset = pos = iter->next;
+
+ while (offset < iter->size) {
+ char *dot;
+ off_t len;
+
+ offset = get_string(iter, pos, &line, &linesz);
+ if (offset <= 0) {
+ if (offset)
+ ERR(iter->ctx, "get_string: %s\n", strerror(errno));
+ pos = iter->size;
+ break;
+ }
+
+ dot = strchr(line, '.');
+ if (!dot) {
+ ERR(iter->ctx, "kmod_builtin_iter_next: unexpected string without modname prefix\n");
+ pos = iter->size;
+ break;
+ }
+
+ len = dot - line;
+
+ if (!modname) {
+ modname = strdup(line);
+ modlen = len;
+ } else if (modlen != len || strncmp(modname, line, len)) {
+ break;
+ }
+
+ iter->nstrings++;
+ pos = offset;
+ }
+
+ iter->pos = iter->next;
+ iter->next = pos;
+
+ free(modname);
+
+ return (iter->pos < iter->size);
+}
+
+bool kmod_builtin_iter_get_modname(struct kmod_builtin_iter *iter,
+ char modname[static PATH_MAX])
+{
+ int sv_errno;
+ char *line, *dot;
+ size_t linesz, len;
+ off_t offset;
+
+ if (iter->pos == iter->size)
+ return false;
+
+ line = NULL;
+
+ offset = get_string(iter, iter->pos, &line, &linesz);
+ if (offset <= 0) {
+ sv_errno = errno;
+ if (offset)
+ ERR(iter->ctx, "get_string: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ dot = strchr(line, '.');
+ if (!dot) {
+ sv_errno = errno;
+ ERR(iter->ctx, "kmod_builtin_iter_get_modname: unexpected string without modname prefix\n");
+ goto fail;
+ }
+
+ len = dot - line;
+
+ if (len > PATH_MAX) {
+ sv_errno = ENAMETOOLONG;
+ goto fail;
+ }
+
+ strncpy(modname, line, len);
+ modname[len] = '\0';
+
+ return true;
+fail:
+ errno = sv_errno;
+ return false;
+}
+
+/* array will be allocated with strings in a single malloc, just free *array */
+ssize_t kmod_builtin_get_modinfo(struct kmod_ctx *ctx, const char *modname,
+ char ***modinfo)
+{
+ ssize_t count = 0;
+ char *s, *line = NULL;
+ size_t i, n, linesz, modlen, size;
+ off_t pos, offset;
+
+ char *name = NULL;
+ char buf[PATH_MAX];
+
+ struct kmod_builtin_iter *iter = kmod_builtin_iter_new(ctx);
+
+ if (!iter)
+ return -errno;
+
+ while (!name && kmod_builtin_iter_next(iter)) {
+ if (!kmod_builtin_iter_get_modname(iter, buf)) {
+ count = -errno;
+ goto fail;
+ }
+
+ if (strcmp(modname, buf))
+ continue;
+
+ name = buf;
+ }
+
+ if (!name) {
+ count = -ENOSYS;
+ goto fail;
+ }
+
+ modlen = strlen(modname) + 1;
+ count = iter->nstrings;
+ size = iter->next - iter->pos - (modlen * count);
+
+ *modinfo = malloc(size + sizeof(char *) * (count + 1));
+ if (!*modinfo) {
+ count = -errno;
+ goto fail;
+ }
+
+ s = (char *)(*modinfo + count + 1);
+ i = 0;
+
+ n = 0;
+ offset = pos = iter->pos;
+
+ while (offset < iter->next) {
+ offset = get_string(iter, pos, &line, &linesz);
+ if (offset <= 0) {
+ count = (offset) ? -errno : -EOF;
+ goto fail;
+ }
+
+ strcpy(s + i, line + modlen);
+ (*modinfo)[n++] = s + i;
+ i += linesz - modlen;
+
+ pos = offset;
+ }
+fail:
+ kmod_builtin_iter_free(iter);
+ return count;
+}
diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c
index aaac0a1..7b62367 100644
--- a/libkmod/libkmod-config.c
+++ b/libkmod/libkmod-config.c
@@ -335,6 +335,7 @@ static int kmod_config_add_softdep(struct kmod_config *config,
n_pre = 0;
n_post = 0;
mode = S_NONE;
+ was_space = false;
for (p = s = line; ; s++) {
size_t plen;
diff --git a/libkmod/libkmod-internal.h b/libkmod/libkmod-internal.h
index a65ddd1..b22ac2a 100644
--- a/libkmod/libkmod-internal.h
+++ b/libkmod/libkmod-internal.h
@@ -89,6 +89,7 @@ int kmod_lookup_alias_from_config(struct kmod_ctx *ctx, const char *name, struct
int kmod_lookup_alias_from_symbols_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
int kmod_lookup_alias_from_aliases_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
int kmod_lookup_alias_from_moddep_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
+int kmod_lookup_alias_from_kernel_builtin_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
int kmod_lookup_alias_from_builtin_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
bool kmod_lookup_alias_is_builtin(struct kmod_ctx *ctx, const char *name) __attribute__((nonnull(1, 2)));
int kmod_lookup_alias_from_commands(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
@@ -145,6 +146,7 @@ void kmod_module_set_visited(struct kmod_module *mod, bool visited) __attribute_
void kmod_module_set_builtin(struct kmod_module *mod, bool builtin) __attribute__((nonnull((1))));
void kmod_module_set_required(struct kmod_module *mod, bool required) __attribute__((nonnull(1)));
bool kmod_module_is_builtin(struct kmod_module *mod) __attribute__((nonnull(1)));
+int kmod_module_get_builtin(struct kmod_ctx *ctx, struct kmod_list **list) __attribute__((nonnull(1, 2)));
/* libkmod-file.c */
struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx, const char *filename) _must_check_ __attribute__((nonnull(1,2)));
@@ -193,3 +195,11 @@ struct kmod_signature_info {
};
bool kmod_module_signature_info(const struct kmod_file *file, struct kmod_signature_info *sig_info) _must_check_ __attribute__((nonnull(1, 2)));
void kmod_module_signature_info_free(struct kmod_signature_info *sig_info) __attribute__((nonnull));
+
+/* libkmod-builtin.c */
+struct kmod_builtin_iter;
+struct kmod_builtin_iter *kmod_builtin_iter_new(struct kmod_ctx *ctx) __attribute__((nonnull(1)));
+void kmod_builtin_iter_free(struct kmod_builtin_iter *iter) __attribute__((nonnull(1)));
+bool kmod_builtin_iter_next(struct kmod_builtin_iter *iter) __attribute__((nonnull(1)));
+bool kmod_builtin_iter_get_modname(struct kmod_builtin_iter *iter, char modname[static PATH_MAX]) __attribute__((nonnull(1, 2)));
+ssize_t kmod_builtin_get_modinfo(struct kmod_ctx *ctx, const char *modname, char ***modinfo) __attribute__((nonnull(1, 2, 3)));
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
index bffe715..714ee21 100644
--- a/libkmod/libkmod-module.c
+++ b/libkmod/libkmod-module.c
@@ -575,10 +575,16 @@ KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx,
err = kmod_lookup_alias_from_aliases_file(ctx, alias, list);
CHECK_ERR_AND_FINISH(err, fail, list, finish);
- DBG(ctx, "lookup modules.builtin %s\n", alias);
- err = kmod_lookup_alias_from_builtin_file(ctx, alias, list);
+ DBG(ctx, "lookup modules.builtin.modinfo %s\n", alias);
+ err = kmod_lookup_alias_from_kernel_builtin_file(ctx, alias, list);
CHECK_ERR_AND_FINISH(err, fail, list, finish);
+ if (err == 0) {
+ DBG(ctx, "lookup modules.builtin %s\n", alias);
+ err = kmod_lookup_alias_from_builtin_file(ctx, alias, list);
+ CHECK_ERR_AND_FINISH(err, fail, list, finish);
+ }
+
finish:
DBG(ctx, "lookup %s=%d, list=%p\n", alias, err, *list);
return err;
@@ -974,14 +980,19 @@ static int command_do(struct kmod_module *mod, const char *type,
err = system(cmd);
unsetenv("MODPROBE_MODULE");
- if (err == -1 || WEXITSTATUS(err)) {
- ERR(mod->ctx, "Error running %s command for %s\n",
- type, modname);
- if (err != -1)
- err = -WEXITSTATUS(err);
+ if (err == -1) {
+ ERR(mod->ctx, "Could not run %s command '%s' for module %s: %m\n",
+ type, cmd, modname);
+ return -EINVAL;
}
- return err;
+ if (WEXITSTATUS(err)) {
+ ERR(mod->ctx, "Error running %s command '%s' for module %s: retcode %d\n",
+ type, cmd, modname, WEXITSTATUS(err));
+ return -EINVAL;
+ }
+
+ return 0;
}
struct probe_insert_cb {
@@ -2280,13 +2291,22 @@ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_
assert(*list == NULL);
- elf = kmod_module_get_elf(mod);
- if (elf == NULL)
- return -errno;
+ /* remove const: this can only change internal state */
+ if (kmod_module_is_builtin((struct kmod_module *)mod)) {
+ count = kmod_builtin_get_modinfo(mod->ctx,
+ kmod_module_get_name(mod),
+ &strings);
+ if (count < 0)
+ return count;
+ } else {
+ elf = kmod_module_get_elf(mod);
+ if (elf == NULL)
+ return -errno;
- count = kmod_elf_get_strings(elf, ".modinfo", &strings);
- if (count < 0)
- return count;
+ count = kmod_elf_get_strings(elf, ".modinfo", &strings);
+ if (count < 0)
+ return count;
+ }
for (i = 0; i < count; i++) {
struct kmod_list *n;
@@ -2310,7 +2330,7 @@ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_
goto list_error;
}
- if (kmod_module_signature_info(mod->file, &sig_info)) {
+ if (mod->file && kmod_module_signature_info(mod->file, &sig_info)) {
struct kmod_list *n;
n = kmod_module_info_append(list, "sig_id", strlen("sig_id"),
@@ -2866,3 +2886,43 @@ KMOD_EXPORT void kmod_module_dependency_symbols_free_list(struct kmod_list *list
list = kmod_list_remove(list);
}
}
+
+/**
+ * kmod_module_get_builtin:
+ * @ctx: kmod library context
+ * @list: where to save the builtin module list
+ *
+ * Returns: 0 on success or < 0 otherwise.
+ */
+int kmod_module_get_builtin(struct kmod_ctx *ctx, struct kmod_list **list)
+{
+ struct kmod_builtin_iter *iter;
+ int err = 0;
+
+ iter = kmod_builtin_iter_new(ctx);
+ if (!iter)
+ return -errno;
+
+ while (kmod_builtin_iter_next(iter)) {
+ struct kmod_module *mod = NULL;
+ char modname[PATH_MAX];
+
+ if (!kmod_builtin_iter_get_modname(iter, modname)) {
+ err = -errno;
+ goto fail;
+ }
+
+ kmod_module_new_from_name(ctx, modname, &mod);
+ kmod_module_set_builtin(mod, true);
+
+ *list = kmod_list_append(*list, mod);
+ }
+
+ kmod_builtin_iter_free(iter);
+ return err;
+fail:
+ kmod_builtin_iter_free(iter);
+ kmod_module_unref_list(*list);
+ *list = NULL;
+ return err;
+}
diff --git a/libkmod/libkmod-signature.c b/libkmod/libkmod-signature.c
index 27d0a8f..9877cf3 100644
--- a/libkmod/libkmod-signature.c
+++ b/libkmod/libkmod-signature.c
@@ -19,7 +19,7 @@
#include <inttypes.h>
#ifdef ENABLE_OPENSSL
-#include <openssl/cms.h>
+#include <openssl/pkcs7.h>
#include <openssl/ssl.h>
#endif
#include <stdio.h>
@@ -121,7 +121,7 @@ static bool fill_default(const char *mem, off_t size,
#ifdef ENABLE_OPENSSL
struct pkcs7_private {
- CMS_ContentInfo *cms;
+ PKCS7 *pkcs7;
unsigned char *key_id;
BIGNUM *sno;
};
@@ -131,7 +131,7 @@ static void pkcs7_free(void *s)
struct kmod_signature_info *si = s;
struct pkcs7_private *pvt = si->private;
- CMS_ContentInfo_free(pvt->cms);
+ PKCS7_free(pvt->pkcs7);
BN_free(pvt->sno);
free(pvt->key_id);
free(pvt);
@@ -196,11 +196,10 @@ static bool fill_pkcs7(const char *mem, off_t size,
struct kmod_signature_info *sig_info)
{
const char *pkcs7_raw;
- CMS_ContentInfo *cms;
- STACK_OF(CMS_SignerInfo) *sis;
- CMS_SignerInfo *si;
- int rc;
- ASN1_OCTET_STRING *key_id;
+ PKCS7 *pkcs7;
+ STACK_OF(PKCS7_SIGNER_INFO) *sis;
+ PKCS7_SIGNER_INFO *si;
+ PKCS7_ISSUER_AND_SERIAL *is;
X509_NAME *issuer;
ASN1_INTEGER *sno;
ASN1_OCTET_STRING *sig;
@@ -219,31 +218,33 @@ static bool fill_pkcs7(const char *mem, off_t size,
in = BIO_new_mem_buf(pkcs7_raw, sig_len);
- cms = d2i_CMS_bio(in, NULL);
- if (cms == NULL) {
+ pkcs7 = d2i_PKCS7_bio(in, NULL);
+ if (pkcs7 == NULL) {
BIO_free(in);
return false;
}
BIO_free(in);
- sis = CMS_get0_SignerInfos(cms);
+ sis = PKCS7_get_signer_info(pkcs7);
if (sis == NULL)
goto err;
- si = sk_CMS_SignerInfo_value(sis, 0);
+ si = sk_PKCS7_SIGNER_INFO_value(sis, 0);
if (si == NULL)
goto err;
- rc = CMS_SignerInfo_get0_signer_id(si, &key_id, &issuer, &sno);
- if (rc == 0)
+ is = si->issuer_and_serial;
+ if (is == NULL)
goto err;
+ issuer = is->issuer;
+ sno = is->serial;
- sig = CMS_SignerInfo_get0_signature(si);
+ sig = si->enc_digest;
if (sig == NULL)
goto err;
- CMS_SignerInfo_get0_algs(si, NULL, NULL, &dig_alg, &sig_alg);
+ PKCS7_SIGNER_INFO_get0_algs(si, NULL, &dig_alg, &sig_alg);
sig_info->sig = (const char *)ASN1_STRING_get0_data(sig);
sig_info->sig_len = ASN1_STRING_length(sig);
@@ -276,7 +277,7 @@ static bool fill_pkcs7(const char *mem, off_t size,
if (pvt == NULL)
goto err3;
- pvt->cms = cms;
+ pvt->pkcs7 = pkcs7;
pvt->key_id = key_id_str;
pvt->sno = sno_bn;
sig_info->private = pvt;
@@ -289,7 +290,7 @@ err3:
err2:
BN_free(sno_bn);
err:
- CMS_ContentInfo_free(cms);
+ PKCS7_free(pkcs7);
return false;
}
diff --git a/libkmod/libkmod.c b/libkmod/libkmod.c
index 69fe431..c9d9e2a 100644
--- a/libkmod/libkmod.c
+++ b/libkmod/libkmod.c
@@ -57,6 +57,7 @@ static struct _index_files {
[KMOD_INDEX_MODULES_DEP] = { .fn = "modules.dep", .prefix = "" },
[KMOD_INDEX_MODULES_ALIAS] = { .fn = "modules.alias", .prefix = "alias " },
[KMOD_INDEX_MODULES_SYMBOL] = { .fn = "modules.symbols", .prefix = "alias "},
+ [KMOD_INDEX_MODULES_BUILTIN_ALIAS] = { .fn = "modules.builtin.alias", .prefix = "" },
[KMOD_INDEX_MODULES_BUILTIN] = { .fn = "modules.builtin", .prefix = ""},
};
@@ -522,6 +523,30 @@ static char *lookup_builtin_file(struct kmod_ctx *ctx, const char *name)
return line;
}
+int kmod_lookup_alias_from_kernel_builtin_file(struct kmod_ctx *ctx,
+ const char *name,
+ struct kmod_list **list)
+{
+ struct kmod_list *l;
+ int ret = kmod_lookup_alias_from_alias_bin(ctx,
+ KMOD_INDEX_MODULES_BUILTIN_ALIAS,
+ name, list);
+ if (ret > 0) {
+ kmod_list_foreach(l, *list) {
+ struct kmod_module *mod = l->data;
+ kmod_module_set_builtin(mod, true);
+ }
+ } else if (ret == -ENOSYS) {
+ /*
+ * If the system does not support this yet, then
+ * there is no need to return an error.
+ */
+ ret = 0;
+ }
+
+ return ret;
+}
+
int kmod_lookup_alias_from_builtin_file(struct kmod_ctx *ctx, const char *name,
struct kmod_list **list)
{
diff --git a/libkmod/libkmod.h b/libkmod/libkmod.h
index 352627e..3cab2e5 100644
--- a/libkmod/libkmod.h
+++ b/libkmod/libkmod.h
@@ -70,6 +70,7 @@ enum kmod_index {
KMOD_INDEX_MODULES_DEP = 0,
KMOD_INDEX_MODULES_ALIAS,
KMOD_INDEX_MODULES_SYMBOL,
+ KMOD_INDEX_MODULES_BUILTIN_ALIAS,
KMOD_INDEX_MODULES_BUILTIN,
/* Padding to make sure enum is not mapped to char */
_KMOD_INDEX_PAD = 1U << 31,
diff --git a/m4/dolt.m4 b/m4/dolt.m4
deleted file mode 100644
index 775a572..0000000
--- a/m4/dolt.m4
+++ /dev/null
@@ -1,181 +0,0 @@
-dnl dolt, a replacement for libtool
-dnl Copyright © 2007-2010 Josh Triplett <josh@joshtriplett.org>
-dnl Copying and distribution of this file, with or without modification,
-dnl are permitted in any medium without royalty provided the copyright
-dnl notice and this notice are preserved.
-dnl
-dnl To use dolt, invoke the DOLT macro immediately after the libtool macros.
-dnl Optionally, copy this file into acinclude.m4, to avoid the need to have it
-dnl installed when running autoconf on your project.
-
-AC_DEFUN([DOLT], [
-AC_REQUIRE([AC_CANONICAL_HOST])
-# dolt, a replacement for libtool
-# Josh Triplett <josh@freedesktop.org>
-AC_PATH_PROG([DOLT_BASH], [bash])
-AC_MSG_CHECKING([if dolt supports this host])
-dolt_supported=yes
-AS_IF([test x$DOLT_BASH = x], [dolt_supported=no])
-AS_IF([test x$GCC != xyes], [dolt_supported=no])
-
-AS_CASE([$host],
- [*-*-linux*|*-*-freebsd*], [pic_options='-fPIC'],
- [*-apple-darwin*], [pic_options='-fno-common'],
- [*mingw*|*nacl*], [pic_options='']
- [*], [dolt_supported=no]
-)
-AS_IF([test x$dolt_supported = xno], [
- AC_MSG_RESULT([no, falling back to libtool])
- LTCOMPILE='$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(COMPILE)'
- LTCXXCOMPILE='$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXXCOMPILE)'
- m4_pattern_allow([AM_V_lt])
-], [
- AC_MSG_RESULT([yes, replacing libtool])
-
-dnl Start writing out doltcompile.
- cat <<__DOLTCOMPILE__EOF__ >doltcompile
-#!$DOLT_BASH
-__DOLTCOMPILE__EOF__
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-args=("$[]@")
-for ((arg=0; arg<${#args@<:@@@:>@}; arg++)) ; do
- if test x"${args@<:@$arg@:>@}" = x-o ; then
- objarg=$((arg+1))
- break
- fi
-done
-if test x$objarg = x ; then
- echo 'Error: no -o on compiler command line' 1>&2
- exit 1
-fi
-lo="${args@<:@$objarg@:>@}"
-obj="${lo%.lo}"
-if test x"$lo" = x"$obj" ; then
- echo "Error: libtool object file name \"$lo\" does not end in .lo" 1>&2
- exit 1
-fi
-objbase="${obj##*/}"
-__DOLTCOMPILE__EOF__
-
-dnl Write out shared compilation code.
- if test x$enable_shared = xyes; then
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-libobjdir="${obj%$objbase}.libs"
-if test ! -d "$libobjdir" ; then
- mkdir_out="$(mkdir "$libobjdir" 2>&1)"
- mkdir_ret=$?
- if test "$mkdir_ret" -ne 0 && test ! -d "$libobjdir" ; then
- echo "$mkdir_out" 1>&2
- exit $mkdir_ret
- fi
-fi
-pic_object="$libobjdir/$objbase.o"
-args@<:@$objarg@:>@="$pic_object"
-__DOLTCOMPILE__EOF__
- cat <<__DOLTCOMPILE__EOF__ >>doltcompile
- pic_options="$pic_options"
- if test x\$passthrough = xtrue; then
- pic_options=""
- fi
-__DOLTCOMPILE__EOF__
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-"${args@<:@@@:>@}" $pic_options -DPIC || exit $?
-__DOLTCOMPILE__EOF__
- fi
-
-dnl Write out static compilation code.
-dnl Avoid duplicate compiler output if also building shared objects.
- if test x$enable_static = xyes; then
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-non_pic_object="$obj.o"
-args@<:@$objarg@:>@="$non_pic_object"
-__DOLTCOMPILE__EOF__
- if test x$enable_shared = xyes; then
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-"${args@<:@@@:>@}" >/dev/null 2>&1 || exit $?
-__DOLTCOMPILE__EOF__
- else
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-"${args@<:@@@:>@}" || exit $?
-__DOLTCOMPILE__EOF__
- fi
- fi
-
-dnl Write out the code to write the .lo file.
-dnl The second line of the .lo file must match "^# Generated by .*libtool"
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-{
-echo "# $lo - a libtool object file"
-echo "# Generated by doltcompile, not libtool"
-__DOLTCOMPILE__EOF__
-
- if test x$enable_shared = xyes; then
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-echo "pic_object='.libs/${objbase}.o'"
-__DOLTCOMPILE__EOF__
- else
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-echo pic_object=none
-__DOLTCOMPILE__EOF__
- fi
-
- if test x$enable_static = xyes; then
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-echo "non_pic_object='${objbase}.o'"
-__DOLTCOMPILE__EOF__
- else
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-echo non_pic_object=none
-__DOLTCOMPILE__EOF__
- fi
-
- cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-} > "$lo"
-__DOLTCOMPILE__EOF__
-
-dnl Done writing out doltcompile; substitute it for libtool compilation.
- chmod +x doltcompile
- LTCOMPILE='$(top_builddir)/doltcompile $(COMPILE)'
- LTCXXCOMPILE='$(top_builddir)/doltcompile $(CXXCOMPILE)'
-
-dnl automake ignores LTCOMPILE and LTCXXCOMPILE when it has separate CFLAGS for
-dnl a target, so write out a libtool wrapper to handle that case.
-dnl Note that doltlibtool does not handle inferred tags or option arguments
-dnl without '=', because automake does not use them.
- cat <<__DOLTLIBTOOL__EOF__ > doltlibtool
-#!$DOLT_BASH
-__DOLTLIBTOOL__EOF__
- cat <<'__DOLTLIBTOOL__EOF__' >>doltlibtool
-top_builddir_slash="${0%%doltlibtool}"
-: ${top_builddir_slash:=./}
-args=()
-modeok=false
-tagok=false
-for arg in "$[]@"; do
- case "$arg" in
- --mode=compile) modeok=true ;;
- --tag=CC|--tag=CXX) tagok=true ;;
- --tag=disable-static) tagok=true ;;
- --tag=ASM|--tag=YASM) tagok=true; passthrough=true;;
- --silent|--quiet) ;;
- *) args@<:@${#args[@]}@:>@="$arg" ;;
- esac
-done
-if $modeok && $tagok ; then
- . ${top_builddir_slash}doltcompile "${args@<:@@@:>@}"
-else
- exec ${top_builddir_slash}libtool "$[]@"
-fi
-__DOLTLIBTOOL__EOF__
-
-dnl Done writing out doltlibtool; substitute it for libtool.
- chmod +x doltlibtool
- LIBTOOL='$(top_builddir)/doltlibtool'
-
-DOLT_CLEANFILES="doltlibtool doltcompile"
-AC_SUBST(DOLT_CLEANFILES)
-])
-AC_SUBST(LTCOMPILE)
-AC_SUBST(LTCXXCOMPILE)
-# end dolt
-])
diff --git a/testsuite/module-playground/.gitignore b/testsuite/module-playground/.gitignore
index 6767e0e..db63fe4 100644
--- a/testsuite/module-playground/.gitignore
+++ b/testsuite/module-playground/.gitignore
@@ -4,9 +4,12 @@
!cache/*.ko
*.mod.c
.tmp_versions
+*.mod
+*.a
+*.cmd
+
modules.order
Module.symvers
-
mod-simple-x86_64.c
mod-simple-i386.c
mod-simple-sparc64.c
diff --git a/tools/depmod.c b/tools/depmod.c
index 391afe9..fbbce10 100644
--- a/tools/depmod.c
+++ b/tools/depmod.c
@@ -2402,6 +2402,68 @@ static int output_devname(struct depmod *depmod, FILE *out)
return 0;
}
+static int output_builtin_alias_bin(struct depmod *depmod, FILE *out)
+{
+ int ret = 0, count = 0;
+ struct index_node *idx;
+ struct kmod_list *l, *builtin = NULL;
+
+ idx = index_create();
+
+ if (idx == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = kmod_module_get_builtin(depmod->ctx, &builtin);
+ if (ret < 0) {
+ if (ret == -ENOENT)
+ ret = 0;
+ goto fail;
+ }
+
+ kmod_list_foreach(l, builtin) {
+ struct kmod_list *ll, *info_list = NULL;
+ struct kmod_module *mod = l->data;
+ const char *modname = kmod_module_get_name(mod);
+
+ ret = kmod_module_get_info(mod, &info_list);
+ if (ret < 0)
+ goto fail;
+
+ kmod_list_foreach(ll, info_list) {
+ char alias[PATH_MAX];
+ const char *key = kmod_module_info_get_key(ll);
+ const char *value = kmod_module_info_get_value(ll);
+
+ if (!streq(key, "alias"))
+ continue;
+
+ alias[0] = '\0';
+ if (alias_normalize(value, alias, NULL) < 0) {
+ WRN("Unmatched bracket in %s\n", value);
+ continue;
+ }
+
+ index_insert(idx, alias, modname, 0);
+ }
+
+ kmod_module_info_free_list(info_list);
+
+ index_insert(idx, modname, modname, 0);
+ count++;
+ }
+
+ if (count)
+ index_write(idx, out);
+ index_destroy(idx);
+fail:
+ if (builtin)
+ kmod_module_unref_list(builtin);
+
+ return ret;
+}
+
static int depmod_output(struct depmod *depmod, FILE *out)
{
static const struct depfile {
@@ -2416,6 +2478,7 @@ static int depmod_output(struct depmod *depmod, FILE *out)
{ "modules.symbols", output_symbols },
{ "modules.symbols.bin", output_symbols_bin },
{ "modules.builtin.bin", output_builtin_bin },
+ { "modules.builtin.alias.bin", output_builtin_alias_bin },
{ "modules.devname", output_devname },
{ }
};
diff --git a/tools/modinfo.c b/tools/modinfo.c
index 86ac04b..0231bb0 100644
--- a/tools/modinfo.c
+++ b/tools/modinfo.c
@@ -172,18 +172,33 @@ static int modinfo_do(struct kmod_module *mod)
{
struct kmod_list *l, *list = NULL;
struct param *params = NULL;
- int err;
+ int err, is_builtin;
+ const char *filename = kmod_module_get_path(mod);
+
+ is_builtin = (filename == NULL);
+
+ if (is_builtin) {
+ printf("%-16s%s%c", "name:", kmod_module_get_name(mod), separator);
+ filename = "(builtin)";
+ }
if (field != NULL && streq(field, "filename")) {
- printf("%s%c", kmod_module_get_path(mod), separator);
+ printf("%s%c", filename, separator);
return 0;
} else if (field == NULL) {
printf("%-16s%s%c", "filename:",
- kmod_module_get_path(mod), separator);
+ filename, separator);
}
err = kmod_module_get_info(mod, &list);
if (err < 0) {
+ if (is_builtin && err == -ENOENT) {
+ /*
+ * This is an old kernel that does not have a file
+ * with information about built-in modules.
+ */
+ return 0;
+ }
ERR("could not get modinfo from '%s': %s\n",
kmod_module_get_name(mod), strerror(-err));
return err;
@@ -276,7 +291,7 @@ static int modinfo_path_do(struct kmod_ctx *ctx, const char *path)
static int modinfo_alias_do(struct kmod_ctx *ctx, const char *alias)
{
- struct kmod_list *l, *filtered, *list = NULL;
+ struct kmod_list *l, *list = NULL;
int err = kmod_module_new_from_lookup(ctx, alias, &list);
if (err < 0) {
ERR("Module alias %s not found.\n", alias);
@@ -288,26 +303,14 @@ static int modinfo_alias_do(struct kmod_ctx *ctx, const char *alias)
return -ENOENT;
}
- err = kmod_module_apply_filter(ctx, KMOD_FILTER_BUILTIN, list, &filtered);
- kmod_module_unref_list(list);
- if (err < 0) {
- ERR("Failed to filter list: %m\n");
- return err;
- }
-
- if (filtered == NULL) {
- ERR("Module %s not found.\n", alias);
- return -ENOENT;
- }
-
- kmod_list_foreach(l, filtered) {
+ kmod_list_foreach(l, list) {
struct kmod_module *mod = kmod_module_get_module(l);
int r = modinfo_do(mod);
kmod_module_unref(mod);
if (r < 0)
err = r;
}
- kmod_module_unref_list(filtered);
+ kmod_module_unref_list(list);
return err;
}
diff --git a/tools/modprobe.c b/tools/modprobe.c
index a9e2331..9387537 100644
--- a/tools/modprobe.c
+++ b/tools/modprobe.c
@@ -353,7 +353,9 @@ static int rmmod_do_remove_module(struct kmod_module *mod)
return err;
}
-static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies);
+#define RMMOD_FLAG_DO_DEPENDENCIES 0x1
+#define RMMOD_FLAG_IGNORE_BUILTIN 0x2
+static int rmmod_do_module(struct kmod_module *mod, int flags);
static int rmmod_do_deps_list(struct kmod_list *list, bool stop_on_errors)
{
@@ -361,7 +363,7 @@ static int rmmod_do_deps_list(struct kmod_list *list, bool stop_on_errors)
kmod_list_foreach_reverse(l, list) {
struct kmod_module *m = kmod_module_get_module(l);
- int r = rmmod_do_module(m, false);
+ int r = rmmod_do_module(m, RMMOD_FLAG_IGNORE_BUILTIN);
kmod_module_unref(m);
if (r < 0 && stop_on_errors)
@@ -371,7 +373,7 @@ static int rmmod_do_deps_list(struct kmod_list *list, bool stop_on_errors)
return 0;
}
-static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies)
+static int rmmod_do_module(struct kmod_module *mod, int flags)
{
const char *modname = kmod_module_get_name(mod);
struct kmod_list *pre = NULL, *post = NULL;
@@ -401,15 +403,19 @@ static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies)
}
goto error;
} else if (state == KMOD_MODULE_BUILTIN) {
- LOG("Module %s is builtin.\n", modname);
- err = -ENOENT;
+ if (flags & RMMOD_FLAG_IGNORE_BUILTIN) {
+ err = 0;
+ } else {
+ LOG("Module %s is builtin.\n", modname);
+ err = -ENOENT;
+ }
goto error;
}
}
rmmod_do_deps_list(post, false);
- if (do_dependencies && remove_dependencies) {
+ if ((flags & RMMOD_FLAG_DO_DEPENDENCIES) && remove_dependencies) {
struct kmod_list *deps = kmod_module_get_dependencies(mod);
err = rmmod_do_deps_list(deps, true);
@@ -462,7 +468,7 @@ static int rmmod(struct kmod_ctx *ctx, const char *alias)
kmod_list_foreach(l, list) {
struct kmod_module *mod = kmod_module_get_module(l);
- err = rmmod_do_module(mod, true);
+ err = rmmod_do_module(mod, RMMOD_FLAG_DO_DEPENDENCIES);
kmod_module_unref(mod);
if (err < 0)
break;
diff --git a/tools/remove.c b/tools/remove.c
index 07e2cc0..387ef0e 100644
--- a/tools/remove.c
+++ b/tools/remove.c
@@ -44,7 +44,7 @@ static void help(void)
static int check_module_inuse(struct kmod_module *mod) {
struct kmod_list *holders;
- int state;
+ int state, ret;
state = kmod_module_get_initstate(mod);
@@ -74,12 +74,15 @@ static int check_module_inuse(struct kmod_module *mod) {
return -EBUSY;
}
- if (kmod_module_get_refcnt(mod) != 0) {
+ ret = kmod_module_get_refcnt(mod);
+ if (ret > 0) {
ERR("Module %s is in use\n", kmod_module_get_name(mod));
return -EBUSY;
+ } else if (ret == -ENOENT) {
+ ERR("Module unloading is not supported\n");
}
- return 0;
+ return ret;
}
static int do_remove(int argc, char *argv[])
diff --git a/tools/rmmod.c b/tools/rmmod.c
index bcdea4c..3942e7b 100644
--- a/tools/rmmod.c
+++ b/tools/rmmod.c
@@ -63,7 +63,7 @@ static void help(void)
static int check_module_inuse(struct kmod_module *mod) {
struct kmod_list *holders;
- int state;
+ int state, ret;
state = kmod_module_get_initstate(mod);
@@ -93,12 +93,15 @@ static int check_module_inuse(struct kmod_module *mod) {
return -EBUSY;
}
- if (kmod_module_get_refcnt(mod) != 0) {
+ ret = kmod_module_get_refcnt(mod);
+ if (ret > 0) {
ERR("Module %s is in use\n", kmod_module_get_name(mod));
return -EBUSY;
+ } else if (ret == -ENOENT) {
+ ERR("Module unloading is not supported\n");
}
- return 0;
+ return ret;
}
static int do_rmmod(int argc, char *argv[])