1 1.36 simonb /* $NetBSD: netbsd32_compat_30.c,v 1.36 2021/01/19 03:20:13 simonb Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (c) 1998, 2001 Matthew R. Green 5 1.1 christos * All rights reserved. 6 1.1 christos * 7 1.1 christos * Redistribution and use in source and binary forms, with or without 8 1.1 christos * modification, are permitted provided that the following conditions 9 1.1 christos * are met: 10 1.1 christos * 1. Redistributions of source code must retain the above copyright 11 1.1 christos * notice, this list of conditions and the following disclaimer. 12 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 christos * notice, this list of conditions and the following disclaimer in the 14 1.1 christos * documentation and/or other materials provided with the distribution. 15 1.1 christos * 16 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 christos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 christos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 christos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 christos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.1 christos * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.1 christos * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.1 christos * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.1 christos * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 christos * SUCH DAMAGE. 27 1.1 christos */ 28 1.1 christos 29 1.1 christos #include <sys/cdefs.h> 30 1.36 simonb __KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_30.c,v 1.36 2021/01/19 03:20:13 simonb Exp $"); 31 1.33 pgoyette 32 1.33 pgoyette #if defined(_KERNEL_OPT) 33 1.33 pgoyette #include <opt_ntp.h> 34 1.33 pgoyette #endif 35 1.1 christos 36 1.1 christos #include <sys/param.h> 37 1.1 christos #include <sys/systm.h> 38 1.33 pgoyette #include <sys/module.h> 39 1.33 pgoyette #include <sys/mount.h> 40 1.1 christos #include <sys/mount.h> 41 1.1 christos #include <sys/socket.h> 42 1.1 christos #include <sys/socketvar.h> 43 1.1 christos #include <sys/stat.h> 44 1.1 christos #include <sys/time.h> 45 1.1 christos #include <sys/ktrace.h> 46 1.1 christos #include <sys/resourcevar.h> 47 1.1 christos #include <sys/vnode.h> 48 1.1 christos #include <sys/file.h> 49 1.1 christos #include <sys/filedesc.h> 50 1.1 christos #include <sys/namei.h> 51 1.1 christos #include <sys/statvfs.h> 52 1.1 christos #include <sys/syscallargs.h> 53 1.33 pgoyette #include <sys/syscallvar.h> 54 1.1 christos #include <sys/proc.h> 55 1.2 christos #include <sys/dirent.h> 56 1.7 elad #include <sys/kauth.h> 57 1.18 dsl #include <sys/vfs_syscalls.h> 58 1.33 pgoyette #include <sys/compat_stub.h> 59 1.1 christos 60 1.1 christos #include <compat/netbsd32/netbsd32.h> 61 1.33 pgoyette #include <compat/netbsd32/netbsd32_syscall.h> 62 1.1 christos #include <compat/netbsd32/netbsd32_syscallargs.h> 63 1.1 christos #include <compat/netbsd32/netbsd32_conv.h> 64 1.9 martin #include <compat/sys/mount.h> 65 1.1 christos 66 1.1 christos int 67 1.23 dsl compat_30_netbsd32_getdents(struct lwp *l, const struct compat_30_netbsd32_getdents_args *uap, register_t *retval) 68 1.1 christos { 69 1.23 dsl /* { 70 1.1 christos syscallarg(int) fd; 71 1.1 christos syscallarg(netbsd32_charp) buf; 72 1.1 christos syscallarg(netbsd32_size_t) count; 73 1.23 dsl } */ 74 1.24 ad file_t *fp; 75 1.1 christos int error, done; 76 1.1 christos char *buf; 77 1.8 simonb netbsd32_size_t count; 78 1.1 christos 79 1.8 simonb /* Limit the size on any kernel buffers used by VOP_READDIR */ 80 1.32 riastrad count = uimin(MAXBSIZE, SCARG(uap, count)); 81 1.8 simonb 82 1.26 ad /* fd_getvnode() will use the descriptor for us */ 83 1.24 ad if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 84 1.36 simonb return error; 85 1.1 christos if ((fp->f_flag & FREAD) == 0) { 86 1.1 christos error = EBADF; 87 1.1 christos goto out; 88 1.1 christos } 89 1.31 maxv if (count == 0) 90 1.31 maxv goto out; 91 1.31 maxv 92 1.30 rmind buf = kmem_alloc(count, KM_SLEEP); 93 1.8 simonb error = vn_readdir(fp, buf, UIO_SYSSPACE, count, &done, l, 0, 0); 94 1.1 christos if (error == 0) { 95 1.1 christos *retval = netbsd32_to_dirent12(buf, done); 96 1.19 dsl error = copyout(buf, SCARG_P32(uap, buf), *retval); 97 1.1 christos } 98 1.30 rmind kmem_free(buf, count); 99 1.1 christos out: 100 1.24 ad fd_putfile(SCARG(uap, fd)); 101 1.36 simonb return error; 102 1.1 christos } 103 1.1 christos 104 1.1 christos int 105 1.23 dsl compat_30_netbsd32___stat13(struct lwp *l, const struct compat_30_netbsd32___stat13_args *uap, register_t *retval) 106 1.1 christos { 107 1.23 dsl /* { 108 1.1 christos syscallarg(const netbsd32_charp) path; 109 1.1 christos syscallarg(netbsd32_stat13p_t) ub; 110 1.23 dsl } */ 111 1.2 christos struct netbsd32_stat13 sb32; 112 1.1 christos struct stat sb; 113 1.1 christos int error; 114 1.1 christos const char *path; 115 1.1 christos 116 1.19 dsl path = SCARG_P32(uap, path); 117 1.1 christos 118 1.24 ad error = do_sys_stat(path, FOLLOW, &sb); 119 1.1 christos if (error) 120 1.36 simonb return error; 121 1.1 christos netbsd32_from___stat13(&sb, &sb32); 122 1.19 dsl error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32)); 123 1.36 simonb return error; 124 1.1 christos } 125 1.1 christos 126 1.1 christos int 127 1.23 dsl compat_30_netbsd32___fstat13(struct lwp *l, const struct compat_30_netbsd32___fstat13_args *uap, register_t *retval) 128 1.1 christos { 129 1.23 dsl /* { 130 1.1 christos syscallarg(int) fd; 131 1.1 christos syscallarg(netbsd32_stat13p_t) sb; 132 1.23 dsl } */ 133 1.2 christos struct netbsd32_stat13 sb32; 134 1.1 christos struct stat ub; 135 1.29 njoly int error; 136 1.1 christos 137 1.29 njoly error = do_sys_fstat(SCARG(uap, fd), &ub); 138 1.1 christos if (error == 0) { 139 1.1 christos netbsd32_from___stat13(&ub, &sb32); 140 1.19 dsl error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32)); 141 1.1 christos } 142 1.36 simonb return error; 143 1.1 christos } 144 1.1 christos 145 1.1 christos int 146 1.23 dsl compat_30_netbsd32___lstat13(struct lwp *l, const struct compat_30_netbsd32___lstat13_args *uap, register_t *retval) 147 1.1 christos { 148 1.23 dsl /* { 149 1.1 christos syscallarg(const netbsd32_charp) path; 150 1.1 christos syscallarg(netbsd32_stat13p_t) ub; 151 1.23 dsl } */ 152 1.2 christos struct netbsd32_stat13 sb32; 153 1.1 christos struct stat sb; 154 1.1 christos int error; 155 1.1 christos const char *path; 156 1.1 christos 157 1.19 dsl path = SCARG_P32(uap, path); 158 1.1 christos 159 1.24 ad error = do_sys_stat(path, NOFOLLOW, &sb); 160 1.1 christos if (error) 161 1.36 simonb return error; 162 1.1 christos netbsd32_from___stat13(&sb, &sb32); 163 1.19 dsl error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32)); 164 1.36 simonb return error; 165 1.1 christos } 166 1.6 cube 167 1.6 cube int 168 1.23 dsl compat_30_netbsd32_fhstat(struct lwp *l, const struct compat_30_netbsd32_fhstat_args *uap, register_t *retval) 169 1.6 cube { 170 1.23 dsl /* { 171 1.6 cube syscallarg(const netbsd32_fhandlep_t) fhp; 172 1.19 dsl syscallarg(netbsd32_stat13p_t) sb; 173 1.23 dsl } */ 174 1.6 cube struct stat sb; 175 1.6 cube struct netbsd32_stat13 sb32; 176 1.6 cube int error; 177 1.9 martin struct compat_30_fhandle fh; 178 1.6 cube struct mount *mp; 179 1.6 cube struct vnode *vp; 180 1.6 cube 181 1.6 cube /* 182 1.6 cube * Must be super user 183 1.6 cube */ 184 1.15 elad if ((error = kauth_authorize_system(l->l_cred, 185 1.15 elad KAUTH_SYSTEM_FILEHANDLE, 0, NULL, NULL, NULL))) 186 1.36 simonb return error; 187 1.6 cube 188 1.19 dsl if ((error = copyin(SCARG_P32(uap, fhp), &fh, sizeof(fh))) != 0) 189 1.36 simonb return error; 190 1.6 cube 191 1.6 cube if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 192 1.36 simonb return ESTALE; 193 1.6 cube if (mp->mnt_op->vfs_fhtovp == NULL) 194 1.6 cube return EOPNOTSUPP; 195 1.34 ad if ((error = VFS_FHTOVP(mp, (struct fid*)&fh.fh_fid, LK_EXCLUSIVE, &vp))) 196 1.36 simonb return error; 197 1.24 ad error = vn_stat(vp, &sb); 198 1.6 cube vput(vp); 199 1.6 cube if (error) 200 1.36 simonb return error; 201 1.6 cube netbsd32_from___stat13(&sb, &sb32); 202 1.35 maxv error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32)); 203 1.36 simonb return error; 204 1.6 cube } 205 1.9 martin 206 1.9 martin int 207 1.23 dsl compat_30_netbsd32_fhstatvfs1(struct lwp *l, const struct compat_30_netbsd32_fhstatvfs1_args *uap, register_t *retval) 208 1.12 martin { 209 1.23 dsl /* { 210 1.12 martin syscallarg(const netbsd32_fhandlep_t) fhp; 211 1.12 martin syscallarg(netbsd32_statvfsp_t) buf; 212 1.12 martin syscallarg(int) flags; 213 1.23 dsl } */ 214 1.12 martin struct statvfs *sbuf; 215 1.12 martin struct netbsd32_statvfs *s32; 216 1.12 martin int error; 217 1.12 martin 218 1.21 dsl sbuf = STATVFSBUF_GET(); 219 1.21 dsl error = do_fhstatvfs(l, SCARG_P32(uap, fhp), FHANDLE_SIZE_COMPAT, sbuf, 220 1.21 dsl SCARG(uap, flags)); 221 1.21 dsl 222 1.21 dsl if (error != 0) { 223 1.30 rmind s32 = kmem_alloc(sizeof(*s32), KM_SLEEP); 224 1.21 dsl netbsd32_from_statvfs(sbuf, s32); 225 1.21 dsl error = copyout(s32, SCARG_P32(uap, buf), sizeof *s32); 226 1.30 rmind kmem_free(s32, sizeof(*s32)); 227 1.21 dsl } 228 1.21 dsl STATVFSBUF_PUT(sbuf); 229 1.12 martin 230 1.36 simonb return error; 231 1.12 martin } 232 1.12 martin 233 1.12 martin int 234 1.23 dsl compat_30_netbsd32_socket(struct lwp *l, const struct compat_30_netbsd32_socket_args *uap, register_t *retval) 235 1.9 martin { 236 1.23 dsl /* { 237 1.9 martin syscallarg(int) domain; 238 1.9 martin syscallarg(int) type; 239 1.9 martin syscallarg(int) protocol; 240 1.23 dsl } */ 241 1.9 martin struct compat_30_sys_socket_args ua; 242 1.9 martin 243 1.9 martin NETBSD32TO64_UAP(domain); 244 1.9 martin NETBSD32TO64_UAP(type); 245 1.9 martin NETBSD32TO64_UAP(protocol); 246 1.36 simonb return compat_30_sys_socket(l, &ua, retval); 247 1.9 martin } 248 1.9 martin 249 1.9 martin int 250 1.23 dsl compat_30_netbsd32_getfh(struct lwp *l, const struct compat_30_netbsd32_getfh_args *uap, register_t *retval) 251 1.9 martin { 252 1.23 dsl /* { 253 1.9 martin syscallarg(const netbsd32_charp) fname; 254 1.9 martin syscallarg(netbsd32_compat_30_fhandlep_t) fhp; 255 1.23 dsl } */ 256 1.9 martin struct compat_30_sys_getfh_args ua; 257 1.9 martin 258 1.9 martin NETBSD32TOP_UAP(fname, const char); 259 1.9 martin NETBSD32TOP_UAP(fhp, struct compat_30_fhandle); 260 1.9 martin /* Lucky for us a fhandle_t doesn't change sizes */ 261 1.36 simonb return compat_30_sys_getfh(l, &ua, retval); 262 1.9 martin } 263 1.12 martin 264 1.12 martin 265 1.23 dsl int 266 1.28 christos compat_30_netbsd32___fhstat30(struct lwp *l, const struct compat_30_netbsd32___fhstat30_args *uap, register_t *retval) 267 1.12 martin { 268 1.23 dsl /* { 269 1.12 martin syscallarg(const netbsd32_fhandlep_t) fhp; 270 1.12 martin syscallarg(netbsd32_statp_t) sb; 271 1.23 dsl } */ 272 1.12 martin struct stat sb; 273 1.28 christos struct netbsd32_stat50 sb32; 274 1.12 martin int error; 275 1.12 martin 276 1.21 dsl error = do_fhstat(l, SCARG_P32(uap, fhp), FHANDLE_SIZE_COMPAT, &sb); 277 1.21 dsl if (error) 278 1.12 martin return error; 279 1.12 martin 280 1.28 christos netbsd32_from___stat50(&sb, &sb32); 281 1.21 dsl error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32)); 282 1.12 martin return error; 283 1.12 martin } 284 1.12 martin 285 1.12 martin /* 286 1.12 martin * Open a file given a file handle. 287 1.12 martin * 288 1.12 martin * Check permissions, allocate an open file structure, 289 1.12 martin * and call the device open routine if any. 290 1.12 martin */ 291 1.12 martin int 292 1.23 dsl compat_30_netbsd32_fhopen(struct lwp *l, const struct compat_30_netbsd32_fhopen_args *uap, register_t *retval) 293 1.12 martin { 294 1.23 dsl /* { 295 1.12 martin syscallarg(const fhandle_t *) fhp; 296 1.12 martin syscallarg(int) flags; 297 1.23 dsl } */ 298 1.12 martin struct compat_30_sys_fhopen_args ua; 299 1.12 martin 300 1.12 martin NETBSD32TOP_UAP(fhp, struct compat_30_fhandle); 301 1.12 martin NETBSD32TO64_UAP(flags); 302 1.36 simonb return compat_30_sys_fhopen(l, &ua, retval); 303 1.12 martin } 304 1.33 pgoyette 305 1.33 pgoyette #ifdef NTP 306 1.33 pgoyette int 307 1.33 pgoyette compat_30_netbsd32_ntp_gettime(struct lwp *l, const struct compat_30_netbsd32_ntp_gettime_args *uap, register_t *retval) 308 1.33 pgoyette { 309 1.33 pgoyette /* { 310 1.33 pgoyette syscallarg(netbsd32_ntptimevalp_t) ntvp; 311 1.33 pgoyette } */ 312 1.33 pgoyette struct netbsd32_ntptimeval30 ntv32; 313 1.33 pgoyette struct ntptimeval ntv; 314 1.33 pgoyette int error = 0; 315 1.33 pgoyette 316 1.33 pgoyette if (vec_ntp_gettime == NULL) 317 1.33 pgoyette return EINVAL; 318 1.33 pgoyette 319 1.33 pgoyette if (SCARG_P32(uap, ntvp)) { 320 1.33 pgoyette (*vec_ntp_gettime)(&ntv); 321 1.33 pgoyette 322 1.33 pgoyette memset(&ntv32, 0, sizeof(ntv32)); 323 1.33 pgoyette ntv32.time.tv_sec = ntv.time.tv_sec; 324 1.33 pgoyette ntv32.time.tv_usec = ntv.time.tv_nsec / 1000; 325 1.33 pgoyette ntv32.maxerror = (netbsd32_long)ntv.maxerror; 326 1.33 pgoyette ntv32.esterror = (netbsd32_long)ntv.esterror; 327 1.33 pgoyette error = copyout(&ntv32, SCARG_P32(uap, ntvp), sizeof(ntv32)); 328 1.33 pgoyette } 329 1.33 pgoyette if (!error) { 330 1.33 pgoyette *retval = (*vec_ntp_timestatus)(); 331 1.33 pgoyette } 332 1.33 pgoyette 333 1.36 simonb return error; 334 1.33 pgoyette } 335 1.33 pgoyette #endif 336 1.33 pgoyette 337 1.33 pgoyette static struct syscall_package compat_netbsd32_30_syscalls[] = { 338 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32_getdents, 0, 339 1.33 pgoyette (sy_call_t *)compat_30_netbsd32_getdents }, 340 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32___stat13, 0, 341 1.33 pgoyette (sy_call_t *)compat_30_netbsd32___stat13 }, 342 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32___fstat13, 0, 343 1.33 pgoyette (sy_call_t *)compat_30_netbsd32___fstat13 }, 344 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32___lstat13, 0, 345 1.33 pgoyette (sy_call_t *)compat_30_netbsd32___lstat13 }, 346 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32_fhstat, 0, 347 1.33 pgoyette (sy_call_t *)compat_30_netbsd32_fhstat }, 348 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32_fhstatvfs1, 0, 349 1.33 pgoyette (sy_call_t *)compat_30_netbsd32_fhstatvfs1 }, 350 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32_socket, 0, 351 1.33 pgoyette (sy_call_t *)compat_30_netbsd32_socket }, 352 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32_getfh, 0, 353 1.33 pgoyette (sy_call_t *)compat_30_netbsd32_getfh }, 354 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32___fhstat30, 0, 355 1.33 pgoyette (sy_call_t *)compat_30_netbsd32___fhstat30 }, 356 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32_fhopen, 0, 357 1.33 pgoyette (sy_call_t *)compat_30_netbsd32_fhopen }, 358 1.33 pgoyette #ifdef NTP 359 1.33 pgoyette { NETBSD32_SYS_compat_30_netbsd32_ntp_gettime, 0, 360 1.33 pgoyette (sy_call_t *)compat_30_netbsd32_ntp_gettime }, 361 1.33 pgoyette #endif 362 1.33 pgoyette { 0, 0, NULL } 363 1.33 pgoyette }; 364 1.33 pgoyette 365 1.33 pgoyette MODULE(MODULE_CLASS_EXEC, compat_netbsd32_30, "compat_netbsd32_40,compat_30"); 366 1.33 pgoyette 367 1.33 pgoyette static int 368 1.33 pgoyette compat_netbsd32_30_modcmd(modcmd_t cmd, void *arg) 369 1.33 pgoyette { 370 1.33 pgoyette 371 1.33 pgoyette switch (cmd) { 372 1.33 pgoyette case MODULE_CMD_INIT: 373 1.33 pgoyette return syscall_establish(&emul_netbsd32, 374 1.33 pgoyette compat_netbsd32_30_syscalls); 375 1.33 pgoyette 376 1.33 pgoyette case MODULE_CMD_FINI: 377 1.33 pgoyette return syscall_disestablish(&emul_netbsd32, 378 1.33 pgoyette compat_netbsd32_30_syscalls); 379 1.33 pgoyette 380 1.33 pgoyette default: 381 1.33 pgoyette return ENOTTY; 382 1.33 pgoyette } 383 1.33 pgoyette } 384