1 /*        $NetBSD: sunos_misc.c,v 1.177 2021/09/07 11:43:05 riastradh Exp $     */
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *        The Regents of the University of California.  All rights reserved.
6  *
7  * This software was developed by the Computer Systems Engineering group
8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9  * contributed to Berkeley.
10  *
11  * All advertising materials mentioning features or use of this software
12  * must display the following acknowledgement:
13  *        This product includes software developed by the University of
14  *        California, Lawrence Berkeley Laboratory.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  *        @(#)sunos_misc.c    8.1 (Berkeley) 6/18/93
41  *
42  *        Header: sunos_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
43  */
44 
45 /*
46  * SunOS compatibility module.
47  *
48  * SunOS system calls that are implemented differently in BSD are
49  * handled here.
50  */
51 
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: sunos_misc.c,v 1.177 2021/09/07 11:43:05 riastradh Exp $");
54 
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/namei.h>
58 #include <sys/proc.h>
59 #include <sys/dirent.h>
60 #include <sys/file.h>
61 #include <sys/stat.h>
62 #include <sys/filedesc.h>
63 #include <sys/ioctl.h>
64 #include <sys/kernel.h>
65 #include <sys/reboot.h>
66 #include <sys/malloc.h>
67 #include <sys/mbuf.h>
68 #include <sys/mman.h>
69 #include <sys/mount.h>
70 #include <sys/ptrace.h>
71 #include <sys/resource.h>
72 #include <sys/resourcevar.h>
73 #include <sys/signal.h>
74 #include <sys/signalvar.h>
75 #include <sys/socket.h>
76 #include <sys/tty.h>
77 #include <sys/vnode.h>
78 #include <sys/uio.h>
79 #include <sys/wait.h>
80 #include <sys/utsname.h>
81 #include <sys/unistd.h>
82 #include <sys/syscall.h>
83 #include <sys/syscallargs.h>
84 #include <sys/conf.h>
85 #include <sys/socketvar.h>
86 #include <sys/exec.h>
87 #include <sys/swap.h>
88 #include <sys/kauth.h>
89 
90 #include <compat/sys/signal.h>
91 
92 #include <compat/sunos/sunos.h>
93 #include <compat/sunos/sunos_syscallargs.h>
94 #include <compat/common/compat_util.h>
95 #include <compat/sunos/sunos_dirent.h>
96 #include <compat/sys/mount.h>
97 
98 #include <netinet/in.h>
99 
100 #include <miscfs/specfs/specdev.h>
101 
102 #include <nfs/rpcv2.h>
103 #include <nfs/nfsproto.h>
104 #include <nfs/nfs.h>
105 #include <nfs/nfsmount.h>
106 
107 static int sunstatfs(struct statvfs *, void *);
108 
109 int
sunos_sys_stime(struct lwp * l,const struct sunos_sys_stime_args * uap,register_t * retval)110 sunos_sys_stime(struct lwp *l, const struct sunos_sys_stime_args *uap, register_t *retval)
111 {
112           struct timeval tv;
113           int error;
114 
115           error = copyin(SCARG(uap, tp), &tv.tv_sec, sizeof(tv.tv_sec));
116           if (error)
117                     return error;
118           tv.tv_usec = 0;
119 
120           return settimeofday1(&tv, false, NULL, l, true);
121 }
122 
123 int
sunos_sys_wait4(struct lwp * l,const struct sunos_sys_wait4_args * uap,register_t * retval)124 sunos_sys_wait4(struct lwp *l, const struct sunos_sys_wait4_args *uap, register_t *retval)
125 {
126           struct compat_50_sys_wait4_args bsd_ua;
127 
128           SCARG(&bsd_ua, pid) = SCARG(uap, pid) == 0 ? WAIT_ANY : SCARG(uap, pid);
129           SCARG(&bsd_ua, status) = SCARG(uap, status);
130           SCARG(&bsd_ua, options) = SCARG(uap, options);
131           SCARG(&bsd_ua, rusage) = SCARG(uap, rusage);
132 
133           return (compat_50_sys_wait4(l, &bsd_ua, retval));
134 }
135 
136 int
sunos_sys_creat(struct lwp * l,const struct sunos_sys_creat_args * uap,register_t * retval)137 sunos_sys_creat(struct lwp *l, const struct sunos_sys_creat_args *uap, register_t *retval)
138 {
139           struct sys_open_args ouap;
140 
141           SCARG(&ouap, path) = SCARG(uap, path);
142           SCARG(&ouap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
143           SCARG(&ouap, mode) = SCARG(uap, mode);
144 
145           return (sys_open(l, &ouap, retval));
146 }
147 
148 int
sunos_sys_execv(struct lwp * l,const struct sunos_sys_execv_args * uap,register_t * retval)149 sunos_sys_execv(struct lwp *l, const struct sunos_sys_execv_args *uap, register_t *retval)
150 {
151           /* {
152                     syscallarg(const char *) path;
153                     syscallarg(char **) argv;
154           } */
155           struct sys_execve_args ap;
156 
157           SCARG(&ap, path) = SCARG(uap, path);
158           SCARG(&ap, argp) = SCARG(uap, argp);
159           SCARG(&ap, envp) = NULL;
160 
161           return (sys_execve(l, &ap, retval));
162 }
163 
164 int
sunos_sys_execve(struct lwp * l,const struct sunos_sys_execve_args * uap,register_t * retval)165 sunos_sys_execve(struct lwp *l, const struct sunos_sys_execve_args *uap, register_t *retval)
166 {
167           /* {
168                     syscallarg(const char *) path;
169                     syscallarg(char **) argv;
170                     syscallarg(char **) envp;
171           } */
172           struct sys_execve_args ap;
173 
174           SCARG(&ap, path) = SCARG(uap, path);
175           SCARG(&ap, argp) = SCARG(uap, argp);
176           SCARG(&ap, envp) = SCARG(uap, envp);
177 
178           return (sys_execve(l, &ap, retval));
179 }
180 
181 int
sunos_sys_omsync(struct lwp * l,const struct sunos_sys_omsync_args * uap,register_t * retval)182 sunos_sys_omsync(struct lwp *l, const struct sunos_sys_omsync_args *uap, register_t *retval)
183 {
184           struct sys___msync13_args ouap;
185 
186           SCARG(&ouap, addr) = SCARG(uap, addr);
187           SCARG(&ouap, len) = SCARG(uap, len);
188           SCARG(&ouap, flags) = SCARG(uap, flags);
189 
190           return (sys___msync13(l, &ouap, retval));
191 }
192 
193 int
sunos_sys_unmount(struct lwp * l,const struct sunos_sys_unmount_args * uap,register_t * retval)194 sunos_sys_unmount(struct lwp *l, const struct sunos_sys_unmount_args *uap, register_t *retval)
195 {
196           struct sys_unmount_args ouap;
197 
198           SCARG(&ouap, path) = SCARG(uap, path);
199           SCARG(&ouap, flags) = 0;
200 
201           return (sys_unmount(l, &ouap, retval));
202 }
203 
204 /*
205  * Conversion table for SunOS NFS mount flags.
206  */
207 static struct {
208           int       sun_flg;
209           int       bsd_flg;
210 } sunnfs_flgtab[] = {
211           { SUNNFS_SOFT,                NFSMNT_SOFT },
212           { SUNNFS_WSIZE,               NFSMNT_WSIZE },
213           { SUNNFS_RSIZE,               NFSMNT_RSIZE },
214           { SUNNFS_TIMEO,               NFSMNT_TIMEO },
215           { SUNNFS_RETRANS,   NFSMNT_RETRANS },
216           { SUNNFS_HOSTNAME,  0 },                          /* Ignored */
217           { SUNNFS_INT,                 NFSMNT_INT },
218           { SUNNFS_NOAC,                0 },                          /* Ignored */
219           { SUNNFS_ACREGMIN,  0 },                          /* Ignored */
220           { SUNNFS_ACREGMAX,  0 },                          /* Ignored */
221           { SUNNFS_ACDIRMIN,  0 },                          /* Ignored */
222           { SUNNFS_ACDIRMAX,  0 },                          /* Ignored */
223           { SUNNFS_SECURE,    0 },                          /* Ignored */
224           { SUNNFS_NOCTO,               0 },                          /* Ignored */
225           { SUNNFS_POSIX,               0 }                           /* Ignored */
226 };
227 
228 int
sunos_sys_mount(struct lwp * l,const struct sunos_sys_mount_args * uap,register_t * retval)229 sunos_sys_mount(struct lwp *l, const struct sunos_sys_mount_args *uap, register_t *retval)
230 {
231           int oflags = SCARG(uap, flags), nflags, error;
232           char fsname[MFSNAMELEN];
233           register_t dummy;
234 
235           if (oflags & (SUNM_NOSUB | SUNM_SYS5))
236                     return (EINVAL);
237           if ((oflags & SUNM_NEWTYPE) == 0)
238                     return (EINVAL);
239           nflags = 0;
240           if (oflags & SUNM_RDONLY)
241                     nflags |= MNT_RDONLY;
242           if (oflags & SUNM_NOSUID)
243                     nflags |= MNT_NOSUID;
244           if (oflags & SUNM_REMOUNT)
245                     nflags |= MNT_UPDATE;
246 
247           error = copyinstr(SCARG(uap, type), fsname, sizeof fsname, NULL);
248           if (error)
249                     return (error);
250 
251           if (strcmp(fsname, "nfs") == 0) {
252                     struct sunos_nfs_args sna;
253                     struct nfs_args na;
254                     int n;
255 
256                     error = copyin(SCARG(uap, data), &sna, sizeof sna);
257                     if (error)
258                               return (error);
259                     /* sa.sa_len = sizeof(sain); */
260                     na.version = NFS_ARGSVERSION;
261                     na.addr = (void *)sna.addr;
262                     na.addrlen = sizeof(struct sockaddr);
263                     na.sotype = SOCK_DGRAM;
264                     na.proto = IPPROTO_UDP;
265                     na.fh = sna.fh;
266                     na.fhsize = NFSX_V2FH;
267                     na.flags = 0;
268                     n = sizeof(sunnfs_flgtab) / sizeof(sunnfs_flgtab[0]);
269                     while (--n >= 0)
270                               if (sna.flags & sunnfs_flgtab[n].sun_flg)
271                                         na.flags |= sunnfs_flgtab[n].bsd_flg;
272                     na.wsize = sna.wsize;
273                     na.rsize = sna.rsize;
274                     if (na.flags & NFSMNT_RSIZE) {
275                               na.flags |= NFSMNT_READDIRSIZE;
276                               na.readdirsize = na.rsize;
277                     }
278                     na.timeo = sna.timeo;
279                     na.retrans = sna.retrans;
280 #ifdef __arch64__
281                     /* XXX */
282                     na.hostname = (char *)(intptr_t)sna.hostname;
283 #else
284                     na.hostname = sna.hostname;
285 #endif
286                     return do_sys_mount(l, "nfs", UIO_SYSSPACE,
287                         SCARG(uap, dir), nflags, &na,
288                         UIO_SYSSPACE, sizeof na, &dummy);
289           }
290 
291           if (strcmp(fsname, "4.2") == 0)
292                     strcpy(fsname, "ffs");
293 
294           return do_sys_mount(l, fsname, UIO_SYSSPACE,
295               SCARG(uap, dir), nflags, SCARG(uap, data),
296               UIO_USERSPACE, 0, &dummy);
297 }
298 
299 int
async_daemon(struct lwp * l,const void * v,register_t * retval)300 async_daemon(struct lwp *l, const void *v, register_t *retval)
301 {
302 
303           return kpause("fakeniod", false, 0, NULL);
304 }
305 
306 void      native_to_sunos_sigset(const sigset_t *, int *);
307 void      sunos_to_native_sigset(const int, sigset_t *);
308 
309 inline void
native_to_sunos_sigset(const sigset_t * ss,int * mask)310 native_to_sunos_sigset(const sigset_t *ss, int *mask)
311 {
312 
313           *mask = ss->__bits[0];
314 }
315 
316 inline void
sunos_to_native_sigset(const int mask,sigset_t * ss)317 sunos_to_native_sigset(const int mask, sigset_t *ss)
318 {
319 
320           memset(ss, 0, sizeof(*ss));
321           ss->__bits[0] = mask;
322           ss->__bits[1] = 0;
323           ss->__bits[2] = 0;
324           ss->__bits[3] = 0;
325 }
326 
327 int
sunos_sys_sigpending(struct lwp * l,const struct sunos_sys_sigpending_args * uap,register_t * retval)328 sunos_sys_sigpending(struct lwp *l, const struct sunos_sys_sigpending_args *uap, register_t *retval)
329 {
330           sigset_t ss;
331           int mask;
332 
333           sigpending1(l, &ss);
334           native_to_sunos_sigset(&ss, &mask);
335 
336           return (copyout((void *)&mask, (void *)SCARG(uap, mask), sizeof(int)));
337 }
338 
339 int
sunos_sys_sigsuspend(struct lwp * l,const struct sunos_sys_sigsuspend_args * uap,register_t * retval)340 sunos_sys_sigsuspend(struct lwp *l, const struct sunos_sys_sigsuspend_args *uap, register_t *retval)
341 {
342           /* {
343                     syscallarg(int) mask;
344           } */
345           int mask;
346           sigset_t ss;
347 
348           mask = SCARG(uap, mask);
349           sunos_to_native_sigset(mask, &ss);
350           return (sigsuspend1(l, &ss));
351 }
352 
353 /*
354  * Read Sun-style directory entries.  We suck them into kernel space so
355  * that they can be massaged before being copied out to user code.  Like
356  * SunOS, we squish out `empty' entries.
357  *
358  * This is quite ugly, but what do you expect from compatibility code?
359  */
360 int
sunos_sys_getdents(struct lwp * l,const struct sunos_sys_getdents_args * uap,register_t * retval)361 sunos_sys_getdents(struct lwp *l, const struct sunos_sys_getdents_args *uap, register_t *retval)
362 {
363           struct dirent *bdp;
364           struct vnode *vp;
365           char *inp, *buf;    /* BSD-format */
366           int len, reclen;    /* BSD-format */
367           char *outp;                   /* Sun-format */
368           int resid, sunos_reclen;/* Sun-format */
369           struct file *fp;
370           struct uio auio;
371           struct iovec aiov;
372           struct sunos_dirent idb;
373           off_t off;                              /* true file offset */
374           int buflen, error, eofflag;
375           off_t *cookiebuf, *cookie;
376           int ncookies;
377 
378           if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
379                     return (error);
380 
381           if ((fp->f_flag & FREAD) == 0) {
382                     error = EBADF;
383                     goto out1;
384           }
385 
386           vp = fp->f_vnode;
387           if (vp->v_type != VDIR) {
388                     error = EINVAL;
389                     goto out1;
390           }
391 
392           buflen = uimin(MAXBSIZE, SCARG(uap, nbytes));
393           buf = malloc(buflen, M_TEMP, M_WAITOK);
394           vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
395           off = fp->f_offset;
396 again:
397           aiov.iov_base = buf;
398           aiov.iov_len = buflen;
399           auio.uio_iov = &aiov;
400           auio.uio_iovcnt = 1;
401           auio.uio_rw = UIO_READ;
402           auio.uio_resid = buflen;
403           auio.uio_offset = off;
404           UIO_SETUP_SYSSPACE(&auio);
405           /*
406            * First we read into the malloc'ed buffer, then
407            * we massage it into user space, one record at a time.
408            */
409           error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
410               &ncookies);
411           if (error)
412                     goto out;
413 
414           inp = buf;
415           outp = SCARG(uap, buf);
416           resid = SCARG(uap, nbytes);
417           if ((len = buflen - auio.uio_resid) == 0)
418                     goto eof;
419 
420           for (cookie = cookiebuf; len > 0; len -= reclen) {
421                     bdp = (struct dirent *)inp;
422                     reclen = bdp->d_reclen;
423                     if (reclen & 3) {
424                               error = EIO;
425                               goto out;
426                     }
427                     if ((*cookie >> 32) != 0) {
428                               compat_offseterr(vp, "sunos_getdents");
429                               error = EINVAL;
430                               goto out;
431                     }
432                     if (bdp->d_fileno == 0) {
433                               inp += reclen;      /* it is a hole; squish it out */
434                               if (cookie)
435                                         off = *cookie++;
436                               else
437                                         off += reclen;
438                               continue;
439                     }
440                     memset(&idb, 0, sizeof(idb));
441                     sunos_reclen = SUNOS_RECLEN(&idb, bdp->d_namlen);
442                     if (reclen > len || resid < sunos_reclen) {
443                               /* entry too big for buffer, so just stop */
444                               outp++;
445                               break;
446                     }
447                     if (cookie)
448                               off = *cookie++;    /* each entry points to next */
449                     else
450                               off += reclen;
451                     /*
452                      * Massage in place to make a Sun-shaped dirent (otherwise
453                      * we have to worry about touching user memory outside of
454                      * the copyout() call).
455                      */
456                     idb.d_fileno = bdp->d_fileno;
457                     idb.d_off = off;
458                     idb.d_reclen = sunos_reclen;
459                     idb.d_namlen = bdp->d_namlen;
460                     strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
461                     if ((error = copyout((void *)&idb, outp, sunos_reclen)) != 0)
462                               goto out;
463                     /* advance past this real entry */
464                     inp += reclen;
465                     /* advance output past Sun-shaped entry */
466                     outp += sunos_reclen;
467                     resid -= sunos_reclen;
468           }
469 
470           /* if we squished out the whole block, try again */
471           if (outp == SCARG(uap, buf)) {
472                     if (cookiebuf)
473                               free(cookiebuf, M_TEMP);
474                     cookiebuf = NULL;
475                     goto again;
476           }
477           fp->f_offset = off;           /* update the vnode offset */
478 
479 eof:
480           *retval = SCARG(uap, nbytes) - resid;
481 out:
482           VOP_UNLOCK(vp);
483           free(cookiebuf, M_TEMP);
484           free(buf, M_TEMP);
485  out1:
486           fd_putfile(SCARG(uap, fd));
487           return (error);
488 }
489 
490 #define   SUNOS__MAP_NEW      0x80000000          /* if not, old mmap & cannot handle */
491 
492 int
sunos_sys_mmap(struct lwp * l,const struct sunos_sys_mmap_args * uap,register_t * retval)493 sunos_sys_mmap(struct lwp *l, const struct sunos_sys_mmap_args *uap, register_t *retval)
494 {
495           struct sys_mmap_args ouap;
496 
497           /*
498            * Verify the arguments.
499            */
500           if (SCARG(uap, prot) & ~(PROT_READ|PROT_WRITE|PROT_EXEC))
501                     return (EINVAL);                        /* XXX still needed? */
502 
503           if ((SCARG(uap, flags) & SUNOS__MAP_NEW) == 0)
504                     return (EINVAL);
505 
506           SCARG(&ouap, flags) = SCARG(uap, flags) & ~SUNOS__MAP_NEW;
507           SCARG(&ouap, addr) = SCARG(uap, addr);
508           SCARG(&ouap, len) = SCARG(uap, len);
509           SCARG(&ouap, prot) = SCARG(uap, prot);
510           SCARG(&ouap, fd) = SCARG(uap, fd);
511           SCARG(&ouap, pos) = SCARG(uap, pos);
512 
513           return (sys_mmap(l, &ouap, retval));
514 }
515 
516 #define   MC_SYNC             1
517 #define   MC_LOCK             2
518 #define   MC_UNLOCK 3
519 #define   MC_ADVISE 4
520 #define   MC_LOCKAS 5
521 #define   MC_UNLOCKAS         6
522 
523 int
sunos_sys_mctl(struct lwp * l,const struct sunos_sys_mctl_args * uap,register_t * retval)524 sunos_sys_mctl(struct lwp *l, const struct sunos_sys_mctl_args *uap, register_t *retval)
525 {
526 
527           switch (SCARG(uap, func)) {
528           case MC_ADVISE:               /* ignore for now */
529                     return (0);
530           case MC_SYNC:                 /* translate to msync */
531                     return (sys___msync13(l, (const void *)uap, retval));
532           default:
533                     return (EINVAL);
534           }
535 }
536 
537 int
sunos_sys_setsockopt(struct lwp * l,const struct sunos_sys_setsockopt_args * uap,register_t * retval)538 sunos_sys_setsockopt(struct lwp *l, const struct sunos_sys_setsockopt_args *uap, register_t *retval)
539 {
540           struct sockopt sopt;
541           struct socket *so;
542           int name = SCARG(uap, name);
543           int error;
544 
545           /* fd_getsock() will use the descriptor for us */
546           if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
547                     return (error);
548 #define   SO_DONTLINGER (~SO_LINGER)
549           if (name == SO_DONTLINGER) {
550                     struct linger lg;
551 
552                     lg.l_onoff = 0;
553                     error = so_setsockopt(l, so, SCARG(uap, level), SO_LINGER,
554                         &lg, sizeof(lg));
555                     goto out;
556           }
557           if (SCARG(uap, level) == IPPROTO_IP) {
558 #define             SUNOS_IP_MULTICAST_IF                   2
559 #define             SUNOS_IP_MULTICAST_TTL                  3
560 #define             SUNOS_IP_MULTICAST_LOOP                 4
561 #define             SUNOS_IP_ADD_MEMBERSHIP                 5
562 #define             SUNOS_IP_DROP_MEMBERSHIP      6
563                     static const int ipoptxlat[] = {
564                               IP_MULTICAST_IF,
565                               IP_MULTICAST_TTL,
566                               IP_MULTICAST_LOOP,
567                               IP_ADD_MEMBERSHIP,
568                               IP_DROP_MEMBERSHIP
569                     };
570                     if (name >= SUNOS_IP_MULTICAST_IF &&
571                         name <= SUNOS_IP_DROP_MEMBERSHIP) {
572                               name = ipoptxlat[name - SUNOS_IP_MULTICAST_IF];
573                     }
574           }
575           if ((unsigned)SCARG(uap, valsize) > MLEN) {
576                     error = EINVAL;
577                     goto out;
578           }
579           sockopt_init(&sopt, SCARG(uap, level), name, SCARG(uap, valsize));
580           if (SCARG(uap, val)) {
581                     error = copyin(SCARG(uap, val), sopt.sopt_data,
582                         (u_int)SCARG(uap, valsize));
583           }
584           if (error == 0)
585                     error = sosetopt(so, &sopt);
586           sockopt_destroy(&sopt);
587  out:
588           fd_putfile(SCARG(uap, s));
589           return (error);
590 }
591 
592 static inline int sunos_sys_socket_common(struct lwp *, register_t *,
593                                                         int type);
594 static inline int
sunos_sys_socket_common(struct lwp * l,register_t * retval,int type)595 sunos_sys_socket_common(struct lwp *l, register_t *retval, int type)
596 {
597           struct socket *so;
598           int error, fd;
599 
600           /* fd_getsock() will use the descriptor for us */
601           fd = (int)*retval;
602           if ((error = fd_getsock(fd, &so)) == 0) {
603                     if (type == SOCK_DGRAM)
604                               so->so_options |= SO_BROADCAST;
605                     fd_putfile(fd);
606           }
607           return (error);
608 }
609 
610 int
sunos_sys_socket(struct lwp * l,const struct sunos_sys_socket_args * uap,register_t * retval)611 sunos_sys_socket(struct lwp *l, const struct sunos_sys_socket_args *uap, register_t *retval)
612 {
613           /* {
614                     syscallarg(int) domain;
615                     syscallarg(int) type;
616                     syscallarg(int) protocol;
617           } */
618           int error;
619 
620           error = compat_30_sys_socket(l, (const void *)uap, retval);
621           if (error)
622                     return (error);
623           return sunos_sys_socket_common(l, retval, SCARG(uap, type));
624 }
625 
626 int
sunos_sys_socketpair(struct lwp * l,const struct sunos_sys_socketpair_args * uap,register_t * retval)627 sunos_sys_socketpair(struct lwp *l, const struct sunos_sys_socketpair_args *uap, register_t *retval)
628 {
629           /* {
630                     syscallarg(int) domain;
631                     syscallarg(int) type;
632                     syscallarg(int) protocol;
633                     syscallarg(int *) rsv;
634           } */
635           int error;
636 
637           error = sys_socketpair(l, (const void *)uap, retval);
638           if (error)
639                     return (error);
640           return sunos_sys_socket_common(l, retval, SCARG(uap, type));
641 }
642 
643 /*
644  * XXX: This needs cleaning up.
645  */
646 int
sunos_sys_auditsys(struct lwp * l,const struct sunos_sys_auditsys_args * uap,register_t * retval)647 sunos_sys_auditsys(struct lwp *l, const struct sunos_sys_auditsys_args *uap, register_t *retval)
648 {
649           return 0;
650 }
651 
652 int
sunos_sys_uname(struct lwp * l,const struct sunos_sys_uname_args * uap,register_t * retval)653 sunos_sys_uname(struct lwp *l, const struct sunos_sys_uname_args *uap, register_t *retval)
654 {
655           struct sunos_utsname sut;
656 
657           memset(&sut, 0, sizeof(sut));
658 
659           strlcpy(sut.sysname, ostype, sizeof(sut.sysname));
660           strlcpy(sut.nodename, hostname, sizeof(sut.nodename));
661           strlcpy(sut.release, osrelease, sizeof(sut.release));
662           strlcpy(sut.version, "1", sizeof(sut.version));
663           strlcpy(sut.machine, machine, sizeof(sut.machine));
664 
665           return copyout(&sut, SCARG(uap, name), sizeof(sut));
666 }
667 
668 int
sunos_sys_setpgrp(struct lwp * l,const struct sunos_sys_setpgrp_args * uap,register_t * retval)669 sunos_sys_setpgrp(struct lwp *l, const struct sunos_sys_setpgrp_args *uap, register_t *retval)
670 {
671           struct proc *p = l->l_proc;
672 
673           /*
674            * difference to our setpgid call is to include backwards
675            * compatibility to pre-setsid() binaries. Do setsid()
676            * instead of setpgid() in those cases where the process
677            * tries to create a new session the old way.
678            */
679           if (!SCARG(uap, pgid) &&
680               (!SCARG(uap, pid) || SCARG(uap, pid) == p->p_pid))
681                     return sys_setsid(l, NULL, retval);
682           else
683                     return sys_setpgid(l, (const void *)uap, retval);
684 }
685 
686 int
sunos_sys_open(struct lwp * l,const struct sunos_sys_open_args * uap,register_t * retval)687 sunos_sys_open(struct lwp *l, const struct sunos_sys_open_args *uap, register_t *retval)
688 {
689           struct proc *p = l->l_proc;
690           struct sys_open_args open_ua;
691           int smode, nmode;
692           int noctty;
693           int ret;
694 
695           /* convert mode into NetBSD mode */
696           smode = SCARG(uap, flags);
697           noctty = smode & 0x8000;
698           nmode =   smode &
699                     (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800);
700           nmode |= ((smode & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0);
701           nmode |= ((smode & 0x0080) ? O_SHLOCK : 0);
702           nmode |= ((smode & 0x0100) ? O_EXLOCK : 0);
703           nmode |= ((smode & 0x2000) ? O_FSYNC : 0);
704 
705           SCARG(&open_ua, path) = SCARG(uap, path);
706           SCARG(&open_ua, flags) = nmode;
707           SCARG(&open_ua, mode) = SCARG(uap, mode);
708           ret = sys_open(l, &open_ua, retval);
709 
710           /* XXXSMP */
711           if (!ret && !noctty && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) {
712                     file_t *fp;
713                     int fd;
714 
715                     fd = (int)*retval;
716                     fp = fd_getfile(fd);
717 
718                     /* ignore any error, just give it a try */
719                     if (fp != NULL) {
720                               if (fp->f_type == DTYPE_VNODE)
721                                         (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, NULL);
722                               fd_putfile(fd);
723                     }
724           }
725           return ret;
726 }
727 
728 int
sunos_sys_ustat(struct lwp * l,const struct sunos_sys_ustat_args * uap,register_t * retval)729 sunos_sys_ustat(struct lwp *l, const struct sunos_sys_ustat_args *uap, register_t *retval)
730 {
731           struct sunos_ustat us;
732           int error;
733 
734           memset(&us, 0, sizeof us);
735 
736           /*
737            * XXX: should set f_tfree and f_tinode at least
738            * How do we translate dev -> fstat? (and then to sunos_ustat)
739            */
740 
741           if ((error = copyout(&us, SCARG(uap, buf), sizeof us)) != 0)
742                     return (error);
743           return 0;
744 }
745 
746 int
sunos_sys_quotactl(struct lwp * l,const struct sunos_sys_quotactl_args * uap,register_t * retval)747 sunos_sys_quotactl(struct lwp *l, const struct sunos_sys_quotactl_args *uap, register_t *retval)
748 {
749 
750           return EINVAL;
751 }
752 
753 int
sunos_sys_vhangup(struct lwp * l,const void * v,register_t * retval)754 sunos_sys_vhangup(struct lwp *l, const void *v, register_t *retval)
755 {
756           struct proc *p = l->l_proc;
757           struct session *sp = p->p_session;
758 
759           if (sp->s_ttyvp == 0)
760                     return 0;
761 
762           if (sp->s_ttyp && sp->s_ttyp->t_session == sp && sp->s_ttyp->t_pgrp)
763                     pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
764 
765           (void) ttywait(sp->s_ttyp);
766           if (sp->s_ttyvp)
767                     VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
768           if (sp->s_ttyvp)
769                     vrele(sp->s_ttyvp);
770           sp->s_ttyvp = NULL;
771 
772           return 0;
773 }
774 
775 static int
sunstatfs(struct statvfs * sp,void * buf)776 sunstatfs(struct statvfs *sp, void *buf)
777 {
778           struct sunos_statfs ssfs;
779 
780           memset(&ssfs, 0, sizeof ssfs);
781           ssfs.f_type = 0;
782           ssfs.f_bsize = sp->f_bsize;
783           ssfs.f_blocks = sp->f_blocks;
784           ssfs.f_bfree = sp->f_bfree;
785           ssfs.f_bavail = sp->f_bavail;
786           ssfs.f_files = sp->f_files;
787           ssfs.f_ffree = sp->f_ffree;
788           ssfs.f_fsid = sp->f_fsidx;
789           return copyout((void *)&ssfs, buf, sizeof ssfs);
790 }
791 
792 int
sunos_sys_statfs(struct lwp * l,const struct sunos_sys_statfs_args * uap,register_t * retval)793 sunos_sys_statfs(struct lwp *l, const struct sunos_sys_statfs_args *uap, register_t *retval)
794 {
795           struct mount *mp;
796           struct statvfs *sp;
797           int error;
798           struct vnode *vp;
799 
800           error = namei_simple_user(SCARG(uap, path),
801                                         NSM_FOLLOW_TRYEMULROOT, &vp);
802           if (error != 0)
803                     return (error);
804           mp = vp->v_mount;
805           sp = &mp->mnt_stat;
806           vrele(vp);
807           if ((error = VFS_STATVFS(mp, sp)) != 0)
808                     return (error);
809           sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
810           return sunstatfs(sp, (void *)SCARG(uap, buf));
811 }
812 
813 int
sunos_sys_fstatfs(struct lwp * l,const struct sunos_sys_fstatfs_args * uap,register_t * retval)814 sunos_sys_fstatfs(struct lwp *l, const struct sunos_sys_fstatfs_args *uap, register_t *retval)
815 {
816           file_t *fp;
817           struct mount *mp;
818           struct statvfs *sp;
819           int error;
820 
821           /* fd_getvnode() will use the descriptor for us */
822           if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
823                     return (error);
824           mp = fp->f_vnode->v_mount;
825           sp = &mp->mnt_stat;
826           if ((error = VFS_STATVFS(mp, sp)) != 0)
827                     goto out;
828           sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
829           error = sunstatfs(sp, (void *)SCARG(uap, buf));
830  out:
831           fd_putfile(SCARG(uap, fd));
832           return (error);
833 }
834 
835 int
sunos_sys_exportfs(struct lwp * l,const struct sunos_sys_exportfs_args * uap,register_t * retval)836 sunos_sys_exportfs(struct lwp *l, const struct sunos_sys_exportfs_args *uap, register_t *retval)
837 {
838           /*
839            * XXX: should perhaps translate into a mount(2)
840            * with MOUNT_EXPORT?
841            */
842           return 0;
843 }
844 
845 int
sunos_sys_mknod(struct lwp * l,const struct sunos_sys_mknod_args * uap,register_t * retval)846 sunos_sys_mknod(struct lwp *l, const struct sunos_sys_mknod_args *uap, register_t *retval)
847 {
848           struct sys_mkfifo_args fifo_ua;
849 
850           if (S_ISFIFO(SCARG(uap, mode))) {
851                     SCARG(&fifo_ua, path) = SCARG(uap, path);
852                     SCARG(&fifo_ua, mode) = SCARG(uap, mode);
853                     return sys_mkfifo(l, &fifo_ua, retval);
854           }
855 
856           return compat_50_sys_mknod(l,
857               (const struct compat_50_sys_mknod_args *)uap, retval);
858 }
859 
860 #define SUNOS_SC_ARG_MAX      1
861 #define SUNOS_SC_CHILD_MAX    2
862 #define SUNOS_SC_CLK_TCK      3
863 #define SUNOS_SC_NGROUPS_MAX  4
864 #define SUNOS_SC_OPEN_MAX     5
865 #define SUNOS_SC_JOB_CONTROL  6
866 #define SUNOS_SC_SAVED_IDS    7
867 #define SUNOS_SC_VERSION      8
868 
869 int
sunos_sys_sysconf(struct lwp * l,const struct sunos_sys_sysconf_args * uap,register_t * retval)870 sunos_sys_sysconf(struct lwp *l, const struct sunos_sys_sysconf_args *uap, register_t *retval)
871 {
872 
873           switch(SCARG(uap, name)) {
874           case SUNOS_SC_ARG_MAX:
875                     *retval = ARG_MAX;
876                     break;
877           case SUNOS_SC_CHILD_MAX:
878                     *retval = maxproc;
879                     break;
880           case SUNOS_SC_CLK_TCK:
881                     *retval = 60;                 /* should this be `hz', ie. 100? */
882                     break;
883           case SUNOS_SC_NGROUPS_MAX:
884                     *retval = NGROUPS_MAX;
885                     break;
886           case SUNOS_SC_OPEN_MAX:
887                     *retval = maxfiles;
888                     break;
889           case SUNOS_SC_JOB_CONTROL:
890                     *retval = 1;
891                     break;
892           case SUNOS_SC_SAVED_IDS:
893 #ifdef _POSIX_SAVED_IDS
894                     *retval = 1;
895 #else
896                     *retval = 0;
897 #endif
898                     break;
899           case SUNOS_SC_VERSION:
900                     *retval = 198808;
901                     break;
902           default:
903                     return EINVAL;
904           }
905           return 0;
906 }
907 
908 #define SUNOS_RLIMIT_NOFILE   6         /* Other RLIMIT_* are the same */
909 #define SUNOS_RLIM_NLIMITS    7
910 
911 int
sunos_sys_getrlimit(struct lwp * l,const struct sunos_sys_getrlimit_args * uap,register_t * retval)912 sunos_sys_getrlimit(struct lwp *l, const struct sunos_sys_getrlimit_args *uap, register_t *retval)
913 {
914           struct compat_43_sys_getrlimit_args ua_43;
915 
916           SCARG(&ua_43, which) = SCARG(uap, which);
917           SCARG(&ua_43, rlp) = SCARG(uap, rlp);
918 
919           if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS)
920                     return EINVAL;
921 
922           if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE)
923                     SCARG(&ua_43, which) = RLIMIT_NOFILE;
924 
925           return compat_43_sys_getrlimit(l, &ua_43, retval);
926 }
927 
928 int
sunos_sys_setrlimit(struct lwp * l,const struct sunos_sys_setrlimit_args * uap,register_t * retval)929 sunos_sys_setrlimit(struct lwp *l, const struct sunos_sys_setrlimit_args *uap, register_t *retval)
930 {
931           struct compat_43_sys_setrlimit_args ua_43;
932 
933           SCARG(&ua_43, which) = SCARG(uap, which);
934           SCARG(&ua_43, rlp) = SCARG(uap, rlp);
935 
936           if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS)
937                     return EINVAL;
938 
939           if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE)
940                     SCARG(&ua_43, which) = RLIMIT_NOFILE;
941 
942           return compat_43_sys_setrlimit(l, &ua_43, retval);
943 }
944 
945 /* for the m68k machines */
946 #ifndef PT_GETFPREGS
947 #define PT_GETFPREGS -1
948 #endif
949 #ifndef PT_SETFPREGS
950 #define PT_SETFPREGS -1
951 #endif
952 
953 static const int sreq2breq[] = {
954           PT_TRACE_ME,    PT_READ_I,      PT_READ_D,      -1,
955           PT_WRITE_I,     PT_WRITE_D,     -1,             PT_CONTINUE,
956           PT_KILL,        -1,             PT_ATTACH,      PT_DETACH,
957           PT_GETREGS,     PT_SETREGS,     PT_GETFPREGS,   PT_SETFPREGS
958 };
959 static const int nreqs = sizeof(sreq2breq) / sizeof(sreq2breq[0]);
960 
961 int
sunos_sys_ptrace(struct lwp * l,const struct sunos_sys_ptrace_args * uap,register_t * retval)962 sunos_sys_ptrace(struct lwp *l, const struct sunos_sys_ptrace_args *uap, register_t *retval)
963 {
964           struct sys_ptrace_args pa;
965           int req;
966 
967 #define   sys_ptrace sysent[SYS_ptrace].sy_call
968           if (sys_ptrace == sys_nosys)
969                     return ENOSYS;
970 
971           req = SCARG(uap, req);
972 
973           if (req < 0 || req >= nreqs)
974                     return (EINVAL);
975 
976           req = sreq2breq[req];
977           if (req == -1)
978                     return (EINVAL);
979 
980           SCARG(&pa, req) = req;
981           SCARG(&pa, pid) = (pid_t)SCARG(uap, pid);
982           SCARG(&pa, addr) = (void *)SCARG(uap, addr);
983           SCARG(&pa, data) = SCARG(uap, data);
984 
985           return sys_ptrace(l, &pa, retval);
986 }
987 
988 /*
989  * SunOS reboot system call (for compatibility).
990  * Sun lets you pass in a boot string which the PROM
991  * saves and provides to the next boot program.
992  */
993 
994 #define SUNOS_RB_ASKNAME      0x001
995 #define SUNOS_RB_SINGLE       0x002
996 #define SUNOS_RB_NOSYNC                 0x004
997 #define SUNOS_RB_HALT                   0x008
998 #define SUNOS_RB_DUMP                   0x080
999 #define   SUNOS_RB_STRING               0x200
1000 
1001 static struct sunos_howto_conv {
1002           int sun_howto;
1003           int bsd_howto;
1004 } sunos_howto_conv[] = {
1005           { SUNOS_RB_ASKNAME, RB_ASKNAME },
1006           { SUNOS_RB_SINGLE,  RB_SINGLE },
1007           { SUNOS_RB_NOSYNC,  RB_NOSYNC },
1008           { SUNOS_RB_HALT,    RB_HALT },
1009           { SUNOS_RB_DUMP,    RB_DUMP },
1010           { SUNOS_RB_STRING,  RB_STRING },
1011           { 0x000,            0 },
1012 };
1013 
1014 int
sunos_sys_reboot(struct lwp * l,const struct sunos_sys_reboot_args * uap,register_t * retval)1015 sunos_sys_reboot(struct lwp *l, const struct sunos_sys_reboot_args *uap, register_t *retval)
1016 {
1017           struct sys_reboot_args ua;
1018           struct sunos_howto_conv *convp;
1019           int error, bsd_howto, sun_howto;
1020           char *bootstr;
1021           char bs[128];
1022 
1023           if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_REBOOT,
1024               0, NULL, NULL, NULL)) != 0)
1025                     return (error);
1026 
1027           /*
1028            * Convert howto bits to BSD format.
1029            */
1030           sun_howto = SCARG(uap, howto);
1031           bsd_howto = 0;
1032           convp = sunos_howto_conv;
1033           while (convp->sun_howto) {
1034                     if (sun_howto & convp->sun_howto)
1035                               bsd_howto |= convp->bsd_howto;
1036                     convp++;
1037           }
1038 
1039           /*
1040            * Sun RB_STRING (Get user supplied bootstring.)
1041            * If the machine supports passing a string to the
1042            * next booted kernel.
1043            */
1044           if (sun_howto & SUNOS_RB_STRING) {
1045                     error = copyinstr(SCARG(uap, bootstr), bs, sizeof(bs), 0);
1046 
1047                     if (error)
1048                               bootstr = NULL;
1049                     else
1050                               bootstr = bs;
1051           } else
1052                     bootstr = NULL;
1053 
1054           SCARG(&ua, opt) = bsd_howto;
1055           SCARG(&ua, bootstr) = bootstr;
1056           sys_reboot(l, &ua, retval);
1057           return(0);
1058 }
1059 
1060 /*
1061  * Generalized interface signal handler, 4.3-compatible.
1062  */
1063 /* ARGSUSED */
1064 int
sunos_sys_sigvec(struct lwp * l,const struct sunos_sys_sigvec_args * uap,register_t * retval)1065 sunos_sys_sigvec(struct lwp *l, const struct sunos_sys_sigvec_args *uap, register_t *retval)
1066 {
1067           /* {
1068                     syscallarg(int) signum;
1069                     syscallarg(struct sigvec *) nsv;
1070                     syscallarg(struct sigvec *) osv;
1071           } */
1072           struct sigvec nsv, osv;
1073           struct sigaction nsa, osa;
1074           int error;
1075 /*XXX*/extern       void compat_43_sigvec_to_sigaction
1076 (const struct sigvec *, struct sigaction *);
1077 /*XXX*/extern       void compat_43_sigaction_to_sigvec
1078 (const struct sigaction *, struct sigvec *);
1079 
1080           if (SCARG(uap, nsv)) {
1081                     error = copyin(SCARG(uap, nsv), &nsv, sizeof(nsv));
1082                     if (error != 0)
1083                               return (error);
1084 
1085                     /*
1086                      * SunOS uses the mask 0x0004 as SV_RESETHAND
1087                      * meaning: `reset to SIG_DFL on delivery'.
1088                      * We support only the bits in: 0xF
1089                      * (those bits are the same as ours)
1090                      */
1091                     if (nsv.sv_flags & ~0xF)
1092                               return (EINVAL);
1093 
1094                     compat_43_sigvec_to_sigaction(&nsv, &nsa);
1095           }
1096           error = sigaction1(l, SCARG(uap, signum),
1097                                  SCARG(uap, nsv) ? &nsa : 0,
1098                                  SCARG(uap, osv) ? &osa : 0,
1099                                  NULL, 0);
1100           if (error != 0)
1101                     return (error);
1102 
1103           if (SCARG(uap, osv)) {
1104                     compat_43_sigaction_to_sigvec(&osa, &osv);
1105                     error = copyout(&osv, SCARG(uap, osv), sizeof(osv));
1106                     if (error != 0)
1107                               return (error);
1108           }
1109 
1110           return (0);
1111 }
1112