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