]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/linux/linux_misc.c
MFC r356727:
[FreeBSD/FreeBSD.git] / sys / compat / linux / linux_misc.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2002 Doug Rabson
5  * Copyright (c) 1994-1995 Søren Schmidt
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer
13  *    in this position and unchanged.
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  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include "opt_compat.h"
36
37 #include <sys/param.h>
38 #include <sys/blist.h>
39 #include <sys/fcntl.h>
40 #if defined(__i386__)
41 #include <sys/imgact_aout.h>
42 #endif
43 #include <sys/jail.h>
44 #include <sys/kernel.h>
45 #include <sys/limits.h>
46 #include <sys/lock.h>
47 #include <sys/malloc.h>
48 #include <sys/mman.h>
49 #include <sys/mount.h>
50 #include <sys/msgbuf.h>
51 #include <sys/mutex.h>
52 #include <sys/namei.h>
53 #include <sys/priv.h>
54 #include <sys/proc.h>
55 #include <sys/procctl.h>
56 #include <sys/reboot.h>
57 #include <sys/racct.h>
58 #include <sys/random.h>
59 #include <sys/resourcevar.h>
60 #include <sys/sched.h>
61 #include <sys/sdt.h>
62 #include <sys/signalvar.h>
63 #include <sys/stat.h>
64 #include <sys/syscallsubr.h>
65 #include <sys/sysctl.h>
66 #include <sys/sysproto.h>
67 #include <sys/systm.h>
68 #include <sys/time.h>
69 #include <sys/vmmeter.h>
70 #include <sys/vnode.h>
71 #include <sys/wait.h>
72 #include <sys/cpuset.h>
73 #include <sys/uio.h>
74
75 #include <security/mac/mac_framework.h>
76
77 #include <vm/vm.h>
78 #include <vm/pmap.h>
79 #include <vm/vm_kern.h>
80 #include <vm/vm_map.h>
81 #include <vm/vm_extern.h>
82 #include <vm/swap_pager.h>
83
84 #ifdef COMPAT_LINUX32
85 #include <machine/../linux32/linux.h>
86 #include <machine/../linux32/linux32_proto.h>
87 #else
88 #include <machine/../linux/linux.h>
89 #include <machine/../linux/linux_proto.h>
90 #endif
91
92 #include <compat/linux/linux_dtrace.h>
93 #include <compat/linux/linux_file.h>
94 #include <compat/linux/linux_mib.h>
95 #include <compat/linux/linux_signal.h>
96 #include <compat/linux/linux_timer.h>
97 #include <compat/linux/linux_util.h>
98 #include <compat/linux/linux_sysproto.h>
99 #include <compat/linux/linux_emul.h>
100 #include <compat/linux/linux_misc.h>
101
102 /**
103  * Special DTrace provider for the linuxulator.
104  *
105  * In this file we define the provider for the entire linuxulator. All
106  * modules (= files of the linuxulator) use it.
107  *
108  * We define a different name depending on the emulated bitsize, see
109  * ../../<ARCH>/linux{,32}/linux.h, e.g.:
110  *      native bitsize          = linuxulator
111  *      amd64, 32bit emulation  = linuxulator32
112  */
113 LIN_SDT_PROVIDER_DEFINE(LINUX_DTRACE);
114
115 int stclohz;                            /* Statistics clock frequency */
116
117 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
118         RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
119         RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE,
120         RLIMIT_MEMLOCK, RLIMIT_AS
121 };
122
123 struct l_sysinfo {
124         l_long          uptime;         /* Seconds since boot */
125         l_ulong         loads[3];       /* 1, 5, and 15 minute load averages */
126 #define LINUX_SYSINFO_LOADS_SCALE 65536
127         l_ulong         totalram;       /* Total usable main memory size */
128         l_ulong         freeram;        /* Available memory size */
129         l_ulong         sharedram;      /* Amount of shared memory */
130         l_ulong         bufferram;      /* Memory used by buffers */
131         l_ulong         totalswap;      /* Total swap space size */
132         l_ulong         freeswap;       /* swap space still available */
133         l_ushort        procs;          /* Number of current processes */
134         l_ushort        pads;
135         l_ulong         totalhigh;
136         l_ulong         freehigh;
137         l_uint          mem_unit;
138         char            _f[20-2*sizeof(l_long)-sizeof(l_int)];  /* padding */
139 };
140
141 struct l_pselect6arg {
142         l_uintptr_t     ss;
143         l_size_t        ss_len;
144 };
145
146 static int      linux_utimensat_nsec_valid(l_long);
147
148
149 int
150 linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args)
151 {
152         struct l_sysinfo sysinfo;
153         int i, j;
154         struct timespec ts;
155
156         bzero(&sysinfo, sizeof(sysinfo));
157         getnanouptime(&ts);
158         if (ts.tv_nsec != 0)
159                 ts.tv_sec++;
160         sysinfo.uptime = ts.tv_sec;
161
162         /* Use the information from the mib to get our load averages */
163         for (i = 0; i < 3; i++)
164                 sysinfo.loads[i] = averunnable.ldavg[i] *
165                     LINUX_SYSINFO_LOADS_SCALE / averunnable.fscale;
166
167         sysinfo.totalram = physmem * PAGE_SIZE;
168         sysinfo.freeram = (u_long)vm_free_count() * PAGE_SIZE;
169
170         /*
171          * sharedram counts pages allocated to named, swap-backed objects such
172          * as shared memory segments and tmpfs files.  There is no cheap way to
173          * compute this, so just leave the field unpopulated.  Linux itself only
174          * started setting this field in the 3.x timeframe.
175          */
176         sysinfo.sharedram = 0;
177         sysinfo.bufferram = 0;
178
179         swap_pager_status(&i, &j);
180         sysinfo.totalswap = i * PAGE_SIZE;
181         sysinfo.freeswap = (i - j) * PAGE_SIZE;
182
183         sysinfo.procs = nprocs;
184
185         /*
186          * Platforms supported by the emulation layer do not have a notion of
187          * high memory.
188          */
189         sysinfo.totalhigh = 0;
190         sysinfo.freehigh = 0;
191
192         sysinfo.mem_unit = 1;
193
194         return (copyout(&sysinfo, args->info, sizeof(sysinfo)));
195 }
196
197 #ifdef LINUX_LEGACY_SYSCALLS
198 int
199 linux_alarm(struct thread *td, struct linux_alarm_args *args)
200 {
201         struct itimerval it, old_it;
202         u_int secs;
203         int error;
204
205 #ifdef DEBUG
206         if (ldebug(alarm))
207                 printf(ARGS(alarm, "%u"), args->secs);
208 #endif
209         secs = args->secs;
210         /*
211          * Linux alarm() is always successful. Limit secs to INT32_MAX / 2
212          * to match kern_setitimer()'s limit to avoid error from it.
213          *
214          * XXX. Linux limit secs to INT_MAX on 32 and does not limit on 64-bit
215          * platforms.
216          */
217         if (secs > INT32_MAX / 2)
218                 secs = INT32_MAX / 2;
219
220         it.it_value.tv_sec = secs;
221         it.it_value.tv_usec = 0;
222         timevalclear(&it.it_interval);
223         error = kern_setitimer(td, ITIMER_REAL, &it, &old_it);
224         KASSERT(error == 0, ("kern_setitimer returns %d", error));
225
226         if ((old_it.it_value.tv_sec == 0 && old_it.it_value.tv_usec > 0) ||
227             old_it.it_value.tv_usec >= 500000)
228                 old_it.it_value.tv_sec++;
229         td->td_retval[0] = old_it.it_value.tv_sec;
230         return (0);
231 }
232 #endif
233
234 int
235 linux_brk(struct thread *td, struct linux_brk_args *args)
236 {
237         struct vmspace *vm = td->td_proc->p_vmspace;
238         uintptr_t new, old;
239
240 #ifdef DEBUG
241         if (ldebug(brk))
242                 printf(ARGS(brk, "%p"), (void *)(uintptr_t)args->dsend);
243 #endif
244         old = (uintptr_t)vm->vm_daddr + ctob(vm->vm_dsize);
245         new = (uintptr_t)args->dsend;
246         if ((caddr_t)new > vm->vm_daddr && !kern_break(td, &new))
247                 td->td_retval[0] = (register_t)new;
248         else
249                 td->td_retval[0] = (register_t)old;
250
251         return (0);
252 }
253
254 #if defined(__i386__)
255 /* XXX: what about amd64/linux32? */
256
257 int
258 linux_uselib(struct thread *td, struct linux_uselib_args *args)
259 {
260         struct nameidata ni;
261         struct vnode *vp;
262         struct exec *a_out;
263         vm_map_t map;
264         vm_map_entry_t entry;
265         struct vattr attr;
266         vm_offset_t vmaddr;
267         unsigned long file_offset;
268         unsigned long bss_size;
269         char *library;
270         ssize_t aresid;
271         int error;
272         bool locked, opened, textset;
273
274         LCONVPATHEXIST(td, args->library, &library);
275
276 #ifdef DEBUG
277         if (ldebug(uselib))
278                 printf(ARGS(uselib, "%s"), library);
279 #endif
280
281         a_out = NULL;
282         vp = NULL;
283         locked = false;
284         textset = false;
285         opened = false;
286
287         NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1,
288             UIO_SYSSPACE, library, td);
289         error = namei(&ni);
290         LFREEPATH(library);
291         if (error)
292                 goto cleanup;
293
294         vp = ni.ni_vp;
295         NDFREE(&ni, NDF_ONLY_PNBUF);
296
297         /*
298          * From here on down, we have a locked vnode that must be unlocked.
299          * XXX: The code below largely duplicates exec_check_permissions().
300          */
301         locked = true;
302
303         /* Executable? */
304         error = VOP_GETATTR(vp, &attr, td->td_ucred);
305         if (error)
306                 goto cleanup;
307
308         if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
309             ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) {
310                 /* EACCESS is what exec(2) returns. */
311                 error = ENOEXEC;
312                 goto cleanup;
313         }
314
315         /* Sensible size? */
316         if (attr.va_size == 0) {
317                 error = ENOEXEC;
318                 goto cleanup;
319         }
320
321         /* Can we access it? */
322         error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
323         if (error)
324                 goto cleanup;
325
326         /*
327          * XXX: This should use vn_open() so that it is properly authorized,
328          * and to reduce code redundancy all over the place here.
329          * XXX: Not really, it duplicates far more of exec_check_permissions()
330          * than vn_open().
331          */
332 #ifdef MAC
333         error = mac_vnode_check_open(td->td_ucred, vp, VREAD);
334         if (error)
335                 goto cleanup;
336 #endif
337         error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL);
338         if (error)
339                 goto cleanup;
340         opened = true;
341
342         /* Pull in executable header into exec_map */
343         error = vm_mmap(exec_map, (vm_offset_t *)&a_out, PAGE_SIZE,
344             VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0);
345         if (error)
346                 goto cleanup;
347
348         /* Is it a Linux binary ? */
349         if (((a_out->a_magic >> 16) & 0xff) != 0x64) {
350                 error = ENOEXEC;
351                 goto cleanup;
352         }
353
354         /*
355          * While we are here, we should REALLY do some more checks
356          */
357
358         /* Set file/virtual offset based on a.out variant. */
359         switch ((int)(a_out->a_magic & 0xffff)) {
360         case 0413:                      /* ZMAGIC */
361                 file_offset = 1024;
362                 break;
363         case 0314:                      /* QMAGIC */
364                 file_offset = 0;
365                 break;
366         default:
367                 error = ENOEXEC;
368                 goto cleanup;
369         }
370
371         bss_size = round_page(a_out->a_bss);
372
373         /* Check various fields in header for validity/bounds. */
374         if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) {
375                 error = ENOEXEC;
376                 goto cleanup;
377         }
378
379         /* text + data can't exceed file size */
380         if (a_out->a_data + a_out->a_text > attr.va_size) {
381                 error = EFAULT;
382                 goto cleanup;
383         }
384
385         /*
386          * text/data/bss must not exceed limits
387          * XXX - this is not complete. it should check current usage PLUS
388          * the resources needed by this library.
389          */
390         PROC_LOCK(td->td_proc);
391         if (a_out->a_text > maxtsiz ||
392             a_out->a_data + bss_size > lim_cur_proc(td->td_proc, RLIMIT_DATA) ||
393             racct_set(td->td_proc, RACCT_DATA, a_out->a_data +
394             bss_size) != 0) {
395                 PROC_UNLOCK(td->td_proc);
396                 error = ENOMEM;
397                 goto cleanup;
398         }
399         PROC_UNLOCK(td->td_proc);
400
401         /*
402          * Prevent more writers.
403          */
404         error = VOP_SET_TEXT(vp);
405         if (error != 0)
406                 goto cleanup;
407         textset = true;
408
409         /*
410          * Lock no longer needed
411          */
412         locked = false;
413         VOP_UNLOCK(vp, 0);
414
415         /*
416          * Check if file_offset page aligned. Currently we cannot handle
417          * misalinged file offsets, and so we read in the entire image
418          * (what a waste).
419          */
420         if (file_offset & PAGE_MASK) {
421 #ifdef DEBUG
422                 printf("uselib: Non page aligned binary %lu\n", file_offset);
423 #endif
424                 /* Map text+data read/write/execute */
425
426                 /* a_entry is the load address and is page aligned */
427                 vmaddr = trunc_page(a_out->a_entry);
428
429                 /* get anon user mapping, read+write+execute */
430                 error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0,
431                     &vmaddr, a_out->a_text + a_out->a_data, 0, VMFS_NO_SPACE,
432                     VM_PROT_ALL, VM_PROT_ALL, 0);
433                 if (error)
434                         goto cleanup;
435
436                 error = vn_rdwr(UIO_READ, vp, (void *)vmaddr, file_offset,
437                     a_out->a_text + a_out->a_data, UIO_USERSPACE, 0,
438                     td->td_ucred, NOCRED, &aresid, td);
439                 if (error != 0)
440                         goto cleanup;
441                 if (aresid != 0) {
442                         error = ENOEXEC;
443                         goto cleanup;
444                 }
445         } else {
446 #ifdef DEBUG
447                 printf("uselib: Page aligned binary %lu\n", file_offset);
448 #endif
449                 /*
450                  * for QMAGIC, a_entry is 20 bytes beyond the load address
451                  * to skip the executable header
452                  */
453                 vmaddr = trunc_page(a_out->a_entry);
454
455                 /*
456                  * Map it all into the process's space as a single
457                  * copy-on-write "data" segment.
458                  */
459                 map = &td->td_proc->p_vmspace->vm_map;
460                 error = vm_mmap(map, &vmaddr,
461                     a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL,
462                     MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, file_offset);
463                 if (error)
464                         goto cleanup;
465                 vm_map_lock(map);
466                 if (!vm_map_lookup_entry(map, vmaddr, &entry)) {
467                         vm_map_unlock(map);
468                         error = EDOOFUS;
469                         goto cleanup;
470                 }
471                 entry->eflags |= MAP_ENTRY_VN_EXEC;
472                 vm_map_unlock(map);
473                 textset = false;
474         }
475 #ifdef DEBUG
476         printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long *)vmaddr)[0],
477             ((long *)vmaddr)[1]);
478 #endif
479         if (bss_size != 0) {
480                 /* Calculate BSS start address */
481                 vmaddr = trunc_page(a_out->a_entry) + a_out->a_text +
482                     a_out->a_data;
483
484                 /* allocate some 'anon' space */
485                 error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0,
486                     &vmaddr, bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL,
487                     VM_PROT_ALL, 0);
488                 if (error)
489                         goto cleanup;
490         }
491
492 cleanup:
493         if (opened) {
494                 if (locked)
495                         VOP_UNLOCK(vp, 0);
496                 locked = false;
497                 VOP_CLOSE(vp, FREAD, td->td_ucred, td);
498         }
499         if (textset) {
500                 if (!locked) {
501                         locked = true;
502                         VOP_LOCK(vp, LK_SHARED | LK_RETRY);
503                 }
504                 VOP_UNSET_TEXT_CHECKED(vp);
505         }
506         if (locked)
507                 VOP_UNLOCK(vp, 0);
508
509         /* Release the temporary mapping. */
510         if (a_out)
511                 kmap_free_wakeup(exec_map, (vm_offset_t)a_out, PAGE_SIZE);
512
513         return (error);
514 }
515
516 #endif  /* __i386__ */
517
518 #ifdef LINUX_LEGACY_SYSCALLS
519 int
520 linux_select(struct thread *td, struct linux_select_args *args)
521 {
522         l_timeval ltv;
523         struct timeval tv0, tv1, utv, *tvp;
524         int error;
525
526 #ifdef DEBUG
527         if (ldebug(select))
528                 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds,
529                     (void *)args->readfds, (void *)args->writefds,
530                     (void *)args->exceptfds, (void *)args->timeout);
531 #endif
532
533         /*
534          * Store current time for computation of the amount of
535          * time left.
536          */
537         if (args->timeout) {
538                 if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
539                         goto select_out;
540                 utv.tv_sec = ltv.tv_sec;
541                 utv.tv_usec = ltv.tv_usec;
542 #ifdef DEBUG
543                 if (ldebug(select))
544                         printf(LMSG("incoming timeout (%jd/%ld)"),
545                             (intmax_t)utv.tv_sec, utv.tv_usec);
546 #endif
547
548                 if (itimerfix(&utv)) {
549                         /*
550                          * The timeval was invalid.  Convert it to something
551                          * valid that will act as it does under Linux.
552                          */
553                         utv.tv_sec += utv.tv_usec / 1000000;
554                         utv.tv_usec %= 1000000;
555                         if (utv.tv_usec < 0) {
556                                 utv.tv_sec -= 1;
557                                 utv.tv_usec += 1000000;
558                         }
559                         if (utv.tv_sec < 0)
560                                 timevalclear(&utv);
561                 }
562                 microtime(&tv0);
563                 tvp = &utv;
564         } else
565                 tvp = NULL;
566
567         error = kern_select(td, args->nfds, args->readfds, args->writefds,
568             args->exceptfds, tvp, LINUX_NFDBITS);
569
570 #ifdef DEBUG
571         if (ldebug(select))
572                 printf(LMSG("real select returns %d"), error);
573 #endif
574         if (error)
575                 goto select_out;
576
577         if (args->timeout) {
578                 if (td->td_retval[0]) {
579                         /*
580                          * Compute how much time was left of the timeout,
581                          * by subtracting the current time and the time
582                          * before we started the call, and subtracting
583                          * that result from the user-supplied value.
584                          */
585                         microtime(&tv1);
586                         timevalsub(&tv1, &tv0);
587                         timevalsub(&utv, &tv1);
588                         if (utv.tv_sec < 0)
589                                 timevalclear(&utv);
590                 } else
591                         timevalclear(&utv);
592 #ifdef DEBUG
593                 if (ldebug(select))
594                         printf(LMSG("outgoing timeout (%jd/%ld)"),
595                             (intmax_t)utv.tv_sec, utv.tv_usec);
596 #endif
597                 ltv.tv_sec = utv.tv_sec;
598                 ltv.tv_usec = utv.tv_usec;
599                 if ((error = copyout(&ltv, args->timeout, sizeof(ltv))))
600                         goto select_out;
601         }
602
603 select_out:
604 #ifdef DEBUG
605         if (ldebug(select))
606                 printf(LMSG("select_out -> %d"), error);
607 #endif
608         return (error);
609 }
610 #endif
611
612 int
613 linux_mremap(struct thread *td, struct linux_mremap_args *args)
614 {
615         uintptr_t addr;
616         size_t len;
617         int error = 0;
618
619 #ifdef DEBUG
620         if (ldebug(mremap))
621                 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"),
622                     (void *)(uintptr_t)args->addr,
623                     (unsigned long)args->old_len,
624                     (unsigned long)args->new_len,
625                     (unsigned long)args->flags);
626 #endif
627
628         if (args->flags & ~(LINUX_MREMAP_FIXED | LINUX_MREMAP_MAYMOVE)) {
629                 td->td_retval[0] = 0;
630                 return (EINVAL);
631         }
632
633         /*
634          * Check for the page alignment.
635          * Linux defines PAGE_MASK to be FreeBSD ~PAGE_MASK.
636          */
637         if (args->addr & PAGE_MASK) {
638                 td->td_retval[0] = 0;
639                 return (EINVAL);
640         }
641
642         args->new_len = round_page(args->new_len);
643         args->old_len = round_page(args->old_len);
644
645         if (args->new_len > args->old_len) {
646                 td->td_retval[0] = 0;
647                 return (ENOMEM);
648         }
649
650         if (args->new_len < args->old_len) {
651                 addr = args->addr + args->new_len;
652                 len = args->old_len - args->new_len;
653                 error = kern_munmap(td, addr, len);
654         }
655
656         td->td_retval[0] = error ? 0 : (uintptr_t)args->addr;
657         return (error);
658 }
659
660 #define LINUX_MS_ASYNC       0x0001
661 #define LINUX_MS_INVALIDATE  0x0002
662 #define LINUX_MS_SYNC        0x0004
663
664 int
665 linux_msync(struct thread *td, struct linux_msync_args *args)
666 {
667
668         return (kern_msync(td, args->addr, args->len,
669             args->fl & ~LINUX_MS_SYNC));
670 }
671
672 #ifdef LINUX_LEGACY_SYSCALLS
673 int
674 linux_time(struct thread *td, struct linux_time_args *args)
675 {
676         struct timeval tv;
677         l_time_t tm;
678         int error;
679
680 #ifdef DEBUG
681         if (ldebug(time))
682                 printf(ARGS(time, "*"));
683 #endif
684
685         microtime(&tv);
686         tm = tv.tv_sec;
687         if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm))))
688                 return (error);
689         td->td_retval[0] = tm;
690         return (0);
691 }
692 #endif
693
694 struct l_times_argv {
695         l_clock_t       tms_utime;
696         l_clock_t       tms_stime;
697         l_clock_t       tms_cutime;
698         l_clock_t       tms_cstime;
699 };
700
701
702 /*
703  * Glibc versions prior to 2.2.1 always use hard-coded CLK_TCK value.
704  * Since 2.2.1 Glibc uses value exported from kernel via AT_CLKTCK
705  * auxiliary vector entry.
706  */
707 #define CLK_TCK         100
708
709 #define CONVOTCK(r)     (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
710 #define CONVNTCK(r)     (r.tv_sec * stclohz + r.tv_usec / (1000000 / stclohz))
711
712 #define CONVTCK(r)      (linux_kernver(td) >= LINUX_KERNVER_2004000 ?           \
713                             CONVNTCK(r) : CONVOTCK(r))
714
715 int
716 linux_times(struct thread *td, struct linux_times_args *args)
717 {
718         struct timeval tv, utime, stime, cutime, cstime;
719         struct l_times_argv tms;
720         struct proc *p;
721         int error;
722
723 #ifdef DEBUG
724         if (ldebug(times))
725                 printf(ARGS(times, "*"));
726 #endif
727
728         if (args->buf != NULL) {
729                 p = td->td_proc;
730                 PROC_LOCK(p);
731                 PROC_STATLOCK(p);
732                 calcru(p, &utime, &stime);
733                 PROC_STATUNLOCK(p);
734                 calccru(p, &cutime, &cstime);
735                 PROC_UNLOCK(p);
736
737                 tms.tms_utime = CONVTCK(utime);
738                 tms.tms_stime = CONVTCK(stime);
739
740                 tms.tms_cutime = CONVTCK(cutime);
741                 tms.tms_cstime = CONVTCK(cstime);
742
743                 if ((error = copyout(&tms, args->buf, sizeof(tms))))
744                         return (error);
745         }
746
747         microuptime(&tv);
748         td->td_retval[0] = (int)CONVTCK(tv);
749         return (0);
750 }
751
752 int
753 linux_newuname(struct thread *td, struct linux_newuname_args *args)
754 {
755         struct l_new_utsname utsname;
756         char osname[LINUX_MAX_UTSNAME];
757         char osrelease[LINUX_MAX_UTSNAME];
758         char *p;
759
760 #ifdef DEBUG
761         if (ldebug(newuname))
762                 printf(ARGS(newuname, "*"));
763 #endif
764
765         linux_get_osname(td, osname);
766         linux_get_osrelease(td, osrelease);
767
768         bzero(&utsname, sizeof(utsname));
769         strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME);
770         getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME);
771         getcreddomainname(td->td_ucred, utsname.domainname, LINUX_MAX_UTSNAME);
772         strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME);
773         strlcpy(utsname.version, version, LINUX_MAX_UTSNAME);
774         for (p = utsname.version; *p != '\0'; ++p)
775                 if (*p == '\n') {
776                         *p = '\0';
777                         break;
778                 }
779 #if defined(__amd64__)
780         /*
781          * On amd64, Linux uname(2) needs to return "x86_64"
782          * for both 64-bit and 32-bit applications.  On 32-bit,
783          * the string returned by getauxval(AT_PLATFORM) needs
784          * to remain "i686", though.
785          */
786         strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME);
787 #else
788         strlcpy(utsname.machine, linux_kplatform, LINUX_MAX_UTSNAME);
789 #endif
790
791         return (copyout(&utsname, args->buf, sizeof(utsname)));
792 }
793
794 struct l_utimbuf {
795         l_time_t l_actime;
796         l_time_t l_modtime;
797 };
798
799 #ifdef LINUX_LEGACY_SYSCALLS
800 int
801 linux_utime(struct thread *td, struct linux_utime_args *args)
802 {
803         struct timeval tv[2], *tvp;
804         struct l_utimbuf lut;
805         char *fname;
806         int error;
807
808         LCONVPATHEXIST(td, args->fname, &fname);
809
810 #ifdef DEBUG
811         if (ldebug(utime))
812                 printf(ARGS(utime, "%s, *"), fname);
813 #endif
814
815         if (args->times) {
816                 if ((error = copyin(args->times, &lut, sizeof lut))) {
817                         LFREEPATH(fname);
818                         return (error);
819                 }
820                 tv[0].tv_sec = lut.l_actime;
821                 tv[0].tv_usec = 0;
822                 tv[1].tv_sec = lut.l_modtime;
823                 tv[1].tv_usec = 0;
824                 tvp = tv;
825         } else
826                 tvp = NULL;
827
828         error = kern_utimesat(td, AT_FDCWD, fname, UIO_SYSSPACE, tvp,
829             UIO_SYSSPACE);
830         LFREEPATH(fname);
831         return (error);
832 }
833 #endif
834
835 #ifdef LINUX_LEGACY_SYSCALLS
836 int
837 linux_utimes(struct thread *td, struct linux_utimes_args *args)
838 {
839         l_timeval ltv[2];
840         struct timeval tv[2], *tvp = NULL;
841         char *fname;
842         int error;
843
844         LCONVPATHEXIST(td, args->fname, &fname);
845
846 #ifdef DEBUG
847         if (ldebug(utimes))
848                 printf(ARGS(utimes, "%s, *"), fname);
849 #endif
850
851         if (args->tptr != NULL) {
852                 if ((error = copyin(args->tptr, ltv, sizeof ltv))) {
853                         LFREEPATH(fname);
854                         return (error);
855                 }
856                 tv[0].tv_sec = ltv[0].tv_sec;
857                 tv[0].tv_usec = ltv[0].tv_usec;
858                 tv[1].tv_sec = ltv[1].tv_sec;
859                 tv[1].tv_usec = ltv[1].tv_usec;
860                 tvp = tv;
861         }
862
863         error = kern_utimesat(td, AT_FDCWD, fname, UIO_SYSSPACE,
864             tvp, UIO_SYSSPACE);
865         LFREEPATH(fname);
866         return (error);
867 }
868 #endif
869
870 static int
871 linux_utimensat_nsec_valid(l_long nsec)
872 {
873
874         if (nsec == LINUX_UTIME_OMIT || nsec == LINUX_UTIME_NOW)
875                 return (0);
876         if (nsec >= 0 && nsec <= 999999999)
877                 return (0);
878         return (1);
879 }
880
881 int
882 linux_utimensat(struct thread *td, struct linux_utimensat_args *args)
883 {
884         struct l_timespec l_times[2];
885         struct timespec times[2], *timesp = NULL;
886         char *path = NULL;
887         int error, dfd, flags = 0;
888
889         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
890
891 #ifdef DEBUG
892         if (ldebug(utimensat))
893                 printf(ARGS(utimensat, "%d, *"), dfd);
894 #endif
895
896         if (args->flags & ~LINUX_AT_SYMLINK_NOFOLLOW)
897                 return (EINVAL);
898
899         if (args->times != NULL) {
900                 error = copyin(args->times, l_times, sizeof(l_times));
901                 if (error != 0)
902                         return (error);
903
904                 if (linux_utimensat_nsec_valid(l_times[0].tv_nsec) != 0 ||
905                     linux_utimensat_nsec_valid(l_times[1].tv_nsec) != 0)
906                         return (EINVAL);
907
908                 times[0].tv_sec = l_times[0].tv_sec;
909                 switch (l_times[0].tv_nsec)
910                 {
911                 case LINUX_UTIME_OMIT:
912                         times[0].tv_nsec = UTIME_OMIT;
913                         break;
914                 case LINUX_UTIME_NOW:
915                         times[0].tv_nsec = UTIME_NOW;
916                         break;
917                 default:
918                         times[0].tv_nsec = l_times[0].tv_nsec;
919                 }
920
921                 times[1].tv_sec = l_times[1].tv_sec;
922                 switch (l_times[1].tv_nsec)
923                 {
924                 case LINUX_UTIME_OMIT:
925                         times[1].tv_nsec = UTIME_OMIT;
926                         break;
927                 case LINUX_UTIME_NOW:
928                         times[1].tv_nsec = UTIME_NOW;
929                         break;
930                 default:
931                         times[1].tv_nsec = l_times[1].tv_nsec;
932                         break;
933                 }
934                 timesp = times;
935
936                 /* This breaks POSIX, but is what the Linux kernel does
937                  * _on purpose_ (documented in the man page for utimensat(2)),
938                  * so we must follow that behaviour. */
939                 if (times[0].tv_nsec == UTIME_OMIT &&
940                     times[1].tv_nsec == UTIME_OMIT)
941                         return (0);
942         }
943
944         if (args->pathname != NULL)
945                 LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
946         else if (args->flags != 0)
947                 return (EINVAL);
948
949         if (args->flags & LINUX_AT_SYMLINK_NOFOLLOW)
950                 flags |= AT_SYMLINK_NOFOLLOW;
951
952         if (path == NULL)
953                 error = kern_futimens(td, dfd, timesp, UIO_SYSSPACE);
954         else {
955                 error = kern_utimensat(td, dfd, path, UIO_SYSSPACE, timesp,
956                         UIO_SYSSPACE, flags);
957                 LFREEPATH(path);
958         }
959
960         return (error);
961 }
962
963 #ifdef LINUX_LEGACY_SYSCALLS
964 int
965 linux_futimesat(struct thread *td, struct linux_futimesat_args *args)
966 {
967         l_timeval ltv[2];
968         struct timeval tv[2], *tvp = NULL;
969         char *fname;
970         int error, dfd;
971
972         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
973         LCONVPATHEXIST_AT(td, args->filename, &fname, dfd);
974
975 #ifdef DEBUG
976         if (ldebug(futimesat))
977                 printf(ARGS(futimesat, "%s, *"), fname);
978 #endif
979
980         if (args->utimes != NULL) {
981                 if ((error = copyin(args->utimes, ltv, sizeof ltv))) {
982                         LFREEPATH(fname);
983                         return (error);
984                 }
985                 tv[0].tv_sec = ltv[0].tv_sec;
986                 tv[0].tv_usec = ltv[0].tv_usec;
987                 tv[1].tv_sec = ltv[1].tv_sec;
988                 tv[1].tv_usec = ltv[1].tv_usec;
989                 tvp = tv;
990         }
991
992         error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE);
993         LFREEPATH(fname);
994         return (error);
995 }
996 #endif
997
998 static int
999 linux_common_wait(struct thread *td, int pid, int *statusp,
1000     int options, struct __wrusage *wrup)
1001 {
1002         siginfo_t siginfo;
1003         idtype_t idtype;
1004         id_t id;
1005         int error, status, tmpstat;
1006
1007         if (pid == WAIT_ANY) {
1008                 idtype = P_ALL;
1009                 id = 0;
1010         } else if (pid < 0) {
1011                 idtype = P_PGID;
1012                 id = (id_t)-pid;
1013         } else {
1014                 idtype = P_PID;
1015                 id = (id_t)pid;
1016         }
1017
1018         /*
1019          * For backward compatibility we implicitly add flags WEXITED
1020          * and WTRAPPED here.
1021          */
1022         options |= WEXITED | WTRAPPED;
1023         error = kern_wait6(td, idtype, id, &status, options, wrup, &siginfo);
1024         if (error)
1025                 return (error);
1026
1027         if (statusp) {
1028                 tmpstat = status & 0xffff;
1029                 if (WIFSIGNALED(tmpstat)) {
1030                         tmpstat = (tmpstat & 0xffffff80) |
1031                             bsd_to_linux_signal(WTERMSIG(tmpstat));
1032                 } else if (WIFSTOPPED(tmpstat)) {
1033                         tmpstat = (tmpstat & 0xffff00ff) |
1034                             (bsd_to_linux_signal(WSTOPSIG(tmpstat)) << 8);
1035 #if defined(__amd64__) && !defined(COMPAT_LINUX32)
1036                         if (WSTOPSIG(status) == SIGTRAP) {
1037                                 tmpstat = linux_ptrace_status(td,
1038                                     siginfo.si_pid, tmpstat);
1039                         }
1040 #endif
1041                 } else if (WIFCONTINUED(tmpstat)) {
1042                         tmpstat = 0xffff;
1043                 }
1044                 error = copyout(&tmpstat, statusp, sizeof(int));
1045         }
1046
1047         return (error);
1048 }
1049
1050 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1051 int
1052 linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
1053 {
1054         struct linux_wait4_args wait4_args;
1055
1056 #ifdef DEBUG
1057         if (ldebug(waitpid))
1058                 printf(ARGS(waitpid, "%d, %p, %d"),
1059                     args->pid, (void *)args->status, args->options);
1060 #endif
1061
1062         wait4_args.pid = args->pid;
1063         wait4_args.status = args->status;
1064         wait4_args.options = args->options;
1065         wait4_args.rusage = NULL;
1066
1067         return (linux_wait4(td, &wait4_args));
1068 }
1069 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1070
1071 int
1072 linux_wait4(struct thread *td, struct linux_wait4_args *args)
1073 {
1074         int error, options;
1075         struct __wrusage wru, *wrup;
1076
1077 #ifdef DEBUG
1078         if (ldebug(wait4))
1079                 printf(ARGS(wait4, "%d, %p, %d, %p"),
1080                     args->pid, (void *)args->status, args->options,
1081                     (void *)args->rusage);
1082 #endif
1083         if (args->options & ~(LINUX_WUNTRACED | LINUX_WNOHANG |
1084             LINUX_WCONTINUED | __WCLONE | __WNOTHREAD | __WALL))
1085                 return (EINVAL);
1086
1087         options = WEXITED;
1088         linux_to_bsd_waitopts(args->options, &options);
1089
1090         if (args->rusage != NULL)
1091                 wrup = &wru;
1092         else
1093                 wrup = NULL;
1094         error = linux_common_wait(td, args->pid, args->status, options, wrup);
1095         if (error != 0)
1096                 return (error);
1097         if (args->rusage != NULL)
1098                 error = linux_copyout_rusage(&wru.wru_self, args->rusage);
1099         return (error);
1100 }
1101
1102 int
1103 linux_waitid(struct thread *td, struct linux_waitid_args *args)
1104 {
1105         int status, options, sig;
1106         struct __wrusage wru;
1107         siginfo_t siginfo;
1108         l_siginfo_t lsi;
1109         idtype_t idtype;
1110         struct proc *p;
1111         int error;
1112
1113         options = 0;
1114         linux_to_bsd_waitopts(args->options, &options);
1115
1116         if (options & ~(WNOHANG | WNOWAIT | WEXITED | WUNTRACED | WCONTINUED))
1117                 return (EINVAL);
1118         if (!(options & (WEXITED | WUNTRACED | WCONTINUED)))
1119                 return (EINVAL);
1120
1121         switch (args->idtype) {
1122         case LINUX_P_ALL:
1123                 idtype = P_ALL;
1124                 break;
1125         case LINUX_P_PID:
1126                 if (args->id <= 0)
1127                         return (EINVAL);
1128                 idtype = P_PID;
1129                 break;
1130         case LINUX_P_PGID:
1131                 if (args->id <= 0)
1132                         return (EINVAL);
1133                 idtype = P_PGID;
1134                 break;
1135         default:
1136                 return (EINVAL);
1137         }
1138
1139         error = kern_wait6(td, idtype, args->id, &status, options,
1140             &wru, &siginfo);
1141         if (error != 0)
1142                 return (error);
1143         if (args->rusage != NULL) {
1144                 error = linux_copyout_rusage(&wru.wru_children,
1145                     args->rusage);
1146                 if (error != 0)
1147                         return (error);
1148         }
1149         if (args->info != NULL) {
1150                 p = td->td_proc;
1151                 bzero(&lsi, sizeof(lsi));
1152                 if (td->td_retval[0] != 0) {
1153                         sig = bsd_to_linux_signal(siginfo.si_signo);
1154                         siginfo_to_lsiginfo(&siginfo, &lsi, sig);
1155                 }
1156                 error = copyout(&lsi, args->info, sizeof(lsi));
1157         }
1158         td->td_retval[0] = 0;
1159
1160         return (error);
1161 }
1162
1163 #ifdef LINUX_LEGACY_SYSCALLS
1164 int
1165 linux_mknod(struct thread *td, struct linux_mknod_args *args)
1166 {
1167         char *path;
1168         int error;
1169
1170         LCONVPATHCREAT(td, args->path, &path);
1171
1172 #ifdef DEBUG
1173         if (ldebug(mknod))
1174                 printf(ARGS(mknod, "%s, %d, %ju"), path, args->mode,
1175                     (uintmax_t)args->dev);
1176 #endif
1177
1178         switch (args->mode & S_IFMT) {
1179         case S_IFIFO:
1180         case S_IFSOCK:
1181                 error = kern_mkfifoat(td, AT_FDCWD, path, UIO_SYSSPACE,
1182                     args->mode);
1183                 break;
1184
1185         case S_IFCHR:
1186         case S_IFBLK:
1187                 error = kern_mknodat(td, AT_FDCWD, path, UIO_SYSSPACE,
1188                     args->mode, args->dev);
1189                 break;
1190
1191         case S_IFDIR:
1192                 error = EPERM;
1193                 break;
1194
1195         case 0:
1196                 args->mode |= S_IFREG;
1197                 /* FALLTHROUGH */
1198         case S_IFREG:
1199                 error = kern_openat(td, AT_FDCWD, path, UIO_SYSSPACE,
1200                     O_WRONLY | O_CREAT | O_TRUNC, args->mode);
1201                 if (error == 0)
1202                         kern_close(td, td->td_retval[0]);
1203                 break;
1204
1205         default:
1206                 error = EINVAL;
1207                 break;
1208         }
1209         LFREEPATH(path);
1210         return (error);
1211 }
1212 #endif
1213
1214 int
1215 linux_mknodat(struct thread *td, struct linux_mknodat_args *args)
1216 {
1217         char *path;
1218         int error, dfd;
1219
1220         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1221         LCONVPATHCREAT_AT(td, args->filename, &path, dfd);
1222
1223 #ifdef DEBUG
1224         if (ldebug(mknodat))
1225                 printf(ARGS(mknodat, "%s, %d, %d"), path, args->mode, args->dev);
1226 #endif
1227
1228         switch (args->mode & S_IFMT) {
1229         case S_IFIFO:
1230         case S_IFSOCK:
1231                 error = kern_mkfifoat(td, dfd, path, UIO_SYSSPACE, args->mode);
1232                 break;
1233
1234         case S_IFCHR:
1235         case S_IFBLK:
1236                 error = kern_mknodat(td, dfd, path, UIO_SYSSPACE, args->mode,
1237                     args->dev);
1238                 break;
1239
1240         case S_IFDIR:
1241                 error = EPERM;
1242                 break;
1243
1244         case 0:
1245                 args->mode |= S_IFREG;
1246                 /* FALLTHROUGH */
1247         case S_IFREG:
1248                 error = kern_openat(td, dfd, path, UIO_SYSSPACE,
1249                     O_WRONLY | O_CREAT | O_TRUNC, args->mode);
1250                 if (error == 0)
1251                         kern_close(td, td->td_retval[0]);
1252                 break;
1253
1254         default:
1255                 error = EINVAL;
1256                 break;
1257         }
1258         LFREEPATH(path);
1259         return (error);
1260 }
1261
1262 /*
1263  * UGH! This is just about the dumbest idea I've ever heard!!
1264  */
1265 int
1266 linux_personality(struct thread *td, struct linux_personality_args *args)
1267 {
1268         struct linux_pemuldata *pem;
1269         struct proc *p = td->td_proc;
1270         uint32_t old;
1271
1272 #ifdef DEBUG
1273         if (ldebug(personality))
1274                 printf(ARGS(personality, "%u"), args->per);
1275 #endif
1276
1277         PROC_LOCK(p);
1278         pem = pem_find(p);
1279         old = pem->persona;
1280         if (args->per != 0xffffffff)
1281                 pem->persona = args->per;
1282         PROC_UNLOCK(p);
1283
1284         td->td_retval[0] = old;
1285         return (0);
1286 }
1287
1288 struct l_itimerval {
1289         l_timeval it_interval;
1290         l_timeval it_value;
1291 };
1292
1293 #define B2L_ITIMERVAL(bip, lip)                                         \
1294         (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec;          \
1295         (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec;        \
1296         (bip)->it_value.tv_sec = (lip)->it_value.tv_sec;                \
1297         (bip)->it_value.tv_usec = (lip)->it_value.tv_usec;
1298
1299 int
1300 linux_setitimer(struct thread *td, struct linux_setitimer_args *uap)
1301 {
1302         int error;
1303         struct l_itimerval ls;
1304         struct itimerval aitv, oitv;
1305
1306 #ifdef DEBUG
1307         if (ldebug(setitimer))
1308                 printf(ARGS(setitimer, "%p, %p"),
1309                     (void *)uap->itv, (void *)uap->oitv);
1310 #endif
1311
1312         if (uap->itv == NULL) {
1313                 uap->itv = uap->oitv;
1314                 return (linux_getitimer(td, (struct linux_getitimer_args *)uap));
1315         }
1316
1317         error = copyin(uap->itv, &ls, sizeof(ls));
1318         if (error != 0)
1319                 return (error);
1320         B2L_ITIMERVAL(&aitv, &ls);
1321 #ifdef DEBUG
1322         if (ldebug(setitimer)) {
1323                 printf("setitimer: value: sec: %jd, usec: %ld\n",
1324                     (intmax_t)aitv.it_value.tv_sec, aitv.it_value.tv_usec);
1325                 printf("setitimer: interval: sec: %jd, usec: %ld\n",
1326                     (intmax_t)aitv.it_interval.tv_sec, aitv.it_interval.tv_usec);
1327         }
1328 #endif
1329         error = kern_setitimer(td, uap->which, &aitv, &oitv);
1330         if (error != 0 || uap->oitv == NULL)
1331                 return (error);
1332         B2L_ITIMERVAL(&ls, &oitv);
1333
1334         return (copyout(&ls, uap->oitv, sizeof(ls)));
1335 }
1336
1337 int
1338 linux_getitimer(struct thread *td, struct linux_getitimer_args *uap)
1339 {
1340         int error;
1341         struct l_itimerval ls;
1342         struct itimerval aitv;
1343
1344 #ifdef DEBUG
1345         if (ldebug(getitimer))
1346                 printf(ARGS(getitimer, "%p"), (void *)uap->itv);
1347 #endif
1348         error = kern_getitimer(td, uap->which, &aitv);
1349         if (error != 0)
1350                 return (error);
1351         B2L_ITIMERVAL(&ls, &aitv);
1352         return (copyout(&ls, uap->itv, sizeof(ls)));
1353 }
1354
1355 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1356 int
1357 linux_nice(struct thread *td, struct linux_nice_args *args)
1358 {
1359         struct setpriority_args bsd_args;
1360
1361         bsd_args.which = PRIO_PROCESS;
1362         bsd_args.who = 0;               /* current process */
1363         bsd_args.prio = args->inc;
1364         return (sys_setpriority(td, &bsd_args));
1365 }
1366 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1367
1368 int
1369 linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
1370 {
1371         struct ucred *newcred, *oldcred;
1372         l_gid_t *linux_gidset;
1373         gid_t *bsd_gidset;
1374         int ngrp, error;
1375         struct proc *p;
1376
1377         ngrp = args->gidsetsize;
1378         if (ngrp < 0 || ngrp >= ngroups_max + 1)
1379                 return (EINVAL);
1380         linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
1381         error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t));
1382         if (error)
1383                 goto out;
1384         newcred = crget();
1385         crextend(newcred, ngrp + 1);
1386         p = td->td_proc;
1387         PROC_LOCK(p);
1388         oldcred = p->p_ucred;
1389         crcopy(newcred, oldcred);
1390
1391         /*
1392          * cr_groups[0] holds egid. Setting the whole set from
1393          * the supplied set will cause egid to be changed too.
1394          * Keep cr_groups[0] unchanged to prevent that.
1395          */
1396
1397         if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) {
1398                 PROC_UNLOCK(p);
1399                 crfree(newcred);
1400                 goto out;
1401         }
1402
1403         if (ngrp > 0) {
1404                 newcred->cr_ngroups = ngrp + 1;
1405
1406                 bsd_gidset = newcred->cr_groups;
1407                 ngrp--;
1408                 while (ngrp >= 0) {
1409                         bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
1410                         ngrp--;
1411                 }
1412         } else
1413                 newcred->cr_ngroups = 1;
1414
1415         setsugid(p);
1416         proc_set_cred(p, newcred);
1417         PROC_UNLOCK(p);
1418         crfree(oldcred);
1419         error = 0;
1420 out:
1421         free(linux_gidset, M_LINUX);
1422         return (error);
1423 }
1424
1425 int
1426 linux_getgroups(struct thread *td, struct linux_getgroups_args *args)
1427 {
1428         struct ucred *cred;
1429         l_gid_t *linux_gidset;
1430         gid_t *bsd_gidset;
1431         int bsd_gidsetsz, ngrp, error;
1432
1433         cred = td->td_ucred;
1434         bsd_gidset = cred->cr_groups;
1435         bsd_gidsetsz = cred->cr_ngroups - 1;
1436
1437         /*
1438          * cr_groups[0] holds egid. Returning the whole set
1439          * here will cause a duplicate. Exclude cr_groups[0]
1440          * to prevent that.
1441          */
1442
1443         if ((ngrp = args->gidsetsize) == 0) {
1444                 td->td_retval[0] = bsd_gidsetsz;
1445                 return (0);
1446         }
1447
1448         if (ngrp < bsd_gidsetsz)
1449                 return (EINVAL);
1450
1451         ngrp = 0;
1452         linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset),
1453             M_LINUX, M_WAITOK);
1454         while (ngrp < bsd_gidsetsz) {
1455                 linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
1456                 ngrp++;
1457         }
1458
1459         error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t));
1460         free(linux_gidset, M_LINUX);
1461         if (error)
1462                 return (error);
1463
1464         td->td_retval[0] = ngrp;
1465         return (0);
1466 }
1467
1468 int
1469 linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args)
1470 {
1471         struct rlimit bsd_rlim;
1472         struct l_rlimit rlim;
1473         u_int which;
1474         int error;
1475
1476 #ifdef DEBUG
1477         if (ldebug(setrlimit))
1478                 printf(ARGS(setrlimit, "%d, %p"),
1479                     args->resource, (void *)args->rlim);
1480 #endif
1481
1482         if (args->resource >= LINUX_RLIM_NLIMITS)
1483                 return (EINVAL);
1484
1485         which = linux_to_bsd_resource[args->resource];
1486         if (which == -1)
1487                 return (EINVAL);
1488
1489         error = copyin(args->rlim, &rlim, sizeof(rlim));
1490         if (error)
1491                 return (error);
1492
1493         bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur;
1494         bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max;
1495         return (kern_setrlimit(td, which, &bsd_rlim));
1496 }
1497
1498 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1499 int
1500 linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args)
1501 {
1502         struct l_rlimit rlim;
1503         struct rlimit bsd_rlim;
1504         u_int which;
1505
1506 #ifdef DEBUG
1507         if (ldebug(old_getrlimit))
1508                 printf(ARGS(old_getrlimit, "%d, %p"),
1509                     args->resource, (void *)args->rlim);
1510 #endif
1511
1512         if (args->resource >= LINUX_RLIM_NLIMITS)
1513                 return (EINVAL);
1514
1515         which = linux_to_bsd_resource[args->resource];
1516         if (which == -1)
1517                 return (EINVAL);
1518
1519         lim_rlimit(td, which, &bsd_rlim);
1520
1521 #ifdef COMPAT_LINUX32
1522         rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur;
1523         if (rlim.rlim_cur == UINT_MAX)
1524                 rlim.rlim_cur = INT_MAX;
1525         rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max;
1526         if (rlim.rlim_max == UINT_MAX)
1527                 rlim.rlim_max = INT_MAX;
1528 #else
1529         rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur;
1530         if (rlim.rlim_cur == ULONG_MAX)
1531                 rlim.rlim_cur = LONG_MAX;
1532         rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max;
1533         if (rlim.rlim_max == ULONG_MAX)
1534                 rlim.rlim_max = LONG_MAX;
1535 #endif
1536         return (copyout(&rlim, args->rlim, sizeof(rlim)));
1537 }
1538 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1539
1540 int
1541 linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args)
1542 {
1543         struct l_rlimit rlim;
1544         struct rlimit bsd_rlim;
1545         u_int which;
1546
1547 #ifdef DEBUG
1548         if (ldebug(getrlimit))
1549                 printf(ARGS(getrlimit, "%d, %p"),
1550                     args->resource, (void *)args->rlim);
1551 #endif
1552
1553         if (args->resource >= LINUX_RLIM_NLIMITS)
1554                 return (EINVAL);
1555
1556         which = linux_to_bsd_resource[args->resource];
1557         if (which == -1)
1558                 return (EINVAL);
1559
1560         lim_rlimit(td, which, &bsd_rlim);
1561
1562         rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur;
1563         rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max;
1564         return (copyout(&rlim, args->rlim, sizeof(rlim)));
1565 }
1566
1567 int
1568 linux_sched_setscheduler(struct thread *td,
1569     struct linux_sched_setscheduler_args *args)
1570 {
1571         struct sched_param sched_param;
1572         struct thread *tdt;
1573         int error, policy;
1574
1575 #ifdef DEBUG
1576         if (ldebug(sched_setscheduler))
1577                 printf(ARGS(sched_setscheduler, "%d, %d, %p"),
1578                     args->pid, args->policy, (const void *)args->param);
1579 #endif
1580
1581         switch (args->policy) {
1582         case LINUX_SCHED_OTHER:
1583                 policy = SCHED_OTHER;
1584                 break;
1585         case LINUX_SCHED_FIFO:
1586                 policy = SCHED_FIFO;
1587                 break;
1588         case LINUX_SCHED_RR:
1589                 policy = SCHED_RR;
1590                 break;
1591         default:
1592                 return (EINVAL);
1593         }
1594
1595         error = copyin(args->param, &sched_param, sizeof(sched_param));
1596         if (error)
1597                 return (error);
1598
1599         if (linux_map_sched_prio) {
1600                 switch (policy) {
1601                 case SCHED_OTHER:
1602                         if (sched_param.sched_priority != 0)
1603                                 return (EINVAL);
1604
1605                         sched_param.sched_priority =
1606                             PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE;
1607                         break;
1608                 case SCHED_FIFO:
1609                 case SCHED_RR:
1610                         if (sched_param.sched_priority < 1 ||
1611                             sched_param.sched_priority >= LINUX_MAX_RT_PRIO)
1612                                 return (EINVAL);
1613
1614                         /*
1615                          * Map [1, LINUX_MAX_RT_PRIO - 1] to
1616                          * [0, RTP_PRIO_MAX - RTP_PRIO_MIN] (rounding down).
1617                          */
1618                         sched_param.sched_priority =
1619                             (sched_param.sched_priority - 1) *
1620                             (RTP_PRIO_MAX - RTP_PRIO_MIN + 1) /
1621                             (LINUX_MAX_RT_PRIO - 1);
1622                         break;
1623                 }
1624         }
1625
1626         tdt = linux_tdfind(td, args->pid, -1);
1627         if (tdt == NULL)
1628                 return (ESRCH);
1629
1630         error = kern_sched_setscheduler(td, tdt, policy, &sched_param);
1631         PROC_UNLOCK(tdt->td_proc);
1632         return (error);
1633 }
1634
1635 int
1636 linux_sched_getscheduler(struct thread *td,
1637     struct linux_sched_getscheduler_args *args)
1638 {
1639         struct thread *tdt;
1640         int error, policy;
1641
1642 #ifdef DEBUG
1643         if (ldebug(sched_getscheduler))
1644                 printf(ARGS(sched_getscheduler, "%d"), args->pid);
1645 #endif
1646
1647         tdt = linux_tdfind(td, args->pid, -1);
1648         if (tdt == NULL)
1649                 return (ESRCH);
1650
1651         error = kern_sched_getscheduler(td, tdt, &policy);
1652         PROC_UNLOCK(tdt->td_proc);
1653
1654         switch (policy) {
1655         case SCHED_OTHER:
1656                 td->td_retval[0] = LINUX_SCHED_OTHER;
1657                 break;
1658         case SCHED_FIFO:
1659                 td->td_retval[0] = LINUX_SCHED_FIFO;
1660                 break;
1661         case SCHED_RR:
1662                 td->td_retval[0] = LINUX_SCHED_RR;
1663                 break;
1664         }
1665         return (error);
1666 }
1667
1668 int
1669 linux_sched_get_priority_max(struct thread *td,
1670     struct linux_sched_get_priority_max_args *args)
1671 {
1672         struct sched_get_priority_max_args bsd;
1673
1674 #ifdef DEBUG
1675         if (ldebug(sched_get_priority_max))
1676                 printf(ARGS(sched_get_priority_max, "%d"), args->policy);
1677 #endif
1678
1679         if (linux_map_sched_prio) {
1680                 switch (args->policy) {
1681                 case LINUX_SCHED_OTHER:
1682                         td->td_retval[0] = 0;
1683                         return (0);
1684                 case LINUX_SCHED_FIFO:
1685                 case LINUX_SCHED_RR:
1686                         td->td_retval[0] = LINUX_MAX_RT_PRIO - 1;
1687                         return (0);
1688                 default:
1689                         return (EINVAL);
1690                 }
1691         }
1692
1693         switch (args->policy) {
1694         case LINUX_SCHED_OTHER:
1695                 bsd.policy = SCHED_OTHER;
1696                 break;
1697         case LINUX_SCHED_FIFO:
1698                 bsd.policy = SCHED_FIFO;
1699                 break;
1700         case LINUX_SCHED_RR:
1701                 bsd.policy = SCHED_RR;
1702                 break;
1703         default:
1704                 return (EINVAL);
1705         }
1706         return (sys_sched_get_priority_max(td, &bsd));
1707 }
1708
1709 int
1710 linux_sched_get_priority_min(struct thread *td,
1711     struct linux_sched_get_priority_min_args *args)
1712 {
1713         struct sched_get_priority_min_args bsd;
1714
1715 #ifdef DEBUG
1716         if (ldebug(sched_get_priority_min))
1717                 printf(ARGS(sched_get_priority_min, "%d"), args->policy);
1718 #endif
1719
1720         if (linux_map_sched_prio) {
1721                 switch (args->policy) {
1722                 case LINUX_SCHED_OTHER:
1723                         td->td_retval[0] = 0;
1724                         return (0);
1725                 case LINUX_SCHED_FIFO:
1726                 case LINUX_SCHED_RR:
1727                         td->td_retval[0] = 1;
1728                         return (0);
1729                 default:
1730                         return (EINVAL);
1731                 }
1732         }
1733
1734         switch (args->policy) {
1735         case LINUX_SCHED_OTHER:
1736                 bsd.policy = SCHED_OTHER;
1737                 break;
1738         case LINUX_SCHED_FIFO:
1739                 bsd.policy = SCHED_FIFO;
1740                 break;
1741         case LINUX_SCHED_RR:
1742                 bsd.policy = SCHED_RR;
1743                 break;
1744         default:
1745                 return (EINVAL);
1746         }
1747         return (sys_sched_get_priority_min(td, &bsd));
1748 }
1749
1750 #define REBOOT_CAD_ON   0x89abcdef
1751 #define REBOOT_CAD_OFF  0
1752 #define REBOOT_HALT     0xcdef0123
1753 #define REBOOT_RESTART  0x01234567
1754 #define REBOOT_RESTART2 0xA1B2C3D4
1755 #define REBOOT_POWEROFF 0x4321FEDC
1756 #define REBOOT_MAGIC1   0xfee1dead
1757 #define REBOOT_MAGIC2   0x28121969
1758 #define REBOOT_MAGIC2A  0x05121996
1759 #define REBOOT_MAGIC2B  0x16041998
1760
1761 int
1762 linux_reboot(struct thread *td, struct linux_reboot_args *args)
1763 {
1764         struct reboot_args bsd_args;
1765
1766 #ifdef DEBUG
1767         if (ldebug(reboot))
1768                 printf(ARGS(reboot, "0x%x"), args->cmd);
1769 #endif
1770
1771         if (args->magic1 != REBOOT_MAGIC1)
1772                 return (EINVAL);
1773
1774         switch (args->magic2) {
1775         case REBOOT_MAGIC2:
1776         case REBOOT_MAGIC2A:
1777         case REBOOT_MAGIC2B:
1778                 break;
1779         default:
1780                 return (EINVAL);
1781         }
1782
1783         switch (args->cmd) {
1784         case REBOOT_CAD_ON:
1785         case REBOOT_CAD_OFF:
1786                 return (priv_check(td, PRIV_REBOOT));
1787         case REBOOT_HALT:
1788                 bsd_args.opt = RB_HALT;
1789                 break;
1790         case REBOOT_RESTART:
1791         case REBOOT_RESTART2:
1792                 bsd_args.opt = 0;
1793                 break;
1794         case REBOOT_POWEROFF:
1795                 bsd_args.opt = RB_POWEROFF;
1796                 break;
1797         default:
1798                 return (EINVAL);
1799         }
1800         return (sys_reboot(td, &bsd_args));
1801 }
1802
1803
1804 int
1805 linux_getpid(struct thread *td, struct linux_getpid_args *args)
1806 {
1807
1808 #ifdef DEBUG
1809         if (ldebug(getpid))
1810                 printf(ARGS(getpid, ""));
1811 #endif
1812         td->td_retval[0] = td->td_proc->p_pid;
1813
1814         return (0);
1815 }
1816
1817 int
1818 linux_gettid(struct thread *td, struct linux_gettid_args *args)
1819 {
1820         struct linux_emuldata *em;
1821
1822 #ifdef DEBUG
1823         if (ldebug(gettid))
1824                 printf(ARGS(gettid, ""));
1825 #endif
1826
1827         em = em_find(td);
1828         KASSERT(em != NULL, ("gettid: emuldata not found.\n"));
1829
1830         td->td_retval[0] = em->em_tid;
1831
1832         return (0);
1833 }
1834
1835
1836 int
1837 linux_getppid(struct thread *td, struct linux_getppid_args *args)
1838 {
1839
1840 #ifdef DEBUG
1841         if (ldebug(getppid))
1842                 printf(ARGS(getppid, ""));
1843 #endif
1844
1845         td->td_retval[0] = kern_getppid(td);
1846         return (0);
1847 }
1848
1849 int
1850 linux_getgid(struct thread *td, struct linux_getgid_args *args)
1851 {
1852
1853 #ifdef DEBUG
1854         if (ldebug(getgid))
1855                 printf(ARGS(getgid, ""));
1856 #endif
1857
1858         td->td_retval[0] = td->td_ucred->cr_rgid;
1859         return (0);
1860 }
1861
1862 int
1863 linux_getuid(struct thread *td, struct linux_getuid_args *args)
1864 {
1865
1866 #ifdef DEBUG
1867         if (ldebug(getuid))
1868                 printf(ARGS(getuid, ""));
1869 #endif
1870
1871         td->td_retval[0] = td->td_ucred->cr_ruid;
1872         return (0);
1873 }
1874
1875
1876 int
1877 linux_getsid(struct thread *td, struct linux_getsid_args *args)
1878 {
1879         struct getsid_args bsd;
1880
1881 #ifdef DEBUG
1882         if (ldebug(getsid))
1883                 printf(ARGS(getsid, "%i"), args->pid);
1884 #endif
1885
1886         bsd.pid = args->pid;
1887         return (sys_getsid(td, &bsd));
1888 }
1889
1890 int
1891 linux_nosys(struct thread *td, struct nosys_args *ignore)
1892 {
1893
1894         return (ENOSYS);
1895 }
1896
1897 int
1898 linux_getpriority(struct thread *td, struct linux_getpriority_args *args)
1899 {
1900         struct getpriority_args bsd_args;
1901         int error;
1902
1903 #ifdef DEBUG
1904         if (ldebug(getpriority))
1905                 printf(ARGS(getpriority, "%i, %i"), args->which, args->who);
1906 #endif
1907
1908         bsd_args.which = args->which;
1909         bsd_args.who = args->who;
1910         error = sys_getpriority(td, &bsd_args);
1911         td->td_retval[0] = 20 - td->td_retval[0];
1912         return (error);
1913 }
1914
1915 int
1916 linux_sethostname(struct thread *td, struct linux_sethostname_args *args)
1917 {
1918         int name[2];
1919
1920 #ifdef DEBUG
1921         if (ldebug(sethostname))
1922                 printf(ARGS(sethostname, "*, %i"), args->len);
1923 #endif
1924
1925         name[0] = CTL_KERN;
1926         name[1] = KERN_HOSTNAME;
1927         return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname,
1928             args->len, 0, 0));
1929 }
1930
1931 int
1932 linux_setdomainname(struct thread *td, struct linux_setdomainname_args *args)
1933 {
1934         int name[2];
1935
1936 #ifdef DEBUG
1937         if (ldebug(setdomainname))
1938                 printf(ARGS(setdomainname, "*, %i"), args->len);
1939 #endif
1940
1941         name[0] = CTL_KERN;
1942         name[1] = KERN_NISDOMAINNAME;
1943         return (userland_sysctl(td, name, 2, 0, 0, 0, args->name,
1944             args->len, 0, 0));
1945 }
1946
1947 int
1948 linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
1949 {
1950
1951 #ifdef DEBUG
1952         if (ldebug(exit_group))
1953                 printf(ARGS(exit_group, "%i"), args->error_code);
1954 #endif
1955
1956         LINUX_CTR2(exit_group, "thread(%d) (%d)", td->td_tid,
1957             args->error_code);
1958
1959         /*
1960          * XXX: we should send a signal to the parent if
1961          * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?)
1962          * as it doesnt occur often.
1963          */
1964         exit1(td, args->error_code, 0);
1965                 /* NOTREACHED */
1966 }
1967
1968 #define _LINUX_CAPABILITY_VERSION_1  0x19980330
1969 #define _LINUX_CAPABILITY_VERSION_2  0x20071026
1970 #define _LINUX_CAPABILITY_VERSION_3  0x20080522
1971
1972 struct l_user_cap_header {
1973         l_int   version;
1974         l_int   pid;
1975 };
1976
1977 struct l_user_cap_data {
1978         l_int   effective;
1979         l_int   permitted;
1980         l_int   inheritable;
1981 };
1982
1983 int
1984 linux_capget(struct thread *td, struct linux_capget_args *uap)
1985 {
1986         struct l_user_cap_header luch;
1987         struct l_user_cap_data lucd[2];
1988         int error, u32s;
1989
1990         if (uap->hdrp == NULL)
1991                 return (EFAULT);
1992
1993         error = copyin(uap->hdrp, &luch, sizeof(luch));
1994         if (error != 0)
1995                 return (error);
1996
1997         switch (luch.version) {
1998         case _LINUX_CAPABILITY_VERSION_1:
1999                 u32s = 1;
2000                 break;
2001         case _LINUX_CAPABILITY_VERSION_2:
2002         case _LINUX_CAPABILITY_VERSION_3:
2003                 u32s = 2;
2004                 break;
2005         default:
2006 #ifdef DEBUG
2007                 if (ldebug(capget))
2008                         printf(LMSG("invalid capget capability version 0x%x"),
2009                             luch.version);
2010 #endif
2011                 luch.version = _LINUX_CAPABILITY_VERSION_1;
2012                 error = copyout(&luch, uap->hdrp, sizeof(luch));
2013                 if (error)
2014                         return (error);
2015                 return (EINVAL);
2016         }
2017
2018         if (luch.pid)
2019                 return (EPERM);
2020
2021         if (uap->datap) {
2022                 /*
2023                  * The current implementation doesn't support setting
2024                  * a capability (it's essentially a stub) so indicate
2025                  * that no capabilities are currently set or available
2026                  * to request.
2027                  */
2028                 memset(&lucd, 0, u32s * sizeof(lucd[0]));
2029                 error = copyout(&lucd, uap->datap, u32s * sizeof(lucd[0]));
2030         }
2031
2032         return (error);
2033 }
2034
2035 int
2036 linux_capset(struct thread *td, struct linux_capset_args *uap)
2037 {
2038         struct l_user_cap_header luch;
2039         struct l_user_cap_data lucd[2];
2040         int error, i, u32s;
2041
2042         if (uap->hdrp == NULL || uap->datap == NULL)
2043                 return (EFAULT);
2044
2045         error = copyin(uap->hdrp, &luch, sizeof(luch));
2046         if (error != 0)
2047                 return (error);
2048
2049         switch (luch.version) {
2050         case _LINUX_CAPABILITY_VERSION_1:
2051                 u32s = 1;
2052                 break;
2053         case _LINUX_CAPABILITY_VERSION_2:
2054         case _LINUX_CAPABILITY_VERSION_3:
2055                 u32s = 2;
2056                 break;
2057         default:
2058 #ifdef DEBUG
2059                 if (ldebug(capset))
2060                         printf(LMSG("invalid capset capability version 0x%x"),
2061                             luch.version);
2062 #endif
2063                 luch.version = _LINUX_CAPABILITY_VERSION_1;
2064                 error = copyout(&luch, uap->hdrp, sizeof(luch));
2065                 if (error)
2066                         return (error);
2067                 return (EINVAL);
2068         }
2069
2070         if (luch.pid)
2071                 return (EPERM);
2072
2073         error = copyin(uap->datap, &lucd, u32s * sizeof(lucd[0]));
2074         if (error != 0)
2075                 return (error);
2076
2077         /* We currently don't support setting any capabilities. */
2078         for (i = 0; i < u32s; i++) {
2079                 if (lucd[i].effective || lucd[i].permitted ||
2080                     lucd[i].inheritable) {
2081                         linux_msg(td,
2082                             "capset[%d] effective=0x%x, permitted=0x%x, "
2083                             "inheritable=0x%x is not implemented", i,
2084                             (int)lucd[i].effective, (int)lucd[i].permitted,
2085                             (int)lucd[i].inheritable);
2086                         return (EPERM);
2087                 }
2088         }
2089
2090         return (0);
2091 }
2092
2093 int
2094 linux_prctl(struct thread *td, struct linux_prctl_args *args)
2095 {
2096         int error = 0, max_size;
2097         struct proc *p = td->td_proc;
2098         char comm[LINUX_MAX_COMM_LEN];
2099         int pdeath_signal;
2100
2101 #ifdef DEBUG
2102         if (ldebug(prctl))
2103                 printf(ARGS(prctl, "%d, %ju, %ju, %ju, %ju"), args->option,
2104                     (uintmax_t)args->arg2, (uintmax_t)args->arg3,
2105                     (uintmax_t)args->arg4, (uintmax_t)args->arg5);
2106 #endif
2107
2108         switch (args->option) {
2109         case LINUX_PR_SET_PDEATHSIG:
2110                 if (!LINUX_SIG_VALID(args->arg2))
2111                         return (EINVAL);
2112                 pdeath_signal = linux_to_bsd_signal(args->arg2);
2113                 return (kern_procctl(td, P_PID, 0, PROC_PDEATHSIG_CTL,
2114                     &pdeath_signal));
2115         case LINUX_PR_GET_PDEATHSIG:
2116                 error = kern_procctl(td, P_PID, 0, PROC_PDEATHSIG_STATUS,
2117                     &pdeath_signal);
2118                 if (error != 0)
2119                         return (error);
2120                 pdeath_signal = bsd_to_linux_signal(pdeath_signal);
2121                 return (copyout(&pdeath_signal,
2122                     (void *)(register_t)args->arg2,
2123                     sizeof(pdeath_signal)));
2124                 break;
2125         case LINUX_PR_GET_KEEPCAPS:
2126                 /*
2127                  * Indicate that we always clear the effective and
2128                  * permitted capability sets when the user id becomes
2129                  * non-zero (actually the capability sets are simply
2130                  * always zero in the current implementation).
2131                  */
2132                 td->td_retval[0] = 0;
2133                 break;
2134         case LINUX_PR_SET_KEEPCAPS:
2135                 /*
2136                  * Ignore requests to keep the effective and permitted
2137                  * capability sets when the user id becomes non-zero.
2138                  */
2139                 break;
2140         case LINUX_PR_SET_NAME:
2141                 /*
2142                  * To be on the safe side we need to make sure to not
2143                  * overflow the size a Linux program expects. We already
2144                  * do this here in the copyin, so that we don't need to
2145                  * check on copyout.
2146                  */
2147                 max_size = MIN(sizeof(comm), sizeof(p->p_comm));
2148                 error = copyinstr((void *)(register_t)args->arg2, comm,
2149                     max_size, NULL);
2150
2151                 /* Linux silently truncates the name if it is too long. */
2152                 if (error == ENAMETOOLONG) {
2153                         /*
2154                          * XXX: copyinstr() isn't documented to populate the
2155                          * array completely, so do a copyin() to be on the
2156                          * safe side. This should be changed in case
2157                          * copyinstr() is changed to guarantee this.
2158                          */
2159                         error = copyin((void *)(register_t)args->arg2, comm,
2160                             max_size - 1);
2161                         comm[max_size - 1] = '\0';
2162                 }
2163                 if (error)
2164                         return (error);
2165
2166                 PROC_LOCK(p);
2167                 strlcpy(p->p_comm, comm, sizeof(p->p_comm));
2168                 PROC_UNLOCK(p);
2169                 break;
2170         case LINUX_PR_GET_NAME:
2171                 PROC_LOCK(p);
2172                 strlcpy(comm, p->p_comm, sizeof(comm));
2173                 PROC_UNLOCK(p);
2174                 error = copyout(comm, (void *)(register_t)args->arg2,
2175                     strlen(comm) + 1);
2176                 break;
2177         default:
2178                 error = EINVAL;
2179                 break;
2180         }
2181
2182         return (error);
2183 }
2184
2185 int
2186 linux_sched_setparam(struct thread *td,
2187     struct linux_sched_setparam_args *uap)
2188 {
2189         struct sched_param sched_param;
2190         struct thread *tdt;
2191         int error, policy;
2192
2193 #ifdef DEBUG
2194         if (ldebug(sched_setparam))
2195                 printf(ARGS(sched_setparam, "%d, *"), uap->pid);
2196 #endif
2197
2198         error = copyin(uap->param, &sched_param, sizeof(sched_param));
2199         if (error)
2200                 return (error);
2201
2202         tdt = linux_tdfind(td, uap->pid, -1);
2203         if (tdt == NULL)
2204                 return (ESRCH);
2205
2206         if (linux_map_sched_prio) {
2207                 error = kern_sched_getscheduler(td, tdt, &policy);
2208                 if (error)
2209                         goto out;
2210
2211                 switch (policy) {
2212                 case SCHED_OTHER:
2213                         if (sched_param.sched_priority != 0) {
2214                                 error = EINVAL;
2215                                 goto out;
2216                         }
2217                         sched_param.sched_priority =
2218                             PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE;
2219                         break;
2220                 case SCHED_FIFO:
2221                 case SCHED_RR:
2222                         if (sched_param.sched_priority < 1 ||
2223                             sched_param.sched_priority >= LINUX_MAX_RT_PRIO) {
2224                                 error = EINVAL;
2225                                 goto out;
2226                         }
2227                         /*
2228                          * Map [1, LINUX_MAX_RT_PRIO - 1] to
2229                          * [0, RTP_PRIO_MAX - RTP_PRIO_MIN] (rounding down).
2230                          */
2231                         sched_param.sched_priority =
2232                             (sched_param.sched_priority - 1) *
2233                             (RTP_PRIO_MAX - RTP_PRIO_MIN + 1) /
2234                             (LINUX_MAX_RT_PRIO - 1);
2235                         break;
2236                 }
2237         }
2238
2239         error = kern_sched_setparam(td, tdt, &sched_param);
2240 out:    PROC_UNLOCK(tdt->td_proc);
2241         return (error);
2242 }
2243
2244 int
2245 linux_sched_getparam(struct thread *td,
2246     struct linux_sched_getparam_args *uap)
2247 {
2248         struct sched_param sched_param;
2249         struct thread *tdt;
2250         int error, policy;
2251
2252 #ifdef DEBUG
2253         if (ldebug(sched_getparam))
2254                 printf(ARGS(sched_getparam, "%d, *"), uap->pid);
2255 #endif
2256
2257         tdt = linux_tdfind(td, uap->pid, -1);
2258         if (tdt == NULL)
2259                 return (ESRCH);
2260
2261         error = kern_sched_getparam(td, tdt, &sched_param);
2262         if (error) {
2263                 PROC_UNLOCK(tdt->td_proc);
2264                 return (error);
2265         }
2266
2267         if (linux_map_sched_prio) {
2268                 error = kern_sched_getscheduler(td, tdt, &policy);
2269                 PROC_UNLOCK(tdt->td_proc);
2270                 if (error)
2271                         return (error);
2272
2273                 switch (policy) {
2274                 case SCHED_OTHER:
2275                         sched_param.sched_priority = 0;
2276                         break;
2277                 case SCHED_FIFO:
2278                 case SCHED_RR:
2279                         /*
2280                          * Map [0, RTP_PRIO_MAX - RTP_PRIO_MIN] to
2281                          * [1, LINUX_MAX_RT_PRIO - 1] (rounding up).
2282                          */
2283                         sched_param.sched_priority =
2284                             (sched_param.sched_priority *
2285                             (LINUX_MAX_RT_PRIO - 1) +
2286                             (RTP_PRIO_MAX - RTP_PRIO_MIN - 1)) /
2287                             (RTP_PRIO_MAX - RTP_PRIO_MIN) + 1;
2288                         break;
2289                 }
2290         } else
2291                 PROC_UNLOCK(tdt->td_proc);
2292
2293         error = copyout(&sched_param, uap->param, sizeof(sched_param));
2294         return (error);
2295 }
2296
2297 /*
2298  * Get affinity of a process.
2299  */
2300 int
2301 linux_sched_getaffinity(struct thread *td,
2302     struct linux_sched_getaffinity_args *args)
2303 {
2304         int error;
2305         struct thread *tdt;
2306
2307 #ifdef DEBUG
2308         if (ldebug(sched_getaffinity))
2309                 printf(ARGS(sched_getaffinity, "%d, %d, *"), args->pid,
2310                     args->len);
2311 #endif
2312         if (args->len < sizeof(cpuset_t))
2313                 return (EINVAL);
2314
2315         tdt = linux_tdfind(td, args->pid, -1);
2316         if (tdt == NULL)
2317                 return (ESRCH);
2318
2319         PROC_UNLOCK(tdt->td_proc);
2320
2321         error = kern_cpuset_getaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID,
2322             tdt->td_tid, sizeof(cpuset_t), (cpuset_t *)args->user_mask_ptr);
2323         if (error == 0)
2324                 td->td_retval[0] = sizeof(cpuset_t);
2325
2326         return (error);
2327 }
2328
2329 /*
2330  *  Set affinity of a process.
2331  */
2332 int
2333 linux_sched_setaffinity(struct thread *td,
2334     struct linux_sched_setaffinity_args *args)
2335 {
2336         struct thread *tdt;
2337
2338 #ifdef DEBUG
2339         if (ldebug(sched_setaffinity))
2340                 printf(ARGS(sched_setaffinity, "%d, %d, *"), args->pid,
2341                     args->len);
2342 #endif
2343         if (args->len < sizeof(cpuset_t))
2344                 return (EINVAL);
2345
2346         tdt = linux_tdfind(td, args->pid, -1);
2347         if (tdt == NULL)
2348                 return (ESRCH);
2349
2350         PROC_UNLOCK(tdt->td_proc);
2351
2352         return (kern_cpuset_setaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID,
2353             tdt->td_tid, sizeof(cpuset_t), (cpuset_t *) args->user_mask_ptr));
2354 }
2355
2356 struct linux_rlimit64 {
2357         uint64_t        rlim_cur;
2358         uint64_t        rlim_max;
2359 };
2360
2361 int
2362 linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args)
2363 {
2364         struct rlimit rlim, nrlim;
2365         struct linux_rlimit64 lrlim;
2366         struct proc *p;
2367         u_int which;
2368         int flags;
2369         int error;
2370
2371 #ifdef DEBUG
2372         if (ldebug(prlimit64))
2373                 printf(ARGS(prlimit64, "%d, %d, %p, %p"), args->pid,
2374                     args->resource, (void *)args->new, (void *)args->old);
2375 #endif
2376
2377         if (args->resource >= LINUX_RLIM_NLIMITS)
2378                 return (EINVAL);
2379
2380         which = linux_to_bsd_resource[args->resource];
2381         if (which == -1)
2382                 return (EINVAL);
2383
2384         if (args->new != NULL) {
2385                 /*
2386                  * Note. Unlike FreeBSD where rlim is signed 64-bit Linux
2387                  * rlim is unsigned 64-bit. FreeBSD treats negative limits
2388                  * as INFINITY so we do not need a conversion even.
2389                  */
2390                 error = copyin(args->new, &nrlim, sizeof(nrlim));
2391                 if (error != 0)
2392                         return (error);
2393         }
2394
2395         flags = PGET_HOLD | PGET_NOTWEXIT;
2396         if (args->new != NULL)
2397                 flags |= PGET_CANDEBUG;
2398         else
2399                 flags |= PGET_CANSEE;
2400         if (args->pid == 0) {
2401                 p = td->td_proc;
2402                 PHOLD(p);
2403         } else {
2404                 error = pget(args->pid, flags, &p);
2405                 if (error != 0)
2406                         return (error);
2407         }
2408         if (args->old != NULL) {
2409                 PROC_LOCK(p);
2410                 lim_rlimit_proc(p, which, &rlim);
2411                 PROC_UNLOCK(p);
2412                 if (rlim.rlim_cur == RLIM_INFINITY)
2413                         lrlim.rlim_cur = LINUX_RLIM_INFINITY;
2414                 else
2415                         lrlim.rlim_cur = rlim.rlim_cur;
2416                 if (rlim.rlim_max == RLIM_INFINITY)
2417                         lrlim.rlim_max = LINUX_RLIM_INFINITY;
2418                 else
2419                         lrlim.rlim_max = rlim.rlim_max;
2420                 error = copyout(&lrlim, args->old, sizeof(lrlim));
2421                 if (error != 0)
2422                         goto out;
2423         }
2424
2425         if (args->new != NULL)
2426                 error = kern_proc_setrlimit(td, p, which, &nrlim);
2427
2428  out:
2429         PRELE(p);
2430         return (error);
2431 }
2432
2433 int
2434 linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
2435 {
2436         struct timeval utv, tv0, tv1, *tvp;
2437         struct l_pselect6arg lpse6;
2438         struct l_timespec lts;
2439         struct timespec uts;
2440         l_sigset_t l_ss;
2441         sigset_t *ssp;
2442         sigset_t ss;
2443         int error;
2444
2445         ssp = NULL;
2446         if (args->sig != NULL) {
2447                 error = copyin(args->sig, &lpse6, sizeof(lpse6));
2448                 if (error != 0)
2449                         return (error);
2450                 if (lpse6.ss_len != sizeof(l_ss))
2451                         return (EINVAL);
2452                 if (lpse6.ss != 0) {
2453                         error = copyin(PTRIN(lpse6.ss), &l_ss,
2454                             sizeof(l_ss));
2455                         if (error != 0)
2456                                 return (error);
2457                         linux_to_bsd_sigset(&l_ss, &ss);
2458                         ssp = &ss;
2459                 }
2460         }
2461
2462         /*
2463          * Currently glibc changes nanosecond number to microsecond.
2464          * This mean losing precision but for now it is hardly seen.
2465          */
2466         if (args->tsp != NULL) {
2467                 error = copyin(args->tsp, &lts, sizeof(lts));
2468                 if (error != 0)
2469                         return (error);
2470                 error = linux_to_native_timespec(&uts, &lts);
2471                 if (error != 0)
2472                         return (error);
2473
2474                 TIMESPEC_TO_TIMEVAL(&utv, &uts);
2475                 if (itimerfix(&utv))
2476                         return (EINVAL);
2477
2478                 microtime(&tv0);
2479                 tvp = &utv;
2480         } else
2481                 tvp = NULL;
2482
2483         error = kern_pselect(td, args->nfds, args->readfds, args->writefds,
2484             args->exceptfds, tvp, ssp, LINUX_NFDBITS);
2485
2486         if (error == 0 && args->tsp != NULL) {
2487                 if (td->td_retval[0] != 0) {
2488                         /*
2489                          * Compute how much time was left of the timeout,
2490                          * by subtracting the current time and the time
2491                          * before we started the call, and subtracting
2492                          * that result from the user-supplied value.
2493                          */
2494
2495                         microtime(&tv1);
2496                         timevalsub(&tv1, &tv0);
2497                         timevalsub(&utv, &tv1);
2498                         if (utv.tv_sec < 0)
2499                                 timevalclear(&utv);
2500                 } else
2501                         timevalclear(&utv);
2502
2503                 TIMEVAL_TO_TIMESPEC(&utv, &uts);
2504
2505                 error = native_to_linux_timespec(&lts, &uts);
2506                 if (error == 0)
2507                         error = copyout(&lts, args->tsp, sizeof(lts));
2508         }
2509
2510         return (error);
2511 }
2512
2513 int
2514 linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
2515 {
2516         struct timespec ts0, ts1;
2517         struct l_timespec lts;
2518         struct timespec uts, *tsp;
2519         l_sigset_t l_ss;
2520         sigset_t *ssp;
2521         sigset_t ss;
2522         int error;
2523
2524         if (args->sset != NULL) {
2525                 if (args->ssize != sizeof(l_ss))
2526                         return (EINVAL);
2527                 error = copyin(args->sset, &l_ss, sizeof(l_ss));
2528                 if (error)
2529                         return (error);
2530                 linux_to_bsd_sigset(&l_ss, &ss);
2531                 ssp = &ss;
2532         } else
2533                 ssp = NULL;
2534         if (args->tsp != NULL) {
2535                 error = copyin(args->tsp, &lts, sizeof(lts));
2536                 if (error)
2537                         return (error);
2538                 error = linux_to_native_timespec(&uts, &lts);
2539                 if (error != 0)
2540                         return (error);
2541
2542                 nanotime(&ts0);
2543                 tsp = &uts;
2544         } else
2545                 tsp = NULL;
2546
2547         error = kern_poll(td, args->fds, args->nfds, tsp, ssp);
2548
2549         if (error == 0 && args->tsp != NULL) {
2550                 if (td->td_retval[0]) {
2551                         nanotime(&ts1);
2552                         timespecsub(&ts1, &ts0, &ts1);
2553                         timespecsub(&uts, &ts1, &uts);
2554                         if (uts.tv_sec < 0)
2555                                 timespecclear(&uts);
2556                 } else
2557                         timespecclear(&uts);
2558
2559                 error = native_to_linux_timespec(&lts, &uts);
2560                 if (error == 0)
2561                         error = copyout(&lts, args->tsp, sizeof(lts));
2562         }
2563
2564         return (error);
2565 }
2566
2567 #if defined(DEBUG) || defined(KTR)
2568 /* XXX: can be removed when every ldebug(...) and KTR stuff are removed. */
2569
2570 #ifdef COMPAT_LINUX32
2571 #define L_MAXSYSCALL    LINUX32_SYS_MAXSYSCALL
2572 #else
2573 #define L_MAXSYSCALL    LINUX_SYS_MAXSYSCALL
2574 #endif
2575
2576 u_char linux_debug_map[howmany(L_MAXSYSCALL, sizeof(u_char))];
2577
2578 static int
2579 linux_debug(int syscall, int toggle, int global)
2580 {
2581
2582         if (global) {
2583                 char c = toggle ? 0 : 0xff;
2584
2585                 memset(linux_debug_map, c, sizeof(linux_debug_map));
2586                 return (0);
2587         }
2588         if (syscall < 0 || syscall >= L_MAXSYSCALL)
2589                 return (EINVAL);
2590         if (toggle)
2591                 clrbit(linux_debug_map, syscall);
2592         else
2593                 setbit(linux_debug_map, syscall);
2594         return (0);
2595 }
2596 #undef L_MAXSYSCALL
2597
2598 /*
2599  * Usage: sysctl linux.debug=<syscall_nr>.<0/1>
2600  *
2601  *    E.g.: sysctl linux.debug=21.0
2602  *
2603  * As a special case, syscall "all" will apply to all syscalls globally.
2604  */
2605 #define LINUX_MAX_DEBUGSTR      16
2606 int
2607 linux_sysctl_debug(SYSCTL_HANDLER_ARGS)
2608 {
2609         char value[LINUX_MAX_DEBUGSTR], *p;
2610         int error, sysc, toggle;
2611         int global = 0;
2612
2613         value[0] = '\0';
2614         error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req);
2615         if (error || req->newptr == NULL)
2616                 return (error);
2617         for (p = value; *p != '\0' && *p != '.'; p++);
2618         if (*p == '\0')
2619                 return (EINVAL);
2620         *p++ = '\0';
2621         sysc = strtol(value, NULL, 0);
2622         toggle = strtol(p, NULL, 0);
2623         if (strcmp(value, "all") == 0)
2624                 global = 1;
2625         error = linux_debug(sysc, toggle, global);
2626         return (error);
2627 }
2628
2629 #endif /* DEBUG || KTR */
2630
2631 int
2632 linux_sched_rr_get_interval(struct thread *td,
2633     struct linux_sched_rr_get_interval_args *uap)
2634 {
2635         struct timespec ts;
2636         struct l_timespec lts;
2637         struct thread *tdt;
2638         int error;
2639
2640         /*
2641          * According to man in case the invalid pid specified
2642          * EINVAL should be returned.
2643          */
2644         if (uap->pid < 0)
2645                 return (EINVAL);
2646
2647         tdt = linux_tdfind(td, uap->pid, -1);
2648         if (tdt == NULL)
2649                 return (ESRCH);
2650
2651         error = kern_sched_rr_get_interval_td(td, tdt, &ts);
2652         PROC_UNLOCK(tdt->td_proc);
2653         if (error != 0)
2654                 return (error);
2655         error = native_to_linux_timespec(&lts, &ts);
2656         if (error != 0)
2657                 return (error);
2658         return (copyout(&lts, uap->interval, sizeof(lts)));
2659 }
2660
2661 /*
2662  * In case when the Linux thread is the initial thread in
2663  * the thread group thread id is equal to the process id.
2664  * Glibc depends on this magic (assert in pthread_getattr_np.c).
2665  */
2666 struct thread *
2667 linux_tdfind(struct thread *td, lwpid_t tid, pid_t pid)
2668 {
2669         struct linux_emuldata *em;
2670         struct thread *tdt;
2671         struct proc *p;
2672
2673         tdt = NULL;
2674         if (tid == 0 || tid == td->td_tid) {
2675                 tdt = td;
2676                 PROC_LOCK(tdt->td_proc);
2677         } else if (tid > PID_MAX)
2678                 tdt = tdfind(tid, pid);
2679         else {
2680                 /*
2681                  * Initial thread where the tid equal to the pid.
2682                  */
2683                 p = pfind(tid);
2684                 if (p != NULL) {
2685                         if (SV_PROC_ABI(p) != SV_ABI_LINUX) {
2686                                 /*
2687                                  * p is not a Linuxulator process.
2688                                  */
2689                                 PROC_UNLOCK(p);
2690                                 return (NULL);
2691                         }
2692                         FOREACH_THREAD_IN_PROC(p, tdt) {
2693                                 em = em_find(tdt);
2694                                 if (tid == em->em_tid)
2695                                         return (tdt);
2696                         }
2697                         PROC_UNLOCK(p);
2698                 }
2699                 return (NULL);
2700         }
2701
2702         return (tdt);
2703 }
2704
2705 void
2706 linux_to_bsd_waitopts(int options, int *bsdopts)
2707 {
2708
2709         if (options & LINUX_WNOHANG)
2710                 *bsdopts |= WNOHANG;
2711         if (options & LINUX_WUNTRACED)
2712                 *bsdopts |= WUNTRACED;
2713         if (options & LINUX_WEXITED)
2714                 *bsdopts |= WEXITED;
2715         if (options & LINUX_WCONTINUED)
2716                 *bsdopts |= WCONTINUED;
2717         if (options & LINUX_WNOWAIT)
2718                 *bsdopts |= WNOWAIT;
2719
2720         if (options & __WCLONE)
2721                 *bsdopts |= WLINUXCLONE;
2722 }
2723
2724 int
2725 linux_getrandom(struct thread *td, struct linux_getrandom_args *args)
2726 {
2727         struct uio uio;
2728         struct iovec iov;
2729         int error;
2730
2731         if (args->flags & ~(LINUX_GRND_NONBLOCK|LINUX_GRND_RANDOM))
2732                 return (EINVAL);
2733         if (args->count > INT_MAX)
2734                 args->count = INT_MAX;
2735
2736         iov.iov_base = args->buf;
2737         iov.iov_len = args->count;
2738
2739         uio.uio_iov = &iov;
2740         uio.uio_iovcnt = 1;
2741         uio.uio_resid = iov.iov_len;
2742         uio.uio_segflg = UIO_USERSPACE;
2743         uio.uio_rw = UIO_READ;
2744         uio.uio_td = td;
2745
2746         error = read_random_uio(&uio, args->flags & LINUX_GRND_NONBLOCK);
2747         if (error == 0)
2748                 td->td_retval[0] = args->count - uio.uio_resid;
2749         return (error);
2750 }
2751
2752 int
2753 linux_mincore(struct thread *td, struct linux_mincore_args *args)
2754 {
2755
2756         /* Needs to be page-aligned */
2757         if (args->start & PAGE_MASK)
2758                 return (EINVAL);
2759         return (kern_mincore(td, args->start, args->len, args->vec));
2760 }
2761
2762 #define SYSLOG_TAG      "<6>"
2763
2764 int
2765 linux_syslog(struct thread *td, struct linux_syslog_args *args)
2766 {
2767         char buf[128], *src, *dst;
2768         u_int seq;
2769         int buflen, error;
2770
2771         if (args->type != LINUX_SYSLOG_ACTION_READ_ALL) {
2772                 linux_msg(td, "syslog unsupported type 0x%x", args->type);
2773                 return (EINVAL);
2774         }
2775
2776         if (args->len < 6) {
2777                 td->td_retval[0] = 0;
2778                 return (0);
2779         }
2780
2781         error = priv_check(td, PRIV_MSGBUF);
2782         if (error)
2783                 return (error);
2784
2785         mtx_lock(&msgbuf_lock);
2786         msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
2787         mtx_unlock(&msgbuf_lock);
2788
2789         dst = args->buf;
2790         error = copyout(&SYSLOG_TAG, dst, sizeof(SYSLOG_TAG));
2791         /* The -1 is to skip the trailing '\0'. */
2792         dst += sizeof(SYSLOG_TAG) - 1;
2793
2794         while (error == 0) {
2795                 mtx_lock(&msgbuf_lock);
2796                 buflen = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
2797                 mtx_unlock(&msgbuf_lock);
2798
2799                 if (buflen == 0)
2800                         break;
2801
2802                 for (src = buf; src < buf + buflen && error == 0; src++) {
2803                         if (*src == '\0')
2804                                 continue;
2805
2806                         if (dst >= args->buf + args->len)
2807                                 goto out;
2808
2809                         error = copyout(src, dst, 1);
2810                         dst++;
2811
2812                         if (*src == '\n' && *(src + 1) != '<' &&
2813                             dst + sizeof(SYSLOG_TAG) < args->buf + args->len) {
2814                                 error = copyout(&SYSLOG_TAG,
2815                                     dst, sizeof(SYSLOG_TAG));
2816                                 dst += sizeof(SYSLOG_TAG) - 1;
2817                         }
2818                 }
2819         }
2820 out:
2821         td->td_retval[0] = dst - args->buf;
2822         return (error);
2823 }
2824
2825 int
2826 linux_getcpu(struct thread *td, struct linux_getcpu_args *args)
2827 {
2828         int cpu, error, node;
2829
2830         cpu = td->td_oncpu; /* Make sure it doesn't change during copyout(9) */
2831         error = 0;
2832         node = cpuid_to_pcpu[cpu]->pc_domain;
2833
2834         if (args->cpu != NULL)
2835                 error = copyout(&cpu, args->cpu, sizeof(l_int));
2836         if (args->node != NULL)
2837                 error = copyout(&node, args->node, sizeof(l_int));
2838         return (error);
2839 }