1 /* $NetBSD: netbsd32_compat_80.c,v 1.8 2023/07/29 13:57:28 pgoyette Exp $ */
2
3 /*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software developed for The NetBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_80.c,v 1.8 2023/07/29 13:57:28 pgoyette Exp $");
33
34 #include <sys/param.h>
35 #include <sys/dirent.h>
36 #include <sys/kauth.h>
37 #include <sys/module.h>
38 #include <sys/kobj.h>
39
40 #include <compat/sys/siginfo.h>
41
42 #include <compat/sys/module.h>
43
44 #include <compat/netbsd32/netbsd32.h>
45 #include <compat/netbsd32/netbsd32_syscall.h>
46 #include <compat/netbsd32/netbsd32_syscallargs.h>
47 #include <compat/netbsd32/netbsd32_conv.h>
48
49 int netbsd32_80_modctl(struct lwp *, const struct netbsd32_modctl_args *,
50 register_t *);
51
52 static int
modctl32_handle_ostat(int cmd,struct netbsd32_iovec * iov,void * arg)53 modctl32_handle_ostat(int cmd, struct netbsd32_iovec *iov, void *arg)
54 {
55 omodstat_t *oms, *omso;
56 modinfo_t *mi;
57 module_t *mod;
58 vaddr_t addr;
59 size_t size;
60 size_t omslen;
61 size_t used;
62 int error;
63 int omscnt;
64 bool stataddr;
65 const char *suffix = "...";
66
67 if (cmd != MODCTL_OSTAT)
68 return EINVAL;
69
70 /* If not privileged, don't expose kernel addresses. */
71 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
72 0, (void *)(uintptr_t)MODCTL_STAT, NULL, NULL);
73 stataddr = (error == 0);
74
75 kernconfig_lock();
76 omscnt = 0;
77 TAILQ_FOREACH(mod, &module_list, mod_chain) {
78 omscnt++;
79 mi = mod->mod_info;
80 }
81 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
82 omscnt++;
83 mi = mod->mod_info;
84 }
85 omslen = omscnt * sizeof(omodstat_t);
86 omso = kmem_zalloc(omslen, KM_SLEEP);
87 oms = omso;
88 TAILQ_FOREACH(mod, &module_list, mod_chain) {
89 mi = mod->mod_info;
90 strlcpy(oms->oms_name, mi->mi_name, sizeof(oms->oms_name));
91 if (mi->mi_required != NULL) {
92 used = strlcpy(oms->oms_required, mi->mi_required,
93 sizeof(oms->oms_required));
94 if (used >= sizeof(oms->oms_required)) {
95 oms->oms_required[sizeof(oms->oms_required) -
96 strlen(suffix) - 1] = '\0';
97 strlcat(oms->oms_required, suffix,
98 sizeof(oms->oms_required));
99 }
100 }
101 if (mod->mod_kobj != NULL && stataddr) {
102 kobj_stat(mod->mod_kobj, &addr, &size);
103 oms->oms_addr = addr;
104 oms->oms_size = size;
105 }
106 oms->oms_class = mi->mi_class;
107 oms->oms_refcnt = mod->mod_refcnt;
108 oms->oms_source = mod->mod_source;
109 oms->oms_flags = mod->mod_flags;
110 oms++;
111 }
112 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
113 mi = mod->mod_info;
114 strlcpy(oms->oms_name, mi->mi_name, sizeof(oms->oms_name));
115 if (mi->mi_required != NULL) {
116 used = strlcpy(oms->oms_required, mi->mi_required,
117 sizeof(oms->oms_required));
118 if (used >= sizeof(oms->oms_required)) {
119 oms->oms_required[sizeof(oms->oms_required) -
120 strlen(suffix) - 1] = '\0';
121 strlcat(oms->oms_required, suffix,
122 sizeof(oms->oms_required));
123 }
124 }
125 if (mod->mod_kobj != NULL && stataddr) {
126 kobj_stat(mod->mod_kobj, &addr, &size);
127 oms->oms_addr = addr;
128 oms->oms_size = size;
129 }
130 oms->oms_class = mi->mi_class;
131 oms->oms_refcnt = -1;
132 KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL);
133 oms->oms_source = mod->mod_source;
134 oms++;
135 }
136 kernconfig_unlock();
137 error = copyout(omso, NETBSD32PTR64(iov->iov_base),
138 uimin(omslen - sizeof(modstat_t), iov->iov_len));
139 kmem_free(omso, omslen);
140 if (error == 0) {
141 iov->iov_len = omslen - sizeof(modstat_t);
142 error = copyout(iov, arg, sizeof(*iov));
143 }
144
145 return error;
146 }
147
148 int
netbsd32_80_modctl(struct lwp * lwp,const struct netbsd32_modctl_args * uap,register_t * result)149 netbsd32_80_modctl(struct lwp *lwp, const struct netbsd32_modctl_args *uap,
150 register_t *result)
151 {
152 /* {
153 syscallarg(int) cmd;
154 syscallarg(netbsd32_voidp) arg;
155 } */
156 struct netbsd32_iovec iov;
157 int error;
158 void *arg;
159
160 arg = SCARG_P32(uap, arg);
161
162 switch (SCARG(uap, cmd)) {
163 case MODCTL_OSTAT:
164 error = copyin(arg, &iov, sizeof(iov));
165 if (error != 0) {
166 break;
167 }
168 error = modctl32_handle_ostat(SCARG(uap, cmd), &iov, arg);
169 break;
170 default:
171 error = EPASSTHROUGH;
172 break;
173 }
174
175 return error;
176 }
177
178 MODULE(MODULE_CLASS_EXEC, compat_netbsd32_80, "compat_netbsd32_90,compat_80");
179
180 static int
compat_netbsd32_80_modcmd(modcmd_t cmd,void * arg)181 compat_netbsd32_80_modcmd(modcmd_t cmd, void *arg)
182 {
183
184 switch (cmd) {
185 case MODULE_CMD_INIT:
186 MODULE_HOOK_SET(compat32_80_modctl_hook, netbsd32_80_modctl);
187 return 0;
188
189 case MODULE_CMD_FINI:
190 MODULE_HOOK_UNSET(compat32_80_modctl_hook);
191 return 0;
192
193 default:
194 return ENOTTY;
195 }
196 }
197