1 /*
2 * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
3 * Copyright (c) Linux Test Project, 2016-2024
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * Author: Alexey Kodanev <alexey.kodanev@oracle.com>
20 *
21 */
22
23 #define _GNU_SOURCE
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <stdbool.h>
28
29 #include "test.h"
30 #include "tst_kconfig.h"
31 #include "ltp_priv.h"
32 #include "old_module.h"
33
tst_module_exists_(void (cleanup_fn)(void),const char * mod_name,char ** mod_path)34 void tst_module_exists_(void (cleanup_fn)(void),
35 const char *mod_name, char **mod_path)
36 {
37 /* check current working directory */
38 if (access(mod_name, F_OK) == 0) {
39 if (mod_path != NULL)
40 *mod_path = strdup(mod_name);
41 return;
42 }
43 char *buf = NULL;
44 int err = -1;
45 /* check LTP installation path */
46 const char *ltproot = getenv("LTPROOT");
47 if (ltproot != NULL) {
48 if (asprintf(&buf, "%s/testcases/bin/%s",
49 ltproot, mod_name) == -1) {
50 tst_brkm(TBROK | TERRNO, cleanup_fn,
51 "asprintf failed at %s:%d",
52 __FILE__, __LINE__);
53 return;
54 }
55 err = access(buf, F_OK);
56 }
57 /* check start working directory */
58 if (err == -1 && tst_tmpdir_created()) {
59 free(buf);
60 if (asprintf(&buf, "%s/%s", tst_get_startwd(),
61 mod_name) == -1) {
62 tst_brkm(TBROK | TERRNO, cleanup_fn,
63 "asprintf failed at %s:%d",
64 __FILE__, __LINE__);
65 return;
66 }
67 err = access(buf, F_OK);
68 }
69
70 if (err != 0) {
71 free(buf);
72 tst_brkm(TCONF, cleanup_fn, "Failed to find module '%s'",
73 mod_name);
74 return;
75 }
76
77 if (mod_path != NULL)
78 *mod_path = buf;
79 else
80 free(buf);
81 }
82
tst_module_load_(void (cleanup_fn)(void),const char * mod_name,char * const argv[])83 void tst_module_load_(void (cleanup_fn)(void),
84 const char *mod_name, char *const argv[])
85 {
86 char *mod_path = NULL;
87 tst_module_exists_(cleanup_fn, mod_name, &mod_path);
88
89 const int offset = 2; /* command name & module path */
90 int size = 0;
91 while (argv && argv[size])
92 ++size;
93 size += offset;
94 const char *mod_argv[size + 1]; /* + NULL in the end */
95 mod_argv[size] = NULL;
96 mod_argv[0] = "insmod";
97 mod_argv[1] = mod_path;
98
99 int i;
100 for (i = offset; i < size; ++i)
101 mod_argv[i] = argv[i - offset];
102
103 tst_cmd(cleanup_fn, mod_argv, NULL, NULL, 0);
104 free(mod_path);
105 }
106
tst_module_unload_(void (cleanup_fn)(void),const char * mod_name)107 void tst_module_unload_(void (cleanup_fn)(void), const char *mod_name)
108 {
109 int i, rc;
110
111 const char *const argv[] = { "rmmod", mod_name, NULL };
112
113 rc = 1;
114 for (i = 0; i < 50; i++) {
115 rc = tst_cmd(NULL, argv, "/dev/null", "/dev/null",
116 TST_CMD_PASS_RETVAL);
117 if (!rc)
118 break;
119
120 usleep(20000);
121 }
122
123 if (rc) {
124 tst_brkm(TBROK, cleanup_fn,
125 "could not unload %s module", mod_name);
126 }
127 }
128
tst_module_signature_enforced_(void)129 bool tst_module_signature_enforced_(void)
130 {
131 struct tst_kcmdline_var params = TST_KCMDLINE_INIT("module.sig_enforce");
132 struct tst_kconfig_var kconfig = TST_KCONFIG_INIT("CONFIG_MODULE_SIG_FORCE");
133 int rc;
134
135 tst_kcmdline_parse(¶ms, 1);
136 tst_kconfig_read(&kconfig, 1);
137
138 rc = params.found || kconfig.choice == 'y';
139 tst_resm(TINFO, "module signature enforcement: %s", rc ? "on" : "off");
140
141 return rc;
142 }
143
tst_requires_module_signature_disabled_(void)144 void tst_requires_module_signature_disabled_(void)
145 {
146 if (tst_module_signature_enforced_())
147 tst_brkm(TCONF, NULL, "module signature is enforced, skip test");
148 }
149