netbsd32_compat_80.c revision 1.1.2.1 1 /* $NetBSD: netbsd32_compat_80.c,v 1.1.2.1 2018/09/10 22:50:51 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.1.2.1 2018/09/10 22:50:51 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/netbsd32/netbsd32.h>
41 #include <compat/netbsd32/netbsd32_syscall.h>
42 #include <compat/netbsd32/netbsd32_syscallargs.h>
43 #include <compat/netbsd32/netbsd32_conv.h>
44
45 #ifdef COMPAT_80
46 static int
47 modctl32_handle_ostat(int cmd, struct netbsd32_iovec *iov, void *arg)
48 {
49 omodstat_t *oms, *omso;
50 modinfo_t *mi;
51 module_t *mod;
52 vaddr_t addr;
53 size_t size;
54 size_t omslen;
55 size_t used;
56 int error;
57 int omscnt;
58 bool stataddr;
59 const char *suffix = "...";
60
61 if (cmd != MODCTL_OSTAT)
62 return EINVAL;
63
64 /* If not privileged, don't expose kernel addresses. */
65 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
66 0, (void *)(uintptr_t)MODCTL_STAT, NULL, NULL);
67 stataddr = (error == 0);
68
69 kernconfig_lock();
70 omscnt = 0;
71 TAILQ_FOREACH(mod, &module_list, mod_chain) {
72 omscnt++;
73 mi = mod->mod_info;
74 }
75 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
76 omscnt++;
77 mi = mod->mod_info;
78 }
79 omslen = omscnt * sizeof(omodstat_t);
80 omso = kmem_zalloc(omslen, KM_SLEEP);
81 oms = omso;
82 TAILQ_FOREACH(mod, &module_list, mod_chain) {
83 mi = mod->mod_info;
84 strlcpy(oms->oms_name, mi->mi_name, sizeof(oms->oms_name));
85 if (mi->mi_required != NULL) {
86 used = strlcpy(oms->oms_required, mi->mi_required,
87 sizeof(oms->oms_required));
88 if (used >= sizeof(oms->oms_required)) {
89 oms->oms_required[sizeof(oms->oms_required) -
90 strlen(suffix) - 1] = '\0';
91 strlcat(oms->oms_required, suffix,
92 sizeof(oms->oms_required));
93 }
94 }
95 if (mod->mod_kobj != NULL && stataddr) {
96 kobj_stat(mod->mod_kobj, &addr, &size);
97 oms->oms_addr = addr;
98 oms->oms_size = size;
99 }
100 oms->oms_class = mi->mi_class;
101 oms->oms_refcnt = mod->mod_refcnt;
102 oms->oms_source = mod->mod_source;
103 oms->oms_flags = mod->mod_flags;
104 oms++;
105 }
106 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
107 mi = mod->mod_info;
108 strlcpy(oms->oms_name, mi->mi_name, sizeof(oms->oms_name));
109 if (mi->mi_required != NULL) {
110 used = strlcpy(oms->oms_required, mi->mi_required,
111 sizeof(oms->oms_required));
112 if (used >= sizeof(oms->oms_required)) {
113 oms->oms_required[sizeof(oms->oms_required) -
114 strlen(suffix) - 1] = '\0';
115 strlcat(oms->oms_required, suffix,
116 sizeof(oms->oms_required));
117 }
118 }
119 if (mod->mod_kobj != NULL && stataddr) {
120 kobj_stat(mod->mod_kobj, &addr, &size);
121 oms->oms_addr = addr;
122 oms->oms_size = size;
123 }
124 oms->oms_class = mi->mi_class;
125 oms->oms_refcnt = -1;
126 KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL);
127 oms->oms_source = mod->mod_source;
128 oms++;
129 }
130 kernconfig_unlock();
131 error = copyout(omso, NETBSD32PTR64(iov->iov_base),
132 uimin(omslen - sizeof(modstat_t), iov->iov_len));
133 kmem_free(omso, omslen);
134 if (error == 0) {
135 iov->iov_len = omslen - sizeof(modstat_t);
136 error = copyout(iov, arg, sizeof(*iov));
137 }
138
139 return error;
140 }
141
142 int
143 netbsd32_80_modctl(struct lwp *lwp, const struct netbsd32_modctl_args *uap,
144 register_t *result)
145 {
146 /* {
147 syscallarg(int) cmd;
148 syscallarg(netbsd32_voidp) arg;
149 } */
150 char buf[MAXMODNAME];
151 struct netbsd32_iovec iov;
152 struct netbsd32_modctl_load ml;
153 int error;
154 void *arg;
155 #ifdef MODULAR
156 uintptr_t loadtype;
157 #endif
158
159 arg = SCARG_P32(uap, arg);
160
161 switch (SCARG(uap, cmd)) {
162 case MODCTL_OSTAT:
163 error = copyin(arg, &iov, sizeof(iov));
164 if (error != 0) {
165 break;
166 }
167 error = modctl32_handle_ostat(SCARG(uap, cmd), &iov, arg);
168 break;
169 default:
170 error = EPASSTHROUGH;
171 break;
172 }
173
174 return error;
175 }
176
177 MODULE(MODULE_CLASS_EXEC, compat_netbsd32_80, "compat_netbsd32,compat_80");
178
179 static int
180 compat_netbsd32_80_modcmd(modcmd_t cmd, void *arg)
181 {
182 static int (*orig_netbsd32_80_modctl)(struct lwp *,
183 const struct netbsd32_modctl_args *, register_t *);
184
185 switch (cmd) {
186 case MODULE_CMD_INIT:
187 orig_netbsd32_80_modctl = vec_compat32_80_modctl;
188 vec_compat32_80_modctl = netbsd32_80_modctl;
189 return 0;
190
191 case MODULE_CMD_FINI:
192 vec_compat32_80_modctl = orig_netbsd32_80_modctl;
193 return 0;
194
195 default:
196 return ENOTTY;
197 }
198 }
199 #endif /* COMPAT_80 */
200
201 vec_compat32_80_modctl = compat32_80_modctl_compat_stub;
202