Bug Summary

File:compat/linux/linux_misc.c
Warning:line 1098, column 11
Copies out a struct with a union element with different sizes

Annotated Source Code

Press '?' to see keyboard shortcuts

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