netbsd32_module.c revision 1.6 1 /* $NetBSD: netbsd32_module.c,v 1.6 2018/01/18 13:31:21 maxv 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_module.c,v 1.6 2018/01/18 13:31:21 maxv 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 static int
46 modctl32_handle_stat(struct netbsd32_iovec *iov, void *arg)
47 {
48 modstat_t *ms, *mso;
49 modinfo_t *mi;
50 module_t *mod;
51 vaddr_t addr;
52 size_t size;
53 size_t mslen;
54 int error;
55 bool stataddr;
56
57 /* If not privileged, don't expose kernel addresses. */
58 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
59 0, (void *)(uintptr_t)MODCTL_STAT, NULL, NULL);
60 stataddr = (error == 0);
61
62 kernconfig_lock();
63 mslen = (module_count+module_builtinlist+1) * sizeof(modstat_t);
64 mso = kmem_zalloc(mslen, KM_SLEEP);
65 ms = mso;
66 TAILQ_FOREACH(mod, &module_list, mod_chain) {
67 mi = mod->mod_info;
68 strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
69 if (mi->mi_required != NULL) {
70 strlcpy(ms->ms_required, mi->mi_required,
71 sizeof(ms->ms_required));
72 }
73 if (mod->mod_kobj != NULL && stataddr) {
74 kobj_stat(mod->mod_kobj, &addr, &size);
75 ms->ms_addr = addr;
76 ms->ms_size = size;
77 }
78 ms->ms_class = mi->mi_class;
79 ms->ms_refcnt = mod->mod_refcnt;
80 ms->ms_source = mod->mod_source;
81 ms->ms_flags = mod->mod_flags;
82 ms++;
83 }
84 TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
85 mi = mod->mod_info;
86 strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name));
87 if (mi->mi_required != NULL) {
88 strlcpy(ms->ms_required, mi->mi_required,
89 sizeof(ms->ms_required));
90 }
91 if (mod->mod_kobj != NULL && stataddr) {
92 kobj_stat(mod->mod_kobj, &addr, &size);
93 ms->ms_addr = addr;
94 ms->ms_size = size;
95 }
96 ms->ms_class = mi->mi_class;
97 ms->ms_refcnt = -1;
98 KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL);
99 ms->ms_source = mod->mod_source;
100 ms++;
101 }
102 kernconfig_unlock();
103 error = copyout(mso, NETBSD32PTR64(iov->iov_base),
104 min(mslen - sizeof(modstat_t), iov->iov_len));
105 kmem_free(mso, mslen);
106 if (error == 0) {
107 iov->iov_len = mslen - sizeof(modstat_t);
108 error = copyout(iov, arg, sizeof(*iov));
109 }
110
111 return error;
112 }
113
114 int
115 netbsd32_modctl(struct lwp *lwp, const struct netbsd32_modctl_args *uap,
116 register_t *result)
117 {
118 /* {
119 syscallarg(int) cmd;
120 syscallarg(netbsd32_voidp) arg;
121 } */
122 char buf[MAXMODNAME];
123 struct netbsd32_iovec iov;
124 struct netbsd32_modctl_load ml;
125 int error;
126 void *arg;
127 #ifdef MODULAR
128 uintptr_t loadtype;
129 #endif
130
131 arg = SCARG_P32(uap, arg);
132
133 switch (SCARG(uap, cmd)) {
134 case MODCTL_LOAD:
135 error = copyin(arg, &ml, sizeof(ml));
136 if (error != 0)
137 break;
138 error = handle_modctl_load(NETBSD32PTR64(ml.ml_filename),
139 ml.ml_flags, NETBSD32PTR64(ml.ml_props), ml.ml_propslen);
140 break;
141
142 case MODCTL_UNLOAD:
143 error = copyinstr(arg, buf, sizeof(buf), NULL);
144 if (error == 0) {
145 error = module_unload(buf);
146 }
147 break;
148
149 case MODCTL_STAT:
150 error = copyin(arg, &iov, sizeof(iov));
151 if (error != 0) {
152 break;
153 }
154 error = modctl32_handle_stat(&iov, arg);
155 break;
156
157 case MODCTL_EXISTS:
158 #ifndef MODULAR
159 error = ENOSYS;
160 #else
161 loadtype = (uintptr_t)arg;
162 switch (loadtype) { /* 0 = modload, 1 = autoload */
163 case 0: /* FALLTHROUGH */
164 case 1:
165 error = kauth_authorize_system(kauth_cred_get(),
166 KAUTH_SYSTEM_MODULE, 0,
167 (void *)(uintptr_t)MODCTL_LOAD,
168 (void *)loadtype, NULL);
169 break;
170
171 default:
172 error = EINVAL;
173 break;
174 }
175 #endif
176 break;
177
178 default:
179 error = EINVAL;
180 break;
181 }
182
183 return error;
184 }
185