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 case LINUX_PR_GET_THP_DISABLE:
1868 /*
1869 * THP not in play, since FreeBSD doesn't have THP. Although
1870 * similar, superpages don't have the crazy issues THP does, so
1871 * tell the best lie possible: there's no problems with crazy
1872 * latency spikes: this feature is disabled.
1873 */
1874
1875 td->td_retval[0] = 1;
1876 break;
1877 case LINUX_PR_SET_THP_DISABLE:
1878 /*
1879 * Accept anything that's valid: Linux treats any nonzero
1880 * arg2 as "disable", so there's nothing to reject here.
1881 */
1882 td->td_retval[0] = 0;
1883 break;
1884 default:
1885 linux_msg(td, "unsupported prctl option %d", args->option);
1886 error = EINVAL;
1887 break;
1888 }
1889
1890 return (error);
1891 }
1892
1893 int
linux_sched_setparam(struct thread * td,struct linux_sched_setparam_args * uap)1894 linux_sched_setparam(struct thread *td,
1895 struct linux_sched_setparam_args *uap)
1896 {
1897 struct sched_param sched_param;
1898 struct thread *tdt;
1899 int error, policy;
1900
1901 error = copyin(uap->param, &sched_param, sizeof(sched_param));
1902 if (error)
1903 return (error);
1904
1905 tdt = linux_tdfind(td, uap->pid, -1);
1906 if (tdt == NULL)
1907 return (ESRCH);
1908
1909 if (linux_map_sched_prio) {
1910 error = kern_sched_getscheduler(td, tdt, &policy);
1911 if (error)
1912 goto out;
1913
1914 switch (policy) {
1915 case SCHED_OTHER:
1916 if (sched_param.sched_priority != 0) {
1917 error = EINVAL;
1918 goto out;
1919 }
1920 sched_param.sched_priority =
1921 PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE;
1922 break;
1923 case SCHED_FIFO:
1924 case SCHED_RR:
1925 if (sched_param.sched_priority < 1 ||
1926 sched_param.sched_priority >= LINUX_MAX_RT_PRIO) {
1927 error = EINVAL;
1928 goto out;
1929 }
1930 /*
1931 * Map [1, LINUX_MAX_RT_PRIO - 1] to
1932 * [0, RTP_PRIO_MAX - RTP_PRIO_MIN] (rounding down).
1933 */
1934 sched_param.sched_priority =
1935 (sched_param.sched_priority - 1) *
1936 (RTP_PRIO_MAX - RTP_PRIO_MIN + 1) /
1937 (LINUX_MAX_RT_PRIO - 1);
1938 break;
1939 }
1940 }
1941
1942 error = kern_sched_setparam(td, tdt, &sched_param);
1943 out: PROC_UNLOCK(tdt->td_proc);
1944 return (error);
1945 }
1946
1947 int
linux_sched_getparam(struct thread * td,struct linux_sched_getparam_args * uap)1948 linux_sched_getparam(struct thread *td,
1949 struct linux_sched_getparam_args *uap)
1950 {
1951 struct sched_param sched_param;
1952 struct thread *tdt;
1953 int error, policy;
1954
1955 tdt = linux_tdfind(td, uap->pid, -1);
1956 if (tdt == NULL)
1957 return (ESRCH);
1958
1959 error = kern_sched_getparam(td, tdt, &sched_param);
1960 if (error) {
1961 PROC_UNLOCK(tdt->td_proc);
1962 return (error);
1963 }
1964
1965 if (linux_map_sched_prio) {
1966 error = kern_sched_getscheduler(td, tdt, &policy);
1967 PROC_UNLOCK(tdt->td_proc);
1968 if (error)
1969 return (error);
1970
1971 switch (policy) {
1972 case SCHED_OTHER:
1973 sched_param.sched_priority = 0;
1974 break;
1975 case SCHED_FIFO:
1976 case SCHED_RR:
1977 /*
1978 * Map [0, RTP_PRIO_MAX - RTP_PRIO_MIN] to
1979 * [1, LINUX_MAX_RT_PRIO - 1] (rounding up).
1980 */
1981 sched_param.sched_priority =
1982 (sched_param.sched_priority *
1983 (LINUX_MAX_RT_PRIO - 1) +
1984 (RTP_PRIO_MAX - RTP_PRIO_MIN - 1)) /
1985 (RTP_PRIO_MAX - RTP_PRIO_MIN) + 1;
1986 break;
1987 }
1988 } else
1989 PROC_UNLOCK(tdt->td_proc);
1990
1991 error = copyout(&sched_param, uap->param, sizeof(sched_param));
1992 return (error);
1993 }
1994
1995 /*
1996 * Get affinity of a process.
1997 */
1998 int
linux_sched_getaffinity(struct thread * td,struct linux_sched_getaffinity_args * args)1999 linux_sched_getaffinity(struct thread *td,
2000 struct linux_sched_getaffinity_args *args)
2001 {
2002 struct thread *tdt;
2003 cpuset_t *mask;
2004 size_t size;
2005 int error;
2006 id_t tid;
2007
2008 tdt = linux_tdfind(td, args->pid, -1);
2009 if (tdt == NULL)
2010 return (ESRCH);
2011 tid = tdt->td_tid;
2012 PROC_UNLOCK(tdt->td_proc);
2013
2014 mask = malloc(sizeof(cpuset_t), M_LINUX, M_WAITOK | M_ZERO);
2015 size = min(args->len, sizeof(cpuset_t));
2016 error = kern_cpuset_getaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID,
2017 tid, size, mask);
2018 if (error == ERANGE)
2019 error = EINVAL;
2020 if (error == 0)
2021 error = copyout(mask, args->user_mask_ptr, size);
2022 if (error == 0)
2023 td->td_retval[0] = size;
2024 free(mask, M_LINUX);
2025 return (error);
2026 }
2027
2028 /*
2029 * Set affinity of a process.
2030 */
2031 int
linux_sched_setaffinity(struct thread * td,struct linux_sched_setaffinity_args * args)2032 linux_sched_setaffinity(struct thread *td,
2033 struct linux_sched_setaffinity_args *args)
2034 {
2035 struct thread *tdt;
2036 cpuset_t *mask;
2037 int cpu, error;
2038 size_t len;
2039 id_t tid;
2040
2041 tdt = linux_tdfind(td, args->pid, -1);
2042 if (tdt == NULL)
2043 return (ESRCH);
2044 tid = tdt->td_tid;
2045 PROC_UNLOCK(tdt->td_proc);
2046
2047 len = min(args->len, sizeof(cpuset_t));
2048 mask = malloc(sizeof(cpuset_t), M_TEMP, M_WAITOK | M_ZERO);
2049 error = copyin(args->user_mask_ptr, mask, len);
2050 if (error != 0)
2051 goto out;
2052 /* Linux ignore high bits */
2053 CPU_FOREACH_ISSET(cpu, mask)
2054 if (cpu > mp_maxid)
2055 CPU_CLR(cpu, mask);
2056
2057 error = kern_cpuset_setaffinity(td, CPU_LEVEL_WHICH, CPU_WHICH_TID,
2058 tid, mask);
2059 if (error == EDEADLK)
2060 error = EINVAL;
2061 out:
2062 free(mask, M_TEMP);
2063 return (error);
2064 }
2065
2066 struct linux_rlimit64 {
2067 uint64_t rlim_cur;
2068 uint64_t rlim_max;
2069 };
2070
2071 int
linux_prlimit64(struct thread * td,struct linux_prlimit64_args * args)2072 linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args)
2073 {
2074 struct rlimit rlim, nrlim;
2075 struct linux_rlimit64 lrlim;
2076 struct proc *p;
2077 u_int which;
2078 int flags;
2079 int error;
2080 bool exec_blocked;
2081
2082 if (args->new == NULL && args->old != NULL) {
2083 if (linux_get_dummy_limit(td, args->resource, &rlim)) {
2084 lrlim.rlim_cur = rlim.rlim_cur;
2085 lrlim.rlim_max = rlim.rlim_max;
2086 return (copyout(&lrlim, args->old, sizeof(lrlim)));
2087 }
2088 }
2089
2090 if (args->resource >= LINUX_RLIM_NLIMITS)
2091 return (EINVAL);
2092
2093 which = linux_to_bsd_resource[args->resource];
2094 if (which == -1)
2095 return (EINVAL);
2096
2097 if (args->new != NULL) {
2098 /*
2099 * Note. Unlike FreeBSD where rlim is signed 64-bit Linux
2100 * rlim is unsigned 64-bit. FreeBSD treats negative limits
2101 * as INFINITY so we do not need a conversion even.
2102 */
2103 error = copyin(args->new, &nrlim, sizeof(nrlim));
2104 if (error != 0)
2105 return (error);
2106 }
2107
2108 exec_blocked = false;
2109 flags = PGET_HOLD | PGET_NOTWEXIT;
2110 if (args->new != NULL)
2111 flags |= PGET_CANDEBUG;
2112 else
2113 flags |= PGET_CANSEE;
2114 if (args->pid == 0) {
2115 p = td->td_proc;
2116 PHOLD(p);
2117 } else {
2118 error = pget(args->pid, flags, &p);
2119 if (error != 0)
2120 return (error);
2121 exec_blocked = true;
2122 PROC_LOCK(p);
2123 execve_block_wait(td, p);
2124 error = args->new != NULL ? p_candebug(td, p) :
2125 p_cansee(td, p);
2126 PROC_UNLOCK(p);
2127 if (error != 0)
2128 goto out;
2129 }
2130 if (args->old != NULL) {
2131 PROC_LOCK(p);
2132 lim_rlimit_proc(p, which, &rlim);
2133 PROC_UNLOCK(p);
2134 if (rlim.rlim_cur == RLIM_INFINITY)
2135 lrlim.rlim_cur = LINUX_RLIM_INFINITY;
2136 else
2137 lrlim.rlim_cur = rlim.rlim_cur;
2138 if (rlim.rlim_max == RLIM_INFINITY)
2139 lrlim.rlim_max = LINUX_RLIM_INFINITY;
2140 else
2141 lrlim.rlim_max = rlim.rlim_max;
2142 error = copyout(&lrlim, args->old, sizeof(lrlim));
2143 if (error != 0)
2144 goto out;
2145 }
2146
2147 if (args->new != NULL)
2148 error = kern_proc_setrlimit(td, p, which, &nrlim);
2149
2150 out:
2151 if (exec_blocked) {
2152 PROC_LOCK(p);
2153 execve_unblock(td, p);
2154 PROC_UNLOCK(p);
2155 }
2156 PRELE(p);
2157 return (error);
2158 }
2159
2160 int
linux_pselect6(struct thread * td,struct linux_pselect6_args * args)2161 linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
2162 {
2163 struct timespec ts, *tsp;
2164 int error;
2165
2166 if (args->tsp != NULL) {
2167 error = linux_get_timespec(&ts, args->tsp);
2168 if (error != 0)
2169 return (error);
2170 tsp = &ts;
2171 } else
2172 tsp = NULL;
2173
2174 error = linux_common_pselect6(td, args->nfds, args->readfds,
2175 args->writefds, args->exceptfds, tsp, args->sig);
2176
2177 if (args->tsp != NULL)
2178 linux_put_timespec(&ts, args->tsp);
2179 return (error);
2180 }
2181
2182 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)2183 linux_common_pselect6(struct thread *td, l_int nfds, l_fd_set *readfds,
2184 l_fd_set *writefds, l_fd_set *exceptfds, struct timespec *tsp,
2185 l_uintptr_t *sig)
2186 {
2187 struct timeval utv, tv0, tv1, *tvp;
2188 struct l_pselect6arg lpse6;
2189 sigset_t *ssp;
2190 sigset_t ss;
2191 int error;
2192
2193 ssp = NULL;
2194 if (sig != NULL) {
2195 error = copyin(sig, &lpse6, sizeof(lpse6));
2196 if (error != 0)
2197 return (error);
2198 error = linux_copyin_sigset(td, PTRIN(lpse6.ss),
2199 lpse6.ss_len, &ss, &ssp);
2200 if (error != 0)
2201 return (error);
2202 } else
2203 ssp = NULL;
2204
2205 /*
2206 * Currently glibc changes nanosecond number to microsecond.
2207 * This mean losing precision but for now it is hardly seen.
2208 */
2209 if (tsp != NULL) {
2210 TIMESPEC_TO_TIMEVAL(&utv, tsp);
2211 if (itimerfix(&utv))
2212 return (EINVAL);
2213
2214 microtime(&tv0);
2215 tvp = &utv;
2216 } else
2217 tvp = NULL;
2218
2219 error = kern_pselect(td, nfds, readfds, writefds,
2220 exceptfds, tvp, ssp, LINUX_NFDBITS);
2221
2222 if (tsp != NULL) {
2223 /*
2224 * Compute how much time was left of the timeout,
2225 * by subtracting the current time and the time
2226 * before we started the call, and subtracting
2227 * that result from the user-supplied value.
2228 */
2229 microtime(&tv1);
2230 timevalsub(&tv1, &tv0);
2231 timevalsub(&utv, &tv1);
2232 if (utv.tv_sec < 0)
2233 timevalclear(&utv);
2234 TIMEVAL_TO_TIMESPEC(&utv, tsp);
2235 }
2236 return (error);
2237 }
2238
2239 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
2240 int
linux_pselect6_time64(struct thread * td,struct linux_pselect6_time64_args * args)2241 linux_pselect6_time64(struct thread *td,
2242 struct linux_pselect6_time64_args *args)
2243 {
2244 struct timespec ts, *tsp;
2245 int error;
2246
2247 if (args->tsp != NULL) {
2248 error = linux_get_timespec64(&ts, args->tsp);
2249 if (error != 0)
2250 return (error);
2251 tsp = &ts;
2252 } else
2253 tsp = NULL;
2254
2255 error = linux_common_pselect6(td, args->nfds, args->readfds,
2256 args->writefds, args->exceptfds, tsp, args->sig);
2257
2258 if (args->tsp != NULL)
2259 linux_put_timespec64(&ts, args->tsp);
2260 return (error);
2261 }
2262 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
2263
2264 int
linux_ppoll(struct thread * td,struct linux_ppoll_args * args)2265 linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
2266 {
2267 struct timespec uts, *tsp;
2268 int error;
2269
2270 if (args->tsp != NULL) {
2271 error = linux_get_timespec(&uts, args->tsp);
2272 if (error != 0)
2273 return (error);
2274 tsp = &uts;
2275 } else
2276 tsp = NULL;
2277
2278 error = linux_common_ppoll(td, args->fds, args->nfds, tsp,
2279 args->sset, args->ssize);
2280 if (error == 0 && args->tsp != NULL)
2281 error = linux_put_timespec(&uts, args->tsp);
2282 return (error);
2283 }
2284
2285 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)2286 linux_common_ppoll(struct thread *td, struct pollfd *fds, uint32_t nfds,
2287 struct timespec *tsp, l_sigset_t *sset, l_size_t ssize)
2288 {
2289 struct timespec ts0, ts1;
2290 struct pollfd stackfds[32];
2291 struct pollfd *kfds;
2292 sigset_t *ssp;
2293 sigset_t ss;
2294 int error;
2295
2296 if (kern_poll_maxfds(nfds))
2297 return (EINVAL);
2298 if (sset != NULL) {
2299 error = linux_copyin_sigset(td, sset, ssize, &ss, &ssp);
2300 if (error != 0)
2301 return (error);
2302 } else
2303 ssp = NULL;
2304 if (tsp != NULL)
2305 nanotime(&ts0);
2306
2307 if (nfds > nitems(stackfds))
2308 kfds = mallocarray(nfds, sizeof(*kfds), M_TEMP, M_WAITOK);
2309 else
2310 kfds = stackfds;
2311 error = linux_pollin(td, kfds, fds, nfds);
2312 if (error != 0)
2313 goto out;
2314
2315 error = kern_poll_kfds(td, kfds, nfds, tsp, ssp);
2316 if (error == 0)
2317 error = linux_pollout(td, kfds, fds, nfds);
2318
2319 if (error == 0 && tsp != NULL) {
2320 if (td->td_retval[0]) {
2321 nanotime(&ts1);
2322 timespecsub(&ts1, &ts0, &ts1);
2323 timespecsub(tsp, &ts1, tsp);
2324 if (tsp->tv_sec < 0)
2325 timespecclear(tsp);
2326 } else
2327 timespecclear(tsp);
2328 }
2329
2330 out:
2331 if (nfds > nitems(stackfds))
2332 free(kfds, M_TEMP);
2333 return (error);
2334 }
2335
2336 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
2337 int
linux_ppoll_time64(struct thread * td,struct linux_ppoll_time64_args * args)2338 linux_ppoll_time64(struct thread *td, struct linux_ppoll_time64_args *args)
2339 {
2340 struct timespec uts, *tsp;
2341 int error;
2342
2343 if (args->tsp != NULL) {
2344 error = linux_get_timespec64(&uts, args->tsp);
2345 if (error != 0)
2346 return (error);
2347 tsp = &uts;
2348 } else
2349 tsp = NULL;
2350 error = linux_common_ppoll(td, args->fds, args->nfds, tsp,
2351 args->sset, args->ssize);
2352 if (error == 0 && args->tsp != NULL)
2353 error = linux_put_timespec64(&uts, args->tsp);
2354 return (error);
2355 }
2356 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
2357
2358 static int
linux_pollin(struct thread * td,struct pollfd * fds,struct pollfd * ufds,u_int nfd)2359 linux_pollin(struct thread *td, struct pollfd *fds, struct pollfd *ufds, u_int nfd)
2360 {
2361 int error;
2362 u_int i;
2363
2364 error = copyin(ufds, fds, nfd * sizeof(*fds));
2365 if (error != 0)
2366 return (error);
2367
2368 for (i = 0; i < nfd; i++) {
2369 if (fds->events != 0)
2370 linux_to_bsd_poll_events(td, fds->fd,
2371 fds->events, &fds->events);
2372 fds++;
2373 }
2374 return (0);
2375 }
2376
2377 static int
linux_pollout(struct thread * td,struct pollfd * fds,struct pollfd * ufds,u_int nfd)2378 linux_pollout(struct thread *td, struct pollfd *fds, struct pollfd *ufds, u_int nfd)
2379 {
2380 int error = 0;
2381 u_int i, n = 0;
2382
2383 for (i = 0; i < nfd; i++) {
2384 if (fds->revents != 0) {
2385 bsd_to_linux_poll_events(fds->revents,
2386 &fds->revents);
2387 n++;
2388 }
2389 error = copyout(&fds->revents, &ufds->revents,
2390 sizeof(ufds->revents));
2391 if (error)
2392 return (error);
2393 fds++;
2394 ufds++;
2395 }
2396 td->td_retval[0] = n;
2397 return (0);
2398 }
2399
2400 static int
linux_sched_rr_get_interval_common(struct thread * td,pid_t pid,struct timespec * ts)2401 linux_sched_rr_get_interval_common(struct thread *td, pid_t pid,
2402 struct timespec *ts)
2403 {
2404 struct thread *tdt;
2405 int error;
2406
2407 /*
2408 * According to man in case the invalid pid specified
2409 * EINVAL should be returned.
2410 */
2411 if (pid < 0)
2412 return (EINVAL);
2413
2414 tdt = linux_tdfind(td, pid, -1);
2415 if (tdt == NULL)
2416 return (ESRCH);
2417
2418 error = kern_sched_rr_get_interval_td(td, tdt, ts);
2419 PROC_UNLOCK(tdt->td_proc);
2420 return (error);
2421 }
2422
2423 int
linux_sched_rr_get_interval(struct thread * td,struct linux_sched_rr_get_interval_args * uap)2424 linux_sched_rr_get_interval(struct thread *td,
2425 struct linux_sched_rr_get_interval_args *uap)
2426 {
2427 struct timespec ts;
2428 int error;
2429
2430 error = linux_sched_rr_get_interval_common(td, uap->pid, &ts);
2431 if (error != 0)
2432 return (error);
2433 return (linux_put_timespec(&ts, uap->interval));
2434 }
2435
2436 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
2437 int
linux_sched_rr_get_interval_time64(struct thread * td,struct linux_sched_rr_get_interval_time64_args * uap)2438 linux_sched_rr_get_interval_time64(struct thread *td,
2439 struct linux_sched_rr_get_interval_time64_args *uap)
2440 {
2441 struct timespec ts;
2442 int error;
2443
2444 error = linux_sched_rr_get_interval_common(td, uap->pid, &ts);
2445 if (error != 0)
2446 return (error);
2447 return (linux_put_timespec64(&ts, uap->interval));
2448 }
2449 #endif
2450
2451 /*
2452 * In case when the Linux thread is the initial thread in
2453 * the thread group thread id is equal to the process id.
2454 * Glibc depends on this magic (assert in pthread_getattr_np.c).
2455 */
2456 struct thread *
linux_tdfind(struct thread * td,lwpid_t tid,pid_t pid)2457 linux_tdfind(struct thread *td, lwpid_t tid, pid_t pid)
2458 {
2459 struct linux_emuldata *em;
2460 struct thread *tdt;
2461 struct proc *p;
2462
2463 tdt = NULL;
2464 if (tid == 0 || tid == td->td_tid) {
2465 if (pid != -1 && td->td_proc->p_pid != pid)
2466 return (NULL);
2467 PROC_LOCK(td->td_proc);
2468 return (td);
2469 } else if (tid > PID_MAX)
2470 return (tdfind(tid, pid));
2471
2472 /*
2473 * Initial thread where the tid equal to the pid.
2474 */
2475 p = pfind(tid);
2476 if (p != NULL) {
2477 if (SV_PROC_ABI(p) != SV_ABI_LINUX ||
2478 (pid != -1 && tid != pid)) {
2479 /*
2480 * p is not a Linuxulator process.
2481 */
2482 PROC_UNLOCK(p);
2483 return (NULL);
2484 }
2485 FOREACH_THREAD_IN_PROC(p, tdt) {
2486 em = em_find(tdt);
2487 if (tid == em->em_tid)
2488 return (tdt);
2489 }
2490 PROC_UNLOCK(p);
2491 }
2492 return (NULL);
2493 }
2494
2495 void
linux_to_bsd_waitopts(int options,int * bsdopts)2496 linux_to_bsd_waitopts(int options, int *bsdopts)
2497 {
2498
2499 if (options & LINUX_WNOHANG)
2500 *bsdopts |= WNOHANG;
2501 if (options & LINUX_WUNTRACED)
2502 *bsdopts |= WUNTRACED;
2503 if (options & LINUX_WEXITED)
2504 *bsdopts |= WEXITED;
2505 if (options & LINUX_WCONTINUED)
2506 *bsdopts |= WCONTINUED;
2507 if (options & LINUX_WNOWAIT)
2508 *bsdopts |= WNOWAIT;
2509
2510 if (options & __WCLONE)
2511 *bsdopts |= WLINUXCLONE;
2512 }
2513
2514 int
linux_getrandom(struct thread * td,struct linux_getrandom_args * args)2515 linux_getrandom(struct thread *td, struct linux_getrandom_args *args)
2516 {
2517 struct uio uio;
2518 struct iovec iov;
2519 int error;
2520
2521 if (args->flags & ~(LINUX_GRND_NONBLOCK|LINUX_GRND_RANDOM))
2522 return (EINVAL);
2523 if (args->count > INT_MAX)
2524 args->count = INT_MAX;
2525
2526 iov.iov_base = args->buf;
2527 iov.iov_len = args->count;
2528
2529 uio.uio_iov = &iov;
2530 uio.uio_iovcnt = 1;
2531 uio.uio_resid = iov.iov_len;
2532 uio.uio_segflg = UIO_USERSPACE;
2533 uio.uio_rw = UIO_READ;
2534 uio.uio_td = td;
2535
2536 error = read_random_uio(&uio, args->flags & LINUX_GRND_NONBLOCK);
2537 if (error == 0)
2538 td->td_retval[0] = args->count - uio.uio_resid;
2539 return (error);
2540 }
2541
2542 int
linux_mincore(struct thread * td,struct linux_mincore_args * args)2543 linux_mincore(struct thread *td, struct linux_mincore_args *args)
2544 {
2545
2546 /* Needs to be page-aligned */
2547 if (args->start & PAGE_MASK)
2548 return (EINVAL);
2549 return (kern_mincore(td, args->start, args->len, args->vec));
2550 }
2551
2552 #define SYSLOG_TAG "<6>"
2553
2554 int
linux_syslog(struct thread * td,struct linux_syslog_args * args)2555 linux_syslog(struct thread *td, struct linux_syslog_args *args)
2556 {
2557 char buf[128], *src, *dst;
2558 u_int seq;
2559 int buflen, error;
2560
2561 if (args->type != LINUX_SYSLOG_ACTION_READ_ALL) {
2562 linux_msg(td, "syslog unsupported type 0x%x", args->type);
2563 return (EINVAL);
2564 }
2565
2566 if (args->len < 6) {
2567 td->td_retval[0] = 0;
2568 return (0);
2569 }
2570
2571 error = priv_check(td, PRIV_MSGBUF);
2572 if (error)
2573 return (error);
2574
2575 mtx_lock(&msgbuf_lock);
2576 msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
2577 mtx_unlock(&msgbuf_lock);
2578
2579 dst = args->buf;
2580 error = copyout(&SYSLOG_TAG, dst, sizeof(SYSLOG_TAG));
2581 /* The -1 is to skip the trailing '\0'. */
2582 dst += sizeof(SYSLOG_TAG) - 1;
2583
2584 while (error == 0) {
2585 mtx_lock(&msgbuf_lock);
2586 buflen = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
2587 mtx_unlock(&msgbuf_lock);
2588
2589 if (buflen == 0)
2590 break;
2591
2592 for (src = buf; src < buf + buflen && error == 0; src++) {
2593 if (*src == '\0')
2594 continue;
2595
2596 if (dst >= args->buf + args->len)
2597 goto out;
2598
2599 error = copyout(src, dst, 1);
2600 dst++;
2601
2602 if (*src == '\n' && *(src + 1) != '<' &&
2603 dst + sizeof(SYSLOG_TAG) < args->buf + args->len) {
2604 error = copyout(&SYSLOG_TAG,
2605 dst, sizeof(SYSLOG_TAG));
2606 dst += sizeof(SYSLOG_TAG) - 1;
2607 }
2608 }
2609 }
2610 out:
2611 td->td_retval[0] = dst - args->buf;
2612 return (error);
2613 }
2614
2615 int
linux_getcpu(struct thread * td,struct linux_getcpu_args * args)2616 linux_getcpu(struct thread *td, struct linux_getcpu_args *args)
2617 {
2618 int cpu, error, node;
2619
2620 cpu = td->td_oncpu; /* Make sure it doesn't change during copyout(9) */
2621 error = 0;
2622 node = cpuid_to_pcpu[cpu]->pc_domain;
2623
2624 if (args->cpu != NULL)
2625 error = copyout(&cpu, args->cpu, sizeof(l_int));
2626 if (args->node != NULL)
2627 error = copyout(&node, args->node, sizeof(l_int));
2628 return (error);
2629 }
2630
2631 #if defined(__i386__) || defined(__amd64__)
2632 int
linux_poll(struct thread * td,struct linux_poll_args * args)2633 linux_poll(struct thread *td, struct linux_poll_args *args)
2634 {
2635 struct timespec ts, *tsp;
2636
2637 if (args->timeout != INFTIM) {
2638 if (args->timeout < 0)
2639 return (EINVAL);
2640 ts.tv_sec = args->timeout / 1000;
2641 ts.tv_nsec = (args->timeout % 1000) * 1000000;
2642 tsp = &ts;
2643 } else
2644 tsp = NULL;
2645
2646 return (linux_common_ppoll(td, args->fds, args->nfds,
2647 tsp, NULL, 0));
2648 }
2649 #endif /* __i386__ || __amd64__ */
2650
2651 int
linux_seccomp(struct thread * td,struct linux_seccomp_args * args)2652 linux_seccomp(struct thread *td, struct linux_seccomp_args *args)
2653 {
2654
2655 switch (args->op) {
2656 case LINUX_SECCOMP_GET_ACTION_AVAIL:
2657 return (EOPNOTSUPP);
2658 default:
2659 /*
2660 * Ignore unknown operations, just like Linux kernel built
2661 * without CONFIG_SECCOMP.
2662 */
2663 return (EINVAL);
2664 }
2665 }
2666
2667 /*
2668 * Custom version of exec_copyin_args(), to copy out argument and environment
2669 * strings from the old process address space into the temporary string buffer.
2670 * Based on freebsd32_exec_copyin_args.
2671 */
2672 static int
linux_exec_copyin_args(struct image_args * args,const char * fname,l_uintptr_t * argv,l_uintptr_t * envv)2673 linux_exec_copyin_args(struct image_args *args, const char *fname,
2674 l_uintptr_t *argv, l_uintptr_t *envv)
2675 {
2676 char *argp, *envp;
2677 l_uintptr_t *ptr, arg;
2678 int error;
2679
2680 bzero(args, sizeof(*args));
2681 if (argv == NULL)
2682 return (EFAULT);
2683
2684 /*
2685 * Allocate demand-paged memory for the file name, argument, and
2686 * environment strings.
2687 */
2688 error = exec_alloc_args(args);
2689 if (error != 0)
2690 return (error);
2691
2692 /*
2693 * Copy the file name.
2694 */
2695 error = exec_args_add_fname(args, fname, UIO_USERSPACE);
2696 if (error != 0)
2697 goto err_exit;
2698
2699 /*
2700 * extract arguments first
2701 */
2702 ptr = argv;
2703 for (;;) {
2704 error = copyin(ptr++, &arg, sizeof(arg));
2705 if (error)
2706 goto err_exit;
2707 if (arg == 0)
2708 break;
2709 argp = PTRIN(arg);
2710 error = exec_args_add_arg(args, argp, UIO_USERSPACE);
2711 if (error != 0)
2712 goto err_exit;
2713 }
2714
2715 /*
2716 * This comment is from Linux do_execveat_common:
2717 * When argv is empty, add an empty string ("") as argv[0] to
2718 * ensure confused userspace programs that start processing
2719 * from argv[1] won't end up walking envp.
2720 */
2721 if (args->argc == 0 &&
2722 (error = exec_args_add_arg(args, "", UIO_SYSSPACE) != 0))
2723 goto err_exit;
2724
2725 /*
2726 * extract environment strings
2727 */
2728 if (envv) {
2729 ptr = envv;
2730 for (;;) {
2731 error = copyin(ptr++, &arg, sizeof(arg));
2732 if (error)
2733 goto err_exit;
2734 if (arg == 0)
2735 break;
2736 envp = PTRIN(arg);
2737 error = exec_args_add_env(args, envp, UIO_USERSPACE);
2738 if (error != 0)
2739 goto err_exit;
2740 }
2741 }
2742
2743 return (0);
2744
2745 err_exit:
2746 exec_free_args(args);
2747 return (error);
2748 }
2749
2750 int
linux_execve(struct thread * td,struct linux_execve_args * args)2751 linux_execve(struct thread *td, struct linux_execve_args *args)
2752 {
2753 struct image_args eargs;
2754 int error;
2755
2756 LINUX_CTR(execve);
2757
2758 error = linux_exec_copyin_args(&eargs, args->path, args->argp,
2759 args->envp);
2760 if (error == 0)
2761 error = linux_common_execve(td, &eargs);
2762 AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td);
2763 return (error);
2764 }
2765
2766 static void
linux_up_rtprio_if(struct thread * td1,struct rtprio * rtp)2767 linux_up_rtprio_if(struct thread *td1, struct rtprio *rtp)
2768 {
2769 struct rtprio rtp2;
2770
2771 pri_to_rtp(td1, &rtp2);
2772 if (rtp2.type < rtp->type ||
2773 (rtp2.type == rtp->type &&
2774 rtp2.prio < rtp->prio)) {
2775 rtp->type = rtp2.type;
2776 rtp->prio = rtp2.prio;
2777 }
2778 }
2779
2780 #define LINUX_PRIO_DIVIDER RTP_PRIO_MAX / LINUX_IOPRIO_MAX
2781
2782 static int
linux_rtprio2ioprio(struct rtprio * rtp)2783 linux_rtprio2ioprio(struct rtprio *rtp)
2784 {
2785 int ioprio, prio;
2786
2787 switch (rtp->type) {
2788 case RTP_PRIO_IDLE:
2789 prio = RTP_PRIO_MIN;
2790 ioprio = LINUX_IOPRIO_PRIO(LINUX_IOPRIO_CLASS_IDLE, prio);
2791 break;
2792 case RTP_PRIO_NORMAL:
2793 prio = rtp->prio / LINUX_PRIO_DIVIDER;
2794 ioprio = LINUX_IOPRIO_PRIO(LINUX_IOPRIO_CLASS_BE, prio);
2795 break;
2796 case RTP_PRIO_REALTIME:
2797 prio = rtp->prio / LINUX_PRIO_DIVIDER;
2798 ioprio = LINUX_IOPRIO_PRIO(LINUX_IOPRIO_CLASS_RT, prio);
2799 break;
2800 default:
2801 prio = RTP_PRIO_MIN;
2802 ioprio = LINUX_IOPRIO_PRIO(LINUX_IOPRIO_CLASS_NONE, prio);
2803 break;
2804 }
2805 return (ioprio);
2806 }
2807
2808 static int
linux_ioprio2rtprio(int ioprio,struct rtprio * rtp)2809 linux_ioprio2rtprio(int ioprio, struct rtprio *rtp)
2810 {
2811
2812 switch (LINUX_IOPRIO_PRIO_CLASS(ioprio)) {
2813 case LINUX_IOPRIO_CLASS_IDLE:
2814 rtp->prio = RTP_PRIO_MIN;
2815 rtp->type = RTP_PRIO_IDLE;
2816 break;
2817 case LINUX_IOPRIO_CLASS_BE:
2818 rtp->prio = LINUX_IOPRIO_PRIO_DATA(ioprio) * LINUX_PRIO_DIVIDER;
2819 rtp->type = RTP_PRIO_NORMAL;
2820 break;
2821 case LINUX_IOPRIO_CLASS_RT:
2822 rtp->prio = LINUX_IOPRIO_PRIO_DATA(ioprio) * LINUX_PRIO_DIVIDER;
2823 rtp->type = RTP_PRIO_REALTIME;
2824 break;
2825 default:
2826 return (EINVAL);
2827 }
2828 return (0);
2829 }
2830 #undef LINUX_PRIO_DIVIDER
2831
2832 int
linux_ioprio_get(struct thread * td,struct linux_ioprio_get_args * args)2833 linux_ioprio_get(struct thread *td, struct linux_ioprio_get_args *args)
2834 {
2835 struct thread *td1;
2836 struct rtprio rtp;
2837 struct pgrp *pg;
2838 struct proc *p;
2839 int error, found;
2840
2841 p = NULL;
2842 td1 = NULL;
2843 error = 0;
2844 found = 0;
2845 rtp.type = RTP_PRIO_IDLE;
2846 rtp.prio = RTP_PRIO_MAX;
2847 switch (args->which) {
2848 case LINUX_IOPRIO_WHO_PROCESS:
2849 if (args->who == 0) {
2850 td1 = td;
2851 p = td1->td_proc;
2852 PROC_LOCK(p);
2853 } else if (args->who > PID_MAX) {
2854 td1 = linux_tdfind(td, args->who, -1);
2855 if (td1 != NULL)
2856 p = td1->td_proc;
2857 } else
2858 p = pfind(args->who);
2859 if (p == NULL)
2860 return (ESRCH);
2861 if ((error = p_cansee(td, p))) {
2862 PROC_UNLOCK(p);
2863 break;
2864 }
2865 if (td1 != NULL) {
2866 pri_to_rtp(td1, &rtp);
2867 } else {
2868 FOREACH_THREAD_IN_PROC(p, td1) {
2869 linux_up_rtprio_if(td1, &rtp);
2870 }
2871 }
2872 found++;
2873 PROC_UNLOCK(p);
2874 break;
2875 case LINUX_IOPRIO_WHO_PGRP:
2876 sx_slock(&proctree_lock);
2877 if (args->who == 0) {
2878 pg = td->td_proc->p_pgrp;
2879 PGRP_LOCK(pg);
2880 } else {
2881 pg = pgfind(args->who);
2882 if (pg == NULL) {
2883 sx_sunlock(&proctree_lock);
2884 error = ESRCH;
2885 break;
2886 }
2887 }
2888 sx_sunlock(&proctree_lock);
2889 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
2890 PROC_LOCK(p);
2891 if (p->p_state == PRS_NORMAL &&
2892 p_cansee(td, p) == 0) {
2893 FOREACH_THREAD_IN_PROC(p, td1) {
2894 linux_up_rtprio_if(td1, &rtp);
2895 found++;
2896 }
2897 }
2898 PROC_UNLOCK(p);
2899 }
2900 PGRP_UNLOCK(pg);
2901 break;
2902 case LINUX_IOPRIO_WHO_USER:
2903 if (args->who == 0)
2904 args->who = td->td_ucred->cr_uid;
2905 sx_slock(&allproc_lock);
2906 FOREACH_PROC_IN_SYSTEM(p) {
2907 PROC_LOCK(p);
2908 if (p->p_state == PRS_NORMAL &&
2909 p->p_ucred->cr_uid == args->who &&
2910 p_cansee(td, p) == 0) {
2911 FOREACH_THREAD_IN_PROC(p, td1) {
2912 linux_up_rtprio_if(td1, &rtp);
2913 found++;
2914 }
2915 }
2916 PROC_UNLOCK(p);
2917 }
2918 sx_sunlock(&allproc_lock);
2919 break;
2920 default:
2921 error = EINVAL;
2922 break;
2923 }
2924 if (error == 0) {
2925 if (found != 0)
2926 td->td_retval[0] = linux_rtprio2ioprio(&rtp);
2927 else
2928 error = ESRCH;
2929 }
2930 return (error);
2931 }
2932
2933 int
linux_ioprio_set(struct thread * td,struct linux_ioprio_set_args * args)2934 linux_ioprio_set(struct thread *td, struct linux_ioprio_set_args *args)
2935 {
2936 struct thread *td1;
2937 struct rtprio rtp;
2938 struct pgrp *pg;
2939 struct proc *p;
2940 int error;
2941
2942 if ((error = linux_ioprio2rtprio(args->ioprio, &rtp)) != 0)
2943 return (error);
2944 /* Attempts to set high priorities (REALTIME) require su privileges. */
2945 if (RTP_PRIO_BASE(rtp.type) == RTP_PRIO_REALTIME &&
2946 (error = priv_check(td, PRIV_SCHED_RTPRIO)) != 0)
2947 return (error);
2948
2949 p = NULL;
2950 td1 = NULL;
2951 switch (args->which) {
2952 case LINUX_IOPRIO_WHO_PROCESS:
2953 if (args->who == 0) {
2954 td1 = td;
2955 p = td1->td_proc;
2956 PROC_LOCK(p);
2957 } else if (args->who > PID_MAX) {
2958 td1 = linux_tdfind(td, args->who, -1);
2959 if (td1 != NULL)
2960 p = td1->td_proc;
2961 } else
2962 p = pfind(args->who);
2963 if (p == NULL)
2964 return (ESRCH);
2965 if ((error = p_cansched(td, p))) {
2966 PROC_UNLOCK(p);
2967 break;
2968 }
2969 if (td1 != NULL) {
2970 error = rtp_to_pri(&rtp, td1);
2971 } else {
2972 FOREACH_THREAD_IN_PROC(p, td1) {
2973 if ((error = rtp_to_pri(&rtp, td1)) != 0)
2974 break;
2975 }
2976 }
2977 PROC_UNLOCK(p);
2978 break;
2979 case LINUX_IOPRIO_WHO_PGRP:
2980 sx_slock(&proctree_lock);
2981 if (args->who == 0) {
2982 pg = td->td_proc->p_pgrp;
2983 PGRP_LOCK(pg);
2984 } else {
2985 pg = pgfind(args->who);
2986 if (pg == NULL) {
2987 sx_sunlock(&proctree_lock);
2988 error = ESRCH;
2989 break;
2990 }
2991 }
2992 sx_sunlock(&proctree_lock);
2993 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
2994 PROC_LOCK(p);
2995 if (p->p_state == PRS_NORMAL &&
2996 p_cansched(td, p) == 0) {
2997 FOREACH_THREAD_IN_PROC(p, td1) {
2998 if ((error = rtp_to_pri(&rtp, td1)) != 0)
2999 break;
3000 }
3001 }
3002 PROC_UNLOCK(p);
3003 if (error != 0)
3004 break;
3005 }
3006 PGRP_UNLOCK(pg);
3007 break;
3008 case LINUX_IOPRIO_WHO_USER:
3009 if (args->who == 0)
3010 args->who = td->td_ucred->cr_uid;
3011 sx_slock(&allproc_lock);
3012 FOREACH_PROC_IN_SYSTEM(p) {
3013 PROC_LOCK(p);
3014 if (p->p_state == PRS_NORMAL &&
3015 p->p_ucred->cr_uid == args->who &&
3016 p_cansched(td, p) == 0) {
3017 FOREACH_THREAD_IN_PROC(p, td1) {
3018 if ((error = rtp_to_pri(&rtp, td1)) != 0)
3019 break;
3020 }
3021 }
3022 PROC_UNLOCK(p);
3023 if (error != 0)
3024 break;
3025 }
3026 sx_sunlock(&allproc_lock);
3027 break;
3028 default:
3029 error = EINVAL;
3030 break;
3031 }
3032 return (error);
3033 }
3034
3035 /* The only flag is O_NONBLOCK */
3036 #define B2L_MQ_FLAGS(bflags) ((bflags) != 0 ? LINUX_O_NONBLOCK : 0)
3037 #define L2B_MQ_FLAGS(lflags) ((lflags) != 0 ? O_NONBLOCK : 0)
3038
3039 int
linux_mq_open(struct thread * td,struct linux_mq_open_args * args)3040 linux_mq_open(struct thread *td, struct linux_mq_open_args *args)
3041 {
3042 struct mq_attr attr;
3043 int error, flags;
3044
3045 flags = linux_common_openflags(args->oflag);
3046 if ((flags & O_ACCMODE) == O_ACCMODE || (flags & O_EXEC) != 0)
3047 return (EINVAL);
3048 flags = FFLAGS(flags);
3049 if ((flags & O_CREAT) != 0 && args->attr != NULL) {
3050 error = copyin(args->attr, &attr, sizeof(attr));
3051 if (error != 0)
3052 return (error);
3053 attr.mq_flags = L2B_MQ_FLAGS(attr.mq_flags);
3054 }
3055
3056 return (kern_kmq_open(td, args->name, flags, args->mode,
3057 args->attr != NULL ? &attr : NULL));
3058 }
3059
3060 int
linux_mq_unlink(struct thread * td,struct linux_mq_unlink_args * args)3061 linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args)
3062 {
3063 struct kmq_unlink_args bsd_args = {
3064 .path = PTRIN(args->name)
3065 };
3066
3067 return (sys_kmq_unlink(td, &bsd_args));
3068 }
3069
3070 int
linux_mq_timedsend(struct thread * td,struct linux_mq_timedsend_args * args)3071 linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args)
3072 {
3073 struct timespec ts, *abs_timeout;
3074 int error;
3075
3076 if (args->abs_timeout == NULL)
3077 abs_timeout = NULL;
3078 else {
3079 error = linux_get_timespec(&ts, args->abs_timeout);
3080 if (error != 0)
3081 return (error);
3082 abs_timeout = &ts;
3083 }
3084
3085 return (kern_kmq_timedsend(td, args->mqd, PTRIN(args->msg_ptr),
3086 args->msg_len, args->msg_prio, abs_timeout));
3087 }
3088
3089 int
linux_mq_timedreceive(struct thread * td,struct linux_mq_timedreceive_args * args)3090 linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args)
3091 {
3092 struct timespec ts, *abs_timeout;
3093 int error;
3094
3095 if (args->abs_timeout == NULL)
3096 abs_timeout = NULL;
3097 else {
3098 error = linux_get_timespec(&ts, args->abs_timeout);
3099 if (error != 0)
3100 return (error);
3101 abs_timeout = &ts;
3102 }
3103
3104 return (kern_kmq_timedreceive(td, args->mqd, PTRIN(args->msg_ptr),
3105 args->msg_len, args->msg_prio, abs_timeout));
3106 }
3107
3108 int
linux_mq_notify(struct thread * td,struct linux_mq_notify_args * args)3109 linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args)
3110 {
3111 struct sigevent ev, *evp;
3112 struct l_sigevent l_ev;
3113 int error;
3114
3115 if (args->sevp == NULL)
3116 evp = NULL;
3117 else {
3118 error = copyin(args->sevp, &l_ev, sizeof(l_ev));
3119 if (error != 0)
3120 return (error);
3121 error = linux_convert_l_sigevent(&l_ev, &ev);
3122 if (error != 0)
3123 return (error);
3124 evp = &ev;
3125 }
3126
3127 return (kern_kmq_notify(td, args->mqd, evp));
3128 }
3129
3130 int
linux_mq_getsetattr(struct thread * td,struct linux_mq_getsetattr_args * args)3131 linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args)
3132 {
3133 struct mq_attr attr, oattr;
3134 int error;
3135
3136 if (args->attr != NULL) {
3137 error = copyin(args->attr, &attr, sizeof(attr));
3138 if (error != 0)
3139 return (error);
3140 attr.mq_flags = L2B_MQ_FLAGS(attr.mq_flags);
3141 }
3142
3143 error = kern_kmq_setattr(td, args->mqd, args->attr != NULL ? &attr : NULL,
3144 &oattr);
3145 if (error == 0 && args->oattr != NULL) {
3146 oattr.mq_flags = B2L_MQ_FLAGS(oattr.mq_flags);
3147 bzero(oattr.__reserved, sizeof(oattr.__reserved));
3148 error = copyout(&oattr, args->oattr, sizeof(oattr));
3149 }
3150
3151 return (error);
3152 }
3153
3154 int
linux_kcmp(struct thread * td,struct linux_kcmp_args * args)3155 linux_kcmp(struct thread *td, struct linux_kcmp_args *args)
3156 {
3157 int type;
3158
3159 switch (args->type) {
3160 case LINUX_KCMP_FILE:
3161 type = KCMP_FILE;
3162 break;
3163 case LINUX_KCMP_FILES:
3164 type = KCMP_FILES;
3165 break;
3166 case LINUX_KCMP_SIGHAND:
3167 type = KCMP_SIGHAND;
3168 break;
3169 case LINUX_KCMP_VM:
3170 type = KCMP_VM;
3171 break;
3172 default:
3173 return (EINVAL);
3174 }
3175
3176 return (kern_kcmp(td, args->pid1, args->pid2, type, args->idx1,
3177 args->idx));
3178 }
3179
3180 int
linux_membarrier(struct thread * td,struct linux_membarrier_args * args)3181 linux_membarrier(struct thread *td, struct linux_membarrier_args *args)
3182 {
3183 static const struct {
3184 int linux_cmd;
3185 int freebsd_cmd;
3186 } cmds[] = {
3187 { LINUX_MEMBARRIER_CMD_QUERY,
3188 MEMBARRIER_CMD_QUERY },
3189 { LINUX_MEMBARRIER_CMD_GLOBAL,
3190 MEMBARRIER_CMD_GLOBAL },
3191 { LINUX_MEMBARRIER_CMD_GLOBAL_EXPEDITED,
3192 MEMBARRIER_CMD_GLOBAL_EXPEDITED },
3193 { LINUX_MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
3194 MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED },
3195 { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED,
3196 MEMBARRIER_CMD_PRIVATE_EXPEDITED },
3197 { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
3198 MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED },
3199 { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE,
3200 MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE },
3201 { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
3202 MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE },
3203 { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ,
3204 MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ },
3205 { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ,
3206 MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ },
3207 { LINUX_MEMBARRIER_CMD_GET_REGISTRATIONS,
3208 MEMBARRIER_CMD_GET_REGISTRATIONS },
3209 };
3210 int cmd, error, flags, i, mask;
3211
3212 cmd = -1;
3213 for (i = 0; i < nitems(cmds); i++) {
3214 if (args->cmd == cmds[i].linux_cmd) {
3215 cmd = cmds[i].freebsd_cmd;
3216 break;
3217 }
3218 }
3219
3220 if (cmd == -1 || (args->flags & ~LINUX_MEMBARRIER_CMD_FLAG_CPU) != 0)
3221 return (EINVAL);
3222
3223 flags = 0;
3224 if ((args->flags & LINUX_MEMBARRIER_CMD_FLAG_CPU) != 0)
3225 flags |= MEMBARRIER_CMD_FLAG_CPU;
3226
3227 error = kern_membarrier(td, cmd, flags, args->cpu_id);
3228 if (error != 0)
3229 return (error);
3230
3231 if (args->cmd == LINUX_MEMBARRIER_CMD_QUERY ||
3232 args->cmd == LINUX_MEMBARRIER_CMD_GET_REGISTRATIONS) {
3233 mask = td->td_retval[0];
3234 td->td_retval[0] = 0;
3235 for (i = 0; i < nitems(cmds); i++)
3236 if ((mask & cmds[i].freebsd_cmd) != 0)
3237 td->td_retval[0] |= cmds[i].linux_cmd;
3238 }
3239
3240 return (0);
3241 }
3242
3243 /*
3244 * setfsuid() & setfsgid() exist to decouple the Linux filesystem credentials
3245 * from the effective credentials, avoiding signal exposure during privilege
3246 * transitions. The signal permission model that motivated this was revised in
3247 * Linux 2.0, making these syscalls obsolete for new applications.
3248 *
3249 * As there's no FreeBSD equivalent, implement both syscalls as no-ops that
3250 * return the current effective UID/GID as the previous filesystem UID/GID.
3251 * Linux returns the previous filesystem UID/GID for these syscalls, with no
3252 * error indication.
3253 */
3254
3255 int
linux_setfsuid(struct thread * td,struct linux_setfsuid_args * args)3256 linux_setfsuid(struct thread *td, struct linux_setfsuid_args *args)
3257 {
3258 td->td_retval[0] = td->td_ucred->cr_uid;
3259 return (0);
3260 }
3261
3262 int
linux_setfsgid(struct thread * td,struct linux_setfsgid_args * args)3263 linux_setfsgid(struct thread *td, struct linux_setfsgid_args *args)
3264 {
3265 td->td_retval[0] = td->td_ucred->cr_gid;
3266 return (0);
3267 }
3268
3269 MODULE_DEPEND(linux, mqueuefs, 1, 1, 1);
3270