* [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework @ 2020-12-17 7:27 Viresh Kumar 2020-12-17 7:27 ` [LTP] [PATCH V2 2/3] syscalls: init_module: Add tests Viresh Kumar ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Viresh Kumar @ 2020-12-17 7:27 UTC (permalink / raw) To: ltp The tests using the new test framework must not use the headers from the old one, fix that by declaring the helpers in tst_module.h. To achieve that rename the original routines in tst_module.c with an underscore and use static inline wrappers to call them. Also update the delete_module tests to use the new header. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> --- V2: - New patch. include/old/old_module.h | 27 ++++++++++++--- include/tst_module.h | 33 +++++++++++++++++++ lib/tst_module.c | 8 ++--- .../syscalls/delete_module/delete_module01.c | 6 ++-- .../syscalls/delete_module/delete_module03.c | 12 +++---- 5 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 include/tst_module.h diff --git a/include/old/old_module.h b/include/old/old_module.h index c50efec76244..1af7d1f68027 100644 --- a/include/old/old_module.h +++ b/include/old/old_module.h @@ -34,6 +34,14 @@ #ifndef TST_MODULE #define TST_MODULE +void tst_module_exist_(void (cleanup_fn)(void), const char *mod_name, + char **mod_path); + +void tst_module_load_(void (cleanup_fn)(void), const char *mod_name, + char *const argv[]); + +void tst_module_unload_(void (cleanup_fn)(void), const char *mod_name); + /* * Check module existence. * @@ -44,8 +52,11 @@ * * In case of failure, test'll call cleanup_fn and exit with TCONF return value. */ -void tst_module_exist(void (cleanup_fn)(void), const char *mod_name, - char **mod_path); +static inline void tst_module_exist(void (cleanup_fn)(void), + const char *mod_name, char **mod_path) +{ + tst_module_exist_(cleanup_fn, mod_name, mod_path); +} /* * Load a module using insmod program. @@ -58,8 +69,11 @@ void tst_module_exist(void (cleanup_fn)(void), const char *mod_name, * In case of insmod failure, test will call cleanup_fn and exit with TBROK * return value. */ -void tst_module_load(void (cleanup_fn)(void), - const char *mod_name, char *const argv[]); +static inline void tst_module_load(void (cleanup_fn)(void), + const char *mod_name, char *const argv[]) +{ + tst_module_load_(cleanup_fn, mod_name, argv); +} /* * Unload a module using rmmod program. In case of failure, test will call @@ -67,6 +81,9 @@ void tst_module_load(void (cleanup_fn)(void), * * @mod_name: can be module name or module's file name. */ -void tst_module_unload(void (cleanup_fn)(void), const char *mod_name); +static inline void tst_module_unload(void (cleanup_fn)(void), const char *mod_name) +{ + tst_module_unload_(cleanup_fn, mod_name); +} #endif /* TST_MODULE */ diff --git a/include/tst_module.h b/include/tst_module.h new file mode 100644 index 000000000000..637e85c0bf2f --- /dev/null +++ b/include/tst_module.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved. + * Alexey Kodanev <alexey.kodanev@oracle.com> + */ + +#ifndef TST_MODULE_H +#define TST_MODULE_H + +void tst_module_exist_(void (cleanup_fn)(void), const char *mod_name, + char **mod_path); + +static inline void tst_module_exist(const char *mod_name, char **mod_path) +{ + tst_module_exist_(NULL, mod_name, mod_path); +} + +void tst_module_load_(void (cleanup_fn)(void), const char *mod_name, + char *const argv[]); + +static inline void tst_module_load(const char *mod_name, char *const argv[]) +{ + tst_module_load_(NULL, mod_name, argv); +} + +void tst_module_unload_(void (cleanup_fn)(void), const char *mod_name); + +static inline void tst_module_unload(const char *mod_name) +{ + tst_module_unload_(NULL, mod_name); +} + +#endif /* TST_MODULE_H */ diff --git a/lib/tst_module.c b/lib/tst_module.c index eda61872fe01..9bd443623616 100644 --- a/lib/tst_module.c +++ b/lib/tst_module.c @@ -28,7 +28,7 @@ #include "ltp_priv.h" #include "old_module.h" -void tst_module_exists(void (cleanup_fn)(void), +void tst_module_exists_(void (cleanup_fn)(void), const char *mod_name, char **mod_path) { /* check current working directory */ @@ -77,11 +77,11 @@ void tst_module_exists(void (cleanup_fn)(void), free(buf); } -void tst_module_load(void (cleanup_fn)(void), +void tst_module_load_(void (cleanup_fn)(void), const char *mod_name, char *const argv[]) { char *mod_path = NULL; - tst_module_exists(cleanup_fn, mod_name, &mod_path); + tst_module_exists_(cleanup_fn, mod_name, &mod_path); const int offset = 2; /* command name & module path */ int size = 0; @@ -101,7 +101,7 @@ void tst_module_load(void (cleanup_fn)(void), free(mod_path); } -void tst_module_unload(void (cleanup_fn)(void), const char *mod_name) +void tst_module_unload_(void (cleanup_fn)(void), const char *mod_name) { int i, rc; diff --git a/testcases/kernel/syscalls/delete_module/delete_module01.c b/testcases/kernel/syscalls/delete_module/delete_module01.c index e5cb53cc9ec3..8fb559f0c703 100644 --- a/testcases/kernel/syscalls/delete_module/delete_module01.c +++ b/testcases/kernel/syscalls/delete_module/delete_module01.c @@ -14,9 +14,9 @@ */ #include <errno.h> -#include "old_module.h" #include "lapi/syscalls.h" #include "tst_test.h" +#include "tst_module.h" #define MODULE_NAME "dummy_del_mod" #define MODULE_NAME_KO "dummy_del_mod.ko" @@ -26,7 +26,7 @@ static int module_loaded; static void do_delete_module(void) { if (module_loaded == 0) { - tst_module_load(NULL, MODULE_NAME_KO, NULL); + tst_module_load(MODULE_NAME_KO, NULL); module_loaded = 1; } @@ -44,7 +44,7 @@ static void do_delete_module(void) static void cleanup(void) { if (module_loaded == 1) - tst_module_unload(NULL, MODULE_NAME_KO); + tst_module_unload(MODULE_NAME_KO); } static struct tst_test test = { diff --git a/testcases/kernel/syscalls/delete_module/delete_module03.c b/testcases/kernel/syscalls/delete_module/delete_module03.c index 8bd51be07dc2..7178e8ef13b0 100644 --- a/testcases/kernel/syscalls/delete_module/delete_module03.c +++ b/testcases/kernel/syscalls/delete_module/delete_module03.c @@ -14,7 +14,7 @@ #include <errno.h> #include "tst_test.h" -#include "old_module.h" +#include "tst_module.h" #include "lapi/syscalls.h" #define DUMMY_MOD "dummy_del_mod" @@ -43,7 +43,7 @@ static void do_delete_module(void) * insmod DUMMY_MOD_KO again in case running * with -i option */ - tst_module_load(NULL, DUMMY_MOD_KO, NULL); + tst_module_load(DUMMY_MOD_KO, NULL); dummy_mod_loaded = 1; } } @@ -51,11 +51,11 @@ static void do_delete_module(void) static void setup(void) { /* Load first kernel module */ - tst_module_load(NULL, DUMMY_MOD_KO, NULL); + tst_module_load(DUMMY_MOD_KO, NULL); dummy_mod_loaded = 1; /* Load dependant kernel module */ - tst_module_load(NULL, DUMMY_MOD_DEP_KO, NULL); + tst_module_load(DUMMY_MOD_DEP_KO, NULL); dummy_mod_dep_loaded = 1; } @@ -63,11 +63,11 @@ static void cleanup(void) { /* Unload dependent kernel module */ if (dummy_mod_dep_loaded == 1) - tst_module_unload(NULL, DUMMY_MOD_DEP_KO); + tst_module_unload(DUMMY_MOD_DEP_KO); /* Unload first kernel module */ if (dummy_mod_loaded == 1) - tst_module_unload(NULL, DUMMY_MOD_KO); + tst_module_unload(DUMMY_MOD_KO); } static struct tst_test test = { -- 2.25.0.rc1.19.g042ed3e048af ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [LTP] [PATCH V2 2/3] syscalls: init_module: Add tests 2020-12-17 7:27 [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework Viresh Kumar @ 2020-12-17 7:27 ` Viresh Kumar 2020-12-17 10:03 ` Cyril Hrubis 2020-12-17 7:27 ` [LTP] [PATCH V2 3/3] syscalls: finit_module: " Viresh Kumar 2020-12-17 10:01 ` [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework Cyril Hrubis 2 siblings, 1 reply; 11+ messages in thread From: Viresh Kumar @ 2020-12-17 7:27 UTC (permalink / raw) To: ltp This patch adds success and failure tests for init_module() syscall. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> --- V2: - Remove unwanted header - Use TST_EXP_*() macros - Always provide definition of init_module(). - Rename module. include/lapi/init_module.h | 19 ++++ runtest/syscalls | 3 + .../kernel/syscalls/init_module/.gitignore | 3 + .../kernel/syscalls/init_module/Makefile | 21 ++++ .../kernel/syscalls/init_module/init_module.c | 37 +++++++ .../syscalls/init_module/init_module01.c | 54 ++++++++++ .../syscalls/init_module/init_module02.c | 99 +++++++++++++++++++ 7 files changed, 236 insertions(+) create mode 100644 include/lapi/init_module.h create mode 100644 testcases/kernel/syscalls/init_module/.gitignore create mode 100644 testcases/kernel/syscalls/init_module/Makefile create mode 100644 testcases/kernel/syscalls/init_module/init_module.c create mode 100644 testcases/kernel/syscalls/init_module/init_module01.c create mode 100644 testcases/kernel/syscalls/init_module/init_module02.c diff --git a/include/lapi/init_module.h b/include/lapi/init_module.h new file mode 100644 index 000000000000..65ff70356c60 --- /dev/null +++ b/include/lapi/init_module.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Linaro Limited. All rights reserved. + * Author: Viresh Kumar <viresh.kumar@linaro.org> + */ + +#ifndef INIT_MODULE_H__ +#define INIT_MODULE_H__ + +#include "config.h" +#include "lapi/syscalls.h" +#include "tst_test.h" + +static inline int init_module(void *module_image, unsigned long len, + const char *param_values) +{ + return tst_syscall(__NR_init_module, module_image, len, param_values); +} +#endif /* INIT_MODULE_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 9c328697b4a3..28174dddd716 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -517,6 +517,9 @@ getxattr03 getxattr03 getxattr04 getxattr04 getxattr05 getxattr05 +init_module01 init_module01 +init_module02 init_module02 + #Needs tty device. #ioctl01 ioctl01 -D /dev/tty0 #ioctl02 ioctl02 -D /dev/tty0 diff --git a/testcases/kernel/syscalls/init_module/.gitignore b/testcases/kernel/syscalls/init_module/.gitignore new file mode 100644 index 000000000000..b4d11e958544 --- /dev/null +++ b/testcases/kernel/syscalls/init_module/.gitignore @@ -0,0 +1,3 @@ +/init_module01 +/init_module02 +/*.ko diff --git a/testcases/kernel/syscalls/init_module/Makefile b/testcases/kernel/syscalls/init_module/Makefile new file mode 100644 index 000000000000..ebdca67d401d --- /dev/null +++ b/testcases/kernel/syscalls/init_module/Makefile @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +ifneq ($(KERNELRELEASE),) + +obj-m := init_module.o + +else + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk + +REQ_VERSION_MAJOR := 2 +REQ_VERSION_PATCH := 6 + +MAKE_TARGETS := init_module01 init_module02 init_module.ko + +include $(top_srcdir)/include/mk/module.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk + +endif diff --git a/testcases/kernel/syscalls/init_module/init_module.c b/testcases/kernel/syscalls/init_module/init_module.c new file mode 100644 index 000000000000..78d03b899a7e --- /dev/null +++ b/testcases/kernel/syscalls/init_module/init_module.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + * + * Dummy test module. + * + * The module accepts a single argument named "status" and it fails + * initialization if the status is set to "invalid". + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/proc_fs.h> +#include <linux/kernel.h> + +static char status[20]; +module_param_string(status, status, 20, 0444); + +static int dummy_init(void) +{ + struct proc_dir_entry *proc_dummy; + + if (!strcmp(status, "invalid")) + return -EINVAL; + + proc_dummy = proc_mkdir("dummy", 0); + return 0; +} +module_init(dummy_init); + +static void dummy_exit(void) +{ + remove_proc_entry("dummy", 0); +} +module_exit(dummy_exit); + +MODULE_LICENSE("GPL"); diff --git a/testcases/kernel/syscalls/init_module/init_module01.c b/testcases/kernel/syscalls/init_module/init_module01.c new file mode 100644 index 000000000000..478ccf1c5fdf --- /dev/null +++ b/testcases/kernel/syscalls/init_module/init_module01.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + */ + +/*\ + * [DESCRIPTION] + * + * Basic init_module() tests. + * + * [ALGORITHM] + * + * Inserts a simple module after opening and mmaping the module file. +\*/ + +#include <errno.h> +#include "lapi/init_module.h" +#include "tst_module.h" + +#define MODULE_NAME "init_module.ko" + +static struct stat sb; +static void *buf; + +static void setup(void) +{ + int fd; + + fd = SAFE_OPEN(MODULE_NAME, O_RDONLY|O_CLOEXEC); + SAFE_FSTAT(fd, &sb); + buf = SAFE_MMAP(0, sb.st_size, PROT_READ|PROT_EXEC, MAP_PRIVATE, fd, 0); + SAFE_CLOSE(fd); +} + +static void run(void) +{ + TST_EXP_PASS(init_module(buf, sb.st_size, "status=valid")); + if (!TST_PASS) + return; + + tst_module_unload(MODULE_NAME); +} + +static void cleanup(void) +{ + munmap(buf, sb.st_size); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_root = 1, +}; diff --git a/testcases/kernel/syscalls/init_module/init_module02.c b/testcases/kernel/syscalls/init_module/init_module02.c new file mode 100644 index 000000000000..102242dba98d --- /dev/null +++ b/testcases/kernel/syscalls/init_module/init_module02.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + */ + +/*\ + * [DESCRIPTION] + * + * Basic init_module() failure tests. + * + * [ALGORITHM] + * + * Tests various failure scenarios for init_module(). +\*/ + +#include <linux/capability.h> +#include <errno.h> +#include "lapi/init_module.h" +#include "tst_module.h" +#include "tst_capability.h" + +#define MODULE_NAME "init_module.ko" + +static unsigned long size, zero_size; +static void *buf, *faulty_buf, *null_buf; + +static struct tst_cap cap_req = TST_CAP(TST_CAP_REQ, CAP_SYS_MODULE); +static struct tst_cap cap_drop = TST_CAP(TST_CAP_DROP, CAP_SYS_MODULE); + +static struct tcase { + const char *name; + void **buf; + unsigned long *size; + const char *param; + int cap; + int exp_errno; +} tcases[] = { + {"NULL-buffer", &null_buf, &size, "", 0, EFAULT}, + {"faulty-buffer", &faulty_buf, &size, "", 0, EFAULT}, + {"null-param", &buf, &size, NULL, 0, EFAULT}, + {"zero-size", &buf, &zero_size, "", 0, ENOEXEC}, + {"invalid_param", &buf, &size, "status=invalid", 0, EINVAL}, + {"no-perm", &buf, &size, "", 1, EPERM}, + {"module-exists", &buf, &size, "", 0, EEXIST}, +}; + +static void setup(void) +{ + struct stat sb; + int fd; + + fd = SAFE_OPEN(MODULE_NAME, O_RDONLY|O_CLOEXEC); + SAFE_FSTAT(fd, &sb); + size = sb.st_size; + buf = SAFE_MMAP(0, size, PROT_READ|PROT_EXEC, MAP_PRIVATE, fd, 0); + SAFE_CLOSE(fd); + + faulty_buf = tst_get_bad_addr(NULL); +} + +static void run(unsigned int n) +{ + struct tcase *tc = &tcases[n]; + + if (tc->cap) + tst_cap_action(&cap_drop); + + /* Insert module twice */ + if (tc->exp_errno == EEXIST) { + TST_EXP_PASS(init_module(*tc->buf, *tc->size, tc->param)); + if (!TST_PASS) + goto out; + + TST_EXP_FAIL(init_module(*tc->buf, *tc->size, tc->param), tc->exp_errno); + tst_module_unload(MODULE_NAME); + } else { + TST_EXP_FAIL(init_module(*tc->buf, *tc->size, tc->param), tc->exp_errno); + } + + if (!TST_PASS && !TST_RET) + tst_module_unload(MODULE_NAME); + +out: + if (tc->cap) + tst_cap_action(&cap_req); +} + +static void cleanup(void) +{ + munmap(buf, size); +} + +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .cleanup = cleanup, + .needs_root = 1, +}; -- 2.25.0.rc1.19.g042ed3e048af ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [LTP] [PATCH V2 2/3] syscalls: init_module: Add tests 2020-12-17 7:27 ` [LTP] [PATCH V2 2/3] syscalls: init_module: Add tests Viresh Kumar @ 2020-12-17 10:03 ` Cyril Hrubis 0 siblings, 0 replies; 11+ messages in thread From: Cyril Hrubis @ 2020-12-17 10:03 UTC (permalink / raw) To: ltp Hi! Pushed with two small fixes, thanks. * Added dummy call to tst_module_exists() to the setup()s which causes the test to exit with TCONF if the module wasn't build for example when kernel devel package wasn't installed * Cleaned up a bit the init_module02.c run() function -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 11+ messages in thread
* [LTP] [PATCH V2 3/3] syscalls: finit_module: Add tests 2020-12-17 7:27 [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework Viresh Kumar 2020-12-17 7:27 ` [LTP] [PATCH V2 2/3] syscalls: init_module: Add tests Viresh Kumar @ 2020-12-17 7:27 ` Viresh Kumar 2020-12-17 10:09 ` Cyril Hrubis ` (2 more replies) 2020-12-17 10:01 ` [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework Cyril Hrubis 2 siblings, 3 replies; 11+ messages in thread From: Viresh Kumar @ 2020-12-17 7:27 UTC (permalink / raw) To: ltp This patch adds success and failure tests for finit_module() syscall. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> --- V2: - Remove unwanted header - Use TST_EXP_*() macros - Rename module. include/lapi/init_module.h | 16 ++++ runtest/syscalls | 3 + .../kernel/syscalls/finit_module/.gitignore | 3 + .../kernel/syscalls/finit_module/Makefile | 21 +++++ .../syscalls/finit_module/finit_module.c | 37 ++++++++ .../syscalls/finit_module/finit_module01.c | 49 +++++++++++ .../syscalls/finit_module/finit_module02.c | 84 +++++++++++++++++++ 7 files changed, 213 insertions(+) create mode 100644 testcases/kernel/syscalls/finit_module/.gitignore create mode 100644 testcases/kernel/syscalls/finit_module/Makefile create mode 100644 testcases/kernel/syscalls/finit_module/finit_module.c create mode 100644 testcases/kernel/syscalls/finit_module/finit_module01.c create mode 100644 testcases/kernel/syscalls/finit_module/finit_module02.c diff --git a/include/lapi/init_module.h b/include/lapi/init_module.h index 65ff70356c60..9e79e11b8557 100644 --- a/include/lapi/init_module.h +++ b/include/lapi/init_module.h @@ -16,4 +16,20 @@ static inline int init_module(void *module_image, unsigned long len, { return tst_syscall(__NR_init_module, module_image, len, param_values); } + +static inline int finit_module(int fd, const char *param_values, int flags) +{ + return tst_syscall(__NR_finit_module, fd, param_values, flags); +} + +void finit_module_supported_by_kernel(void) +{ + if ((tst_kvercmp(3, 8, 0)) < 0) { + /* Check if the syscall is backported on an older kernel */ + TEST(syscall(__NR_finit_module, 0, "", 0)); + if (TST_RET == -1 && TST_ERR == ENOSYS) + tst_brk(TCONF, "Test not supported on kernel version < v3.8"); + } +} + #endif /* INIT_MODULE_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 28174dddd716..961545e73834 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -327,6 +327,9 @@ fgetxattr01 fgetxattr01 fgetxattr02 fgetxattr02 fgetxattr03 fgetxattr03 +finit_module01 finit_module01 +finit_module02 finit_module02 + flistxattr01 flistxattr01 flistxattr02 flistxattr02 flistxattr03 flistxattr03 diff --git a/testcases/kernel/syscalls/finit_module/.gitignore b/testcases/kernel/syscalls/finit_module/.gitignore new file mode 100644 index 000000000000..5fcafdb3736d --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/.gitignore @@ -0,0 +1,3 @@ +/finit_module01 +/finit_module02 +/*.ko diff --git a/testcases/kernel/syscalls/finit_module/Makefile b/testcases/kernel/syscalls/finit_module/Makefile new file mode 100644 index 000000000000..a529695d23cc --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/Makefile @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +ifneq ($(KERNELRELEASE),) + +obj-m := finit_module.o + +else + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk + +REQ_VERSION_MAJOR := 3 +REQ_VERSION_PATCH := 8 + +MAKE_TARGETS := finit_module01 finit_module02 finit_module.ko + +include $(top_srcdir)/include/mk/module.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk + +endif diff --git a/testcases/kernel/syscalls/finit_module/finit_module.c b/testcases/kernel/syscalls/finit_module/finit_module.c new file mode 100644 index 000000000000..78d03b899a7e --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + * + * Dummy test module. + * + * The module accepts a single argument named "status" and it fails + * initialization if the status is set to "invalid". + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/proc_fs.h> +#include <linux/kernel.h> + +static char status[20]; +module_param_string(status, status, 20, 0444); + +static int dummy_init(void) +{ + struct proc_dir_entry *proc_dummy; + + if (!strcmp(status, "invalid")) + return -EINVAL; + + proc_dummy = proc_mkdir("dummy", 0); + return 0; +} +module_init(dummy_init); + +static void dummy_exit(void) +{ + remove_proc_entry("dummy", 0); +} +module_exit(dummy_exit); + +MODULE_LICENSE("GPL"); diff --git a/testcases/kernel/syscalls/finit_module/finit_module01.c b/testcases/kernel/syscalls/finit_module/finit_module01.c new file mode 100644 index 000000000000..c31c0c2dce4c --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module01.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + */ + +/*\ + * [DESCRIPTION] + * + * Basic finit_module() tests. + * + * [ALGORITHM] + * + * Inserts a simple module after opening and mmaping the module file. +\*/ + +#include <errno.h> +#include "lapi/init_module.h" +#include "tst_module.h" + +#define MODULE_NAME "finit_module.ko" + +int fd; + +static void setup(void) +{ + finit_module_supported_by_kernel(); + fd = SAFE_OPEN(MODULE_NAME, O_RDONLY|O_CLOEXEC); +} + +static void run(void) +{ + TST_EXP_PASS(finit_module(fd, "status=valid", 0)); + if (!TST_PASS) + return; + + tst_module_unload(MODULE_NAME); +} + +static void cleanup(void) +{ + SAFE_CLOSE(fd); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_root = 1, +}; diff --git a/testcases/kernel/syscalls/finit_module/finit_module02.c b/testcases/kernel/syscalls/finit_module/finit_module02.c new file mode 100644 index 000000000000..220c83fd4d1c --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module02.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + */ + +/*\ + * [DESCRIPTION] + * + * Basic finit_module() failure tests. + * + * [ALGORITHM] + * + * Tests various failure scenarios for finit_module(). +\*/ + +#include <linux/capability.h> +#include <errno.h> +#include "lapi/init_module.h" +#include "tst_module.h" +#include "tst_capability.h" + +#define MODULE_NAME "finit_module.ko" + +static int fd, fd_zero, fd_invalid = -1; + +static struct tst_cap cap_req = TST_CAP(TST_CAP_REQ, CAP_SYS_MODULE); +static struct tst_cap cap_drop = TST_CAP(TST_CAP_DROP, CAP_SYS_MODULE); + +static struct tcase { + const char *name; + int *fd; + const char *param; + int open_flags; + int flags; + int cap; + int exp_errno; +} tcases[] = { + {"zero-fd", &fd_zero, "", O_RDONLY | O_CLOEXEC, 0, 0, EINVAL}, + {"invalid-fd", &fd_invalid, "", O_RDONLY | O_CLOEXEC, 0, 0, ENOEXEC}, + {"null-param", &fd, NULL, O_RDONLY | O_CLOEXEC, 0, 0, EFAULT}, + {"invalid-param", &fd, "status=invalid", O_RDONLY | O_CLOEXEC, 0, 0, EINVAL}, + {"invalid-flags", &fd, "", O_RDONLY | O_CLOEXEC, -1, 0, EINVAL}, + {"no-perm", &fd, "", O_RDONLY | O_CLOEXEC, 0, 1, EPERM}, + {"module-exists", &fd, "", O_RDONLY | O_CLOEXEC, 0, 0, EEXIST}, + {"file-not-readable", &fd, "", O_WRONLY | O_CLOEXEC, 0, 0, EBADF}, +}; + +static void run(unsigned int n) +{ + struct tcase *tc = &tcases[n]; + + fd = SAFE_OPEN(MODULE_NAME, tc->open_flags); + + if (tc->cap) + tst_cap_action(&cap_drop); + + /* Insert module twice */ + if (tc->exp_errno == EEXIST) { + TST_EXP_PASS(finit_module(*tc->fd, tc->param, tc->flags)); + if (!TST_PASS) + goto out; + + TST_EXP_FAIL(finit_module(*tc->fd, tc->param, tc->flags), tc->exp_errno); + tst_module_unload(MODULE_NAME); + } else { + TST_EXP_FAIL(finit_module(*tc->fd, tc->param, tc->flags), tc->exp_errno); + } + + if (!TST_PASS && !TST_RET) + tst_module_unload(MODULE_NAME); + +out: + if (tc->cap) + tst_cap_action(&cap_req); + + SAFE_CLOSE(fd); +} + +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), + .setup = finit_module_supported_by_kernel, + .needs_root = 1, +}; -- 2.25.0.rc1.19.g042ed3e048af ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [LTP] [PATCH V2 3/3] syscalls: finit_module: Add tests 2020-12-17 7:27 ` [LTP] [PATCH V2 3/3] syscalls: finit_module: " Viresh Kumar @ 2020-12-17 10:09 ` Cyril Hrubis 2020-12-17 10:24 ` Viresh Kumar 2020-12-17 10:29 ` [LTP] [PATCH V3 " Viresh Kumar 2020-12-18 6:55 ` [LTP] [PATCH V4 " Viresh Kumar 2 siblings, 1 reply; 11+ messages in thread From: Cyril Hrubis @ 2020-12-17 10:09 UTC (permalink / raw) To: ltp Hi! This finit_module02 fails for me: tst_test.c:1261: TINFO: Timeout per run is 0h 05m 00s finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EINVAL (22) finit_module02.c:66: TFAIL: finit_module(*tc->fd, tc->param, tc->flags) expected ENOEXEC: EBADF (9) finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EFAULT (14) finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EINVAL (22) finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EINVAL (22) tst_capability.c:29: TINFO: Dropping CAP_SYS_MODULE(16) finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EPERM (1) tst_capability.c:41: TINFO: Permitting CAP_SYS_MODULE(16) finit_module02.c:59: TPASS: finit_module(*tc->fd, tc->param, tc->flags) passed finit_module02.c:63: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EEXIST (17) finit_module02.c:66: TFAIL: finit_module(*tc->fd, tc->param, tc->flags) expected EBADF: ETXTBSY (26) Linux 5.9.12 Also it looks to me like EBADF is more reasonable error for fd set to -1 also ETXTBSY sounds more reasonable for a file opened for writing. I guess that someone cleaned up the kernel implementation but forget to update the manual pages? -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 11+ messages in thread
* [LTP] [PATCH V2 3/3] syscalls: finit_module: Add tests 2020-12-17 10:09 ` Cyril Hrubis @ 2020-12-17 10:24 ` Viresh Kumar 0 siblings, 0 replies; 11+ messages in thread From: Viresh Kumar @ 2020-12-17 10:24 UTC (permalink / raw) To: ltp On 17-12-20, 11:09, Cyril Hrubis wrote: > Hi! > This finit_module02 fails for me: > > tst_test.c:1261: TINFO: Timeout per run is 0h 05m 00s > finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EINVAL (22) > finit_module02.c:66: TFAIL: finit_module(*tc->fd, tc->param, tc->flags) expected ENOEXEC: EBADF (9) > finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EFAULT (14) > finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EINVAL (22) > finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EINVAL (22) > tst_capability.c:29: TINFO: Dropping CAP_SYS_MODULE(16) > finit_module02.c:66: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EPERM (1) > tst_capability.c:41: TINFO: Permitting CAP_SYS_MODULE(16) > finit_module02.c:59: TPASS: finit_module(*tc->fd, tc->param, tc->flags) passed > finit_module02.c:63: TPASS: finit_module(*tc->fd, tc->param, tc->flags): EEXIST (17) > finit_module02.c:66: TFAIL: finit_module(*tc->fd, tc->param, tc->flags) expected EBADF: ETXTBSY (26) > > Linux 5.9.12 > > Also it looks to me like EBADF is more reasonable error for fd set to -1 > also ETXTBSY sounds more reasonable for a file opened for writing. > > I guess that someone cleaned up the kernel implementation but forget to > update the manual pages? Merged in v4.6 and I am on 4.4 :( commit a1db74209483a24c861c848b4bb79a4d945ef6fa Author: Mimi Zohar <zohar@linux.vnet.ibm.com> Date: Wed Dec 30 07:35:30 2015 -0500 module: replace copy_module_from_fd with kernel version Replace copy_module_from_fd() with kernel_read_file_from_fd(). Although none of the upstreamed LSMs define a kernel_module_from_file hook, IMA is called, based on policy, to prevent unsigned kernel modules from being loaded by the original kernel module syscall and to measure/appraise signed kernel modules. The security function security_kernel_module_from_file() was called prior to reading a kernel module. Preventing unsigned kernel modules from being loaded by the original kernel module syscall remains on the pre-read kernel_read_file() security hook. Instead of reading the kernel module twice, once for measuring/appraising and again for loading the kernel module, the signature validation is moved to the kernel_post_read_file() security hook. This patch removes the security_kernel_module_from_file() hook and security call. Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Acked-by: Kees Cook <keescook@chromium.org> Acked-by: Luis R. Rodriguez <mcgrof@kernel.org> Cc: Rusty Russell <rusty@rustcorp.com.au> -- viresh ^ permalink raw reply [flat|nested] 11+ messages in thread
* [LTP] [PATCH V3 3/3] syscalls: finit_module: Add tests 2020-12-17 7:27 ` [LTP] [PATCH V2 3/3] syscalls: finit_module: " Viresh Kumar 2020-12-17 10:09 ` Cyril Hrubis @ 2020-12-17 10:29 ` Viresh Kumar 2020-12-17 12:02 ` Cyril Hrubis 2020-12-18 6:55 ` [LTP] [PATCH V4 " Viresh Kumar 2 siblings, 1 reply; 11+ messages in thread From: Viresh Kumar @ 2020-12-17 10:29 UTC (permalink / raw) To: ltp This patch adds success and failure tests for finit_module() syscall. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> --- include/lapi/init_module.h | 16 ++++ runtest/syscalls | 3 + .../kernel/syscalls/finit_module/.gitignore | 3 + .../kernel/syscalls/finit_module/Makefile | 21 +++++ .../syscalls/finit_module/finit_module.c | 37 ++++++++ .../syscalls/finit_module/finit_module01.c | 49 ++++++++++ .../syscalls/finit_module/finit_module02.c | 89 +++++++++++++++++++ 7 files changed, 218 insertions(+) create mode 100644 testcases/kernel/syscalls/finit_module/.gitignore create mode 100644 testcases/kernel/syscalls/finit_module/Makefile create mode 100644 testcases/kernel/syscalls/finit_module/finit_module.c create mode 100644 testcases/kernel/syscalls/finit_module/finit_module01.c create mode 100644 testcases/kernel/syscalls/finit_module/finit_module02.c diff --git a/include/lapi/init_module.h b/include/lapi/init_module.h index 65ff70356c60..9e79e11b8557 100644 --- a/include/lapi/init_module.h +++ b/include/lapi/init_module.h @@ -16,4 +16,20 @@ static inline int init_module(void *module_image, unsigned long len, { return tst_syscall(__NR_init_module, module_image, len, param_values); } + +static inline int finit_module(int fd, const char *param_values, int flags) +{ + return tst_syscall(__NR_finit_module, fd, param_values, flags); +} + +void finit_module_supported_by_kernel(void) +{ + if ((tst_kvercmp(3, 8, 0)) < 0) { + /* Check if the syscall is backported on an older kernel */ + TEST(syscall(__NR_finit_module, 0, "", 0)); + if (TST_RET == -1 && TST_ERR == ENOSYS) + tst_brk(TCONF, "Test not supported on kernel version < v3.8"); + } +} + #endif /* INIT_MODULE_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 28174dddd716..961545e73834 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -327,6 +327,9 @@ fgetxattr01 fgetxattr01 fgetxattr02 fgetxattr02 fgetxattr03 fgetxattr03 +finit_module01 finit_module01 +finit_module02 finit_module02 + flistxattr01 flistxattr01 flistxattr02 flistxattr02 flistxattr03 flistxattr03 diff --git a/testcases/kernel/syscalls/finit_module/.gitignore b/testcases/kernel/syscalls/finit_module/.gitignore new file mode 100644 index 000000000000..5fcafdb3736d --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/.gitignore @@ -0,0 +1,3 @@ +/finit_module01 +/finit_module02 +/*.ko diff --git a/testcases/kernel/syscalls/finit_module/Makefile b/testcases/kernel/syscalls/finit_module/Makefile new file mode 100644 index 000000000000..a529695d23cc --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/Makefile @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +ifneq ($(KERNELRELEASE),) + +obj-m := finit_module.o + +else + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk + +REQ_VERSION_MAJOR := 3 +REQ_VERSION_PATCH := 8 + +MAKE_TARGETS := finit_module01 finit_module02 finit_module.ko + +include $(top_srcdir)/include/mk/module.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk + +endif diff --git a/testcases/kernel/syscalls/finit_module/finit_module.c b/testcases/kernel/syscalls/finit_module/finit_module.c new file mode 100644 index 000000000000..78d03b899a7e --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + * + * Dummy test module. + * + * The module accepts a single argument named "status" and it fails + * initialization if the status is set to "invalid". + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/proc_fs.h> +#include <linux/kernel.h> + +static char status[20]; +module_param_string(status, status, 20, 0444); + +static int dummy_init(void) +{ + struct proc_dir_entry *proc_dummy; + + if (!strcmp(status, "invalid")) + return -EINVAL; + + proc_dummy = proc_mkdir("dummy", 0); + return 0; +} +module_init(dummy_init); + +static void dummy_exit(void) +{ + remove_proc_entry("dummy", 0); +} +module_exit(dummy_exit); + +MODULE_LICENSE("GPL"); diff --git a/testcases/kernel/syscalls/finit_module/finit_module01.c b/testcases/kernel/syscalls/finit_module/finit_module01.c new file mode 100644 index 000000000000..c31c0c2dce4c --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module01.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + */ + +/*\ + * [DESCRIPTION] + * + * Basic finit_module() tests. + * + * [ALGORITHM] + * + * Inserts a simple module after opening and mmaping the module file. +\*/ + +#include <errno.h> +#include "lapi/init_module.h" +#include "tst_module.h" + +#define MODULE_NAME "finit_module.ko" + +int fd; + +static void setup(void) +{ + finit_module_supported_by_kernel(); + fd = SAFE_OPEN(MODULE_NAME, O_RDONLY|O_CLOEXEC); +} + +static void run(void) +{ + TST_EXP_PASS(finit_module(fd, "status=valid", 0)); + if (!TST_PASS) + return; + + tst_module_unload(MODULE_NAME); +} + +static void cleanup(void) +{ + SAFE_CLOSE(fd); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_root = 1, +}; diff --git a/testcases/kernel/syscalls/finit_module/finit_module02.c b/testcases/kernel/syscalls/finit_module/finit_module02.c new file mode 100644 index 000000000000..088b15055221 --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module02.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + */ + +/*\ + * [DESCRIPTION] + * + * Basic finit_module() failure tests. + * + * [ALGORITHM] + * + * Tests various failure scenarios for finit_module(). +\*/ + +#include <linux/capability.h> +#include <errno.h> +#include "lapi/init_module.h" +#include "tst_module.h" +#include "tst_capability.h" + +#define MODULE_NAME "finit_module.ko" + +static int fd, fd_zero, fd_invalid = -1; + +static struct tst_cap cap_req = TST_CAP(TST_CAP_REQ, CAP_SYS_MODULE); +static struct tst_cap cap_drop = TST_CAP(TST_CAP_DROP, CAP_SYS_MODULE); + +static struct tcase { + const char *name; + int *fd; + const char *param; + int open_flags; + int flags; + int cap; + int exp_errno; +} tcases[] = { + {"invalid-fd", &fd_invalid, "", O_RDONLY | O_CLOEXEC, 0, 0, EBADF}, /* Keep this at index 0 */ + {"zero-fd", &fd_zero, "", O_RDONLY | O_CLOEXEC, 0, 0, EINVAL}, + {"null-param", &fd, NULL, O_RDONLY | O_CLOEXEC, 0, 0, EFAULT}, + {"invalid-param", &fd, "status=invalid", O_RDONLY | O_CLOEXEC, 0, 0, EINVAL}, + {"invalid-flags", &fd, "", O_RDONLY | O_CLOEXEC, -1, 0, EINVAL}, + {"no-perm", &fd, "", O_RDONLY | O_CLOEXEC, 0, 1, EPERM}, + {"module-exists", &fd, "", O_RDONLY | O_CLOEXEC, 0, 0, EEXIST}, + {"file-not-readable", &fd, "", O_WRONLY | O_CLOEXEC, 0, 0, EBADF}, +}; + +static void setup(void) +{ + finit_module_supported_by_kernel(); + + /* Kernel returned ENOEXEC for fd = -1 earlier */ + if ((tst_kvercmp(4, 6, 0)) < 0) + tcases[0].exp_errno = ENOEXEC; +} + +static void run(unsigned int n) +{ + struct tcase *tc = &tcases[n]; + + fd = SAFE_OPEN(MODULE_NAME, tc->open_flags); + + if (tc->cap) + tst_cap_action(&cap_drop); + + /* Insert module twice */ + if (tc->exp_errno == EEXIST) + tst_module_load(MODULE_NAME, NULL); + + TST_EXP_FAIL(finit_module(*tc->fd, tc->param, tc->flags), tc->exp_errno); + + if (tc->exp_errno == EEXIST) + tst_module_unload(MODULE_NAME); + + if (!TST_PASS && !TST_RET) + tst_module_unload(MODULE_NAME); + + if (tc->cap) + tst_cap_action(&cap_req); + + SAFE_CLOSE(fd); +} + +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .needs_root = 1, +}; -- 2.25.0.rc1.19.g042ed3e048af ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [LTP] [PATCH V3 3/3] syscalls: finit_module: Add tests 2020-12-17 10:29 ` [LTP] [PATCH V3 " Viresh Kumar @ 2020-12-17 12:02 ` Cyril Hrubis 0 siblings, 0 replies; 11+ messages in thread From: Cyril Hrubis @ 2020-12-17 12:02 UTC (permalink / raw) To: ltp Hi! > +static void setup(void) > +{ > + finit_module_supported_by_kernel(); > + > + /* Kernel returned ENOEXEC for fd = -1 earlier */ > + if ((tst_kvercmp(4, 6, 0)) < 0) > + tcases[0].exp_errno = ENOEXEC; There are plenty of ways how to avoid hackery like that. What about we defined a setup function in the test structure and then loop over the testcases in the test setup() and execute all per-test setup functions we have. The we can keep the errno set to zero in the static structure and initialize it in the per-testcase setup as: static void bad_fd_setup(struct tcase *tc) { if (tst_kvercmp(4, 6, 0)) < 0) tc->errno = ENOEXEC; else tc->errno = EBADFD; } Also I think that the last test needs to handle ETXTBSY in the same way and we may possibly add more tests since I guess that most of the errors that apply to execve() would apply here as well. What happpens for example if we pass a fd that points to a directory? -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 11+ messages in thread
* [LTP] [PATCH V4 3/3] syscalls: finit_module: Add tests 2020-12-17 7:27 ` [LTP] [PATCH V2 3/3] syscalls: finit_module: " Viresh Kumar 2020-12-17 10:09 ` Cyril Hrubis 2020-12-17 10:29 ` [LTP] [PATCH V3 " Viresh Kumar @ 2020-12-18 6:55 ` Viresh Kumar 2021-01-06 10:00 ` Cyril Hrubis 2 siblings, 1 reply; 11+ messages in thread From: Viresh Kumar @ 2020-12-18 6:55 UTC (permalink / raw) To: ltp This patch adds success and failure tests for finit_module() syscall. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> --- V4: - Add fix_errno() callback in tcase in finit_module02.c and use it for 3 of the tests. - Add test where fd is a directory. include/lapi/init_module.h | 16 +++ runtest/syscalls | 3 + .../kernel/syscalls/finit_module/.gitignore | 3 + .../kernel/syscalls/finit_module/Makefile | 21 +++ .../syscalls/finit_module/finit_module.c | 37 +++++ .../syscalls/finit_module/finit_module01.c | 49 +++++++ .../syscalls/finit_module/finit_module02.c | 131 ++++++++++++++++++ 7 files changed, 260 insertions(+) create mode 100644 testcases/kernel/syscalls/finit_module/.gitignore create mode 100644 testcases/kernel/syscalls/finit_module/Makefile create mode 100644 testcases/kernel/syscalls/finit_module/finit_module.c create mode 100644 testcases/kernel/syscalls/finit_module/finit_module01.c create mode 100644 testcases/kernel/syscalls/finit_module/finit_module02.c diff --git a/include/lapi/init_module.h b/include/lapi/init_module.h index 65ff70356c60..9e79e11b8557 100644 --- a/include/lapi/init_module.h +++ b/include/lapi/init_module.h @@ -16,4 +16,20 @@ static inline int init_module(void *module_image, unsigned long len, { return tst_syscall(__NR_init_module, module_image, len, param_values); } + +static inline int finit_module(int fd, const char *param_values, int flags) +{ + return tst_syscall(__NR_finit_module, fd, param_values, flags); +} + +void finit_module_supported_by_kernel(void) +{ + if ((tst_kvercmp(3, 8, 0)) < 0) { + /* Check if the syscall is backported on an older kernel */ + TEST(syscall(__NR_finit_module, 0, "", 0)); + if (TST_RET == -1 && TST_ERR == ENOSYS) + tst_brk(TCONF, "Test not supported on kernel version < v3.8"); + } +} + #endif /* INIT_MODULE_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 28174dddd716..961545e73834 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -327,6 +327,9 @@ fgetxattr01 fgetxattr01 fgetxattr02 fgetxattr02 fgetxattr03 fgetxattr03 +finit_module01 finit_module01 +finit_module02 finit_module02 + flistxattr01 flistxattr01 flistxattr02 flistxattr02 flistxattr03 flistxattr03 diff --git a/testcases/kernel/syscalls/finit_module/.gitignore b/testcases/kernel/syscalls/finit_module/.gitignore new file mode 100644 index 000000000000..5fcafdb3736d --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/.gitignore @@ -0,0 +1,3 @@ +/finit_module01 +/finit_module02 +/*.ko diff --git a/testcases/kernel/syscalls/finit_module/Makefile b/testcases/kernel/syscalls/finit_module/Makefile new file mode 100644 index 000000000000..a529695d23cc --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/Makefile @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +ifneq ($(KERNELRELEASE),) + +obj-m := finit_module.o + +else + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk + +REQ_VERSION_MAJOR := 3 +REQ_VERSION_PATCH := 8 + +MAKE_TARGETS := finit_module01 finit_module02 finit_module.ko + +include $(top_srcdir)/include/mk/module.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk + +endif diff --git a/testcases/kernel/syscalls/finit_module/finit_module.c b/testcases/kernel/syscalls/finit_module/finit_module.c new file mode 100644 index 000000000000..78d03b899a7e --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + * + * Dummy test module. + * + * The module accepts a single argument named "status" and it fails + * initialization if the status is set to "invalid". + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/proc_fs.h> +#include <linux/kernel.h> + +static char status[20]; +module_param_string(status, status, 20, 0444); + +static int dummy_init(void) +{ + struct proc_dir_entry *proc_dummy; + + if (!strcmp(status, "invalid")) + return -EINVAL; + + proc_dummy = proc_mkdir("dummy", 0); + return 0; +} +module_init(dummy_init); + +static void dummy_exit(void) +{ + remove_proc_entry("dummy", 0); +} +module_exit(dummy_exit); + +MODULE_LICENSE("GPL"); diff --git a/testcases/kernel/syscalls/finit_module/finit_module01.c b/testcases/kernel/syscalls/finit_module/finit_module01.c new file mode 100644 index 000000000000..c31c0c2dce4c --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module01.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + */ + +/*\ + * [DESCRIPTION] + * + * Basic finit_module() tests. + * + * [ALGORITHM] + * + * Inserts a simple module after opening and mmaping the module file. +\*/ + +#include <errno.h> +#include "lapi/init_module.h" +#include "tst_module.h" + +#define MODULE_NAME "finit_module.ko" + +int fd; + +static void setup(void) +{ + finit_module_supported_by_kernel(); + fd = SAFE_OPEN(MODULE_NAME, O_RDONLY|O_CLOEXEC); +} + +static void run(void) +{ + TST_EXP_PASS(finit_module(fd, "status=valid", 0)); + if (!TST_PASS) + return; + + tst_module_unload(MODULE_NAME); +} + +static void cleanup(void) +{ + SAFE_CLOSE(fd); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_root = 1, +}; diff --git a/testcases/kernel/syscalls/finit_module/finit_module02.c b/testcases/kernel/syscalls/finit_module/finit_module02.c new file mode 100644 index 000000000000..109de94821da --- /dev/null +++ b/testcases/kernel/syscalls/finit_module/finit_module02.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> + */ + +/*\ + * [DESCRIPTION] + * + * Basic finit_module() failure tests. + * + * [ALGORITHM] + * + * Tests various failure scenarios for finit_module(). +\*/ + +#include <linux/capability.h> +#include <errno.h> +#include "lapi/init_module.h" +#include "tst_module.h" +#include "tst_capability.h" + +#define MODULE_NAME "finit_module.ko" +#define TEST_DIR "test_dir" + +static int fd, fd_zero, fd_invalid = -1, fd_dir; + +static struct tst_cap cap_req = TST_CAP(TST_CAP_REQ, CAP_SYS_MODULE); +static struct tst_cap cap_drop = TST_CAP(TST_CAP_DROP, CAP_SYS_MODULE); + +struct tcase { + const char *name; + int *fd; + const char *param; + int open_flags; + int flags; + int cap; + int exp_errno; + void (*fix_errno)(struct tcase *tc); +}; + +static void bad_fd_setup(struct tcase *tc) +{ + if (tst_kvercmp(4, 6, 0) < 0) + tc->exp_errno = ENOEXEC; + else + tc->exp_errno = EBADF; +} + +static void wo_file_setup(struct tcase *tc) +{ + if (tst_kvercmp(4, 6, 0) < 0) + tc->exp_errno = EBADF; + else + tc->exp_errno = ETXTBSY; +} + +static void dir_setup(struct tcase *tc) +{ + if (tst_kvercmp(4, 6, 0) < 0) + tc->exp_errno = EISDIR; + else + tc->exp_errno = EINVAL; +} + +static struct tcase tcases[] = { + {"invalid-fd", &fd_invalid, "", O_RDONLY | O_CLOEXEC, 0, 0, 0, bad_fd_setup}, + {"zero-fd", &fd_zero, "", O_RDONLY | O_CLOEXEC, 0, 0, EINVAL, NULL}, + {"null-param", &fd, NULL, O_RDONLY | O_CLOEXEC, 0, 0, EFAULT, NULL}, + {"invalid-param", &fd, "status=invalid", O_RDONLY | O_CLOEXEC, 0, 0, EINVAL, NULL}, + {"invalid-flags", &fd, "", O_RDONLY | O_CLOEXEC, -1, 0, EINVAL, NULL}, + {"no-perm", &fd, "", O_RDONLY | O_CLOEXEC, 0, 1, EPERM, NULL}, + {"module-exists", &fd, "", O_RDONLY | O_CLOEXEC, 0, 0, EEXIST, NULL}, + {"file-not-readable", &fd, "", O_WRONLY | O_CLOEXEC, 0, 0, 0, wo_file_setup}, + {"directory", &fd_dir, "", O_RDONLY | O_CLOEXEC, 0, 0, 0, dir_setup}, +}; + +static void setup(void) +{ + unsigned long int i; + + finit_module_supported_by_kernel(); + SAFE_MKDIR(TEST_DIR, 0700); + fd_dir = SAFE_OPEN(TEST_DIR, O_DIRECTORY); + + for (i = 0; i < ARRAY_SIZE(tcases); i++) { + if (tcases[i].fix_errno) + tcases[i].fix_errno(&tcases[i]); + } +} + +static void cleanup(void) +{ + SAFE_CLOSE(fd_dir); + SAFE_RMDIR(TEST_DIR); +} + +static void run(unsigned int n) +{ + struct tcase *tc = &tcases[n]; + + fd = SAFE_OPEN(MODULE_NAME, tc->open_flags); + + if (tc->cap) + tst_cap_action(&cap_drop); + + /* Insert module twice */ + if (tc->exp_errno == EEXIST) + tst_module_load(MODULE_NAME, NULL); + + TST_EXP_FAIL(finit_module(*tc->fd, tc->param, tc->flags), tc->exp_errno, + "TestName: %s", tc->name); + + if (tc->exp_errno == EEXIST) + tst_module_unload(MODULE_NAME); + + if (!TST_PASS && !TST_RET) + tst_module_unload(MODULE_NAME); + + if (tc->cap) + tst_cap_action(&cap_req); + + SAFE_CLOSE(fd); +} + +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .cleanup = cleanup, + .needs_root = 1, +}; -- 2.25.0.rc1.19.g042ed3e048af ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [LTP] [PATCH V4 3/3] syscalls: finit_module: Add tests 2020-12-18 6:55 ` [LTP] [PATCH V4 " Viresh Kumar @ 2021-01-06 10:00 ` Cyril Hrubis 0 siblings, 0 replies; 11+ messages in thread From: Cyril Hrubis @ 2021-01-06 10:00 UTC (permalink / raw) To: ltp Hi! Applied, thanks. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 11+ messages in thread
* [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework 2020-12-17 7:27 [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework Viresh Kumar 2020-12-17 7:27 ` [LTP] [PATCH V2 2/3] syscalls: init_module: Add tests Viresh Kumar 2020-12-17 7:27 ` [LTP] [PATCH V2 3/3] syscalls: finit_module: " Viresh Kumar @ 2020-12-17 10:01 ` Cyril Hrubis 2 siblings, 0 replies; 11+ messages in thread From: Cyril Hrubis @ 2020-12-17 10:01 UTC (permalink / raw) To: ltp Hi! Pushed with a small fix, thanks. It turned out that there was a typo in the old_module.h header, the function tst_module_exist() never existed and it's supposed to be tst_module_exists(). So I've renamed all instances accordingly. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2021-01-06 10:00 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-12-17 7:27 [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework Viresh Kumar 2020-12-17 7:27 ` [LTP] [PATCH V2 2/3] syscalls: init_module: Add tests Viresh Kumar 2020-12-17 10:03 ` Cyril Hrubis 2020-12-17 7:27 ` [LTP] [PATCH V2 3/3] syscalls: finit_module: " Viresh Kumar 2020-12-17 10:09 ` Cyril Hrubis 2020-12-17 10:24 ` Viresh Kumar 2020-12-17 10:29 ` [LTP] [PATCH V3 " Viresh Kumar 2020-12-17 12:02 ` Cyril Hrubis 2020-12-18 6:55 ` [LTP] [PATCH V4 " Viresh Kumar 2021-01-06 10:00 ` Cyril Hrubis 2020-12-17 10:01 ` [LTP] [PATCH V2 1/3] tst_module: Add separate declarations of helpers for new tests framework Cyril Hrubis
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.