1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 43 * 44 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 45 * $Id: sunos_misc.c,v 1.1 1993/10/02 10:24:40 deraadt Exp $ 46 */ 47 48 /* 49 * SunOS compatibility module. 50 * 51 * SunOS system calls that are implemented differently in BSD are 52 * handled here. 53 */ 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/dirent.h> 58 #include <sys/proc.h> 59 #include <sys/file.h> 60 #include <sys/filedesc.h> 61 #include <sys/ioctl.h> 62 #include <sys/malloc.h> 63 #include <sys/mbuf.h> 64 #include <sys/mman.h> 65 #include <sys/mount.h> 66 #include <sys/resource.h> 67 #include <sys/resourcevar.h> 68 #include <sys/signal.h> 69 #include <sys/signalvar.h> 70 #include <sys/socket.h> 71 #include <sys/vnode.h> 72 #include <sys/uio.h> 73 #include <sys/wait.h> 74 75 #include <miscfs/specfs/specdev.h> 76 77 #include <vm/vm.h> 78 79 struct sun_wait4_args { 80 int pid; 81 int *status; 82 int options; 83 struct rusage *rusage; 84 }; 85 sun_wait4(p, uap, retval) 86 struct proc *p; 87 struct sun_wait4_args *uap; 88 int *retval; 89 { 90 91 if (uap->pid == 0) 92 uap->pid = WAIT_ANY; 93 return (wait4(p, uap, retval)); 94 } 95 96 struct sun_creat_args { 97 char *fname; 98 int fmode; 99 }; 100 sun_creat(p, uap, retval) 101 struct proc *p; 102 struct sun_creat_args *uap; 103 int *retval; 104 { 105 struct args { 106 char *fname; 107 int mode; 108 int crtmode; 109 } openuap; 110 111 openuap.fname = uap->fname; 112 openuap.crtmode = uap->fmode; 113 openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 114 return (open(p, &openuap, retval)); 115 } 116 117 struct sun_execv_args { 118 char *fname; 119 char **argp; 120 char **envp; /* pseudo */ 121 }; 122 sun_execv(p, uap, retval) 123 struct proc *p; 124 struct sun_execv_args *uap; 125 int *retval; 126 { 127 128 uap->envp = NULL; 129 return (execve(p, uap, retval)); 130 } 131 132 struct sun_omsync_args { 133 caddr_t addr; 134 int len; 135 int flags; 136 }; 137 sun_omsync(p, uap, retval) 138 struct proc *p; 139 struct sun_omsync_args *uap; 140 int *retval; 141 { 142 143 if (uap->flags) 144 return (EINVAL); 145 return (msync(p, uap, retval)); 146 } 147 148 struct sun_unmount_args { 149 char *name; 150 int flags; /* pseudo */ 151 }; 152 sun_unmount(p, uap, retval) 153 struct proc *p; 154 struct sun_unmount_args *uap; 155 int *retval; 156 { 157 158 uap->flags = 0; 159 return (unmount(p, uap, retval)); 160 } 161 162 static int 163 gettype(tptr) 164 int *tptr; 165 { 166 int type, error; 167 char in[20]; 168 169 if (error = copyinstr((caddr_t)*tptr, in, sizeof in, (u_int *)0)) 170 return (error); 171 if (strcmp(in, "4.2") == 0 || strcmp(in, "ufs") == 0) 172 type = MOUNT_UFS; 173 else if (strcmp(in, "nfs") == 0) 174 type = MOUNT_NFS; 175 else 176 return (EINVAL); 177 *tptr = type; 178 return (0); 179 } 180 181 #define SUNM_RDONLY 0x01 /* mount fs read-only */ 182 #define SUNM_NOSUID 0x02 /* mount fs with setuid disallowed */ 183 #define SUNM_NEWTYPE 0x04 /* type is string (char *), not int */ 184 #define SUNM_GRPID 0x08 /* (bsd semantics; ignored) */ 185 #define SUNM_REMOUNT 0x10 /* update existing mount */ 186 #define SUNM_NOSUB 0x20 /* prevent submounts (rejected) */ 187 #define SUNM_MULTI 0x40 /* (ignored) */ 188 #define SUNM_SYS5 0x80 /* Sys 5-specific semantics (rejected) */ 189 190 struct sun_mount_args { 191 int type; 192 char *dir; 193 int flags; 194 caddr_t data; 195 }; 196 sun_mount(p, uap, retval) 197 struct proc *p; 198 struct sun_mount_args *uap; 199 int *retval; 200 { 201 int oflags = uap->flags, nflags, error; 202 203 if (oflags & (SUNM_NOSUB | SUNM_SYS5)) 204 return (EINVAL); 205 if (oflags & SUNM_NEWTYPE && (error = gettype(&uap->type))) 206 return (error); 207 nflags = 0; 208 if (oflags & SUNM_RDONLY) 209 nflags |= MNT_RDONLY; 210 if (oflags & SUNM_NOSUID) 211 nflags |= MNT_NOSUID; 212 if (oflags & SUNM_REMOUNT) 213 nflags |= MNT_UPDATE; 214 uap->flags = nflags; 215 return (mount(p, uap, retval)); 216 } 217 218 struct sun_sigpending_args { 219 int *mask; 220 }; 221 sun_sigpending(p, uap, retval) 222 struct proc *p; 223 struct sun_sigpending_args *uap; 224 int *retval; 225 { 226 int mask = p->p_sig & p->p_sigmask; 227 228 return (copyout((caddr_t)&mask, (caddr_t)uap->mask, sizeof(int))); 229 } 230 231 /* 232 * Here is the sun layout. (Compare the BSD layout in <sys/dirent.h>.) 233 * We can assume big-endian, so the BSD d_type field is just the high 234 * byte of the SunOS d_namlen field, after adjusting for the extra "long". 235 */ 236 struct sun_dirent { 237 long d_off; 238 u_long d_fileno; 239 u_short d_reclen; 240 u_short d_namlen; 241 char d_name[256]; 242 }; 243 244 /* 245 * Read Sun-style directory entries. We suck them into kernel space so 246 * that they can be massaged before being copied out to user code. Like 247 * SunOS, we squish out `empty' entries. 248 * 249 * This is quite ugly, but what do you expect from compatibility code? 250 */ 251 struct sun_getdents_args { 252 int fd; 253 char *buf; 254 int nbytes; 255 }; 256 sun_getdents(p, uap, retval) 257 struct proc *p; 258 register struct sun_getdents_args *uap; 259 int *retval; 260 { 261 register struct vnode *vp; 262 register caddr_t inp, buf; /* BSD-format */ 263 register int len, reclen; /* BSD-format */ 264 register caddr_t outp; /* Sun-format */ 265 register int resid; /* Sun-format */ 266 struct file *fp; 267 struct uio auio; 268 struct iovec aiov; 269 off_t off; /* true file offset */ 270 long soff; /* Sun file offset */ 271 int buflen, error, eofflag; 272 #define BSD_DIRENT(cp) ((struct dirent *)(cp)) 273 #define SUN_RECLEN(reclen) (reclen + sizeof(long)) 274 275 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) 276 return (error); 277 if ((fp->f_flag & FREAD) == 0) 278 return (EBADF); 279 vp = (struct vnode *)fp->f_data; 280 if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */ 281 return (EINVAL); 282 buflen = min(MAXBSIZE, uap->nbytes); 283 buf = malloc(buflen, M_TEMP, M_WAITOK); 284 VOP_LOCK(vp); 285 off = fp->f_offset; 286 again: 287 aiov.iov_base = buf; 288 aiov.iov_len = buflen; 289 auio.uio_iov = &aiov; 290 auio.uio_iovcnt = 1; 291 auio.uio_rw = UIO_READ; 292 auio.uio_segflg = UIO_SYSSPACE; 293 auio.uio_procp = p; 294 auio.uio_resid = buflen; 295 auio.uio_offset = off; 296 /* 297 * First we read into the malloc'ed buffer, then 298 * we massage it into user space, one record at a time. 299 */ 300 if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag)) 301 goto out; 302 inp = buf; 303 outp = uap->buf; 304 resid = uap->nbytes; 305 if ((len = buflen - auio.uio_resid) == 0) 306 goto eof; 307 for (; len > 0; len -= reclen) { 308 reclen = ((struct dirent *)inp)->d_reclen; 309 if (reclen & 3) 310 panic("sun_getdents"); 311 off += reclen; /* each entry points to next */ 312 if (BSD_DIRENT(inp)->d_fileno == 0) { 313 inp += reclen; /* it is a hole; squish it out */ 314 continue; 315 } 316 if (reclen > len || resid < SUN_RECLEN(reclen)) { 317 /* entry too big for buffer, so just stop */ 318 outp++; 319 break; 320 } 321 /* 322 * Massage in place to make a Sun-shaped dirent (otherwise 323 * we have to worry about touching user memory outside of 324 * the copyout() call). 325 */ 326 BSD_DIRENT(inp)->d_reclen = SUN_RECLEN(reclen); 327 BSD_DIRENT(inp)->d_type = 0; 328 soff = off; 329 if ((error = copyout((caddr_t)&soff, outp, sizeof soff)) != 0 || 330 (error = copyout(inp, outp + sizeof soff, reclen)) != 0) 331 goto out; 332 /* advance past this real entry */ 333 inp += reclen; 334 /* advance output past Sun-shaped entry */ 335 outp += SUN_RECLEN(reclen); 336 resid -= SUN_RECLEN(reclen); 337 } 338 /* if we squished out the whole block, try again */ 339 if (outp == uap->buf) 340 goto again; 341 fp->f_offset = off; /* update the vnode offset */ 342 eof: 343 *retval = uap->nbytes - resid; 344 out: 345 VOP_UNLOCK(vp); 346 free(buf, M_TEMP); 347 return (error); 348 } 349 350 #define MAXDOMAINNAME 64 351 char sun_domainname[MAXDOMAINNAME]; 352 int sun_domainnamelen = 1; 353 354 struct sun_getdomainname_args { 355 char *name; 356 int namelen; 357 }; 358 sun_getdomainname(p, uap, retval) 359 struct proc *p; 360 struct sun_getdomainname_args *uap; 361 int *retval; 362 { 363 register int l = min(uap->namelen, sun_domainnamelen + 1); 364 365 return (copyout(sun_domainname, uap->name, l)); 366 } 367 368 struct sun_setdomainname_args { 369 char *name; 370 int namelen; 371 }; 372 sun_setdomainname(p, uap, retval) 373 struct proc *p; 374 struct sun_setdomainname_args *uap; 375 int *retval; 376 { 377 register int l = uap->namelen, error; 378 379 if (l >= MAXDOMAINNAME) 380 return (EINVAL); /* ??? ENAMETOOLONG? */ 381 if (error = suser(p->p_ucred, &p->p_acflag)) 382 return (error); 383 if (error = copyin(uap->name, sun_domainname, l)) 384 return (error); 385 sun_domainname[l] = 0; 386 return (0); 387 } 388 389 #define SUN_MMAP_MASK 0xf /* mask for SHARED/PRIVATE */ 390 #define SUN_MMAP_CANDO 0x80000000 /* if not, old mmap & cannot handle */ 391 392 #define DEVZERO makedev(3, 12) /* major,minor of /dev/zero */ 393 394 #define SUN_MMAP_SAME (MAP_SHARED|MAP_PRIVATE|MAP_FIXED|MAP_INHERIT) 395 396 struct sun_mmap_args { 397 caddr_t addr; 398 size_t len; 399 int prot; 400 int flags; 401 int fd; 402 long off; /* not off_t! */ 403 quad_t qoff; /* created here and fed to mmap() */ 404 }; 405 sun_mmap(p, uap, retval) 406 register struct proc *p; 407 register struct sun_mmap_args *uap; 408 int *retval; 409 { 410 register int flags; 411 register struct filedesc *fdp; 412 register struct file *fp; 413 register struct vnode *vp; 414 415 /* 416 * Verify the arguments. 417 */ 418 flags = uap->flags; 419 if ((flags & SUN_MMAP_CANDO) == 0) 420 return (EINVAL); 421 if ((flags & SUN_MMAP_MASK) != MAP_SHARED && 422 (flags & SUN_MMAP_MASK) != MAP_PRIVATE) 423 return (EINVAL); 424 flags &= ~SUN_MMAP_CANDO; 425 426 /* 427 * Special case: if fd refers to /dev/zero, map as MAP_ANON. (XXX) 428 */ 429 fdp = p->p_fd; 430 if ((unsigned)uap->fd < fdp->fd_nfiles && /*XXX*/ 431 (fp = fdp->fd_ofiles[uap->fd]) != NULL && /*XXX*/ 432 fp->f_type == DTYPE_VNODE && /*XXX*/ 433 (vp = (struct vnode *)fp->f_data)->v_type == VCHR && /*XXX*/ 434 vp->v_rdev == DEVZERO) { /*XXX*/ 435 flags |= MAP_ANON; 436 uap->fd = -1; 437 } 438 439 /* All done, fix up fields and go. */ 440 uap->flags = flags; 441 uap->qoff = (quad_t)uap->off; 442 return (mmap(p, uap, retval)); 443 } 444 445 #define MC_SYNC 1 446 #define MC_LOCK 2 447 #define MC_UNLOCK 3 448 #define MC_ADVISE 4 449 #define MC_LOCKAS 5 450 #define MC_UNLOCKAS 6 451 452 struct sun_mctl_args { 453 caddr_t addr; 454 size_t len; 455 int func; 456 void *arg; 457 }; 458 sun_mctl(p, uap, retval) 459 register struct proc *p; 460 register struct sun_mctl_args *uap; 461 int *retval; 462 { 463 464 switch (uap->func) { 465 466 case MC_ADVISE: /* ignore for now */ 467 return (0); 468 469 case MC_SYNC: /* translate to msync */ 470 return (msync(p, uap, retval)); 471 472 default: 473 return (EINVAL); 474 } 475 } 476 477 struct sun_setsockopt_args { 478 int s; 479 int level; 480 int name; 481 caddr_t val; 482 int valsize; 483 }; 484 sun_setsockopt(p, uap, retval) 485 struct proc *p; 486 register struct sun_setsockopt_args *uap; 487 int *retval; 488 { 489 struct file *fp; 490 struct mbuf *m = NULL; 491 int error; 492 493 if (error = getsock(p->p_fd, uap->s, &fp)) 494 return (error); 495 #define SO_DONTLINGER (~SO_LINGER) 496 if (uap->name == SO_DONTLINGER) { 497 m = m_get(M_WAIT, MT_SOOPTS); 498 if (m == NULL) 499 return (ENOBUFS); 500 mtod(m, struct linger *)->l_onoff = 0; 501 m->m_len = sizeof(struct linger); 502 return (sosetopt((struct socket *)fp->f_data, uap->level, 503 SO_LINGER, m)); 504 } 505 if (uap->valsize > MLEN) 506 return (EINVAL); 507 if (uap->val) { 508 m = m_get(M_WAIT, MT_SOOPTS); 509 if (m == NULL) 510 return (ENOBUFS); 511 if (error = copyin(uap->val, mtod(m, caddr_t), 512 (u_int)uap->valsize)) { 513 (void) m_free(m); 514 return (error); 515 } 516 m->m_len = uap->valsize; 517 } 518 return (sosetopt((struct socket *)fp->f_data, uap->level, 519 uap->name, m)); 520 } 521 522 struct sun_fchroot_args { 523 int fdes; 524 }; 525 sun_fchroot(p, uap, retval) 526 register struct proc *p; 527 register struct sun_fchroot_args *uap; 528 int *retval; 529 { 530 register struct filedesc *fdp = p->p_fd; 531 register struct vnode *vp; 532 struct file *fp; 533 int error; 534 535 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 536 return (error); 537 if ((error = getvnode(fdp, uap->fdes, &fp)) != 0) 538 return (error); 539 vp = (struct vnode *)fp->f_data; 540 VOP_LOCK(vp); 541 if (vp->v_type != VDIR) 542 error = ENOTDIR; 543 else 544 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 545 VOP_UNLOCK(vp); 546 if (error) 547 return (error); 548 VREF(vp); 549 if (fdp->fd_rdir != NULL) 550 vrele(fdp->fd_rdir); 551 fdp->fd_rdir = vp; 552 return (0); 553 } 554