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 #include <sys/param.h>
34 #include <sys/fcntl.h>
35 #include <sys/jail.h>
36 #include <sys/imgact.h>
37 #include <sys/limits.h>
38 #include <sys/lock.h>
39 #include <sys/membarrier.h>
40 #include <sys/msgbuf.h>
41 #include <sys/mqueue.h>
42 #include <sys/mutex.h>
43 #include <sys/poll.h>
44 #include <sys/priv.h>
45 #include <sys/proc.h>
46 #include <sys/procctl.h>
47 #include <sys/reboot.h>
48 #include <sys/random.h>
49 #include <sys/resourcevar.h>
50 #include <sys/rtprio.h>
51 #include <sys/sched.h>
52 #include <sys/smp.h>
53 #include <sys/stat.h>
54 #include <sys/syscallsubr.h>
55 #include <sys/sysctl.h>
56 #include <sys/sysent.h>
57 #include <sys/sysproto.h>
58 #include <sys/time.h>
59 #include <sys/unistd.h>
60 #include <sys/vmmeter.h>
61 #include <sys/vnode.h>
62
63 #include <security/audit/audit.h>
64 #include <security/mac/mac_framework.h>
65
66 #include <vm/pmap.h>
67 #include <vm/vm_map.h>
68 #include <vm/swap_pager.h>
69
70 #ifdef COMPAT_LINUX32
71 #include <machine/../linux32/linux.h>
72 #include <machine/../linux32/linux32_proto.h>
73 #else
74 #include <machine/../linux/linux.h>
75 #include <machine/../linux/linux_proto.h>
76 #endif
77
78 #include <compat/linux/linux_common.h>
79 #include <compat/linux/linux_dtrace.h>
80 #include <compat/linux/linux_file.h>
81 #include <compat/linux/linux_mib.h>
82 #include <compat/linux/linux_mmap.h>
83 #include <compat/linux/linux_signal.h>
84 #include <compat/linux/linux_time.h>
85 #include <compat/linux/linux_util.h>
86 #include <compat/linux/linux_emul.h>
87 #include <compat/linux/linux_misc.h>
88
89 int stclohz; /* Statistics clock frequency */
90
91 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
92 RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
93 RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE,
94 RLIMIT_MEMLOCK, RLIMIT_AS
95 };
96
97 struct l_sysinfo {
98 l_long uptime; /* Seconds since boot */
99 l_ulong loads[3]; /* 1, 5, and 15 minute load averages */
100 #define LINUX_SYSINFO_LOADS_SCALE 65536
101 l_ulong totalram; /* Total usable main memory size */
102 l_ulong freeram; /* Available memory size */
103 l_ulong sharedram; /* Amount of shared memory */
104 l_ulong bufferram; /* Memory used by buffers */
105 l_ulong totalswap; /* Total swap space size */
106 l_ulong freeswap; /* swap space still available */
107 l_ushort procs; /* Number of current processes */
108 l_ushort pads;
109 l_ulong totalhigh;
110 l_ulong freehigh;
111 l_uint mem_unit;
112 char _f[20-2*sizeof(l_long)-sizeof(l_int)]; /* padding */
113 };
114
115 struct l_pselect6arg {
116 l_uintptr_t ss;
117 l_size_t ss_len;
118 };
119
120 /**
121 * `SCHED_ATTR_SIZE_VER0` represents the size of the initial published structure.
122 *
123 * See `linux/kernel/sched/syscalls.c` for more details.
124 */
125 #define LINUX_SCHED_ATTR_SIZE_VER0 48
126 /**
127 * Linux struct sched_attr
128 */
129 struct linux_sched_attr {
130 l_uint size;
131 l_uint sched_policy;
132 uint64_t sched_flags;
133 int32_t sched_nice;
134 l_uint sched_priority;
135
136 uint64_t sched_runtime;
137 uint64_t sched_deadline;
138 uint64_t sched_period;
139
140 l_uint sched_util_min;
141 l_uint sched_util_max;
142 };
143 /**
144 * `.size` must be checked at runtime as well in the syscall to match the
145 * Linux implementation.
146 *
147 * This `_Static_assert(..)` is a sanity check to ensure that the structure
148 * meets the minimum expected bar.
149 */
150 _Static_assert(sizeof(struct linux_sched_attr) >= LINUX_SCHED_ATTR_SIZE_VER0,
151 "struct linux_sched_attr size");
152
153 static int bsd_sched_policy_to_linux_sched_policy(int);
154
155 static int linux_utimensat_lts_to_ts(struct l_timespec *,
156 struct timespec *);
157 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
158 static int linux_utimensat_lts64_to_ts(struct l_timespec64 *,
159 struct timespec *);
160 #endif
161 static int linux_common_utimensat(struct thread *, int,
162 const char *, struct timespec *, int);
163 static int linux_common_pselect6(struct thread *, l_int,
164 l_fd_set *, l_fd_set *, l_fd_set *,
165 struct timespec *, l_uintptr_t *);
166 static int linux_common_ppoll(struct thread *, struct pollfd *,
167 uint32_t, struct timespec *, l_sigset_t *,
168 l_size_t);
169 static int linux_pollin(struct thread *, struct pollfd *,
170 struct pollfd *, u_int);
171 static int linux_pollout(struct thread *, struct pollfd *,
172 struct pollfd *, u_int);
173
174 int
linux_sysinfo(struct thread * td,struct linux_sysinfo_args * args)175 linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args)
176 {
177 struct l_sysinfo sysinfo;
178 int i, j;
179 struct timespec ts;
180
181 bzero(&sysinfo, sizeof(sysinfo));
182 getnanouptime(&ts);
183 if (ts.tv_nsec != 0)
184 ts.tv_sec++;
185 sysinfo.uptime = ts.tv_sec;
186
187 /* Use the information from the mib to get our load averages */
188 for (i = 0; i < 3; i++)
189 sysinfo.loads[i] = averunnable.ldavg[i] *
190 LINUX_SYSINFO_LOADS_SCALE / averunnable.fscale;
191
192 sysinfo.totalram = physmem * PAGE_SIZE;
193 sysinfo.freeram = (u_long)vm_free_count() * PAGE_SIZE;
194
195 /*
196 * sharedram counts pages allocated to named, swap-backed objects such
197 * as shared memory segments and tmpfs files. There is no cheap way to
198 * compute this, so just leave the field unpopulated. Linux itself only
199 * started setting this field in the 3.x timeframe.
200 */
201 sysinfo.sharedram = 0;
202 sysinfo.bufferram = 0;
203
204 swap_pager_status(&i, &j);
205 sysinfo.totalswap = i * PAGE_SIZE;
206 sysinfo.freeswap = (i - j) * PAGE_SIZE;
207
208 sysinfo.procs = nprocs;
209
210 /*
211 * Platforms supported by the emulation layer do not have a notion of
212 * high memory.
213 */
214 sysinfo.totalhigh = 0;
215 sysinfo.freehigh = 0;
216
217 sysinfo.mem_unit = 1;
218
219 return (copyout(&sysinfo, args->info, sizeof(sysinfo)));
220 }
221
222 #ifdef LINUX_LEGACY_SYSCALLS
223 int
linux_alarm(struct thread * td,struct linux_alarm_args * args)224 linux_alarm(struct thread *td, struct linux_alarm_args *args)
225 {
226 struct itimerval it, old_it;
227 u_int secs;
228 int error __diagused;
229
230 secs = args->secs;
231 /*
232 * Linux alarm() is always successful. Limit secs to INT32_MAX / 2
233 * to match kern_setitimer()'s limit to avoid error from it.
234 *
235 * XXX. Linux limit secs to INT_MAX on 32 and does not limit on 64-bit
236 * platforms.
237 */
238 if (secs > INT32_MAX / 2)
239 secs = INT32_MAX / 2;
240
241 it.it_value.tv_sec = secs;
242 it.it_value.tv_usec = 0;
243 timevalclear(&it.it_interval);
244 error = kern_setitimer(td, ITIMER_REAL, &it, &old_it);
245 KASSERT(error == 0, ("kern_setitimer returns %d", error));
246
247 if ((old_it.it_value.tv_sec == 0 && old_it.it_value.tv_usec > 0) ||
248 old_it.it_value.tv_usec >= 500000)
249 old_it.it_value.tv_sec++;
250 td->td_retval[0] = old_it.it_value.tv_sec;
251 return (0);
252 }
253 #endif
254
255 int
linux_brk(struct thread * td,struct linux_brk_args * args)256 linux_brk(struct thread *td, struct linux_brk_args *args)
257 {
258 struct vmspace *vm = td->td_proc->p_vmspace;
259 uintptr_t new, old;
260
261 old = (uintptr_t)vm->vm_daddr + ctob(vm->vm_dsize);
262 new = (uintptr_t)args->dsend;
263 if ((caddr_t)new > vm->vm_daddr && !kern_break(td, &new))
264 td->td_retval[0] = (register_t)new;
265 else
266 td->td_retval[0] = (register_t)old;
267
268 return (0);
269 }
270
271 #ifdef LINUX_LEGACY_SYSCALLS
272 int
linux_select(struct thread * td,struct linux_select_args * args)273 linux_select(struct thread *td, struct linux_select_args *args)
274 {
275 l_timeval ltv;
276 struct timeval tv0, tv1, utv, *tvp;
277 int error;
278
279 /*
280 * Store current time for computation of the amount of
281 * time left.
282 */
283 if (args->timeout) {
284 if ((error = copyin(args->timeout, <v, sizeof(ltv))))
285 goto select_out;
286 utv.tv_sec = ltv.tv_sec;
287 utv.tv_usec = ltv.tv_usec;
288
289 if (itimerfix(&utv)) {
290 /*
291 * The timeval was invalid. Convert it to something
292 * valid that will act as it does under Linux.
293 */
294 utv.tv_sec += utv.tv_usec / 1000000;
295 utv.tv_usec %= 1000000;
296 if (utv.tv_usec < 0) {
297 utv.tv_sec -= 1;
298 utv.tv_usec += 1000000;
299 }
300 if (utv.tv_sec < 0)
301 timevalclear(&utv);
302 }
303 microtime(&tv0);
304 tvp = &utv;
305 } else
306 tvp = NULL;
307
308 error = kern_select(td, args->nfds, args->readfds, args->writefds,
309 args->exceptfds, tvp, LINUX_NFDBITS);
310 if (error)
311 goto select_out;
312
313 if (args->timeout) {
314 if (td->td_retval[0]) {
315 /*
316 * Compute how much time was left of the timeout,
317 * by subtracting the current time and the time
318 * before we started the call, and subtracting
319 * that result from the user-supplied value.
320 */
321 microtime(&tv1);
322 timevalsub(&tv1, &tv0);
323 timevalsub(&utv, &tv1);
324 if (utv.tv_sec < 0)
325 timevalclear(&utv);
326 } else
327 timevalclear(&utv);
328 ltv.tv_sec = utv.tv_sec;
329 ltv.tv_usec = utv.tv_usec;
330 if ((error = copyout(<v, args->timeout, sizeof(ltv))))
331 goto select_out;
332 }
333
334 select_out:
335 return (error);
336 }
337 #endif
338
339 int
linux_mremap(struct thread * td,struct linux_mremap_args * args)340 linux_mremap(struct thread *td, struct linux_mremap_args *args)
341 {
342 uintptr_t addr;
343 size_t len;
344 int error = 0;
345
346 if (args->flags & ~(LINUX_MREMAP_FIXED | LINUX_MREMAP_MAYMOVE)) {
347 td->td_retval[0] = 0;
348 return (EINVAL);
349 }
350
351 /*
352 * Check for the page alignment.
353 * Linux defines PAGE_MASK to be FreeBSD ~PAGE_MASK.
354 */
355 if (args->addr & PAGE_MASK) {
356 td->td_retval[0] = 0;
357 return (EINVAL);
358 }
359
360 args->new_len = round_page(args->new_len);
361 args->old_len = round_page(args->old_len);
362
363 if (args->new_len > args->old_len) {
364 td->td_retval[0] = 0;
365 return (ENOMEM);
366 }
367
368 if (args->new_len < args->old_len) {
369 addr = args->addr + args->new_len;
370 len = args->old_len - args->new_len;
371 error = kern_munmap(td, addr, len);
372 }
373
374 td->td_retval[0] = error ? 0 : (uintptr_t)args->addr;
375 return (error);
376 }
377
378 #define LINUX_MS_ASYNC 0x0001
379 #define LINUX_MS_INVALIDATE 0x0002
380 #define LINUX_MS_SYNC 0x0004
381
382 int
linux_msync(struct thread * td,struct linux_msync_args * args)383 linux_msync(struct thread *td, struct linux_msync_args *args)
384 {
385
386 return (kern_msync(td, args->addr, args->len,
387 args->fl & ~LINUX_MS_SYNC));
388 }
389
390 int
linux_mprotect(struct thread * td,struct linux_mprotect_args * uap)391 linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
392 {
393
394 return (linux_mprotect_common(td, PTROUT(uap->addr), uap->len,
395 uap->prot));
396 }
397
398 int
linux_pkey_mprotect(struct thread * td,struct linux_pkey_mprotect_args * uap)399 linux_pkey_mprotect(struct thread *td, struct linux_pkey_mprotect_args *uap)
400 {
401
402 return (linux_pkey_mprotect_common(td, uap->start, uap->len,
403 uap->prot, uap->pkey));
404 }
405
406 int
linux_pkey_alloc(struct thread * td,struct linux_pkey_alloc_args * uap)407 linux_pkey_alloc(struct thread *td, struct linux_pkey_alloc_args *uap)
408 {
409
410 return (linux_pkey_alloc_common(td, uap->flags, uap->init_val));
411 }
412
413 int
linux_pkey_free(struct thread * td,struct linux_pkey_free_args * uap)414 linux_pkey_free(struct thread *td, struct linux_pkey_free_args *uap)
415 {
416
417 return (linux_pkey_free_common(td, uap->pkey));
418 }
419
420 int
linux_madvise(struct thread * td,struct linux_madvise_args * uap)421 linux_madvise(struct thread *td, struct linux_madvise_args *uap)
422 {
423
424 return (linux_madvise_common(td, PTROUT(uap->addr), uap->len,
425 uap->behav));
426 }
427
428 int
linux_mmap2(struct thread * td,struct linux_mmap2_args * uap)429 linux_mmap2(struct thread *td, struct linux_mmap2_args *uap)
430 {
431 #if defined(LINUX_ARCHWANT_MMAP2PGOFF)
432 /*
433 * For architectures with sizeof (off_t) < sizeof (loff_t) mmap is
434 * implemented with mmap2 syscall and the offset is represented in
435 * multiples of page size.
436 */
437 return (linux_mmap_common(td, PTROUT(uap->addr), uap->len, uap->prot,
438 uap->flags, uap->fd, (uint64_t)(uint32_t)uap->pgoff * PAGE_SIZE));
439 #else
440 return (linux_mmap_common(td, PTROUT(uap->addr), uap->len, uap->prot,
441 uap->flags, uap->fd, uap->pgoff));
442 #endif
443 }
444
445 #ifdef LINUX_LEGACY_SYSCALLS
446 int
linux_time(struct thread * td,struct linux_time_args * args)447 linux_time(struct thread *td, struct linux_time_args *args)
448 {
449 struct timeval tv;
450 l_time_t tm;
451 int error;
452
453 microtime(&tv);
454 tm = tv.tv_sec;
455 if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm))))
456 return (error);
457 td->td_retval[0] = tm;
458 return (0);
459 }
460 #endif
461
462 struct l_times_argv {
463 l_clock_t tms_utime;
464 l_clock_t tms_stime;
465 l_clock_t tms_cutime;
466 l_clock_t tms_cstime;
467 };
468
469 /*
470 * Glibc versions prior to 2.2.1 always use hard-coded CLK_TCK value.
471 * Since 2.2.1 Glibc uses value exported from kernel via AT_CLKTCK
472 * auxiliary vector entry.
473 */
474 #define CLK_TCK 100
475
476 #define CONVOTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
477 #define CONVNTCK(r) (r.tv_sec * stclohz + r.tv_usec / (1000000 / stclohz))
478
479 #define CONVTCK(r) (linux_kernver(td) >= LINUX_KERNVER(2,4,0) ? \
480 CONVNTCK(r) : CONVOTCK(r))
481
482 int
linux_times(struct thread * td,struct linux_times_args * args)483 linux_times(struct thread *td, struct linux_times_args *args)
484 {
485 struct timeval tv, utime, stime, cutime, cstime;
486 struct l_times_argv tms;
487 struct proc *p;
488 int error;
489
490 if (args->buf != NULL) {
491 p = td->td_proc;
492 PROC_LOCK(p);
493 PROC_STATLOCK(p);
494 calcru(p, &utime, &stime);
495 PROC_STATUNLOCK(p);
496 calccru(p, &cutime, &cstime);
497 PROC_UNLOCK(p);
498
499 tms.tms_utime = CONVTCK(utime);
500 tms.tms_stime = CONVTCK(stime);
501
502 tms.tms_cutime = CONVTCK(cutime);
503 tms.tms_cstime = CONVTCK(cstime);
504
505 if ((error = copyout(&tms, args->buf, sizeof(tms))))
506 return (error);
507 }
508
509 microuptime(&tv);
510 td->td_retval[0] = (int)CONVTCK(tv);
511 return (0);
512 }
513
514 int
linux_newuname(struct thread * td,struct linux_newuname_args * args)515 linux_newuname(struct thread *td, struct linux_newuname_args *args)
516 {
517 struct l_new_utsname utsname;
518 char osname[LINUX_MAX_UTSNAME];
519 char osrelease[LINUX_MAX_UTSNAME];
520 char *p;
521
522 linux_get_osname(td, osname);
523 linux_get_osrelease(td, osrelease);
524
525 bzero(&utsname, sizeof(utsname));
526 strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME);
527 getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME);
528 getcreddomainname(td->td_ucred, utsname.domainname, LINUX_MAX_UTSNAME);
529 strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME);
530 strlcpy(utsname.version, version, LINUX_MAX_UTSNAME);
531 for (p = utsname.version; *p != '\0'; ++p)
532 if (*p == '\n') {
533 *p = '\0';
534 break;
535 }
536 #if defined(__amd64__)
537 /*
538 * On amd64, Linux uname(2) needs to return "x86_64"
539 * for both 64-bit and 32-bit applications. On 32-bit,
540 * the string returned by getauxval(AT_PLATFORM) needs
541 * to remain "i686", though.
542 */
543 #if defined(COMPAT_LINUX32)
544 if (linux32_emulate_i386)
545 strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME);
546 else
547 #endif
548 strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME);
549 #elif defined(__aarch64__)
550 strlcpy(utsname.machine, "aarch64", LINUX_MAX_UTSNAME);
551 #elif defined(__i386__)
552 strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME);
553 #endif
554
555 return (copyout(&utsname, args->buf, sizeof(utsname)));
556 }
557
558 struct l_utimbuf {
559 l_time_t l_actime;
560 l_time_t l_modtime;
561 };
562
563 #ifdef LINUX_LEGACY_SYSCALLS
564 int
linux_utime(struct thread * td,struct linux_utime_args * args)565 linux_utime(struct thread *td, struct linux_utime_args *args)
566 {
567 struct timeval tv[2], *tvp;
568 struct l_utimbuf lut;
569 int error;
570
571 if (args->times) {
572 if ((error = copyin(args->times, &lut, sizeof lut)) != 0)
573 return (error);
574 tv[0].tv_sec = lut.l_actime;
575 tv[0].tv_usec = 0;
576 tv[1].tv_sec = lut.l_modtime;
577 tv[1].tv_usec = 0;
578 tvp = tv;
579 } else
580 tvp = NULL;
581
582 return (kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE,
583 tvp, UIO_SYSSPACE));
584 }
585 #endif
586
587 #ifdef LINUX_LEGACY_SYSCALLS
588 int
linux_utimes(struct thread * td,struct linux_utimes_args * args)589 linux_utimes(struct thread *td, struct linux_utimes_args *args)
590 {
591 l_timeval ltv[2];
592 struct timeval tv[2], *tvp = NULL;
593 int error;
594
595 if (args->tptr != NULL) {
596 if ((error = copyin(args->tptr, ltv, sizeof ltv)) != 0)
597 return (error);
598 tv[0].tv_sec = ltv[0].tv_sec;
599 tv[0].tv_usec = ltv[0].tv_usec;
600 tv[1].tv_sec = ltv[1].tv_sec;
601 tv[1].tv_usec = ltv[1].tv_usec;
602 tvp = tv;
603 }
604
605 return (kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE,
606 tvp, UIO_SYSSPACE));
607 }
608 #endif
609
610 static int
linux_utimensat_lts_to_ts(struct l_timespec * l_times,struct timespec * times)611 linux_utimensat_lts_to_ts(struct l_timespec *l_times, struct timespec *times)
612 {
613
614 if (l_times->tv_nsec != LINUX_UTIME_OMIT &&
615 l_times->tv_nsec != LINUX_UTIME_NOW &&
616 (l_times->tv_nsec < 0 || l_times->tv_nsec > 999999999))
617 return (EINVAL);
618
619 times->tv_sec = l_times->tv_sec;
620 switch (l_times->tv_nsec)
621 {
622 case LINUX_UTIME_OMIT:
623 times->tv_nsec = UTIME_OMIT;
624 break;
625 case LINUX_UTIME_NOW:
626 times->tv_nsec = UTIME_NOW;
627 break;
628 default:
629 times->tv_nsec = l_times->tv_nsec;
630 }
631
632 return (0);
633 }
634
635 static int
linux_common_utimensat(struct thread * td,int ldfd,const char * pathname,struct timespec * timesp,int lflags)636 linux_common_utimensat(struct thread *td, int ldfd, const char *pathname,
637 struct timespec *timesp, int lflags)
638 {
639 int dfd, flags = 0;
640
641 dfd = (ldfd == LINUX_AT_FDCWD) ? AT_FDCWD : ldfd;
642
643 if (lflags & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH))
644 return (EINVAL);
645
646 if (timesp != NULL) {
647 /* This breaks POSIX, but is what the Linux kernel does
648 * _on purpose_ (documented in the man page for utimensat(2)),
649 * so we must follow that behaviour. */
650 if (timesp[0].tv_nsec == UTIME_OMIT &&
651 timesp[1].tv_nsec == UTIME_OMIT)
652 return (0);
653 }
654
655 if (lflags & LINUX_AT_SYMLINK_NOFOLLOW)
656 flags |= AT_SYMLINK_NOFOLLOW;
657 if (lflags & LINUX_AT_EMPTY_PATH)
658 flags |= AT_EMPTY_PATH;
659
660 if (pathname != NULL)
661 return (kern_utimensat(td, dfd, pathname,
662 UIO_USERSPACE, timesp, UIO_SYSSPACE, flags));
663
664 if (lflags != 0)
665 return (EINVAL);
666
667 return (kern_futimens(td, dfd, timesp, UIO_SYSSPACE));
668 }
669
670 int
linux_utimensat(struct thread * td,struct linux_utimensat_args * args)671 linux_utimensat(struct thread *td, struct linux_utimensat_args *args)
672 {
673 struct l_timespec l_times[2];
674 struct timespec times[2], *timesp;
675 int error;
676
677 if (args->times != NULL) {
678 error = copyin(args->times, l_times, sizeof(l_times));
679 if (error != 0)
680 return (error);
681
682 error = linux_utimensat_lts_to_ts(&l_times[0], ×[0]);
683 if (error != 0)
684 return (error);
685 error = linux_utimensat_lts_to_ts(&l_times[1], ×[1]);
686 if (error != 0)
687 return (error);
688 timesp = times;
689 } else
690 timesp = NULL;
691
692 return (linux_common_utimensat(td, args->dfd, args->pathname,
693 timesp, args->flags));
694 }
695
696 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
697 static int
linux_utimensat_lts64_to_ts(struct l_timespec64 * l_times,struct timespec * times)698 linux_utimensat_lts64_to_ts(struct l_timespec64 *l_times, struct timespec *times)
699 {
700
701 /* Zero out the padding in compat mode. */
702 l_times->tv_nsec &= 0xFFFFFFFFUL;
703
704 if (l_times->tv_nsec != LINUX_UTIME_OMIT &&
705 l_times->tv_nsec != LINUX_UTIME_NOW &&
706 (l_times->tv_nsec < 0 || l_times->tv_nsec > 999999999))
707 return (EINVAL);
708
709 times->tv_sec = l_times->tv_sec;
710 switch (l_times->tv_nsec)
711 {
712 case LINUX_UTIME_OMIT:
713 times->tv_nsec = UTIME_OMIT;
714 break;
715 case LINUX_UTIME_NOW:
716 times->tv_nsec = UTIME_NOW;
717 break;
718 default:
719 times->tv_nsec = l_times->tv_nsec;
720 }
721
722 return (0);
723 }
724
725 int
linux_utimensat_time64(struct thread * td,struct linux_utimensat_time64_args * args)726 linux_utimensat_time64(struct thread *td, struct linux_utimensat_time64_args *args)
727 {
728 struct l_timespec64 l_times[2];
729 struct timespec times[2], *timesp;
730 int error;
731
732 if (args->times64 != NULL) {
733 error = copyin(args->times64, l_times, sizeof(l_times));
734 if (error != 0)
735 return (error);
736
737 error = linux_utimensat_lts64_to_ts(&l_times[0], ×[0]);
738 if (error != 0)
739 return (error);
740 error = linux_utimensat_lts64_to_ts(&l_times[1], ×[1]);
741 if (error != 0)
742 return (error);
743 timesp = times;
744 } else
745 timesp = NULL;
746
747 return (linux_common_utimensat(td, args->dfd, args->pathname,
748 timesp, args->flags));
749 }
750 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
751
752 #ifdef LINUX_LEGACY_SYSCALLS
753 int
linux_futimesat(struct thread * td,struct linux_futimesat_args * args)754 linux_futimesat(struct thread *td, struct linux_futimesat_args *args)
755 {
756 l_timeval ltv[2];
757 struct timeval tv[2], *tvp = NULL;
758 int error, dfd;
759
760 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
761
762 if (args->utimes != NULL) {
763 if ((error = copyin(args->utimes, ltv, sizeof ltv)) != 0)
764 return (error);
765 tv[0].tv_sec = ltv[0].tv_sec;
766 tv[0].tv_usec = ltv[0].tv_usec;
767 tv[1].tv_sec = ltv[1].tv_sec;
768 tv[1].tv_usec = ltv[1].tv_usec;
769 tvp = tv;
770 }
771
772 return (kern_utimesat(td, dfd, args->filename, UIO_USERSPACE,
773 tvp, UIO_SYSSPACE));
774 }
775 #endif
776
777 static int
linux_common_wait(struct thread * td,idtype_t idtype,int id,int * statusp,int options,void * rup,l_siginfo_t * infop)778 linux_common_wait(struct thread *td, idtype_t idtype, int id, int *statusp,
779 int options, void *rup, l_siginfo_t *infop)
780 {
781 l_siginfo_t lsi;
782 siginfo_t siginfo;
783 struct __wrusage wru;
784 int error, status, tmpstat, sig;
785
786 error = kern_wait6(td, idtype, id, &status, options,
787 rup != NULL ? &wru : NULL, &siginfo);
788
789 if (error == 0 && statusp) {
790 tmpstat = status & 0xffff;
791 if (WIFSIGNALED(tmpstat)) {
792 tmpstat = (tmpstat & 0xffffff80) |
793 bsd_to_linux_signal(WTERMSIG(tmpstat));
794 } else if (WIFSTOPPED(tmpstat)) {
795 tmpstat = (tmpstat & 0xffff00ff) |
796 (bsd_to_linux_signal(WSTOPSIG(tmpstat)) << 8);
797 #if defined(__aarch64__) || (defined(__amd64__) && !defined(COMPAT_LINUX32))
798 if (WSTOPSIG(status) == SIGTRAP) {
799 tmpstat = linux_ptrace_status(td,
800 siginfo.si_pid, tmpstat);
801 }
802 #endif
803 } else if (WIFCONTINUED(tmpstat)) {
804 tmpstat = 0xffff;
805 }
806 error = copyout(&tmpstat, statusp, sizeof(int));
807 }
808 if (error == 0 && rup != NULL)
809 error = linux_copyout_rusage(&wru.wru_self, rup);
810 if (error == 0 && infop != NULL && td->td_retval[0] != 0) {
811 sig = bsd_to_linux_signal(siginfo.si_signo);
812 memset(&lsi, 0, sizeof(lsi));
813 siginfo_to_lsiginfo(&siginfo, &lsi, sig);
814 error = copyout(&lsi, infop, sizeof(lsi));
815 }
816
817 return (error);
818 }
819
820 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
821 int
linux_waitpid(struct thread * td,struct linux_waitpid_args * args)822 linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
823 {
824 struct linux_wait4_args wait4_args = {
825 .pid = args->pid,
826 .status = args->status,
827 .options = args->options,
828 .rusage = NULL,
829 };
830
831 return (linux_wait4(td, &wait4_args));
832 }
833 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
834
835 int
linux_wait4(struct thread * td,struct linux_wait4_args * args)836 linux_wait4(struct thread *td, struct linux_wait4_args *args)
837 {
838 struct proc *p;
839 int options, id, idtype;
840
841 if (args->options & ~(LINUX_WUNTRACED | LINUX_WNOHANG |
842 LINUX_WCONTINUED | __WCLONE | __WNOTHREAD | __WALL))
843 return (EINVAL);
844
845 /* -INT_MIN is not defined. */
846 if (args->pid == INT_MIN)
847 return (ESRCH);
848
849 options = 0;
850 linux_to_bsd_waitopts(args->options, &options);
851
852 /*
853 * For backward compatibility we implicitly add flags WEXITED
854 * and WTRAPPED here.
855 */
856 options |= WEXITED | WTRAPPED;
857
858 if (args->pid == WAIT_ANY) {
859 idtype = P_ALL;
860 id = 0;
861 } else if (args->pid < 0) {
862 idtype = P_PGID;
863 id = (id_t)-args->pid;
864 } else if (args->pid == 0) {
865 idtype = P_PGID;
866 p = td->td_proc;
867 PROC_LOCK(p);
868 id = p->p_pgid;
869 PROC_UNLOCK(p);
870 } else {
871 idtype = P_PID;
872 id = (id_t)args->pid;
873 }
874
875 return (linux_common_wait(td, idtype, id, args->status, options,
876 args->rusage, NULL));
877 }
878
879 int
linux_waitid(struct thread * td,struct linux_waitid_args * args)880 linux_waitid(struct thread *td, struct linux_waitid_args *args)
881 {
882 idtype_t idtype;
883 int error, options;
884 struct proc *p;
885 pid_t id;
886
887 if (args->options & ~(LINUX_WNOHANG | LINUX_WNOWAIT | LINUX_WEXITED |
888 LINUX_WSTOPPED | LINUX_WCONTINUED | __WCLONE | __WNOTHREAD | __WALL))
889 return (EINVAL);
890
891 options = 0;
892 linux_to_bsd_waitopts(args->options, &options);
893
894 id = args->id;
895 switch (args->idtype) {
896 case LINUX_P_ALL:
897 idtype = P_ALL;
898 break;
899 case LINUX_P_PID:
900 if (args->id <= 0)
901 return (EINVAL);
902 idtype = P_PID;
903 break;
904 case LINUX_P_PGID:
905 if (linux_kernver(td) >= LINUX_KERNVER(5,4,0) && args->id == 0) {
906 p = td->td_proc;
907 PROC_LOCK(p);
908 id = p->p_pgid;
909 PROC_UNLOCK(p);
910 } else if (args->id <= 0)
911 return (EINVAL);
912 idtype = P_PGID;
913 break;
914 case LINUX_P_PIDFD:
915 LINUX_RATELIMIT_MSG("unsupported waitid P_PIDFD idtype");
916 return (ENOSYS);
917 default:
918 return (EINVAL);
919 }
920
921 error = linux_common_wait(td, idtype, id, NULL, options,
922 args->rusage, args->info);
923 td->td_retval[0] = 0;
924
925 return (error);
926 }
927
928 #ifdef LINUX_LEGACY_SYSCALLS
929 int
linux_mknod(struct thread * td,struct linux_mknod_args * args)930 linux_mknod(struct thread *td, struct linux_mknod_args *args)
931 {
932 int error;
933
934 switch (args->mode & S_IFMT) {
935 case S_IFIFO:
936 case S_IFSOCK:
937 error = kern_mkfifoat(td, AT_FDCWD, args->path, UIO_USERSPACE,
938 args->mode);
939 break;
940
941 case S_IFCHR:
942 case S_IFBLK:
943 error = kern_mknodat(td, AT_FDCWD, args->path, UIO_USERSPACE,
944 args->mode, linux_decode_dev(args->dev));
945 break;
946
947 case S_IFDIR:
948 error = EPERM;
949 break;
950
951 case 0:
952 args->mode |= S_IFREG;
953 /* FALLTHROUGH */
954 case S_IFREG:
955 error = kern_openat(td, AT_FDCWD, args->path, UIO_USERSPACE,
956 O_WRONLY | O_CREAT | O_TRUNC, args->mode);
957 if (error == 0)
958 kern_close(td, td->td_retval[0]);
959 break;
960
961 default:
962 error = EINVAL;
963 break;
964 }
965 return (error);
966 }
967 #endif
968
969 int
linux_mknodat(struct thread * td,struct linux_mknodat_args * args)970 linux_mknodat(struct thread *td, struct linux_mknodat_args *args)
971 {
972 int error, dfd;
973
974 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
975
976 switch (args->mode & S_IFMT) {
977 case S_IFIFO:
978 case S_IFSOCK:
979 error = kern_mkfifoat(td, dfd, args->filename, UIO_USERSPACE,
980 args->mode);
981 break;
982
983 case S_IFCHR:
984 case S_IFBLK:
985 error = kern_mknodat(td, dfd, args->filename, UIO_USERSPACE,
986 args->mode, linux_decode_dev(args->dev));
987 break;
988
989 case S_IFDIR:
990 error = EPERM;
991 break;
992
993 case 0:
994 args->mode |= S_IFREG;
995 /* FALLTHROUGH */
996 case S_IFREG:
997 error = kern_openat(td, dfd, args->filename, UIO_USERSPACE,
998 O_WRONLY | O_CREAT | O_TRUNC, args->mode);
999 if (error == 0)
1000 kern_close(td, td->td_retval[0]);
1001 break;
1002
1003 default:
1004 error = EINVAL;
1005 break;
1006 }
1007 return (error);
1008 }
1009
1010 /*
1011 * UGH! This is just about the dumbest idea I've ever heard!!
1012 */
1013 int
linux_personality(struct thread * td,struct linux_personality_args * args)1014 linux_personality(struct thread *td, struct linux_personality_args *args)
1015 {
1016 struct linux_pemuldata *pem;
1017 struct proc *p = td->td_proc;
1018 uint32_t old;
1019
1020 PROC_LOCK(p);
1021 pem = pem_find(p);
1022 old = pem->persona;
1023 if (args->per != 0xffffffff)
1024 pem->persona = args->per;
1025 PROC_UNLOCK(p);
1026
1027 td->td_retval[0] = old;
1028 return (0);
1029 }
1030
1031 struct l_itimerval {
1032 l_timeval it_interval;
1033 l_timeval it_value;
1034 };
1035
1036 #define B2L_ITIMERVAL(bip, lip) \
1037 (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \
1038 (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \
1039 (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \
1040 (bip)->it_value.tv_usec = (lip)->it_value.tv_usec;
1041
1042 int
linux_setitimer(struct thread * td,struct linux_setitimer_args * uap)1043 linux_setitimer(struct thread *td, struct linux_setitimer_args *uap)
1044 {
1045 int error;
1046 struct l_itimerval ls;
1047 struct itimerval aitv, oitv;
1048
1049 if (uap->itv == NULL) {
1050 uap->itv = uap->oitv;
1051 return (linux_getitimer(td, (struct linux_getitimer_args *)uap));
1052 }
1053
1054 error = copyin(uap->itv, &ls, sizeof(ls));
1055 if (error != 0)
1056 return (error);
1057 B2L_ITIMERVAL(&aitv, &ls);
1058 error = kern_setitimer(td, uap->which, &aitv, &oitv);
1059 if (error != 0 || uap->oitv == NULL)
1060 return (error);
1061 B2L_ITIMERVAL(&ls, &oitv);
1062
1063 return (copyout(&ls, uap->oitv, sizeof(ls)));
1064 }
1065
1066 int
linux_getitimer(struct thread * td,struct linux_getitimer_args * uap)1067 linux_getitimer(struct thread *td, struct linux_getitimer_args *uap)
1068 {
1069 int error;
1070 struct l_itimerval ls;
1071 struct itimerval aitv;
1072
1073 error = kern_getitimer(td, uap->which, &aitv);
1074 if (error != 0)
1075 return (error);
1076 B2L_ITIMERVAL(&ls, &aitv);
1077 return (copyout(&ls, uap->itv, sizeof(ls)));
1078 }
1079
1080 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1081 int
linux_nice(struct thread * td,struct linux_nice_args * args)1082 linux_nice(struct thread *td, struct linux_nice_args *args)
1083 {
1084
1085 return (kern_setpriority(td, PRIO_PROCESS, 0, args->inc));
1086 }
1087 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1088
1089 int
linux_setgroups(struct thread * td,struct linux_setgroups_args * args)1090 linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
1091 {
1092 const int ngrp = args->gidsetsize;
1093 struct ucred *newcred, *oldcred;
1094 l_gid_t *linux_gidset;
1095 int error;
1096 struct proc *p;
1097
1098 if (ngrp < 0 || ngrp > ngroups_max)
1099 return (EINVAL);
1100 linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
1101 error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t));
1102 if (error)
1103 goto out;
1104
1105 newcred = crget();
1106 crextend(newcred, ngrp);
1107 p = td->td_proc;
1108 PROC_LOCK(p);
1109 oldcred = crcopysafe(p, newcred);
1110
1111 if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS)) != 0) {
1112 PROC_UNLOCK(p);
1113 crfree(newcred);
1114 goto out;
1115 }
1116
1117 newcred->cr_ngroups = ngrp;
1118 for (int i = 0; i < ngrp; i++)
1119 newcred->cr_groups[i] = linux_gidset[i];
1120 newcred->cr_flags |= CRED_FLAG_GROUPSET;
1121
1122 setsugid(p);
1123 proc_set_cred(p, newcred);
1124 PROC_UNLOCK(p);
1125 crfree(oldcred);
1126 error = 0;
1127 out:
1128 free(linux_gidset, M_LINUX);
1129 return (error);
1130 }
1131
1132 int
linux_getgroups(struct thread * td,struct linux_getgroups_args * args)1133 linux_getgroups(struct thread *td, struct linux_getgroups_args *args)
1134 {
1135 const struct ucred *const cred = td->td_ucred;
1136 l_gid_t *linux_gidset;
1137 int ngrp, error;
1138
1139 ngrp = args->gidsetsize;
1140
1141 if (ngrp == 0) {
1142 td->td_retval[0] = cred->cr_ngroups;
1143 return (0);
1144 }
1145 if (ngrp < cred->cr_ngroups)
1146 return (EINVAL);
1147
1148 ngrp = cred->cr_ngroups;
1149
1150 linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
1151 for (int i = 0; i < ngrp; ++i)
1152 linux_gidset[i] = cred->cr_groups[i];
1153
1154 error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t));
1155 free(linux_gidset, M_LINUX);
1156
1157 if (error != 0)
1158 return (error);
1159
1160 td->td_retval[0] = ngrp;
1161 return (0);
1162 }
1163
1164 static bool
linux_get_dummy_limit(struct thread * td,l_uint resource,struct rlimit * rlim)1165 linux_get_dummy_limit(struct thread *td, l_uint resource, struct rlimit *rlim)
1166 {
1167 ssize_t size;
1168 int res, error;
1169
1170 if (linux_dummy_rlimits == 0)
1171 return (false);
1172
1173 switch (resource) {
1174 case LINUX_RLIMIT_LOCKS:
1175 case LINUX_RLIMIT_RTTIME:
1176 rlim->rlim_cur = LINUX_RLIM_INFINITY;
1177 rlim->rlim_max = LINUX_RLIM_INFINITY;
1178 return (true);
1179 case LINUX_RLIMIT_NICE:
1180 case LINUX_RLIMIT_RTPRIO:
1181 rlim->rlim_cur = 0;
1182 rlim->rlim_max = 0;
1183 return (true);
1184 case LINUX_RLIMIT_SIGPENDING:
1185 error = kernel_sysctlbyname(td,
1186 "kern.sigqueue.max_pending_per_proc",
1187 &res, &size, 0, 0, 0, 0);
1188 if (error != 0)
1189 return (false);
1190 rlim->rlim_cur = res;
1191 rlim->rlim_max = res;
1192 return (true);
1193 case LINUX_RLIMIT_MSGQUEUE:
1194 error = kernel_sysctlbyname(td,
1195 "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0);
1196 if (error != 0)
1197 return (false);
1198 rlim->rlim_cur = res;
1199 rlim->rlim_max = res;
1200 return (true);
1201 default:
1202 return (false);
1203 }
1204 }
1205
1206 int
linux_setrlimit(struct thread * td,struct linux_setrlimit_args * args)1207 linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args)
1208 {
1209 struct rlimit bsd_rlim;
1210 struct l_rlimit rlim;
1211 u_int which;
1212 int error;
1213
1214 if (args->resource >= LINUX_RLIM_NLIMITS)
1215 return (EINVAL);
1216
1217 which = linux_to_bsd_resource[args->resource];
1218 if (which == -1)
1219 return (EINVAL);
1220
1221 error = copyin(args->rlim, &rlim, sizeof(rlim));
1222 if (error)
1223 return (error);
1224
1225 bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur;
1226 bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max;
1227 return (kern_setrlimit(td, which, &bsd_rlim));
1228 }
1229
1230 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1231 int
linux_old_getrlimit(struct thread * td,struct linux_old_getrlimit_args * args)1232 linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args)
1233 {
1234 struct l_rlimit rlim;
1235 struct rlimit bsd_rlim;
1236 u_int which;
1237
1238 if (linux_get_dummy_limit(td, args->resource, &bsd_rlim)) {
1239 rlim.rlim_cur = bsd_rlim.rlim_cur;
1240 rlim.rlim_max = bsd_rlim.rlim_max;
1241 return (copyout(&rlim, args->rlim, sizeof(rlim)));
1242 }
1243
1244 if (args->resource >= LINUX_RLIM_NLIMITS)
1245 return (EINVAL);
1246
1247 which = linux_to_bsd_resource[args->resource];
1248 if (which == -1)
1249 return (EINVAL);
1250
1251 lim_rlimit(td, which, &bsd_rlim);
1252
1253 #ifdef COMPAT_LINUX32
1254 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur;
1255 if (rlim.rlim_cur == UINT_MAX)
1256 rlim.rlim_cur = INT_MAX;
1257 rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max;
1258 if (rlim.rlim_max == UINT_MAX)
1259 rlim.rlim_max = INT_MAX;
1260 #else
1261 rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur;
1262 if (rlim.rlim_cur == ULONG_MAX)
1263 rlim.rlim_cur = LONG_MAX;
1264 rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max;
1265 if (rlim.rlim_max == ULONG_MAX)
1266 rlim.rlim_max = LONG_MAX;
1267 #endif
1268 return (copyout(&rlim, args->rlim, sizeof(rlim)));
1269 }
1270 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1271
1272 int
linux_getrlimit(struct thread * td,struct linux_getrlimit_args * args)1273 linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args)
1274 {
1275 struct l_rlimit rlim;
1276 struct rlimit bsd_rlim;
1277 u_int which;
1278
1279 if (linux_get_dummy_limit(td, args->resource, &bsd_rlim)) {
1280 rlim.rlim_cur = bsd_rlim.rlim_cur;
1281 rlim.rlim_max = bsd_rlim.rlim_max;
1282 return (copyout(&rlim, args->rlim, sizeof(rlim)));
1283 }
1284
1285 if (args->resource >= LINUX_RLIM_NLIMITS)
1286 return (EINVAL);
1287
1288 which = linux_to_bsd_resource[args->resource];
1289 if (which == -1)
1290 return (EINVAL);
1291
1292 lim_rlimit(td, which, &bsd_rlim);
1293
1294 rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur;
1295 rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max;
1296 return (copyout(&rlim, args->rlim, sizeof(rlim)));
1297 }
1298
1299 int
linux_sched_setscheduler(struct thread * td,struct linux_sched_setscheduler_args * args)1300 linux_sched_setscheduler(struct thread *td,
1301 struct linux_sched_setscheduler_args *args)
1302 {
1303 struct sched_param sched_param;
1304 struct thread *tdt;
1305 int error, policy;
1306
1307 switch (args->policy) {
1308 case LINUX_SCHED_OTHER:
1309 policy = SCHED_OTHER;
1310 break;
1311 case LINUX_SCHED_FIFO:
1312 policy = SCHED_FIFO;
1313 break;
1314 case LINUX_SCHED_RR:
1315 policy = SCHED_RR;
1316 break;
1317 default:
1318 return (EINVAL);
1319 }
1320
1321 error = copyin(args->param, &sched_param, sizeof(sched_param));
1322 if (error)
1323 return (error);
1324
1325 if (linux_map_sched_prio) {
1326 switch (policy) {
1327 case SCHED_OTHER:
1328 if (sched_param.sched_priority != 0)
1329 return (EINVAL);
1330
1331 sched_param.sched_priority =
1332 PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE;
1333 break;
1334 case SCHED_FIFO:
1335 case SCHED_RR:
1336 if (sched_param.sched_priority < 1 ||
1337 sched_param.sched_priority >= LINUX_MAX_RT_PRIO)
1338 return (EINVAL);
1339
1340 /*
1341 * Map [1, LINUX_MAX_RT_PRIO - 1] to
1342 * [0, RTP_PRIO_MAX - RTP_PRIO_MIN] (rounding down).
1343 */
1344 sched_param.sched_priority =
1345 (sched_param.sched_priority - 1) *
1346 (RTP_PRIO_MAX - RTP_PRIO_MIN + 1) /
1347 (LINUX_MAX_RT_PRIO - 1);
1348 break;
1349 }
1350 }
1351
1352 tdt = linux_tdfind(td, args->pid, -1);
1353 if (tdt == NULL)
1354 return (ESRCH);
1355
1356 error = kern_sched_setscheduler(td, tdt, policy, &sched_param);
1357 PROC_UNLOCK(tdt->td_proc);
1358 return (error);
1359 }
1360
1361 int
linux_sched_getscheduler(struct thread * td,struct linux_sched_getscheduler_args * args)1362 linux_sched_getscheduler(struct thread *td,
1363 struct linux_sched_getscheduler_args *args)
1364 {
1365 struct thread *tdt;
1366 int error, policy;
1367
1368 tdt = linux_tdfind(td, args->pid, -1);
1369 if (tdt == NULL)
1370 return (ESRCH);
1371
1372 error = kern_sched_getscheduler(td, tdt, &policy);
1373 PROC_UNLOCK(tdt->td_proc);
1374
1375 switch (policy) {
1376 case SCHED_OTHER:
1377 td->td_retval[0] = LINUX_SCHED_OTHER;
1378 break;
1379 case SCHED_FIFO:
1380 td->td_retval[0] = LINUX_SCHED_FIFO;
1381 break;
1382 case SCHED_RR:
1383 td->td_retval[0] = LINUX_SCHED_RR;
1384 break;
1385 }
1386 return (error);
1387 }
1388
1389 static int
bsd_sched_policy_to_linux_sched_policy(int bsd_policy)1390 bsd_sched_policy_to_linux_sched_policy(int bsd_policy)
1391 {
1392
1393 switch (bsd_policy) {
1394 case SCHED_FIFO:
1395 return (LINUX_SCHED_FIFO);
1396 case SCHED_RR:
1397 return (LINUX_SCHED_RR);
1398 case SCHED_OTHER:
1399 /* FALLTHROUGH */
1400 default:
1401 return (LINUX_SCHED_OTHER);
1402 }
1403 }
1404
1405 int
linux_sched_getattr(struct thread * td,struct linux_sched_getattr_args * args)1406 linux_sched_getattr(struct thread *td, struct linux_sched_getattr_args *args)
1407 {
1408 struct linux_sched_attr lattr;
1409 struct sched_param bsd;
1410 struct thread *tdt;
1411 int error, policy;
1412
1413 if (args->attr == NULL || args->pid < 0 || args->flags != 0 ||
1414 args->size < LINUX_SCHED_ATTR_SIZE_VER0 || args->size > PAGE_SIZE)
1415 return (EINVAL);
1416
1417 tdt = linux_tdfind(td, args->pid, -1);
1418 if (tdt == NULL)
1419 return (ESRCH);
1420
1421 error = kern_sched_getscheduler(td, tdt, &policy);
1422 if (error != 0) {
1423 PROC_UNLOCK(tdt->td_proc);
1424 return (error);
1425 }
1426
1427 error = kern_sched_getparam(td, tdt, &bsd);
1428 PROC_UNLOCK(tdt->td_proc);
1429 if (error != 0)
1430 return (error);
1431
1432 memset(&lattr, 0, sizeof(lattr));
1433 lattr.size = MIN(args->size, sizeof(lattr));
1434 lattr.sched_policy = bsd_sched_policy_to_linux_sched_policy(policy);
1435 /*
1436 * TODO(PR#299617,ngie): fill in `.sched_nice` with policies like
1437 * `LINUX_SCHED_NORMAL`, etc.
1438 */
1439
1440 if (linux_map_sched_prio) {
1441 switch (lattr.sched_policy) {
1442 case LINUX_SCHED_OTHER:
1443 lattr.sched_priority = 0;
1444 break;
1445 case LINUX_SCHED_FIFO:
1446 case LINUX_SCHED_RR:
1447 /**
1448 * Map [0, RTP_PRIO_MAX - RTP_PRIO_MIN] to
1449 * [1, LINUX_MAX_RT_PRIO - 1] (rounding up).
1450 */
1451 lattr.sched_priority =
1452 (bsd.sched_priority *
1453 (LINUX_MAX_RT_PRIO - 1) +
1454 (RTP_PRIO_MAX - RTP_PRIO_MIN - 1)) /
1455 (RTP_PRIO_MAX - RTP_PRIO_MIN) + 1;
1456 break;
1457 }
1458 } else {
1459 lattr.sched_priority = bsd.sched_priority;
1460 }
1461
1462 return (copyout(&lattr, args->attr, lattr.size));
1463 }
1464
1465 int
linux_sched_get_priority_max(struct thread * td,struct linux_sched_get_priority_max_args * args)1466 linux_sched_get_priority_max(struct thread *td,
1467 struct linux_sched_get_priority_max_args *args)
1468 {
1469 struct sched_get_priority_max_args bsd;
1470
1471 if (linux_map_sched_prio) {
1472 switch (args->policy) {
1473 case LINUX_SCHED_OTHER:
1474 td->td_retval[0] = 0;
1475 return (0);
1476 case LINUX_SCHED_FIFO:
1477 case LINUX_SCHED_RR:
1478 td->td_retval[0] = LINUX_MAX_RT_PRIO - 1;
1479 return (0);
1480 default:
1481 return (EINVAL);
1482 }
1483 }
1484
1485 switch (args->policy) {
1486 case LINUX_SCHED_OTHER:
1487 bsd.policy = SCHED_OTHER;
1488 break;
1489 case LINUX_SCHED_FIFO:
1490 bsd.policy = SCHED_FIFO;
1491 break;
1492 case LINUX_SCHED_RR:
1493 bsd.policy = SCHED_RR;
1494 break;
1495 default:
1496 return (EINVAL);
1497 }
1498 return (sys_sched_get_priority_max(td, &bsd));
1499 }
1500
1501 int
linux_sched_get_priority_min(struct thread * td,struct linux_sched_get_priority_min_args * args)1502 linux_sched_get_priority_min(struct thread *td,
1503 struct linux_sched_get_priority_min_args *args)
1504 {
1505 struct sched_get_priority_min_args bsd;
1506
1507 if (linux_map_sched_prio) {
1508 switch (args->policy) {
1509 case LINUX_SCHED_OTHER:
1510 td->td_retval[0] = 0;
1511 return (0);
1512 case LINUX_SCHED_FIFO:
1513 case LINUX_SCHED_RR:
1514 td->td_retval[0] = 1;
1515 return (0);
1516 default:
1517 return (EINVAL);
1518 }
1519 }
1520
1521 switch (args->policy) {
1522 case LINUX_SCHED_OTHER:
1523 bsd.policy = SCHED_OTHER;
1524 break;
1525 case LINUX_SCHED_FIFO:
1526 bsd.policy = SCHED_FIFO;
1527 break;
1528 case LINUX_SCHED_RR:
1529 bsd.policy = SCHED_RR;
1530 break;
1531 default:
1532 return (EINVAL);
1533 }
1534 return (sys_sched_get_priority_min(td, &bsd));
1535 }
1536
1537 #define REBOOT_CAD_ON 0x89abcdef
1538 #define REBOOT_CAD_OFF 0
1539 #define REBOOT_HALT 0xcdef0123
1540 #define REBOOT_RESTART 0x01234567
1541 #define REBOOT_RESTART2 0xA1B2C3D4
1542 #define REBOOT_POWEROFF 0x4321FEDC
1543 #define REBOOT_MAGIC1 0xfee1dead
1544 #define REBOOT_MAGIC2 0x28121969
1545 #define REBOOT_MAGIC2A 0x05121996
1546 #define REBOOT_MAGIC2B 0x16041998
1547
1548 int
linux_reboot(struct thread * td,struct linux_reboot_args * args)1549 linux_reboot(struct thread *td, struct linux_reboot_args *args)
1550 {
1551 struct reboot_args bsd_args;
1552
1553 if (args->magic1 != REBOOT_MAGIC1)
1554 return (EINVAL);
1555
1556 switch (args->magic2) {
1557 case REBOOT_MAGIC2:
1558 case REBOOT_MAGIC2A:
1559 case REBOOT_MAGIC2B:
1560 break;
1561 default:
1562 return (EINVAL);
1563 }
1564
1565 switch (args->cmd) {
1566 case REBOOT_CAD_ON:
1567 case REBOOT_CAD_OFF:
1568 return (priv_check(td, PRIV_REBOOT));
1569 case REBOOT_HALT:
1570 bsd_args.opt = RB_HALT;
1571 break;
1572 case REBOOT_RESTART:
1573 case REBOOT_RESTART2:
1574 bsd_args.opt = 0;
1575 break;
1576 case REBOOT_POWEROFF:
1577 bsd_args.opt = RB_POWEROFF;
1578 break;
1579 default:
1580 return (EINVAL);
1581 }
1582 return (sys_reboot(td, &bsd_args));
1583 }
1584
1585 int
linux_getpid(struct thread * td,struct linux_getpid_args * args)1586 linux_getpid(struct thread *td, struct linux_getpid_args *args)
1587 {
1588
1589 td->td_retval[0] = td->td_proc->p_pid;
1590
1591 return (0);
1592 }
1593
1594 int
linux_gettid(struct thread * td,struct linux_gettid_args * args)1595 linux_gettid(struct thread *td, struct linux_gettid_args *args)
1596 {
1597 struct linux_emuldata *em;
1598
1599 em = em_find(td);
1600 KASSERT(em != NULL, ("gettid: emuldata not found.\n"));
1601
1602 td->td_retval[0] = em->em_tid;
1603
1604 return (0);
1605 }
1606
1607 int
linux_getppid(struct thread * td,struct linux_getppid_args * args)1608 linux_getppid(struct thread *td, struct linux_getppid_args *args)
1609 {
1610
1611 td->td_retval[0] = kern_getppid(td);
1612 return (0);
1613 }
1614
1615 int
linux_getgid(struct thread * td,struct linux_getgid_args * args)1616 linux_getgid(struct thread *td, struct linux_getgid_args *args)
1617 {
1618
1619 td->td_retval[0] = td->td_ucred->cr_rgid;
1620 return (0);
1621 }
1622
1623 int
linux_getuid(struct thread * td,struct linux_getuid_args * args)1624 linux_getuid(struct thread *td, struct linux_getuid_args *args)
1625 {
1626
1627 td->td_retval[0] = td->td_ucred->cr_ruid;
1628 return (0);
1629 }
1630
1631 int
linux_getsid(struct thread * td,struct linux_getsid_args * args)1632 linux_getsid(struct thread *td, struct linux_getsid_args *args)
1633 {
1634
1635 return (kern_getsid(td, args->pid));
1636 }
1637
1638 int
linux_getpriority(struct thread * td,struct linux_getpriority_args * args)1639 linux_getpriority(struct thread *td, struct linux_getpriority_args *args)
1640 {
1641 int error;
1642
1643 error = kern_getpriority(td, args->which, args->who);
1644 td->td_retval[0] = 20 - td->td_retval[0];
1645 return (error);
1646 }
1647
1648 int
linux_sethostname(struct thread * td,struct linux_sethostname_args * args)1649 linux_sethostname(struct thread *td, struct linux_sethostname_args *args)
1650 {
1651 int name[2];
1652
1653 name[0] = CTL_KERN;
1654 name[1] = KERN_HOSTNAME;
1655 return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname,
1656 args->len, 0, 0));
1657 }
1658
1659 int
linux_setdomainname(struct thread * td,struct linux_setdomainname_args * args)1660 linux_setdomainname(struct thread *td, struct linux_setdomainname_args *args)
1661 {
1662 int name[2];
1663
1664 name[0] = CTL_KERN;
1665 name[1] = KERN_NISDOMAINNAME;
1666 return (userland_sysctl(td, name, 2, 0, 0, 0, args->name,
1667 args->len, 0, 0));
1668 }
1669
1670 int
linux_exit_group(struct thread * td,struct linux_exit_group_args * args)1671 linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
1672 {
1673
1674 LINUX_CTR2(exit_group, "thread(%d) (%d)", td->td_tid,
1675 args->error_code);
1676
1677 /*
1678 * XXX: we should send a signal to the parent if
1679 * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?)
1680 * as it doesnt occur often.
1681 */
1682 kern_exit(td, args->error_code, 0);
1683 return (0);
1684 }
1685
1686 #define _LINUX_CAPABILITY_VERSION_1 0x19980330
1687 #define _LINUX_CAPABILITY_VERSION_2 0x20071026
1688 #define _LINUX_CAPABILITY_VERSION_3 0x20080522
1689
1690 struct l_user_cap_header {
1691 l_int version;
1692 l_int pid;
1693 };
1694
1695 struct l_user_cap_data {
1696 l_int effective;
1697 l_int permitted;
1698 l_int inheritable;
1699 };
1700
1701 int
linux_capget(struct thread * td,struct linux_capget_args * uap)1702 linux_capget(struct thread *td, struct linux_capget_args *uap)
1703 {
1704 struct l_user_cap_header luch;
1705 struct l_user_cap_data lucd[2];
1706 int error, u32s;
1707
1708 if (uap->hdrp == NULL)
1709 return (EFAULT);
1710
1711 error = copyin(uap->hdrp, &luch, sizeof(luch));
1712 if (error != 0)
1713 return (error);
1714
1715 switch (luch.version) {
1716 case _LINUX_CAPABILITY_VERSION_1:
1717 u32s = 1;
1718 break;
1719 case _LINUX_CAPABILITY_VERSION_2:
1720 case _LINUX_CAPABILITY_VERSION_3:
1721 u32s = 2;
1722 break;
1723 default:
1724 luch.version = _LINUX_CAPABILITY_VERSION_1;
1725 error = copyout(&luch, uap->hdrp, sizeof(luch));
1726 if (error)
1727 return (error);
1728 return (EINVAL);
1729 }
1730
1731 if (luch.pid)
1732 return (EPERM);
1733
1734 if (uap->datap) {
1735 /*
1736 * The current implementation doesn't support setting
1737 * a capability (it's essentially a stub) so indicate
1738 * that no capabilities are currently set or available
1739 * to request.
1740 */
1741 memset(&lucd, 0, u32s * sizeof(lucd[0]));
1742 error = copyout(&lucd, uap->datap, u32s * sizeof(lucd[0]));
1743 }
1744
1745 return (error);
1746 }
1747
1748 int
linux_capset(struct thread * td,struct linux_capset_args * uap)1749 linux_capset(struct thread *td, struct linux_capset_args *uap)
1750 {
1751 struct l_user_cap_header luch;
1752 struct l_user_cap_data lucd[2];
1753 int error, i, u32s;
1754
1755 if (uap->hdrp == NULL || uap->datap == NULL)
1756 return (EFAULT);
1757
1758 error = copyin(uap->hdrp, &luch, sizeof(luch));
1759 if (error != 0)
1760 return (error);
1761
1762 switch (luch.version) {
1763 case _LINUX_CAPABILITY_VERSION_1:
1764 u32s = 1;
1765 break;
1766 case _LINUX_CAPABILITY_VERSION_2:
1767 case _LINUX_CAPABILITY_VERSION_3:
1768 u32s = 2;
1769 break;
1770 default:
1771 luch.version = _LINUX_CAPABILITY_VERSION_1;
1772 error = copyout(&luch, uap->hdrp, sizeof(luch));
1773 if (error)
1774 return (error);
1775 return (EINVAL);
1776 }
1777
1778 if (luch.pid)
1779 return (EPERM);
1780
1781 error = copyin(uap->datap, &lucd, u32s * sizeof(lucd[0]));
1782 if (error != 0)
1783 return (error);
1784
1785 /* We currently don't support setting any capabilities. */
1786 for (i = 0; i < u32s; i++) {
1787 if (lucd[i].effective || lucd[i].permitted ||
1788 lucd[i].inheritable) {
1789 linux_msg(td,
1790 "capset[%d] effective=0x%x, permitted=0x%x, "
1791 "inheritable=0x%x is not implemented", i,
1792 (int)lucd[i].effective, (int)lucd[i].permitted,
1793 (int)lucd[i].inheritable);
1794 return (EPERM);
1795 }
1796 }
1797
1798 return (0);
1799 }
1800
1801 int
linux_prctl(struct thread * td,struct linux_prctl_args * args)1802 linux_prctl(struct thread *td, struct linux_prctl_args *args)
1803 {
1804 int error = 0, max_size, arg;
1805 struct proc *p = td->td_proc;
1806 char comm[LINUX_MAX_COMM_LEN];
1807 int pdeath_signal, trace_state;
1808
1809 switch (args->option) {
1810 case LINUX_PR_SET_PDEATHSIG:
1811 if (!LINUX_SIG_VALID(args->arg2))
1812 return (EINVAL);
1813 pdeath_signal = linux_to_bsd_signal(args->arg2);
1814 return (kern_procctl(td, P_PID, 0, PROC_PDEATHSIG_CTL,
1815 &pdeath_signal));
1816 case LINUX_PR_GET_PDEATHSIG:
1817 error = kern_procctl(td, P_PID, 0, PROC_PDEATHSIG_STATUS,
1818 &pdeath_signal);
1819 if (error != 0)
1820 return (error);
1821 pdeath_signal = bsd_to_linux_signal(pdeath_signal);
1822 return (copyout(&pdeath_signal,
1823 (void *)(register_t)args->arg2,
1824 sizeof(pdeath_signal)));
1825 /*
1826 * In Linux, this flag controls if set[gu]id processes can coredump.
1827 * There are additional semantics imposed on processes that cannot
1828 * coredump:
1829 * - Such processes can not be ptraced.
1830 * - There are some semantics around ownership of process-related files
1831 * in the /proc namespace.
1832 *
1833 * In FreeBSD, we can (and by default, do) disable setuid coredump
1834 * system-wide with 'sugid_coredump.' We control tracability on a
1835 * per-process basis with the procctl PROC_TRACE (=> P2_NOTRACE flag).
1836 * By happy coincidence, P2_NOTRACE also prevents coredumping. So the
1837 * procctl is roughly analogous to Linux's DUMPABLE.
1838 *
1839 * So, proxy these knobs to the corresponding PROC_TRACE setting.
1840 */
1841 case LINUX_PR_GET_DUMPABLE:
1842 error = kern_procctl(td, P_PID, p->p_pid, PROC_TRACE_STATUS,
1843 &trace_state);
1844 if (error != 0)
1845 return (error);
1846 td->td_retval[0] = (trace_state != -1);
1847 return (0);
1848 case LINUX_PR_SET_DUMPABLE:
1849 /*
1850 * It is only valid for userspace to set one of these two
1851 * flags, and only one at a time.
1852 */
1853 switch (args->arg2) {
1854 case LINUX_SUID_DUMP_DISABLE:
1855 trace_state = PROC_TRACE_CTL_DISABLE_EXEC;
1856 break;
1857 case LINUX_SUID_DUMP_USER:
1858 trace_state = PROC_TRACE_CTL_ENABLE;
1859 break;
1860 default:
1861 return (EINVAL);
1862 }
1863 return (kern_procctl(td, P_PID, p->p_pid, PROC_TRACE_CTL,
1864 &trace_state));
1865 case LINUX_PR_GET_KEEPCAPS:
1866 /*
1867 * Indicate that we always clear the effective and
1868 * permitted capability sets when the user id becomes
1869 * non-zero (actually the capability sets are simply
1870 * always zero in the current implementation).
1871 */
1872 td->td_retval[0] = 0;
1873 break;
1874 case LINUX_PR_SET_KEEPCAPS:
1875 /*
1876 * Ignore requests to keep the effective and permitted
1877 * capability sets when the user id becomes non-zero.
1878 */
1879 break;
1880 case LINUX_PR_SET_NAME:
1881 /*
1882 * To be on the safe side we need to make sure to not
1883 * overflow the size a Linux program expects. We already
1884 * do this here in the copyin, so that we don't need to
1885 * check on copyout.
1886 */
1887 max_size = MIN(sizeof(comm), sizeof(p->p_comm));
1888 error = copyinstr((void *)(register_t)args->arg2, comm,
1889 max_size, NULL);
1890
1891 /* Linux silently truncates the name if it is too long. */
1892 if (error == ENAMETOOLONG) {
1893 /*
1894 * XXX: copyinstr() isn't documented to populate the
1895 * array completely, so do a copyin() to be on the
1896 * safe side. This should be changed in case
1897 * copyinstr() is changed to guarantee this.
1898 */
1899 error = copyin((void *)(register_t)args->arg2, comm,
1900 max_size - 1);
1901 comm[max_size - 1] = '\0';
1902 }
1903 if (error)
1904 return (error);
1905
1906 PROC_LOCK(p);
1907 strlcpy(p->p_comm, comm, sizeof(p->p_comm));
1908 PROC_UNLOCK(p);
1909 break;
1910 case LINUX_PR_GET_NAME:
1911 PROC_LOCK(p);
1912 strlcpy(comm, p->p_comm, sizeof(comm));
1913 PROC_UNLOCK(p);
1914 error = copyout(comm, (void *)(register_t)args->arg2,
1915 strlen(comm) + 1);
1916 break;
1917 case LINUX_PR_GET_SECCOMP:
1918 case LINUX_PR_SET_SECCOMP:
1919 /*
1920 * Same as returned by Linux without CONFIG_SECCOMP enabled.
1921 */
1922 error = EINVAL;
1923 break;
1924 case LINUX_PR_CAPBSET_READ:
1925 #if 0
1926 /*
1927 * This makes too much noise with Ubuntu Focal.
1928 */
1929 linux_msg(td, "unsupported prctl PR_CAPBSET_READ %d",
1930 (int)args->arg2);
1931 #endif
1932 error = EINVAL;
1933 break;
1934 case LINUX_PR_SET_CHILD_SUBREAPER:
1935 if (args->arg2 == 0) {
1936 return (kern_procctl(td, P_PID, 0, PROC_REAP_RELEASE,
1937 NULL));
1938 }
1939
1940 return (kern_procctl(td, P_PID, 0, PROC_REAP_ACQUIRE,
1941 NULL));
1942 case LINUX_PR_GET_CHILD_SUBREAPER: {
1943 struct procctl_reaper_status rs;
1944 l_int val;
1945
1946 error = kern_procctl(td, P_PID, 0, PROC_REAP_STATUS, &rs);
1947 if (error != 0)
1948 return (error);
1949 val = rs.rs_reaper == p->p_pid ? 1 : 0;
1950 error = copyout(&val, (void *)(register_t)args->arg2,
1951 sizeof(val));
1952 break;
1953 }
1954 case LINUX_PR_SET_NO_NEW_PRIVS:
1955 arg = args->arg2 == 1 ?
1956 PROC_NO_NEW_PRIVS_ENABLE : PROC_NO_NEW_PRIVS_DISABLE;
1957 error = kern_procctl(td, P_PID, p->p_pid,
1958 PROC_NO_NEW_PRIVS_CTL, &arg);
1959 break;
1960 case LINUX_PR_GET_NO_NEW_PRIVS:
1961 error = kern_procctl(td, P_PID, p->p_pid,
1962 PROC_NO_NEW_PRIVS_STATUS, &arg);
1963 if (error != 0)
1964 return (error);
1965 /* Linux returns the value as the syscall return */
1966 td->td_retval[0] = arg == PROC_NO_NEW_PRIVS_ENABLE ? 1 : 0;
1967 break;
1968 case LINUX_PR_SET_PTRACER:
1969 linux_msg(td, "unsupported prctl PR_SET_PTRACER");
1970 error = EINVAL;
1971 break;
1972 case LINUX_PR_SET_VMA:
1973 if (args->arg2 != LINUX_PR_SET_VMA_ANON_NAME) {
1974 linux_msg(td, "unsupported prctl PR_SET_VMA attr %ju",
1975 (uintmax_t)args->arg2);
1976 error = EINVAL;
1977 }
1978 break;
1979 case LINUX_PR_GET_THP_DISABLE:
1980 /*
1981 * THP not in play, since FreeBSD doesn't have THP. Although
1982 * similar, superpages don't have the crazy issues THP does, so
1983 * tell the best lie possible: there's no problems with crazy
1984 * latency spikes: this feature is disabled.
1985 */
1986
1987 td->td_retval[0] = 1;
1988 break;
1989 case LINUX_PR_SET_THP_DISABLE:
1990 /*
1991 * Accept anything that's valid: Linux treats any nonzero
1992 * arg2 as "disable", so there's nothing to reject here.
1993 */
1994 td->td_retval[0] = 0;
1995 break;
1996 default:
1997 linux_msg(td, "unsupported prctl option %d", args->option);
1998 error = EINVAL;
1999 break;
2000 }
2001
2002 return (error);
2003 }
2004
2005 int
linux_sched_setparam(struct thread * td,struct linux_sched_setparam_args * uap)2006 linux_sched_setparam(struct thread *td,
2007 struct linux_sched_setparam_args *uap)
2008 {
2009 struct sched_param sched_param;
2010 struct thread *tdt;
2011 int error, policy;
2012
2013 error = copyin(uap->param, &sched_param, sizeof(sched_param));
2014 if (error)
2015 return (error);
2016
2017 tdt = linux_tdfind(td, uap->pid, -1);
2018 if (tdt == NULL)
2019 return (ESRCH);
2020
2021 if (linux_map_sched_prio) {
2022 error = kern_sched_getscheduler(td, tdt, &policy);
2023 if (error)
2024 goto out;
2025
2026 switch (policy) {
2027 case SCHED_OTHER:
2028 if (sched_param.sched_priority != 0) {
2029 error = EINVAL;
2030 goto out;
2031 }
2032 sched_param.sched_priority =
2033 PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE;
2034 break;
2035 case SCHED_FIFO:
2036 case SCHED_RR:
2037 if (sched_param.sched_priority < 1 ||
2038 sched_param.sched_priority >= LINUX_MAX_RT_PRIO) {
2039 error = EINVAL;
2040 goto out;
2041 }
2042 /*
2043 * Map [1, LINUX_MAX_RT_PRIO - 1] to
2044 * [0, RTP_PRIO_MAX - RTP_PRIO_MIN] (rounding down).
2045 */
2046 sched_param.sched_priority =
2047 (sched_param.sched_priority - 1) *
2048 (RTP_PRIO_MAX - RTP_PRIO_MIN + 1) /
2049 (LINUX_MAX_RT_PRIO - 1);
2050 break;
2051 }
2052 }
2053
2054 error = kern_sched_setparam(td, tdt, &sched_param);
2055 out: PROC_UNLOCK(tdt->td_proc);
2056 return (error);
2057 }
2058
2059 int
linux_sched_getparam(struct thread * td,struct linux_sched_getparam_args * uap)2060 linux_sched_getparam(struct thread *td,
2061 struct linux_sched_getparam_args *uap)
2062 {
2063 struct sched_param sched_param;
2064 struct thread *tdt;
2065 int error, policy;
2066
2067 tdt = linux_tdfind(td, uap->pid, -1);
2068 if (tdt == NULL)
2069 return (ESRCH);
2070
2071 error = kern_sched_getparam(td, tdt, &sched_param);
2072 if (error) {
2073 PROC_UNLOCK(tdt->td_proc);
2074 return (error);
2075 }
2076
2077 if (linux_map_sched_prio) {
2078 error = kern_sched_getscheduler(td, tdt, &policy);
2079 PROC_UNLOCK(tdt->td_proc);
2080 if (error)
2081 return (error);
2082
2083 switch (policy) {
2084 case SCHED_OTHER:
2085 sched_param.sched_priority = 0;
2086 break;
2087 case SCHED_FIFO:
2088 case SCHED_RR:
2089 /*
2090 * Map [0, RTP_PRIO_MAX - RTP_PRIO_MIN] to
2091 * [1, LINUX_MAX_RT_PRIO - 1] (rounding up).
2092 */
2093 sched_param.sched_priority =
2094 (sched_param.sched_priority *
2095 (LINUX_MAX_RT_PRIO - 1) +
2096 (RTP_PRIO_MAX - RTP_PRIO_MIN - 1)) /
2097 (RTP_PRIO_MAX - RTP_PRIO_MIN) + 1;
2098 break;
2099 }
2100 } else
2101 PROC_UNLOCK(tdt->td_proc);
2102
2103 error = copyout(&sched_param, uap->param, sizeof(sched_param));
2104 return (error);
2105 }
2106
2107 /*
2108 * Get affinity of a process.
2109 */
2110 int
linux_sched_getaffinity(struct thread * td,struct linux_sched_getaffinity_args * args)2111 linux_sched_getaffinity(struct thread *td,
2112 struct linux_sched_getaffinity_args *args)
2113 {
2114 struct thread *tdt;
2115 cpuset_t *mask;
2116 size_t size;
2117 int error;
2118 id_t tid;
2119
2120 tdt = linux_tdfind(td, args->pid, -1);
2121 if (tdt == NULL)
2122 return (ESRCH);
2123 tid = tdt->td_tid;
2124 PROC_UNLOCK(tdt->td_proc);
2125
2126 mask = malloc(sizeof(cpuset_t), M_LINUX, M_WAITOK | M_ZERO);
2127 size = min(args->len, sizeof(cpuset_t));
2128 error = kern_cpuset_getaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID,
2129 tid, size, mask);
2130 if (error == ERANGE)
2131 error = EINVAL;
2132 if (error == 0)
2133 error = copyout(mask, args->user_mask_ptr, size);
2134 if (error == 0)
2135 td->td_retval[0] = size;
2136 free(mask, M_LINUX);
2137 return (error);
2138 }
2139
2140 /*
2141 * Set affinity of a process.
2142 */
2143 int
linux_sched_setaffinity(struct thread * td,struct linux_sched_setaffinity_args * args)2144 linux_sched_setaffinity(struct thread *td,
2145 struct linux_sched_setaffinity_args *args)
2146 {
2147 struct thread *tdt;
2148 cpuset_t *mask;
2149 int cpu, error;
2150 size_t len;
2151 id_t tid;
2152
2153 tdt = linux_tdfind(td, args->pid, -1);
2154 if (tdt == NULL)
2155 return (ESRCH);
2156 tid = tdt->td_tid;
2157 PROC_UNLOCK(tdt->td_proc);
2158
2159 len = min(args->len, sizeof(cpuset_t));
2160 mask = malloc(sizeof(cpuset_t), M_TEMP, M_WAITOK | M_ZERO);
2161 error = copyin(args->user_mask_ptr, mask, len);
2162 if (error != 0)
2163 goto out;
2164 /* Linux ignore high bits */
2165 CPU_FOREACH_ISSET(cpu, mask)
2166 if (cpu > mp_maxid)
2167 CPU_CLR(cpu, mask);
2168
2169 error = kern_cpuset_setaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID,
2170 tid, mask);
2171 if (error == EDEADLK)
2172 error = EINVAL;
2173 out:
2174 free(mask, M_TEMP);
2175 return (error);
2176 }
2177
2178 struct linux_rlimit64 {
2179 uint64_t rlim_cur;
2180 uint64_t rlim_max;
2181 };
2182
2183 int
linux_prlimit64(struct thread * td,struct linux_prlimit64_args * args)2184 linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args)
2185 {
2186 struct rlimit rlim, nrlim;
2187 struct linux_rlimit64 lrlim;
2188 struct proc *p;
2189 u_int which;
2190 int flags;
2191 int error;
2192 bool exec_blocked;
2193
2194 if (args->new == NULL && args->old != NULL) {
2195 if (linux_get_dummy_limit(td, args->resource, &rlim)) {
2196 lrlim.rlim_cur = rlim.rlim_cur;
2197 lrlim.rlim_max = rlim.rlim_max;
2198 return (copyout(&lrlim, args->old, sizeof(lrlim)));
2199 }
2200 }
2201
2202 if (args->resource >= LINUX_RLIM_NLIMITS)
2203 return (EINVAL);
2204
2205 which = linux_to_bsd_resource[args->resource];
2206 if (which == -1)
2207 return (EINVAL);
2208
2209 if (args->new != NULL) {
2210 /*
2211 * Note. Unlike FreeBSD where rlim is signed 64-bit Linux
2212 * rlim is unsigned 64-bit. FreeBSD treats negative limits
2213 * as INFINITY so we do not need a conversion even.
2214 */
2215 error = copyin(args->new, &nrlim, sizeof(nrlim));
2216 if (error != 0)
2217 return (error);
2218 }
2219
2220 exec_blocked = false;
2221 flags = PGET_HOLD | PGET_NOTWEXIT;
2222 if (args->new != NULL)
2223 flags |= PGET_CANDEBUG;
2224 else
2225 flags |= PGET_CANSEE;
2226 if (args->pid == 0) {
2227 p = td->td_proc;
2228 PHOLD(p);
2229 } else {
2230 error = pget(args->pid, flags, &p);
2231 if (error != 0)
2232 return (error);
2233 exec_blocked = true;
2234 PROC_LOCK(p);
2235 execve_block_wait(td, p);
2236 error = args->new != NULL ? p_candebug(td, p) :
2237 p_cansee(td, p);
2238 PROC_UNLOCK(p);
2239 if (error != 0)
2240 goto out;
2241 }
2242 if (args->old != NULL) {
2243 PROC_LOCK(p);
2244 lim_rlimit_proc(p, which, &rlim);
2245 PROC_UNLOCK(p);
2246 if (rlim.rlim_cur == RLIM_INFINITY)
2247 lrlim.rlim_cur = LINUX_RLIM_INFINITY;
2248 else
2249 lrlim.rlim_cur = rlim.rlim_cur;
2250 if (rlim.rlim_max == RLIM_INFINITY)
2251 lrlim.rlim_max = LINUX_RLIM_INFINITY;
2252 else
2253 lrlim.rlim_max = rlim.rlim_max;
2254 error = copyout(&lrlim, args->old, sizeof(lrlim));
2255 if (error != 0)
2256 goto out;
2257 }
2258
2259 if (args->new != NULL)
2260 error = kern_proc_setrlimit(td, p, which, &nrlim);
2261
2262 out:
2263 if (exec_blocked) {
2264 PROC_LOCK(p);
2265 execve_unblock(td, p);
2266 PROC_UNLOCK(p);
2267 }
2268 PRELE(p);
2269 return (error);
2270 }
2271
2272 int
linux_pselect6(struct thread * td,struct linux_pselect6_args * args)2273 linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
2274 {
2275 struct timespec ts, *tsp;
2276 int error;
2277
2278 if (args->tsp != NULL) {
2279 error = linux_get_timespec(&ts, args->tsp);
2280 if (error != 0)
2281 return (error);
2282 tsp = &ts;
2283 } else
2284 tsp = NULL;
2285
2286 error = linux_common_pselect6(td, args->nfds, args->readfds,
2287 args->writefds, args->exceptfds, tsp, args->sig);
2288
2289 if (args->tsp != NULL)
2290 linux_put_timespec(&ts, args->tsp);
2291 return (error);
2292 }
2293
2294 static int
linux_common_pselect6(struct thread * td,l_int nfds,l_fd_set * readfds,l_fd_set * writefds,l_fd_set * exceptfds,struct timespec * tsp,l_uintptr_t * sig)2295 linux_common_pselect6(struct thread *td, l_int nfds, l_fd_set *readfds,
2296 l_fd_set *writefds, l_fd_set *exceptfds, struct timespec *tsp,
2297 l_uintptr_t *sig)
2298 {
2299 struct timeval utv, tv0, tv1, *tvp;
2300 struct l_pselect6arg lpse6;
2301 sigset_t *ssp;
2302 sigset_t ss;
2303 int error;
2304
2305 ssp = NULL;
2306 if (sig != NULL) {
2307 error = copyin(sig, &lpse6, sizeof(lpse6));
2308 if (error != 0)
2309 return (error);
2310 error = linux_copyin_sigset(td, PTRIN(lpse6.ss),
2311 lpse6.ss_len, &ss, &ssp);
2312 if (error != 0)
2313 return (error);
2314 } else
2315 ssp = NULL;
2316
2317 /*
2318 * Currently glibc changes nanosecond number to microsecond.
2319 * This mean losing precision but for now it is hardly seen.
2320 */
2321 if (tsp != NULL) {
2322 TIMESPEC_TO_TIMEVAL(&utv, tsp);
2323 if (itimerfix(&utv))
2324 return (EINVAL);
2325
2326 microtime(&tv0);
2327 tvp = &utv;
2328 } else
2329 tvp = NULL;
2330
2331 error = kern_pselect(td, nfds, readfds, writefds,
2332 exceptfds, tvp, ssp, LINUX_NFDBITS);
2333
2334 if (tsp != NULL) {
2335 /*
2336 * Compute how much time was left of the timeout,
2337 * by subtracting the current time and the time
2338 * before we started the call, and subtracting
2339 * that result from the user-supplied value.
2340 */
2341 microtime(&tv1);
2342 timevalsub(&tv1, &tv0);
2343 timevalsub(&utv, &tv1);
2344 if (utv.tv_sec < 0)
2345 timevalclear(&utv);
2346 TIMEVAL_TO_TIMESPEC(&utv, tsp);
2347 }
2348 return (error);
2349 }
2350
2351 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
2352 int
linux_pselect6_time64(struct thread * td,struct linux_pselect6_time64_args * args)2353 linux_pselect6_time64(struct thread *td,
2354 struct linux_pselect6_time64_args *args)
2355 {
2356 struct timespec ts, *tsp;
2357 int error;
2358
2359 if (args->tsp != NULL) {
2360 error = linux_get_timespec64(&ts, args->tsp);
2361 if (error != 0)
2362 return (error);
2363 tsp = &ts;
2364 } else
2365 tsp = NULL;
2366
2367 error = linux_common_pselect6(td, args->nfds, args->readfds,
2368 args->writefds, args->exceptfds, tsp, args->sig);
2369
2370 if (args->tsp != NULL)
2371 linux_put_timespec64(&ts, args->tsp);
2372 return (error);
2373 }
2374 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
2375
2376 int
linux_ppoll(struct thread * td,struct linux_ppoll_args * args)2377 linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
2378 {
2379 struct timespec uts, *tsp;
2380 int error;
2381
2382 if (args->tsp != NULL) {
2383 error = linux_get_timespec(&uts, args->tsp);
2384 if (error != 0)
2385 return (error);
2386 tsp = &uts;
2387 } else
2388 tsp = NULL;
2389
2390 error = linux_common_ppoll(td, args->fds, args->nfds, tsp,
2391 args->sset, args->ssize);
2392 if (error == 0 && args->tsp != NULL)
2393 error = linux_put_timespec(&uts, args->tsp);
2394 return (error);
2395 }
2396
2397 static int
linux_common_ppoll(struct thread * td,struct pollfd * fds,uint32_t nfds,struct timespec * tsp,l_sigset_t * sset,l_size_t ssize)2398 linux_common_ppoll(struct thread *td, struct pollfd *fds, uint32_t nfds,
2399 struct timespec *tsp, l_sigset_t *sset, l_size_t ssize)
2400 {
2401 struct timespec ts0, ts1;
2402 struct pollfd stackfds[32];
2403 struct pollfd *kfds;
2404 sigset_t *ssp;
2405 sigset_t ss;
2406 int error;
2407
2408 if (kern_poll_maxfds(nfds))
2409 return (EINVAL);
2410 if (sset != NULL) {
2411 error = linux_copyin_sigset(td, sset, ssize, &ss, &ssp);
2412 if (error != 0)
2413 return (error);
2414 } else
2415 ssp = NULL;
2416 if (tsp != NULL)
2417 nanotime(&ts0);
2418
2419 if (nfds > nitems(stackfds))
2420 kfds = mallocarray(nfds, sizeof(*kfds), M_TEMP, M_WAITOK);
2421 else
2422 kfds = stackfds;
2423 error = linux_pollin(td, kfds, fds, nfds);
2424 if (error != 0)
2425 goto out;
2426
2427 error = kern_poll_kfds(td, kfds, nfds, tsp, ssp);
2428 if (error == 0)
2429 error = linux_pollout(td, kfds, fds, nfds);
2430
2431 if (error == 0 && tsp != NULL) {
2432 if (td->td_retval[0]) {
2433 nanotime(&ts1);
2434 timespecsub(&ts1, &ts0, &ts1);
2435 timespecsub(tsp, &ts1, tsp);
2436 if (tsp->tv_sec < 0)
2437 timespecclear(tsp);
2438 } else
2439 timespecclear(tsp);
2440 }
2441
2442 out:
2443 if (nfds > nitems(stackfds))
2444 free(kfds, M_TEMP);
2445 return (error);
2446 }
2447
2448 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
2449 int
linux_ppoll_time64(struct thread * td,struct linux_ppoll_time64_args * args)2450 linux_ppoll_time64(struct thread *td, struct linux_ppoll_time64_args *args)
2451 {
2452 struct timespec uts, *tsp;
2453 int error;
2454
2455 if (args->tsp != NULL) {
2456 error = linux_get_timespec64(&uts, args->tsp);
2457 if (error != 0)
2458 return (error);
2459 tsp = &uts;
2460 } else
2461 tsp = NULL;
2462 error = linux_common_ppoll(td, args->fds, args->nfds, tsp,
2463 args->sset, args->ssize);
2464 if (error == 0 && args->tsp != NULL)
2465 error = linux_put_timespec64(&uts, args->tsp);
2466 return (error);
2467 }
2468 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
2469
2470 static int
linux_pollin(struct thread * td,struct pollfd * fds,struct pollfd * ufds,u_int nfd)2471 linux_pollin(struct thread *td, struct pollfd *fds, struct pollfd *ufds, u_int nfd)
2472 {
2473 int error;
2474 u_int i;
2475
2476 error = copyin(ufds, fds, nfd * sizeof(*fds));
2477 if (error != 0)
2478 return (error);
2479
2480 for (i = 0; i < nfd; i++) {
2481 if (fds->events != 0)
2482 linux_to_bsd_poll_events(td, fds->fd,
2483 fds->events, &fds->events);
2484 fds++;
2485 }
2486 return (0);
2487 }
2488
2489 static int
linux_pollout(struct thread * td,struct pollfd * fds,struct pollfd * ufds,u_int nfd)2490 linux_pollout(struct thread *td, struct pollfd *fds, struct pollfd *ufds, u_int nfd)
2491 {
2492 int error = 0;
2493 u_int i, n = 0;
2494
2495 for (i = 0; i < nfd; i++) {
2496 if (fds->revents != 0) {
2497 bsd_to_linux_poll_events(fds->revents,
2498 &fds->revents);
2499 n++;
2500 }
2501 error = copyout(&fds->revents, &ufds->revents,
2502 sizeof(ufds->revents));
2503 if (error)
2504 return (error);
2505 fds++;
2506 ufds++;
2507 }
2508 td->td_retval[0] = n;
2509 return (0);
2510 }
2511
2512 static int
linux_sched_rr_get_interval_common(struct thread * td,pid_t pid,struct timespec * ts)2513 linux_sched_rr_get_interval_common(struct thread *td, pid_t pid,
2514 struct timespec *ts)
2515 {
2516 struct thread *tdt;
2517 int error;
2518
2519 /*
2520 * According to man in case the invalid pid specified
2521 * EINVAL should be returned.
2522 */
2523 if (pid < 0)
2524 return (EINVAL);
2525
2526 tdt = linux_tdfind(td, pid, -1);
2527 if (tdt == NULL)
2528 return (ESRCH);
2529
2530 error = kern_sched_rr_get_interval_td(td, tdt, ts);
2531 PROC_UNLOCK(tdt->td_proc);
2532 return (error);
2533 }
2534
2535 int
linux_sched_rr_get_interval(struct thread * td,struct linux_sched_rr_get_interval_args * uap)2536 linux_sched_rr_get_interval(struct thread *td,
2537 struct linux_sched_rr_get_interval_args *uap)
2538 {
2539 struct timespec ts;
2540 int error;
2541
2542 error = linux_sched_rr_get_interval_common(td, uap->pid, &ts);
2543 if (error != 0)
2544 return (error);
2545 return (linux_put_timespec(&ts, uap->interval));
2546 }
2547
2548 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
2549 int
linux_sched_rr_get_interval_time64(struct thread * td,struct linux_sched_rr_get_interval_time64_args * uap)2550 linux_sched_rr_get_interval_time64(struct thread *td,
2551 struct linux_sched_rr_get_interval_time64_args *uap)
2552 {
2553 struct timespec ts;
2554 int error;
2555
2556 error = linux_sched_rr_get_interval_common(td, uap->pid, &ts);
2557 if (error != 0)
2558 return (error);
2559 return (linux_put_timespec64(&ts, uap->interval));
2560 }
2561 #endif
2562
2563 /*
2564 * In case when the Linux thread is the initial thread in
2565 * the thread group thread id is equal to the process id.
2566 * Glibc depends on this magic (assert in pthread_getattr_np.c).
2567 */
2568 struct thread *
linux_tdfind(struct thread * td,lwpid_t tid,pid_t pid)2569 linux_tdfind(struct thread *td, lwpid_t tid, pid_t pid)
2570 {
2571 struct linux_emuldata *em;
2572 struct thread *tdt;
2573 struct proc *p;
2574
2575 tdt = NULL;
2576 if (tid == 0 || tid == td->td_tid) {
2577 if (pid != -1 && td->td_proc->p_pid != pid)
2578 return (NULL);
2579 PROC_LOCK(td->td_proc);
2580 return (td);
2581 } else if (tid > PID_MAX)
2582 return (tdfind(tid, pid));
2583
2584 /*
2585 * Initial thread where the tid equal to the pid.
2586 */
2587 p = pfind(tid);
2588 if (p != NULL) {
2589 if (SV_PROC_ABI(p) != SV_ABI_LINUX ||
2590 (pid != -1 && tid != pid)) {
2591 /*
2592 * p is not a Linuxulator process.
2593 */
2594 PROC_UNLOCK(p);
2595 return (NULL);
2596 }
2597 FOREACH_THREAD_IN_PROC(p, tdt) {
2598 em = em_find(tdt);
2599 if (tid == em->em_tid)
2600 return (tdt);
2601 }
2602 PROC_UNLOCK(p);
2603 }
2604 return (NULL);
2605 }
2606
2607 void
linux_to_bsd_waitopts(int options,int * bsdopts)2608 linux_to_bsd_waitopts(int options, int *bsdopts)
2609 {
2610
2611 if (options & LINUX_WNOHANG)
2612 *bsdopts |= WNOHANG;
2613 if (options & LINUX_WUNTRACED)
2614 *bsdopts |= WUNTRACED;
2615 if (options & LINUX_WEXITED)
2616 *bsdopts |= WEXITED;
2617 if (options & LINUX_WCONTINUED)
2618 *bsdopts |= WCONTINUED;
2619 if (options & LINUX_WNOWAIT)
2620 *bsdopts |= WNOWAIT;
2621
2622 if (options & __WCLONE)
2623 *bsdopts |= WLINUXCLONE;
2624 }
2625
2626 int
linux_getrandom(struct thread * td,struct linux_getrandom_args * args)2627 linux_getrandom(struct thread *td, struct linux_getrandom_args *args)
2628 {
2629 struct uio uio;
2630 struct iovec iov;
2631 int error;
2632
2633 if (args->flags & ~(LINUX_GRND_NONBLOCK|LINUX_GRND_RANDOM))
2634 return (EINVAL);
2635 if (args->count > INT_MAX)
2636 args->count = INT_MAX;
2637
2638 iov.iov_base = args->buf;
2639 iov.iov_len = args->count;
2640
2641 uio.uio_iov = &iov;
2642 uio.uio_iovcnt = 1;
2643 uio.uio_resid = iov.iov_len;
2644 uio.uio_segflg = UIO_USERSPACE;
2645 uio.uio_rw = UIO_READ;
2646 uio.uio_td = td;
2647
2648 error = read_random_uio(&uio, args->flags & LINUX_GRND_NONBLOCK);
2649 if (error == 0)
2650 td->td_retval[0] = args->count - uio.uio_resid;
2651 return (error);
2652 }
2653
2654 int
linux_mincore(struct thread * td,struct linux_mincore_args * args)2655 linux_mincore(struct thread *td, struct linux_mincore_args *args)
2656 {
2657
2658 /* Needs to be page-aligned */
2659 if (args->start & PAGE_MASK)
2660 return (EINVAL);
2661 return (kern_mincore(td, args->start, args->len, args->vec));
2662 }
2663
2664 #define SYSLOG_TAG "<6>"
2665
2666 int
linux_syslog(struct thread * td,struct linux_syslog_args * args)2667 linux_syslog(struct thread *td, struct linux_syslog_args *args)
2668 {
2669 char buf[128], *src, *dst;
2670 u_int seq;
2671 int buflen, error;
2672
2673 if (args->type != LINUX_SYSLOG_ACTION_READ_ALL) {
2674 linux_msg(td, "syslog unsupported type 0x%x", args->type);
2675 return (EINVAL);
2676 }
2677
2678 if (args->len < 6) {
2679 td->td_retval[0] = 0;
2680 return (0);
2681 }
2682
2683 error = priv_check(td, PRIV_MSGBUF);
2684 if (error)
2685 return (error);
2686
2687 mtx_lock(&msgbuf_lock);
2688 msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
2689 mtx_unlock(&msgbuf_lock);
2690
2691 dst = args->buf;
2692 error = copyout(&SYSLOG_TAG, dst, sizeof(SYSLOG_TAG));
2693 /* The -1 is to skip the trailing '\0'. */
2694 dst += sizeof(SYSLOG_TAG) - 1;
2695
2696 while (error == 0) {
2697 mtx_lock(&msgbuf_lock);
2698 buflen = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
2699 mtx_unlock(&msgbuf_lock);
2700
2701 if (buflen == 0)
2702 break;
2703
2704 for (src = buf; src < buf + buflen && error == 0; src++) {
2705 if (*src == '\0')
2706 continue;
2707
2708 if (dst >= args->buf + args->len)
2709 goto out;
2710
2711 error = copyout(src, dst, 1);
2712 dst++;
2713
2714 if (*src == '\n' && *(src + 1) != '<' &&
2715 dst + sizeof(SYSLOG_TAG) < args->buf + args->len) {
2716 error = copyout(&SYSLOG_TAG,
2717 dst, sizeof(SYSLOG_TAG));
2718 dst += sizeof(SYSLOG_TAG) - 1;
2719 }
2720 }
2721 }
2722 out:
2723 td->td_retval[0] = dst - args->buf;
2724 return (error);
2725 }
2726
2727 int
linux_getcpu(struct thread * td,struct linux_getcpu_args * args)2728 linux_getcpu(struct thread *td, struct linux_getcpu_args *args)
2729 {
2730 int cpu, error, node;
2731
2732 cpu = td->td_oncpu; /* Make sure it doesn't change during copyout(9) */
2733 error = 0;
2734 node = cpuid_to_pcpu[cpu]->pc_domain;
2735
2736 if (args->cpu != NULL)
2737 error = copyout(&cpu, args->cpu, sizeof(l_int));
2738 if (args->node != NULL)
2739 error = copyout(&node, args->node, sizeof(l_int));
2740 return (error);
2741 }
2742
2743 #if defined(__i386__) || defined(__amd64__)
2744 int
linux_poll(struct thread * td,struct linux_poll_args * args)2745 linux_poll(struct thread *td, struct linux_poll_args *args)
2746 {
2747 struct timespec ts, *tsp;
2748
2749 if (args->timeout != INFTIM) {
2750 if (args->timeout < 0)
2751 return (EINVAL);
2752 ts.tv_sec = args->timeout / 1000;
2753 ts.tv_nsec = (args->timeout % 1000) * 1000000;
2754 tsp = &ts;
2755 } else
2756 tsp = NULL;
2757
2758 return (linux_common_ppoll(td, args->fds, args->nfds,
2759 tsp, NULL, 0));
2760 }
2761 #endif /* __i386__ || __amd64__ */
2762
2763 int
linux_seccomp(struct thread * td,struct linux_seccomp_args * args)2764 linux_seccomp(struct thread *td, struct linux_seccomp_args *args)
2765 {
2766
2767 switch (args->op) {
2768 case LINUX_SECCOMP_GET_ACTION_AVAIL:
2769 return (EOPNOTSUPP);
2770 default:
2771 /*
2772 * Ignore unknown operations, just like Linux kernel built
2773 * without CONFIG_SECCOMP.
2774 */
2775 return (EINVAL);
2776 }
2777 }
2778
2779 /*
2780 * Custom version of exec_copyin_args(), to copy out argument and environment
2781 * strings from the old process address space into the temporary string buffer.
2782 * Based on freebsd32_exec_copyin_args.
2783 */
2784 static int
linux_exec_copyin_args(struct image_args * args,const char * fname,l_uintptr_t * argv,l_uintptr_t * envv)2785 linux_exec_copyin_args(struct image_args *args, const char *fname,
2786 l_uintptr_t *argv, l_uintptr_t *envv)
2787 {
2788 char *argp, *envp;
2789 l_uintptr_t *ptr, arg;
2790 int error;
2791
2792 bzero(args, sizeof(*args));
2793 if (argv == NULL)
2794 return (EFAULT);
2795
2796 /*
2797 * Allocate demand-paged memory for the file name, argument, and
2798 * environment strings.
2799 */
2800 error = exec_alloc_args(args);
2801 if (error != 0)
2802 return (error);
2803
2804 /*
2805 * Copy the file name.
2806 */
2807 error = exec_args_add_fname(args, fname, UIO_USERSPACE);
2808 if (error != 0)
2809 goto err_exit;
2810
2811 /*
2812 * extract arguments first
2813 */
2814 ptr = argv;
2815 for (;;) {
2816 error = copyin(ptr++, &arg, sizeof(arg));
2817 if (error)
2818 goto err_exit;
2819 if (arg == 0)
2820 break;
2821 argp = PTRIN(arg);
2822 error = exec_args_add_arg(args, argp, UIO_USERSPACE);
2823 if (error != 0)
2824 goto err_exit;
2825 }
2826
2827 /*
2828 * This comment is from Linux do_execveat_common:
2829 * When argv is empty, add an empty string ("") as argv[0] to
2830 * ensure confused userspace programs that start processing
2831 * from argv[1] won't end up walking envp.
2832 */
2833 if (args->argc == 0 &&
2834 (error = exec_args_add_arg(args, "", UIO_SYSSPACE) != 0))
2835 goto err_exit;
2836
2837 /*
2838 * extract environment strings
2839 */
2840 if (envv) {
2841 ptr = envv;
2842 for (;;) {
2843 error = copyin(ptr++, &arg, sizeof(arg));
2844 if (error)
2845 goto err_exit;
2846 if (arg == 0)
2847 break;
2848 envp = PTRIN(arg);
2849 error = exec_args_add_env(args, envp, UIO_USERSPACE);
2850 if (error != 0)
2851 goto err_exit;
2852 }
2853 }
2854
2855 return (0);
2856
2857 err_exit:
2858 exec_free_args(args);
2859 return (error);
2860 }
2861
2862 int
linux_execve(struct thread * td,struct linux_execve_args * args)2863 linux_execve(struct thread *td, struct linux_execve_args *args)
2864 {
2865 struct image_args eargs;
2866 int error;
2867
2868 LINUX_CTR(execve);
2869
2870 error = linux_exec_copyin_args(&eargs, args->path, args->argp,
2871 args->envp);
2872 if (error == 0)
2873 error = linux_common_execve(td, &eargs);
2874 AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td);
2875 return (error);
2876 }
2877
2878 static void
linux_up_rtprio_if(struct thread * td1,struct rtprio * rtp)2879 linux_up_rtprio_if(struct thread *td1, struct rtprio *rtp)
2880 {
2881 struct rtprio rtp2;
2882
2883 pri_to_rtp(td1, &rtp2);
2884 if (rtp2.type < rtp->type ||
2885 (rtp2.type == rtp->type &&
2886 rtp2.prio < rtp->prio)) {
2887 rtp->type = rtp2.type;
2888 rtp->prio = rtp2.prio;
2889 }
2890 }
2891
2892 #define LINUX_PRIO_DIVIDER RTP_PRIO_MAX / LINUX_IOPRIO_MAX
2893
2894 static int
linux_rtprio2ioprio(struct rtprio * rtp)2895 linux_rtprio2ioprio(struct rtprio *rtp)
2896 {
2897 int ioprio, prio;
2898
2899 switch (rtp->type) {
2900 case RTP_PRIO_IDLE:
2901 prio = RTP_PRIO_MIN;
2902 ioprio = LINUX_IOPRIO_PRIO(LINUX_IOPRIO_CLASS_IDLE, prio);
2903 break;
2904 case RTP_PRIO_NORMAL:
2905 prio = rtp->prio / LINUX_PRIO_DIVIDER;
2906 ioprio = LINUX_IOPRIO_PRIO(LINUX_IOPRIO_CLASS_BE, prio);
2907 break;
2908 case RTP_PRIO_REALTIME:
2909 prio = rtp->prio / LINUX_PRIO_DIVIDER;
2910 ioprio = LINUX_IOPRIO_PRIO(LINUX_IOPRIO_CLASS_RT, prio);
2911 break;
2912 default:
2913 prio = RTP_PRIO_MIN;
2914 ioprio = LINUX_IOPRIO_PRIO(LINUX_IOPRIO_CLASS_NONE, prio);
2915 break;
2916 }
2917 return (ioprio);
2918 }
2919
2920 static int
linux_ioprio2rtprio(int ioprio,struct rtprio * rtp)2921 linux_ioprio2rtprio(int ioprio, struct rtprio *rtp)
2922 {
2923
2924 switch (LINUX_IOPRIO_PRIO_CLASS(ioprio)) {
2925 case LINUX_IOPRIO_CLASS_IDLE:
2926 rtp->prio = RTP_PRIO_MIN;
2927 rtp->type = RTP_PRIO_IDLE;
2928 break;
2929 case LINUX_IOPRIO_CLASS_BE:
2930 rtp->prio = LINUX_IOPRIO_PRIO_DATA(ioprio) * LINUX_PRIO_DIVIDER;
2931 rtp->type = RTP_PRIO_NORMAL;
2932 break;
2933 case LINUX_IOPRIO_CLASS_RT:
2934 rtp->prio = LINUX_IOPRIO_PRIO_DATA(ioprio) * LINUX_PRIO_DIVIDER;
2935 rtp->type = RTP_PRIO_REALTIME;
2936 break;
2937 default:
2938 return (EINVAL);
2939 }
2940 return (0);
2941 }
2942 #undef LINUX_PRIO_DIVIDER
2943
2944 int
linux_ioprio_get(struct thread * td,struct linux_ioprio_get_args * args)2945 linux_ioprio_get(struct thread *td, struct linux_ioprio_get_args *args)
2946 {
2947 struct thread *td1;
2948 struct rtprio rtp;
2949 struct pgrp *pg;
2950 struct proc *p;
2951 int error, found;
2952
2953 p = NULL;
2954 td1 = NULL;
2955 error = 0;
2956 found = 0;
2957 rtp.type = RTP_PRIO_IDLE;
2958 rtp.prio = RTP_PRIO_MAX;
2959 switch (args->which) {
2960 case LINUX_IOPRIO_WHO_PROCESS:
2961 if (args->who == 0) {
2962 td1 = td;
2963 p = td1->td_proc;
2964 PROC_LOCK(p);
2965 } else if (args->who > PID_MAX) {
2966 td1 = linux_tdfind(td, args->who, -1);
2967 if (td1 != NULL)
2968 p = td1->td_proc;
2969 } else
2970 p = pfind(args->who);
2971 if (p == NULL)
2972 return (ESRCH);
2973 if ((error = p_cansee(td, p))) {
2974 PROC_UNLOCK(p);
2975 break;
2976 }
2977 if (td1 != NULL) {
2978 pri_to_rtp(td1, &rtp);
2979 } else {
2980 FOREACH_THREAD_IN_PROC(p, td1) {
2981 linux_up_rtprio_if(td1, &rtp);
2982 }
2983 }
2984 found++;
2985 PROC_UNLOCK(p);
2986 break;
2987 case LINUX_IOPRIO_WHO_PGRP:
2988 sx_slock(&proctree_lock);
2989 if (args->who == 0) {
2990 pg = td->td_proc->p_pgrp;
2991 PGRP_LOCK(pg);
2992 } else {
2993 pg = pgfind(args->who);
2994 if (pg == NULL) {
2995 sx_sunlock(&proctree_lock);
2996 error = ESRCH;
2997 break;
2998 }
2999 }
3000 sx_sunlock(&proctree_lock);
3001 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
3002 PROC_LOCK(p);
3003 if (p->p_state == PRS_NORMAL &&
3004 p_cansee(td, p) == 0) {
3005 FOREACH_THREAD_IN_PROC(p, td1) {
3006 linux_up_rtprio_if(td1, &rtp);
3007 found++;
3008 }
3009 }
3010 PROC_UNLOCK(p);
3011 }
3012 PGRP_UNLOCK(pg);
3013 break;
3014 case LINUX_IOPRIO_WHO_USER:
3015 if (args->who == 0)
3016 args->who = td->td_ucred->cr_uid;
3017 sx_slock(&allproc_lock);
3018 FOREACH_PROC_IN_SYSTEM(p) {
3019 PROC_LOCK(p);
3020 if (p->p_state == PRS_NORMAL &&
3021 p->p_ucred->cr_uid == args->who &&
3022 p_cansee(td, p) == 0) {
3023 FOREACH_THREAD_IN_PROC(p, td1) {
3024 linux_up_rtprio_if(td1, &rtp);
3025 found++;
3026 }
3027 }
3028 PROC_UNLOCK(p);
3029 }
3030 sx_sunlock(&allproc_lock);
3031 break;
3032 default:
3033 error = EINVAL;
3034 break;
3035 }
3036 if (error == 0) {
3037 if (found != 0)
3038 td->td_retval[0] = linux_rtprio2ioprio(&rtp);
3039 else
3040 error = ESRCH;
3041 }
3042 return (error);
3043 }
3044
3045 int
linux_ioprio_set(struct thread * td,struct linux_ioprio_set_args * args)3046 linux_ioprio_set(struct thread *td, struct linux_ioprio_set_args *args)
3047 {
3048 struct thread *td1;
3049 struct rtprio rtp;
3050 struct pgrp *pg;
3051 struct proc *p;
3052 int error;
3053
3054 if ((error = linux_ioprio2rtprio(args->ioprio, &rtp)) != 0)
3055 return (error);
3056 /* Attempts to set high priorities (REALTIME) require su privileges. */
3057 if (RTP_PRIO_BASE(rtp.type) == RTP_PRIO_REALTIME &&
3058 (error = priv_check(td, PRIV_SCHED_RTPRIO)) != 0)
3059 return (error);
3060
3061 p = NULL;
3062 td1 = NULL;
3063 switch (args->which) {
3064 case LINUX_IOPRIO_WHO_PROCESS:
3065 if (args->who == 0) {
3066 td1 = td;
3067 p = td1->td_proc;
3068 PROC_LOCK(p);
3069 } else if (args->who > PID_MAX) {
3070 td1 = linux_tdfind(td, args->who, -1);
3071 if (td1 != NULL)
3072 p = td1->td_proc;
3073 } else
3074 p = pfind(args->who);
3075 if (p == NULL)
3076 return (ESRCH);
3077 if ((error = p_cansched(td, p))) {
3078 PROC_UNLOCK(p);
3079 break;
3080 }
3081 if (td1 != NULL) {
3082 error = rtp_to_pri(&rtp, td1);
3083 } else {
3084 FOREACH_THREAD_IN_PROC(p, td1) {
3085 if ((error = rtp_to_pri(&rtp, td1)) != 0)
3086 break;
3087 }
3088 }
3089 PROC_UNLOCK(p);
3090 break;
3091 case LINUX_IOPRIO_WHO_PGRP:
3092 sx_slock(&proctree_lock);
3093 if (args->who == 0) {
3094 pg = td->td_proc->p_pgrp;
3095 PGRP_LOCK(pg);
3096 } else {
3097 pg = pgfind(args->who);
3098 if (pg == NULL) {
3099 sx_sunlock(&proctree_lock);
3100 error = ESRCH;
3101 break;
3102 }
3103 }
3104 sx_sunlock(&proctree_lock);
3105 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
3106 PROC_LOCK(p);
3107 if (p->p_state == PRS_NORMAL &&
3108 p_cansched(td, p) == 0) {
3109 FOREACH_THREAD_IN_PROC(p, td1) {
3110 if ((error = rtp_to_pri(&rtp, td1)) != 0)
3111 break;
3112 }
3113 }
3114 PROC_UNLOCK(p);
3115 if (error != 0)
3116 break;
3117 }
3118 PGRP_UNLOCK(pg);
3119 break;
3120 case LINUX_IOPRIO_WHO_USER:
3121 if (args->who == 0)
3122 args->who = td->td_ucred->cr_uid;
3123 sx_slock(&allproc_lock);
3124 FOREACH_PROC_IN_SYSTEM(p) {
3125 PROC_LOCK(p);
3126 if (p->p_state == PRS_NORMAL &&
3127 p->p_ucred->cr_uid == args->who &&
3128 p_cansched(td, p) == 0) {
3129 FOREACH_THREAD_IN_PROC(p, td1) {
3130 if ((error = rtp_to_pri(&rtp, td1)) != 0)
3131 break;
3132 }
3133 }
3134 PROC_UNLOCK(p);
3135 if (error != 0)
3136 break;
3137 }
3138 sx_sunlock(&allproc_lock);
3139 break;
3140 default:
3141 error = EINVAL;
3142 break;
3143 }
3144 return (error);
3145 }
3146
3147 /* The only flag is O_NONBLOCK */
3148 #define B2L_MQ_FLAGS(bflags) ((bflags) != 0 ? LINUX_O_NONBLOCK : 0)
3149 #define L2B_MQ_FLAGS(lflags) ((lflags) != 0 ? O_NONBLOCK : 0)
3150
3151 int
linux_mq_open(struct thread * td,struct linux_mq_open_args * args)3152 linux_mq_open(struct thread *td, struct linux_mq_open_args *args)
3153 {
3154 struct mq_attr attr;
3155 int error, flags;
3156
3157 flags = linux_common_openflags(args->oflag);
3158 if ((flags & O_ACCMODE) == O_ACCMODE || (flags & O_EXEC) != 0)
3159 return (EINVAL);
3160 flags = FFLAGS(flags);
3161 if ((flags & O_CREAT) != 0 && args->attr != NULL) {
3162 error = copyin(args->attr, &attr, sizeof(attr));
3163 if (error != 0)
3164 return (error);
3165 attr.mq_flags = L2B_MQ_FLAGS(attr.mq_flags);
3166 }
3167
3168 return (kern_kmq_open(td, args->name, flags, args->mode,
3169 args->attr != NULL ? &attr : NULL));
3170 }
3171
3172 int
linux_mq_unlink(struct thread * td,struct linux_mq_unlink_args * args)3173 linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args)
3174 {
3175 struct kmq_unlink_args bsd_args = {
3176 .path = PTRIN(args->name)
3177 };
3178
3179 return (sys_kmq_unlink(td, &bsd_args));
3180 }
3181
3182 int
linux_mq_timedsend(struct thread * td,struct linux_mq_timedsend_args * args)3183 linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args)
3184 {
3185 struct timespec ts, *abs_timeout;
3186 int error;
3187
3188 if (args->abs_timeout == NULL)
3189 abs_timeout = NULL;
3190 else {
3191 error = linux_get_timespec(&ts, args->abs_timeout);
3192 if (error != 0)
3193 return (error);
3194 abs_timeout = &ts;
3195 }
3196
3197 return (kern_kmq_timedsend(td, args->mqd, PTRIN(args->msg_ptr),
3198 args->msg_len, args->msg_prio, abs_timeout));
3199 }
3200
3201 int
linux_mq_timedreceive(struct thread * td,struct linux_mq_timedreceive_args * args)3202 linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args)
3203 {
3204 struct timespec ts, *abs_timeout;
3205 int error;
3206
3207 if (args->abs_timeout == NULL)
3208 abs_timeout = NULL;
3209 else {
3210 error = linux_get_timespec(&ts, args->abs_timeout);
3211 if (error != 0)
3212 return (error);
3213 abs_timeout = &ts;
3214 }
3215
3216 return (kern_kmq_timedreceive(td, args->mqd, PTRIN(args->msg_ptr),
3217 args->msg_len, args->msg_prio, abs_timeout));
3218 }
3219
3220 int
linux_mq_notify(struct thread * td,struct linux_mq_notify_args * args)3221 linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args)
3222 {
3223 struct sigevent ev, *evp;
3224 struct l_sigevent l_ev;
3225 int error;
3226
3227 if (args->sevp == NULL)
3228 evp = NULL;
3229 else {
3230 error = copyin(args->sevp, &l_ev, sizeof(l_ev));
3231 if (error != 0)
3232 return (error);
3233 error = linux_convert_l_sigevent(&l_ev, &ev);
3234 if (error != 0)
3235 return (error);
3236 evp = &ev;
3237 }
3238
3239 return (kern_kmq_notify(td, args->mqd, evp));
3240 }
3241
3242 int
linux_mq_getsetattr(struct thread * td,struct linux_mq_getsetattr_args * args)3243 linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args)
3244 {
3245 struct mq_attr attr, oattr;
3246 int error;
3247
3248 if (args->attr != NULL) {
3249 error = copyin(args->attr, &attr, sizeof(attr));
3250 if (error != 0)
3251 return (error);
3252 attr.mq_flags = L2B_MQ_FLAGS(attr.mq_flags);
3253 }
3254
3255 error = kern_kmq_setattr(td, args->mqd, args->attr != NULL ? &attr : NULL,
3256 &oattr);
3257 if (error == 0 && args->oattr != NULL) {
3258 oattr.mq_flags = B2L_MQ_FLAGS(oattr.mq_flags);
3259 bzero(oattr.__reserved, sizeof(oattr.__reserved));
3260 error = copyout(&oattr, args->oattr, sizeof(oattr));
3261 }
3262
3263 return (error);
3264 }
3265
3266 int
linux_kcmp(struct thread * td,struct linux_kcmp_args * args)3267 linux_kcmp(struct thread *td, struct linux_kcmp_args *args)
3268 {
3269 int type;
3270
3271 switch (args->type) {
3272 case LINUX_KCMP_FILE:
3273 type = KCMP_FILE;
3274 break;
3275 case LINUX_KCMP_FILES:
3276 type = KCMP_FILES;
3277 break;
3278 case LINUX_KCMP_SIGHAND:
3279 type = KCMP_SIGHAND;
3280 break;
3281 case LINUX_KCMP_VM:
3282 type = KCMP_VM;
3283 break;
3284 default:
3285 return (EINVAL);
3286 }
3287
3288 return (kern_kcmp(td, args->pid1, args->pid2, type, args->idx1,
3289 args->idx));
3290 }
3291
3292 int
linux_membarrier(struct thread * td,struct linux_membarrier_args * args)3293 linux_membarrier(struct thread *td, struct linux_membarrier_args *args)
3294 {
3295 static const struct {
3296 int linux_cmd;
3297 int freebsd_cmd;
3298 } cmds[] = {
3299 { LINUX_MEMBARRIER_CMD_QUERY,
3300 MEMBARRIER_CMD_QUERY },
3301 { LINUX_MEMBARRIER_CMD_GLOBAL,
3302 MEMBARRIER_CMD_GLOBAL },
3303 { LINUX_MEMBARRIER_CMD_GLOBAL_EXPEDITED,
3304 MEMBARRIER_CMD_GLOBAL_EXPEDITED },
3305 { LINUX_MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
3306 MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED },
3307 { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED,
3308 MEMBARRIER_CMD_PRIVATE_EXPEDITED },
3309 { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
3310 MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED },
3311 { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE,
3312 MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE },
3313 { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
3314 MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE },
3315 { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ,
3316 MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ },
3317 { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ,
3318 MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ },
3319 { LINUX_MEMBARRIER_CMD_GET_REGISTRATIONS,
3320 MEMBARRIER_CMD_GET_REGISTRATIONS },
3321 };
3322 int cmd, error, flags, i, mask;
3323
3324 cmd = -1;
3325 for (i = 0; i < nitems(cmds); i++) {
3326 if (args->cmd == cmds[i].linux_cmd) {
3327 cmd = cmds[i].freebsd_cmd;
3328 break;
3329 }
3330 }
3331
3332 if (cmd == -1 || (args->flags & ~LINUX_MEMBARRIER_CMD_FLAG_CPU) != 0)
3333 return (EINVAL);
3334
3335 flags = 0;
3336 if ((args->flags & LINUX_MEMBARRIER_CMD_FLAG_CPU) != 0)
3337 flags |= MEMBARRIER_CMD_FLAG_CPU;
3338
3339 error = kern_membarrier(td, cmd, flags, args->cpu_id);
3340 if (error != 0)
3341 return (error);
3342
3343 if (args->cmd == LINUX_MEMBARRIER_CMD_QUERY ||
3344 args->cmd == LINUX_MEMBARRIER_CMD_GET_REGISTRATIONS) {
3345 mask = td->td_retval[0];
3346 td->td_retval[0] = 0;
3347 for (i = 0; i < nitems(cmds); i++)
3348 if ((mask & cmds[i].freebsd_cmd) != 0)
3349 td->td_retval[0] |= cmds[i].linux_cmd;
3350 }
3351
3352 return (0);
3353 }
3354
3355 /*
3356 * setfsuid() & setfsgid() exist to decouple the Linux filesystem credentials
3357 * from the effective credentials, avoiding signal exposure during privilege
3358 * transitions. The signal permission model that motivated this was revised in
3359 * Linux 2.0, making these syscalls obsolete for new applications.
3360 *
3361 * As there's no FreeBSD equivalent, implement both syscalls as no-ops that
3362 * return the current effective UID/GID as the previous filesystem UID/GID.
3363 * Linux returns the previous filesystem UID/GID for these syscalls, with no
3364 * error indication.
3365 */
3366
3367 int
linux_setfsuid(struct thread * td,struct linux_setfsuid_args * args)3368 linux_setfsuid(struct thread *td, struct linux_setfsuid_args *args)
3369 {
3370 td->td_retval[0] = td->td_ucred->cr_uid;
3371 return (0);
3372 }
3373
3374 int
linux_setfsgid(struct thread * td,struct linux_setfsgid_args * args)3375 linux_setfsgid(struct thread *td, struct linux_setfsgid_args *args)
3376 {
3377 td->td_retval[0] = td->td_ucred->cr_gid;
3378 return (0);
3379 }
3380
3381 MODULE_DEPEND(linux, mqueuefs, 1, 1, 1);
3382