1 /* $NetBSD: netbsd32_compat_30.c,v 1.13 2006/08/04 16:29:51 yamt Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_30.c,v 1.13 2006/08/04 16:29:51 yamt Exp $"); 33 34 #include "opt_nfsserver.h" 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <sys/mount.h> 40 #include <sys/socket.h> 41 #include <sys/socketvar.h> 42 #include <sys/stat.h> 43 #include <sys/time.h> 44 #include <sys/ktrace.h> 45 #include <sys/resourcevar.h> 46 #include <sys/vnode.h> 47 #include <sys/file.h> 48 #include <sys/filedesc.h> 49 #include <sys/namei.h> 50 #include <sys/sa.h> 51 #include <sys/statvfs.h> 52 #include <sys/syscallargs.h> 53 #include <sys/proc.h> 54 #include <sys/dirent.h> 55 #include <sys/kauth.h> 56 57 #include <compat/netbsd32/netbsd32.h> 58 #include <compat/netbsd32/netbsd32_syscallargs.h> 59 #include <compat/netbsd32/netbsd32_conv.h> 60 #include <compat/sys/mount.h> 61 62 63 int 64 netbsd32_getdents(l, v, retval) 65 struct lwp *l; 66 void *v; 67 register_t *retval; 68 { 69 struct netbsd32_getdents_args /* { 70 syscallarg(int) fd; 71 syscallarg(netbsd32_charp) buf; 72 syscallarg(netbsd32_size_t) count; 73 } */ *uap = v; 74 struct file *fp; 75 int error, done; 76 char *buf; 77 netbsd32_size_t count; 78 struct proc *p = l->l_proc; 79 80 /* Limit the size on any kernel buffers used by VOP_READDIR */ 81 count = min(MAXBSIZE, SCARG(uap, count)); 82 83 /* getvnode() will use the descriptor for us */ 84 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 85 return (error); 86 if ((fp->f_flag & FREAD) == 0) { 87 error = EBADF; 88 goto out; 89 } 90 buf = malloc(count, M_TEMP, M_WAITOK); 91 error = vn_readdir(fp, buf, UIO_SYSSPACE, count, &done, l, 0, 0); 92 if (error == 0) { 93 *retval = netbsd32_to_dirent12(buf, done); 94 error = copyout(buf, NETBSD32PTR64(SCARG(uap, buf)), *retval); 95 } 96 free(buf, M_TEMP); 97 out: 98 FILE_UNUSE(fp, l); 99 return (error); 100 } 101 102 int 103 netbsd32___stat13(l, v, retval) 104 struct lwp *l; 105 void *v; 106 register_t *retval; 107 { 108 struct netbsd32___stat13_args /* { 109 syscallarg(const netbsd32_charp) path; 110 syscallarg(netbsd32_stat13p_t) ub; 111 } */ *uap = v; 112 struct netbsd32_stat13 sb32; 113 struct stat sb; 114 int error; 115 struct nameidata nd; 116 caddr_t sg; 117 const char *path; 118 struct proc *p = l->l_proc; 119 120 path = (char *)NETBSD32PTR64(SCARG(uap, path)); 121 sg = stackgap_init(p, 0); 122 CHECK_ALT_EXIST(l, &sg, path); 123 124 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, path, l); 125 if ((error = namei(&nd)) != 0) 126 return (error); 127 error = vn_stat(nd.ni_vp, &sb, l); 128 vput(nd.ni_vp); 129 if (error) 130 return (error); 131 netbsd32_from___stat13(&sb, &sb32); 132 error = copyout(&sb32, (caddr_t)NETBSD32PTR64(SCARG(uap, ub)), 133 sizeof(sb32)); 134 return (error); 135 } 136 137 int 138 netbsd32___fstat13(l, v, retval) 139 struct lwp *l; 140 void *v; 141 register_t *retval; 142 { 143 struct netbsd32___fstat13_args /* { 144 syscallarg(int) fd; 145 syscallarg(netbsd32_stat13p_t) sb; 146 } */ *uap = v; 147 int fd = SCARG(uap, fd); 148 struct proc *p = l->l_proc; 149 struct filedesc *fdp = p->p_fd; 150 struct file *fp; 151 struct netbsd32_stat13 sb32; 152 struct stat ub; 153 int error = 0; 154 155 if ((fp = fd_getfile(fdp, fd)) == NULL) 156 return (EBADF); 157 158 FILE_USE(fp); 159 error = (*fp->f_ops->fo_stat)(fp, &ub, l); 160 FILE_UNUSE(fp, l); 161 162 if (error == 0) { 163 netbsd32_from___stat13(&ub, &sb32); 164 error = copyout(&sb32, (caddr_t)NETBSD32PTR64(SCARG(uap, sb)), 165 sizeof(sb32)); 166 } 167 return (error); 168 } 169 170 int 171 netbsd32___lstat13(l, v, retval) 172 struct lwp *l; 173 void *v; 174 register_t *retval; 175 { 176 struct netbsd32___lstat13_args /* { 177 syscallarg(const netbsd32_charp) path; 178 syscallarg(netbsd32_stat13p_t) ub; 179 } */ *uap = v; 180 struct netbsd32_stat13 sb32; 181 struct stat sb; 182 int error; 183 struct nameidata nd; 184 caddr_t sg; 185 const char *path; 186 struct proc *p = l->l_proc; 187 188 path = (char *)NETBSD32PTR64(SCARG(uap, path)); 189 sg = stackgap_init(p, 0); 190 CHECK_ALT_EXIST(l, &sg, path); 191 192 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, path, l); 193 if ((error = namei(&nd)) != 0) 194 return (error); 195 error = vn_stat(nd.ni_vp, &sb, l); 196 vput(nd.ni_vp); 197 if (error) 198 return (error); 199 netbsd32_from___stat13(&sb, &sb32); 200 error = copyout(&sb32, (caddr_t)NETBSD32PTR64(SCARG(uap, ub)), 201 sizeof(sb32)); 202 return (error); 203 } 204 205 int 206 compat_30_netbsd32_fhstat(l, v, retval) 207 struct lwp *l; 208 void *v; 209 register_t *retval; 210 { 211 struct compat_30_netbsd32_fhstat_args /* { 212 syscallarg(const netbsd32_fhandlep_t) fhp; 213 syscallarg(netbsd32_stat13p_t) sb); 214 } */ *uap = v; 215 struct stat sb; 216 struct netbsd32_stat13 sb32; 217 int error; 218 struct compat_30_fhandle fh; 219 struct mount *mp; 220 struct vnode *vp; 221 222 /* 223 * Must be super user 224 */ 225 if ((error = kauth_authorize_generic(l->l_cred, 226 KAUTH_GENERIC_ISSUSER, &l->l_acflag))) 227 return (error); 228 229 if ((error = copyin(NETBSD32PTR64(SCARG(uap, fhp)), &fh, 230 sizeof(fh))) != 0) 231 return (error); 232 233 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 234 return (ESTALE); 235 if (mp->mnt_op->vfs_fhtovp == NULL) 236 return EOPNOTSUPP; 237 if ((error = VFS_FHTOVP(mp, (struct fid*)&fh.fh_fid, &vp))) 238 return (error); 239 error = vn_stat(vp, &sb, l); 240 vput(vp); 241 if (error) 242 return (error); 243 netbsd32_from___stat13(&sb, &sb32); 244 error = copyout(&sb32, NETBSD32PTR64(SCARG(uap, sb)), sizeof(sb)); 245 return (error); 246 } 247 248 int 249 compat_30_netbsd32_fhstatvfs1(l, v, retval) 250 struct lwp *l; 251 void *v; 252 register_t *retval; 253 { 254 struct compat_30_netbsd32_fhstatvfs1_args /* { 255 syscallarg(const netbsd32_fhandlep_t) fhp; 256 syscallarg(netbsd32_statvfsp_t) buf; 257 syscallarg(int) flags; 258 } */ *uap = v; 259 struct statvfs *sbuf; 260 struct netbsd32_statvfs *s32; 261 fhandle_t *fh; 262 struct vnode *vp; 263 int error; 264 265 /* 266 * Must be super user 267 */ 268 if ((error = kauth_authorize_generic(l->l_cred, 269 KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0) 270 return error; 271 272 if ((error = vfs_copyinfh_alloc(NETBSD32PTR64(SCARG(uap, fhp)), 273 FHANDLE_SIZE_COMPAT, &fh)) != 0) 274 goto bad; 275 if ((error = vfs_fhtovp(fh, &vp)) != 0) 276 goto bad; 277 278 sbuf = (struct statvfs *)malloc(sizeof(struct statvfs), M_TEMP, 279 M_WAITOK); 280 error = dostatvfs(vp->v_mount, sbuf, l, SCARG(uap, flags), 1); 281 vput(vp); 282 if (error != 0) 283 goto out; 284 285 s32 = (struct netbsd32_statvfs *) 286 malloc(sizeof(struct netbsd32_statvfs), M_TEMP, M_WAITOK); 287 netbsd32_from_statvfs(sbuf, s32); 288 error = copyout(s32, (caddr_t)NETBSD32PTR64(SCARG(uap, buf)), 289 sizeof(struct netbsd32_statvfs)); 290 free(s32, M_TEMP); 291 292 out: 293 free(sbuf, M_TEMP); 294 bad: 295 vfs_copyinfh_free(fh); 296 return (error); 297 } 298 299 int 300 compat_30_netbsd32_socket(l, v, retval) 301 struct lwp *l; 302 void *v; 303 register_t *retval; 304 { 305 struct compat_30_netbsd32_socket_args /* { 306 syscallarg(int) domain; 307 syscallarg(int) type; 308 syscallarg(int) protocol; 309 } */ *uap = v; 310 struct compat_30_sys_socket_args ua; 311 312 NETBSD32TO64_UAP(domain); 313 NETBSD32TO64_UAP(type); 314 NETBSD32TO64_UAP(protocol); 315 return (compat_30_sys_socket(l, &ua, retval)); 316 } 317 318 int 319 compat_30_netbsd32_getfh(l, v, retval) 320 struct lwp *l; 321 void *v; 322 register_t *retval; 323 { 324 struct compat_30_netbsd32_getfh_args /* { 325 syscallarg(const netbsd32_charp) fname; 326 syscallarg(netbsd32_compat_30_fhandlep_t) fhp; 327 } */ *uap = v; 328 struct compat_30_sys_getfh_args ua; 329 330 NETBSD32TOP_UAP(fname, const char); 331 NETBSD32TOP_UAP(fhp, struct compat_30_fhandle); 332 /* Lucky for us a fhandle_t doesn't change sizes */ 333 return (compat_30_sys_getfh(l, &ua, retval)); 334 } 335 336 337 int compat_30_netbsd32_sys___fhstat30(l, v, retval) 338 struct lwp *l; 339 void *v; 340 register_t *retval; 341 { 342 struct compat_30_netbsd32_sys___fhstat30_args /* { 343 syscallarg(const netbsd32_fhandlep_t) fhp; 344 syscallarg(netbsd32_statp_t) sb; 345 } */ *uap = v; 346 struct stat sb; 347 struct netbsd32_stat sb32; 348 int error; 349 fhandle_t *fh; 350 struct vnode *vp; 351 352 /* 353 * Must be super user 354 */ 355 if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, 356 &l->l_acflag))) 357 return error; 358 359 if ((error = vfs_copyinfh_alloc(NETBSD32PTR64(SCARG(uap, fhp)), 360 FHANDLE_SIZE_COMPAT, &fh)) != 0) 361 goto bad; 362 363 if ((error = vfs_fhtovp(fh, &vp)) != 0) 364 goto bad; 365 366 error = vn_stat(vp, &sb, l); 367 vput(vp); 368 if (error) 369 goto bad; 370 netbsd32_from___stat30(&sb, &sb32); 371 error = copyout(&sb32, NETBSD32PTR64(SCARG(uap, sb)), sizeof(sb)); 372 bad: 373 vfs_copyinfh_free(fh); 374 return error; 375 } 376 377 /* 378 * Open a file given a file handle. 379 * 380 * Check permissions, allocate an open file structure, 381 * and call the device open routine if any. 382 */ 383 int 384 compat_30_netbsd32_fhopen(l, v, retval) 385 struct lwp *l; 386 void *v; 387 register_t *retval; 388 { 389 struct compat_30_netbsd32_fhopen_args /* { 390 syscallarg(const fhandle_t *) fhp; 391 syscallarg(int) flags; 392 } */ *uap = v; 393 struct compat_30_sys_fhopen_args ua; 394 395 NETBSD32TOP_UAP(fhp, struct compat_30_fhandle); 396 NETBSD32TO64_UAP(flags); 397 return (compat_30_sys_fhopen(l, &ua, retval)); 398 } 399