1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
4 * Copyright (c) 2018 Xiao Yang <yangx.jy@cn.fujitsu.com>
5 */
6
7 /*
8 * AUTHOR: Madhu T L <madhu.tarikere@wipro.com>
9 *
10 * DESCRIPTION
11 * Verify that,
12 * 1. delete_module(2) returns -1 and sets errno to ENOENT for nonexistent
13 * module entry.
14 * 2. delete_module(2) returns -1 and sets errno to EFAULT, if
15 * module name parameter is outside program's accessible address space.
16 * 3. delete_module(2) returns -1 and sets errno to EPERM, if effective
17 * user id of the caller is not superuser.
18 */
19
20 #include <errno.h>
21 #include <pwd.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #include "tst_test.h"
26 #include "lapi/syscalls.h"
27
28 #define BASEMODNAME "dummy"
29 #define LONGMODNAMECHAR 'm'
30
31 /*
32 * From kernel internal headers: include/linux/module.h
33 * include/linux/moduleparam.h
34 */
35 #define MODULE_NAME_LEN (64 - sizeof(unsigned long))
36
37 static struct passwd *ltpuser;
38 static char longmodname[MODULE_NAME_LEN];
39 static char modname[20];
40
41 static struct test_case_t {
42 char *modname;
43 int experrno;
44 char *desc;
45 /* 1: nobody_user 0: root_user */
46 int nobody_user;
47 } tdat[] = {
48 { modname, ENOENT, "nonexistent module", 0},
49 { "", ENOENT, "null terminated module name", 0},
50 { NULL, EFAULT, "module name outside program's accessible address space", 0},
51 { longmodname, ENOENT, "long module name", 0},
52 { modname, EPERM, "non-superuser", 1},
53 };
54
do_delete_module(unsigned int n)55 static void do_delete_module(unsigned int n)
56 {
57 struct test_case_t *tc = &tdat[n];
58
59 if (!tc->modname)
60 tc->modname = tst_get_bad_addr(NULL);
61
62 if (tc->nobody_user)
63 SAFE_SETEUID(ltpuser->pw_uid);
64
65 tst_res(TINFO, "test %s", tc->desc);
66 TEST(tst_syscall(__NR_delete_module, tc->modname, 0));
67 if (TST_RET != -1) {
68 tst_res(TFAIL, "delete_module() succeeded unexpectedly");
69 } else if (TST_ERR == tc->experrno) {
70 tst_res(TPASS | TTERRNO, "delete_module() failed as expected");
71 } else {
72 tst_res(TFAIL | TTERRNO, "delete_module() failed unexpectedly;"
73 " expected: %s", tst_strerrno(tc->experrno));
74 }
75
76 if (tc->nobody_user)
77 SAFE_SETEUID(0);
78 }
79
setup(void)80 static void setup(void)
81 {
82 ltpuser = SAFE_GETPWNAM("nobody");
83
84 /* Initialize longmodname to LONGMODNAMECHAR character */
85 memset(longmodname, LONGMODNAMECHAR, MODULE_NAME_LEN - 1);
86
87 /* Get unique module name for each child process */
88 sprintf(modname, "%s_%d", BASEMODNAME, getpid());
89 }
90
91 static struct tst_test test = {
92 .tcnt = ARRAY_SIZE(tdat),
93 .needs_root = 1,
94 .setup = setup,
95 .test = do_delete_module,
96 };
97