From 63547ab7a60b58be6ac5531b3903582fe1edcf19 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 11:12:23 +0100 Subject: [PATCH 01/13] libkmod: remove unreachable assert() instances In a handful of places, we're using asserts to guard for internal API misuse. At the same time, having asserts() in a library is generally a bad idea, especially since distributions may be building with or without "-DNDEBUG". Based on code analysis, some instances are not reachable so let's remove them. Signed-off-by: Emil Velikov --- libkmod/libkmod-elf.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libkmod/libkmod-elf.c b/libkmod/libkmod-elf.c index 52b04339..2b25818b 100644 --- a/libkmod/libkmod-elf.c +++ b/libkmod/libkmod-elf.c @@ -3,7 +3,6 @@ * Copyright (C) 2011-2013 ProFUSION embedded systems */ -#include #include #include #include @@ -146,8 +145,6 @@ static inline uint64_t elf_get_uint(const struct kmod_elf *elf, uint64_t offset, const uint8_t *p; uint64_t ret = 0; - assert(size <= sizeof(uint64_t)); - p = elf->memory + offset; if (elf->msb) { @@ -174,8 +171,6 @@ static inline int elf_set_uint(const struct kmod_elf *elf, uint64_t offset, uint "size=%" PRIu64 " offset=%" PRIu64 " value=%" PRIu64 " write memory=%p\n", size, offset, value, changed); - assert(size <= sizeof(uint64_t)); - p = changed + offset; if (elf->msb) { for (i = 1; i <= size; i++) { @@ -204,8 +199,6 @@ static inline const void *elf_get_mem(const struct kmod_elf *elf, uint64_t offse static inline uint64_t elf_get_section_header_offset(const struct kmod_elf *elf, uint16_t idx) { - assert(idx != SHN_UNDEF); - assert(idx < elf->header.section.count); if (idx == SHN_UNDEF || idx >= elf->header.section.count) { ELFDBG(elf, "invalid section number: %" PRIu16 ", last=%" PRIu16 "\n", idx, elf->header.section.count); @@ -662,8 +655,6 @@ int kmod_elf_strip(const struct kmod_elf *elf, unsigned int flags, const void ** uint8_t *changed; int err = 0; - assert(flags & (KMOD_INSERT_FORCE_MODVERSION | KMOD_INSERT_FORCE_VERMAGIC)); - changed = memdup(elf->memory, elf->size); if (changed == NULL) return -ENOMEM; From b7339f43660bcfabe2c6acfd939c96994f39fddf Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 11:18:43 +0100 Subject: [PATCH 02/13] libkmod: annotate index_mm_open() as _nonnull_all_ The function already requires that all the pointers are non-null, so add the attribute macro. Thus the compiler will give us a lovely warning when it detects a potential issue. As result we can remove the assert(), which really shouldn't exist in a shared library. Signed-off-by: Emil Velikov --- libkmod/libkmod-index.c | 3 --- libkmod/libkmod-index.h | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libkmod/libkmod-index.c b/libkmod/libkmod-index.c index cd5cf0eb..dce14ae8 100644 --- a/libkmod/libkmod-index.c +++ b/libkmod/libkmod-index.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -752,8 +751,6 @@ int index_mm_open(const struct kmod_ctx *ctx, const char *filename, } hdr; const void *p; - assert(pidx != NULL); - DBG(ctx, "file=%s\n", filename); idx = malloc(sizeof(*idx)); diff --git a/libkmod/libkmod-index.h b/libkmod/libkmod-index.h index 47c50d38..3fd01ecf 100644 --- a/libkmod/libkmod-index.h +++ b/libkmod/libkmod-index.h @@ -26,8 +26,8 @@ void index_values_free(struct index_value *values); /* Implementation using mmap */ struct index_mm; -int index_mm_open(const struct kmod_ctx *ctx, const char *filename, - unsigned long long *stamp, struct index_mm **pidx); +_nonnull_all_ int index_mm_open(const struct kmod_ctx *ctx, const char *filename, + unsigned long long *stamp, struct index_mm **pidx); void index_mm_close(struct index_mm *index); char *index_mm_search(const struct index_mm *idx, const char *key); struct index_value *index_mm_searchwild(const struct index_mm *idx, const char *key); From d5499e3f4c44a4688cd425724a83a3a4336e403f Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 11:39:39 +0100 Subject: [PATCH 03/13] libkmod: remove assert() from public API Handful of public facing functions check if the respective pointers are NULL initialized, while others assert() on it. Remove the latter (which is frowned upon in shared libraries) and return early in that case. Should this change yield any user-facing changes, this means they were already getting random corruption and haven't noticed it yet. Signed-off-by: Emil Velikov --- libkmod/libkmod-module.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 7bf37bba..905cc35b 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -1243,12 +1243,9 @@ KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod, const struct kmod_list *l; const struct kmod_config *config; - if (mod == NULL || pre == NULL || post == NULL) + if (mod == NULL || pre == NULL || *pre != NULL || post == NULL || *post != NULL) return -ENOENT; - assert(*pre == NULL); - assert(*post == NULL); - config = kmod_get_config(mod->ctx); kmod_list_foreach(l, config->softdeps) { @@ -1280,11 +1277,9 @@ KMOD_EXPORT int kmod_module_get_weakdeps(const struct kmod_module *mod, const struct kmod_list *l; const struct kmod_config *config; - if (mod == NULL || weak == NULL) + if (mod == NULL || weak == NULL || *weak != NULL) return -ENOENT; - assert(*weak == NULL); - config = kmod_get_config(mod->ctx); kmod_list_foreach(l, config->weakdeps) { @@ -1858,11 +1853,9 @@ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, int i, count, ret = -ENOMEM; struct kmod_signature_info sig_info = {}; - if (mod == NULL || list == NULL) + if (mod == NULL || list == NULL || *list != NULL) return -ENOENT; - assert(*list == NULL); - /* 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), @@ -2013,11 +2006,9 @@ KMOD_EXPORT int kmod_module_get_versions(const struct kmod_module *mod, struct kmod_modversion *versions; int i, count, ret = 0; - if (mod == NULL || list == NULL) + if (mod == NULL || list == NULL || *list != NULL) return -ENOENT; - assert(*list == NULL); - ret = kmod_module_get_elf(mod, &elf); if (ret) return ret; @@ -2114,11 +2105,9 @@ KMOD_EXPORT int kmod_module_get_symbols(const struct kmod_module *mod, struct kmod_modversion *symbols; int i, count, ret = 0; - if (mod == NULL || list == NULL) + if (mod == NULL || list == NULL || *list != NULL) return -ENOENT; - assert(*list == NULL); - ret = kmod_module_get_elf(mod, &elf); if (ret) return ret; @@ -2220,11 +2209,9 @@ KMOD_EXPORT int kmod_module_get_dependency_symbols(const struct kmod_module *mod struct kmod_modversion *symbols; int i, count, ret = 0; - if (mod == NULL || list == NULL) + if (mod == NULL || list == NULL || *list != NULL) return -ENOENT; - assert(*list == NULL); - ret = kmod_module_get_elf(mod, &elf); if (ret) return ret; From e8cab7ca95f1f29df511d89bdc20e9af7a30321d Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 11:50:52 +0100 Subject: [PATCH 04/13] libkmod: pass the command to module_do_install_commands() The only caller of module_do_install_commands() already knows the command (+ ensures it's non-null). So let's just pass it as argument, drop the duplicate kmod_module_get_install_commands() call and unreachable assert(). Signed-off-by: Emil Velikov --- libkmod/libkmod-module.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 905cc35b..5bc746cb 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -805,17 +805,14 @@ struct probe_insert_cb { void *data; }; -static int module_do_install_commands(struct kmod_module *mod, const char *options, - struct probe_insert_cb *cb) +static int module_do_install_commands(struct kmod_module *mod, const char *command, + const char *options, struct probe_insert_cb *cb) { - const char *command = kmod_module_get_install_commands(mod); char *p; _cleanup_free_ char *cmd; int err; size_t cmdlen, options_len, varlen; - assert(command); - if (options == NULL) options = ""; @@ -1073,7 +1070,7 @@ KMOD_EXPORT int kmod_module_probe_insert_module( print_action(m, true, options ?: ""); if (!(flags & KMOD_PROBE_DRY_RUN)) - err = module_do_install_commands(m, options, &cb); + err = module_do_install_commands(m, cmd, options, &cb); } else { if (print_action != NULL) print_action(m, false, options ?: ""); From bd7c76576558de59bc857f6a8d971c1157f09d5e Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 11:53:00 +0100 Subject: [PATCH 05/13] libkmod: remove unreachable asserts in kmod_module_get_probe_list() The only caller of kmod_module_get_probe_list() already ensures that the respective arguments are not NULL. Thus we can drop the asserts(). Signed-off-by: Emil Velikov --- libkmod/libkmod-module.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 5bc746cb..c0fabe9d 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -978,9 +978,6 @@ static int kmod_module_get_probe_list(struct kmod_module *mod, bool ignorecmd, { int err; - assert(mod != NULL); - assert(list != NULL && *list == NULL); - /* * Make sure we don't get screwed by previous calls to this function */ From afe8f96412d320ac72173ac5ba72bc26a6d5decc Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 11:57:13 +0100 Subject: [PATCH 06/13] libkmod: remove unreachable assert in kmod_module_parse_depline() We cannot reach the assert() even though the current code-paths, do not make that abundantly clear. A follow-up commit can resolve that, but for now we can remove the assert. Signed-off-by: Emil Velikov --- libkmod/libkmod-module.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index c0fabe9d..452d6360 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -3,7 +3,6 @@ * Copyright (C) 2011-2013 ProFUSION embedded systems */ -#include #include #include #include @@ -117,7 +116,7 @@ void kmod_module_parse_depline(struct kmod_module *mod, char *line) if (mod->init.dep) return; - assert(mod->dep == NULL); + mod->init.dep = true; p = strchr(line, ':'); From 9d75362c562bbe49ee203d7f5d24f46e69a8ec46 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 12:40:06 +0100 Subject: [PATCH 07/13] libkmod: remove unreachable assert from kmod_lookup_alias_from_* Effectively we have two callers of the said APIs - kmod_module_new_from_lookup() and kmod_module_new_from_name_lookup(). Both of those ensure the list (pointer) is initialized, so we can drop the unreachable asserts. Signed-off-by: Emil Velikov --- libkmod/libkmod.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/libkmod/libkmod.c b/libkmod/libkmod.c index a62946dc..7b503afa 100644 --- a/libkmod/libkmod.c +++ b/libkmod/libkmod.c @@ -3,7 +3,6 @@ * Copyright (C) 2011-2013 ProFUSION embedded systems */ -#include #include #include #include @@ -359,8 +358,6 @@ static int kmod_lookup_alias_from_alias_bin(struct kmod_ctx *ctx, struct index_file *idx; struct index_value *realnames, *realname; - assert(*list == NULL); - if (ctx->indexes[index_number] != NULL) { DBG(ctx, "use mmapped index '%s' for name=%s\n", index_files[index_number].fn, name); @@ -485,8 +482,6 @@ int kmod_lookup_alias_from_kernel_builtin_file(struct kmod_ctx *ctx, const char int kmod_lookup_alias_from_builtin_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) { - assert(*list == NULL); - if (lookup_builtin_file(ctx, name)) { struct kmod_module *mod; struct kmod_list *node; @@ -530,8 +525,6 @@ int kmod_lookup_alias_from_moddep_file(struct kmod_ctx *ctx, const char *name, char *line; int n = 0; - assert(*list == NULL); - /* * Module names do not contain ':'. Return early if we know it will * not be found. @@ -575,8 +568,6 @@ int kmod_lookup_alias_from_config(struct kmod_ctx *ctx, const char *name, struct kmod_list *l; int err, nmatch = 0; - assert(*list == NULL); - kmod_list_foreach(l, config->aliases) { const char *aliasname = kmod_alias_get_name(l); const char *modname = kmod_alias_get_modname(l); @@ -619,8 +610,6 @@ int kmod_lookup_alias_from_commands(struct kmod_ctx *ctx, const char *name, struct kmod_list *l, *node; int err, nmatch = 0; - assert(*list == NULL); - kmod_list_foreach(l, config->install_commands) { const char *modname = kmod_command_get_modname(l); From d361b5ffaa8a1ba73f7d9d48f9bb813fef1df6ed Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 13:02:12 +0100 Subject: [PATCH 08/13] shared/array: remove unreachable assert Signed-off-by: Emil Velikov --- shared/array.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/shared/array.c b/shared/array.c index 7bedf45b..85f8955e 100644 --- a/shared/array.c +++ b/shared/array.c @@ -3,7 +3,6 @@ * Copyright (C) 2011-2013 ProFUSION embedded systems */ -#include #include #include #include @@ -39,7 +38,6 @@ static void array_trim(struct array *array) void array_init(struct array *array, size_t step) { - assert(step > 0); array->array = NULL; array->count = 0; array->total = 0; From e2a74957ae61d01f7b5b8a93dc3847e2a3a78e3a Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 13:04:01 +0100 Subject: [PATCH 09/13] shared/strbuf: annotate strbuf_pushmem() as _nonnull_all_ Drop the asserts and instead annotate the function as _nonnull_all_ which means we'll get a compiler warning, instead of a runtime crash should a NULL is passed to the function. Signed-off-by: Emil Velikov --- shared/strbuf.c | 3 --- shared/strbuf.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/shared/strbuf.c b/shared/strbuf.c index ef99eb78..4c0afff5 100644 --- a/shared/strbuf.c +++ b/shared/strbuf.c @@ -83,9 +83,6 @@ bool strbuf_pushchar(struct strbuf *buf, char ch) size_t strbuf_pushmem(struct strbuf *buf, const char *src, size_t sz) { - assert(src != NULL); - assert(buf != NULL); - if (sz == 0) return 0; diff --git a/shared/strbuf.h b/shared/strbuf.h index 074699a6..30a90b61 100644 --- a/shared/strbuf.h +++ b/shared/strbuf.h @@ -51,7 +51,7 @@ void strbuf_clear(struct strbuf *buf); const char *strbuf_str(struct strbuf *buf); bool strbuf_pushchar(struct strbuf *buf, char ch); -size_t strbuf_pushmem(struct strbuf *buf, const char *src, size_t sz); +_nonnull_all_ size_t strbuf_pushmem(struct strbuf *buf, const char *src, size_t sz); static inline size_t strbuf_pushchars(struct strbuf *buf, const char *str) { return strbuf_pushmem(buf, str, strlen(str)); From b9137f912dd93de916f50cd24bb1ba5c33e768e0 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 13:06:07 +0100 Subject: [PATCH 10/13] shared/strbuf: remove remaining assert() instances Remove the final assert calls from the library and the respective test. The latter being the only xfail test in the whole project and covering only one of the asserts being removed. In addition, since assert() uses abort() the code coverage of the function is completely thrown away... Which isn't great. We could reintroduce some of these checks (asserts remove here and previous commits) and/or tests, although it should probably be done differently. Having any assert() in a public/shared library is a no-go. Signed-off-by: Emil Velikov --- shared/strbuf.c | 4 ---- testsuite/test-strbuf.c | 15 --------------- 2 files changed, 19 deletions(-) diff --git a/shared/strbuf.c b/shared/strbuf.c index 4c0afff5..75d6c790 100644 --- a/shared/strbuf.c +++ b/shared/strbuf.c @@ -4,7 +4,6 @@ * Copyright (C) 2014 Intel Corporation. All rights reserved. */ -#include #include #include #include @@ -97,19 +96,16 @@ size_t strbuf_pushmem(struct strbuf *buf, const char *src, size_t sz) void strbuf_popchar(struct strbuf *buf) { - assert(buf->used > 0); buf->used--; } void strbuf_popchars(struct strbuf *buf, size_t n) { - assert(buf->used >= n); buf->used -= n; } void strbuf_shrink_to(struct strbuf *buf, size_t sz) { - assert(buf->used >= sz); buf->used = sz; } diff --git a/testsuite/test-strbuf.c b/testsuite/test-strbuf.c index 0be7148f..84730d20 100644 --- a/testsuite/test-strbuf.c +++ b/testsuite/test-strbuf.c @@ -187,19 +187,4 @@ static int test_strbuf_shrink_to(void) } DEFINE_TEST(test_strbuf_shrink_to, .description = "test strbuf_shrink_to"); -static int xfail_strbuf_shrink_to(void) -{ - _cleanup_strbuf_ struct strbuf buf; - - strbuf_init(&buf); - strbuf_pushchar(&buf, '/'); - - /* This should crash on assert */ - strbuf_shrink_to(&buf, 2); - - return 0; -} -DEFINE_TEST(xfail_strbuf_shrink_to, .description = "xfail strbuf_shrink_to", - .expected_fail = true); - TESTSUITE_MAIN(); From 4e2417eb082cc62925513ae4f024ffc29b4b3de7 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 13:13:28 +0100 Subject: [PATCH 11/13] testsuite: remove asserts(), fix create_sysfs_files errorpath Two of the three instances are unreachable, while the last one can be replaced with proper error handling. Signed-off-by: Emil Velikov --- testsuite/init_module.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/testsuite/init_module.c b/testsuite/init_module.c index 8ff26999..07cceeb5 100644 --- a/testsuite/init_module.c +++ b/testsuite/init_module.c @@ -8,7 +8,6 @@ #define HAVE_FINIT_MODULE 1 #endif -#include #include #include #include @@ -111,9 +110,6 @@ static int write_one_line_file(const char *fn, const char *line) FILE *f; int r; - assert(fn); - assert(line); - f = fopen(fn, "we"); if (!f) return -errno; @@ -144,12 +140,15 @@ static int create_sysfs_files(const char *modname) char buf[PATH_MAX]; const char *sysfsmod = "/sys/module/"; int len = strlen(sysfsmod); + int err; memcpy(buf, sysfsmod, len); strcpy(buf + len, modname); len += strlen(modname); - assert(mkdir_p(buf, len, 0755) >= 0); + err = mkdir_p(buf, len, 0755); + if (err != 0) + return err; strcpy(buf + len, "/initstate"); return write_one_line_file(buf, "live\n"); @@ -275,8 +274,11 @@ long init_module(void *mem, unsigned long len, _maybe_unused_ const char *args) } else err = 0; - if (err == 0) - create_sysfs_files(modname); + if (err == 0) { + err = create_sysfs_files(modname); + if (err != 0) + err = -1; + } return err; } From b49c0b4f62b978c576789f632225d301eeb68458 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 12:58:16 +0100 Subject: [PATCH 12/13] Use ISO/C11 static_assert Currently we use the GNU extension _Static_assert, with a fallback for older compilers. At the same time, we require a C11 compiler, which by definition has the ISO static_assert(). Use the C11 one, remove the build-time check and diverging code path. Signed-off-by: Emil Velikov --- meson.build | 1 - shared/macro.h | 10 ++-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/meson.build b/meson.build index 75d309b1..f5d8f724 100644 --- a/meson.build +++ b/meson.build @@ -78,7 +78,6 @@ foreach tuple : _decls cdata.set10('HAVE_DECL_@0@'.format(decl.to_upper()), have) endforeach -cdata.set10('HAVE_STATIC_ASSERT', cc.compiles('_Static_assert(1, "Test");', name : '_Static_assert')) cdata.set10('HAVE_NORETURN', cc.compiles('#include ; _Noreturn int foo(void) { exit(0); }', name : '_Noreturn')) ################################################################################ diff --git a/shared/macro.h b/shared/macro.h index 0ad5fddc..2bc7bb09 100644 --- a/shared/macro.h +++ b/shared/macro.h @@ -4,16 +4,10 @@ */ #pragma once +#include #include -#if HAVE_STATIC_ASSERT -#define assert_cc(expr) _Static_assert((expr), #expr) -#else -#define assert_cc(expr) \ - do { \ - (void)sizeof(char[1 - 2 * !(expr)]); \ - } while (0) -#endif +#define assert_cc(expr) static_assert((expr), #expr) #define check_types_match(expr1, expr2) ((typeof(expr1) *)0 != (typeof(expr2) *)0) From 7f504cb0e32d7bf95fd2d534dd4449d7d11cd318 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Thu, 26 Jun 2025 13:19:21 +0100 Subject: [PATCH 13/13] Remove no-longer needed assert.h includes With (nearly) all assert() instances gone and the static_assert() instance properly pulling assert.h we no longer need these includes. Signed-off-by: Emil Velikov --- shared/util.c | 1 - testsuite/delete_module.c | 1 - testsuite/path.c | 1 - tools/modprobe.c | 1 - 4 files changed, 4 deletions(-) diff --git a/shared/util.c b/shared/util.c index 2ffe5647..18df3b4a 100644 --- a/shared/util.c +++ b/shared/util.c @@ -5,7 +5,6 @@ * Copyright (C) 2013-2014 Intel Corporation. All rights reserved. */ -#include #include #include #include diff --git a/testsuite/delete_module.c b/testsuite/delete_module.c index 023f58a1..8ae2026d 100644 --- a/testsuite/delete_module.c +++ b/testsuite/delete_module.c @@ -3,7 +3,6 @@ * Copyright (C) 2012-2013 ProFUSION embedded systems */ -#include #include #include #include diff --git a/testsuite/path.c b/testsuite/path.c index 3024d50e..04f0ff10 100644 --- a/testsuite/path.c +++ b/testsuite/path.c @@ -8,7 +8,6 @@ #undef _FILE_OFFSET_BITS #undef _TIME_BITS -#include #include #include #include diff --git a/tools/modprobe.c b/tools/modprobe.c index f97b9618..a9dd6eb4 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -5,7 +5,6 @@ * Copyright (C) 2011-2013 ProFUSION embedded systems */ -#include #include #include #include