blob: 22a75014bc5bd2202b4a2a58e88d3597e4a619bf [file] [log] [blame]
sewardj8eb8bab2015-07-21 14:44:28 +00001
2/*--------------------------------------------------------------------*/
3/*--- Solaris-specific syscalls, etc. syswrap-solaris.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2011-2017 Petr Pavlu
sewardj8eb8bab2015-07-21 14:44:28 +000011 setup@dagobah.cz
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
Elliott Hughesed398002017-06-21 14:41:24 -070031/* Copyright 2013-2017, Ivo Raisr <ivosh@ivosh.net>. */
sewardj8eb8bab2015-07-21 14:44:28 +000032
Elliott Hughesed398002017-06-21 14:41:24 -070033/* Copyright 2015-2017, Tomas Jedlicka <jedlickat@gmail.com>. */
iraisre0365402015-09-25 20:12:26 +000034
sewardj8eb8bab2015-07-21 14:44:28 +000035/* Copyright 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
36
37#if defined(VGO_solaris)
38
39#include "libvex_guest_offsets.h"
40#include "pub_core_basics.h"
41#include "pub_core_vki.h"
42#include "pub_core_vkiscnums.h"
43#include "pub_core_threadstate.h"
44#include "pub_core_aspacemgr.h"
45#include "pub_core_debuginfo.h" // VG_(di_notify_*)
46#include "pub_core_debuglog.h"
47#include "pub_core_clientstate.h"
48#include "pub_core_gdbserver.h"
49#include "pub_core_inner.h"
50#include "pub_core_libcassert.h"
51#include "pub_core_libcbase.h"
52#include "pub_core_libcfile.h"
53#include "pub_core_libcprint.h"
54#include "pub_core_libcproc.h"
55#include "pub_core_libcsignal.h"
56#include "pub_core_machine.h" // VG_(get_SP)
57#include "pub_core_mallocfree.h"
58#include "pub_core_options.h"
59#include "pub_core_tooliface.h"
60#include "pub_core_transtab.h" // VG_(discard_translations)
61#include "pub_core_scheduler.h"
62#include "pub_core_sigframe.h"
63#include "pub_core_signals.h"
64#include "pub_core_stacks.h"
65#include "pub_core_syscall.h"
66#include "pub_core_syswrap.h"
67#include "pub_core_ume.h"
68#if defined(ENABLE_INNER_CLIENT_REQUEST)
69#include "pub_core_clreq.h"
70#endif
71
72#include "priv_types_n_macros.h"
73#include "priv_syswrap-generic.h"
Elliott Hughesa0664b92017-04-18 17:46:52 -070074#include "priv_syswrap-main.h"
sewardj8eb8bab2015-07-21 14:44:28 +000075#include "priv_syswrap-solaris.h"
76
77/* Return the number of non-dead and daemon threads.
78 count_daemon == True: count daemon threads
79 count_daemon == False: count non-daemon threads */
80static UInt count_living_daemon_threads(Bool count_daemon)
81{
82 UInt count = 0;
83 for (ThreadId tid = 1; tid < VG_N_THREADS; tid++)
84 if (VG_(threads)[tid].status != VgTs_Empty &&
85 VG_(threads)[tid].status != VgTs_Zombie &&
86 VG_(threads)[tid].os_state.daemon_thread == count_daemon)
87 count++;
88
89 return count;
90}
91
92/* Note: The following functions (thread_wrapper, run_a_thread_NORETURN,
93 ML_(start_thread_NORETURN), ML_(allocstack) and
94 VG_(main_thread_wrapper_NORETURN)) are based on the code in
95 syswrap-linux.c. Keep them synchronized! */
96
97/* Run a thread from beginning to end and return the thread's
98 scheduler-return-code. */
99static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
100{
101 VgSchedReturnCode ret;
102 ThreadId tid = (ThreadId)tidW;
103 ThreadState *tst = VG_(get_ThreadState)(tid);
104
105 VG_(debugLog)(1, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000106 "thread_wrapper(tid=%u): entry\n",
107 tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000108
109 vg_assert(tst->status == VgTs_Init);
110
111 /* Make sure we get the CPU lock before doing anything significant. */
112 VG_(acquire_BigLock)(tid, "thread_wrapper(starting new thread)");
113
114 if (0)
florianb26101c2015-08-08 21:45:33 +0000115 VG_(printf)("thread tid %u started: stack = %p\n", tid, (void *)&tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000116
117 /* Make sure error reporting is enabled in the new thread. */
118 tst->err_disablement_level = 0;
119
120 if (tid == 1)
121 VG_TRACK(pre_thread_first_insn, tid);
122 else {
123 /* For newly created threads, VG_TRACK(pre_thread_first_insn, tid) is
124 invoked later from PRE(sys_getsetcontext)() when setucontext()
125 called from _thrp_setup() concludes new thread setup. Invoking it
126 here would be way too early - new thread has no stack, yet. */
127 }
128
129 tst->os_state.lwpid = VG_(gettid)();
130 tst->os_state.threadgroup = VG_(getpid)();
131
132 /* Thread created with all signals blocked; scheduler will set the
133 appropriate mask. */
134
135 ret = VG_(scheduler)(tid);
136
137 vg_assert(VG_(is_exiting)(tid));
138
139 vg_assert(tst->status == VgTs_Runnable);
140 vg_assert(VG_(is_running_thread)(tid));
141
142 VG_(debugLog)(1, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000143 "thread_wrapper(tid=%u): exit, schedreturncode %s\n",
144 tid, VG_(name_of_VgSchedReturnCode)(ret));
sewardj8eb8bab2015-07-21 14:44:28 +0000145
146 /* Return to caller, still holding the lock. */
147 return ret;
148}
149
150/* Run a thread all the way to the end, then do appropriate exit actions
151 (this is the last-one-out-turn-off-the-lights bit). */
152static void run_a_thread_NORETURN(Word tidW)
153{
154 ThreadId tid = (ThreadId)tidW;
155 VgSchedReturnCode src;
156 Int c;
157 ThreadState *tst;
158#ifdef ENABLE_INNER_CLIENT_REQUEST
159 Int registered_vgstack_id;
160#endif
161
162 VG_(debugLog)(1, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000163 "run_a_thread_NORETURN(tid=%u): pre-thread_wrapper\n",
164 tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000165
166 tst = VG_(get_ThreadState)(tid);
167 vg_assert(tst);
168
169 /* A thread has two stacks:
170 * the simulated stack (used by the synthetic cpu. Guest process
171 is using this stack).
172 * the valgrind stack (used by the real cpu. Valgrind code is running
173 on this stack).
174 When Valgrind runs as an inner, it must signal that its (real) stack
175 is the stack to use by the outer to e.g. do stacktraces.
176 */
177 INNER_REQUEST
178 (registered_vgstack_id
179 = VALGRIND_STACK_REGISTER(tst->os_state.valgrind_stack_base,
180 tst->os_state.valgrind_stack_init_SP));
181
182 /* Run the thread all the way through. */
183 src = thread_wrapper(tid);
184
185 VG_(debugLog)(1, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000186 "run_a_thread_NORETURN(tid=%u): post-thread_wrapper\n",
187 tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000188
189 c = count_living_daemon_threads(False);
190 vg_assert(c >= 1); /* Stay sane. */
191
192 /* Tell the tool that schedctl data belonging to this thread are gone. */
193 Addr a = tst->os_state.schedctl_data;
194 if (a != 0)
195 VG_TRACK(die_mem_munmap, a, sizeof(struct vki_sc_shared));
196
197 /* Deregister thread's stack. */
Elliott Hughesed398002017-06-21 14:41:24 -0700198 if (tst->os_state.stk_id != NULL_STK_ID)
sewardj8eb8bab2015-07-21 14:44:28 +0000199 VG_(deregister_stack)(tst->os_state.stk_id);
200
201 /* Tell the tool this thread is exiting. */
202 VG_TRACK(pre_thread_ll_exit, tid);
203
204 /* If the thread is exiting with errors disabled, complain loudly;
205 doing so is bad (does the user know this has happened?) Also, in all
206 cases, be paranoid and clear the flag anyway so that the thread slot is
207 safe in this respect if later reallocated. This should be unnecessary
208 since the flag should be cleared when the slot is reallocated, in
209 thread_wrapper(). */
210 if (tst->err_disablement_level > 0) {
211 VG_(umsg)(
212 "WARNING: exiting thread has error reporting disabled.\n"
213 "WARNING: possibly as a result of some mistake in the use\n"
214 "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
215 );
216 VG_(debugLog)(
217 1, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000218 "run_a_thread_NORETURN(tid=%u): "
sewardj8eb8bab2015-07-21 14:44:28 +0000219 "WARNING: exiting thread has err_disablement_level = %u\n",
florianb26101c2015-08-08 21:45:33 +0000220 tid, tst->err_disablement_level
sewardj8eb8bab2015-07-21 14:44:28 +0000221 );
222 }
223 tst->err_disablement_level = 0;
224
225 if (c == 1) {
226 UInt daemon_threads = count_living_daemon_threads(True);
227 if (daemon_threads == 0)
228 VG_(debugLog)(1, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000229 "run_a_thread_NORETURN(tid=%u): "
sewardj8eb8bab2015-07-21 14:44:28 +0000230 "last one standing\n",
florianb26101c2015-08-08 21:45:33 +0000231 tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000232 else
233 VG_(debugLog)(1, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000234 "run_a_thread_NORETURN(tid=%u): "
sewardj8eb8bab2015-07-21 14:44:28 +0000235 "last non-daemon thread standing "
236 "[daemon threads=%u]\n",
florianb26101c2015-08-08 21:45:33 +0000237 tid, daemon_threads);
sewardj8eb8bab2015-07-21 14:44:28 +0000238
239 /* We are the last non-daemon thread standing. Keep hold of the lock and
240 carry on to show final tool results, then exit the entire system.
241 Use the continuation pointer set at startup in m_main. */
242 if ((src == VgSrc_ExitThread) && (daemon_threads > 0))
243 src = VgSrc_ExitProcess;
244 (*VG_(address_of_m_main_shutdown_actions_NORETURN))(tid, src);
245 }
246 else {
247 VG_(debugLog)(1, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000248 "run_a_thread_NORETURN(tid=%u): "
sewardj8eb8bab2015-07-21 14:44:28 +0000249 "not last one standing\n",
florianb26101c2015-08-08 21:45:33 +0000250 tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000251
252 /* OK, thread is dead, but others still exist. Just exit. */
253
254 /* This releases the run lock. */
255 VG_(exit_thread)(tid);
256 vg_assert(tst->status == VgTs_Zombie);
257 vg_assert(sizeof(tst->status) == 4);
258
259 INNER_REQUEST(VALGRIND_STACK_DEREGISTER(registered_vgstack_id));
260
261 /* We have to use this sequence to terminate the thread to
262 prevent a subtle race. If VG_(exit_thread)() had left the
263 ThreadState as Empty, then it could have been reallocated, reusing
264 the stack while we're doing these last cleanups. Instead,
265 VG_(exit_thread) leaves it as Zombie to prevent reallocation. We
266 need to make sure we don't touch the stack between marking it Empty
267 and exiting. Hence the assembler. */
268#if defined(VGP_x86_solaris)
269 /* Luckily lwp_exit doesn't take any arguments so we don't have to mess
270 with the stack. */
271 __asm__ __volatile__ (
272 "movl %[EMPTY], %[status]\n" /* set tst->status = VgTs_Empty */
273 "movl $"VG_STRINGIFY(__NR_lwp_exit)", %%eax\n"
274 "int $0x91\n" /* lwp_exit() */
275 : [status] "=m" (tst->status)
276 : [EMPTY] "n" (VgTs_Empty)
277 : "eax", "edx", "cc", "memory");
278#elif defined(VGP_amd64_solaris)
279 __asm__ __volatile__ (
280 "movl %[EMPTY], %[status]\n" /* set tst->status = VgTs_Empty */
281 "movq $"VG_STRINGIFY(__NR_lwp_exit)", %%rax\n"
282 "syscall\n" /* lwp_exit() */
283 : [status] "=m" (tst->status)
284 : [EMPTY] "n" (VgTs_Empty)
285 : "rax", "rdx", "cc", "memory");
286#else
287# error "Unknown platform"
288#endif
289
290 VG_(core_panic)("Thread exit failed?\n");
291 }
292
293 /*NOTREACHED*/
294 vg_assert(0);
295}
296
297Word ML_(start_thread_NORETURN)(void *arg)
298{
299 ThreadState *tst = (ThreadState*)arg;
300 ThreadId tid = tst->tid;
301
302 run_a_thread_NORETURN((Word)tid);
303 /*NOTREACHED*/
304 vg_assert(0);
305}
306
307/* Allocate a stack for this thread, if it doesn't already have one.
308 They're allocated lazily, and never freed. Returns the initial stack
309 pointer value to use, or 0 if allocation failed. */
310Addr ML_(allocstack)(ThreadId tid)
311{
312 ThreadState *tst = VG_(get_ThreadState)(tid);
313 VgStack *stack;
314 Addr initial_SP;
315
316 /* Either the stack_base and stack_init_SP are both zero (in which
317 case a stack hasn't been allocated) or they are both non-zero,
318 in which case it has. */
319
320 if (tst->os_state.valgrind_stack_base == 0)
321 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
322
323 if (tst->os_state.valgrind_stack_base != 0)
324 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
325
326 /* If no stack is present, allocate one. */
327
328 if (tst->os_state.valgrind_stack_base == 0) {
329 stack = VG_(am_alloc_VgStack)( &initial_SP );
330 if (stack) {
331 tst->os_state.valgrind_stack_base = (Addr)stack;
332 tst->os_state.valgrind_stack_init_SP = initial_SP;
333 }
334 }
335
336 if (0)
florianb26101c2015-08-08 21:45:33 +0000337 VG_(printf)("stack for tid %u at %p; init_SP=%p\n",
sewardj8eb8bab2015-07-21 14:44:28 +0000338 tid,
339 (void*)tst->os_state.valgrind_stack_base,
340 (void*)tst->os_state.valgrind_stack_init_SP);
341
342 return tst->os_state.valgrind_stack_init_SP;
343}
344
345/* Allocate a stack for the main thread, and run it all the way to the
346 end. Although we already have a working VgStack (VG_(interim_stack)) it's
347 better to allocate a new one, so that overflow detection works uniformly
348 for all threads. Also initialize the GDT (for normal threads, this is done
349 in the PRE wrapper of lwp_create). */
350void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
351{
352 Addr sp;
353
354 VG_(debugLog)(1, "syswrap-solaris",
355 "entering VG_(main_thread_wrapper_NORETURN)\n");
356
357 sp = ML_(allocstack)(tid);
358#if defined(ENABLE_INNER_CLIENT_REQUEST)
359 {
360 // we must register the main thread stack before the call
361 // to ML_(call_on_new_stack_0_1), otherwise the outer valgrind
362 // reports 'write error' on the non registered stack.
363 ThreadState *tst = VG_(get_ThreadState)(tid);
364 INNER_REQUEST
365 ((void)
366 VALGRIND_STACK_REGISTER(tst->os_state.valgrind_stack_base,
367 tst->os_state.valgrind_stack_init_SP));
368 }
369#endif
370
371#if defined(VGP_x86_solaris)
372 {
373 ThreadState *tst = VG_(get_ThreadState)(tid);
374 ML_(setup_gdt)(&tst->arch.vex);
375 ML_(update_gdt_lwpgs)(tid);
376 }
377#elif defined(VGP_amd64_solaris)
378 /* Nothing to do. */
379#else
380# error "Unknown platform"
381#endif
382
383 /* If we can't even allocate the first thread's stack, we're hosed.
384 Give up. */
385 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
386
387 /* Shouldn't be any other threads around yet. */
388 vg_assert(VG_(count_living_threads)() == 1);
389
390 ML_(call_on_new_stack_0_1)(
391 (Addr)sp, /* stack */
392 0, /* bogus return address */
393 run_a_thread_NORETURN, /* fn to call */
394 (Word)tid /* arg to give it */
395 );
396
397 /*NOTREACHED*/
398 vg_assert(0);
399}
400
401/* Deallocate the GDT for a thread. */
402void VG_(cleanup_thread)(ThreadArchState *arch)
403{
404#if defined(VGP_x86_solaris)
405 ML_(cleanup_gdt)(&arch->vex);
406#elif defined(VGP_amd64_solaris)
407 /* Nothing to do. */
408#else
409# error "Unknown platform"
410#endif
411}
412
413/*
414 * Notify core about spring cleaning of schedctl data pages for all threads
415 * in child post-fork handler. Libc will issue new schedctl syscalls for threads
416 * in the child when needs arise.
417 *
418 * See also POST(schedctl) and run_a_thread_NORETURN() when a thread exits.
419 */
420static void clean_schedctl_data(ThreadId tid)
421{
422 UInt i;
423 for (i = 0; i < VG_N_THREADS; i++) {
424 ThreadState *tst = &VG_(threads)[i];
425 if (tst->status != VgTs_Empty) {
426 Addr a = tst->os_state.schedctl_data;
427 if (a != 0) {
428 tst->os_state.schedctl_data = 0;
429 a = VG_PGROUNDDN(a);
Elliott Hughesa0664b92017-04-18 17:46:52 -0700430 if (VG_(am_find_anon_segment)(a))
sewardj8eb8bab2015-07-21 14:44:28 +0000431 VG_(am_notify_munmap)(a, VKI_PAGE_SIZE);
432 }
433 }
434 }
435}
436
437void VG_(syswrap_init)(void)
438{
439 VG_(atfork)(NULL, NULL, clean_schedctl_data);
440}
441
iraisre0365402015-09-25 20:12:26 +0000442/* Changes ownership of a memory mapping shared between kernel and the client
443 process. This mapping should have already been pre-arranged during process
444 address space initialization happening in kernel. Valgrind on startup created
445 a segment for this mapping categorized as Valgrind's owned anonymous.
446 Size of this mapping typically varies among Solaris versions but should be
447 page aligned.
448 If 'once_only' is 'True', it is expected this function is called once only
449 and the mapping ownership has not been changed, yet [useful during
450 initialization]. If 'False', this function can be called many times but does
451 change ownership only upon the first invocation [useful in syscall wrappers].
452 */
453void VG_(change_mapping_ownership)(Addr addr, Bool once_only)
454{
455 const NSegment *seg = VG_(am_find_anon_segment)(addr);
456 vg_assert(seg != NULL);
457 vg_assert(seg->start == addr);
458 vg_assert(VG_IS_PAGE_ALIGNED(seg->start));
459 vg_assert(VG_IS_PAGE_ALIGNED(seg->end + 1));
460 SizeT size = seg->end - seg->start + 1;
461 vg_assert(size > 0);
462
463 Bool do_change = False;
464 if (once_only) {
465 vg_assert(VG_(am_is_valid_for_valgrind)(addr, size, VKI_PROT_READ));
466 do_change = True;
467 } else {
468 if (!VG_(am_is_valid_for_client)(addr, size, VKI_PROT_READ))
469 do_change = True;
470 }
471
472 if (do_change) {
473 Bool change_ownership_OK = VG_(am_change_ownership_v_to_c)(addr, size);
474 vg_assert(change_ownership_OK);
475
476 /* Tell the tool about just discovered mapping. */
477 VG_TRACK(new_mem_startup,
478 addr, size,
479 True /* readable? */,
480 False /* writable? */,
481 False /* executable? */,
482 0 /* di_handle */);
483 }
484}
485
sewardj8eb8bab2015-07-21 14:44:28 +0000486/* Calculate the Fletcher-32 checksum of a given buffer. */
487UInt ML_(fletcher32)(UShort *buf, SizeT blocks)
488{
489 UInt sum1 = 0;
490 UInt sum2 = 0;
491 SizeT i;
492
493 for (i = 0; i < blocks; i++) {
494 sum1 = (sum1 + buf[i]) % 0xffff;
495 sum2 = (sum2 + sum1) % 0xffff;
496 }
497
498 return (sum2 << 16) | sum1;
499}
500
501/* Calculate the Fletcher-64 checksum of a given buffer. */
502ULong ML_(fletcher64)(UInt *buf, SizeT blocks)
503{
504 ULong sum1 = 0;
505 ULong sum2 = 0;
506 SizeT i;
507
508 for (i = 0; i < blocks; i++) {
509 sum1 = (sum1 + buf[i]) % 0xffffffff;
510 sum2 = (sum2 + sum1) % 0xffffffff;
511 }
512 return (sum2 << 32) | sum1;
513}
514
515/* Save a complete context (VCPU state, sigmask) of a given client thread
516 into the vki_ucontext_t structure. This structure is supposed to be
517 allocated in the client memory, a caller must make sure that the memory can
518 be dereferenced. The active tool is informed about the save. */
519void VG_(save_context)(ThreadId tid, vki_ucontext_t *uc, CorePart part)
520{
521 ThreadState *tst = VG_(get_ThreadState)(tid);
522
523 VG_TRACK(pre_mem_write, part, tid, "save_context(uc)", (Addr)uc,
524 sizeof(*uc));
525
526 uc->uc_flags = VKI_UC_ALL;
527 VG_TRACK(post_mem_write, part, tid, (Addr)&uc->uc_flags,
528 sizeof(uc->uc_flags));
529
530 /* Old context */
531 uc->uc_link = tst->os_state.oldcontext;
532 VG_TRACK(post_mem_write, part, tid, (Addr)&uc->uc_link,
533 sizeof(uc->uc_link));
534
535 /* Clear uc->vki_uc_signo. This slot is used by the signal machinery to
536 store a signal number. */
537 VKI_UC_SIGNO(uc) = 0;
538
539 /* Sigmask */
540 uc->uc_sigmask = tst->sig_mask;
541 VG_TRACK(post_mem_write, part, tid, (Addr)&uc->uc_sigmask,
542 sizeof(uc->uc_sigmask));
543
544 /* Stack */
545 {
546 if (tst->os_state.ustack
547 && ML_(safe_to_deref)(tst->os_state.ustack, sizeof(vki_stack_t))
548 && tst->os_state.ustack->ss_size) {
549 /* If ustack points to a valid stack copy it to ucontext. */
550 uc->uc_stack = *tst->os_state.ustack;
551 }
552 else {
553 /* Ustack is not valid. A correct stack has to be figured out
554 manually. */
555 SysRes res;
556 vki_stack_t altstack;
557
558 /* Get information about alternate stack. */
559 res = VG_(do_sys_sigaltstack)(tid, NULL, &altstack);
560 vg_assert(!sr_isError(res));
561
562 if (altstack.ss_flags == VKI_SS_ONSTACK) {
563 /* If the alternate stack is active copy it to ucontext. */
564 uc->uc_stack = altstack;
565 }
566 else {
567 /* No information about stack is present, save information about
568 current main stack to ucontext. This branch should be reached
569 only by the main thread. */
570 ThreadState *tst2 = VG_(get_ThreadState)(1);
571 uc->uc_stack.ss_sp = (void*)(tst2->client_stack_highest_byte + 1
572 - tst2->client_stack_szB);
573 uc->uc_stack.ss_size = tst2->client_stack_szB;
574 uc->uc_stack.ss_flags = 0;
575 }
576 }
577
578 VG_TRACK(post_mem_write, part, tid, (Addr)&uc->uc_stack,
579 sizeof(uc->uc_stack));
580 }
581
582 /* Save the architecture-specific part of the context. */
583 ML_(save_machine_context)(tid, uc, part);
584}
585
586/* Set a complete context (VCPU state, sigmask) of a given client thread
587 according to values passed in the vki_ucontext_t structure. This structure
588 is supposed to be allocated in the client memory, a caller must make sure
589 that the memory can be dereferenced. The active tool is informed about
590 what parts of the structure are read.
591
592 This function is a counterpart to VG_(save_context)(). */
593void VG_(restore_context)(ThreadId tid, vki_ucontext_t *uc, CorePart part,
594 Bool esp_is_thrptr)
595{
596 ThreadState *tst = VG_(get_ThreadState)(tid);
597 Addr old_esp = VG_(get_SP)(tid);
598
599 VG_TRACK(pre_mem_read, part, tid, "restore_context(uc->uc_flags)",
600 (Addr)&uc->uc_flags, sizeof(uc->uc_flags));
601
602 /* Old context */
603 VG_TRACK(pre_mem_read, part, tid, "restore_context(uc->uc_link)",
604 (Addr)&uc->uc_link, sizeof(uc->uc_link));
605 tst->os_state.oldcontext = uc->uc_link;
606
607 /* Sigmask */
608 if (uc->uc_flags & VKI_UC_SIGMASK) {
609 SysRes res;
610
611 VG_TRACK(pre_mem_read, part, tid, "restore_context(uc->uc_sigmask)",
612 (Addr)&uc->uc_sigmask, sizeof(uc->uc_sigmask));
613 res = VG_(do_sys_sigprocmask)(tid, VKI_SIG_SETMASK, &uc->uc_sigmask,
614 NULL);
615 /* Setting signal mask should never fail. */
616 vg_assert(!sr_isError(res));
617 }
618
619 /* Stack */
620 if (uc->uc_flags & VKI_UC_STACK) {
621 VG_TRACK(pre_mem_read, part, tid, "restore_context(uc->uc_stack)",
622 (Addr)&uc->uc_stack, sizeof(uc->uc_stack));
623
624 if (uc->uc_stack.ss_flags == VKI_SS_ONSTACK) {
625 /* This seems to be a little bit dangerous but it is what the kernel
626 does. */
627 if (VG_(clo_trace_signals))
florianb26101c2015-08-08 21:45:33 +0000628 VG_(dmsg)("restore_context, sigaltstack: tid %u, "
sewardj8eb8bab2015-07-21 14:44:28 +0000629 "ss %p{%p,sz=%lu,flags=%#x}\n",
630 tid, &uc->uc_stack, uc->uc_stack.ss_sp,
631 (SizeT)uc->uc_stack.ss_size, uc->uc_stack.ss_flags);
632
633 tst->altstack.ss_sp = uc->uc_stack.ss_sp;
634 tst->altstack.ss_size = uc->uc_stack.ss_size;
635 /* Do not copy ss_flags, they are calculated dynamically by
636 Valgrind. */
637 }
638
639 /* Copyout the new stack. */
640 if (tst->os_state.ustack
641 && VG_(am_is_valid_for_client)((Addr)tst->os_state.ustack,
642 sizeof(*tst->os_state.ustack),
643 VKI_PROT_WRITE))
644 *tst->os_state.ustack = uc->uc_stack;
645 VG_TRACK(post_mem_write, part, tid, (Addr)&tst->os_state.ustack,
646 sizeof(tst->os_state.ustack));
647 }
648
649 /* Restore the architecture-specific part of the context. */
650 ML_(restore_machine_context)(tid, uc, part, esp_is_thrptr);
651
652 /* If the thread stack is already known, kill the deallocated stack area.
653 This is important when returning from a signal handler. */
654 if (tst->client_stack_highest_byte && tst->client_stack_szB) {
655 Addr end = tst->client_stack_highest_byte;
656 Addr start = end + 1 - tst->client_stack_szB;
657 Addr new_esp = VG_(get_SP)(tid);
658
659 /* Make sure that the old and new stack pointer are on the same (active)
660 stack. Alternate stack is currently never affected by this code. */
661 if (start <= old_esp && old_esp <= end
662 && start <= new_esp && new_esp <= end
663 && new_esp > old_esp)
664 VG_TRACK(die_mem_stack, old_esp - VG_STACK_REDZONE_SZB,
665 (new_esp - old_esp) + VG_STACK_REDZONE_SZB);
666 }
667}
668
669/* Set a client stack associated with a given thread id according to values
670 passed in the vki_stack_t structure. */
671static void set_stack(ThreadId tid, vki_stack_t *st)
672{
673 ThreadState *tst = VG_(get_ThreadState)(tid);
674 Addr new_start, new_end;
675 SizeT new_size;
676 Addr cur_start;
677 SizeT cur_size;
678
679 VG_(debugLog)(2, "syswrap-solaris",
680 "set stack: sp=%#lx, size=%#lx.\n",
681 (Addr)st->ss_sp, (SizeT)st->ss_size);
682
683 /* Stay sane. */
684 vg_assert(st->ss_flags == 0);
685
686 new_start = (Addr)st->ss_sp;
687 new_end = new_start + st->ss_size - 1;
688 new_size = st->ss_size;
689 cur_start = tst->client_stack_highest_byte + 1
690 - tst->client_stack_szB;
691 cur_size = tst->client_stack_szB;
692
693 if (new_start == cur_start && new_size == cur_size) {
694 /* No change is requested, bail out. */
695 return;
696 }
697
698 if (tid == 1 && (new_size == 0 || new_size > VG_(clstk_max_size))) {
699 /* The main thread requests to use a stack without any size checking, or
700 too big stack. Fallback to the maximum allocated client stack. */
701
702 /* TODO I think it is possible to give up on setting main stack anyway.
703 Valgrind knows where it is located and it is already registered as
704 VG_(clstk_id). */
705
706 new_size = VG_(clstk_max_size);
707 new_end = tst->client_stack_highest_byte;
708 new_start = new_end + 1 - new_size;
709 }
710
Elliott Hughesed398002017-06-21 14:41:24 -0700711 if (tst->os_state.stk_id == NULL_STK_ID) {
sewardj8eb8bab2015-07-21 14:44:28 +0000712 /* This thread doesn't have a stack set yet. */
713 VG_(debugLog)(2, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000714 "Stack set to %#lx-%#lx (new) for thread %u.\n",
sewardj8eb8bab2015-07-21 14:44:28 +0000715 new_start, new_end, tid);
716 tst->os_state.stk_id = VG_(register_stack)(new_start, new_end);
Elliott Hughesed398002017-06-21 14:41:24 -0700717 } else {
sewardj8eb8bab2015-07-21 14:44:28 +0000718 /* Change a thread stack. */
719 VG_(debugLog)(2, "syswrap-solaris",
florianb26101c2015-08-08 21:45:33 +0000720 "Stack set to %#lx-%#lx (change) for thread %u.\n",
sewardj8eb8bab2015-07-21 14:44:28 +0000721 new_start, new_end, tid);
722 VG_(change_stack)(tst->os_state.stk_id, new_start, new_end);
723 }
724 tst->client_stack_highest_byte = new_end;
725 tst->client_stack_szB = new_size;
726}
727
728/* ---------------------------------------------------------------------
729 Door tracking. Used mainly for server side where door_return()
730 parameters alone do not contain sufficient information.
731 Also used on client side when new door descriptors are passed via
732 door_call() in desc_ptr. Not used for tracking door descriptors
733 explicitly open()'ed [generic fd tracking is used in that case].
734 ------------------------------------------------------------------ */
735
736/* One of these is allocated for each created door. */
737typedef struct OpenDoor
738{
739 Bool server; /* TRUE = server door, FALSE = client door */
740 Int fd; /* The file descriptor. */
741 union {
742 /* Server side. */
743 struct {
744 Addr server_procedure; /* The door server procedure. */
745 HChar *pathname; /* NULL if unknown. */
746 };
747 /* Client side. */
748 struct {
749 /* Hook called during PRE door_call()
750 to check contents of params->data_ptr. */
751 void (*pre_mem_hook)(ThreadId tid, Int fd,
752 void *data_ptr, SizeT data_size);
753 /* Hook called during POST door_call()
754 to define contents of params->rbuf. */
755 void (*post_mem_hook)(ThreadId tid, Int fd,
756 void *rbuf, SizeT rsize);
757 };
758 };
759 struct OpenDoor *next, *prev;
760} OpenDoor;
761
762/* List of allocated door fds. */
763static OpenDoor *doors_recorded = NULL;
764static UInt nr_doors_recorded = 0;
765
766static OpenDoor *door_record_create(void)
767{
768 OpenDoor *d = VG_(malloc)("syswrap.door_record_create.1", sizeof(OpenDoor));
769 d->prev = NULL;
770 d->next = doors_recorded;
771 if (doors_recorded != NULL)
772 doors_recorded->prev = d;
773 doors_recorded = d;
774 nr_doors_recorded += 1;
775
776 return d;
777}
778
779/* Records a server door. */
780static void door_record_server(ThreadId tid, Addr server_procedure, Int fd)
781{
782 OpenDoor *d = doors_recorded;
783
784 while (d != NULL) {
785 if ((d->server == TRUE) && (d->server_procedure == server_procedure)) {
786 if (d->pathname) {
787 VG_(free)(d->pathname);
788 }
789 break;
790 }
791 d = d->next;
792 }
793
794 if (d == NULL)
795 d = door_record_create();
796 vg_assert(d != NULL);
797
798 d->server = TRUE;
799 d->fd = fd;
800 d->server_procedure = server_procedure;
801 d->pathname = NULL;
802}
803
804/* Records a client door. */
805static void door_record_client(ThreadId tid, Int fd,
806 void (*pre_mem_hook)(ThreadId tid, Int fd, void *data_ptr, SizeT data_size),
807 void (*post_mem_hook)(ThreadId tid, Int fd, void *rbuf, SizeT rsize))
808{
809 OpenDoor *d = doors_recorded;
810
811 while (d != NULL) {
812 if ((d->server == FALSE) && (d->fd == fd))
813 break;
814 d = d->next;
815 }
816
817 if (d == NULL)
818 d = door_record_create();
819 vg_assert(d != NULL);
820
821 d->server = FALSE;
822 d->fd = fd;
823 d->pre_mem_hook = pre_mem_hook;
824 d->post_mem_hook = post_mem_hook;
825}
826
827/* Revokes an open door, be it server side or client side. */
Elliott Hughesa0664b92017-04-18 17:46:52 -0700828static void door_record_revoke(ThreadId tid, Int fd)
sewardj8eb8bab2015-07-21 14:44:28 +0000829{
830 OpenDoor *d = doors_recorded;
831
832 while (d != NULL) {
833 if (d->fd == fd) {
834 if (d->prev != NULL)
835 d->prev->next = d->next;
836 else
837 doors_recorded = d->next;
838 if (d->next != NULL)
839 d->next->prev = d->prev;
840
841 if ((d->server == TRUE) && (d->pathname != NULL))
842 VG_(free)(d->pathname);
843 VG_(free)(d);
844 nr_doors_recorded -= 1;
845 return;
846 }
847 d = d->next;
848 }
849}
850
851/* Attaches a server door to a filename. */
Elliott Hughesa0664b92017-04-18 17:46:52 -0700852static void door_record_server_fattach(Int fd, HChar *pathname)
sewardj8eb8bab2015-07-21 14:44:28 +0000853{
854 OpenDoor *d = doors_recorded;
855
856 while (d != NULL) {
857 if (d->fd == fd) {
858 vg_assert(d->server == TRUE);
859
860 if (d->pathname != NULL)
861 VG_(free)(d->pathname);
862 d->pathname = VG_(strdup)("syswrap.door_server_fattach.1", pathname);
863 return;
864 }
865 d = d->next;
866 }
867}
868
869/* Finds a server door based on server procedure. */
870static const OpenDoor *door_find_by_proc(Addr server_procedure)
871{
872 OpenDoor *d = doors_recorded;
873
874 while (d != NULL) {
875 if ((d->server) && (d->server_procedure == server_procedure))
876 return d;
877 d = d->next;
878 }
879
880 return NULL;
881}
882
883/* Finds a client door based on fd. */
884static const OpenDoor *door_find_by_fd(Int fd)
885{
886 OpenDoor *d = doors_recorded;
887
888 while (d != NULL) {
889 if ((d->server == FALSE) && (d->fd == fd))
890 return d;
891 d = d->next;
892 }
893
894 return NULL;
895}
896
897/* ---------------------------------------------------------------------
898 PRE/POST wrappers for Solaris-specific syscalls
899 ------------------------------------------------------------------ */
900
901#define PRE(name) DEFN_PRE_TEMPLATE(solaris, name)
902#define POST(name) DEFN_POST_TEMPLATE(solaris, name)
903
904/* prototypes */
905DECL_TEMPLATE(solaris, sys_exit);
906#if defined(SOLARIS_SPAWN_SYSCALL)
907DECL_TEMPLATE(solaris, sys_spawn);
908#endif /* SOLARIS_SPAWN_SYSCALL */
909#if defined(SOLARIS_OLD_SYSCALLS)
910DECL_TEMPLATE(solaris, sys_open);
911#endif /* SOLARIS_OLD_SYSCALLS */
912DECL_TEMPLATE(solaris, sys_close);
913DECL_TEMPLATE(solaris, sys_linkat);
914DECL_TEMPLATE(solaris, sys_symlinkat);
915DECL_TEMPLATE(solaris, sys_time);
916DECL_TEMPLATE(solaris, sys_brk);
917DECL_TEMPLATE(solaris, sys_stat);
918DECL_TEMPLATE(solaris, sys_lseek);
919DECL_TEMPLATE(solaris, sys_mount);
920DECL_TEMPLATE(solaris, sys_readlinkat);
921DECL_TEMPLATE(solaris, sys_stime);
922DECL_TEMPLATE(solaris, sys_fstat);
923#if defined(SOLARIS_FREALPATHAT_SYSCALL)
924DECL_TEMPLATE(solaris, sys_frealpathat);
925#endif /* SOLARIS_FREALPATHAT_SYSCALL */
926DECL_TEMPLATE(solaris, sys_stty);
927DECL_TEMPLATE(solaris, sys_gtty);
928DECL_TEMPLATE(solaris, sys_pgrpsys);
929DECL_TEMPLATE(solaris, sys_pipe);
930DECL_TEMPLATE(solaris, sys_faccessat);
931DECL_TEMPLATE(solaris, sys_mknodat);
932DECL_TEMPLATE(solaris, sys_sysi86);
933DECL_TEMPLATE(solaris, sys_shmsys);
934DECL_TEMPLATE(solaris, sys_semsys);
935DECL_TEMPLATE(solaris, sys_ioctl);
936DECL_TEMPLATE(solaris, sys_fchownat);
937DECL_TEMPLATE(solaris, sys_fdsync);
938DECL_TEMPLATE(solaris, sys_execve);
939DECL_TEMPLATE(solaris, sys_fcntl);
940DECL_TEMPLATE(solaris, sys_renameat);
941DECL_TEMPLATE(solaris, sys_unlinkat);
942DECL_TEMPLATE(solaris, sys_fstatat);
943DECL_TEMPLATE(solaris, sys_openat);
944DECL_TEMPLATE(solaris, sys_tasksys);
945DECL_TEMPLATE(solaris, sys_getpagesizes);
946DECL_TEMPLATE(solaris, sys_lwp_park);
947DECL_TEMPLATE(solaris, sys_sendfilev);
948#if defined(SOLARIS_LWP_NAME_SYSCALL)
949DECL_TEMPLATE(solaris, sys_lwp_name);
950#endif /* SOLARIS_LWP_NAME_SYSCALL */
951DECL_TEMPLATE(solaris, sys_privsys);
952DECL_TEMPLATE(solaris, sys_ucredsys);
Elliott Hughesa0664b92017-04-18 17:46:52 -0700953DECL_TEMPLATE(solaris, sys_sysfs);
sewardj8eb8bab2015-07-21 14:44:28 +0000954DECL_TEMPLATE(solaris, sys_getmsg);
955DECL_TEMPLATE(solaris, sys_putmsg);
956DECL_TEMPLATE(solaris, sys_lstat);
957DECL_TEMPLATE(solaris, sys_sigprocmask);
Elliott Hughesed398002017-06-21 14:41:24 -0700958DECL_TEMPLATE(solaris, sys_sigsuspend);
sewardj8eb8bab2015-07-21 14:44:28 +0000959DECL_TEMPLATE(solaris, sys_sigaction);
960DECL_TEMPLATE(solaris, sys_sigpending);
961DECL_TEMPLATE(solaris, sys_getsetcontext);
962DECL_TEMPLATE(solaris, sys_fchmodat);
963DECL_TEMPLATE(solaris, sys_mkdirat);
964DECL_TEMPLATE(solaris, sys_statvfs);
965DECL_TEMPLATE(solaris, sys_fstatvfs);
966DECL_TEMPLATE(solaris, sys_nfssys);
967DECL_TEMPLATE(solaris, sys_waitid);
Elliott Hughesed398002017-06-21 14:41:24 -0700968DECL_TEMPLATE(solaris, sys_sigsendsys);
sewardj8eb8bab2015-07-21 14:44:28 +0000969#if defined(SOLARIS_UTIMESYS_SYSCALL)
970DECL_TEMPLATE(solaris, sys_utimesys);
971#endif /* SOLARIS_UTIMESYS_SYSCALL */
972#if defined(SOLARIS_UTIMENSAT_SYSCALL)
973DECL_TEMPLATE(solaris, sys_utimensat);
974#endif /* SOLARIS_UTIMENSAT_SYSCALL */
975DECL_TEMPLATE(solaris, sys_sigresend);
976DECL_TEMPLATE(solaris, sys_priocntlsys);
977DECL_TEMPLATE(solaris, sys_pathconf);
978DECL_TEMPLATE(solaris, sys_mmap);
979#if defined(SOLARIS_UUIDSYS_SYSCALL)
980DECL_TEMPLATE(solaris, sys_uuidsys);
981#endif /* SOLARIS_UUIDSYS_SYSCALL */
982DECL_TEMPLATE(solaris, sys_mmapobj);
983DECL_TEMPLATE(solaris, sys_memcntl);
984DECL_TEMPLATE(solaris, sys_getpmsg);
985DECL_TEMPLATE(solaris, sys_putpmsg);
986#if defined(SOLARIS_OLD_SYSCALLS)
987DECL_TEMPLATE(solaris, sys_rename);
988#endif /* SOLARIS_OLD_SYSCALLS */
989DECL_TEMPLATE(solaris, sys_uname);
990DECL_TEMPLATE(solaris, sys_setegid);
991DECL_TEMPLATE(solaris, sys_sysconfig);
992DECL_TEMPLATE(solaris, sys_systeminfo);
993DECL_TEMPLATE(solaris, sys_seteuid);
994DECL_TEMPLATE(solaris, sys_forksys);
Elliott Hughesa0664b92017-04-18 17:46:52 -0700995#if defined(SOLARIS_GETRANDOM_SYSCALL)
996DECL_TEMPLATE(solaris, sys_getrandom);
997#endif /* SOLARIS_GETRANDOM_SYSCALL */
sewardj8eb8bab2015-07-21 14:44:28 +0000998DECL_TEMPLATE(solaris, sys_sigtimedwait);
999DECL_TEMPLATE(solaris, sys_yield);
1000DECL_TEMPLATE(solaris, sys_lwp_sema_post);
1001DECL_TEMPLATE(solaris, sys_lwp_sema_trywait);
1002DECL_TEMPLATE(solaris, sys_lwp_detach);
Elliott Hughesa0664b92017-04-18 17:46:52 -07001003DECL_TEMPLATE(solaris, sys_modctl);
sewardj8eb8bab2015-07-21 14:44:28 +00001004DECL_TEMPLATE(solaris, sys_fchroot);
iraisrc0d46cd2015-09-25 21:04:45 +00001005#if defined(SOLARIS_SYSTEM_STATS_SYSCALL)
1006DECL_TEMPLATE(solaris, sys_system_stats);
1007#endif /* SOLARIS_SYSTEM_STATS_SYSCALL */
sewardj8eb8bab2015-07-21 14:44:28 +00001008DECL_TEMPLATE(solaris, sys_gettimeofday);
1009DECL_TEMPLATE(solaris, sys_lwp_create);
1010DECL_TEMPLATE(solaris, sys_lwp_exit);
1011DECL_TEMPLATE(solaris, sys_lwp_suspend);
1012DECL_TEMPLATE(solaris, sys_lwp_continue);
1013#if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
1014DECL_TEMPLATE(solaris, sys_lwp_sigqueue);
1015#else
1016DECL_TEMPLATE(solaris, sys_lwp_kill);
1017#endif /* SOLARIS_LWP_SIGQUEUE_SYSCALL */
1018DECL_TEMPLATE(solaris, sys_lwp_self);
1019DECL_TEMPLATE(solaris, sys_lwp_sigmask);
1020DECL_TEMPLATE(solaris, sys_lwp_private);
1021DECL_TEMPLATE(solaris, sys_lwp_wait);
1022DECL_TEMPLATE(solaris, sys_lwp_mutex_wakeup);
iraisr173bb6e2015-10-16 12:20:20 +00001023DECL_TEMPLATE(solaris, sys_lwp_cond_wait);
Elliott Hughesa0664b92017-04-18 17:46:52 -07001024DECL_TEMPLATE(solaris, sys_lwp_cond_signal);
sewardj8eb8bab2015-07-21 14:44:28 +00001025DECL_TEMPLATE(solaris, sys_lwp_cond_broadcast);
1026DECL_TEMPLATE(solaris, sys_pread);
1027DECL_TEMPLATE(solaris, sys_pwrite);
Elliott Hughesed398002017-06-21 14:41:24 -07001028DECL_TEMPLATE(solaris, sys_lgrpsys);
sewardj8eb8bab2015-07-21 14:44:28 +00001029DECL_TEMPLATE(solaris, sys_rusagesys);
1030DECL_TEMPLATE(solaris, sys_port);
1031DECL_TEMPLATE(solaris, sys_pollsys);
1032DECL_TEMPLATE(solaris, sys_labelsys);
1033DECL_TEMPLATE(solaris, sys_acl);
1034DECL_TEMPLATE(solaris, sys_auditsys);
1035DECL_TEMPLATE(solaris, sys_p_online);
1036DECL_TEMPLATE(solaris, sys_sigqueue);
1037DECL_TEMPLATE(solaris, sys_clock_gettime);
1038DECL_TEMPLATE(solaris, sys_clock_settime);
1039DECL_TEMPLATE(solaris, sys_clock_getres);
1040DECL_TEMPLATE(solaris, sys_timer_create);
1041DECL_TEMPLATE(solaris, sys_timer_delete);
1042DECL_TEMPLATE(solaris, sys_timer_settime);
1043DECL_TEMPLATE(solaris, sys_timer_gettime);
1044DECL_TEMPLATE(solaris, sys_timer_getoverrun);
1045DECL_TEMPLATE(solaris, sys_facl);
1046DECL_TEMPLATE(solaris, sys_door);
1047DECL_TEMPLATE(solaris, sys_schedctl);
iraisr7d4aa192015-10-12 19:10:42 +00001048DECL_TEMPLATE(solaris, sys_pset);
sewardj8eb8bab2015-07-21 14:44:28 +00001049DECL_TEMPLATE(solaris, sys_resolvepath);
1050DECL_TEMPLATE(solaris, sys_lwp_mutex_timedlock);
1051DECL_TEMPLATE(solaris, sys_lwp_rwlock_sys);
1052DECL_TEMPLATE(solaris, sys_lwp_sema_timedwait);
1053DECL_TEMPLATE(solaris, sys_zone);
1054DECL_TEMPLATE(solaris, sys_getcwd);
1055DECL_TEMPLATE(solaris, sys_so_socket);
1056DECL_TEMPLATE(solaris, sys_so_socketpair);
1057DECL_TEMPLATE(solaris, sys_bind);
1058DECL_TEMPLATE(solaris, sys_listen);
1059DECL_TEMPLATE(solaris, sys_accept);
1060DECL_TEMPLATE(solaris, sys_connect);
1061DECL_TEMPLATE(solaris, sys_shutdown);
1062DECL_TEMPLATE(solaris, sys_recv);
1063DECL_TEMPLATE(solaris, sys_recvfrom);
1064DECL_TEMPLATE(solaris, sys_recvmsg);
1065DECL_TEMPLATE(solaris, sys_send);
1066DECL_TEMPLATE(solaris, sys_sendmsg);
1067DECL_TEMPLATE(solaris, sys_sendto);
1068DECL_TEMPLATE(solaris, sys_getpeername);
1069DECL_TEMPLATE(solaris, sys_getsockname);
1070DECL_TEMPLATE(solaris, sys_getsockopt);
1071DECL_TEMPLATE(solaris, sys_setsockopt);
1072DECL_TEMPLATE(solaris, sys_lwp_mutex_register);
1073DECL_TEMPLATE(solaris, sys_uucopy);
1074DECL_TEMPLATE(solaris, sys_umount2);
1075
1076DECL_TEMPLATE(solaris, fast_gethrtime);
1077DECL_TEMPLATE(solaris, fast_gethrvtime);
1078DECL_TEMPLATE(solaris, fast_gethrestime);
Elliott Hughesed398002017-06-21 14:41:24 -07001079DECL_TEMPLATE(solaris, fast_getlgrp);
sewardj8eb8bab2015-07-21 14:44:28 +00001080#if defined(SOLARIS_GETHRT_FASTTRAP)
1081DECL_TEMPLATE(solaris, fast_gethrt);
1082#endif /* SOLARIS_GETHRT_FASTTRAP */
1083#if defined(SOLARIS_GETZONEOFFSET_FASTTRAP)
1084DECL_TEMPLATE(solaris, fast_getzoneoffset);
1085#endif /* SOLARIS_GETZONEOFFSET_FASTTRAP */
1086
1087/* implementation */
1088PRE(sys_exit)
1089{
1090 /* void exit(int status); */
1091 ThreadId t;
1092
florianb26101c2015-08-08 21:45:33 +00001093 PRINT("sys_exit( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00001094 PRE_REG_READ1(void, "exit", int, status);
1095
1096 for (t = 1; t < VG_N_THREADS; t++) {
1097 if (VG_(threads)[t].status == VgTs_Empty)
1098 continue;
1099
Elliott Hughesa0664b92017-04-18 17:46:52 -07001100 /* Assign the exit code, VG_(nuke_all_threads_except) will assign
1101 the exitreason. */
sewardj8eb8bab2015-07-21 14:44:28 +00001102 VG_(threads)[t].os_state.exitcode = ARG1;
sewardj8eb8bab2015-07-21 14:44:28 +00001103 }
1104
Elliott Hughesa0664b92017-04-18 17:46:52 -07001105 /* Indicate in all other threads that the process is exiting.
1106 Then wait using VG_(reap_threads) for these threads to disappear.
1107 See comments in syswrap-linux.c, PRE(sys_exit_group) wrapper,
1108 for reasoning why this cannot give a deadlock. */
1109 VG_(nuke_all_threads_except)(tid, VgSrc_ExitProcess);
1110 VG_(reap_threads)(tid);
1111 VG_(threads)[tid].exitreason = VgSrc_ExitThread;
1112 /* We do assign VgSrc_ExitThread and not VgSrc_ExitProcess, as this thread
1113 is the thread calling exit_group and so its registers must be considered
1114 as not reachable. See pub_tool_machine.h VG_(apply_to_GP_regs). */
1115
sewardj8eb8bab2015-07-21 14:44:28 +00001116 /* We have to claim the syscall already succeeded. */
1117 SET_STATUS_Success(0);
1118}
1119
1120#if defined(SOLARIS_SPAWN_SYSCALL)
1121static Bool spawn_pre_check_kfa(ThreadId tid, SyscallStatus *status,
1122 vki_kfile_attr_t *kfa)
1123{
1124 PRE_FIELD_READ("spawn(attrs->kfa_size)", kfa->kfa_size);
1125 PRE_FIELD_READ("spawn(attrs->kfa_type)", kfa->kfa_type);
1126
1127 if (ML_(safe_to_deref)(kfa, kfa->kfa_size)) {
1128 switch (kfa->kfa_type) {
1129 case VKI_FA_DUP2:
1130 PRE_FIELD_READ("spawn(attrs->kfa_filedes)", kfa->kfa_filedes);
1131 PRE_FIELD_READ("spawn(attrs->kfa_newfiledes)", kfa->kfa_newfiledes);
1132 if (!ML_(fd_allowed)(kfa->kfa_filedes, "spawn(dup2)", tid, False) ||
1133 !ML_(fd_allowed)(kfa->kfa_newfiledes, "spawn(dup2)", tid, False)) {
1134 SET_STATUS_Failure(VKI_EBADF);
1135 return False;
1136 }
1137 break;
1138 case VKI_FA_CLOSE:
1139 PRE_FIELD_READ("spawn(attrs->kfa_filedes)", kfa->kfa_filedes);
1140 /* If doing -d style logging (which is to fd = 2 = stderr),
1141 don't allow that filedes to be closed. See ML_(fd_allowed)(). */
1142 if (!ML_(fd_allowed)(kfa->kfa_filedes, "spawn(close)", tid, False) ||
1143 (kfa->kfa_filedes == 2 && VG_(debugLog_getLevel)() > 0)) {
1144 SET_STATUS_Failure(VKI_EBADF);
1145 return False;
1146 }
1147 break;
1148 case VKI_FA_CLOSEFROM:
1149 /* :TODO: All file descriptors greater than or equal to
1150 kfa->kfa_filedes would have to be checked. */
1151 VG_(unimplemented)("Support for spawn() with file attribute type "
1152 "FA_CLOSEFROM.");
1153 break;
1154 case VKI_FA_OPEN:
1155 PRE_FIELD_READ("spawn(attrs->kfa_filedes)", kfa->kfa_filedes);
1156 PRE_FIELD_READ("spawn(attrs->kfa_oflag)", kfa->kfa_oflag);
1157 PRE_FIELD_READ("spawn(attrs->kfa_mode)", kfa->kfa_mode);
1158 if (!ML_(fd_allowed)(kfa->kfa_filedes, "spawn(open)", tid, False)) {
1159 SET_STATUS_Failure(VKI_EBADF);
1160 return False;
1161 }
1162 /* fallthrough */
1163 case VKI_FA_CHDIR:
1164 PRE_FIELD_READ("spawn(attrs->kfa_pathsize)", kfa->kfa_pathsize);
1165 if (kfa->kfa_pathsize != 0) {
1166 PRE_MEM_RASCIIZ("spawn(attrs->kfa_data)", (Addr) kfa->kfa_data);
1167 }
1168 break;
1169 default:
1170 VG_(unimplemented)("Support for spawn() with file attribute type %u.",
1171 kfa->kfa_type);
1172 }
1173 }
1174
1175 return True;
1176}
1177
1178PRE(sys_spawn)
1179{
1180 /* int spawn(char *path, void *attrs, size_t attrsize,
1181 char *argenv, size_t aesize); */
florianb26101c2015-08-08 21:45:33 +00001182 PRINT("sys_spawn ( %#lx(%s), %#lx, %lu, %#lx, %lu )",
sewardj8eb8bab2015-07-21 14:44:28 +00001183 ARG1, (HChar *) ARG1, ARG2, ARG3, ARG4, ARG5);
1184 PRE_REG_READ5(long, "spawn", const char *, path, void *, attrs,
1185 size_t, attrsize, char *, argenv, size_t, aesize);
1186
1187 /* First check input arguments. */
1188 PRE_MEM_RASCIIZ("spawn(path)", ARG1);
1189 if (ARG3 > 0) {
1190 /* --- vki_kspawn_attr_t --
1191 | ksa_version |
1192 | ksa_size |
1193 | ksa_attr_off | -----| (only if != 0)
1194 | ksa_attr_size | |
1195 | ksa_path_off | =====|====| (only if != 0)
1196 | ksa_path_size | | |
1197 | ksa_shell_off | -----|----|----| (only if != 0)
1198 | ksa_shell_size | | | |
1199 | ksa_data[0] | | | |
1200 ------------------------ | | |
1201 | vki_spawn_attr_t | <----| | |
1202 ------------------------ | |
1203 | path | <---------| |
1204 ------------------------ |
1205 | shell | <---------------
1206 ------------------------
1207 | file actions | (not included in ksa_size, only in ARG3)
1208 ------------------------
1209
1210 ksa_size = sizeof(vki_kspawn_attr_t) + ksa_attr_size + ksa_path_size +
1211 ksa_shell_size
1212 attrs_size (ARG3) = ksa_size + file actions size */
1213
1214 vki_kspawn_attr_t *attrs = (vki_kspawn_attr_t *) ARG2;
1215 PRE_FIELD_READ("spawn(attrs->ksa_version)", attrs->ksa_version);
1216 PRE_FIELD_READ("spawn(attrs->ksa_size)", attrs->ksa_size);
1217 PRE_FIELD_READ("spawn(attrs->ksa_attr_off)", attrs->ksa_attr_off);
1218 PRE_FIELD_READ("spawn(attrs->ksa_path_off)", attrs->ksa_path_off);
1219 PRE_FIELD_READ("spawn(attrs->ksa_shell_off)", attrs->ksa_shell_off);
1220
1221 if (ML_(safe_to_deref)(attrs, sizeof(vki_kspawn_attr_t))) {
1222 if (attrs->ksa_version != VKI_SPAWN_VERSION) {
1223 VG_(unimplemented)("Support for spawn() with attributes "
1224 "version %u.", attrs->ksa_version);
1225 }
1226
1227 if (attrs->ksa_attr_off != 0) {
1228 PRE_FIELD_READ("spawn(attrs->ksa_attr_size)", attrs->ksa_attr_size);
1229 vki_spawn_attr_t *sap =
1230 (vki_spawn_attr_t *) ((Addr) attrs + attrs->ksa_attr_off);
1231 PRE_MEM_READ("spawn(attrs->ksa_attr)",
1232 (Addr) sap, attrs->ksa_attr_size);
1233 if (ML_(safe_to_deref)(sap, sizeof(vki_spawn_attr_t))) {
1234 if (sap->sa_psflags & VKI_POSIX_SPAWN_SETVAMASK_NP) {
1235 VG_(unimplemented)("Support for spawn() with attributes flag "
1236 "including POSIX_SPAWN_SETVAMASK_NP.");
1237 }
1238 /* paranoia */
1239 Int rem = sap->sa_psflags & ~(
1240 VKI_POSIX_SPAWN_RESETIDS | VKI_POSIX_SPAWN_SETPGROUP |
1241 VKI_POSIX_SPAWN_SETSIGDEF | VKI_POSIX_SPAWN_SETSIGMASK |
1242 VKI_POSIX_SPAWN_SETSCHEDPARAM | VKI_POSIX_SPAWN_SETSCHEDULER |
1243 VKI_POSIX_SPAWN_SETSID_NP | VKI_POSIX_SPAWN_SETVAMASK_NP |
1244 VKI_POSIX_SPAWN_SETSIGIGN_NP | VKI_POSIX_SPAWN_NOSIGCHLD_NP |
1245 VKI_POSIX_SPAWN_WAITPID_NP | VKI_POSIX_SPAWN_NOEXECERR_NP);
1246 if (rem != 0) {
1247 VG_(unimplemented)("Support for spawn() with attributes flag "
1248 "%#x.", sap->sa_psflags);
1249 }
1250 }
1251 }
1252
1253 if (attrs->ksa_path_off != 0) {
1254 PRE_FIELD_READ("spawn(attrs->ksa_path_size)", attrs->ksa_path_size);
1255 PRE_MEM_RASCIIZ("spawn(attrs->ksa_path)",
1256 (Addr) attrs + attrs->ksa_path_off);
1257 }
1258
1259 if (attrs->ksa_shell_off != 0) {
1260 PRE_FIELD_READ("spawn(attrs->ksa_shell_size)",
1261 attrs->ksa_shell_size);
1262 PRE_MEM_RASCIIZ("spawn(attrs->ksa_shell)",
1263 (Addr) attrs + attrs->ksa_shell_off);
1264 }
1265
1266 vki_kfile_attr_t *kfa = (vki_kfile_attr_t *) (ARG2 + attrs->ksa_size);
1267 while ((Addr) kfa < ARG2 + ARG3) {
1268 if (spawn_pre_check_kfa(tid, status, kfa) == False) {
1269 return;
1270 }
1271 kfa = (vki_kfile_attr_t *) ((Addr) kfa + kfa->kfa_size);
1272 }
1273 }
1274 }
1275 PRE_MEM_READ("spawn(argenv)", ARG4, ARG5);
1276
1277 /* Check that the name at least begins in client-accessible storage. */
1278 if ((ARG1 == 0) || !ML_(safe_to_deref)((HChar *) ARG1, 1)) {
1279 SET_STATUS_Failure(VKI_EFAULT);
1280 return;
1281 }
1282
1283 /* Check that attrs reside in client-accessible storage. */
1284 if (ARG2 != 0) {
1285 if (!VG_(am_is_valid_for_client)(ARG2, ARG3, VKI_PROT_READ)) {
1286 SET_STATUS_Failure(VKI_EFAULT);
1287 return;
1288 }
1289 }
1290
1291 /* Check that the argenv reside in client-accessible storage.
1292 Solaris disallows to perform spawn() without any arguments & environment
1293 variables specified. */
1294 if ((ARG4 == 0) /* obviously bogus */ ||
1295 !VG_(am_is_valid_for_client)(ARG4, ARG5, VKI_PROT_READ)) {
1296 SET_STATUS_Failure(VKI_EFAULT);
1297 return;
1298 }
1299
1300 /* Copy existing attrs or create empty minimal ones. */
1301 vki_kspawn_attr_t *attrs;
1302 SizeT attrs_size;
1303 if (ARG2 == 0) {
1304 /* minimalistic kspawn_attr_t + spawn_attr_t */
1305 attrs_size = sizeof(vki_kspawn_attr_t) + sizeof(vki_spawn_attr_t);
1306 attrs = VG_(calloc)("syswrap.spawn.1", 1, attrs_size);
1307 attrs->ksa_version = VKI_SPAWN_VERSION;
1308 attrs->ksa_size = attrs_size;
1309 attrs->ksa_attr_off = sizeof(vki_kspawn_attr_t);
1310 attrs->ksa_attr_size = sizeof(vki_spawn_attr_t);
1311 } else if (((vki_kspawn_attr_t *) ARG2)->ksa_attr_off == 0) {
1312 /* existing kspawn_attr_t but missing spawn_attr_t */
1313 attrs_size = ARG3 + sizeof(vki_spawn_attr_t);
1314 attrs = VG_(calloc)("syswrap.spawn.2", 1, attrs_size);
1315 VG_(memcpy)(attrs, (void *) ARG2, sizeof(vki_kspawn_attr_t));
1316 SizeT file_actions_size = ARG3 - attrs->ksa_size;
1317 attrs->ksa_size += sizeof(vki_spawn_attr_t);
1318 attrs->ksa_attr_off = sizeof(vki_kspawn_attr_t);
1319 attrs->ksa_attr_size = sizeof(vki_spawn_attr_t);
1320 if (attrs->ksa_path_off != 0) {
1321 VG_(memcpy)((HChar *) attrs + attrs->ksa_path_off +
1322 sizeof(vki_spawn_attr_t), (HChar *) ARG2 +
1323 attrs->ksa_path_off, attrs->ksa_path_size);
1324 attrs->ksa_path_off += sizeof(vki_spawn_attr_t);
1325 }
1326 if (attrs->ksa_shell_off != 0) {
1327 VG_(memcpy)((HChar *) attrs + attrs->ksa_shell_off +
1328 sizeof(vki_spawn_attr_t), (HChar *) ARG2 +
1329 attrs->ksa_shell_off, attrs->ksa_shell_size);
1330 attrs->ksa_shell_off += sizeof(vki_spawn_attr_t);
1331 }
1332 if (file_actions_size > 0) {
1333 VG_(memcpy)((HChar *) attrs + attrs_size - file_actions_size,
1334 (HChar *) ARG2 + ARG3 - file_actions_size,
1335 file_actions_size);
1336 }
1337 } else {
1338 /* existing kspawn_attr_t + spawn_attr_t */
1339 attrs_size = ARG3;
1340 attrs = VG_(malloc)("syswrap.spawn.3", attrs_size);
1341 VG_(memcpy)(attrs, (void *) ARG2, attrs_size);
1342 }
1343 vki_spawn_attr_t *spa = (vki_spawn_attr_t *) ((HChar *) attrs +
1344 attrs->ksa_attr_off);
1345
1346 /* Convert argv and envp parts of argenv into their separate XArray's.
1347 Duplicate strings because argv and envp will be then modified. */
1348 XArray *argv = VG_(newXA)(VG_(malloc), "syswrap.spawn.4",
1349 VG_(free), sizeof(HChar *));
1350 XArray *envp = VG_(newXA)(VG_(malloc), "syswrap.spawn.5",
1351 VG_(free), sizeof(HChar *));
1352
1353 HChar *argenv = (HChar *) ARG4;
1354 XArray *current_xa = argv;
1355 while ((Addr) argenv < ARG4 + ARG5) {
1356 if (*argenv == '\0') {
1357 argenv += 1;
1358 if (current_xa == argv) {
1359 current_xa = envp;
1360 if ((*argenv == '\0') && ((Addr) argenv == ARG4 + ARG5 - 1)) {
1361 /* envp part is empty, it contained only {NULL}. */
1362 break;
1363 }
1364 } else {
1365 if ((Addr) argenv != ARG4 + ARG5) {
1366 if (VG_(clo_trace_syscalls))
1367 VG_(debugLog)(3, "syswrap-solaris", "spawn: bogus argenv\n");
1368 SET_STATUS_Failure(VKI_EINVAL);
1369 goto exit;
1370 }
1371 break;
1372 }
1373 }
1374
1375 if (*argenv != '\1') {
1376 if (VG_(clo_trace_syscalls))
1377 VG_(debugLog)(3, "syswrap-solaris", "spawn: bogus argenv\n");
1378 SET_STATUS_Failure(VKI_EINVAL);
1379 goto exit;
1380 }
1381 argenv += 1;
1382
1383 HChar *duplicate = VG_(strdup)("syswrap.spawn.6", argenv);
1384 VG_(addToXA)(current_xa, &duplicate);
1385 argenv += VG_(strlen)(argenv) + 1;
1386 }
1387
1388 /* Debug-only printing. */
1389 if (0) {
1390 VG_(printf)("\nARG1 = %#lx(%s)\n", ARG1, (HChar *) ARG1);
1391 VG_(printf)("ARG4 (argv) = ");
1392 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1393 VG_(printf)("%s ", *(HChar **) VG_(indexXA)(argv, i));
1394 }
1395
1396 VG_(printf)("\nARG4 (envp) = ");
1397 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1398 VG_(printf)("%s ", *(HChar **) VG_(indexXA)(envp, i));
1399 }
1400 VG_(printf)("\n");
1401 }
1402
1403 /* Decide whether or not we want to trace the spawned child.
1404 Omit the executable name itself from child_argv. */
1405 const HChar **child_argv = VG_(malloc)("syswrap.spawn.7",
1406 (VG_(sizeXA)(argv) - 1) * sizeof(HChar *));
1407 for (Word i = 1; i < VG_(sizeXA)(argv); i++) {
1408 child_argv[i - 1] = *(HChar **) VG_(indexXA)(argv, i);
1409 }
1410 Bool trace_this_child = VG_(should_we_trace_this_child)((HChar *) ARG1,
1411 child_argv);
1412 VG_(free)(child_argv);
1413
1414 /* If we're tracing the child, and the launcher name looks bogus (possibly
1415 because launcher.c couldn't figure it out, see comments therein) then we
1416 have no option but to fail. */
1417 if (trace_this_child &&
1418 (!VG_(name_of_launcher) || VG_(name_of_launcher)[0] != '/')) {
1419 SET_STATUS_Failure(VKI_ECHILD); /* "No child processes." */
1420 goto exit;
1421 }
1422
1423 /* Set up the child's exe path. */
1424 const HChar *path = (const HChar *) ARG1;
1425 const HChar *launcher_basename = NULL;
1426 if (trace_this_child) {
1427 /* We want to exec the launcher. */
1428 path = VG_(name_of_launcher);
1429 vg_assert(path != NULL);
1430
1431 launcher_basename = VG_(strrchr)(path, '/');
1432 if ((launcher_basename == NULL) || (launcher_basename[1] == '\0')) {
1433 launcher_basename = path; /* hmm, tres dubious */
1434 } else {
1435 launcher_basename++;
1436 }
1437 }
1438
1439 /* Set up the child's environment.
1440
1441 Remove the valgrind-specific stuff from the environment so the child
1442 doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc. This is done
1443 unconditionally, since if we are tracing the child, the child valgrind
1444 will set up the appropriate client environment.
1445
1446 Then, if tracing the child, set VALGRIND_LIB for it. */
1447 HChar **child_envp = VG_(calloc)("syswrap.spawn.8",
1448 VG_(sizeXA)(envp) + 1, sizeof(HChar *));
1449 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1450 child_envp[i] = *(HChar **) VG_(indexXA)(envp, i);
1451 }
1452 VG_(env_remove_valgrind_env_stuff)(child_envp, /* ro_strings */ False,
1453 VG_(free));
1454
1455 /* Stuff was removed from child_envp, reflect that in envp XArray. */
1456 VG_(dropTailXA)(envp, VG_(sizeXA)(envp));
1457 for (UInt i = 0; child_envp[i] != NULL; i++) {
1458 VG_(addToXA)(envp, &child_envp[i]);
1459 }
1460 VG_(free)(child_envp);
1461
1462 if (trace_this_child) {
1463 /* Set VALGRIND_LIB in envp. */
1464 SizeT len = VG_(strlen)(VALGRIND_LIB) + VG_(strlen)(VG_(libdir)) + 2;
1465 HChar *valstr = VG_(malloc)("syswrap.spawn.9", len);
1466 VG_(sprintf)(valstr, "%s=%s", VALGRIND_LIB, VG_(libdir));
1467 VG_(addToXA)(envp, &valstr);
1468 }
1469
1470 /* Set up the child's args. If not tracing it, they are left untouched.
1471 Otherwise, they are:
1472
1473 [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG4[1..],
1474
1475 except that the first VG_(args_for_valgrind_noexecpass) args are
1476 omitted. */
1477 if (trace_this_child) {
1478 vg_assert(VG_(args_for_valgrind) != NULL);
1479 vg_assert(VG_(args_for_valgrind_noexecpass) >= 0);
1480 vg_assert(VG_(args_for_valgrind_noexecpass)
1481 <= VG_(sizeXA)(VG_(args_for_valgrind)));
1482
1483 /* So what args will there be? Bear with me... */
1484 /* ... launcher basename, ... */
1485 HChar *duplicate = VG_(strdup)("syswrap.spawn.10", launcher_basename);
1486 VG_(insertIndexXA)(argv, 0, &duplicate);
1487
1488 /* ... Valgrind's args, ... */
1489 UInt v_args = VG_(sizeXA)(VG_(args_for_valgrind));
1490 v_args -= VG_(args_for_valgrind_noexecpass);
1491 for (Word i = VG_(args_for_valgrind_noexecpass);
1492 i < VG_(sizeXA)(VG_(args_for_valgrind)); i++) {
1493 duplicate = VG_(strdup)("syswrap.spawn.11",
1494 *(HChar **) VG_(indexXA)(VG_(args_for_valgrind), i));
1495 VG_(insertIndexXA)(argv, 1 + i, &duplicate);
1496 }
1497
1498 /* ... name of client executable, ... */
1499 duplicate = VG_(strdup)("syswrap.spawn.12", (HChar *) ARG1);
1500 VG_(insertIndexXA)(argv, 1 + v_args, &duplicate);
1501
1502 /* ... and args for client executable (without [0]). */
1503 duplicate = *(HChar **) VG_(indexXA)(argv, 1 + v_args + 1);
1504 VG_(free)(duplicate);
1505 VG_(removeIndexXA)(argv, 1 + v_args + 1);
1506 }
1507
1508 /* Debug-only printing. */
1509 if (0) {
1510 VG_(printf)("\npath = %s\n", path);
1511 VG_(printf)("argv = ");
1512 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1513 VG_(printf)("%s ", *(HChar **) VG_(indexXA)(argv, i));
1514 }
1515
1516 VG_(printf)("\nenvp = ");
1517 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1518 VG_(printf)("%s ", *(HChar **) VG_(indexXA)(envp, i));
1519 }
1520 VG_(printf)("\n");
1521 }
1522
1523 /* Set the signal state up for spawned child.
1524
1525 Signals set to be caught are equivalent to signals set to the default
1526 action, from the child's perspective.
1527
1528 Therefore query SCSS and prepare default (DFL) and ignore (IGN) signal
1529 sets. Then combine these sets with those passed from client, if flags
1530 POSIX_SPAWN_SETSIGDEF, or POSIX_SPAWN_SETSIGIGN_NP have been specified.
1531 */
1532 vki_sigset_t sig_default;
1533 vki_sigset_t sig_ignore;
1534 VG_(sigemptyset)(&sig_default);
1535 VG_(sigemptyset)(&sig_ignore);
1536 for (Int i = 1; i < VG_(max_signal); i++) {
1537 vki_sigaction_fromK_t sa;
1538 VG_(do_sys_sigaction)(i, NULL, &sa); /* query SCSS */
1539 if (sa.sa_handler == VKI_SIG_IGN) {
1540 VG_(sigaddset)(&sig_ignore, i);
1541 } else {
1542 VG_(sigaddset)(&sig_default, i);
1543 }
1544 }
1545
1546 if (spa->sa_psflags & VKI_POSIX_SPAWN_SETSIGDEF) {
1547 VG_(sigaddset_from_set)(&spa->sa_sigdefault, &sig_default);
1548 } else {
1549 spa->sa_psflags |= VKI_POSIX_SPAWN_SETSIGDEF;
1550 spa->sa_sigdefault = sig_default;
1551 }
1552
1553 if (spa->sa_psflags & VKI_POSIX_SPAWN_SETSIGIGN_NP) {
1554 VG_(sigaddset_from_set)(&spa->sa_sigignore, &sig_ignore);
1555 } else {
1556 spa->sa_psflags |= VKI_POSIX_SPAWN_SETSIGIGN_NP;
1557 spa->sa_sigignore = sig_ignore;
1558 }
1559
1560 /* Set the signal mask for spawned child.
1561
1562 Analogous to signal handlers: query SCSS for blocked signals mask
1563 and combine this mask with that passed from client, if flag
1564 POSIX_SPAWN_SETSIGMASK has been specified. */
1565 vki_sigset_t *sigmask = &VG_(get_ThreadState)(tid)->sig_mask;
1566 if (spa->sa_psflags & VKI_POSIX_SPAWN_SETSIGMASK) {
1567 VG_(sigaddset_from_set)(&spa->sa_sigmask, sigmask);
1568 } else {
1569 spa->sa_psflags |= VKI_POSIX_SPAWN_SETSIGMASK;
1570 spa->sa_sigmask = *sigmask;
1571 }
1572
1573 /* Lastly, reconstruct argenv from argv + envp. */
1574 SizeT argenv_size = 1 + 1;
1575 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1576 argenv_size += VG_(strlen)(*(HChar **) VG_(indexXA)(argv, i)) + 2;
1577 }
1578 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1579 argenv_size += VG_(strlen)(*(HChar **) VG_(indexXA)(envp, i)) + 2;
1580 }
1581
1582 argenv = VG_(malloc)("syswrap.spawn.13", argenv_size);
1583 HChar *current = argenv;
1584#define COPY_CHAR_TO_ARGENV(dst, character) \
1585 do { \
1586 *(dst) = character; \
1587 (dst) += 1; \
1588 } while (0)
1589#define COPY_STRING_TO_ARGENV(dst, src) \
1590 do { \
1591 COPY_CHAR_TO_ARGENV(dst, '\1'); \
1592 SizeT src_len = VG_(strlen)((src)) + 1; \
1593 VG_(memcpy)((dst), (src), src_len); \
1594 (dst) += src_len; \
1595 } while (0)
1596
1597 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1598 COPY_STRING_TO_ARGENV(current, *(HChar **) VG_(indexXA)(argv, i));
1599 }
1600 COPY_CHAR_TO_ARGENV(current, '\0');
1601 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1602 COPY_STRING_TO_ARGENV(current, *(HChar **) VG_(indexXA)(envp, i));
1603 }
1604 COPY_CHAR_TO_ARGENV(current, '\0');
1605 vg_assert(current == argenv + argenv_size);
1606#undef COPY_CHAR_TO_ARGENV
1607#undef COPY_STRING_TOARGENV
1608
sewardj8eb8bab2015-07-21 14:44:28 +00001609 /* Actual spawn() syscall. */
1610 SysRes res = VG_(do_syscall5)(__NR_spawn, (UWord) path, (UWord) attrs,
1611 attrs_size, (UWord) argenv, argenv_size);
1612 SET_STATUS_from_SysRes(res);
1613 VG_(free)(argenv);
1614
sewardj8eb8bab2015-07-21 14:44:28 +00001615 if (SUCCESS) {
1616 PRINT(" spawn: process %d spawned child %ld\n", VG_(getpid)(), RES);
1617 }
1618
1619exit:
1620 VG_(free)(attrs);
1621 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1622 VG_(free)(*(HChar **) VG_(indexXA)(argv, i));
1623 }
1624 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1625 VG_(free)(*(HChar **) VG_(indexXA)(envp, i));
1626 }
1627 VG_(deleteXA)(argv);
1628 VG_(deleteXA)(envp);
1629}
1630#endif /* SOLARIS_SPAWN_SYSCALL */
1631
1632/* Handles the case where the open is of /proc/self/psinfo or
1633 /proc/<pid>/psinfo. Fetch fresh contents into psinfo_t,
1634 fake fname, psargs, argc and argv. Write the structure to the fake
1635 file we cooked up at startup (in m_main) and give out a copy of this
1636 fd. Also seek the cloned fd back to the start. */
1637static Bool handle_psinfo_open(SyscallStatus *status,
1638 Bool use_openat,
1639 const HChar *filename,
1640 Int arg1, UWord arg3, UWord arg4)
1641{
1642 if (!ML_(safe_to_deref)((const void *) filename, 1))
1643 return False;
1644
1645 HChar name[VKI_PATH_MAX]; // large enough
1646 VG_(sprintf)(name, "/proc/%d/psinfo", VG_(getpid)());
1647
1648 if (!VG_STREQ(filename, name) && !VG_STREQ(filename, "/proc/self/psinfo"))
1649 return False;
1650
iraisr23e68ca2015-08-14 20:50:11 +00001651 /* Use original arguments to open() or openat(). */
sewardj8eb8bab2015-07-21 14:44:28 +00001652 SysRes sres;
1653#if defined(SOLARIS_OLD_SYSCALLS)
1654 if (use_openat)
1655 sres = VG_(do_syscall4)(SYS_openat, arg1, (UWord) filename,
1656 arg3, arg4);
1657 else
1658 sres = VG_(do_syscall3)(SYS_open, (UWord) filename, arg3, arg4);
1659#else
1660 vg_assert(use_openat == True);
1661 sres = VG_(do_syscall4)(SYS_openat, arg1, (UWord) filename,
1662 arg3, arg4);
1663#endif /* SOLARIS_OLD_SYSCALLS */
1664
1665 if (sr_isError(sres)) {
1666 SET_STATUS_from_SysRes(sres);
1667 return True;
1668 }
1669 Int fd = sr_Res(sres);
1670
1671 vki_psinfo_t psinfo;
1672 sres = VG_(do_syscall3)(SYS_read, fd, (UWord) &psinfo, sizeof(psinfo));
1673 if (sr_isError(sres)) {
1674 SET_STATUS_from_SysRes(sres);
1675 VG_(close)(fd);
1676 return True;
1677 }
1678 if (sr_Res(sres) != sizeof(psinfo)) {
1679 SET_STATUS_Failure(VKI_ENODATA);
1680 VG_(close)(fd);
1681 return True;
1682 }
1683
1684 VG_(close)(fd);
1685
1686 VG_(client_fname)(psinfo.pr_fname, sizeof(psinfo.pr_fname), True);
1687 VG_(client_cmd_and_args)(psinfo.pr_psargs, sizeof(psinfo.pr_psargs));
1688
1689 Addr *ptr = (Addr *) VG_(get_initial_client_SP)();
1690 psinfo.pr_argc = *ptr++;
1691 psinfo.pr_argv = (Addr) ptr;
1692
1693 sres = VG_(do_syscall4)(SYS_pwrite, VG_(cl_psinfo_fd),
1694 (UWord) &psinfo, sizeof(psinfo), 0);
1695 if (sr_isError(sres)) {
1696 SET_STATUS_from_SysRes(sres);
1697 return True;
1698 }
1699
1700 sres = VG_(dup)(VG_(cl_psinfo_fd));
1701 SET_STATUS_from_SysRes(sres);
1702 if (!sr_isError(sres)) {
1703 OffT off = VG_(lseek)(sr_Res(sres), 0, VKI_SEEK_SET);
1704 if (off < 0)
1705 SET_STATUS_Failure(VKI_EMFILE);
1706 }
1707
1708 return True;
1709}
1710
iraisr23e68ca2015-08-14 20:50:11 +00001711#if defined(SOLARIS_PROC_CMDLINE)
1712/* Handles the case where the open is of /proc/self/cmdline or
1713 /proc/<pid>/cmdline. Just give it a copy of VG_(cl_cmdline_fd) for the
1714 fake file we cooked up at startup (in m_main). Also, seek the
1715 cloned fd back to the start. */
1716static Bool handle_cmdline_open(SyscallStatus *status, const HChar *filename)
1717{
1718 if (!ML_(safe_to_deref)((const void *) filename, 1))
1719 return False;
1720
1721 HChar name[VKI_PATH_MAX]; // large enough
1722 VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
1723
1724 if (!VG_STREQ(filename, name) && !VG_STREQ(filename, "/proc/self/cmdline"))
1725 return False;
1726
1727 SysRes sres = VG_(dup)(VG_(cl_cmdline_fd));
1728 SET_STATUS_from_SysRes(sres);
1729 if (!sr_isError(sres)) {
1730 OffT off = VG_(lseek)(sr_Res(sres), 0, VKI_SEEK_SET);
1731 if (off < 0)
1732 SET_STATUS_Failure(VKI_EMFILE);
1733 }
1734
1735 return True;
1736}
1737#endif /* SOLARIS_PROC_CMDLINE */
1738
1739
sewardj8eb8bab2015-07-21 14:44:28 +00001740#if defined(SOLARIS_OLD_SYSCALLS)
1741PRE(sys_open)
1742{
1743 /* int open(const char *filename, int flags);
1744 int open(const char *filename, int flags, mode_t mode); */
1745
1746 if (ARG2 & VKI_O_CREAT) {
1747 /* 3-arg version */
1748 PRINT("sys_open ( %#lx(%s), %ld, %ld )", ARG1, (HChar *) ARG1,
florianb26101c2015-08-08 21:45:33 +00001749 SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00001750 PRE_REG_READ3(long, "open", const char *, filename,
1751 int, flags, vki_mode_t, mode);
1752 } else {
1753 /* 2-arg version */
florianb26101c2015-08-08 21:45:33 +00001754 PRINT("sys_open ( %#lx(%s), %ld )", ARG1, (HChar *) ARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00001755 PRE_REG_READ2(long, "open", const char *, filename, int, flags);
1756 }
1757
1758 PRE_MEM_RASCIIZ("open(filename)", ARG1);
1759
1760 if (ML_(handle_auxv_open)(status, (const HChar*)ARG1, ARG2))
1761 return;
1762
1763 if (handle_psinfo_open(status, False /*use_openat*/, (const HChar*)ARG1, 0,
1764 ARG2, ARG3))
1765 return;
1766
1767 *flags |= SfMayBlock;
1768}
1769
1770POST(sys_open)
1771{
1772 if (!ML_(fd_allowed)(RES, "open", tid, True)) {
1773 VG_(close)(RES);
1774 SET_STATUS_Failure(VKI_EMFILE);
1775 } else if (VG_(clo_track_fds))
1776 ML_(record_fd_open_with_given_name)(tid, RES, (HChar *) ARG1);
1777}
1778#endif /* SOLARIS_OLD_SYSCALLS */
1779
1780PRE(sys_close)
1781{
1782 WRAPPER_PRE_NAME(generic, sys_close)(tid, layout, arrghs, status,
1783 flags);
1784}
1785
1786POST(sys_close)
1787{
1788 WRAPPER_POST_NAME(generic, sys_close)(tid, arrghs, status);
Elliott Hughesa0664b92017-04-18 17:46:52 -07001789 door_record_revoke(tid, ARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00001790 /* Possibly an explicitly open'ed client door fd was just closed.
1791 Generic sys_close wrapper calls this only if VG_(clo_track_fds) = True. */
1792 if (!VG_(clo_track_fds))
1793 ML_(record_fd_close)(ARG1);
1794}
1795
1796PRE(sys_linkat)
1797{
1798 /* int linkat(int fd1, const char *path1, int fd2,
1799 const char *path2, int flag);
1800 */
1801
1802 /* Interpret the first and third arguments as 32-bit values even on 64-bit
1803 architecture. This is different from Linux, for example, where glibc
1804 sign-extends them. */
1805 Int fd1 = (Int) ARG1;
1806 Int fd2 = (Int) ARG3;
1807
1808 PRINT("sys_linkat ( %d, %#lx(%s), %d, %#lx(%s), %ld )",
florianb26101c2015-08-08 21:45:33 +00001809 fd1, ARG2, (HChar *) ARG2, fd2, ARG4, (HChar *) ARG4, SARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00001810 PRE_REG_READ5(long, "linkat", int, fd1, const char *, path1,
1811 int, fd2, const char *, path2, int, flags);
1812 PRE_MEM_RASCIIZ("linkat(path1)", ARG2);
1813 PRE_MEM_RASCIIZ("linkat(path2)", ARG4);
1814
1815 /* Be strict but ignore fd1/fd2 for absolute path1/path2. */
1816 if (fd1 != VKI_AT_FDCWD
1817 && ML_(safe_to_deref)((void *) ARG2, 1)
1818 && ((HChar *) ARG2)[0] != '/'
1819 && !ML_(fd_allowed)(fd1, "linkat", tid, False)) {
1820 SET_STATUS_Failure(VKI_EBADF);
1821 }
1822 if (fd2 != VKI_AT_FDCWD
1823 && ML_(safe_to_deref)((void *) ARG4, 1)
1824 && ((HChar *) ARG4)[0] != '/'
1825 && !ML_(fd_allowed)(fd2, "linkat", tid, False)) {
1826 SET_STATUS_Failure(VKI_EBADF);
1827 }
1828
1829 *flags |= SfMayBlock;
1830}
1831
1832PRE(sys_symlinkat)
1833{
1834 /* int symlinkat(const char *path1, int fd, const char *path2); */
1835
1836 /* Interpret the second argument as 32-bit value even on 64-bit architecture.
1837 This is different from Linux, for example, where glibc sign-extends it. */
1838 Int fd = (Int) ARG2;
1839
1840 PRINT("sys_symlinkat ( %#lx(%s), %d, %#lx(%s) )",
1841 ARG1, (HChar *) ARG1, fd, ARG3, (HChar *) ARG3);
1842 PRE_REG_READ3(long, "symlinkat", const char *, path1, int, fd,
1843 const char *, path2);
1844 PRE_MEM_RASCIIZ("symlinkat(path1)", ARG1);
1845 PRE_MEM_RASCIIZ("symlinkat(path2)", ARG3);
1846
1847 /* Be strict but ignore fd for absolute path2. */
1848 if (fd != VKI_AT_FDCWD
1849 && ML_(safe_to_deref)((void *) ARG3, 1)
1850 && ((HChar *) ARG3)[0] != '/'
1851 && !ML_(fd_allowed)(fd, "symlinkat", tid, False))
1852 SET_STATUS_Failure(VKI_EBADF);
1853
1854 *flags |= SfMayBlock;
1855}
1856
1857PRE(sys_time)
1858{
1859 /* time_t time(); */
1860 PRINT("sys_time ( )");
1861 PRE_REG_READ0(long, "time");
1862}
1863
iraisr1c628f32015-08-20 20:25:19 +00001864/* Data segment for brk (heap). It is an expandable anonymous mapping
1865 abutting a 1-page reservation. The data segment starts at VG_(brk_base)
1866 and runs up to VG_(brk_limit). None of these two values have to be
iraisrbcfaeed2015-08-22 22:08:43 +00001867 page-aligned.
1868 Initial data segment is established (see initimg-solaris.c for rationale):
1869 - directly during client program image initialization,
1870 - or on demand when the executed program is the runtime linker itself,
1871 after it has loaded its target dynamic executable (see PRE(sys_mmapobj)),
1872 or when the first brk() syscall is made.
1873
iraisr1c628f32015-08-20 20:25:19 +00001874 Notable facts:
sewardj8eb8bab2015-07-21 14:44:28 +00001875 - VG_(brk_base) is not page aligned; does not move
1876 - VG_(brk_limit) moves between [VG_(brk_base), data segment end]
1877 - data segment end is always page aligned
1878 - right after data segment end is 1-page reservation
1879
iraisr1c628f32015-08-20 20:25:19 +00001880 | heap | 1 page
sewardj8eb8bab2015-07-21 14:44:28 +00001881 +------+------+--------------+-------+
1882 | BSS | anon | anon | resvn |
1883 +------+------+--------------+-------+
1884
1885 ^ ^ ^ ^
1886 | | | |
1887 | | | data segment end
1888 | | VG_(brk_limit) -- no alignment constraint
1889 | brk_base_pgup -- page aligned
1890 VG_(brk_base) -- not page aligned -- does not move
1891
1892 Because VG_(brk_base) is not page-aligned and is initially located within
iraisr1c628f32015-08-20 20:25:19 +00001893 pre-established BSS (data) segment, special care has to be taken in the code
1894 below to handle this feature.
1895
1896 Reservation segment is used to protect the data segment merging with
1897 a pre-existing segment. This should be no problem because address space
1898 manager ensures that requests for client address space are satisfied from
1899 the highest available addresses. However when memory is low, data segment
1900 can meet with mmap'ed objects and the reservation segment separates these.
1901 The page that contains VG_(brk_base) is already allocated by the program's
1902 loaded data segment. The brk syscall wrapper handles this special case. */
1903
iraisrbcfaeed2015-08-22 22:08:43 +00001904static Bool brk_segment_established = False;
1905
iraisr1c628f32015-08-20 20:25:19 +00001906/* Establishes initial data segment for brk (heap). */
iraisrbcfaeed2015-08-22 22:08:43 +00001907Bool VG_(setup_client_dataseg)(void)
iraisr1c628f32015-08-20 20:25:19 +00001908{
iraisrbcfaeed2015-08-22 22:08:43 +00001909 /* Segment size is initially at least 1 MB and at most 8 MB. */
1910 SizeT m1 = 1024 * 1024;
1911 SizeT m8 = 8 * m1;
1912 SizeT initial_size = VG_(client_rlimit_data).rlim_cur;
1913 VG_(debugLog)(1, "syswrap-solaris", "Setup client data (brk) segment "
1914 "at %#lx\n", VG_(brk_base));
1915 if (initial_size < m1)
1916 initial_size = m1;
1917 if (initial_size > m8)
1918 initial_size = m8;
1919 initial_size = VG_PGROUNDUP(initial_size);
1920
iraisr1c628f32015-08-20 20:25:19 +00001921 Addr anon_start = VG_PGROUNDUP(VG_(brk_base));
1922 SizeT anon_size = VG_PGROUNDUP(initial_size);
1923 Addr resvn_start = anon_start + anon_size;
1924 SizeT resvn_size = VKI_PAGE_SIZE;
1925
1926 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
1927 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
1928 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
1929 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
1930 vg_assert(VG_(brk_base) == VG_(brk_limit));
1931
1932 /* Find the loaded data segment and remember its protection. */
1933 const NSegment *seg = VG_(am_find_nsegment)(VG_(brk_base) - 1);
1934 vg_assert(seg != NULL);
1935 UInt prot = (seg->hasR ? VKI_PROT_READ : 0)
1936 | (seg->hasW ? VKI_PROT_WRITE : 0)
1937 | (seg->hasX ? VKI_PROT_EXEC : 0);
1938
1939 /* Try to create the data segment and associated reservation where
1940 VG_(brk_base) says. */
1941 Bool ok = VG_(am_create_reservation)(resvn_start, resvn_size, SmLower,
1942 anon_size);
1943 if (!ok) {
1944 /* That didn't work, we're hosed. */
1945 return False;
1946 }
1947
1948 /* Map the data segment. */
1949 SysRes sres = VG_(am_mmap_anon_fixed_client)(anon_start, anon_size, prot);
1950 vg_assert(!sr_isError(sres));
1951 vg_assert(sr_Res(sres) == anon_start);
1952
iraisrbcfaeed2015-08-22 22:08:43 +00001953 brk_segment_established = True;
iraisr1c628f32015-08-20 20:25:19 +00001954 return True;
1955}
1956
iraisrbcfaeed2015-08-22 22:08:43 +00001957/* Tell the tool about the client data segment and then kill it which will
1958 make it initially inaccessible/unaddressable. */
1959void VG_(track_client_dataseg)(ThreadId tid)
1960{
1961 const NSegment *seg = VG_(am_find_nsegment)(VG_PGROUNDUP(VG_(brk_base)));
1962 vg_assert(seg != NULL);
1963 vg_assert(seg->kind == SkAnonC);
1964
1965 VG_TRACK(new_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base), tid);
1966 VG_TRACK(die_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base));
1967}
sewardj8eb8bab2015-07-21 14:44:28 +00001968
Elliott Hughesed398002017-06-21 14:41:24 -07001969static void PRINTF_CHECK(1, 2)
1970possibly_complain_brk(const HChar *format, ...)
1971{
1972 static Bool alreadyComplained = False;
1973 if (!alreadyComplained) {
1974 alreadyComplained = True;
1975 if (VG_(clo_verbosity) > 0) {
1976 va_list vargs;
1977 va_start(vargs, format);
1978 VG_(vmessage)(Vg_UserMsg, format, vargs);
1979 va_end(vargs);
1980 VG_(umsg)("(See section Limitations in the user manual.)\n");
1981 VG_(umsg)("NOTE: further instances of this message will not be "
1982 "shown.\n");
1983 }
1984 }
1985}
1986
sewardj8eb8bab2015-07-21 14:44:28 +00001987PRE(sys_brk)
1988{
1989 /* unsigned long brk(caddr_t end_data_segment); */
1990 /* The Solaris kernel returns 0 on success.
1991 In addition to this, brk(0) returns current data segment end. This is
1992 very different from the Linux kernel, for example. */
1993
1994 Addr old_brk_limit = VG_(brk_limit);
1995 /* If VG_(brk_base) is page-aligned then old_brk_base_pgup is equal to
1996 VG_(brk_base). */
1997 Addr old_brk_base_pgup = VG_PGROUNDUP(VG_(brk_base));
1998 Addr new_brk = ARG1;
1999 const NSegment *seg, *seg2;
2000
2001 PRINT("sys_brk ( %#lx )", ARG1);
2002 PRE_REG_READ1(unsigned long, "brk", vki_caddr_t, end_data_segment);
2003
iraisr1c628f32015-08-20 20:25:19 +00002004 if (new_brk == 0) {
sewardj8eb8bab2015-07-21 14:44:28 +00002005 /* brk(0) - specific to Solaris 11 only. */
2006 SET_STATUS_Success(old_brk_limit);
2007 return;
2008 }
2009
2010 /* Handle some trivial cases. */
2011 if (new_brk == old_brk_limit) {
2012 SET_STATUS_Success(0);
2013 return;
2014 }
2015 if (new_brk < VG_(brk_base)) {
2016 /* Clearly impossible. */
2017 SET_STATUS_Failure(VKI_ENOMEM);
2018 return;
2019 }
2020 if (new_brk - VG_(brk_base) > VG_(client_rlimit_data).rlim_cur) {
2021 SET_STATUS_Failure(VKI_ENOMEM);
2022 return;
2023 }
2024
iraisrbcfaeed2015-08-22 22:08:43 +00002025 /* The brk base and limit must have been already set. */
2026 vg_assert(VG_(brk_base) != -1);
2027 vg_assert(VG_(brk_limit) != -1);
2028
iraisr1c628f32015-08-20 20:25:19 +00002029 if (!brk_segment_established) {
2030 /* Stay sane (because there should have been no brk activity yet). */
2031 vg_assert(VG_(brk_base) == VG_(brk_limit));
2032
iraisrbcfaeed2015-08-22 22:08:43 +00002033 if (!VG_(setup_client_dataseg)()) {
Elliott Hughesed398002017-06-21 14:41:24 -07002034 possibly_complain_brk("Cannot map memory to initialize brk segment in "
2035 "thread #%d at %#lx\n", tid, VG_(brk_base));
iraisr1c628f32015-08-20 20:25:19 +00002036 SET_STATUS_Failure(VKI_ENOMEM);
2037 return;
2038 }
2039
iraisrbcfaeed2015-08-22 22:08:43 +00002040 VG_(track_client_dataseg)(tid);
iraisr1c628f32015-08-20 20:25:19 +00002041 }
2042
sewardj8eb8bab2015-07-21 14:44:28 +00002043 if (new_brk < old_brk_limit) {
2044 /* Shrinking the data segment. Be lazy and don't munmap the excess
2045 area. */
2046 if (old_brk_limit > old_brk_base_pgup) {
2047 /* Calculate new local brk (=MAX(new_brk, old_brk_base_pgup)). */
2048 Addr new_brk_local;
2049 if (new_brk < old_brk_base_pgup)
2050 new_brk_local = old_brk_base_pgup;
2051 else
2052 new_brk_local = new_brk;
2053
2054 /* Find a segment at the beginning and at the end of the shrinked
2055 range. */
2056 seg = VG_(am_find_nsegment)(new_brk_local);
2057 seg2 = VG_(am_find_nsegment)(old_brk_limit - 1);
2058 vg_assert(seg);
2059 vg_assert(seg->kind == SkAnonC);
2060 vg_assert(seg2);
2061 vg_assert(seg == seg2);
2062
2063 /* Discard any translations and zero-out the area. */
2064 if (seg->hasT)
2065 VG_(discard_translations)(new_brk_local,
2066 old_brk_limit - new_brk_local,
2067 "do_brk(shrink)");
2068 /* Since we're being lazy and not unmapping pages, we have to zero out
2069 the area, so that if the area later comes back into circulation, it
2070 will be filled with zeroes, as if it really had been unmapped and
2071 later remapped. Be a bit paranoid and try hard to ensure we're not
2072 going to segfault by doing the write - check that segment is
2073 writable. */
2074 if (seg->hasW)
2075 VG_(memset)((void*)new_brk_local, 0, old_brk_limit - new_brk_local);
2076 }
2077
2078 /* Fixup code if the VG_(brk_base) is not page-aligned. */
2079 if (new_brk < old_brk_base_pgup) {
2080 /* Calculate old local brk (=MIN(old_brk_limit, old_brk_base_up)). */
2081 Addr old_brk_local;
2082 if (old_brk_limit < old_brk_base_pgup)
2083 old_brk_local = old_brk_limit;
2084 else
2085 old_brk_local = old_brk_base_pgup;
2086
2087 /* Find a segment at the beginning and at the end of the shrinked
2088 range. */
2089 seg = VG_(am_find_nsegment)(new_brk);
2090 seg2 = VG_(am_find_nsegment)(old_brk_local - 1);
2091 vg_assert(seg);
2092 vg_assert(seg2);
2093 vg_assert(seg == seg2);
2094
2095 /* Discard any translations and zero-out the area. */
2096 if (seg->hasT)
2097 VG_(discard_translations)(new_brk, old_brk_local - new_brk,
2098 "do_brk(shrink)");
2099 if (seg->hasW)
2100 VG_(memset)((void*)new_brk, 0, old_brk_local - new_brk);
2101 }
2102
2103 /* We are done, update VG_(brk_limit), tell the tool about the changes,
2104 and leave. */
2105 VG_(brk_limit) = new_brk;
2106 VG_TRACK(die_mem_brk, new_brk, old_brk_limit - new_brk);
2107 SET_STATUS_Success(0);
2108 return;
2109 }
2110
2111 /* We are expanding the brk segment. */
2112
2113 /* Fixup code if the VG_(brk_base) is not page-aligned. */
2114 if (old_brk_limit < old_brk_base_pgup) {
2115 /* Calculate new local brk (=MIN(new_brk, old_brk_base_pgup)). */
2116 Addr new_brk_local;
2117 if (new_brk < old_brk_base_pgup)
2118 new_brk_local = new_brk;
2119 else
2120 new_brk_local = old_brk_base_pgup;
2121
2122 /* Find a segment at the beginning and at the end of the expanded
2123 range. */
2124 seg = VG_(am_find_nsegment)(old_brk_limit);
2125 seg2 = VG_(am_find_nsegment)(new_brk_local - 1);
2126 vg_assert(seg);
2127 vg_assert(seg2);
2128 vg_assert(seg == seg2);
2129
2130 /* Nothing else to do. */
2131 }
2132
2133 if (new_brk > old_brk_base_pgup) {
2134 /* Calculate old local brk (=MAX(old_brk_limit, old_brk_base_pgup)). */
2135 Addr old_brk_local;
2136 if (old_brk_limit < old_brk_base_pgup)
2137 old_brk_local = old_brk_base_pgup;
2138 else
2139 old_brk_local = old_brk_limit;
2140
2141 /* Find a segment at the beginning of the expanded range. */
2142 if (old_brk_local > old_brk_base_pgup)
2143 seg = VG_(am_find_nsegment)(old_brk_local - 1);
2144 else
2145 seg = VG_(am_find_nsegment)(old_brk_local);
2146 vg_assert(seg);
2147 vg_assert(seg->kind == SkAnonC);
2148
2149 /* Find the 1-page reservation segment. */
2150 seg2 = VG_(am_next_nsegment)(seg, True/*forwards*/);
2151 vg_assert(seg2);
2152 vg_assert(seg2->kind == SkResvn);
2153 vg_assert(seg->end + 1 == seg2->start);
2154 vg_assert(seg2->end - seg2->start + 1 == VKI_PAGE_SIZE);
2155
2156 if (new_brk <= seg2->start) {
2157 /* Still fits within the existing anon segment, nothing to do. */
2158 } else {
2159 /* Data segment limit was already checked. */
2160 Addr anon_start = seg->end + 1;
2161 Addr resvn_start = VG_PGROUNDUP(new_brk);
2162 SizeT anon_size = resvn_start - anon_start;
2163 SizeT resvn_size = VKI_PAGE_SIZE;
2164 SysRes sres;
2165
2166 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
2167 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
2168 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
2169 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
2170 vg_assert(anon_size > 0);
2171
2172 /* Address space manager checks for free address space for us;
2173 reservation would not be otherwise created. */
2174 Bool ok = VG_(am_create_reservation)(resvn_start, resvn_size, SmLower,
2175 anon_size);
2176 if (!ok) {
Elliott Hughesed398002017-06-21 14:41:24 -07002177 possibly_complain_brk("brk segment overflow in thread #%d: can not "
2178 "grow to %#lx\n", tid, new_brk);
sewardj8eb8bab2015-07-21 14:44:28 +00002179 SET_STATUS_Failure(VKI_ENOMEM);
2180 return;
2181 }
2182
2183 /* Establish protection from the existing segment. */
2184 UInt prot = (seg->hasR ? VKI_PROT_READ : 0)
2185 | (seg->hasW ? VKI_PROT_WRITE : 0)
2186 | (seg->hasX ? VKI_PROT_EXEC : 0);
2187
2188 /* Address space manager will merge old and new data segments. */
2189 sres = VG_(am_mmap_anon_fixed_client)(anon_start, anon_size, prot);
2190 if (sr_isError(sres)) {
Elliott Hughesed398002017-06-21 14:41:24 -07002191 possibly_complain_brk("Cannot map memory to grow brk segment in "
2192 "thread #%d to %#lx\n", tid, new_brk);
sewardj8eb8bab2015-07-21 14:44:28 +00002193 SET_STATUS_Failure(VKI_ENOMEM);
2194 return;
2195 }
2196 vg_assert(sr_Res(sres) == anon_start);
2197
2198 seg = VG_(am_find_nsegment)(old_brk_base_pgup);
2199 seg2 = VG_(am_find_nsegment)(VG_PGROUNDUP(new_brk) - 1);
2200 vg_assert(seg);
2201 vg_assert(seg2);
2202 vg_assert(seg == seg2);
2203 vg_assert(new_brk <= seg->end + 1);
2204 }
2205 }
2206
2207 /* We are done, update VG_(brk_limit), tell the tool about the changes, and
2208 leave. */
2209 VG_(brk_limit) = new_brk;
2210 VG_TRACK(new_mem_brk, old_brk_limit, new_brk - old_brk_limit, tid);
2211 SET_STATUS_Success(0);
2212}
2213
2214PRE(sys_stat)
2215{
2216 /* int stat(const char *path, struct stat *buf); */
2217 /* Note: We could use here the sys_newstat generic wrapper, but the 'new'
2218 in its name is rather confusing in the Solaris context, thus we provide
2219 our own wrapper. */
2220 PRINT("sys_stat ( %#lx(%s), %#lx )", ARG1, (HChar *) ARG1, ARG2);
2221 PRE_REG_READ2(long, "stat", const char *, path, struct stat *, buf);
2222
2223 PRE_MEM_RASCIIZ("stat(path)", ARG1);
2224 PRE_MEM_WRITE("stat(buf)", ARG2, sizeof(struct vki_stat));
2225}
2226
2227POST(sys_stat)
2228{
2229 POST_MEM_WRITE(ARG2, sizeof(struct vki_stat));
2230}
2231
2232PRE(sys_lseek)
2233{
2234 /* off_t lseek(int fildes, off_t offset, int whence); */
florianb26101c2015-08-08 21:45:33 +00002235 PRINT("sys_lseek ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00002236 PRE_REG_READ3(long, "lseek", int, fildes, vki_off_t, offset, int, whence);
2237
2238 /* Stay sane. */
2239 if (!ML_(fd_allowed)(ARG1, "lseek", tid, False))
2240 SET_STATUS_Failure(VKI_EBADF);
2241}
2242
2243PRE(sys_mount)
2244{
2245 /* int mount(const char *spec, const char *dir, int mflag, char *fstype,
2246 char *dataptr, int datalen, char *optptr, int optlen); */
2247 *flags |= SfMayBlock;
2248 if (ARG3 & VKI_MS_OPTIONSTR) {
2249 /* 8-argument mount */
2250 PRINT("sys_mount ( %#lx(%s), %#lx(%s), %ld, %#lx(%s), %#lx, %ld, "
florianb26101c2015-08-08 21:45:33 +00002251 "%#lx(%s), %ld )", ARG1, (HChar *) ARG1, ARG2, (HChar *) ARG2, SARG3,
2252 ARG4, (HChar *) ARG4, ARG5, ARG6, ARG7, (HChar *) ARG7, SARG8);
sewardj8eb8bab2015-07-21 14:44:28 +00002253 PRE_REG_READ8(long, "mount", const char *, spec, const char *, dir,
2254 int, mflag, char *, fstype, char *, dataptr, int, datalen,
2255 char *, optptr, int, optlen);
2256 }
2257 else if (ARG3 & VKI_MS_DATA) {
2258 /* 6-argument mount */
2259 PRINT("sys_mount ( %#lx(%s), %#lx(%s), %ld, %#lx(%s), %#lx, %ld )",
florianb26101c2015-08-08 21:45:33 +00002260 ARG1, (HChar *) ARG1, ARG2, (HChar *) ARG2, SARG3, ARG4,
2261 (HChar *) ARG4, ARG5, SARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00002262 PRE_REG_READ6(long, "mount", const char *, spec, const char *, dir,
2263 int, mflag, char *, fstype, char *, dataptr,
2264 int, datalen);
2265 }
2266 else {
2267 /* 4-argument mount */
2268 PRINT("sys_mount ( %#lx(%s), %#lx(%s), %ld, %#lx(%s) )", ARG1,
florianb26101c2015-08-08 21:45:33 +00002269 (HChar *) ARG1, ARG2, (HChar *) ARG2, SARG3, ARG4, (HChar *) ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002270 PRE_REG_READ4(long, "mount", const char *, spec, const char *, dir,
2271 int, mflag, char *, fstype);
2272 }
2273 if (ARG1)
2274 PRE_MEM_RASCIIZ("mount(spec)", ARG1);
2275 PRE_MEM_RASCIIZ("mount(dir)", ARG2);
2276 if (ARG4 && ARG4 >= 256) {
2277 /* If ARG4 < 256, then it's an index to a fs table in the kernel. */
2278 PRE_MEM_RASCIIZ("mount(fstype)", ARG4);
2279 }
2280 if (ARG3 & (VKI_MS_DATA | VKI_MS_OPTIONSTR)) {
2281 if (ARG5)
2282 PRE_MEM_READ("mount(dataptr)", ARG5, ARG6);
2283 if ((ARG3 & VKI_MS_OPTIONSTR) && ARG7) {
2284 /* in/out buffer */
2285 PRE_MEM_RASCIIZ("mount(optptr)", ARG7);
2286 PRE_MEM_WRITE("mount(optptr)", ARG7, ARG8);
2287 }
2288 }
2289}
2290
2291POST(sys_mount)
2292{
2293 if (ARG3 & VKI_MS_OPTIONSTR) {
2294 POST_MEM_WRITE(ARG7, VG_(strlen)((HChar*)ARG7) + 1);
2295 } else if (ARG3 & VKI_MS_DATA) {
2296 if ((ARG2) &&
2297 (ARG3 & MS_NOMNTTAB) &&
2298 (VG_STREQ((HChar *) ARG4, "namefs")) &&
2299 (ARG6 == sizeof(struct vki_namefd)) &&
2300 ML_(safe_to_deref)((void *) ARG5, ARG6)) {
2301 /* Most likely an fattach() call for a door file descriptor. */
Elliott Hughesa0664b92017-04-18 17:46:52 -07002302 door_record_server_fattach(((struct vki_namefd *) ARG5)->fd,
2303 (HChar *) ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00002304 }
2305 }
2306}
2307
2308PRE(sys_readlinkat)
2309{
2310 /* ssize_t readlinkat(int dfd, const char *path, char *buf,
2311 size_t bufsiz); */
2312 HChar name[30]; // large enough
2313 Word saved = SYSNO;
2314
2315 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
2316 This is different from Linux, for example, where glibc sign-extends it. */
2317 Int dfd = (Int) ARG1;
2318
florianb26101c2015-08-08 21:45:33 +00002319 PRINT("sys_readlinkat ( %d, %#lx(%s), %#lx, %ld )", dfd, ARG2,
2320 (HChar *) ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002321 PRE_REG_READ4(long, "readlinkat", int, dfd, const char *, path,
2322 char *, buf, int, bufsiz);
2323 PRE_MEM_RASCIIZ("readlinkat(path)", ARG2);
2324 PRE_MEM_WRITE("readlinkat(buf)", ARG3, ARG4);
2325
2326 /* Be strict but ignore dfd for absolute path. */
2327 if (dfd != VKI_AT_FDCWD
2328 && ML_(safe_to_deref)((void *) ARG2, 1)
2329 && ((HChar *) ARG2)[0] != '/'
2330 && !ML_(fd_allowed)(dfd, "readlinkat", tid, False)) {
2331 SET_STATUS_Failure(VKI_EBADF);
2332 return;
2333 }
2334
2335 /* Handle the case where readlinkat is looking at /proc/self/path/a.out or
2336 /proc/<pid>/path/a.out. */
2337 VG_(sprintf)(name, "/proc/%d/path/a.out", VG_(getpid)());
2338 if (ML_(safe_to_deref)((void*)ARG2, 1) &&
2339 (!VG_(strcmp)((HChar*)ARG2, name) ||
2340 !VG_(strcmp)((HChar*)ARG2, "/proc/self/path/a.out"))) {
2341 VG_(sprintf)(name, "/proc/self/path/%d", VG_(cl_exec_fd));
2342 SET_STATUS_from_SysRes(VG_(do_syscall4)(saved, dfd, (UWord)name, ARG3,
2343 ARG4));
2344 }
2345}
2346
2347POST(sys_readlinkat)
2348{
2349 POST_MEM_WRITE(ARG3, RES);
2350}
2351
2352PRE(sys_stime)
2353{
2354 /* Kernel: int stime(time_t time); */
2355 PRINT("sys_stime ( %ld )", ARG1);
2356 PRE_REG_READ1(long, "stime", vki_time_t, time);
2357}
2358
2359PRE(sys_fstat)
2360{
2361 /* int fstat(int fildes, struct stat *buf); */
2362 /* Note: We could use here the sys_newfstat generic wrapper, but the 'new'
2363 in its name is rather confusing in the Solaris context, thus we provide
2364 our own wrapper. */
florianb26101c2015-08-08 21:45:33 +00002365 PRINT("sys_fstat ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00002366 PRE_REG_READ2(long, "fstat", int, fildes, struct stat *, buf);
2367 PRE_MEM_WRITE("fstat(buf)", ARG2, sizeof(struct vki_stat));
2368
2369 /* Be strict. */
2370 if (!ML_(fd_allowed)(ARG1, "fstat", tid, False))
2371 SET_STATUS_Failure(VKI_EBADF);
2372}
2373
2374POST(sys_fstat)
2375{
2376 POST_MEM_WRITE(ARG2, sizeof(struct vki_stat));
2377}
2378
2379#if defined(SOLARIS_FREALPATHAT_SYSCALL)
2380PRE(sys_frealpathat)
2381{
2382 /* int frealpathat(int fd, char *path, char *buf, size_t buflen); */
2383
2384 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
2385 This is different from Linux, for example, where glibc sign-extends it. */
2386 Int fd = (Int) ARG1;
2387
florianb26101c2015-08-08 21:45:33 +00002388 PRINT("sys_frealpathat ( %d, %#lx(%s), %#lx, %lu )",
sewardj8eb8bab2015-07-21 14:44:28 +00002389 fd, ARG2, (HChar *) ARG2, ARG3, ARG4);
2390 PRE_REG_READ4(long, "frealpathat", int, fd, char *, path,
2391 char *, buf, vki_size_t, buflen);
2392 PRE_MEM_RASCIIZ("frealpathat(path)", ARG2);
2393 PRE_MEM_WRITE("frealpathat(buf)", ARG3, ARG4);
2394
2395 /* Be strict but ignore fd for absolute path. */
2396 if (fd != VKI_AT_FDCWD
2397 && ML_(safe_to_deref)((void *) ARG2, 1)
2398 && ((HChar *) ARG2)[0] != '/'
2399 && !ML_(fd_allowed)(fd, "frealpathat", tid, False))
2400 SET_STATUS_Failure(VKI_EBADF);
2401}
2402
2403POST(sys_frealpathat)
2404{
2405 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
2406}
2407#endif /* SOLARIS_FREALPATHAT_SYSCALL */
2408
2409PRE(sys_stty)
2410{
2411 /* int stty(int fd, const struct sgttyb *tty); */
florianb26101c2015-08-08 21:45:33 +00002412 PRINT("sys_stty ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00002413 PRE_REG_READ2(long, "stty", int, fd,
2414 const struct vki_sgttyb *, tty);
2415 PRE_MEM_READ("stty(tty)", ARG2, sizeof(struct vki_sgttyb));
2416
2417 /* Be strict. */
2418 if (!ML_(fd_allowed)(ARG1, "stty", tid, False))
2419 SET_STATUS_Failure(VKI_EBADF);
2420}
2421
2422PRE(sys_gtty)
2423{
2424 /* int gtty(int fd, struct sgttyb *tty); */
florianb26101c2015-08-08 21:45:33 +00002425 PRINT("sys_gtty ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00002426 PRE_REG_READ2(long, "gtty", int, fd, struct vki_sgttyb *, tty);
2427 PRE_MEM_WRITE("gtty(tty)", ARG2, sizeof(struct vki_sgttyb));
2428
2429 /* Be strict. */
2430 if (!ML_(fd_allowed)(ARG1, "gtty", tid, False))
2431 SET_STATUS_Failure(VKI_EBADF);
2432}
2433
2434POST(sys_gtty)
2435{
2436 POST_MEM_WRITE(ARG2, sizeof(struct vki_sgttyb));
2437}
2438
2439PRE(sys_pgrpsys)
2440{
2441 /* Kernel: int setpgrp(int flag, int pid, int pgid); */
2442 switch (ARG1 /*flag*/) {
2443 case 0:
2444 /* Libc: pid_t getpgrp(void); */
florianb26101c2015-08-08 21:45:33 +00002445 PRINT("sys_pgrpsys ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00002446 PRE_REG_READ1(long, SC2("pgrpsys", "getpgrp"), int, flag);
2447 break;
2448 case 1:
2449 /* Libc: pid_t setpgrp(void); */
florianb26101c2015-08-08 21:45:33 +00002450 PRINT("sys_pgrpsys ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00002451 PRE_REG_READ1(long, SC2("pgrpsys", "setpgrp"), int, flag);
2452 break;
2453 case 2:
2454 /* Libc: pid_t getsid(pid_t pid); */
florianb26101c2015-08-08 21:45:33 +00002455 PRINT("sys_pgrpsys ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00002456 PRE_REG_READ2(long, SC2("pgrpsys", "getsid"), int, flag,
2457 vki_pid_t, pid);
2458 break;
2459 case 3:
2460 /* Libc: pid_t setsid(void); */
florianb26101c2015-08-08 21:45:33 +00002461 PRINT("sys_pgrpsys ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00002462 PRE_REG_READ1(long, SC2("pgrpsys", "setsid"), int, flag);
2463 break;
2464 case 4:
2465 /* Libc: pid_t getpgid(pid_t pid); */
florianb26101c2015-08-08 21:45:33 +00002466 PRINT("sys_pgrpsys ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00002467 PRE_REG_READ2(long, SC2("pgrpsys", "getpgid"), int, flag,
2468 vki_pid_t, pid);
2469 break;
2470 case 5:
2471 /* Libc: int setpgid(pid_t pid, pid_t pgid); */
florianb26101c2015-08-08 21:45:33 +00002472 PRINT("sys_pgrpsys ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00002473 PRE_REG_READ3(long, SC2("pgrpsys", "setpgid"), int, flag,
2474 vki_pid_t, pid, vki_pid_t, pgid);
2475 break;
2476 default:
florianb26101c2015-08-08 21:45:33 +00002477 VG_(unimplemented)("Syswrap of the pgrpsys call with flag %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00002478 /*NOTREACHED*/
2479 break;
2480 }
2481}
2482
2483PRE(sys_pipe)
2484{
2485#if defined(SOLARIS_NEW_PIPE_SYSCALL)
2486 /* int pipe(int fildes[2], int flags); */
florianb26101c2015-08-08 21:45:33 +00002487 PRINT("sys_pipe ( %#lx, %ld )", ARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00002488 PRE_REG_READ2(long, "pipe", int *, fildes, int, flags);
2489 PRE_MEM_WRITE("pipe(fildes)", ARG1, 2 * sizeof(int));
2490#else
2491 /* longlong_t pipe(); */
2492 PRINT("sys_pipe ( )");
2493 PRE_REG_READ0(long, "pipe");
2494#endif /* SOLARIS_NEW_PIPE_SYSCALL */
2495}
2496
2497POST(sys_pipe)
2498{
2499 Int p0, p1;
2500
2501#if defined(SOLARIS_NEW_PIPE_SYSCALL)
2502 int *fds = (int*)ARG1;
2503 p0 = fds[0];
2504 p1 = fds[1];
2505 POST_MEM_WRITE(ARG1, 2 * sizeof(int));
2506#else
2507 p0 = RES;
2508 p1 = RESHI;
2509#endif /* SOLARIS_NEW_PIPE_SYSCALL */
2510
2511 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
2512 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
2513 VG_(close)(p0);
2514 VG_(close)(p1);
2515 SET_STATUS_Failure(VKI_EMFILE);
2516 }
2517 else if (VG_(clo_track_fds)) {
2518 ML_(record_fd_open_nameless)(tid, p0);
2519 ML_(record_fd_open_nameless)(tid, p1);
2520 }
2521}
2522
2523PRE(sys_faccessat)
2524{
2525 /* int faccessat(int fd, const char *path, int amode, int flag); */
2526
2527 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
2528 This is different from Linux, for example, where glibc sign-extends it. */
2529 Int fd = (Int) ARG1;
2530
2531 PRINT("sys_faccessat ( %d, %#lx(%s), %ld, %ld )", fd, ARG2,
florianb26101c2015-08-08 21:45:33 +00002532 (HChar *) ARG2, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002533 PRE_REG_READ4(long, "faccessat", int, fd, const char *, path,
2534 int, amode, int, flag);
2535 PRE_MEM_RASCIIZ("faccessat(path)", ARG2);
2536
2537 /* Be strict but ignore fd for absolute path. */
2538 if (fd != VKI_AT_FDCWD
2539 && ML_(safe_to_deref)((void *) ARG2, 1)
2540 && ((HChar *) ARG2)[0] != '/'
2541 && !ML_(fd_allowed)(fd, "faccessat", tid, False))
2542 SET_STATUS_Failure(VKI_EBADF);
2543}
2544
2545PRE(sys_mknodat)
2546{
2547 /* int mknodat(int fd, char *fname, mode_t fmode, dev_t dev); */
2548
2549 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
2550 This is different from Linux, for example, where glibc sign-extends it. */
2551 Int fd = (Int) ARG1;
2552
2553 PRINT("sys_mknodat ( %d, %#lx(%s), %ld, %ld )", fd, ARG2,
florianb26101c2015-08-08 21:45:33 +00002554 (HChar *) ARG2, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002555 PRE_REG_READ4(long, "mknodat", int, fd, const char *, fname,
2556 vki_mode_t, fmode, vki_dev_t, dev);
2557 PRE_MEM_RASCIIZ("mknodat(fname)", ARG2);
2558
2559 /* Be strict but ignore fd for absolute path. */
2560 if (fd != VKI_AT_FDCWD
2561 && ML_(safe_to_deref)((void *) ARG2, 1)
2562 && ((HChar *) ARG2)[0] != '/'
2563 && !ML_(fd_allowed)(fd, "mknodat", tid, False))
2564 SET_STATUS_Failure(VKI_EBADF);
2565
2566 *flags |= SfMayBlock;
2567}
2568
2569POST(sys_mknodat)
2570{
2571 if (!ML_(fd_allowed)(RES, "mknodat", tid, True)) {
2572 VG_(close)(RES);
2573 SET_STATUS_Failure(VKI_EMFILE);
2574 } else if (VG_(clo_track_fds))
2575 ML_(record_fd_open_with_given_name)(tid, RES, (HChar *) ARG2);
2576}
2577
2578PRE(sys_sysi86)
2579{
2580 /* int sysi86(int cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3); */
florianb26101c2015-08-08 21:45:33 +00002581 PRINT("sys_sysi86 ( %ld, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002582 PRE_REG_READ4(long, "sysi86", int, cmd, uintptr_t, arg1, uintptr_t, arg2,
2583 uintptr_t, arg3);
2584
2585 switch (ARG1 /*cmd*/) {
2586 case VKI_SI86FPSTART:
2587 PRE_MEM_WRITE("sysi86(fp_hw)", ARG2, sizeof(vki_uint_t));
2588 /* ARG3 is a desired x87 FCW value, ARG4 is a desired SSE MXCSR value.
2589 They are passed to the kernel but V will change them later anyway
2590 (this is a general Valgrind limitation described in the official
2591 documentation). */
2592 break;
2593 default:
florianb26101c2015-08-08 21:45:33 +00002594 VG_(unimplemented)("Syswrap of the sysi86 call with cmd %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00002595 /*NOTREACHED*/
2596 break;
2597 }
2598}
2599
2600POST(sys_sysi86)
2601{
2602 switch (ARG1 /*cmd*/) {
2603 case VKI_SI86FPSTART:
2604 POST_MEM_WRITE(ARG2, sizeof(vki_uint_t));
2605 break;
2606 default:
2607 vg_assert(0);
2608 break;
2609 }
2610}
2611
2612PRE(sys_shmsys)
2613{
2614 /* Kernel: uintptr_t shmsys(int opcode, uintptr_t a0, uintptr_t a1,
2615 uintptr_t a2, uintptr_t a3);
2616 */
2617 *flags |= SfMayBlock;
2618
2619 switch (ARG1 /*opcode*/) {
2620 case VKI_SHMAT:
2621 /* Libc: void *shmat(int shmid, const void *shmaddr, int shmflg); */
2622 PRINT("sys_shmsys ( %ld, %ld, %#lx, %ld )",
florianb26101c2015-08-08 21:45:33 +00002623 SARG1, SARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002624 PRE_REG_READ4(long, SC2("shmsys", "shmat"), int, opcode,
2625 int, shmid, const void *, shmaddr, int, shmflg);
2626
2627 UWord addr = ML_(generic_PRE_sys_shmat)(tid, ARG2, ARG3, ARG4);
2628 if (addr == 0)
2629 SET_STATUS_Failure(VKI_EINVAL);
2630 else
2631 ARG3 = addr;
2632 break;
2633
2634 case VKI_SHMCTL:
2635 /* Libc: int shmctl(int shmid, int cmd, struct shmid_ds *buf); */
2636 switch (ARG3 /* cmd */) {
2637 case VKI_SHM_LOCK:
florianb26101c2015-08-08 21:45:33 +00002638 PRINT("sys_shmsys ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00002639 PRE_REG_READ3(long, SC3("shmsys", "shmctl", "lock"),
2640 int, opcode, int, shmid, int, cmd);
2641 break;
2642 case VKI_SHM_UNLOCK:
florianb26101c2015-08-08 21:45:33 +00002643 PRINT("sys_shmsys ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00002644 PRE_REG_READ3(long, SC3("shmsys", "shmctl", "unlock"),
2645 int, opcode, int, shmid, int, cmd);
2646 break;
2647 case VKI_IPC_RMID:
florianb26101c2015-08-08 21:45:33 +00002648 PRINT("sys_shmsys ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00002649 PRE_REG_READ3(long, SC3("shmsys", "shmctl", "rmid"),
2650 int, opcode, int, shmid, int, cmd);
2651 break;
2652 case VKI_IPC_SET:
2653 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002654 SARG1, SARG2, SARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002655 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "set"),
2656 int, opcode, int, shmid, int, cmd,
2657 struct vki_shmid_ds *, buf);
2658
2659 struct vki_shmid_ds *buf = (struct vki_shmid_ds *) ARG4;
2660 PRE_FIELD_READ("shmsys(shmctl, ipc_set, buf->shm_perm.uid)",
2661 buf->shm_perm.uid);
2662 PRE_FIELD_READ("shmsys(shmctl, ipc_set, buf->shm_perm.gid)",
2663 buf->shm_perm.gid);
2664 PRE_FIELD_READ("shmsys(shmctl, ipc_set, buf->shm_perm.mode)",
2665 buf->shm_perm.mode);
2666 break;
2667 case VKI_IPC_STAT:
2668 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002669 SARG1, SARG2, SARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002670 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "stat"),
2671 int, opcode, int, shmid, int, cmd,
2672 struct vki_shmid_ds *, buf);
2673 PRE_MEM_WRITE("shmsys(shmctl, ipc_stat, buf)", ARG4,
2674 sizeof(struct vki_shmid_ds));
2675 break;
2676 case VKI_IPC_SET64:
2677 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002678 SARG1, SARG2, SARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002679 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "set64"),
2680 int, opcode, int, shmid, int, cmd,
2681 struct vki_shmid_ds64 *, buf);
2682
2683 struct vki_shmid_ds64 *buf64 = (struct vki_shmid_ds64 *) ARG4;
2684 PRE_FIELD_READ("shmsys(shmctl, ipc_set64, "
2685 "buf->shmx_perm.ipcx_uid)",
2686 buf64->shmx_perm.ipcx_uid);
2687 PRE_FIELD_READ("shmsys(shmctl, ipc_set64, "
2688 "buf->shmx_perm.ipcx_gid)",
2689 buf64->shmx_perm.ipcx_gid);
2690 PRE_FIELD_READ("shmsys(shmctl, ipc_set64, "
2691 "buf->shmx_perm.ipcx_mode)",
2692 buf64->shmx_perm.ipcx_mode);
2693 break;
2694 case VKI_IPC_STAT64:
2695 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002696 SARG1, SARG2, SARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002697 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "stat64"),
2698 int, opcode, int, shmid, int, cmd,
2699 struct vki_shmid_ds64 *, buf);
2700 PRE_MEM_WRITE("shmsys(shmctl, ipc_stat64, buf)", ARG4,
2701 sizeof(struct vki_shmid_ds64));
2702 break;
2703#if defined(SOLARIS_SHM_NEW)
2704 case VKI_IPC_XSTAT64:
2705 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002706 SARG1, SARG2, SARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002707 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "xstat64"),
2708 int, opcode, int, shmid, int, cmd,
2709 struct vki_shmid_ds64 *, buf);
2710 PRE_MEM_WRITE("shmsys(shmctl, ipc_xstat64, buf)", ARG4,
2711 sizeof(struct vki_shmid_xds64));
2712 break;
2713#endif /* SOLARIS_SHM_NEW */
2714 default:
2715 VG_(unimplemented)("Syswrap of the shmsys(shmctl) call with "
florianb26101c2015-08-08 21:45:33 +00002716 "cmd %ld.", SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00002717 /*NOTREACHED*/
2718 break;
2719 }
2720 break;
2721
2722 case VKI_SHMDT:
2723 /* Libc: int shmdt(const void *shmaddr); */
florianb26101c2015-08-08 21:45:33 +00002724 PRINT("sys_shmsys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00002725 PRE_REG_READ2(long, SC2("shmsys", "shmdt"), int, opcode,
2726 const void *, shmaddr);
2727
2728 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG2))
2729 SET_STATUS_Failure(VKI_EINVAL);
2730 break;
2731
2732 case VKI_SHMGET:
2733 /* Libc: int shmget(key_t key, size_t size, int shmflg); */
florianb26101c2015-08-08 21:45:33 +00002734 PRINT("sys_shmsys ( %ld, %ld, %lu, %ld )",
2735 SARG1, SARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002736 PRE_REG_READ4(long, SC2("shmsys", "shmget"), int, opcode,
2737 vki_key_t, key, vki_size_t, size, int, shmflg);
2738 break;
2739
2740 case VKI_SHMIDS:
2741 /* Libc: int shmids(int *buf, uint_t nids, uint_t *pnids); */
florianb26101c2015-08-08 21:45:33 +00002742 PRINT("sys_shmsys ( %ld, %#lx, %lu, %#lx )",
2743 SARG1, ARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002744 PRE_REG_READ4(long, SC2("shmsys", "shmids"), int, opcode,
2745 int *, buf, vki_uint_t, nids, vki_uint_t *, pnids);
2746
2747 PRE_MEM_WRITE("shmsys(shmids, buf)", ARG2, ARG3 * sizeof(int *));
2748 PRE_MEM_WRITE("shmsys(shmids, pnids)", ARG4, sizeof(vki_uint_t));
2749 break;
2750
2751#if defined(SOLARIS_SHM_NEW)
2752 case VKI_SHMADV:
2753 /* Libc: int shmadv(int shmid, uint_t cmd, uint_t *advice); */
florianb26101c2015-08-08 21:45:33 +00002754 PRINT("sys_shmsys ( %ld, %ld, %lu, %ld )",
2755 SARG1, SARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002756 PRE_REG_READ4(long, SC2("shmsys", "shmadv"), int, opcode,
2757 int, shmid, vki_uint_t, cmd, vki_uint_t *, advice);
2758
2759 switch (ARG3 /*cmd*/) {
2760 case VKI_SHM_ADV_GET:
2761 PRE_MEM_WRITE("shmsys(shmadv, advice)", ARG4,
2762 sizeof(vki_uint_t));
2763 break;
2764 case VKI_SHM_ADV_SET:
2765 PRE_MEM_READ("shmsys(shmadv, advice)", ARG4,
2766 sizeof(vki_uint_t));
2767 break;
2768 default:
2769 VG_(unimplemented)("Syswrap of the shmsys(shmadv) call with "
florianb26101c2015-08-08 21:45:33 +00002770 "cmd %lu.", ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00002771 /*NOTREACHED*/
2772 break;
2773 }
2774 break;
2775
2776 case VKI_SHMGET_OSM:
2777 /* Libc: int shmget_osm(key_t key, size_t size, int shmflg,
2778 size_t granule_sz);
2779 */
florianb26101c2015-08-08 21:45:33 +00002780 PRINT("sys_shmsys ( %ld, %ld, %lu, %ld, %lu )",
2781 SARG1, SARG2, ARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00002782 PRE_REG_READ5(long, SC2("shmsys", "shmget_osm"), int, opcode,
2783 vki_key_t, key, vki_size_t, size, int, shmflg,
2784 vki_size_t, granule_sz);
2785 break;
2786#endif /* SOLARIS_SHM_NEW */
2787
2788 default:
2789 VG_(unimplemented)("Syswrap of the shmsys call with opcode %ld.",
florianb26101c2015-08-08 21:45:33 +00002790 SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00002791 /*NOTREACHED*/
2792 break;
2793 }
2794}
2795
2796POST(sys_shmsys)
2797{
2798 switch (ARG1 /*opcode*/) {
2799 case VKI_SHMAT:
2800 ML_(generic_POST_sys_shmat)(tid, RES, ARG2, ARG3, ARG4);
2801 break;
2802
2803 case VKI_SHMCTL:
2804 switch (ARG3 /*cmd*/) {
2805 case VKI_SHM_LOCK:
2806 case VKI_SHM_UNLOCK:
2807 case VKI_IPC_RMID:
2808 case VKI_IPC_SET:
2809 break;
2810 case VKI_IPC_STAT:
2811 POST_MEM_WRITE(ARG4, sizeof(struct vki_shmid_ds));
2812 break;
2813 case VKI_IPC_SET64:
2814 break;
2815 case VKI_IPC_STAT64:
2816 POST_MEM_WRITE(ARG4, sizeof(struct vki_shmid_ds64));
2817 break;
2818#if defined(SOLARIS_SHM_NEW)
2819 case VKI_IPC_XSTAT64:
2820 POST_MEM_WRITE(ARG4, sizeof(struct vki_shmid_xds64));
2821 break;
2822#endif /* SOLARIS_SHM_NEW */
2823 default:
2824 vg_assert(0);
2825 break;
2826 }
2827 break;
2828
2829 case VKI_SHMDT:
2830 ML_(generic_POST_sys_shmdt)(tid, RES, ARG2);
2831 break;
2832
2833 case VKI_SHMGET:
2834 break;
2835
2836 case VKI_SHMIDS:
2837 {
2838 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
2839
2840 uint_t *pnids = (vki_uint_t *) ARG4;
2841 if (*pnids <= ARG3)
2842 POST_MEM_WRITE(ARG2, *pnids * sizeof(int *));
2843 }
2844 break;
2845
2846#if defined(SOLARIS_SHM_NEW)
2847 case VKI_SHMADV:
2848 switch (ARG3 /*cmd*/) {
2849 case VKI_SHM_ADV_GET:
2850 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
2851 break;
2852 case VKI_SHM_ADV_SET:
2853 break;
2854 default:
2855 vg_assert(0);
2856 break;
2857 }
2858 break;
2859
2860 case VKI_SHMGET_OSM:
2861 break;
2862#endif /* SOLARIS_SHM_NEW */
2863
2864 default:
2865 vg_assert(0);
2866 break;
2867 }
2868}
2869
2870PRE(sys_semsys)
2871{
2872 /* Kernel: int semsys(int opcode, uintptr_t a1, uintptr_t a2, uintptr_t a3,
2873 uintptr_t a4);
2874 */
2875 *flags |= SfMayBlock;
2876
2877 switch (ARG1 /*opcode*/) {
2878 case VKI_SEMCTL:
2879 /* Libc: int semctl(int semid, int semnum, int cmd...); */
2880 switch (ARG4) {
2881 case VKI_IPC_STAT:
2882 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002883 SARG1, SARG2, SARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00002884 PRE_REG_READ5(long, SC3("semsys", "semctl", "stat"), int, opcode,
2885 int, semid, int, semnum, int, cmd,
2886 struct vki_semid_ds *, arg);
2887 break;
2888 case VKI_IPC_SET:
2889 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002890 SARG1, SARG2, SARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00002891 PRE_REG_READ5(long, SC3("semsys", "semctl", "set"), int, opcode,
2892 int, semid, int, semnum, int, cmd,
2893 struct vki_semid_ds *, arg);
2894 break;
2895 case VKI_IPC_STAT64:
2896 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002897 SARG1, SARG2, SARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00002898 PRE_REG_READ5(long, SC3("semsys", "semctl", "stat64"), int, opcode,
2899 int, semid, int, semnum, int, cmd,
2900 struct vki_semid64_ds *, arg);
2901 break;
2902 case VKI_IPC_SET64:
2903 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002904 SARG1, SARG2, SARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00002905 PRE_REG_READ5(long, SC3("semsys", "semctl", "set64"), int, opcode,
2906 int, semid, int, semnum, int, cmd,
2907 struct vki_semid64_ds *, arg);
2908 break;
2909 case VKI_IPC_RMID:
florianb26101c2015-08-08 21:45:33 +00002910 PRINT("sys_semsys ( %ld, %ld, %ld )", SARG1, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002911 PRE_REG_READ3(long, SC3("semsys", "semctl", "rmid"), int, opcode,
2912 int, semid, int, cmd);
2913 break;
2914 case VKI_GETALL:
2915 PRINT("sys_semsys ( %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002916 SARG1, SARG2, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00002917 PRE_REG_READ4(long, SC3("semsys", "semctl", "getall"), int, opcode,
2918 int, semid, int, cmd, ushort_t *, arg);
2919 break;
2920 case VKI_SETALL:
2921 PRINT("sys_semsys ( %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002922 SARG1, SARG2, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00002923 PRE_REG_READ4(long, SC3("semsys", "semctl", "setall"), int, opcode,
2924 int, semid, int, cmd, ushort_t *, arg);
2925 break;
2926 case VKI_GETVAL:
2927 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )",
florianb26101c2015-08-08 21:45:33 +00002928 SARG1, SARG2, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002929 PRE_REG_READ4(long, SC3("semsys", "semctl", "getval"), int, opcode,
2930 int, semid, int, semnum, int, cmd);
2931 break;
2932 case VKI_SETVAL:
2933 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00002934 SARG1, SARG2, SARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00002935 PRE_REG_READ5(long, SC3("semsys", "semctl", "setval"), int, opcode,
2936 int, semid, int, semnum, int, cmd,
2937 union vki_semun *, arg);
2938 break;
2939 case VKI_GETPID:
2940 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )",
florianb26101c2015-08-08 21:45:33 +00002941 SARG1, SARG2, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002942 PRE_REG_READ4(long, SC3("semsys", "semctl", "getpid"), int, opcode,
2943 int, semid, int, semnum, int, cmd);
2944 break;
2945 case VKI_GETNCNT:
2946 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )",
florianb26101c2015-08-08 21:45:33 +00002947 SARG1, SARG2, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002948 PRE_REG_READ4(long, SC3("semsys", "semctl", "getncnt"),
2949 int, opcode, int, semid, int, semnum, int, cmd);
2950 break;
2951 case VKI_GETZCNT:
2952 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )",
florianb26101c2015-08-08 21:45:33 +00002953 SARG1, SARG2, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002954 PRE_REG_READ4(long, SC3("semsys", "semctl", "getzcnt"),
2955 int, opcode, int, semid, int, semnum, int, cmd);
2956 break;
2957 default:
2958 VG_(unimplemented)("Syswrap of the semsys(semctl) call "
florianb26101c2015-08-08 21:45:33 +00002959 "with cmd %ld.", SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002960 /*NOTREACHED*/
2961 break;
2962 }
2963 ML_(generic_PRE_sys_semctl)(tid, ARG2, ARG3, ARG4, ARG5);
2964 break;
2965 case VKI_SEMGET:
2966 /* Libc: int semget(key_t key, int nsems, int semflg); */
florianb26101c2015-08-08 21:45:33 +00002967 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )", SARG1, SARG2, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002968 PRE_REG_READ4(long, SC2("semsys", "semget"), int, opcode,
2969 vki_key_t, key, int, nsems, int, semflg);
2970 break;
2971 case VKI_SEMOP:
2972 /* Libc: int semop(int semid, struct sembuf *sops, size_t nsops); */
florianb26101c2015-08-08 21:45:33 +00002973 PRINT("sys_semsys ( %ld, %ld, %#lx, %lu )", SARG1, SARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002974 PRE_REG_READ4(long, SC2("semsys", "semop"), int, opcode, int, semid,
2975 struct vki_sembuf *, sops, vki_size_t, nsops);
2976 ML_(generic_PRE_sys_semop)(tid, ARG2, ARG3, ARG4);
2977 break;
2978 case VKI_SEMIDS:
2979 /* Libc: int semids(int *buf, uint_t nids, uint_t *pnids); */
florianb26101c2015-08-08 21:45:33 +00002980 PRINT("sys_semsys ( %ld, %#lx, %lu, %#lx )", SARG1, ARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00002981 PRE_REG_READ4(long, SC2("semsys", "semids"), int, opcode, int *, buf,
2982 vki_uint_t, nids, vki_uint_t *, pnids);
2983
2984 PRE_MEM_WRITE("semsys(semids, buf)", ARG2, ARG3 * sizeof(int *));
2985 PRE_MEM_WRITE("semsys(semids, pnids)", ARG4, sizeof(vki_uint_t));
2986 break;
2987 case VKI_SEMTIMEDOP:
2988 /* Libc: int semtimedop(int semid, struct sembuf *sops, size_t nsops,
2989 const struct timespec *timeout);
2990 */
florianb26101c2015-08-08 21:45:33 +00002991 PRINT("sys_semsys ( %ld, %ld, %#lx, %lu, %#lx )", SARG1, SARG2, ARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00002992 ARG4, ARG5);
2993 PRE_REG_READ5(long, SC2("semsys", "semtimedop"), int, opcode,
2994 int, semid, struct vki_sembuf *, sops, vki_size_t, nsops,
2995 struct vki_timespec *, timeout);
2996 ML_(generic_PRE_sys_semtimedop)(tid, ARG2, ARG3, ARG4, ARG5);
2997 break;
2998 default:
florianb26101c2015-08-08 21:45:33 +00002999 VG_(unimplemented)("Syswrap of the semsys call with opcode %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00003000 /*NOTREACHED*/
3001 break;
3002 }
3003}
3004
3005POST(sys_semsys)
3006{
3007 switch (ARG1 /*opcode*/) {
3008 case VKI_SEMCTL:
3009 ML_(generic_POST_sys_semctl)(tid, RES, ARG2, ARG3, ARG4, ARG5);
3010 break;
3011 case VKI_SEMGET:
3012 case VKI_SEMOP:
3013 break;
3014 case VKI_SEMIDS:
3015 {
3016 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
3017
3018 uint_t *pnids = (uint_t *)ARG4;
3019 if (*pnids <= ARG3)
3020 POST_MEM_WRITE(ARG2, *pnids * sizeof(int *));
3021 }
3022 break;
3023 case VKI_SEMTIMEDOP:
3024 break;
3025 default:
3026 vg_assert(0);
3027 break;
3028 }
3029}
3030
3031/* ---------------------------------------------------------------------
3032 ioctl wrappers
3033 ------------------------------------------------------------------ */
3034
3035PRE(sys_ioctl)
3036{
3037 /* int ioctl(int fildes, int request, ...); */
3038 *flags |= SfMayBlock;
3039
3040 /* Prevent sign extending the switch case values to 64-bits on 64-bits
3041 architectures. */
3042 Int cmd = (Int) ARG2;
3043
3044 switch (cmd /*request*/) {
3045 /* Handle 2-arg specially here (they do not use ARG3 at all). */
Elliott Hughesa0664b92017-04-18 17:46:52 -07003046 case VKI_DINFOIDENT:
sewardj8eb8bab2015-07-21 14:44:28 +00003047 case VKI_TIOCNOTTY:
3048 case VKI_TIOCSCTTY:
florianb26101c2015-08-08 21:45:33 +00003049 PRINT("sys_ioctl ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00003050 PRE_REG_READ2(long, "ioctl", int, fd, int, request);
3051 break;
3052 /* And now come the 3-arg ones. */
3053 default:
florianb26101c2015-08-08 21:45:33 +00003054 PRINT("sys_ioctl ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00003055 PRE_REG_READ3(long, "ioctl", int, fd, int, request, intptr_t, arg);
3056 break;
3057 }
3058
3059 switch (cmd /*request*/) {
3060 /* pools */
3061 case VKI_POOL_STATUSQ:
3062 PRE_MEM_WRITE("ioctl(POOL_STATUSQ)", ARG3, sizeof(vki_pool_status_t));
3063 break;
3064
3065 /* mntio */
Elliott Hughesa0664b92017-04-18 17:46:52 -07003066 case VKI_MNTIOC_GETEXTMNTENT:
3067 {
3068 PRE_MEM_READ("ioctl(MNTIOC_GETEXTMNTENT)",
3069 ARG3, sizeof(struct vki_mntentbuf));
3070
3071 struct vki_mntentbuf *embuf = (struct vki_mntentbuf *) ARG3;
3072 if (ML_(safe_to_deref(embuf, sizeof(*embuf)))) {
3073 PRE_MEM_WRITE("ioctl(MNTIOC_GETEXTMNTENT, embuf->mbuf_emp)",
3074 (Addr) embuf->mbuf_emp, sizeof(struct vki_extmnttab));
3075 PRE_MEM_WRITE("ioctl(MNTIOC_GETEXTMNTENT, embuf->mbuf_buf)",
3076 (Addr) embuf->mbuf_buf, embuf->mbuf_bufsize);
3077 }
3078 }
3079 break;
3080
sewardj8eb8bab2015-07-21 14:44:28 +00003081 case VKI_MNTIOC_GETMNTANY:
3082 {
3083 PRE_MEM_READ("ioctl(MNTIOC_GETMNTANY)",
3084 ARG3, sizeof(struct vki_mntentbuf));
3085
3086 struct vki_mntentbuf *embuf = (struct vki_mntentbuf *) ARG3;
3087 if (ML_(safe_to_deref(embuf, sizeof(*embuf)))) {
3088 PRE_MEM_READ("ioctl(MNTIOC_GETMNTANY, embuf->mbuf_emp)",
Elliott Hughesa0664b92017-04-18 17:46:52 -07003089 (Addr) embuf->mbuf_emp, sizeof(struct vki_mnttab));
sewardj8eb8bab2015-07-21 14:44:28 +00003090 PRE_MEM_WRITE("ioctl(MNTIOC_GETMNTANY, embuf->mbuf_buf)",
Elliott Hughesa0664b92017-04-18 17:46:52 -07003091 (Addr) embuf->mbuf_buf, embuf->mbuf_bufsize);
3092
3093 struct vki_mnttab *mnt = (struct vki_mnttab *) embuf->mbuf_emp;
sewardj8eb8bab2015-07-21 14:44:28 +00003094 if (ML_(safe_to_deref(mnt, sizeof(struct vki_mnttab)))) {
3095 if (mnt->mnt_special != NULL)
3096 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_special)",
3097 (Addr) mnt->mnt_special);
3098 if (mnt->mnt_mountp != NULL)
3099 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_mountp)",
3100 (Addr) mnt->mnt_mountp);
3101 if (mnt->mnt_fstype != NULL)
3102 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_fstype)",
3103 (Addr) mnt->mnt_fstype);
3104 if (mnt->mnt_mntopts != NULL)
3105 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_mntopts)",
3106 (Addr) mnt->mnt_mntopts);
3107 if (mnt->mnt_time != NULL)
3108 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_time)",
3109 (Addr) mnt->mnt_time);
3110 }
3111 }
3112 }
3113 break;
3114
3115 /* termio/termios */
3116 case VKI_TCGETA:
3117 PRE_MEM_WRITE("ioctl(TCGETA)", ARG3, sizeof(struct vki_termio));
3118 break;
3119 case VKI_TCGETS:
3120 PRE_MEM_WRITE("ioctl(TCGETS)", ARG3, sizeof(struct vki_termios));
3121 break;
3122 case VKI_TCSETS:
3123 PRE_MEM_READ("ioctl(TCSETS)", ARG3, sizeof(struct vki_termios));
3124 break;
3125 case VKI_TCSETSW:
3126 PRE_MEM_READ("ioctl(TCSETSW)", ARG3, sizeof(struct vki_termios));
3127 break;
3128 case VKI_TCSETSF:
3129 PRE_MEM_READ("ioctl(TCSETSF)", ARG3, sizeof(struct vki_termios));
3130 break;
3131 case VKI_TIOCGWINSZ:
3132 PRE_MEM_WRITE("ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize));
3133 break;
3134 case VKI_TIOCSWINSZ:
3135 PRE_MEM_READ("ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize));
3136 break;
3137 case VKI_TIOCGPGRP:
3138 PRE_MEM_WRITE("ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t));
3139 break;
3140 case VKI_TIOCSPGRP:
3141 PRE_MEM_READ("ioctl(TIOCSPGRP)", ARG3, sizeof(vki_pid_t));
3142 break;
3143 case VKI_TIOCGSID:
3144 PRE_MEM_WRITE("ioctl(TIOCGSID)", ARG3, sizeof(vki_pid_t));
3145 break;
3146 case VKI_TIOCNOTTY:
3147 case VKI_TIOCSCTTY:
3148 break;
3149
3150 /* STREAMS */
3151 case VKI_I_PUSH:
3152 PRE_MEM_RASCIIZ("ioctl(I_PUSH)", ARG3);
3153 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07003154 case VKI_I_FLUSH:
3155 break;
sewardj8eb8bab2015-07-21 14:44:28 +00003156 case VKI_I_STR:
3157 {
3158 PRE_MEM_READ("ioctl(I_STR)", ARG3, sizeof(struct vki_strioctl));
3159
3160 struct vki_strioctl *p = (struct vki_strioctl *) ARG3;
3161 if (ML_(safe_to_deref(p, sizeof(*p)))) {
3162 if ((p->ic_dp != NULL) && (p->ic_len > 0)) {
3163 PRE_MEM_READ("ioctl(I_STR, strioctl->ic_dp)",
3164 (Addr) p->ic_dp, p->ic_len);
3165 }
3166 }
3167 }
3168 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07003169 case VKI_I_FIND:
3170 PRE_MEM_RASCIIZ("ioctl(I_FIND)", ARG3);
3171 break;
sewardj8eb8bab2015-07-21 14:44:28 +00003172 case VKI_I_PEEK:
3173 {
3174 /* Try hard not to mark strpeek->*buf.len members as being read. */
3175 struct vki_strpeek *p = (struct vki_strpeek*)ARG3;
3176
3177 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->ctlbuf.maxlen)",
3178 p->ctlbuf.maxlen);
3179 PRE_FIELD_WRITE("ioctl(I_PEEK, strpeek->ctlbuf.len)",
3180 p->ctlbuf.len);
3181 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->ctlbuf.buf)",
3182 p->ctlbuf.buf);
3183 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->databuf.maxlen)",
3184 p->databuf.maxlen);
3185 PRE_FIELD_WRITE("ioctl(I_PEEK, strpeek->databuf.len)",
3186 p->databuf.len);
3187 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->databuf.buf)",
3188 p->databuf.buf);
3189 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->flags)", p->flags);
3190 /*PRE_FIELD_WRITE("ioctl(I_PEEK, strpeek->flags)", p->flags);*/
3191
3192 if (ML_(safe_to_deref(p, sizeof(*p)))) {
3193 if (p->ctlbuf.buf && p->ctlbuf.maxlen > 0)
3194 PRE_MEM_WRITE("ioctl(I_PEEK, strpeek->ctlbuf.buf)",
3195 (Addr)p->ctlbuf.buf, p->ctlbuf.maxlen);
3196 if (p->databuf.buf && p->databuf.maxlen > 0)
3197 PRE_MEM_WRITE("ioctl(I_PEEK, strpeek->databuf.buf)",
3198 (Addr)p->databuf.buf, p->databuf.maxlen);
3199 }
3200 }
3201 break;
3202 case VKI_I_CANPUT:
3203 break;
3204
3205 /* sockio */
iraisr2d20d8d2015-09-29 05:20:16 +00003206 case VKI_SIOCGIFCONF:
3207 {
3208 struct vki_ifconf *p = (struct vki_ifconf *) ARG3;
3209 PRE_FIELD_READ("ioctl(SIOCGIFCONF, ifconf->ifc_len)", p->ifc_len);
3210 PRE_FIELD_READ("ioctl(SIOCGIFCONF, ifconf->ifc_buf)", p->ifc_buf);
3211 if (ML_(safe_to_deref)(p, sizeof(*p))) {
3212 if ((p->ifc_buf != NULL) && (p->ifc_len > 0))
3213 PRE_MEM_WRITE("ioctl(SIOCGIFCONF, ifconf->ifc_buf)",
3214 (Addr) p->ifc_buf, p->ifc_len);
3215 }
3216 /* ifc_len gets also written to during SIOCGIFCONF ioctl. */
3217 }
3218 break;
3219 case VKI_SIOCGIFFLAGS:
3220 {
3221 struct vki_ifreq *p = (struct vki_ifreq *) ARG3;
3222 PRE_FIELD_READ("ioctl(SIOCGIFFLAGS, ifreq->ifr_name)", p->ifr_name);
3223 PRE_FIELD_WRITE("ioctl(SIOCGIFFLAGS, ifreq->ifr_flags)", p->ifr_flags);
3224 }
3225 break;
3226 case VKI_SIOCGIFNETMASK:
3227 {
3228 struct vki_ifreq *p = (struct vki_ifreq *) ARG3;
3229 PRE_FIELD_READ("ioctl(SIOCGIFFLAGS, ifreq->ifr_name)", p->ifr_name);
3230 PRE_FIELD_WRITE("ioctl(SIOCGIFFLAGS, ifreq->ifr_addr)", p->ifr_addr);
3231 }
3232 break;
3233 case VKI_SIOCGIFNUM:
3234 PRE_MEM_WRITE("ioctl(SIOCGIFNUM)", ARG3, sizeof(int));
3235 break;
iraisrf185f3c2015-09-29 14:23:51 +00003236 case VKI_SIOCGLIFBRDADDR:
3237 {
3238 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3239 PRE_FIELD_READ("ioctl(SIOCGLIFBRDADDR, lifreq->lifr_name)",
3240 p->lifr_name);
3241 PRE_FIELD_WRITE("ioctl(SIOCGLIFBRDADDR, lifreq->lifr_addr)",
3242 p->lifr_addr);
3243 }
3244 break;
3245 case VKI_SIOCGLIFCONF:
3246 {
3247 struct vki_lifconf *p = (struct vki_lifconf *) ARG3;
3248 PRE_FIELD_READ("ioctl(SIOCGLIFCONF, lifconf->lifc_len)", p->lifc_len);
3249 PRE_FIELD_READ("ioctl(SIOCGLIFCONF, lifconf->lifc_buf)", p->lifc_buf);
3250 PRE_FIELD_READ("ioctl(SIOCGLIFCONF, lifconf->lifc_family)",
3251 p->lifc_family);
3252 PRE_FIELD_READ("ioctl(SIOCGLIFCONF, lifconf->lifc_flags)",
3253 p->lifc_flags);
3254 if (ML_(safe_to_deref)(p, sizeof(*p))) {
3255 if ((p->lifc_buf != NULL) && (p->lifc_len > 0))
3256 PRE_MEM_WRITE("ioctl(SIOCGLIFCONF, lifconf->lifc_buf)",
3257 (Addr) p->lifc_buf, p->lifc_len);
3258 }
3259 /* lifc_len gets also written to during SIOCGLIFCONF ioctl. */
3260 }
3261 break;
3262 case VKI_SIOCGLIFFLAGS:
3263 {
3264 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3265 PRE_FIELD_READ("ioctl(SIOCGLIFFLAGS, lifreq->lifr_name)",
3266 p->lifr_name);
3267 PRE_FIELD_WRITE("ioctl(SIOCGLIFFLAGS, lifreq->lifr_flags)",
3268 p->lifr_flags);
3269 }
3270 break;
3271 case VKI_SIOCGLIFNETMASK:
3272 {
3273 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3274 PRE_FIELD_READ("ioctl(SIOCGLIFNETMASK, lifreq->lifr_name)",
3275 p->lifr_name);
3276 PRE_FIELD_WRITE("ioctl(SIOCGLIFNETMASK, lifreq->lifr_addr)",
3277 p->lifr_addr);
3278 }
3279 break;
sewardj8eb8bab2015-07-21 14:44:28 +00003280 case VKI_SIOCGLIFNUM:
3281 {
3282 struct vki_lifnum *p = (struct vki_lifnum *) ARG3;
3283 PRE_FIELD_READ("ioctl(SIOCGLIFNUM, lifn->lifn_family)",
3284 p->lifn_family);
3285 PRE_FIELD_READ("ioctl(SIOCGLIFNUM, lifn->lifn_flags)",
3286 p->lifn_flags);
3287 PRE_FIELD_WRITE("ioctl(SIOCGLIFNUM, lifn->lifn_count)",
3288 p->lifn_count);
3289 }
iraisr2d20d8d2015-09-29 05:20:16 +00003290 break;
sewardj8eb8bab2015-07-21 14:44:28 +00003291
3292 /* filio */
3293 case VKI_FIOSETOWN:
3294 PRE_MEM_READ("ioctl(FIOSETOWN)", ARG3, sizeof(vki_pid_t));
3295 break;
3296 case VKI_FIOGETOWN:
3297 PRE_MEM_WRITE("ioctl(FIOGETOWN)", ARG3, sizeof(vki_pid_t));
3298 break;
3299
3300 /* CRYPTO */
3301 case VKI_CRYPTO_GET_PROVIDER_LIST:
3302 {
3303 vki_crypto_get_provider_list_t *pl =
3304 (vki_crypto_get_provider_list_t *) ARG3;
3305 PRE_FIELD_READ("ioctl(CRYPTO_GET_PROVIDER_LIST, pl->pl_count)",
3306 pl->pl_count);
3307
3308 if (ML_(safe_to_deref)(pl, sizeof(*pl))) {
3309 PRE_MEM_WRITE("ioctl(CRYPTO_GET_PROVIDER_LIST)", ARG3,
3310 MAX(1, pl->pl_count) *
3311 sizeof(vki_crypto_get_provider_list_t));
3312 }
3313 /* Save the requested count to unused ARG4 below,
3314 when we know pre-handler succeeded.
3315 */
3316 }
3317 break;
3318
3319 /* dtrace */
3320 case VKI_DTRACEHIOC_REMOVE:
3321 break;
3322 case VKI_DTRACEHIOC_ADDDOF:
3323 {
3324 vki_dof_helper_t *dh = (vki_dof_helper_t *) ARG3;
3325 PRE_MEM_RASCIIZ("ioctl(DTRACEHIOC_ADDDOF, dh->dofhp_mod)",
3326 (Addr) dh->dofhp_mod);
3327 PRE_FIELD_READ("ioctl(DTRACEHIOC_ADDDOF, dh->dofhp_addr",
3328 dh->dofhp_addr);
3329 PRE_FIELD_READ("ioctl(DTRACEHIOC_ADDDOF, dh->dofhp_dof",
3330 dh->dofhp_dof);
3331 }
3332 break;
3333
Elliott Hughesa0664b92017-04-18 17:46:52 -07003334 /* devinfo */
3335 case VKI_DINFOUSRLD:
3336 /* We should do PRE_MEM_WRITE here but the question is for how many? */
3337 break;
3338 case VKI_DINFOIDENT:
3339 break;
3340
sewardj8eb8bab2015-07-21 14:44:28 +00003341 default:
3342 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
3343 break;
3344 }
3345
3346 /* Be strict. */
3347 if (!ML_(fd_allowed)(ARG1, "ioctl", tid, False)) {
3348 SET_STATUS_Failure(VKI_EBADF);
3349 } else if (ARG2 == VKI_CRYPTO_GET_PROVIDER_LIST) {
3350 /* Save the requested count to unused ARG4 now. */
3351 ARG4 = ARG3;
3352 }
3353}
3354
3355POST(sys_ioctl)
3356{
3357 /* Prevent sign extending the switch case values to 64-bits on 64-bits
3358 architectures. */
3359 Int cmd = (Int) ARG2;
3360
3361 switch (cmd /*request*/) {
3362 /* pools */
3363 case VKI_POOL_STATUSQ:
3364 POST_MEM_WRITE(ARG3, sizeof(vki_pool_status_t));
3365 break;
3366
3367 /* mntio */
Elliott Hughesa0664b92017-04-18 17:46:52 -07003368 case VKI_MNTIOC_GETEXTMNTENT:
3369 {
3370 struct vki_mntentbuf *embuf = (struct vki_mntentbuf *) ARG3;
3371 struct vki_extmnttab *mnt = (struct vki_extmnttab *) embuf->mbuf_emp;
3372
3373 POST_MEM_WRITE((Addr) mnt, sizeof(struct vki_extmnttab));
3374 if (mnt != NULL) {
3375 if (mnt->mnt_special != NULL)
3376 POST_MEM_WRITE((Addr) mnt->mnt_special,
3377 VG_(strlen)(mnt->mnt_special) + 1);
3378 if (mnt->mnt_mountp != NULL)
3379 POST_MEM_WRITE((Addr) mnt->mnt_mountp,
3380 VG_(strlen)(mnt->mnt_mountp) + 1);
3381 if (mnt->mnt_fstype != NULL)
3382 POST_MEM_WRITE((Addr) mnt->mnt_fstype,
3383 VG_(strlen)(mnt->mnt_fstype) + 1);
3384 if (mnt->mnt_mntopts != NULL)
3385 POST_MEM_WRITE((Addr) mnt->mnt_mntopts,
3386 VG_(strlen)(mnt->mnt_mntopts) + 1);
3387 if (mnt->mnt_time != NULL)
3388 POST_MEM_WRITE((Addr) mnt->mnt_time,
3389 VG_(strlen)(mnt->mnt_time) + 1);
3390 }
3391 }
3392 break;
3393
sewardj8eb8bab2015-07-21 14:44:28 +00003394 case VKI_MNTIOC_GETMNTANY:
3395 {
3396 struct vki_mntentbuf *embuf = (struct vki_mntentbuf *) ARG3;
3397 struct vki_mnttab *mnt = (struct vki_mnttab *) embuf->mbuf_emp;
3398
3399 POST_MEM_WRITE((Addr) mnt, sizeof(struct vki_mnttab));
3400 if (mnt != NULL) {
3401 if (mnt->mnt_special != NULL)
3402 POST_MEM_WRITE((Addr) mnt->mnt_special,
3403 VG_(strlen)(mnt->mnt_special) + 1);
3404 if (mnt->mnt_mountp != NULL)
3405 POST_MEM_WRITE((Addr) mnt->mnt_mountp,
3406 VG_(strlen)(mnt->mnt_mountp) + 1);
3407 if (mnt->mnt_fstype != NULL)
3408 POST_MEM_WRITE((Addr) mnt->mnt_fstype,
3409 VG_(strlen)(mnt->mnt_fstype) + 1);
3410 if (mnt->mnt_mntopts != NULL)
3411 POST_MEM_WRITE((Addr) mnt->mnt_mntopts,
3412 VG_(strlen)(mnt->mnt_mntopts) + 1);
3413 if (mnt->mnt_time != NULL)
3414 POST_MEM_WRITE((Addr) mnt->mnt_time,
3415 VG_(strlen)(mnt->mnt_time) + 1);
3416 }
3417 }
3418 break;
3419
3420 /* termio/termios */
3421 case VKI_TCGETA:
3422 POST_MEM_WRITE(ARG3, sizeof(struct vki_termio));
3423 break;
3424 case VKI_TCGETS:
3425 POST_MEM_WRITE(ARG3, sizeof(struct vki_termios));
3426 break;
3427 case VKI_TCSETS:
3428 break;
3429 case VKI_TCSETSW:
3430 break;
3431 case VKI_TCSETSF:
3432 break;
3433 case VKI_TIOCGWINSZ:
3434 POST_MEM_WRITE(ARG3, sizeof(struct vki_winsize));
3435 break;
3436 case VKI_TIOCSWINSZ:
3437 break;
3438 case VKI_TIOCGPGRP:
3439 POST_MEM_WRITE(ARG3, sizeof(vki_pid_t));
3440 break;
3441 case VKI_TIOCSPGRP:
3442 break;
3443 case VKI_TIOCGSID:
3444 POST_MEM_WRITE(ARG3, sizeof(vki_pid_t));
3445 break;
3446 case VKI_TIOCNOTTY:
3447 case VKI_TIOCSCTTY:
3448 break;
3449
3450 /* STREAMS */
3451 case VKI_I_PUSH:
3452 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07003453 case VKI_I_FLUSH:
3454 break;
sewardj8eb8bab2015-07-21 14:44:28 +00003455 case VKI_I_STR:
3456 {
3457 struct vki_strioctl *p = (struct vki_strioctl *) ARG3;
3458
3459 POST_FIELD_WRITE(p->ic_len);
3460 if ((p->ic_dp != NULL) && (p->ic_len > 0))
3461 POST_MEM_WRITE((Addr) p->ic_dp, p->ic_len);
3462 }
3463 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07003464 case VKI_I_FIND:
3465 break;
sewardj8eb8bab2015-07-21 14:44:28 +00003466 case VKI_I_PEEK:
3467 {
3468 struct vki_strpeek *p = (struct vki_strpeek*)ARG3;
3469
3470 POST_FIELD_WRITE(p->ctlbuf.len);
3471 POST_FIELD_WRITE(p->databuf.len);
3472 POST_FIELD_WRITE(p->flags);
3473
3474 if (p->ctlbuf.buf && p->ctlbuf.len > 0)
3475 POST_MEM_WRITE((Addr)p->ctlbuf.buf, p->ctlbuf.len);
3476 if (p->databuf.buf && p->databuf.len > 0)
3477 POST_MEM_WRITE((Addr)p->databuf.buf, p->databuf.len);
3478 }
3479 break;
3480 case VKI_I_CANPUT:
3481 break;
3482
3483 /* sockio */
iraisr2d20d8d2015-09-29 05:20:16 +00003484 case VKI_SIOCGIFCONF:
3485 {
3486 struct vki_ifconf *p = (struct vki_ifconf *) ARG3;
3487 POST_FIELD_WRITE(p->ifc_len);
3488 POST_FIELD_WRITE(p->ifc_req);
3489 if ((p->ifc_req != NULL) && (p->ifc_len > 0))
3490 POST_MEM_WRITE((Addr) p->ifc_req, p->ifc_len);
3491 }
3492 break;
3493 case VKI_SIOCGIFFLAGS:
3494 {
3495 struct vki_ifreq *p = (struct vki_ifreq *) ARG3;
3496 POST_FIELD_WRITE(p->ifr_flags);
3497 }
3498 break;
3499 case VKI_SIOCGIFNETMASK:
3500 {
3501 struct vki_ifreq *p = (struct vki_ifreq *) ARG3;
3502 POST_FIELD_WRITE(p->ifr_addr);
3503 }
3504 break;
3505 case VKI_SIOCGIFNUM:
3506 POST_MEM_WRITE(ARG3, sizeof(int));
3507 break;
iraisrf185f3c2015-09-29 14:23:51 +00003508 case VKI_SIOCGLIFBRDADDR:
3509 {
3510 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3511 POST_FIELD_WRITE(p->lifr_addr);
3512 }
3513 break;
3514 case VKI_SIOCGLIFCONF:
3515 {
3516 struct vki_lifconf *p = (struct vki_lifconf *) ARG3;
3517 POST_FIELD_WRITE(p->lifc_len);
3518 POST_FIELD_WRITE(p->lifc_req);
3519 if ((p->lifc_req != NULL) && (p->lifc_len > 0))
3520 POST_MEM_WRITE((Addr) p->lifc_req, p->lifc_len);
3521 }
3522 break;
3523 case VKI_SIOCGLIFFLAGS:
3524 {
3525 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3526 POST_FIELD_WRITE(p->lifr_flags);
3527 }
3528 break;
3529 case VKI_SIOCGLIFNETMASK:
3530 {
3531 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3532 POST_FIELD_WRITE(p->lifr_addr);
3533 }
3534 break;
sewardj8eb8bab2015-07-21 14:44:28 +00003535 case VKI_SIOCGLIFNUM:
3536 {
3537 struct vki_lifnum *p = (struct vki_lifnum *) ARG3;
3538 POST_FIELD_WRITE(p->lifn_count);
3539 }
3540 break;
3541
3542 /* filio */
3543 case VKI_FIOSETOWN:
3544 break;
3545 case VKI_FIOGETOWN:
3546 POST_MEM_WRITE(ARG3, sizeof(vki_pid_t));
3547 break;
3548
3549 /* CRYPTO */
3550 case VKI_CRYPTO_GET_PROVIDER_LIST:
3551 {
3552 vki_crypto_get_provider_list_t *pl =
3553 (vki_crypto_get_provider_list_t *) ARG3;
3554
3555 POST_FIELD_WRITE(pl->pl_count);
3556 POST_FIELD_WRITE(pl->pl_return_value);
3557
3558 if ((ARG4 > 0) && (pl->pl_return_value == VKI_CRYPTO_SUCCESS))
3559 POST_MEM_WRITE((Addr) pl->pl_list, pl->pl_count *
3560 sizeof(vki_crypto_provider_entry_t));
3561 }
3562 break;
3563
3564 /* dtrace */
3565 case VKI_DTRACEHIOC_REMOVE:
3566 case VKI_DTRACEHIOC_ADDDOF:
3567 break;
3568
Elliott Hughesa0664b92017-04-18 17:46:52 -07003569 /* devinfo */
3570 case VKI_DINFOUSRLD:
3571 POST_MEM_WRITE(ARG3, RES);
3572 break;
3573 case VKI_DINFOIDENT:
3574 break;
3575
sewardj8eb8bab2015-07-21 14:44:28 +00003576 default:
3577 /* Not really anything to do since ioctl direction hints are hardly used
3578 on Solaris. */
3579 break;
3580 }
3581}
3582
3583PRE(sys_fchownat)
3584{
3585 /* int fchownat(int fd, const char *path, uid_t owner, gid_t group,
3586 int flag); */
3587
3588 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
3589 This is different from Linux, for example, where glibc sign-extends it. */
3590 Int fd = (Int) ARG1;
3591
3592 PRINT("sys_fchownat ( %d, %#lx(%s), %ld, %ld, %ld )", fd,
florianb26101c2015-08-08 21:45:33 +00003593 ARG2, (HChar *) ARG2, SARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00003594 PRE_REG_READ5(long, "fchownat", int, fd, const char *, path,
3595 vki_uid_t, owner, vki_gid_t, group, int, flag);
3596
3597 if (ARG2)
3598 PRE_MEM_RASCIIZ("fchownat(path)", ARG2);
3599
3600 /* Be strict but ignore fd for absolute path. */
3601 if (fd != VKI_AT_FDCWD
3602 && ML_(safe_to_deref)((void *) ARG2, 1)
3603 && ((HChar *) ARG2)[0] != '/'
3604 && !ML_(fd_allowed)(fd, "fchownat", tid, False))
3605 SET_STATUS_Failure(VKI_EBADF);
3606}
3607
3608PRE(sys_fdsync)
3609{
3610 /* int fdsync(int fd, int flag); */
florianb26101c2015-08-08 21:45:33 +00003611 PRINT("sys_fdsync ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00003612 PRE_REG_READ2(long, "fdsync", int, fd, int, flag);
3613
3614 /* Be strict. */
3615 if (!ML_(fd_allowed)(ARG1, "fdsync", tid, False))
3616 SET_STATUS_Failure(VKI_EBADF);
3617}
3618
3619PRE(sys_execve)
3620{
3621 Int i, j;
3622 /* This is a Solaris specific version of the generic pre-execve wrapper. */
3623
3624#if defined(SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS)
3625 /* int execve(uintptr_t file, const char **argv, const char **envp,
3626 int flags); */
florianb26101c2015-08-08 21:45:33 +00003627 PRINT("sys_execve ( %#lx, %#lx, %#lx, %ld )", ARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00003628 PRE_REG_READ4(long, "execve", uintptr_t, file, const char **, argv,
3629 const char **, envp, int, flags);
3630
3631#else
3632
3633 /* int execve(const char *fname, const char **argv, const char **envp); */
3634 PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )",
3635 ARG1, (HChar *) ARG1, ARG2, ARG3);
3636 PRE_REG_READ3(long, "execve", const char *, file, const char **, argv,
3637 const char **, envp);
3638#endif /* SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS */
3639
3640 Bool ARG1_is_fd = False;
3641#if defined(SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS)
3642 if (ARG4 & VKI_EXEC_DESCRIPTOR) {
3643 ARG1_is_fd = True;
3644 }
3645#endif /* SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS */
3646
3647 if (ARG1_is_fd == False)
3648 PRE_MEM_RASCIIZ("execve(filename)", ARG1);
3649 if (ARG2)
3650 ML_(pre_argv_envp)(ARG2, tid, "execve(argv)", "execve(argv[i])");
3651 if (ARG3)
3652 ML_(pre_argv_envp)(ARG3, tid, "execve(envp)", "execve(envp[i])");
3653
3654 /* Erk. If the exec fails, then the following will have made a mess of
3655 things which makes it hard for us to continue. The right thing to do is
3656 piece everything together again in POST(execve), but that's close to
3657 impossible. Instead, we make an effort to check that the execve will
3658 work before actually doing it. */
3659
3660 const HChar *fname = (const HChar *) ARG1;
3661 if (ARG1_is_fd) {
3662 if (!ML_(fd_allowed)(ARG1, "execve", tid, False)) {
3663 SET_STATUS_Failure(VKI_EBADF);
3664 return;
3665 }
3666
3667 if (VG_(resolve_filename)(ARG1, &fname) == False) {
3668 SET_STATUS_Failure(VKI_EBADF);
3669 return;
3670 }
3671
3672 struct vg_stat stats;
3673 if (VG_(fstat)(ARG1, &stats) != 0) {
3674 SET_STATUS_Failure(VKI_EBADF);
3675 return;
3676 }
3677
3678 if (stats.nlink > 1)
3679 VG_(unimplemented)("Syswrap of execve where fd points to a hardlink.");
3680 }
3681
3682 /* Check that the name at least begins in client-accessible storage. */
3683 if (ARG1_is_fd == False) {
3684 if ((fname == NULL) || !ML_(safe_to_deref)(fname, 1)) {
3685 SET_STATUS_Failure(VKI_EFAULT);
3686 return;
3687 }
3688 }
3689
3690 /* Check that the args at least begin in client-accessible storage.
3691 Solaris disallows to perform the exec without any arguments specified.
3692 */
3693 if (!ARG2 /* obviously bogus */ ||
3694 !VG_(am_is_valid_for_client)(ARG2, 1, VKI_PROT_READ)) {
3695 SET_STATUS_Failure(VKI_EFAULT);
3696 return;
3697 }
3698
3699 /* Debug-only printing. */
3700 if (0) {
3701 VG_(printf)("ARG1 = %#lx(%s)\n", ARG1, fname);
3702 if (ARG2) {
3703 Int q;
3704 HChar** vec = (HChar**)ARG2;
3705
3706 VG_(printf)("ARG2 = ");
3707 for (q = 0; vec[q]; q++)
3708 VG_(printf)("%p(%s) ", vec[q], vec[q]);
3709 VG_(printf)("\n");
3710 }
3711 else
3712 VG_(printf)("ARG2 = null\n");
3713 }
3714
3715 /* Decide whether or not we want to follow along. */
3716 /* Make 'child_argv' be a pointer to the child's arg vector (skipping the
3717 exe name) */
3718 const HChar **child_argv = (const HChar **) ARG2;
3719 if (child_argv[0] == NULL)
3720 child_argv = NULL;
3721 Bool trace_this_child = VG_(should_we_trace_this_child)(fname, child_argv);
3722
3723 /* Do the important checks: it is a file, is executable, permissions are
3724 ok, etc. We allow setuid executables to run only in the case when
3725 we are not simulating them, that is, they to be run natively. */
3726 Bool setuid_allowed = trace_this_child ? False : True;
3727 SysRes res = VG_(pre_exec_check)(fname, NULL, setuid_allowed);
3728 if (sr_isError(res)) {
3729 SET_STATUS_Failure(sr_Err(res));
3730 return;
3731 }
3732
3733 /* If we're tracing the child, and the launcher name looks bogus (possibly
3734 because launcher.c couldn't figure it out, see comments therein) then we
3735 have no option but to fail. */
3736 if (trace_this_child &&
3737 (!VG_(name_of_launcher) || VG_(name_of_launcher)[0] != '/')) {
3738 SET_STATUS_Failure(VKI_ECHILD); /* "No child processes." */
3739 return;
3740 }
3741
3742 /* After this point, we can't recover if the execve fails. */
3743 VG_(debugLog)(1, "syswrap", "Exec of %s\n", fname);
3744
3745 /* Terminate gdbserver if it is active. */
3746 if (VG_(clo_vgdb) != Vg_VgdbNo) {
3747 /* If the child will not be traced, we need to terminate gdbserver to
3748 cleanup the gdbserver resources (e.g. the FIFO files). If child will
3749 be traced, we also terminate gdbserver: the new Valgrind will start a
3750 fresh gdbserver after exec. */
3751 VG_(gdbserver)(0);
3752 }
3753
3754 /* Resistance is futile. Nuke all other threads. POSIX mandates this.
3755 (Really, nuke them all, since the new process will make its own new
3756 thread.) */
3757 VG_(nuke_all_threads_except)(tid, VgSrc_ExitThread);
3758 VG_(reap_threads)(tid);
3759
3760 /* Set up the child's exe path. */
3761 const HChar *path = fname;
3762 const HChar *launcher_basename = NULL;
3763 if (trace_this_child) {
3764 /* We want to exec the launcher. Get its pre-remembered path. */
3765 path = VG_(name_of_launcher);
3766 /* VG_(name_of_launcher) should have been acquired by m_main at
3767 startup. */
3768 vg_assert(path);
3769
3770 launcher_basename = VG_(strrchr)(path, '/');
3771 if (!launcher_basename || launcher_basename[1] == '\0')
3772 launcher_basename = path; /* hmm, tres dubious */
3773 else
3774 launcher_basename++;
3775 }
3776
3777 /* Set up the child's environment.
3778
3779 Remove the valgrind-specific stuff from the environment so the child
3780 doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc. This is done
3781 unconditionally, since if we are tracing the child, the child valgrind
3782 will set up the appropriate client environment. Nb: we make a copy of
3783 the environment before trying to mangle it as it might be in read-only
3784 memory (bug #101881).
3785
3786 Then, if tracing the child, set VALGRIND_LIB for it. */
3787 HChar **envp = NULL;
3788 if (ARG3 != 0) {
3789 envp = VG_(env_clone)((HChar**)ARG3);
3790 vg_assert(envp != NULL);
3791 VG_(env_remove_valgrind_env_stuff)(envp, True /*ro_strings*/, NULL);
3792 }
3793
3794 if (trace_this_child) {
3795 /* Set VALGRIND_LIB in ARG3 (the environment). */
3796 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
3797 }
3798
3799 /* Set up the child's args. If not tracing it, they are simply ARG2.
3800 Otherwise, they are:
3801
3802 [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..],
3803
3804 except that the first VG_(args_for_valgrind_noexecpass) args are
3805 omitted. */
3806 HChar **argv = NULL;
3807 if (!trace_this_child)
3808 argv = (HChar **) ARG2;
3809 else {
3810 Int tot_args;
3811
3812 vg_assert(VG_(args_for_valgrind));
3813 vg_assert(VG_(args_for_valgrind_noexecpass) >= 0);
3814 vg_assert(VG_(args_for_valgrind_noexecpass)
3815 <= VG_(sizeXA)(VG_(args_for_valgrind)));
3816
3817 /* How many args in total will there be? */
3818 /* launcher basename */
3819 tot_args = 1;
3820 /* V's args */
3821 tot_args += VG_(sizeXA)(VG_(args_for_valgrind));
3822 tot_args -= VG_(args_for_valgrind_noexecpass);
3823 /* name of client exe */
3824 tot_args++;
3825 /* args for client exe, skipping [0] */
3826 HChar **arg2copy = (HChar **) ARG2;
3827 if (arg2copy[0] != NULL)
3828 for (i = 1; arg2copy[i]; i++)
3829 tot_args++;
3830 /* allocate */
3831 argv = VG_(malloc)("syswrap.exec.5", (tot_args + 1) * sizeof(HChar*));
3832 /* copy */
3833 j = 0;
3834 argv[j++] = CONST_CAST(HChar *, launcher_basename);
3835 for (i = 0; i < VG_(sizeXA)(VG_(args_for_valgrind)); i++) {
3836 if (i < VG_(args_for_valgrind_noexecpass))
3837 continue;
3838 argv[j++] = *(HChar**)VG_(indexXA)(VG_(args_for_valgrind), i);
3839 }
3840 argv[j++] = CONST_CAST(HChar *, fname);
3841 if (arg2copy[0] != NULL)
3842 for (i = 1; arg2copy[i]; i++)
3843 argv[j++] = arg2copy[i];
3844 argv[j++] = NULL;
3845 /* check */
3846 vg_assert(j == tot_args + 1);
3847 }
3848
3849 /* Set the signal state up for exec.
3850
3851 We need to set the real signal state to make sure the exec'd process
3852 gets SIG_IGN properly.
3853
3854 Also set our real sigmask to match the client's sigmask so that the
3855 exec'd child will get the right mask. First we need to clear out any
3856 pending signals so they they don't get delivered, which would confuse
3857 things.
3858
3859 XXX This is a bug - the signals should remain pending, and be delivered
3860 to the new process after exec. There's also a race-condition, since if
3861 someone delivers us a signal between the sigprocmask and the execve,
3862 we'll still get the signal. Oh well.
3863 */
3864 {
3865 vki_sigset_t allsigs;
3866 vki_siginfo_t info;
3867
3868 /* What this loop does: it queries SCSS (the signal state that the
3869 client _thinks_ the kernel is in) by calling VG_(do_sys_sigaction),
3870 and modifies the real kernel signal state accordingly. */
3871 for (i = 1; i < VG_(max_signal); i++) {
3872 vki_sigaction_fromK_t sa_f;
3873 vki_sigaction_toK_t sa_t;
3874 VG_(do_sys_sigaction)(i, NULL, &sa_f);
3875 VG_(convert_sigaction_fromK_to_toK)(&sa_f, &sa_t);
3876 VG_(sigaction)(i, &sa_t, NULL);
3877 }
3878
3879 VG_(sigfillset)(&allsigs);
3880 while (VG_(sigtimedwait_zero)(&allsigs, &info) > 0)
3881 ;
3882
3883 ThreadState *tst = VG_(get_ThreadState)(tid);
3884 VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
3885 }
3886
sewardj8eb8bab2015-07-21 14:44:28 +00003887 /* Debug-only printing. */
3888 if (0) {
3889 HChar **cpp;
3890 VG_(printf)("exec: %s\n", path);
3891 for (cpp = argv; cpp && *cpp; cpp++)
3892 VG_(printf)("argv: %s\n", *cpp);
3893 if (0)
3894 for (cpp = envp; cpp && *cpp; cpp++)
3895 VG_(printf)("env: %s\n", *cpp);
3896 }
3897
3898#if defined(SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS)
3899 res = VG_(do_syscall4)(__NR_execve, (UWord) path, (UWord) argv,
3900 (UWord) envp, ARG4 & ~VKI_EXEC_DESCRIPTOR);
3901#else
3902 res = VG_(do_syscall3)(__NR_execve, (UWord) path, (UWord) argv,
3903 (UWord) envp);
3904#endif /* SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS */
3905 SET_STATUS_from_SysRes(res);
3906
3907 /* If we got here, then the execve failed. We've already made way too much
3908 of a mess to continue, so we have to abort. */
3909 vg_assert(FAILURE);
3910#if defined(SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS)
3911 if (ARG1_is_fd)
florianb26101c2015-08-08 21:45:33 +00003912 VG_(message)(Vg_UserMsg, "execve(%ld, %#lx, %#lx, %lu) failed, "
3913 "errno %ld\n", SARG1, ARG2, ARG3, ARG4, ERR);
sewardj8eb8bab2015-07-21 14:44:28 +00003914 else
3915 VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx, %ld) failed, errno"
florianb26101c2015-08-08 21:45:33 +00003916 " %lu\n", ARG1, (HChar *) ARG1, ARG2, ARG3, SARG4, ERR);
sewardj8eb8bab2015-07-21 14:44:28 +00003917#else
florianb26101c2015-08-08 21:45:33 +00003918 VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %lu\n",
sewardj8eb8bab2015-07-21 14:44:28 +00003919 ARG1, (HChar *) ARG1, ARG2, ARG3, ERR);
3920#endif /* SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS */
3921 VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
3922 "execve() failing, so I'm dying.\n");
3923 VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
3924 "or work out how to recover.\n");
3925 VG_(exit)(101);
3926 /*NOTREACHED*/
3927}
3928
3929static void pre_mem_read_flock(ThreadId tid, struct vki_flock *lock)
3930{
3931 PRE_FIELD_READ("fcntl(lock->l_type)", lock->l_type);
3932 PRE_FIELD_READ("fcntl(lock->l_whence)", lock->l_whence);
3933 PRE_FIELD_READ("fcntl(lock->l_start)", lock->l_start);
3934 PRE_FIELD_READ("fcntl(lock->l_len)", lock->l_len);
3935}
3936
3937#if defined(VGP_x86_solaris)
3938static void pre_mem_read_flock64(ThreadId tid, struct vki_flock64 *lock)
3939{
3940 PRE_FIELD_READ("fcntl(lock->l_type)", lock->l_type);
3941 PRE_FIELD_READ("fcntl(lock->l_whence)", lock->l_whence);
3942 PRE_FIELD_READ("fcntl(lock->l_start)", lock->l_start);
3943 PRE_FIELD_READ("fcntl(lock->l_len)", lock->l_len);
3944}
3945#endif /* VGP_x86_solaris */
3946
3947PRE(sys_fcntl)
3948{
3949 /* int fcntl(int fildes, int cmd, ...); */
3950
3951 switch (ARG2 /*cmd*/) {
3952 /* These ones ignore ARG3. */
3953 case VKI_F_GETFD:
3954 case VKI_F_GETFL:
3955 case VKI_F_GETXFL:
florianb26101c2015-08-08 21:45:33 +00003956 PRINT("sys_fcntl ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00003957 PRE_REG_READ2(long, "fcntl", int, fildes, int, cmd);
3958 break;
3959
3960 /* These ones use ARG3 as "arg". */
3961 case VKI_F_DUPFD:
Elliott Hughesed398002017-06-21 14:41:24 -07003962 case VKI_F_DUPFD_CLOEXEC:
sewardj8eb8bab2015-07-21 14:44:28 +00003963 case VKI_F_SETFD:
3964 case VKI_F_SETFL:
3965 case VKI_F_DUP2FD:
3966 case VKI_F_BADFD:
florianb26101c2015-08-08 21:45:33 +00003967 PRINT("sys_fcntl ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00003968 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd, int, arg);
3969 /* Check if a client program isn't going to poison any of V's output
3970 fds. */
3971 if (ARG2 == VKI_F_DUP2FD &&
3972 !ML_(fd_allowed)(ARG3, "fcntl(F_DUP2FD)", tid, False)) {
3973 SET_STATUS_Failure(VKI_EBADF);
3974 return;
3975 }
3976 break;
3977
3978 /* These ones use ARG3 as "native lock" (input only). */
3979 case VKI_F_SETLK:
3980 case VKI_F_SETLKW:
3981 case VKI_F_ALLOCSP:
3982 case VKI_F_FREESP:
3983 case VKI_F_SETLK_NBMAND:
florianb26101c2015-08-08 21:45:33 +00003984 PRINT("sys_fcntl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00003985 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
3986 struct flock *, lock);
3987 pre_mem_read_flock(tid, (struct vki_flock*)ARG3);
3988 break;
3989
3990 /* This one uses ARG3 as "native lock" (input&output). */
3991 case VKI_F_GETLK:
florianb26101c2015-08-08 21:45:33 +00003992 PRINT("sys_fcntl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00003993 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
3994 struct flock *, lock);
3995 pre_mem_read_flock(tid, (struct vki_flock*)ARG3);
3996 PRE_MEM_WRITE("fcntl(lock)", ARG3, sizeof(struct vki_flock));
3997 break;
3998
3999#if defined(VGP_x86_solaris)
4000 /* These ones use ARG3 as "transitional 64b lock" (input only). */
4001 case VKI_F_SETLK64:
4002 case VKI_F_SETLKW64:
4003 case VKI_F_ALLOCSP64:
4004 case VKI_F_FREESP64:
4005 case VKI_F_SETLK64_NBMAND:
florianb26101c2015-08-08 21:45:33 +00004006 PRINT("sys_fcntl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004007 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
4008 struct flock64 *, lock);
4009 pre_mem_read_flock64(tid, (struct vki_flock64*)ARG3);
4010 break;
4011
4012 /* This one uses ARG3 as "transitional 64b lock" (input&output). */
4013 case VKI_F_GETLK64:
florianb26101c2015-08-08 21:45:33 +00004014 PRINT("sys_fcntl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004015 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
4016 struct flock64 *, lock);
4017 pre_mem_read_flock64(tid, (struct vki_flock64*)ARG3);
4018 PRE_MEM_WRITE("fcntl(lock)", ARG3, sizeof(struct vki_flock64));
4019 break;
4020#endif /* VGP_x86_solaris */
4021
4022 /* These ones use ARG3 as "fshare". */
4023 case VKI_F_SHARE:
4024 case VKI_F_UNSHARE:
4025 case VKI_F_SHARE_NBMAND:
florianb26101c2015-08-08 21:45:33 +00004026 PRINT("sys_fcntl[ARG3=='fshare'] ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004027 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
4028 struct fshare *, sh);
4029 PRE_MEM_READ("fcntl(fshare)", ARG3, sizeof(struct vki_fshare));
4030 break;
4031
4032 default:
florianb26101c2015-08-08 21:45:33 +00004033 VG_(unimplemented)("Syswrap of the fcntl call with cmd %ld.", SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00004034 /*NOTREACHED*/
4035 break;
4036 }
4037
4038 if (ARG2 == VKI_F_SETLKW
4039#if defined(VGP_x86_solaris)
4040 || ARG2 == VKI_F_SETLKW64
4041#endif /* VGP_x86_solaris */
4042 )
4043 *flags |= SfMayBlock;
4044
4045 /* Be strict. */
4046 if (!ML_(fd_allowed)(ARG1, "fcntl", tid, False))
4047 SET_STATUS_Failure(VKI_EBADF);
4048}
4049
4050POST(sys_fcntl)
4051{
4052 switch (ARG2 /*cmd*/) {
4053 case VKI_F_DUPFD:
4054 if (!ML_(fd_allowed)(RES, "fcntl(F_DUPFD)", tid, True)) {
4055 VG_(close)(RES);
4056 SET_STATUS_Failure(VKI_EMFILE);
Elliott Hughesed398002017-06-21 14:41:24 -07004057 } else if (VG_(clo_track_fds))
4058 ML_(record_fd_open_named)(tid, RES);
4059 break;
4060
4061 case VKI_F_DUPFD_CLOEXEC:
4062 if (!ML_(fd_allowed)(RES, "fcntl(F_DUPFD_CLOEXEC)", tid, True)) {
4063 VG_(close)(RES);
4064 SET_STATUS_Failure(VKI_EMFILE);
4065 } else if (VG_(clo_track_fds))
sewardj8eb8bab2015-07-21 14:44:28 +00004066 ML_(record_fd_open_named)(tid, RES);
4067 break;
4068
4069 case VKI_F_DUP2FD:
4070 if (!ML_(fd_allowed)(RES, "fcntl(F_DUP2FD)", tid, True)) {
4071 VG_(close)(RES);
4072 SET_STATUS_Failure(VKI_EMFILE);
Elliott Hughesed398002017-06-21 14:41:24 -07004073 } else if (VG_(clo_track_fds))
sewardj8eb8bab2015-07-21 14:44:28 +00004074 ML_(record_fd_open_named)(tid, RES);
4075 break;
4076
4077 /* This one uses ARG3 as "native lock" (input&output). */
4078 case VKI_F_GETLK:
4079 POST_MEM_WRITE(ARG3, sizeof(struct vki_flock));
4080 break;
4081
4082#if defined(VGP_x86_solaris)
4083 /* This one uses ARG3 as "transitional 64b lock" (input&output). */
4084 case VKI_F_GETLK64:
4085 POST_MEM_WRITE(ARG3, sizeof(struct vki_flock64));
4086 break;
4087#endif /* VGP_x86_solaris */
4088
4089 default:
4090 break;
4091 }
4092}
4093
4094PRE(sys_renameat)
4095{
4096 /* int renameat(int fromfd, const char *old, int tofd, const char *new); */
4097
4098 /* Interpret the first and third arguments as 32-bit values even on 64-bit
4099 architecture. This is different from Linux, for example, where glibc
4100 sign-extends them. */
4101 Int fromfd = (Int) ARG1;
4102 Int tofd = (Int) ARG3;
4103
4104 *flags |= SfMayBlock;
4105 PRINT("sys_renameat ( %d, %#lx(%s), %d, %#lx(%s) )", fromfd,
4106 ARG2, (HChar *) ARG2, tofd, ARG4, (HChar *) ARG4);
4107 PRE_REG_READ4(long, "renameat", int, fromfd, const char *, old,
4108 int, tofd, const char *, new);
4109
4110 PRE_MEM_RASCIIZ("renameat(old)", ARG2);
4111 PRE_MEM_RASCIIZ("renameat(new)", ARG4);
4112
4113 /* Be strict but ignore fromfd/tofd for absolute old/new. */
4114 if (fromfd != VKI_AT_FDCWD
4115 && ML_(safe_to_deref)((void *) ARG2, 1)
4116 && ((HChar *) ARG2)[0] != '/'
4117 && !ML_(fd_allowed)(fromfd, "renameat", tid, False)) {
4118 SET_STATUS_Failure(VKI_EBADF);
4119 }
4120 if (tofd != VKI_AT_FDCWD
4121 && ML_(safe_to_deref)((void *) ARG4, 1)
4122 && ((HChar *) ARG4)[0] != '/'
4123 && !ML_(fd_allowed)(tofd, "renameat", tid, False)) {
4124 SET_STATUS_Failure(VKI_EBADF);
4125 }
4126}
4127
4128PRE(sys_unlinkat)
4129{
4130 /* int unlinkat(int dirfd, const char *pathname, int flags); */
4131
4132 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
4133 This is different from Linux, for example, where glibc sign-extends it. */
4134 Int dfd = (Int) ARG1;
4135
4136 *flags |= SfMayBlock;
4137 PRINT("sys_unlinkat ( %d, %#lx(%s), %ld )", dfd, ARG2, (HChar *) ARG2,
florianb26101c2015-08-08 21:45:33 +00004138 SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004139 PRE_REG_READ3(long, "unlinkat", int, dirfd, const char *, pathname,
4140 int, flags);
4141 PRE_MEM_RASCIIZ("unlinkat(pathname)", ARG2);
4142
4143 /* Be strict but ignore dfd for absolute pathname. */
4144 if (dfd != VKI_AT_FDCWD
4145 && ML_(safe_to_deref)((void *) ARG2, 1)
4146 && ((HChar *) ARG2)[0] != '/'
4147 && !ML_(fd_allowed)(dfd, "unlinkat", tid, False))
4148 SET_STATUS_Failure(VKI_EBADF);
4149}
4150
4151PRE(sys_fstatat)
4152{
4153 /* int fstatat(int fildes, const char *path, struct stat *buf,
4154 int flag); */
4155
4156 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
4157 This is different from Linux, for example, where glibc sign-extends it. */
4158 Int fd = (Int) ARG1;
4159
4160 PRINT("sys_fstatat ( %d, %#lx(%s), %#lx, %ld )", fd, ARG2,
florianb26101c2015-08-08 21:45:33 +00004161 (HChar *) ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00004162 PRE_REG_READ4(long, "fstatat", int, fildes, const char *, path,
4163 struct stat *, buf, int, flag);
4164 if (ARG2) {
4165 /* Only test ARG2 if it isn't NULL. The kernel treats the NULL-case as
4166 fstat(fildes, buf). */
4167 PRE_MEM_RASCIIZ("fstatat(path)", ARG2);
4168 }
4169 PRE_MEM_WRITE("fstatat(buf)", ARG3, sizeof(struct vki_stat));
4170
4171 /* Be strict but ignore fildes for absolute path. */
4172 if (fd != VKI_AT_FDCWD
4173 && ML_(safe_to_deref)((void *) ARG2, 1)
4174 && ((HChar *) ARG2)[0] != '/'
4175 && !ML_(fd_allowed)(fd, "fstatat", tid, False))
4176 SET_STATUS_Failure(VKI_EBADF);
4177}
4178
4179POST(sys_fstatat)
4180{
4181 POST_MEM_WRITE(ARG3, sizeof(struct vki_stat));
4182}
4183
4184PRE(sys_openat)
4185{
4186 /* int openat(int fildes, const char *filename, int flags);
4187 int openat(int fildes, const char *filename, int flags, mode_t mode); */
4188
4189 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
4190 This is different from Linux, for example, where glibc sign-extends it. */
4191 Int fd = (Int) ARG1;
4192
4193 if (ARG3 & VKI_O_CREAT) {
4194 /* 4-arg version */
4195 PRINT("sys_openat ( %d, %#lx(%s), %ld, %ld )", fd, ARG2, (HChar *) ARG2,
florianb26101c2015-08-08 21:45:33 +00004196 SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00004197 PRE_REG_READ4(long, "openat", int, fildes, const char *, filename,
4198 int, flags, vki_mode_t, mode);
4199 }
4200 else {
4201 /* 3-arg version */
4202 PRINT("sys_openat ( %d, %#lx(%s), %ld )", fd, ARG2, (HChar *) ARG2,
florianb26101c2015-08-08 21:45:33 +00004203 SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004204 PRE_REG_READ3(long, "openat", int, fildes, const char *, filename,
4205 int, flags);
4206 }
4207
4208 PRE_MEM_RASCIIZ("openat(filename)", ARG2);
4209
4210 /* Be strict but ignore fildes for absolute pathname. */
4211 if (fd != VKI_AT_FDCWD
4212 && ML_(safe_to_deref)((void *) ARG2, 1)
4213 && ((HChar *) ARG2)[0] != '/'
4214 && !ML_(fd_allowed)(fd, "openat", tid, False)) {
4215 SET_STATUS_Failure(VKI_EBADF);
4216 return;
4217 }
4218
iraisr23e68ca2015-08-14 20:50:11 +00004219 if (ML_(handle_auxv_open)(status, (const HChar *) ARG2, ARG3))
sewardj8eb8bab2015-07-21 14:44:28 +00004220 return;
4221
iraisr23e68ca2015-08-14 20:50:11 +00004222 if (handle_psinfo_open(status, True /*use_openat*/, (const HChar *) ARG2,
sewardj8eb8bab2015-07-21 14:44:28 +00004223 fd, ARG3, ARG4))
4224 return;
4225
iraisr23e68ca2015-08-14 20:50:11 +00004226#if defined(SOLARIS_PROC_CMDLINE)
4227 if (handle_cmdline_open(status, (const HChar *) ARG2))
4228 return;
4229#endif /* SOLARIS_PROC_CMDLINE */
4230
sewardj8eb8bab2015-07-21 14:44:28 +00004231 *flags |= SfMayBlock;
4232}
4233
4234POST(sys_openat)
4235{
4236 if (!ML_(fd_allowed)(RES, "openat", tid, True)) {
4237 VG_(close)(RES);
4238 SET_STATUS_Failure(VKI_EMFILE);
4239 }
4240 else if (VG_(clo_track_fds))
4241 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG2);
4242}
4243
4244PRE(sys_tasksys)
4245{
4246 /* Kernel: long tasksys(int code, projid_t projid, uint_t flags,
4247 void *projidbuf, size_t pbufsz);
4248 */
4249 switch (ARG1 /*code*/) {
4250 case 0:
4251 /* Libc: taskid_t settaskid(projid_t project, uint_t flags); */
florianb26101c2015-08-08 21:45:33 +00004252 PRINT("sys_tasksys ( %ld, %ld, %lu )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004253 PRE_REG_READ3(long, SC2("tasksys", "settaskid"), int, code,
4254 vki_projid_t, projid, vki_uint_t, flags);
4255 break;
4256 case 1:
4257 /* Libc: taskid_t gettaskid(void); */
florianb26101c2015-08-08 21:45:33 +00004258 PRINT("sys_tasksys ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004259 PRE_REG_READ1(long, SC2("tasksys", "gettaskid"), int, code);
4260 break;
4261 case 2:
4262 /* Libc: projid_t getprojid(void); */
florianb26101c2015-08-08 21:45:33 +00004263 PRINT("sys_tasksys ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004264 PRE_REG_READ1(long, SC2("tasksys", "getprojid"), int, code);
4265 break;
4266 case 3:
4267 /* Libproject: size_t projlist(id_t *idbuf, size_t idbufsz); */
florianb26101c2015-08-08 21:45:33 +00004268 PRINT("sys_tasksys ( %ld, %#lx, %lu )", SARG1, ARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00004269 PRE_REG_READ3(long, SC2("tasksys", "projlist"), int, code,
4270 vki_id_t *, idbuf, vki_size_t, idbufsz);
4271 PRE_MEM_WRITE("tasksys(idbuf)", ARG4, ARG5);
4272 break;
4273 default:
florianb26101c2015-08-08 21:45:33 +00004274 VG_(unimplemented)("Syswrap of the tasksys call with code %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004275 /*NOTREACHED*/
4276 break;
4277 }
4278}
4279
4280POST(sys_tasksys)
4281{
4282 switch (ARG1 /*code*/) {
4283 case 0:
4284 case 1:
4285 case 2:
4286 break;
4287 case 3:
4288 if ((ARG4 != 0) && (ARG5 != 0))
4289 POST_MEM_WRITE(ARG4, MIN(RES, ARG5));
4290 break;
4291 default:
4292 vg_assert(0);
4293 break;
4294 }
4295}
4296
4297PRE(sys_lwp_park)
4298{
4299 /* Kernel: int lwp_park(int which, uintptr_t arg1, uintptr_t arg2);
4300 */
4301 *flags |= SfMayBlock;
4302 switch (ARG1 /*which*/) {
4303 case 0:
4304 /* Libc: int lwp_park(timespec_t *timeout, id_t lwpid); */
florianb26101c2015-08-08 21:45:33 +00004305 PRINT("sys_lwp_park ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004306 PRE_REG_READ3(long, SC2("lwp_park", "lwp_park"), int, which,
4307 timespec_t *, timeout, vki_id_t, lwpid);
4308 if (ARG2) {
4309 PRE_MEM_READ("lwp_park(timeout)", ARG2, sizeof(vki_timespec_t));
4310 /*PRE_MEM_WRITE("lwp_park(timeout)", ARG2,
4311 sizeof(vki_timespec_t));*/
4312 }
4313 break;
4314 case 1:
4315 /* Libc: int lwp_unpark(id_t lwpid); */
florianb26101c2015-08-08 21:45:33 +00004316 PRINT("sys_lwp_park ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00004317 PRE_REG_READ2(long, SC2("lwp_park", "lwp_unpark"), int, which,
4318 vki_id_t, lwpid);
4319 break;
4320 case 2:
4321 /* Libc: int lwp_unpark_all(id_t *lwpid, int nids); */
florianb26101c2015-08-08 21:45:33 +00004322 PRINT("sys_lwp_park ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004323 PRE_REG_READ3(long, SC2("lwp_park", "lwp_unpark_all"), int, which,
4324 id_t *, lwpid, int, nids);
4325 PRE_MEM_READ("lwp_park(lwpid)", ARG2, ARG3 * sizeof(vki_id_t));
4326 break;
4327 default:
florianb26101c2015-08-08 21:45:33 +00004328 VG_(unimplemented)("Syswrap of the lwp_park call with which %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004329 /*NOTREACHED*/
4330 break;
4331 }
4332}
4333
4334POST(sys_lwp_park)
4335{
4336 switch (ARG1 /*which*/) {
4337 case 0:
4338 if (ARG2)
4339 POST_MEM_WRITE(ARG2, sizeof(vki_timespec_t));
4340 break;
4341 case 1:
4342 case 2:
4343 break;
4344 default:
4345 vg_assert(0);
4346 break;
4347 }
4348}
4349
4350PRE(sys_sendfilev)
4351{
4352 /* Kernel: ssize_t sendfilev(int opcode, int fd,
4353 const struct sendfilevec *vec,
4354 int sfvcnt, size_t *xferred);
4355 */
4356 PRINT("sys_sendfilev ( %ld, %ld, %#lx, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00004357 SARG1, SARG2, ARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00004358
4359 switch (ARG1 /*opcode*/) {
4360 case VKI_SENDFILEV:
4361 {
4362 PRE_REG_READ5(long, "sendfilev", int, opcode, int, fd,
4363 const struct vki_sendfilevec *, vec,
4364 int, sfvcnt, vki_size_t *, xferred);
4365
4366 PRE_MEM_READ("sendfilev(vec)", ARG3,
4367 ARG4 * sizeof(struct vki_sendfilevec));
4368 PRE_MEM_WRITE("sendfilev(xferred)", ARG5, sizeof(vki_size_t));
4369
4370 struct vki_sendfilevec *vec = (struct vki_sendfilevec *) ARG3;
4371 if (ML_(safe_to_deref)(vec, ARG4 *
4372 sizeof(struct vki_sendfilevec))) {
4373 UInt i;
4374 for (i = 0; i < ARG4; i++) {
4375 HChar desc[35]; // large enough
4376 if (vec[i].sfv_fd == VKI_SFV_FD_SELF) {
4377 VG_(snprintf)(desc, sizeof(desc),
4378 "sendfilev(vec[%u].sfv_off", i);
4379 PRE_MEM_READ(desc, vec[i].sfv_off, vec[i].sfv_len);
4380 } else {
4381 VG_(snprintf)(desc, sizeof(desc),
4382 "sendfilev(vec[%u].sfv_fd)", i);
4383 if (!ML_(fd_allowed)(vec[i].sfv_fd, desc, tid, False))
4384 SET_STATUS_Failure(VKI_EBADF);
4385 }
4386 }
4387 }
4388 }
4389 break;
4390 case VKI_SENDFILEV64:
4391 {
4392 PRE_REG_READ5(long, "sendfilev", int, opcode, int, fd,
4393 const struct vki_sendfilevec64 *, vec,
4394 int, sfvcnt, vki_size_t *, xferred);
4395
4396 PRE_MEM_READ("sendfilev(vec)", ARG3,
4397 ARG4 * sizeof(struct vki_sendfilevec64));
4398 PRE_MEM_WRITE("sendfilev(xferred)", ARG5, sizeof(vki_size_t));
4399
4400 struct vki_sendfilevec64 *vec64 =
4401 (struct vki_sendfilevec64 *) ARG3;
4402 if (ML_(safe_to_deref)(vec64, ARG4 *
4403 sizeof(struct vki_sendfilevec64))) {
4404 UInt i;
4405 for (i = 0; i < ARG4; i++) {
4406 HChar desc[35]; // large enough
4407 if (vec64[i].sfv_fd == VKI_SFV_FD_SELF) {
4408 VG_(snprintf)(desc, sizeof(desc),
4409 "sendfilev(vec[%u].sfv_off", i);
4410 PRE_MEM_READ(desc, vec64[i].sfv_off, vec64[i].sfv_len);
4411 } else {
4412 VG_(snprintf)(desc, sizeof(desc),
4413 "sendfilev(vec[%u].sfv_fd)", i);
4414 if (!ML_(fd_allowed)(vec64[i].sfv_fd, desc,
4415 tid, False))
4416 SET_STATUS_Failure(VKI_EBADF);
4417 }
4418 }
4419 }
4420 }
4421 break;
4422 default:
4423 VG_(unimplemented)("Syswrap of the sendfilev call with "
florianb26101c2015-08-08 21:45:33 +00004424 "opcode %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004425 /*NOTREACHED*/
4426 break;
4427 }
4428
4429 /* Be strict. */
4430 if (!ML_(fd_allowed)(ARG2, "sendfilev(fd)", tid, False))
4431 SET_STATUS_Failure(VKI_EBADF);
4432
4433 *flags |= SfMayBlock;
4434}
4435
4436POST(sys_sendfilev)
4437{
4438 POST_MEM_WRITE(ARG5, sizeof(vki_size_t));
4439}
4440
4441#if defined(SOLARIS_LWP_NAME_SYSCALL)
4442PRE(sys_lwp_name)
4443{
4444 /* int lwp_name(int opcode, id_t lwpid, char *name, size_t len); */
florianb26101c2015-08-08 21:45:33 +00004445 PRINT("sys_lwp_name ( %ld, %ld, %#lx, %lu )", SARG1, SARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00004446
4447 switch (ARG1 /*opcode*/) {
4448 case 0:
4449 /* lwp_setname */
4450 PRE_REG_READ3(long, "lwp_name", int, opcode, vki_id_t, lwpid,
4451 char *, name);
4452 PRE_MEM_RASCIIZ("lwp_name(name)", ARG3);
4453 break;
4454 case 1:
4455 /* lwp_getname */
4456 PRE_REG_READ4(long, "lwp_name", int, opcode, vki_id_t, lwpid,
4457 char *, name, vki_size_t, len);
4458 PRE_MEM_WRITE("lwp_name(name)", ARG3, ARG4);
4459 break;
4460 default:
florianb26101c2015-08-08 21:45:33 +00004461 VG_(unimplemented)("Syswrap of the lwp_name call with opcode %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004462 /*NOTREACHED*/
4463 break;
4464 }
4465}
4466
4467POST(sys_lwp_name)
4468{
4469 switch (ARG1 /*opcode*/) {
4470 case 0:
4471 if (ARG3) { // Paranoia
4472 const HChar *new_name = (const HChar *) ARG3;
4473 ThreadState *tst = VG_(get_ThreadState)(tid);
4474 SizeT new_len = VG_(strlen)(new_name);
4475
4476 /* Don't bother reusing the memory. This is a rare event. */
4477 tst->thread_name = VG_(realloc)("syswrap.lwp_name", tst->thread_name,
4478 new_len + 1);
4479 VG_(strcpy)(tst->thread_name, new_name);
4480 }
4481 break;
4482 case 1:
4483 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
4484 break;
4485 default:
4486 vg_assert(0);
4487 break;
4488 }
4489}
4490#endif /* SOLARIS_LWP_NAME_SYSCALL */
4491
4492PRE(sys_privsys)
4493{
4494 /* Kernel: int privsys(int code, priv_op_t op, priv_ptype_t type,
4495 void *buf, size_t bufsize, int itype);
4496 */
4497 switch (ARG1 /*code*/) {
4498 case VKI_PRIVSYS_SETPPRIV:
4499 /* Libc: int setppriv(priv_op_t op, priv_ptype_t type,
4500 const priv_set_t *pset);
4501 */
florianb26101c2015-08-08 21:45:33 +00004502 PRINT("sys_privsys ( %ld, %ld, %ld, %#lx, %lu )", SARG1, SARG2, SARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00004503 ARG4, ARG5);
4504 PRE_REG_READ5(long, SC2("privsys", "setppriv"), int, code,
4505 vki_priv_op_t, op, vki_priv_ptype_t, type,
4506 const priv_set_t *, pset, vki_size_t, bufsize);
4507 PRE_MEM_READ("privsys(pset)", ARG4, ARG5);
4508 break;
4509 case VKI_PRIVSYS_GETPPRIV:
4510 /* Libc: int getppriv(priv_ptype_t type, priv_set_t *pset);
4511 priv_set_t *pset -> void *buf
4512 */
florianb26101c2015-08-08 21:45:33 +00004513 PRINT("sys_privsys ( %ld, %ld, %ld, %#lx, %lu )", SARG1, SARG2, SARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00004514 ARG4, ARG5);
4515 PRE_REG_READ5(long, SC2("privsys", "getppriv"), int, code,
4516 vki_priv_op_t, op, vki_priv_ptype_t, type, priv_set_t *, pset,
4517 vki_size_t, bufsize);
4518 PRE_MEM_WRITE("privsys(pset)", ARG4, ARG5);
4519 break;
4520 case VKI_PRIVSYS_GETIMPLINFO:
4521 /* Libc: int getprivinfo(priv_impl_info_t *buf, size_t bufsize);
4522 priv_impl_info_t *buf -> void *buf
4523 */
florianb26101c2015-08-08 21:45:33 +00004524 PRINT("sys_privsys ( %ld, %ld, %ld, %#lx, %lu )", SARG1, SARG2, SARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00004525 ARG4, ARG5);
4526 PRE_REG_READ5(long, SC2("privsys", "getprivinfo"), int, code,
4527 vki_priv_op_t, op, vki_priv_ptype_t, type,
4528 priv_impl_info_t *, buf, vki_size_t, bufsize);
4529 PRE_MEM_WRITE("privsys(buf)", ARG4, ARG5);
4530 break;
4531 case VKI_PRIVSYS_SETPFLAGS:
4532 /* Libc: int setpflags(uint_t flag, uint_t val);
4533 uint_t flag -> priv_op_t op
4534 uint_t val -> priv_ptype_t type
4535 */
florianb26101c2015-08-08 21:45:33 +00004536 PRINT("sys_privsys ( %ld, %lu, %lu )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004537 PRE_REG_READ3(long, SC2("privsys", "setpflags"), int, code,
4538 vki_uint_t, flag, vki_uint_t, val);
4539 break;
4540 case VKI_PRIVSYS_GETPFLAGS:
4541 /* Libc: uint_t getpflags(uint_t flag);
4542 uint_t flag -> priv_op_t op
4543 */
florianb26101c2015-08-08 21:45:33 +00004544 PRINT("sys_privsys ( %ld, %lu )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00004545 PRE_REG_READ2(long, SC2("privsys", "setpflags"), int, code,
4546 vki_uint_t, flag);
4547 break;
4548 case VKI_PRIVSYS_ISSETUGID:
4549 /* Libc: int issetugid(void); */
florianb26101c2015-08-08 21:45:33 +00004550 PRINT("sys_privsys ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004551 PRE_REG_READ1(long, SC2("privsys", "issetugid"), int, code);
4552 break;
4553 case VKI_PRIVSYS_PFEXEC_REG:
4554 /* Libc: int register_pfexec(int did);
4555 int did -> priv_op_t op
4556 */
florianb26101c2015-08-08 21:45:33 +00004557 PRINT("sys_privsys ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00004558 PRE_REG_READ2(long, SC2("privsys", "register_pfexec"), int, code,
4559 int, did);
4560 break;
4561 case VKI_PRIVSYS_PFEXEC_UNREG:
4562 /* Libc: int unregister_pfexec(int did); */
florianb26101c2015-08-08 21:45:33 +00004563 PRINT("sys_privsys ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00004564 PRE_REG_READ2(long, SC2("privsys", "unregister_pfexec"), int, code,
4565 int, did);
4566 break;
4567 default:
florianb26101c2015-08-08 21:45:33 +00004568 VG_(unimplemented)("Syswrap of the privsys call with code %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004569 /*NOTREACHED*/
4570 break;
4571 }
4572
4573 /* Be strict. */
4574 if ((ARG1 == VKI_PRIVSYS_PFEXEC_REG ||
4575 ARG1 == VKI_PRIVSYS_PFEXEC_UNREG) &&
4576 !ML_(fd_allowed)(ARG2, "privsys", tid, False))
4577 SET_STATUS_Failure(VKI_EBADF);
4578}
4579
4580POST(sys_privsys)
4581{
4582 switch (ARG1 /*code*/) {
4583 case VKI_PRIVSYS_SETPPRIV:
4584 break;
4585 case VKI_PRIVSYS_GETPPRIV:
4586 POST_MEM_WRITE(ARG4, sizeof(vki_priv_set_t));
4587 break;
4588 case VKI_PRIVSYS_GETIMPLINFO:
4589 /* The kernel copy outs data of size min(bufsize, privinfosize).
4590 Unfortunately, it does not seem to be possible to easily obtain the
4591 privinfosize value. The code below optimistically marks all ARG5
4592 bytes (aka bufsize) as written by the kernel. */
4593 POST_MEM_WRITE(ARG4, ARG5);
4594 break;
4595 case VKI_PRIVSYS_SETPFLAGS:
4596 case VKI_PRIVSYS_GETPFLAGS:
4597 case VKI_PRIVSYS_ISSETUGID:
4598 case VKI_PRIVSYS_PFEXEC_REG:
4599 case VKI_PRIVSYS_PFEXEC_UNREG:
4600 break;
4601 default:
4602 vg_assert(0);
4603 break;
4604 }
4605}
4606
4607PRE(sys_ucredsys)
4608{
4609 /* Kernel: int ucredsys(int code, int obj, void *buf); */
florianb26101c2015-08-08 21:45:33 +00004610 PRINT("sys_ucredsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004611
4612 switch (ARG1 /*code*/) {
4613 case VKI_UCREDSYS_UCREDGET:
4614 /* Libc: ucred_t *ucred_get(pid_t pid); */
4615 PRE_REG_READ3(long, SC2("ucredsys", "ucredget"), int, code,
4616 vki_pid_t, pid, vki_ucred_t *, buf);
4617 PRE_MEM_WRITE("ucredsys(buf)", ARG3, sizeof(vki_ucred_t));
4618 break;
4619
4620 case VKI_UCREDSYS_GETPEERUCRED:
4621 /* Libc: int getpeerucred(int fd, ucred_t **ucred); */
4622 PRE_REG_READ3(long, SC2("ucredsys", "getpeerucred"), int, code,
4623 int, fd, vki_ucred_t *, buf);
4624 PRE_MEM_WRITE("ucredsys(buf)", ARG3, sizeof(vki_ucred_t));
4625
4626 /* Be strict. */
4627 if (!ML_(fd_allowed)(ARG2, "ucredsys", tid, False))
4628 SET_STATUS_Failure(VKI_EBADF);
4629 break;
4630
4631 default:
florianb26101c2015-08-08 21:45:33 +00004632 VG_(unimplemented)("Syswrap of the ucredsys call with code %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00004633 /*NOTREACHED*/
4634 break;
4635 }
4636}
4637
4638POST(sys_ucredsys)
4639{
4640 switch (ARG1 /*code*/) {
4641 case VKI_UCREDSYS_UCREDGET:
4642 case VKI_UCREDSYS_GETPEERUCRED:
4643 vg_assert(ARG3 != 0);
4644 POST_MEM_WRITE(ARG3, ((vki_ucred_t *) ARG3)->uc_size);
4645 break;
4646
4647 default:
4648 vg_assert(0);
4649 break;
4650 }
4651}
4652
Elliott Hughesa0664b92017-04-18 17:46:52 -07004653PRE(sys_sysfs)
4654{
4655 /* Kernel: int sysfs(int opcode, long a1, long a2); */
4656 PRINT("sys_sysfs ( %ld, %ld, %ld )", SARG1, SARG2, ARG3);
4657
4658 switch (ARG1 /*opcode*/) {
4659 case VKI_GETFSIND:
4660 /* Libc: int sysfs(int opcode, const char *fsname); */
4661 PRE_REG_READ2(long, SC2("sysfs", "getfsind"), int, opcode,
4662 const char *, fsname);
4663 PRE_MEM_RASCIIZ("sysfs(fsname)", ARG2);
4664 break;
4665 case VKI_GETFSTYP:
4666 /* Libc: int sysfs(int opcode, int fs_index, char *buf); */
4667 PRE_REG_READ3(long, SC2("sysfs", "getfstyp"), int, opcode,
4668 int, fs_index, char *, buf);
4669 PRE_MEM_WRITE("sysfs(buf)", ARG3, VKI_FSTYPSZ + 1);
4670 break;
4671 case VKI_GETNFSTYP:
4672 /* Libc: int sysfs(int opcode); */
4673 PRE_REG_READ1(long, SC2("sysfs", "getnfstyp"), int, opcode);
4674 break;
4675 default:
4676 VG_(unimplemented)("Syswrap of the sysfs call with opcode %ld.", SARG1);
4677 /*NOTREACHED*/
4678 break;
4679 }
4680}
4681
4682POST(sys_sysfs)
4683{
4684 switch (ARG1 /*opcode*/) {
4685 case VKI_GETFSIND:
4686 case VKI_GETNFSTYP:
4687 break;
4688 case VKI_GETFSTYP:
4689 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
4690 break;
4691 default:
4692 vg_assert(0);
4693 break;
4694 }
4695}
4696
4697
sewardj8eb8bab2015-07-21 14:44:28 +00004698PRE(sys_getmsg)
4699{
4700 /* int getmsg(int fildes, struct strbuf *ctlptr, struct strbuf *dataptr,
4701 int *flagsp); */
4702 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
4703 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
4704 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004705 PRINT("sys_getmsg ( %ld, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00004706 PRE_REG_READ4(long, "getmsg", int, fildes, struct vki_strbuf *, ctlptr,
4707 struct vki_strbuf *, dataptr, int *, flagsp);
4708 if (ctrlptr) {
4709 PRE_FIELD_READ("getmsg(ctrlptr->maxlen)", ctrlptr->maxlen);
4710 PRE_FIELD_WRITE("getmsg(ctrlptr->len)", ctrlptr->len);
4711 PRE_FIELD_READ("getmsg(ctrlptr->buf)", ctrlptr->buf);
4712 if (ML_(safe_to_deref)((void*)ARG2, sizeof(struct vki_strbuf))
4713 && ctrlptr->maxlen > 0)
4714 PRE_MEM_WRITE("getmsg(ctrlptr->buf)", (Addr)ctrlptr->buf,
4715 ctrlptr->maxlen);
4716 }
4717 if (dataptr) {
4718 PRE_FIELD_READ("getmsg(dataptr->maxlen)", dataptr->maxlen);
4719 PRE_FIELD_WRITE("getmsg(dataptr->len)", dataptr->len);
4720 PRE_FIELD_READ("getmsg(dataptr->buf)", dataptr->buf);
4721 if (ML_(safe_to_deref)((void*)ARG3, sizeof(struct vki_strbuf))
4722 && dataptr->maxlen > 0)
4723 PRE_MEM_WRITE("getmsg(dataptr->buf)", (Addr)dataptr->buf,
4724 dataptr->maxlen);
4725 }
4726 PRE_MEM_READ("getmsg(flagsp)", ARG4, sizeof(int));
4727 /*PRE_MEM_WRITE("getmsg(flagsp)", ARG4, sizeof(int));*/
4728
4729 /* Be strict. */
4730 if (!ML_(fd_allowed)(ARG1, "getmsg", tid, False))
4731 SET_STATUS_Failure(VKI_EBADF);
4732}
4733
4734POST(sys_getmsg)
4735{
4736 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
4737 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
4738
4739 if (ctrlptr && ctrlptr->len > 0)
4740 POST_MEM_WRITE((Addr)ctrlptr->buf, ctrlptr->len);
4741 if (dataptr && dataptr->len > 0)
4742 POST_MEM_WRITE((Addr)dataptr->buf, dataptr->len);
4743 POST_MEM_WRITE(ARG4, sizeof(int));
4744}
4745
4746PRE(sys_putmsg)
4747{
4748 /* int putmsg(int fildes, struct strbuf *ctlptr, struct strbuf *dataptr,
4749 int flags); */
4750 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
4751 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
4752 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004753 PRINT("sys_putmsg ( %ld, %#lx, %#lx, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00004754 PRE_REG_READ4(long, "putmsg", int, fildes, struct vki_strbuf *, ctrlptr,
4755 struct vki_strbuf *, dataptr, int, flags);
4756 if (ctrlptr) {
4757 PRE_FIELD_READ("putmsg(ctrlptr->len)", ctrlptr->len);
4758 PRE_FIELD_READ("putmsg(ctrlptr->buf)", ctrlptr->buf);
4759 if (ML_(safe_to_deref)((void*)ARG2, sizeof(struct vki_strbuf))
4760 && ctrlptr->len > 0)
4761 PRE_MEM_READ("putmsg(ctrlptr->buf)", (Addr)ctrlptr->buf,
4762 ctrlptr->len);
4763 }
4764 if (dataptr) {
4765 PRE_FIELD_READ("putmsg(dataptr->len)", dataptr->len);
4766 PRE_FIELD_READ("putmsg(dataptr->buf)", dataptr->buf);
4767 if (ML_(safe_to_deref)((void*)ARG3, sizeof(struct vki_strbuf))
4768 && dataptr->len > 0)
4769 PRE_MEM_READ("putmsg(dataptr->buf)", (Addr)dataptr->buf,
4770 dataptr->len);
4771 }
4772
4773 /* Be strict. */
4774 if (!ML_(fd_allowed)(ARG1, "putmsg", tid, False))
4775 SET_STATUS_Failure(VKI_EBADF);
4776}
4777
4778PRE(sys_lstat)
4779{
4780 /* int lstat(const char *path, struct stat *buf); */
4781 /* Note: We could use here the sys_newlstat generic wrapper, but the 'new'
4782 in its name is rather confusing in the Solaris context, thus we provide
4783 our own wrapper. */
4784 PRINT("sys_lstat ( %#lx(%s), %#lx )", ARG1, (HChar *) ARG1, ARG2);
4785 PRE_REG_READ2(long, "lstat", const char *, path, struct stat *, buf);
4786
4787 PRE_MEM_RASCIIZ("lstat(path)", ARG1);
4788 PRE_MEM_WRITE("lstat(buf)", ARG2, sizeof(struct vki_stat));
4789}
4790
4791POST(sys_lstat)
4792{
4793 POST_MEM_WRITE(ARG2, sizeof(struct vki_stat));
4794}
4795
4796PRE(sys_sigprocmask)
4797{
4798 /* int sigprocmask(int how, const sigset_t *set, sigset_t *oset); */
florianb26101c2015-08-08 21:45:33 +00004799 PRINT("sys_sigprocmask ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004800 PRE_REG_READ3(long, "sigprocmask",
4801 int, how, vki_sigset_t *, set, vki_sigset_t *, oset);
4802 if (ARG2)
4803 PRE_MEM_READ("sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
4804 if (ARG3)
4805 PRE_MEM_WRITE("sigprocmask(oset)", ARG3, sizeof(vki_sigset_t));
4806
4807 /* Be safe. */
4808 if (ARG2 && !ML_(safe_to_deref((void*)ARG2, sizeof(vki_sigset_t)))) {
4809 SET_STATUS_Failure(VKI_EFAULT);
4810 }
4811 if (ARG3 && !ML_(safe_to_deref((void*)ARG3, sizeof(vki_sigset_t)))) {
4812 SET_STATUS_Failure(VKI_EFAULT);
4813 }
4814
4815 if (!FAILURE)
4816 SET_STATUS_from_SysRes(
4817 VG_(do_sys_sigprocmask)(tid, ARG1 /*how*/, (vki_sigset_t*)ARG2,
4818 (vki_sigset_t*)ARG3)
4819 );
4820
4821 if (SUCCESS)
4822 *flags |= SfPollAfter;
4823}
4824
4825POST(sys_sigprocmask)
4826{
4827 if (ARG3)
4828 POST_MEM_WRITE(ARG3, sizeof(vki_sigset_t));
4829}
4830
Elliott Hughesed398002017-06-21 14:41:24 -07004831PRE(sys_sigsuspend)
4832{
4833 *flags |= SfMayBlock;
4834
4835 /* int sigsuspend(const sigset_t *set); */
4836 PRINT("sys_sigsuspend ( %#lx )", ARG1);
4837 PRE_REG_READ1(long, "sigsuspend", vki_sigset_t *, set);
4838 PRE_MEM_READ("sigsuspend(set)", ARG1, sizeof(vki_sigset_t));
4839
4840 /* Be safe. */
4841 if (ARG1 && ML_(safe_to_deref((void *) ARG1, sizeof(vki_sigset_t)))) {
4842 VG_(sigdelset)((vki_sigset_t *) ARG1, VG_SIGVGKILL);
4843 /* We cannot mask VG_SIGVGKILL, as otherwise this thread would not
4844 be killable by VG_(nuke_all_threads_except).
4845 We thus silently ignore the user request to mask this signal.
4846 Note that this is similar to what is done for e.g.
4847 sigprocmask (see m_signals.c calculate_SKSS_from_SCSS). */
4848 }
4849}
4850
sewardj8eb8bab2015-07-21 14:44:28 +00004851PRE(sys_sigaction)
4852{
4853 /* int sigaction(int signal, const struct sigaction *act,
4854 struct sigaction *oact); */
florianb26101c2015-08-08 21:45:33 +00004855 PRINT("sys_sigaction ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00004856 PRE_REG_READ3(long, "sigaction", int, signal,
4857 const struct sigaction *, act, struct sigaction *, oact);
4858
4859 /* Note that on Solaris, vki_sigaction_toK_t and vki_sigaction_fromK_t are
4860 both typedefs of 'struct sigaction'. */
4861
4862 if (ARG2) {
4863 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t*)ARG2;
4864 PRE_FIELD_READ("sigaction(act->sa_flags)", sa->sa_flags);
4865 PRE_FIELD_READ("sigaction(act->sa_handler)", sa->ksa_handler);
4866 PRE_FIELD_READ("sigaction(act->sa_mask)", sa->sa_mask);
4867 }
4868 if (ARG3)
4869 PRE_MEM_WRITE("sigaction(oact)", ARG3, sizeof(vki_sigaction_fromK_t));
4870
4871 /* Be safe. */
4872 if (ARG2 && !ML_(safe_to_deref((void*)ARG2,
4873 sizeof(vki_sigaction_toK_t)))) {
4874 SET_STATUS_Failure(VKI_EFAULT);
4875 }
4876 if (ARG3 && !ML_(safe_to_deref((void*)ARG3,
4877 sizeof(vki_sigaction_fromK_t)))) {
4878 SET_STATUS_Failure(VKI_EFAULT);
4879 }
4880
4881 if (!FAILURE)
4882 SET_STATUS_from_SysRes(
4883 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t*)ARG2,
4884 (vki_sigaction_fromK_t*)ARG3));
4885}
4886
4887POST(sys_sigaction)
4888{
4889 if (ARG3)
4890 POST_MEM_WRITE(ARG3, sizeof(vki_sigaction_fromK_t));
4891}
4892
4893PRE(sys_sigpending)
4894{
4895 /* int sigpending(int flag, sigset_t *setp); */
florianb26101c2015-08-08 21:45:33 +00004896 PRINT("sys_sigpending ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00004897 PRE_REG_READ2(long, "sigpending", int, flag, sigset_t *, setp);
4898 PRE_MEM_WRITE("sigpending(setp)", ARG2, sizeof(vki_sigset_t));
4899}
4900
4901POST(sys_sigpending)
4902{
4903 POST_MEM_WRITE(ARG2, sizeof(vki_sigset_t));
4904}
4905
4906PRE(sys_getsetcontext)
4907{
4908 /* Kernel: int getsetcontext(int flag, void *arg) */
4909 ThreadState *tst = VG_(get_ThreadState)(tid);
florianb26101c2015-08-08 21:45:33 +00004910 PRINT("sys_getsetcontext ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00004911 switch (ARG1 /*flag*/) {
4912 case VKI_GETCONTEXT:
4913 /* Libc: int getcontext(ucontext_t *ucp); */
4914 PRE_REG_READ2(long, SC2("getsetcontext", "getcontext"), int, flag,
4915 ucontext_t *, ucp);
4916 PRE_MEM_WRITE("getsetcontext(ucp)", ARG2, sizeof(vki_ucontext_t));
4917
4918 if (!ML_(safe_to_deref((void*)ARG2, sizeof(vki_ucontext_t)))) {
4919 SET_STATUS_Failure(VKI_EFAULT);
4920 return;
4921 }
4922 VG_(save_context)(tid, (vki_ucontext_t*)ARG2, Vg_CoreSysCall);
4923 SET_STATUS_Success(0);
4924 break;
4925 case VKI_SETCONTEXT:
4926 /* Libc: int setcontext(const ucontext_t *ucp); */
4927 PRE_REG_READ2(long, SC2("getsetcontext", "setcontext"), int, flag,
4928 const ucontext_t *, ucp);
4929
4930 if (!ARG2) {
4931 /* Setting NULL context causes thread exit. */
4932 tst->exitreason = VgSrc_ExitThread;
4933 tst->os_state.exitcode = 0;
4934 SET_STATUS_Success(0);
4935 return;
4936 }
4937
4938 if (!ML_(safe_to_deref((void*)ARG2, sizeof(vki_ucontext_t)))) {
4939 SET_STATUS_Failure(VKI_EFAULT);
4940 return;
4941 }
4942
4943 VG_(restore_context)(tid, (vki_ucontext_t*)ARG2,
4944 Vg_CoreSysCall, False/*esp_is_thrptr*/);
4945 /* Tell the driver not to update the guest state with the "result". */
4946 *flags |= SfNoWriteResult;
4947 /* Check to see if any signals arose as a result of this. */
4948 *flags |= SfPollAfter;
4949
4950 /* Check if this is a possible return from a signal handler. */
4951 VG_(sigframe_return)(tid, (vki_ucontext_t*)ARG2);
4952
4953 SET_STATUS_Success(0);
4954 break;
4955 case VKI_GETUSTACK:
4956 /* Libc: int getustack(stack_t **spp); */
4957 PRE_REG_READ2(long, SC2("getsetcontext", "getustack"), int, flag,
4958 stack_t **, spp);
4959 PRE_MEM_WRITE("getsetcontext(spp)", ARG2, sizeof(vki_stack_t*));
4960
4961 if (!ML_(safe_to_deref((void*)ARG2, sizeof(vki_stack_t*)))) {
4962 SET_STATUS_Failure(VKI_EFAULT);
4963 return;
4964 }
4965
4966 *(vki_stack_t**)ARG2 = tst->os_state.ustack;
4967 POST_MEM_WRITE(ARG2, sizeof(vki_stack_t*));
4968 SET_STATUS_Success(0);
4969 break;
4970 case VKI_SETUSTACK:
4971 {
4972 /* Libc: int setustack(stack_t *sp); */
4973 PRE_REG_READ2(long, SC2("getsetcontext", "setustack"), int, flag,
4974 stack_t *, sp);
4975
4976 /* The kernel does not read the stack data instantly but it can read
4977 them later so it is better to make sure the data are defined. */
4978 PRE_MEM_READ("getsetcontext_setustack(sp)", ARG2, sizeof(vki_stack_t));
4979
4980 if (!ML_(safe_to_deref((void*)ARG2, sizeof(vki_stack_t)))) {
4981 SET_STATUS_Failure(VKI_EFAULT);
4982 return;
4983 }
4984
4985 vki_stack_t *old_stack = tst->os_state.ustack;
4986 tst->os_state.ustack = (vki_stack_t*)ARG2;
4987
4988 /* The thread is setting the ustack pointer. It is a good time to get
4989 information about its stack. */
4990 if (tst->os_state.ustack->ss_flags == 0) {
4991 /* If the sanity check of ss_flags passed set the stack. */
4992 set_stack(tid, tst->os_state.ustack);
4993
4994 if ((old_stack == NULL) && (tid > 1)) {
4995 /* New thread creation is now completed. Inform the tool. */
4996 VG_TRACK(pre_thread_first_insn, tid);
4997 }
4998 }
4999
5000 SET_STATUS_Success(0);
5001 }
5002 break;
5003 default:
florianb26101c2015-08-08 21:45:33 +00005004 VG_(unimplemented)("Syswrap of the context call with flag %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00005005 /*NOTREACHED*/
5006 break;
5007 }
5008}
5009
5010PRE(sys_fchmodat)
5011{
5012 /* int fchmodat(int fd, const char *path, mode_t mode, int flag); */
5013
5014 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
5015 This is different from Linux, for example, where glibc sign-extends it. */
5016 Int fd = (Int) ARG1;
5017
5018 PRINT("sys_fchmodat ( %d, %#lx(%s), %ld, %ld )",
florianb26101c2015-08-08 21:45:33 +00005019 fd, ARG2, (HChar *) ARG2, SARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00005020 PRE_REG_READ4(long, "fchmodat",
5021 int, fd, const char *, path, vki_mode_t, mode, int, flag);
5022
5023 if (ARG2)
5024 PRE_MEM_RASCIIZ("fchmodat(path)", ARG2);
5025
5026 /* Be strict but ignore fd for absolute path. */
5027 if (fd != VKI_AT_FDCWD
5028 && ML_(safe_to_deref)((void *) ARG2, 1)
5029 && ((HChar *) ARG2)[0] != '/'
5030 && !ML_(fd_allowed)(fd, "fchmodat", tid, False))
5031 SET_STATUS_Failure(VKI_EBADF);
5032}
5033
5034PRE(sys_mkdirat)
5035{
5036 /* int mkdirat(int fd, const char *path, mode_t mode); */
5037
5038 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
5039 This is different from Linux, for example, where glibc sign-extends it. */
5040 Int fd = (Int) ARG1;
5041
5042 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00005043 PRINT("sys_mkdirat ( %d, %#lx(%s), %ld )", fd, ARG2, (HChar *) ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00005044 PRE_REG_READ3(long, "mkdirat", int, fd, const char *, path,
5045 vki_mode_t, mode);
5046 PRE_MEM_RASCIIZ("mkdirat(path)", ARG2);
5047
5048 /* Be strict but ignore fd for absolute path. */
5049 if (fd != VKI_AT_FDCWD
5050 && ML_(safe_to_deref)((void *) ARG2, 1)
5051 && ((HChar *) ARG2)[0] != '/'
5052 && !ML_(fd_allowed)(fd, "mkdirat", tid, False))
5053 SET_STATUS_Failure(VKI_EBADF);
5054}
5055
5056static void do_statvfs_post(struct vki_statvfs *stats, ThreadId tid)
5057{
5058 POST_FIELD_WRITE(stats->f_bsize);
5059 POST_FIELD_WRITE(stats->f_frsize);
5060 POST_FIELD_WRITE(stats->f_blocks);
5061 POST_FIELD_WRITE(stats->f_bfree);
5062 POST_FIELD_WRITE(stats->f_bavail);
5063 POST_FIELD_WRITE(stats->f_files);
5064 POST_FIELD_WRITE(stats->f_ffree);
5065 POST_FIELD_WRITE(stats->f_favail);
5066 POST_FIELD_WRITE(stats->f_fsid);
5067 POST_MEM_WRITE((Addr) stats->f_basetype, VG_(strlen)(stats->f_basetype) + 1);
5068 POST_FIELD_WRITE(stats->f_flag);
5069 POST_FIELD_WRITE(stats->f_namemax);
5070 POST_MEM_WRITE((Addr) stats->f_fstr, VG_(strlen)(stats->f_fstr) + 1);
5071}
5072
5073PRE(sys_statvfs)
5074{
5075 /* int statvfs(const char *path, struct statvfs *buf); */
5076 *flags |= SfMayBlock;
5077 PRINT("sys_statvfs ( %#lx(%s), %#lx )", ARG1, (HChar *) ARG1, ARG2);
5078 PRE_REG_READ2(long, "statvfs", const char *, path,
5079 struct vki_statvfs *, buf);
5080 PRE_MEM_RASCIIZ("statvfs(path)", ARG1);
5081 PRE_MEM_WRITE("statvfs(buf)", ARG2, sizeof(struct vki_statvfs));
5082}
5083
5084POST(sys_statvfs)
5085{
5086 do_statvfs_post((struct vki_statvfs *) ARG2, tid);
5087}
5088
5089PRE(sys_fstatvfs)
5090{
5091 /* int fstatvfs(int fd, struct statvfs *buf); */
5092 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00005093 PRINT("sys_fstatvfs ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00005094 PRE_REG_READ2(long, "fstatvfs", int, fd, struct vki_statvfs *, buf);
5095 PRE_MEM_WRITE("fstatvfs(buf)", ARG2, sizeof(struct vki_statvfs));
5096
5097 /* Be strict. */
5098 if (!ML_(fd_allowed)(ARG1, "fstatvfs", tid, False))
5099 SET_STATUS_Failure(VKI_EBADF);
5100}
5101
5102POST(sys_fstatvfs)
5103{
5104 do_statvfs_post((struct vki_statvfs *) ARG2, tid);
5105}
5106
5107PRE(sys_nfssys)
5108{
5109 /* int nfssys(enum nfssys_op opcode, void *arg); */
5110 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00005111 PRINT("sys_nfssys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00005112
5113 switch (ARG1 /*opcode*/) {
5114 case VKI_NFS_REVAUTH:
5115 PRE_REG_READ2(long, SC2("nfssys", "nfs_revauth"), int, opcode,
5116 struct vki_nfs_revauth_args *, args);
5117 PRE_MEM_READ("nfssys(arg)", ARG2,
5118 sizeof(struct vki_nfs_revauth_args));
5119 break;
5120 default:
florianb26101c2015-08-08 21:45:33 +00005121 VG_(unimplemented)("Syswrap of the nfssys call with opcode %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00005122 /*NOTREACHED*/
5123 break;
5124 }
5125}
5126
5127POST(sys_nfssys)
5128{
5129 switch (ARG1 /*opcode*/) {
5130 case VKI_NFS_REVAUTH:
5131 break;
5132 default:
5133 vg_assert(0);
5134 break;
5135 }
5136}
5137
5138PRE(sys_waitid)
5139{
5140 /* int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); */
5141 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00005142 PRINT("sys_waitid( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00005143 PRE_REG_READ4(long, "waitid", vki_idtype_t, idtype, vki_id_t, id,
5144 siginfo_t *, infop, int, options);
5145 PRE_MEM_WRITE("waitid(infop)", ARG3, sizeof(vki_siginfo_t));
5146}
5147
5148POST(sys_waitid)
5149{
5150 POST_MEM_WRITE(ARG3, sizeof(vki_siginfo_t));
5151}
5152
Elliott Hughesed398002017-06-21 14:41:24 -07005153PRE(sys_sigsendsys)
5154{
5155 /* int sigsendsys(procset_t *psp, int sig); */
5156 PRINT("sys_sigsendsys( %#lx, %ld )", ARG1, SARG2);
5157 PRE_REG_READ2(long, "sigsendsys", vki_procset_t *, psp, int, signal);
5158 PRE_MEM_READ("sigsendsys(psp)", ARG1, sizeof(vki_procset_t));
5159
5160 if (!ML_(client_signal_OK)(ARG1)) {
5161 SET_STATUS_Failure(VKI_EINVAL);
5162 }
5163 if (!ML_(safe_to_deref)((void *) ARG1, sizeof(vki_procset_t))) {
5164 SET_STATUS_Failure(VKI_EFAULT);
5165 }
5166
5167 /* Exit early if there are problems. */
5168 if (FAILURE)
5169 return;
5170
5171 vki_procset_t *psp = (vki_procset_t *) ARG1;
5172 switch (psp->p_op) {
5173 case VKI_POP_AND:
5174 break;
5175 default:
5176 VG_(unimplemented)("Syswrap of the sigsendsys call with op %u.",
5177 psp->p_op);
5178 }
5179
5180 UInt pid;
5181 if ((psp->p_lidtype == VKI_P_PID) && (psp->p_ridtype == VKI_P_ALL)) {
5182 pid = psp->p_lid;
5183 } else if ((psp->p_lidtype == VKI_P_ALL) && (psp->p_ridtype == VKI_P_PID)) {
5184 pid = psp->p_rid;
5185 } else {
5186 VG_(unimplemented)("Syswrap of the sigsendsys call with lidtype %u and"
5187 "ridtype %u.", psp->p_lidtype, psp->p_ridtype);
5188 }
5189
5190 if (VG_(clo_trace_signals))
5191 VG_(message)(Vg_DebugMsg, "sigsendsys: sending signal to process %d\n",
5192 pid);
5193
5194 /* Handle SIGKILL specially. */
5195 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(pid, -1)) {
5196 SET_STATUS_Success(0);
5197 return;
5198 }
5199
5200 /* Check to see if this gave us a pending signal. */
5201 *flags |= SfPollAfter;
5202}
5203
sewardj8eb8bab2015-07-21 14:44:28 +00005204#if defined(SOLARIS_UTIMESYS_SYSCALL)
5205PRE(sys_utimesys)
5206{
5207 /* Kernel: int utimesys(int code, uintptr_t arg1, uintptr_t arg2,
5208 uintptr_t arg3, uintptr_t arg4);
5209 */
5210
5211 switch (ARG1 /*code*/) {
5212 case 0:
5213 /* Libc: int futimens(int fd, const timespec_t times[2]); */
florianb26101c2015-08-08 21:45:33 +00005214 PRINT("sys_utimesys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00005215 PRE_REG_READ3(long, "utimesys", int, code, int, fd,
5216 const vki_timespec_t *, times);
5217 if (ARG3)
5218 PRE_MEM_READ("utimesys(times)", ARG3, 2 * sizeof(vki_timespec_t));
5219
5220 /* Be strict. */
5221 if (!ML_(fd_allowed)(ARG2, "utimesys", tid, False))
5222 SET_STATUS_Failure(VKI_EBADF);
5223 break;
5224 case 1:
5225 {
5226 /* Libc: int utimensat(int fd, const char *path,
5227 const timespec_t times[2], int flag);
5228 */
5229
5230 /* Interpret the second argument as 32-bit value even on 64-bit
5231 architecture. This is different from Linux, for example, where glibc
5232 sign-extends it. */
5233 Int fd = (Int) ARG2;
5234
5235 PRINT("sys_utimesys ( %ld, %d, %#lx(%s), %#lx, %ld )",
florianb26101c2015-08-08 21:45:33 +00005236 SARG1, fd, ARG3, (HChar *) ARG3, ARG4, SARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00005237 PRE_REG_READ5(long, "utimesys", int, code, int, fd, const char *, path,
5238 const vki_timespec_t *, times, int, flag);
5239 if (ARG3)
5240 PRE_MEM_RASCIIZ("utimesys(path)", ARG3);
5241 if (ARG4)
5242 PRE_MEM_READ("utimesys(times)", ARG4, 2 * sizeof(vki_timespec_t));
5243
5244 /* Be strict but ignore fd for absolute path. */
5245 if (fd != VKI_AT_FDCWD
5246 && ML_(safe_to_deref)((void *) ARG3, 1)
5247 && ((HChar *) ARG3)[0] != '/'
5248 && !ML_(fd_allowed)(fd, "utimesys", tid, False))
5249 SET_STATUS_Failure(VKI_EBADF);
5250 break;
5251 }
5252 default:
florianb26101c2015-08-08 21:45:33 +00005253 VG_(unimplemented)("Syswrap of the utimesys call with code %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00005254 /*NOTREACHED*/
5255 break;
5256 }
5257}
5258#endif /* SOLARIS_UTIMESYS_SYSCALL */
5259
5260#if defined(SOLARIS_UTIMENSAT_SYSCALL)
5261PRE(sys_utimensat)
5262{
5263 /* int utimensat(int fd, const char *path, const timespec_t times[2],
5264 int flag);
5265 */
5266
5267 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
5268 This is different from Linux, for example, where glibc sign-extends it. */
5269 Int fd = (Int) ARG1;
5270
5271 PRINT("sys_utimensat ( %d, %#lx(%s), %#lx, %ld )",
florianb26101c2015-08-08 21:45:33 +00005272 fd, ARG2, (HChar *) ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00005273 PRE_REG_READ4(long, "utimensat", int, fd, const char *, path,
5274 const vki_timespec_t *, times, int, flag);
5275 if (ARG2)
5276 PRE_MEM_RASCIIZ("utimensat(path)", ARG2);
5277 if (ARG3)
5278 PRE_MEM_READ("utimensat(times)", ARG3, 2 * sizeof(vki_timespec_t));
5279
5280 /* Be strict but ignore fd for absolute path. */
5281 if (fd != VKI_AT_FDCWD
5282 && ML_(safe_to_deref)((void *) ARG2, 1)
5283 && ((HChar *) ARG2)[0] != '/'
5284 && !ML_(fd_allowed)(fd, "utimensat", tid, False))
5285 SET_STATUS_Failure(VKI_EBADF);
5286}
5287#endif /* SOLARIS_UTIMENSAT_SYSCALL */
5288
5289PRE(sys_sigresend)
5290{
5291 /* int sigresend(int signal, siginfo_t *siginfo, sigset_t *mask); */
5292 /* Sends a signal to the calling thread, the mask parameter specifies a new
5293 signal mask. */
5294
5295 /* Static (const) mask accessible from outside of this function. */
5296 static vki_sigset_t block_all;
5297
florianb26101c2015-08-08 21:45:33 +00005298 PRINT("sys_sigresend( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00005299 PRE_REG_READ3(long, "sigresend", int, signal, vki_siginfo_t *, siginfo,
5300 vki_sigset_t *, mask);
5301
5302 if (ARG2)
5303 PRE_MEM_READ("sigresend(siginfo)", ARG2, sizeof(vki_siginfo_t));
5304 PRE_MEM_WRITE("sigresend(mask)", ARG3, sizeof(vki_sigset_t));
5305
5306 /* Check the signal and mask. */
5307 if (!ML_(client_signal_OK)(ARG1)) {
5308 SET_STATUS_Failure(VKI_EINVAL);
5309 }
5310 if (!ML_(safe_to_deref)((void*)ARG3, sizeof(vki_sigset_t))) {
5311 SET_STATUS_Failure(VKI_EFAULT);
5312 }
5313
5314 /* Exit early if there are problems. */
5315 if (FAILURE)
5316 return;
5317
5318 /* Save the requested mask to unused ARG4. */
5319 ARG4 = ARG3;
5320
5321 /* Fake the requested sigmask with a block-all mask. If the syscall
Elliott Hughesed398002017-06-21 14:41:24 -07005322 succeeds then we will block "all" signals for a few instructions (in
sewardj8eb8bab2015-07-21 14:44:28 +00005323 syscall-x86-solaris.S) but the correct mask will be almost instantly set
5324 again by a call to sigprocmask (also in syscall-x86-solaris.S). If the
5325 syscall fails then the mask is not changed, so everything is ok too. */
5326 VG_(sigfillset)(&block_all);
5327 ARG3 = (UWord)&block_all;
5328
5329 /* Check to see if this gave us a pending signal. */
5330 *flags |= SfPollAfter;
5331
5332 if (VG_(clo_trace_signals))
5333 VG_(message)(Vg_DebugMsg, "sigresend: resending signal %ld\n", ARG1);
5334
5335 /* Handle SIGKILL specially. */
5336 if (ARG1 == VKI_SIGKILL && ML_(do_sigkill)(tid, -1)) {
5337 SET_STATUS_Success(0);
5338 return;
5339 }
5340
5341 /* Ask to handle this syscall via the slow route, since that's the only one
5342 that sets tst->status to VgTs_WaitSys. If the result of doing the
5343 syscall is an immediate run of async_signalhandler() in m_signals.c,
5344 then we need the thread to be properly tidied away. */
5345 *flags |= SfMayBlock;
5346}
5347
5348POST(sys_sigresend)
5349{
5350 /* The syscall succeeded, set the requested mask. */
5351 VG_(do_sys_sigprocmask)(tid, VKI_SIG_SETMASK, (vki_sigset_t*)ARG4, NULL);
5352
5353 if (VG_(clo_trace_signals))
florianb26101c2015-08-08 21:45:33 +00005354 VG_(message)(Vg_DebugMsg, "sigresend: resent signal %lu\n", ARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00005355}
5356
5357static void mem_priocntlsys_parm_ok(ThreadId tid, Bool pre, Bool reade,
5358 vki_pc_vaparm_t *parm)
5359{
5360 if (reade)
5361 return;
5362
5363 if (pre)
5364 PRE_FIELD_WRITE("priocntlsys(parm)", parm->pc_parm);
5365 else
5366 POST_FIELD_WRITE(parm->pc_parm);
5367}
5368
5369static void mem_priocntlsys_parm(ThreadId tid, Bool pre, Bool reade,
5370 const HChar *clname,
5371 vki_pc_vaparm_t *parm)
5372{
5373 /* This function is used to handle the PC_SETXPARMS and PC_GETXPARMS
5374 parameters. In the case of PC_SETXPARMS, the code below merely checks
5375 if all parameters are scalar, PRE_MEM_READ() for these parameters is
5376 already done by the PC_SETXPARMS handler in PRE(sys_priocntlsys).
5377
5378 A caller of this function is responsible for checking that clname and
5379 &parm->key can be dereferenced. */
5380
5381 if (VG_STREQ(clname, "RT")) {
5382 switch (parm->pc_key) {
5383 case VKI_RT_KY_PRI:
5384 case VKI_RT_KY_TQSECS:
5385 case VKI_RT_KY_TQNSECS:
5386 case VKI_RT_KY_TQSIG:
5387 /* Scalar values that are stored directly in pc_parm. */
5388 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5389 return;
5390 }
5391 }
5392 else if (VG_STREQ(clname, "TS")) {
5393 switch (parm->pc_key) {
5394 case VKI_TS_KY_UPRILIM:
5395 case VKI_TS_KY_UPRI:
5396 /* Scalar values that are stored directly in pc_parm. */
5397 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5398 return;
5399 }
5400 }
5401 else if (VG_STREQ(clname, "IA")) {
5402 switch (parm->pc_key) {
5403 case VKI_IA_KY_UPRILIM:
5404 case VKI_IA_KY_UPRI:
5405 case VKI_IA_KY_MODE:
5406 /* Scalar values that are stored directly in pc_parm. */
5407 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5408 return;
5409 }
5410 }
5411 else if (VG_STREQ(clname, "FSS")) {
5412 switch (parm->pc_key) {
5413 case VKI_FSS_KY_UPRILIM:
5414 case VKI_FSS_KY_UPRI:
5415 /* Scalar values that are stored directly in pc_parm. */
5416 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5417 return;
5418 }
5419 }
5420 else if (VG_STREQ(clname, "FX")) {
5421 switch (parm->pc_key) {
5422 case VKI_FX_KY_UPRILIM:
5423 case VKI_FX_KY_UPRI:
5424 case VKI_FX_KY_TQSECS:
5425 case VKI_FX_KY_TQNSECS:
5426 /* Scalar values that are stored directly in pc_parm. */
5427 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5428 return;
5429 }
5430 }
5431 else {
5432 /* Unknown class. */
5433 VG_(unimplemented)("Syswrap of the priocntlsys call where clname=%s.",
5434 clname);
5435 /*NOTREACHED*/
5436 }
5437
5438 /* The class is known but pc_key is unknown. */
5439 VG_(unimplemented)("Syswrap of the priocntlsys call where clname=%s "
5440 "and pc_key=%d.", clname, parm->pc_key);
5441 /*NOTREACHED*/
5442}
5443
5444PRE(sys_priocntlsys)
5445{
5446 /* long priocntlsys(int pc_version, procset_t *psp, int cmd, caddr_t arg,
5447 caddr_t arg2); */
5448
5449 if (ARG1 != 1) {
5450 /* Only the first version of priocntlsys is supported by the code below.
5451 */
florianb26101c2015-08-08 21:45:33 +00005452 VG_(unimplemented)("Syswrap of the priocntlsys where pc_version=%lu.",
sewardj8eb8bab2015-07-21 14:44:28 +00005453 ARG1);
5454 /*NOTREACHED*/
5455 }
5456
florianb26101c2015-08-08 21:45:33 +00005457 PRINT("sys_priocntlsys ( %ld, %#lx, %ld, %#lx, %#lx )", SARG1, ARG2, SARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00005458 ARG4, ARG5);
5459 PRE_REG_READ5(long, "priocntlsys", int, pc_version, procset_t *, psp,
5460 int, cmd, void *, arg, void *, arg2);
5461
5462 switch (ARG3 /*cmd*/) {
5463 case VKI_PC_GETCID:
5464 if (ARG4) {
5465 vki_pcinfo_t *info = (vki_pcinfo_t*)ARG4;
5466 PRE_MEM_RASCIIZ("priocntlsys(clname)", (Addr)info->pc_clname);
5467 /* The next line says that the complete pcinfo_t structure can be
5468 written, but this actually isn't true for pc_clname which is
5469 always only read. */
5470 PRE_MEM_WRITE("priocntlsys(pcinfo)", ARG4, sizeof(vki_pcinfo_t));
5471 }
5472 break;
5473 case VKI_PC_GETCLINFO:
5474 if (ARG4) {
5475 vki_pcinfo_t *info = (vki_pcinfo_t*)ARG4;
5476 PRE_FIELD_READ("priocntlsys(cid)", info->pc_cid);
5477 /* The next line says that the complete pcinfo_t structure can be
5478 written, but this actually isn't true for pc_cid which is
5479 always only read. */
5480 PRE_MEM_WRITE("priocntlsys(pcinfo)", ARG4, sizeof(vki_pcinfo_t));
5481 }
5482 break;
5483 case VKI_PC_SETPARMS:
5484 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5485 /* The next line says that the complete pcparms_t structure is read
5486 which is never actually true (we are too pessimistic here).
5487 Unfortunately we can't do better because we don't know what
5488 process class is involved. */
5489 PRE_MEM_READ("priocntlsys(parms)", ARG4, sizeof(vki_pcparms_t));
5490 break;
5491 case VKI_PC_GETPARMS:
5492 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5493 PRE_MEM_WRITE("priocntlsys(parms)", ARG4, sizeof(vki_pcparms_t));
5494 break;
5495 case VKI_PC_GETPRIRANGE:
5496 {
5497 vki_pcpri_t *pcpri = (vki_pcpri_t*)ARG4;
5498 PRE_FIELD_READ("priocntlsys(cid)", pcpri->pc_cid);
5499 }
5500 PRE_MEM_WRITE("priocntlsys(pri)", ARG4, sizeof(vki_pcpri_t));
5501 break;
5502 case VKI_PC_DONICE:
5503 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5504 {
5505 vki_pcnice_t *nicee = (vki_pcnice_t*)ARG4;
5506 PRE_FIELD_READ("priocntlsys(op)", nicee->pc_op);
5507 if (ML_(safe_to_deref)(&nicee->pc_op, sizeof(nicee->pc_op))) {
5508 switch (nicee->pc_op) {
5509 case VKI_PC_GETNICE:
5510 PRE_FIELD_WRITE("priocntlsys(val)", nicee->pc_val);
5511 break;
5512 case VKI_PC_SETNICE:
5513 PRE_FIELD_READ("priocntlsys(val)", nicee->pc_val);
5514 break;
5515 default:
5516 VG_(unimplemented)("Syswrap of the priocntlsys call where "
5517 "cmd=PC_DONICE and pc_op=%d", nicee->pc_op);
5518 /*NOTREACHED*/
5519 break;
5520 }
5521 }
5522 }
5523 break;
5524 case VKI_PC_SETXPARMS:
5525 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5526 PRE_MEM_RASCIIZ("priocntlsys(clname)", ARG4);
5527 if (ARG5) {
5528 vki_pc_vaparms_t *parms = (vki_pc_vaparms_t*)ARG5;
5529 PRE_FIELD_READ("priocntlsys(vaparmscnt)", parms->pc_vaparmscnt);
5530 if (ML_(safe_to_deref)(&parms->pc_vaparmscnt,
5531 sizeof(parms->pc_vaparmscnt))) {
5532 vki_uint_t i;
5533 PRE_MEM_READ("priocntlsys(parms)", (Addr)parms->pc_parms,
5534 parms->pc_vaparmscnt * sizeof(parms->pc_parms[0]));
5535 for (i = 0; i < parms->pc_vaparmscnt; i++) {
5536 vki_pc_vaparm_t *parm = &parms->pc_parms[i];
5537 if (ML_(safe_to_deref)(parm, sizeof(*parm)) &&
5538 ML_(safe_to_deref)((void*)ARG4, 1))
5539 mem_priocntlsys_parm(tid, True /*pre*/, True /*read*/,
5540 (HChar*)ARG4, parm);
5541 }
5542 }
5543 }
5544 break;
5545 case VKI_PC_GETXPARMS:
5546 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5547 if (ARG4)
5548 PRE_MEM_RASCIIZ("priocntlsys(clname)", ARG4);
5549 if (ARG5) {
5550 vki_pc_vaparms_t *parms = (vki_pc_vaparms_t*)ARG5;
5551 PRE_FIELD_READ("priocntlsys(vaparmscnt)", parms->pc_vaparmscnt);
5552 if (ML_(safe_to_deref)(&parms->pc_vaparmscnt,
5553 sizeof(parms->pc_vaparmscnt))) {
5554 vki_uint_t i;
5555 for (i = 0; i < parms->pc_vaparmscnt; i++) {
5556 vki_pc_vaparm_t *parm = &parms->pc_parms[i];
5557 PRE_MEM_READ("priocntlsys(parms)", (Addr)&parm->pc_key,
5558 parms->pc_vaparmscnt * sizeof(parm->pc_key));
5559 if (ML_(safe_to_deref)(&parm->pc_key,
5560 sizeof(parm->pc_key))) {
5561 /* First handle PC_KY_CLNAME, then class specific keys.
5562 Note that PC_KY_CLNAME can be used only with
5563 ARG4==NULL && parms->pc_vaparmscnt==1. We are not so
5564 strict here and handle this special case as a regular
5565 one which makes the code simpler. */
5566 if (parm->pc_key == VKI_PC_KY_CLNAME)
5567 PRE_MEM_WRITE("priocntlsys(clname)", parm->pc_parm,
5568 VKI_PC_CLNMSZ);
5569 else if (ARG4 && ML_(safe_to_deref)((void*)ARG4, 1))
5570 mem_priocntlsys_parm(tid, True /*pre*/,
5571 False /*read*/, (HChar*)ARG4,
5572 parm);
5573 }
5574 }
5575 }
5576 }
5577 break;
5578 case VKI_PC_SETDFLCL:
5579 PRE_MEM_RASCIIZ("priocntlsys(clname)", ARG4);
5580 break;
5581 case VKI_PC_GETDFLCL:
5582 if (ARG4) {
5583 /* GETDFLCL writes to the ARG4 buffer only if ARG4 isn't NULL. Also
5584 note that if ARG4 is NULL then the syscall succeeds. */
5585 PRE_MEM_WRITE("priocntlsys(clname)", ARG4, VKI_PC_CLNMSZ);
5586 }
5587 break;
5588 case VKI_PC_DOPRIO:
5589 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5590 {
5591 vki_pcprio_t *prio = (vki_pcprio_t*)ARG4;
5592 PRE_FIELD_READ("priocntlsys(op)", prio->pc_op);
5593 if (ML_(safe_to_deref)(&prio->pc_op, sizeof(prio->pc_op))) {
5594 switch (prio->pc_op) {
5595 case VKI_PC_GETPRIO:
5596 PRE_FIELD_WRITE("priocntlsys(cid)", prio->pc_cid);
5597 PRE_FIELD_WRITE("priocntlsys(val)", prio->pc_val);
5598 break;
5599 case VKI_PC_SETPRIO:
5600 PRE_FIELD_READ("priocntlsys(cid)", prio->pc_cid);
5601 PRE_FIELD_READ("priocntlsys(val)", prio->pc_val);
5602 break;
5603 default:
5604 VG_(unimplemented)("Syswrap of the priocntlsys call where "
5605 "cmd=PC_DOPRIO and pc_op=%d", prio->pc_op);
5606 /*NOTREACHED*/
5607 break;
5608 }
5609 }
5610 }
5611 break;
5612 case VKI_PC_ADMIN:
5613 default:
florianb26101c2015-08-08 21:45:33 +00005614 VG_(unimplemented)("Syswrap of the priocntlsys call with cmd %ld.", SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00005615 /*NOTREACHED*/
5616 break;
5617 }
5618}
5619
5620static void post_mem_write_priocntlsys_clinfo(ThreadId tid,
5621 const HChar *clname, Addr clinfo)
5622{
5623 if (VG_STREQ(clname, "RT"))
5624 POST_MEM_WRITE(clinfo, sizeof(vki_rtinfo_t));
5625 else if (VG_STREQ(clname, "TS"))
5626 POST_MEM_WRITE(clinfo, sizeof(vki_tsinfo_t));
5627 else if (VG_STREQ(clname, "IA"))
5628 POST_MEM_WRITE(clinfo, sizeof(vki_iainfo_t));
5629 else if (VG_STREQ(clname, "FSS"))
5630 POST_MEM_WRITE(clinfo, sizeof(vki_fssinfo_t));
5631 else if (VG_STREQ(clname, "FX"))
5632 POST_MEM_WRITE(clinfo, sizeof(vki_fxinfo_t));
5633 else if (VG_STREQ(clname, "SDC")) {
5634 /* Relax. */
5635 }
5636 else {
5637 VG_(unimplemented)("Syswrap of the priocntlsys call where clname=%s.",
5638 clname);
5639 /*NOTREACHED*/
5640 }
5641}
5642
5643POST(sys_priocntlsys)
5644{
5645 switch (ARG3 /*cmd*/) {
5646 case VKI_PC_GETCID:
5647 if (ARG4) {
5648 vki_pcinfo_t *info = (vki_pcinfo_t*)ARG4;
5649 POST_FIELD_WRITE(info->pc_cid);
5650 post_mem_write_priocntlsys_clinfo(tid, info->pc_clname,
5651 (Addr)&info->pc_clinfo);
5652 }
5653 break;
5654 case VKI_PC_GETCLINFO:
5655 if (ARG4) {
5656 vki_pcinfo_t *info = (vki_pcinfo_t*)ARG4;
5657 POST_MEM_WRITE((Addr)info->pc_clname,
5658 VG_(strlen)((HChar*)info->pc_clname) + 1);
5659 post_mem_write_priocntlsys_clinfo(tid, info->pc_clname,
5660 (Addr)&info->pc_clinfo);
5661 }
5662 break;
5663 case VKI_PC_SETPARMS:
5664 /* Relax. */
5665 break;
5666 case VKI_PC_GETPARMS:
5667 /* The next line says that the complete pcparms_t structure is
5668 written which is never actually true (we are too optimistic here).
5669 Unfortunately we can't do better because we don't know what
5670 process class is involved. */
5671 POST_MEM_WRITE(ARG4, sizeof(vki_pcparms_t));
5672 break;
5673 case VKI_PC_GETPRIRANGE:
5674 POST_MEM_WRITE(ARG4, sizeof(vki_pcpri_t));
5675 break;
5676 case VKI_PC_DONICE:
5677 {
5678 vki_pcnice_t *nicee = (vki_pcnice_t*)ARG4;
5679 if (nicee->pc_op == VKI_PC_GETNICE)
5680 POST_FIELD_WRITE(nicee->pc_val);
5681 }
5682 break;
5683 case VKI_PC_SETXPARMS:
5684 /* Relax. */
5685 break;
5686 case VKI_PC_GETXPARMS:
5687 {
5688 vki_pc_vaparms_t *parms = (vki_pc_vaparms_t*)ARG5;
5689 vki_uint_t i;
5690 for (i = 0; i < parms->pc_vaparmscnt; i++) {
5691 vki_pc_vaparm_t *parm = &parms->pc_parms[i];
5692 if (parm->pc_key == VKI_PC_KY_CLNAME)
5693 POST_MEM_WRITE(parm->pc_parm,
5694 VG_(strlen)((HChar*)(Addr)parm->pc_parm) + 1);
5695 else if (ARG4)
5696 mem_priocntlsys_parm(tid, False /*pre*/, False /*read*/,
5697 (HChar*)ARG4, parm);
5698 }
5699 }
5700 break;
5701 case VKI_PC_SETDFLCL:
5702 /* Relax. */
5703 break;
5704 case VKI_PC_GETDFLCL:
5705 if (ARG4)
5706 POST_MEM_WRITE(ARG4, VG_(strlen)((HChar*)ARG4) + 1);
5707 break;
5708 case VKI_PC_DOPRIO:
5709 {
5710 vki_pcprio_t *prio = (vki_pcprio_t*)ARG4;
5711 if (prio->pc_op == VKI_PC_GETPRIO) {
5712 POST_FIELD_WRITE(prio->pc_cid);
5713 POST_FIELD_WRITE(prio->pc_val);
5714 }
5715 }
5716 break;
5717 case VKI_PC_ADMIN:
5718 default:
5719 vg_assert(0);
5720 break;
5721 }
5722}
5723
5724PRE(sys_pathconf)
5725{
5726 /* long pathconf(const char *path, int name); */
florianb26101c2015-08-08 21:45:33 +00005727 PRINT("sys_pathconf ( %#lx(%s), %ld )", ARG1, (HChar *) ARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00005728 PRE_REG_READ2(long, "pathconf", const char *, path, int, name);
5729 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
5730}
5731
5732PRE(sys_mmap)
5733{
5734 /* void *mmap(void *addr, size_t len, int prot, int flags,
5735 int fildes, off_t off); */
5736 SysRes r;
5737 OffT offset;
5738
5739 /* Stay sane. */
5740 vg_assert(VKI_PAGE_SIZE == 4096);
5741 vg_assert(sizeof(offset) == sizeof(ARG6));
5742
5743 PRINT("sys_mmap ( %#lx, %#lx, %#lx, %#lx, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00005744 ARG1, ARG2, ARG3, ARG4, SARG5, ARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00005745 PRE_REG_READ6(long, "mmap", void *, start, vki_size_t, length,
5746 int, prot, int, flags, int, fd, vki_off_t, offset);
5747
5748 /* Make sure that if off < 0 then it's passed correctly to the generic mmap
5749 wraper. */
5750 offset = *(OffT*)&ARG6;
5751
5752 r = ML_(generic_PRE_sys_mmap)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, offset);
5753 SET_STATUS_from_SysRes(r);
5754}
5755
5756#if defined(SOLARIS_UUIDSYS_SYSCALL)
5757PRE(sys_uuidsys)
5758{
5759 /* int uuidsys(struct uuid *uuid); */
5760 PRINT("sys_uuidsys ( %#lx )", ARG1);
5761 PRE_REG_READ1(long, "uuidsys", struct vki_uuid *, uuid);
5762 PRE_MEM_WRITE("uuidsys(uuid)", ARG1, sizeof(struct vki_uuid));
5763}
5764
5765POST(sys_uuidsys)
5766{
5767 POST_MEM_WRITE(ARG1, sizeof(struct vki_uuid));
5768}
5769#endif /* SOLARIS_UUIDSYS_SYSCALL */
5770
5771/* Syscall mmapobj emulation. Processes ELF program headers
5772 and maps them into correct place in memory. Not an easy task, though.
5773 ELF program header of PT_LOAD/PT_SUNWBSS type specifies:
5774 o p_vaddr - actually a memory offset
5775 o p_memsz - total segment size, including text, data and BSS
5776 o p_filesz - file-based segment size mapping (includes only text and data);
5777 p_memsz - p_filesz is the size of BSS
5778 o p_offset - offset into the ELF file where the file-based mapping starts
5779
5780 Several problematic areas to cover here:
5781 1. p_offset can contain a value which is not page-aligned. In that case
5782 we mmap a part of the file prior to p_offset to make the start address
5783 page-aligned.
5784 2. Partially unused page after the file-based mapping must be zeroed.
5785 3. The first mapping is flagged with MR_HDR_ELF and needs to contain
5786 the ELF header. This information is used and verified by the dynamic
5787 linker (ld.so.1). */
5788static SysRes mmapobj_process_phdrs(ThreadId tid, Int fd,
5789 vki_mmapobj_result_t *storage,
5790 vki_uint_t *elements,
5791 const VKI_ESZ(Ehdr) *ehdr,
5792 const VKI_ESZ(Phdr) *phdrs)
5793{
5794#define ADVANCE_PHDR(ehdr, phdr) \
5795 (const VKI_ESZ(Phdr) *) ((const HChar *) (phdr) + (ehdr)->e_phentsize)
5796
5797 SysRes res;
5798 Int i;
5799 Int first_segment_idx = -1;
5800 UInt idx;
5801 UInt segments = 0; /* loadable segments */
5802 Addr start_addr = 0;
5803 Addr end_addr = 0;
iraisre8b9ee32015-08-31 21:31:09 +00005804 Addr elfbrk = 0;
sewardj8eb8bab2015-07-21 14:44:28 +00005805 SizeT max_align = VKI_PAGE_SIZE;
5806
5807 /* 1. First pass over phdrs - determine number, span and max alignment. */
5808 const VKI_ESZ(Phdr) *phdr = phdrs;
5809 for (idx = 0; idx < ehdr->e_phnum; idx++, phdr = ADVANCE_PHDR(ehdr, phdr)) {
5810 /* Skip this header if no memory is requested. */
5811 if (phdr->p_memsz == 0)
5812 continue;
5813
5814 if ((phdr->p_type == VKI_PT_LOAD) || (phdr->p_type == VKI_PT_SUNWBSS)) {
5815 Off64T offset = 0;
5816
5817 if (VG_(clo_trace_syscalls))
5818 VG_(debugLog)(2, "syswrap-solaris", "mmapobj_process_phdrs: "
5819 "program header #%u: addr=%#lx type=%#lx "
5820 "prot=%#lx memsz=%#lx filesz=%#lx file "
5821 "offset=%#lx\n", idx, phdr->p_vaddr,
5822 (UWord) phdr->p_type, (UWord) phdr->p_flags,
5823 phdr->p_memsz, phdr->p_filesz, phdr->p_offset);
5824
5825 if (segments == 0) {
5826 first_segment_idx = idx;
5827
5828 if (phdr->p_filesz == 0) {
5829 VG_(unimplemented)("Syswrap of the mmapobj call with the first "
5830 "loadable ELF program header specifying "
5831 "p_filesz == 0");
5832 /*NOTREACHED*/
5833 return res;
5834 }
5835
5836 /* Address of the first segment must be either NULL or within the
5837 first page. */
5838 if ((ehdr->e_type == VKI_ET_DYN) &&
5839 ((phdr->p_vaddr & VKI_PAGEMASK) != 0)) {
5840 if (VG_(clo_trace_syscalls))
5841 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
5842 "ELF program header #%u does not land on "
5843 "the first page (vaddr=%#lx)\n", idx,
5844 phdr->p_vaddr);
5845 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5846 }
5847
5848 start_addr = phdr->p_vaddr;
5849 /* The first segment is mapped from the beginning of the file (to
5850 include also the ELF header), so include this memory as well.
5851 Later on we flag this mapping with MR_HDR_ELF. */
5852 offset = phdr->p_offset;
5853 }
5854
5855 if (phdr->p_align > 1) {
5856 if ((phdr->p_vaddr % phdr->p_align) !=
5857 (phdr->p_offset % phdr->p_align)) {
5858 if (VG_(clo_trace_syscalls))
5859 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
5860 "ELF program header #%u does not have "
5861 "congruent offset and vaddr (vaddr=%#lx "
5862 "file offset=%#lx align=%#lx)\n", idx,
5863 phdr->p_vaddr, phdr->p_offset,
5864 phdr->p_align);
5865 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5866 }
5867 }
5868
5869 if (phdr->p_vaddr < end_addr) {
5870 if (VG_(clo_trace_syscalls))
5871 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
5872 "ELF program header #%u specifies overlaping "
5873 "address (vaddr=%#lx end_addr=%#lx)\n",
5874 idx, phdr->p_vaddr, end_addr);
5875 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5876 }
5877
iraisre8b9ee32015-08-31 21:31:09 +00005878 end_addr = elfbrk = phdr->p_vaddr + phdr->p_memsz + offset;
sewardj8eb8bab2015-07-21 14:44:28 +00005879 end_addr = VG_PGROUNDUP(end_addr);
5880 if (phdr->p_align > max_align) {
5881 max_align = phdr->p_align;
5882 }
5883
5884 segments += 1;
5885 }
5886 }
5887
5888 /* Alignment check - it should be power of two. */
5889 if ((max_align & (max_align - 1)) != 0) {
5890 if (VG_(clo_trace_syscalls))
5891 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: alignment "
5892 "is not a power of 2 (%#lx)\n", max_align);
5893 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5894 }
5895 vg_assert(max_align >= VKI_PAGE_SIZE);
5896
5897#if defined(VGP_x86_solaris)
5898 if (max_align > VKI_UINT_MAX) {
5899 if (VG_(clo_trace_syscalls))
5900 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: alignment "
5901 "for 32-bit ELF is >32-bits (%#lx)\n", max_align);
5902 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5903 }
5904#endif /* VGP_x86_solaris */
5905
5906 if (segments == 0) {
5907 if (VG_(clo_trace_syscalls))
5908 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: nothing "
5909 "to map (0 loadable segments)");
5910 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5911 }
5912
5913 vg_assert(end_addr >= start_addr);
5914 SizeT span = end_addr - start_addr;
5915 if (span == 0) {
5916 if (VG_(clo_trace_syscalls))
5917 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: nothing "
5918 "to map (%u loadable segments spanning 0 bytes)\n",
5919 segments);
5920 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5921 }
5922 vg_assert(first_segment_idx >= 0);
5923
5924 if (segments > *elements) {
5925 if (VG_(clo_trace_syscalls))
5926 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: too many "
5927 "segments (%u)\n", segments);
5928 return VG_(mk_SysRes_Error)(VKI_E2BIG);
5929 }
5930
5931 if (VG_(clo_trace_syscalls))
5932 VG_(debugLog)(2, "syswrap-solaris", "mmapobj_process_phdrs: there "
5933 "are %u loadable segments spanning %#lx bytes; max "
5934 "align is %#lx\n", segments, span, max_align);
5935
5936 /* Now get the aspacemgr oraculum advisory.
5937 Later on we mmap file-based and BSS mappings into this address space area
5938 as required and leave the holes unmapped. */
iraisre8b9ee32015-08-31 21:31:09 +00005939 if (ehdr->e_type == VKI_ET_DYN) {
5940 MapRequest mreq = {MAlign, max_align, span};
5941 Bool ok;
5942 start_addr = VG_(am_get_advisory)(&mreq, True /* forClient */, &ok);
5943 if (!ok) {
5944 if (VG_(clo_trace_syscalls))
5945 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
5946 "failed to reserve address space of %#lx bytes "
5947 "with alignment %#lx\n", span, max_align);
5948 return VG_(mk_SysRes_Error)(VKI_ENOMEM);
5949 }
5950 vg_assert(VG_ROUNDUP(start_addr, max_align) == start_addr);
sewardj8eb8bab2015-07-21 14:44:28 +00005951
iraisre8b9ee32015-08-31 21:31:09 +00005952 if (VG_(clo_trace_syscalls))
5953 VG_(debugLog)(2, "syswrap-solaris", "PRE(sys_mmapobj): address space "
5954 "reserved at: vaddr=%#lx size=%#lx\n",
5955 start_addr, span);
5956 } else {
5957 vg_assert(ehdr->e_type == VKI_ET_EXEC);
5958 /* ET_EXEC uses fixed mappings. Will be checked when processing phdrs. */
5959 }
sewardj8eb8bab2015-07-21 14:44:28 +00005960
5961 /* This is an utterly ugly hack, the aspacemgr assumes that only one
5962 segment is added at the time. However we add here multiple segments so
5963 AM_SANITY_CHECK inside the aspacemgr can easily fail. We want to
5964 prevent that thus we disable these checks. The scheduler will check the
5965 aspacemgr sanity after the syscall. */
5966 UInt sanity_level = VG_(clo_sanity_level);
5967 VG_(clo_sanity_level) = 1;
5968
5969 /* 2. Second pass over phdrs - map the program headers and fill in
5970 the mmapobj_result_t array. */
5971 phdr = phdrs;
5972 *elements = 0;
5973 for (idx = 0; idx < ehdr->e_phnum; idx++, phdr = ADVANCE_PHDR(ehdr, phdr)) {
5974 /* Skip this header if no memory is requested. */
5975 if (phdr->p_memsz == 0)
5976 continue;
5977
5978 if ((phdr->p_type == VKI_PT_LOAD) || (phdr->p_type == VKI_PT_SUNWBSS)) {
5979 UInt prot = 0;
5980 if (phdr->p_flags & VKI_PF_R)
5981 prot |= VKI_PROT_READ;
5982 if (phdr->p_flags & VKI_PF_W)
5983 prot |= VKI_PROT_WRITE;
5984 if (phdr->p_flags & VKI_PF_X)
5985 prot |= VKI_PROT_EXEC;
5986
5987 vki_mmapobj_result_t *mrp = &storage[*elements];
sewardj8eb8bab2015-07-21 14:44:28 +00005988 mrp->mr_msize = phdr->p_memsz;
5989 mrp->mr_fsize = phdr->p_filesz;
5990 mrp->mr_offset = 0;
5991 mrp->mr_prot = prot;
5992 mrp->mr_flags = 0;
5993 Off64T file_offset = phdr->p_offset;
5994 if (idx == first_segment_idx) {
5995 mrp->mr_flags = VKI_MR_HDR_ELF;
iraisre8b9ee32015-08-31 21:31:09 +00005996 if (ehdr->e_type == VKI_ET_DYN) {
5997 if (phdr->p_offset > 0) {
5998 /* Include the ELF header into the first segment.
5999 This means we ignore p_offset from the program header
6000 and map from file offset 0. */
6001 mrp->mr_msize += phdr->p_offset;
6002 mrp->mr_fsize += phdr->p_offset;
6003 file_offset = 0;
6004 }
6005 } else {
6006 vg_assert(ehdr->e_type == VKI_ET_EXEC);
6007 start_addr = phdr->p_vaddr;
sewardj8eb8bab2015-07-21 14:44:28 +00006008 }
6009 }
6010
iraisre8b9ee32015-08-31 21:31:09 +00006011 /* p_vaddr is absolute for ET_EXEC, and relative for ET_DYN. */
6012 mrp->mr_addr = (vki_caddr_t) phdr->p_vaddr;
6013 if (ehdr->e_type == VKI_ET_DYN) {
6014 mrp->mr_addr += start_addr;
6015 }
6016
sewardj8eb8bab2015-07-21 14:44:28 +00006017 SizeT page_offset = (Addr) mrp->mr_addr & VKI_PAGEOFFSET;
6018 if (page_offset > 0) {
6019 vg_assert(file_offset >= page_offset);
6020 /* Mapping address does not start at the beginning of a page.
6021 Therefore include some bytes before to make it page aligned. */
6022 mrp->mr_addr -= page_offset;
6023 mrp->mr_msize += page_offset;
6024 mrp->mr_offset = page_offset;
6025 file_offset -= page_offset;
6026 }
6027 SizeT file_size = mrp->mr_fsize + mrp->mr_offset;
6028 if (VG_(clo_trace_syscalls))
6029 VG_(debugLog)(2, "syswrap-solaris", "mmapobj_process_phdrs: "
6030 "mmapobj result #%u: addr=%#lx msize=%#lx "
6031 "fsize=%#lx mr_offset=%#lx prot=%#x flags=%#x\n",
6032 *elements, (Addr) mrp->mr_addr,
6033 (UWord) mrp->mr_msize, (UWord) mrp->mr_fsize,
6034 (UWord) mrp->mr_offset, mrp->mr_prot,
6035 mrp->mr_flags);
6036
6037 UInt flags = VKI_MAP_PRIVATE | VKI_MAP_FIXED;
6038 if ((mrp->mr_prot & (VKI_PROT_WRITE | VKI_PROT_EXEC)) ==
6039 VKI_PROT_EXEC) {
6040 flags |= VKI_MAP_TEXT;
6041 } else {
6042 flags |= VKI_MAP_INITDATA;
6043 }
6044
6045 /* Determine if there will be partially unused page after file-based
6046 mapping. If so, then we need to zero it explicitly afterwards. */
6047 Addr mapping_end = (Addr) mrp->mr_addr + file_size;
6048 SizeT zeroed_size = VG_PGROUNDUP(mapping_end) - mapping_end;
6049 Bool mprotect_needed = False;
6050 if ((zeroed_size > 0) && ((prot & VKI_PROT_WRITE) == 0)) {
6051 prot |= VKI_PROT_WRITE;
6052 mprotect_needed = True;
6053 }
6054
iraisre8b9ee32015-08-31 21:31:09 +00006055 if (ehdr->e_type == VKI_ET_EXEC) {
6056 /* Now check if the requested address space is available. */
6057 if (!VG_(am_is_free_or_resvn)((Addr) mrp->mr_addr, mrp->mr_msize)) {
6058 if (VG_(clo_trace_syscalls))
6059 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
6060 "requested segment at %#lx with size of "
6061 "%#lx bytes is not available\n",
6062 (Addr) mrp->mr_addr, (UWord) mrp->mr_msize);
6063 res = VG_(mk_SysRes_Error)(VKI_EADDRINUSE);
6064 goto mmap_error;
6065 }
6066 }
6067
sewardj8eb8bab2015-07-21 14:44:28 +00006068 if (file_size > 0) {
6069 res = VG_(am_mmap_file_fixed_client_flags)((Addr) mrp->mr_addr,
6070 file_size, prot, flags, fd, file_offset);
6071 if (sr_isError(res)) {
6072 if (VG_(clo_trace_syscalls))
6073 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
6074 "mmap failed: addr=%#lx size=%#lx prot=%#x "
6075 "flags=%#x fd=%d file offset=%#llx\n",
6076 (Addr) mrp->mr_addr, file_size,
6077 prot, flags, fd, file_offset);
6078 goto mmap_error;
6079 }
6080
6081 VG_(debugLog)(1, "syswrap-solaris", "PRE(sys_mmapobj): new "
6082 "segment: vaddr=%#lx size=%#lx prot=%#x "
6083 "flags=%#x fd=%d file offset=%#llx\n",
6084 (Addr) mrp->mr_addr, file_size, mrp->mr_prot,
6085 flags, fd, file_offset);
6086 }
6087
6088 if (zeroed_size > 0) {
6089 /* Now zero out the end of partially used page. */
6090 VG_(memset)((void *) mapping_end, 0, zeroed_size);
6091 if (mprotect_needed) {
6092 prot &= ~VKI_PROT_WRITE;
6093 res = VG_(do_syscall3)(SYS_mprotect, (Addr) mrp->mr_addr,
6094 file_size, prot);
6095 if (sr_isError(res)) {
6096 if (VG_(clo_trace_syscalls))
6097 VG_(debugLog)(3, "syswrap-solaris",
6098 "mmapobj_process_phdrs: mprotect failed: "
6099 "addr=%#lx size=%#lx prot=%#x",
6100 (Addr) mrp->mr_addr, file_size, prot);
6101 /* Mapping for this segment was already established. */
6102 idx += 1;
6103 goto mmap_error;
6104 }
6105 }
6106 }
6107
6108 if (file_size > 0) {
6109 ML_(notify_core_and_tool_of_mmap)((Addr) mrp->mr_addr, file_size,
6110 prot, flags, fd, file_offset);
6111 }
6112
6113 /* Page(s) after the mapping backed up by the file are part of BSS.
6114 They need to be mmap'ed over with correct flags and will be
6115 implicitly zeroed. */
6116 mapping_end = VG_PGROUNDUP(mrp->mr_addr + mrp->mr_msize);
6117 Addr page_end = VG_PGROUNDUP(mrp->mr_addr + file_size);
6118 vg_assert(mapping_end >= page_end);
6119 zeroed_size = mapping_end - page_end;
6120 if (zeroed_size > 0) {
6121 flags = VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS;
6122 res = VG_(am_mmap_anon_fixed_client)(page_end, zeroed_size, prot);
6123 if (sr_isError(res)) {
6124 if (VG_(clo_trace_syscalls))
6125 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
6126 "mmap_anon failed: addr=%#lx size=%#lx "
6127 "prot=%#x\n", page_end, zeroed_size, prot);
6128 idx += 1; /* mapping for this segment was already established */
6129 goto mmap_error;
6130 }
6131
6132 VG_(debugLog)(1, "syswrap-solaris", "PRE(sys_mmapobj): new "
6133 "anonymous segment (BSS): vaddr=%#lx size=%#lx "
6134 "prot=%#x\n", page_end, zeroed_size, prot);
6135 ML_(notify_core_and_tool_of_mmap)(page_end, zeroed_size,
6136 prot, flags, -1, 0);
6137 }
6138
6139 VG_(di_notify_mmap)((Addr) mrp->mr_addr, False /*allow_SkFileV*/, fd);
6140
6141 *elements += 1;
6142 vg_assert(*elements <= segments);
6143 }
6144 }
6145
iraisre8b9ee32015-08-31 21:31:09 +00006146 if ((ehdr->e_type == VKI_ET_EXEC) && (!brk_segment_established)) {
6147 vg_assert(VG_(brk_base) == VG_(brk_limit));
6148 vg_assert(VG_(brk_base) == -1);
6149 VG_(brk_base) = VG_(brk_limit) = elfbrk;
6150
6151 if (!VG_(setup_client_dataseg)()) {
6152 VG_(umsg)("Cannot map memory to initialize brk segment in thread #%d "
6153 "at %#lx\n", tid, VG_(brk_base));
6154 res = VG_(mk_SysRes_Error)(VKI_ENOMEM);
6155 goto mmap_error;
6156 }
6157
6158 VG_(track_client_dataseg)(tid);
6159 }
6160
sewardj8eb8bab2015-07-21 14:44:28 +00006161 /* Restore VG_(clo_sanity_level). The scheduler will perform the aspacemgr
6162 sanity check after the syscall. */
6163 VG_(clo_sanity_level) = sanity_level;
6164
6165 return VG_(mk_SysRes_Success)(0);
6166
6167mmap_error:
6168 for (i = idx - 1; i > 0; i--) {
6169 Bool discard_translations;
6170 Addr addr = (Addr) storage[i].mr_addr;
6171
6172 VG_(am_munmap_client)(&discard_translations, addr, storage[i].mr_msize);
6173 ML_(notify_core_and_tool_of_munmap)(addr, storage[i].mr_msize);
6174 }
6175 *elements = 0;
6176 return res;
6177
6178#undef ADVANCE_PHDR
6179}
6180
6181static SysRes mmapobj_interpret(ThreadId tid, Int fd,
6182 vki_mmapobj_result_t *storage,
6183 vki_uint_t *elements)
6184{
6185 SysRes res;
6186
6187 struct vg_stat stats;
6188 if (VG_(fstat)(fd, &stats) != 0) {
6189 return VG_(mk_SysRes_Error)(VKI_EBADF);
6190 }
6191
6192 if (stats.size < sizeof(VKI_ESZ(Ehdr))) {
6193 if (VG_(clo_trace_syscalls))
6194 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: insufficient "
6195 "file size (%lld)\n", stats.size);
6196 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6197 }
6198
6199 /* Align the header buffer appropriately. */
6200 vki_ulong_t lheader[sizeof(VKI_ESZ(Ehdr)) / sizeof(vki_ulong_t) + 1];
6201 HChar *header = (HChar *) &lheader;
6202
6203 res = VG_(pread)(fd, header, sizeof(VKI_ESZ(Ehdr)), 0);
6204 if (sr_isError(res)) {
6205 if (VG_(clo_trace_syscalls))
6206 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: read of ELF "
6207 "header failed\n");
6208 return res;
6209 } else if (sr_Res(res) != sizeof(VKI_ESZ(Ehdr))) {
6210 if (VG_(clo_trace_syscalls))
6211 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: read of ELF "
6212 "header failed - only %lu bytes out of %lu\n",
6213 sr_Res(res), (UWord) sizeof(VKI_ESZ(Ehdr)));
6214 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6215 }
6216
6217 /* Verify file type is ELF. */
6218 if ((header[VKI_EI_MAG0] != VKI_ELFMAG0) ||
6219 (header[VKI_EI_MAG1] != VKI_ELFMAG1) ||
6220 (header[VKI_EI_MAG2] != VKI_ELFMAG2) ||
6221 (header[VKI_EI_MAG3] != VKI_ELFMAG3)) {
6222 if (VG_(clo_trace_syscalls))
6223 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: ELF header "
6224 "missing magic\n");
6225 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6226 }
6227
6228 if (header[VKI_EI_CLASS] != VG_ELF_CLASS) {
6229 if (VG_(clo_trace_syscalls))
6230 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: ELF class "
6231 "mismatch (%u vs %u)\n", header[VKI_EI_CLASS],
6232 VG_ELF_CLASS);
6233 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6234 }
6235
6236 VKI_ESZ(Ehdr) *ehdr = (VKI_ESZ(Ehdr) *) header;
iraisre8b9ee32015-08-31 21:31:09 +00006237 if ((ehdr->e_type != VKI_ET_EXEC) && (ehdr->e_type != VKI_ET_DYN)) {
sewardj8eb8bab2015-07-21 14:44:28 +00006238 VG_(unimplemented)("Syswrap of the mmapobj call with ELF type %u.",
6239 ehdr->e_type);
6240 /*NOTREACHED*/
6241 return res;
6242 }
6243
6244 if (ehdr->e_phnum == VKI_PN_XNUM) {
6245 VG_(unimplemented)("Syswrap of the mmapobj call with number of ELF "
6246 "program headers == PN_XNUM");
6247 /*NOTREACHED*/
6248 return res;
6249 }
6250
6251 /* Check alignment. */
6252#if defined(VGP_x86_solaris)
6253 if (!VG_IS_4_ALIGNED(ehdr->e_phentsize)) {
6254#elif defined(VGP_amd64_solaris)
6255 if (!VG_IS_8_ALIGNED(ehdr->e_phentsize)) {
6256#else
6257# error "Unknown platform"
6258#endif
6259 if (VG_(clo_trace_syscalls))
6260 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: ELF header "
6261 "phentsize not aligned properly (%u)\n",
6262 ehdr->e_phentsize);
6263 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6264 }
6265
6266 SizeT phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
6267 if (phdrs_size == 0) {
6268 if (VG_(clo_trace_syscalls))
6269 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: no ELF "
6270 "program headers\n");
6271 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6272 }
6273
6274 VKI_ESZ(Phdr) *phdrs = VG_(malloc)("syswrap.mi.1", phdrs_size);
6275 res = VG_(pread)(fd, phdrs, phdrs_size, ehdr->e_phoff);
6276 if (sr_isError(res)) {
6277 if (VG_(clo_trace_syscalls))
6278 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: read of ELF "
6279 "program headers failed\n");
6280 VG_(free)(phdrs);
6281 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6282 } else if (sr_Res(res) != phdrs_size) {
6283 if (VG_(clo_trace_syscalls))
6284 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: read of ELF "
6285 "program headers failed - only %lu bytes out of %lu\n",
6286 sr_Res(res), phdrs_size);
6287 VG_(free)(phdrs);
6288 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6289 }
6290
6291 if (VG_(clo_trace_syscalls))
6292 VG_(debugLog)(2, "syswrap-solaris", "mmapobj_interpret: %u ELF "
6293 "program headers with total size of %lu bytes\n",
6294 ehdr->e_phnum, phdrs_size);
6295
6296 /* Now process the program headers. */
6297 res = mmapobj_process_phdrs(tid, fd, storage, elements, ehdr, phdrs);
6298 VG_(free)(phdrs);
6299 return res;
6300}
6301
6302PRE(sys_mmapobj)
6303{
6304 /* int mmapobj(int fd, uint_t flags, mmapobj_result_t *storage,
6305 uint_t *elements, void *arg); */
florianb26101c2015-08-08 21:45:33 +00006306 PRINT("sys_mmapobj ( %ld, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00006307 ARG4, ARG5);
6308 PRE_REG_READ5(long, "mmapobj", int, fd, vki_uint_t, flags,
6309 mmapobj_result_t *, storage, uint_t *, elements,
6310 void *, arg);
6311
6312 PRE_MEM_READ("mmapobj(elements)", ARG4, sizeof(vki_uint_t));
6313 /*PRE_MEM_WRITE("mmapobj(elements)", ARG4, sizeof(vki_uint_t));*/
6314 if (ML_(safe_to_deref)((void*)ARG4, sizeof(vki_uint_t))) {
6315 vki_uint_t *u = (vki_uint_t*)ARG4;
6316 PRE_MEM_WRITE("mmapobj(storage)", ARG3,
6317 *u * sizeof(vki_mmapobj_result_t));
6318 }
6319
6320 if (ARG2 & VKI_MMOBJ_PADDING)
6321 PRE_MEM_READ("mmapobj(arg)", ARG5, sizeof(vki_size_t));
6322
6323 /* Be strict. */
6324 if (!ML_(fd_allowed)(ARG1, "mmapobj", tid, False)) {
6325 SET_STATUS_Failure(VKI_EBADF);
6326 return;
6327 }
6328
6329 /* We cannot advise mmapobj about desired address(es). Unfortunately
6330 kernel places mappings from mmapobj at the end of process address
6331 space, defeating memcheck's optimized fast 2-level array algorithm.
6332 So we need to emulate what mmapobj does in the kernel. */
6333
6334 /* Sanity check on parameters. */
6335 if ((ARG2 & ~VKI_MMOBJ_ALL_FLAGS) != 0) {
6336 SET_STATUS_Failure(VKI_EINVAL);
6337 return;
6338 }
6339
6340 if (!ML_(safe_to_deref)((void *) ARG4, sizeof(vki_uint_t))) {
6341 SET_STATUS_Failure(VKI_EFAULT);
6342 return;
6343 }
6344 vki_uint_t *elements = (vki_uint_t *) ARG4;
6345
6346 if (*elements > 0) {
6347 if (!ML_(safe_to_deref)((void *) ARG3,
6348 *elements * sizeof(vki_mmapobj_result_t))) {
6349 SET_STATUS_Failure(VKI_EFAULT);
6350 return;
6351 }
6352 }
6353
6354 /* For now, supported is only MMOBJ_INTERPRET and no MMOBJ_PADDING. */
6355 if (ARG2 != VKI_MMOBJ_INTERPRET) {
florianb26101c2015-08-08 21:45:33 +00006356 VG_(unimplemented)("Syswrap of the mmapobj call with flags %lu.", ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00006357 /*NOTREACHED*/
6358 return;
6359 }
6360
6361 SysRes res = mmapobj_interpret(tid, (Int) ARG1,
6362 (vki_mmapobj_result_t *) ARG3, elements);
6363 SET_STATUS_from_SysRes(res);
6364
6365 if (!sr_isError(res)) {
6366 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
6367
6368 UInt idx;
6369 for (idx = 0; idx < *(vki_uint_t *) ARG4; idx++) {
6370 vki_mmapobj_result_t *mrp = &((vki_mmapobj_result_t *) ARG3)[idx];
6371 POST_FIELD_WRITE(mrp->mr_addr);
6372 POST_FIELD_WRITE(mrp->mr_msize);
6373 POST_FIELD_WRITE(mrp->mr_fsize);
6374 POST_FIELD_WRITE(mrp->mr_prot);
6375 POST_FIELD_WRITE(mrp->mr_flags);
6376 POST_FIELD_WRITE(mrp->mr_offset);
6377 }
6378 }
6379}
6380
6381PRE(sys_memcntl)
6382{
6383 /* int memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg,
6384 int attr, int mask); */
6385 PRINT("sys_memcntl ( %#lx, %#lx, %ld, %#lx, %#lx, %#lx )", ARG1, ARG2,
florianb26101c2015-08-08 21:45:33 +00006386 SARG3, ARG4, ARG5, ARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00006387 PRE_REG_READ6(long, "memcntl", void *, addr, vki_size_t, len, int, cmd,
6388 void *, arg, int, attr, int, mask);
6389
6390 if (ARG3 != VKI_MC_LOCKAS && ARG3 != VKI_MC_UNLOCKAS &&
6391 !ML_(valid_client_addr)(ARG1, ARG2, tid, "memcntl")) {
6392 /* MC_LOCKAS and MC_UNLOCKAS work on the complete address space thus we
6393 don't check the address range validity if these commands are
6394 requested. */
6395 SET_STATUS_Failure(VKI_ENOMEM);
6396 return;
6397 }
6398
6399 if (ARG3 == VKI_MC_HAT_ADVISE)
6400 PRE_MEM_READ("memcntl(arg)", ARG4, sizeof(struct vki_memcntl_mha));
6401}
6402
6403PRE(sys_getpmsg)
6404{
6405 /* int getpmsg(int fildes, struct strbuf *ctlptr, struct strbuf *dataptr,
6406 int *bandp, int *flagsp); */
6407 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
6408 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
6409 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00006410 PRINT("sys_getpmsg ( %ld, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00006411 ARG4, ARG5);
6412 PRE_REG_READ5(long, "getpmsg", int, fildes, struct vki_strbuf *, ctlptr,
6413 struct vki_strbuf *, dataptr, int *, bandp, int *, flagsp);
6414 if (ctrlptr) {
6415 PRE_FIELD_READ("getpmsg(ctrlptr->maxlen)", ctrlptr->maxlen);
6416 PRE_FIELD_WRITE("getpmsg(ctrlptr->len)", ctrlptr->len);
6417 PRE_FIELD_READ("getpmsg(ctrlptr->buf)", ctrlptr->buf);
6418 if (ML_(safe_to_deref)((void*)ARG2, sizeof(struct vki_strbuf))
6419 && ctrlptr->maxlen > 0)
6420 PRE_MEM_WRITE("getpmsg(ctrlptr->buf)", (Addr)ctrlptr->buf,
6421 ctrlptr->maxlen);
6422 }
6423 if (dataptr) {
6424 PRE_FIELD_READ("getpmsg(dataptr->maxlen)", dataptr->maxlen);
6425 PRE_FIELD_WRITE("getpmsg(dataptr->len)", dataptr->len);
6426 PRE_FIELD_READ("getpmsg(dataptr->buf)", dataptr->buf);
6427 if (ML_(safe_to_deref)((void*)ARG3, sizeof(struct vki_strbuf))
6428 && dataptr->maxlen > 0)
6429 PRE_MEM_WRITE("getpmsg(dataptr->buf)", (Addr)dataptr->buf,
6430 dataptr->maxlen);
6431 }
6432 PRE_MEM_READ("getpmsg(bandp)", ARG4, sizeof(int));
6433 /*PRE_MEM_WRITE("getpmsg(bandp)", ARG4, sizeof(int));*/
6434 PRE_MEM_READ("getpmsg(flagsp)", ARG5, sizeof(int));
6435 /*PRE_MEM_WRITE("getpmsg(flagsp)", ARG5, sizeof(int));*/
6436
6437 /* Be strict. */
6438 if (!ML_(fd_allowed)(ARG1, "getpmsg", tid, False))
6439 SET_STATUS_Failure(VKI_EBADF);
6440}
6441
6442POST(sys_getpmsg)
6443{
6444 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
6445 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
6446
6447 if (ctrlptr && ctrlptr->len > 0)
6448 POST_MEM_WRITE((Addr)ctrlptr->buf, ctrlptr->len);
6449 if (dataptr && dataptr->len > 0)
6450 POST_MEM_WRITE((Addr)dataptr->buf, dataptr->len);
6451 POST_MEM_WRITE(ARG4, sizeof(int));
6452 POST_MEM_WRITE(ARG5, sizeof(int));
6453}
6454
6455PRE(sys_putpmsg)
6456{
6457 /* int putpmsg(int fildes, const struct strbuf *ctlptr,
6458 const struct strbuf *dataptr, int band, int flags); */
6459 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
6460 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
6461 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00006462 PRINT("sys_putpmsg ( %ld, %#lx, %#lx, %ld, %ld )", SARG1, ARG2, ARG3, SARG4,
6463 SARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00006464 PRE_REG_READ5(long, "putpmsg", int, fildes, struct vki_strbuf *, ctrlptr,
6465 struct vki_strbuf *, dataptr, int, band, int, flags);
6466 if (ctrlptr) {
6467 PRE_FIELD_READ("putpmsg(ctrlptr->len)", ctrlptr->len);
6468 PRE_FIELD_READ("putpmsg(ctrlptr->buf)", ctrlptr->buf);
6469 if (ML_(safe_to_deref)((void*)ARG2, sizeof(struct vki_strbuf))
6470 && ctrlptr->len > 0)
6471 PRE_MEM_READ("putpmsg(ctrlptr->buf)", (Addr)ctrlptr->buf,
6472 ctrlptr->len);
6473 }
6474 if (dataptr) {
6475 PRE_FIELD_READ("putpmsg(dataptr->len)", dataptr->len);
6476 PRE_FIELD_READ("putpmsg(dataptr->buf)", dataptr->buf);
6477 if (ML_(safe_to_deref)((void*)ARG3, sizeof(struct vki_strbuf))
6478 && dataptr->len > 0)
6479 PRE_MEM_READ("putpmsg(dataptr->buf)", (Addr)dataptr->buf,
6480 dataptr->len);
6481 }
6482
6483 /* Be strict. */
6484 if (!ML_(fd_allowed)(ARG1, "putpmsg", tid, False))
6485 SET_STATUS_Failure(VKI_EBADF);
6486}
6487
6488#if defined(SOLARIS_OLD_SYSCALLS)
6489PRE(sys_rename)
6490{
6491 /* int rename(const char *from, const char *to); */
6492
6493 *flags |= SfMayBlock;
6494 PRINT("sys_rename ( %#lx(%s), %#lx(%s) )",
florianb26101c2015-08-08 21:45:33 +00006495 ARG1, (HChar *) ARG1, ARG2, (HChar *) ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00006496 PRE_REG_READ2(long, "rename", const char *, from, const char *, to);
6497
6498 PRE_MEM_RASCIIZ("rename(from)", ARG1);
6499 PRE_MEM_RASCIIZ("rename(to)", ARG2);
6500}
6501#endif /* SOLARIS_OLD_SYSCALLS */
6502
6503PRE(sys_uname)
6504{
6505 /* int uname(struct utsname *name); */
6506 PRINT("sys_uname ( %#lx )", ARG1);
6507 PRE_REG_READ1(long, "uname", struct vki_utsname *, name);
6508 PRE_MEM_WRITE("uname(name)", ARG1, sizeof(struct vki_utsname));
6509}
6510
6511POST(sys_uname)
6512{
6513 struct vki_utsname *name = (struct vki_utsname *) ARG1;
6514 POST_MEM_WRITE((Addr) name->sysname, VG_(strlen)(name->sysname) + 1);
6515 POST_MEM_WRITE((Addr) name->nodename, VG_(strlen)(name->nodename) + 1);
6516 POST_MEM_WRITE((Addr) name->release, VG_(strlen)(name->release) + 1);
6517 POST_MEM_WRITE((Addr) name->version, VG_(strlen)(name->version) + 1);
6518 POST_MEM_WRITE((Addr) name->machine, VG_(strlen)(name->machine) + 1);
6519}
6520
6521PRE(sys_setegid)
6522{
6523 /* int setegid(gid_t egid); */
florianb26101c2015-08-08 21:45:33 +00006524 PRINT("sys_setegid ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00006525 PRE_REG_READ1(long, "setegid", vki_gid_t, egid);
6526}
6527
6528PRE(sys_sysconfig)
6529{
6530 /* long sysconf(int name); */
florianb26101c2015-08-08 21:45:33 +00006531 PRINT("sys_sysconfig ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00006532 PRE_REG_READ1(long, "sysconf", int, name);
6533
6534 if (ARG1 == VKI_CONFIG_OPEN_FILES)
6535 SET_STATUS_Success(VG_(fd_soft_limit));
6536}
6537
6538PRE(sys_systeminfo)
6539{
6540 /* int sysinfo(int command, char *buf, long count); */
florianb26101c2015-08-08 21:45:33 +00006541 PRINT("sys_systeminfo ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00006542 PRE_REG_READ3(long, "sysinfo", int, command, char *, buf, long, count);
6543
6544 switch (ARG1 /*command*/) {
6545 case VKI_SI_SYSNAME:
6546 case VKI_SI_HOSTNAME:
6547 case VKI_SI_RELEASE:
6548 case VKI_SI_VERSION:
6549 case VKI_SI_MACHINE:
6550 case VKI_SI_ARCHITECTURE:
6551 case VKI_SI_HW_SERIAL:
6552 case VKI_SI_HW_PROVIDER:
6553 case VKI_SI_SRPC_DOMAIN:
6554 case VKI_SI_PLATFORM:
6555 case VKI_SI_ISALIST:
6556 case VKI_SI_DHCP_CACHE:
6557 case VKI_SI_ARCHITECTURE_32:
6558 case VKI_SI_ARCHITECTURE_64:
6559 case VKI_SI_ARCHITECTURE_K:
6560 case VKI_SI_ARCHITECTURE_NATIVE:
6561 PRE_MEM_WRITE("sysinfo(buf)", ARG2, ARG3);
6562 break;
6563
6564 case VKI_SI_SET_HOSTNAME:
6565 case VKI_SI_SET_SRCP_DOMAIN:
6566 PRE_MEM_RASCIIZ("sysinfo(buf)", ARG2);
6567 break;
6568
6569 default:
florianb26101c2015-08-08 21:45:33 +00006570 VG_(unimplemented)("Syswrap of the sysinfo call with command %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00006571 /*NOTREACHED*/
6572 break;
6573 }
6574}
6575
6576POST(sys_systeminfo)
6577{
6578 if (ARG1 != VKI_SI_SET_HOSTNAME && ARG1 != VKI_SI_SET_SRCP_DOMAIN)
6579 POST_MEM_WRITE(ARG2, MIN(RES, ARG3));
6580}
6581
6582PRE(sys_seteuid)
6583{
6584 /* int seteuid(uid_t euid); */
florianb26101c2015-08-08 21:45:33 +00006585 PRINT("sys_seteuid ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00006586 PRE_REG_READ1(long, "seteuid", vki_uid_t, euid);
6587}
6588
6589PRE(sys_forksys)
6590{
6591 /* int64_t forksys(int subcode, int flags); */
6592 Int fds[2];
6593 Int res;
florianb26101c2015-08-08 21:45:33 +00006594 PRINT("sys_forksys ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00006595 PRE_REG_READ2(long, "forksys", int, subcode, int, flags);
6596
6597 if (ARG1 == 1) {
6598 /* Support for forkall() requires changes to the big lock processing
6599 which are not yet implemented. */
6600 VG_(unimplemented)("Support for forkall().");
6601 /*NOTREACHED*/
6602 return;
6603 }
6604
6605 if (ARG1 != 0 && ARG1 != 2) {
6606 VG_(unimplemented)("Syswrap of the forksys call where subcode=%ld.",
florianb26101c2015-08-08 21:45:33 +00006607 SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00006608 /*NOTREACHED*/
6609 }
6610
6611 if (ARG1 == 2) {
6612 /* vfork() is requested. Translate it to a normal fork() but work around
6613 a problem with posix_spawn() which relies on the real vfork()
6614 behaviour. See a description in vg_preloaded.c for details. */
6615 res = VG_(pipe)(fds);
6616 vg_assert(res == 0);
6617
6618 vg_assert(fds[0] != fds[1]);
6619
6620 /* Move to Valgrind fds and set close-on-exec flag on both of them (done
6621 by VG_(safe_fd). */
6622 fds[0] = VG_(safe_fd)(fds[0]);
6623 fds[1] = VG_(safe_fd)(fds[1]);
6624 vg_assert(fds[0] != fds[1]);
6625
6626 vg_assert(VG_(vfork_fildes_addr) != NULL);
6627 vg_assert(*VG_(vfork_fildes_addr) == -1);
6628 *VG_(vfork_fildes_addr) = fds[0];
6629 }
6630
6631 VG_(do_atfork_pre)(tid);
6632 SET_STATUS_from_SysRes(VG_(do_syscall2)(__NR_forksys, 0, ARG2));
6633
6634 if (!SUCCESS) {
6635 /* vfork */
6636 if (ARG1 == 2) {
6637 VG_(close)(fds[0]);
6638 VG_(close)(fds[1]);
6639 }
6640
6641 return;
6642 }
6643
6644 if (RESHI) {
6645 VG_(do_atfork_child)(tid);
6646
sewardj8eb8bab2015-07-21 14:44:28 +00006647 /* vfork */
6648 if (ARG1 == 2)
6649 VG_(close)(fds[1]);
Elliott Hughesa0664b92017-04-18 17:46:52 -07006650
6651# if defined(SOLARIS_PT_SUNDWTRACE_THRP)
6652 /* Kernel can map a new page as a scratch space of the DTrace fasttrap
6653 provider. There is no way we can directly get its address - it's all
6654 private to the kernel. Fish it the slow way. */
6655 Addr addr;
6656 SizeT size;
6657 UInt prot;
6658 Bool found = VG_(am_search_for_new_segment)(&addr, &size, &prot);
6659 if (found) {
6660 VG_(debugLog)(1, "syswrap-solaris", "PRE(forksys), new segment: "
6661 "vaddr=%#lx, size=%#lx, prot=%#x\n", addr, size, prot);
6662 vg_assert(prot == (VKI_PROT_READ | VKI_PROT_EXEC));
6663 vg_assert(size == VKI_PAGE_SIZE);
6664 ML_(notify_core_and_tool_of_mmap)(addr, size, prot, VKI_MAP_ANONYMOUS,
6665 -1, 0);
6666
6667 /* Note: We don't notify the debuginfo reader about this mapping
6668 because there is no debug information stored in this segment. */
6669 }
6670# endif /* SOLARIS_PT_SUNDWTRACE_THRP */
sewardj8eb8bab2015-07-21 14:44:28 +00006671 }
6672 else {
6673 VG_(do_atfork_parent)(tid);
6674
6675 /* Print information about the fork. */
6676 PRINT(" fork: process %d created child %d\n", VG_(getpid)(),
6677 (Int)RES);
6678
6679 /* vfork */
6680 if (ARG1 == 2) {
6681 /* Wait for the child to finish (exec or exit). */
6682 UChar w;
6683
6684 VG_(close)(fds[0]);
6685
6686 res = VG_(read)(fds[1], &w, 1);
6687 if (res == 1)
6688 SET_STATUS_Failure(w);
6689 VG_(close)(fds[1]);
6690
6691 *VG_(vfork_fildes_addr) = -1;
6692 }
6693 }
6694}
6695
Elliott Hughesa0664b92017-04-18 17:46:52 -07006696#if defined(SOLARIS_GETRANDOM_SYSCALL)
6697PRE(sys_getrandom)
6698{
6699 /* int getrandom(void *buf, size_t buflen, uint_t flags); */
6700 PRINT("sys_getrandom ( %#lx, %lu, %lu )", ARG1, ARG2, ARG3);
6701 PRE_REG_READ3(long, "getrandom", void *, buf, vki_size_t, buflen,
6702 vki_uint_t, flags);
6703 PRE_MEM_WRITE("getrandom(buf)", ARG1, ARG2);
6704}
6705
6706POST(sys_getrandom)
6707{
6708 POST_MEM_WRITE(ARG1, RES);
6709}
6710#endif /* SOLARIS_GETRANDOM_SYSCALL */
6711
sewardj8eb8bab2015-07-21 14:44:28 +00006712PRE(sys_sigtimedwait)
6713{
6714 /* int sigtimedwait(const sigset_t *set, siginfo_t *info,
6715 const timespec_t *timeout); */
6716 *flags |= SfMayBlock;
6717 PRINT("sys_sigtimedwait ( %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3);
6718 PRE_REG_READ3(long, "sigtimedwait", vki_sigset_t *, set,
6719 vki_siginfo_t *, info, vki_timespec_t *, timeout);
6720 PRE_MEM_READ("sigtimewait(set)", ARG1, sizeof(vki_sigset_t));
6721 if (ARG2)
6722 PRE_MEM_WRITE("sigtimedwait(info)", ARG2, sizeof(vki_siginfo_t));
6723 if (ARG3)
6724 PRE_MEM_READ("sigtimedwait(timeout)", ARG3, sizeof(vki_timespec_t));
6725}
6726
6727POST(sys_sigtimedwait)
6728{
6729 if (ARG2)
6730 POST_MEM_WRITE(ARG2, sizeof(vki_siginfo_t));
6731}
6732
6733PRE(sys_yield)
6734{
6735 /* void yield(void); */
6736 *flags |= SfMayBlock;
6737 PRINT("sys_yield ( )");
6738 PRE_REG_READ0(long, "yield");
6739}
6740
6741PRE(sys_lwp_sema_post)
6742{
6743 /* int lwp_sema_post(lwp_sema_t *sema); */
6744 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
6745 *flags |= SfMayBlock;
6746 PRINT("sys_lwp_sema_post ( %#lx )", ARG1);
6747 PRE_REG_READ1(long, "lwp_sema_post", lwp_sema_t *, sema);
6748
6749 PRE_FIELD_READ("lwp_sema_post(sema->type)", sema->vki_sema_type);
6750 PRE_FIELD_READ("lwp_sema_post(sema->count)", sema->vki_sema_count);
6751 /*PRE_FIELD_WRITE("lwp_sema_post(sema->count)", sema->vki_sema_count);*/
6752 PRE_FIELD_READ("lwp_sema_post(sema->waiters)", sema->vki_sema_waiters);
6753 /*PRE_FIELD_WRITE("lwp_sema_post(sema->waiters)", sema->vki_sema_waiters);*/
6754}
6755
6756POST(sys_lwp_sema_post)
6757{
6758 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
6759 POST_FIELD_WRITE(sema->vki_sema_count);
6760 POST_FIELD_WRITE(sema->vki_sema_waiters);
6761}
6762
6763PRE(sys_lwp_sema_trywait)
6764{
6765 /* int lwp_sema_trywait(lwp_sema_t *sema); */
6766 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
6767 PRINT("sys_lwp_sema_trywait ( %#lx )", ARG1);
6768 PRE_REG_READ1(long, "lwp_sema_trywait", lwp_sema_t *, sema);
6769
6770 PRE_FIELD_READ("lwp_sema_trywait(sema->type)", sema->vki_sema_type);
6771 PRE_FIELD_READ("lwp_sema_trywait(sema->count)", sema->vki_sema_count);
6772 /*PRE_FIELD_WRITE("lwp_sema_trywait(sema->count)", sema->vki_sema_count);*/
6773 PRE_FIELD_READ("lwp_sema_trywait(sema->waiters)", sema->vki_sema_waiters);
6774 /*PRE_FIELD_WRITE("lwp_sema_trywait(sema->waiters)",
6775 sema->vki_sema_waiters);*/
6776}
6777
6778POST(sys_lwp_sema_trywait)
6779{
6780 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
6781 POST_FIELD_WRITE(sema->vki_sema_count);
6782 POST_FIELD_WRITE(sema->vki_sema_waiters);
6783}
6784
6785PRE(sys_lwp_detach)
6786{
6787 /* int lwp_detach(id_t lwpid); */
florianb26101c2015-08-08 21:45:33 +00006788 PRINT("sys_lwp_detach ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00006789 PRE_REG_READ1(long, "lwp_detach", vki_id_t, lwpid);
6790}
6791
Elliott Hughesa0664b92017-04-18 17:46:52 -07006792PRE(sys_modctl)
6793{
6794 /* int modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3,
6795 uintptr_t a4, uintptr_t a5); */
6796 *flags |= SfMayBlock;
6797
6798 switch (ARG1 /*cmd*/) {
6799 case VKI_MODLOAD:
6800 /* int modctl_modload(int use_path, char *filename, int *rvp); */
6801 PRINT("sys_modctl ( %ld, %ld, %#lx(%s), %#lx )",
6802 SARG1, ARG2, ARG3, (HChar *) ARG3, ARG4);
6803 PRE_REG_READ4(long, SC2("modctl", "modload"),
6804 int, cmd, int, use_path, char *, filename, int *, rvp);
6805 PRE_MEM_RASCIIZ("modctl(filaneme)", ARG3);
6806 if (ARG4 != 0) {
6807 PRE_MEM_WRITE("modctl(rvp)", ARG4, sizeof(int *));
6808 }
6809 break;
6810 case VKI_MODUNLOAD:
6811 /* int modctl_modunload(modid_t id); */
6812 PRINT("sys_modctl ( %ld, %ld )", SARG1, SARG2);
6813 PRE_REG_READ2(long, SC2("modctl", "modunload"),
6814 int, cmd, vki_modid_t, id);
6815 break;
6816 case VKI_MODINFO: {
6817 /* int modctl_modinfo(modid_t id, struct modinfo *umodi); */
6818 PRINT("sys_modctl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
6819 PRE_REG_READ3(long, SC2("modctl", "modinfo"),
6820 int, cmd, vki_modid_t, id, struct modinfo *, umodi);
6821
6822 struct vki_modinfo *umodi = (struct vki_modinfo *) ARG3;
6823 PRE_FIELD_READ("modctl(umodi->mi_info)", umodi->mi_info);
6824 PRE_FIELD_READ("modctl(umodi->mi_id)", umodi->mi_id);
6825 PRE_FIELD_READ("modctl(umodi->mi_nextid)", umodi->mi_nextid);
6826 PRE_MEM_WRITE("modctl(umodi)", ARG3, sizeof(struct vki_modinfo));
6827 break;
6828 }
6829
6830# if defined(SOLARIS_MODCTL_MODNVL)
6831 case VKI_MODNVL_DEVLINKSYNC:
6832 /* int modnvl_devlinksync(sysnvl_op_t a1, uintptr_t a2, uintptr_t a3,
6833 uintptr_t a4); */
6834 switch (ARG2 /*op*/) {
6835
6836# if defined(HAVE_SYS_SYSNVL_H)
6837 case VKI_SYSNVL_OP_GET:
6838 PRE_REG_READ5(long, SC3("modctl", "modnvl_devlinksync", "get"),
6839 int, cmd, sysnvl_op_t, a1, char *, bufp,
6840 uint64_t *, buflenp, uint64_t *, genp);
6841# else
6842 case VKI_MODCTL_NVL_OP_GET:
6843 PRE_REG_READ5(long, SC3("modctl", "modnvl_devlinksync", "get"),
6844 int, cmd, modctl_nvl_op_t, a1, char *, bufp,
6845 uint64_t *, buflenp, uint64_t *, genp);
6846# endif /* HAVE_SYS_SYSNVL_H */
6847
6848 PRINT("sys_modctl ( %ld, %lu, %#lx, %#lx, %#lx )",
6849 SARG1, ARG2, ARG3, ARG4, ARG5);
6850 PRE_MEM_WRITE("modctl(buflenp)", ARG4, sizeof(vki_uint64_t));
6851 if (ML_(safe_to_deref)((vki_uint64_t *) ARG4, sizeof(vki_uint64_t))) {
6852 if (ARG3 != 0) {
6853 PRE_MEM_WRITE("modctl(bufp)", ARG3, *(vki_uint64_t *) ARG4);
6854 }
6855 }
6856 if (ARG5 != 0) {
6857 PRE_MEM_WRITE("modctl(genp)", ARG5, sizeof(vki_uint64_t));
6858 }
6859 break;
6860
6861# if defined(HAVE_SYS_SYSNVL_H)
6862 case VKI_SYSNVL_OP_UPDATE:
6863 PRE_REG_READ4(long, SC3("modctl", "modnvl_devlinksync", "update"),
6864 int, cmd, sysnvl_op_t, a1, char *, bufp,
6865 uint64_t *, buflenp);
6866# else
6867 case VKI_MODCTL_NVL_OP_UPDATE:
6868 PRE_REG_READ4(long, SC3("modctl", "modnvl_devlinksync", "update"),
6869 int, cmd, modctl_nvl_op_t, a1, char *, bufp,
6870 uint64_t *, buflenp);
6871# endif /* HAVE_SYS_SYSNVL_H */
6872
6873 PRINT("sys_modctl ( %ld, %lu, %#lx, %#lx )", SARG1, ARG2, ARG3, ARG4);
6874 PRE_MEM_READ("modctl(buflenp)", ARG4, sizeof(vki_uint64_t));
6875 if (ML_(safe_to_deref)((vki_uint64_t *) ARG4, sizeof(vki_uint64_t))) {
6876 PRE_MEM_READ("modctl(bufp)", ARG3, *(vki_uint64_t *) ARG4);
6877 }
6878 break;
6879
6880 default:
6881 VG_(unimplemented)("Syswrap of the modctl call with command "
6882 "MODNVL_DEVLINKSYNC and op %ld.", ARG2);
6883 /*NOTREACHED*/
6884 break;
6885 }
6886 break;
6887
6888 case VKI_MODDEVINFO_CACHE_TS:
6889 /* int modctl_devinfo_cache_ts(uint64_t *utsp); */
6890 PRINT("sys_modctl ( %ld, %#lx )", SARG1, ARG2);
6891 PRE_REG_READ2(long, SC2("modctl", "moddevinfo_cache_ts"),
6892 int, cmd, uint64_t *, utsp);
6893 PRE_MEM_WRITE("modctl(utsp)", ARG2, sizeof(vki_uint64_t));
6894 break;
6895# endif /* SOLARIS_MODCTL_MODNVL */
6896
6897 default:
6898 VG_(unimplemented)("Syswrap of the modctl call with command %ld.", SARG1);
6899 /*NOTREACHED*/
6900 break;
6901 }
6902}
6903
6904POST(sys_modctl)
6905{
6906 switch (ARG1 /*cmd*/) {
6907 case VKI_MODLOAD:
6908 if (ARG4 != 0) {
6909 POST_MEM_WRITE(ARG4, sizeof(int *));
6910 }
6911 break;
6912 case VKI_MODUNLOAD:
6913 break;
6914 case VKI_MODINFO:
6915 POST_MEM_WRITE(ARG3, sizeof(struct vki_modinfo));
6916 break;
6917# if defined(SOLARIS_MODCTL_MODNVL)
6918 case VKI_MODNVL_DEVLINKSYNC:
6919 switch (ARG2 /*op*/) {
6920
6921# if defined(HAVE_SYS_SYSNVL_H)
6922 case VKI_SYSNVL_OP_GET:
6923# else
6924 case VKI_MODCTL_NVL_OP_GET:
6925# endif /* HAVE_SYS_SYSNVL_H */
6926
6927 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
6928 if (ARG3 != 0) {
6929 POST_MEM_WRITE(ARG3, *(vki_uint64_t *) ARG4);
6930 }
6931 if (ARG5 != 0) {
6932 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
6933 }
6934 break;
6935
6936# if defined(HAVE_SYS_SYSNVL_H)
6937 case VKI_SYSNVL_OP_UPDATE:
6938# else
6939 case VKI_MODCTL_NVL_OP_UPDATE:
6940# endif /* HAVE_SYS_SYSNVL_H */
6941 break;
6942
6943 default:
6944 vg_assert(0);
6945 break;
6946 }
6947 break;
6948 case VKI_MODDEVINFO_CACHE_TS:
6949 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
6950 break;
6951# endif /* SOLARIS_MODCTL_MODNVL */
6952
6953 default:
6954 vg_assert(0);
6955 break;
6956 }
6957}
6958
sewardj8eb8bab2015-07-21 14:44:28 +00006959PRE(sys_fchroot)
6960{
6961 /* int fchroot(int fd); */
florianb26101c2015-08-08 21:45:33 +00006962 PRINT("sys_fchroot ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00006963 PRE_REG_READ1(long, "fchroot", int, fd);
6964
6965 /* Be strict. */
6966 if (!ML_(fd_allowed)(ARG1, "fchroot", tid, False))
6967 SET_STATUS_Failure(VKI_EBADF);
6968}
6969
iraisrc0d46cd2015-09-25 21:04:45 +00006970#if defined(SOLARIS_SYSTEM_STATS_SYSCALL)
6971PRE(sys_system_stats)
6972{
6973 /* void system_stats(int flag); */
6974 PRINT("sys_system_stats ( %ld )", SARG1);
6975 PRE_REG_READ1(void, "system_stats", int, flag);
6976}
6977#endif /* SOLARIS_SYSTEM_STATS_SYSCALL */
6978
sewardj8eb8bab2015-07-21 14:44:28 +00006979PRE(sys_gettimeofday)
6980{
6981 /* Kernel: int gettimeofday(struct timeval *tp); */
6982 PRINT("sys_gettimeofday ( %#lx )", ARG1);
6983 PRE_REG_READ1(long, "gettimeofday", struct timeval *, tp);
6984 if (ARG1)
6985 PRE_timeval_WRITE("gettimeofday(tp)", ARG1);
6986}
6987
6988POST(sys_gettimeofday)
6989{
6990 if (ARG1)
6991 POST_timeval_WRITE(ARG1);
6992}
6993
6994PRE(sys_lwp_create)
6995{
6996 /* int lwp_create(ucontext_t *ucp, int flags, id_t *new_lwp) */
6997
6998 ThreadId ctid;
6999 ThreadState *ptst;
7000 ThreadState *ctst;
7001 Addr stack;
7002 SysRes res;
7003 vki_ucontext_t uc;
7004 Bool tool_informed = False;
7005
7006 PRINT("sys_lwp_create ( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3);
7007 PRE_REG_READ3(long, "lwp_create", ucontext_t *, ucp, int, flags,
7008 id_t *, new_lwp);
7009
7010 if (ARG3 != 0)
7011 PRE_MEM_WRITE("lwp_create(new_lwp)", ARG3, sizeof(vki_id_t));
7012
7013 /* If we can't deref ucontext_t then we can't do anything. */
7014 if (!ML_(safe_to_deref)((void*)ARG1, sizeof(vki_ucontext_t))) {
7015 SET_STATUS_Failure(VKI_EINVAL);
7016 return;
7017 }
7018
7019 ctid = VG_(alloc_ThreadState)();
7020 ptst = VG_(get_ThreadState)(tid);
7021 ctst = VG_(get_ThreadState)(ctid);
7022
7023 /* Stay sane. */
7024 vg_assert(VG_(is_running_thread)(tid));
7025 vg_assert(VG_(is_valid_tid)(ctid));
7026
7027 stack = ML_(allocstack)(ctid);
7028 if (!stack) {
7029 res = VG_(mk_SysRes_Error)(VKI_ENOMEM);
7030 goto out;
7031 }
7032
7033 /* First inherit parent's guest state */
7034 ctst->arch.vex = ptst->arch.vex;
7035 ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1;
7036 ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2;
7037
7038 /* Set up some values. */
7039 ctst->os_state.parent = tid;
7040 ctst->os_state.threadgroup = ptst->os_state.threadgroup;
7041 ctst->sig_mask = ptst->sig_mask;
7042 ctst->tmp_sig_mask = ptst->sig_mask;
7043
7044 /* No stack definition should be currently present. The stack will be set
7045 later by libc by a setustack() call (the getsetcontext syscall). */
7046 ctst->client_stack_highest_byte = 0;
7047 ctst->client_stack_szB = 0;
Elliott Hughesed398002017-06-21 14:41:24 -07007048 vg_assert(ctst->os_state.stk_id == NULL_STK_ID);
sewardj8eb8bab2015-07-21 14:44:28 +00007049
7050 /* Inform a tool that a new thread is created. This has to be done before
7051 any other core->tool event is sent. */
7052 vg_assert(VG_(owns_BigLock_LL)(tid));
7053 VG_TRACK(pre_thread_ll_create, tid, ctid);
7054 tool_informed = True;
7055
7056#if defined(VGP_x86_solaris)
7057 /* Set up GDT (this has to be done before calling
7058 VG_(restore_context)(). */
7059 ML_(setup_gdt)(&ctst->arch.vex);
7060#elif defined(VGP_amd64_solaris)
7061 /* Nothing to do. */
7062#else
7063# error "Unknown platform"
7064#endif
7065
7066 /* Now set up the new thread according to ucontext_t. */
7067 VG_(restore_context)(ctid, (vki_ucontext_t*)ARG1, Vg_CoreSysCall,
7068 True/*esp_is_thrptr*/);
7069
7070 /* Set up V thread (this also tells the kernel to block all signals in the
7071 thread). */
7072 ML_(setup_start_thread_context)(ctid, &uc);
7073
7074 /* Actually create the new thread. */
7075 res = VG_(do_syscall3)(__NR_lwp_create, (UWord)&uc, ARG2, ARG3);
7076
7077 if (!sr_isError(res)) {
7078 if (ARG3 != 0)
7079 POST_MEM_WRITE(ARG3, sizeof(vki_id_t));
7080 if (ARG2 & VKI_LWP_DAEMON)
7081 ctst->os_state.daemon_thread = True;
7082 }
7083
7084out:
7085 if (sr_isError(res)) {
7086 if (tool_informed) {
7087 /* Tell a tool the thread exited in a hurry. */
7088 VG_TRACK(pre_thread_ll_exit, ctid);
7089 }
7090
7091 /* lwp_create failed. */
7092 VG_(cleanup_thread)(&ctst->arch);
7093 ctst->status = VgTs_Empty;
7094 }
7095
7096 SET_STATUS_from_SysRes(res);
7097}
7098
7099PRE(sys_lwp_exit)
7100{
7101 /* void syslwp_exit(); */
7102 ThreadState *tst = VG_(get_ThreadState)(tid);
7103 PRINT("sys_lwp_exit ( )");
7104 PRE_REG_READ0(long, "lwp_exit");
7105
7106 /* Set the thread's status to be exiting, then claim that the syscall
7107 succeeded. */
7108 tst->exitreason = VgSrc_ExitThread;
7109 tst->os_state.exitcode = 0;
7110 SET_STATUS_Success(0);
7111}
7112
7113PRE(sys_lwp_suspend)
7114{
7115 /* int lwp_suspend(id_t lwpid); */
7116 ThreadState *tst = VG_(get_ThreadState)(tid);
florianb26101c2015-08-08 21:45:33 +00007117 PRINT("sys_lwp_suspend ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007118 PRE_REG_READ1(long, "lwp_suspend", vki_id_t, lwpid);
7119
7120 if (ARG1 == tst->os_state.lwpid) {
7121 /* Set the SfMayBlock flag only if the currently running thread should
7122 be suspended. If this flag was used also when suspending other
7123 threads then it could happen that a thread holding the_BigLock would
7124 be suspended and Valgrind would hang. */
7125 *flags |= SfMayBlock;
7126 }
7127}
7128
7129PRE(sys_lwp_continue)
7130{
7131 /* int lwp_continue(id_t target_lwp); */
florianb26101c2015-08-08 21:45:33 +00007132 PRINT("sys_lwp_continue ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007133 PRE_REG_READ1(long, "lwp_continue", vki_id_t, target_lwp);
7134}
7135
7136static void
7137do_lwp_sigqueue(const HChar *syscall_name, UWord target_lwp, UWord signo,
7138 SyscallStatus *status, UWord *flags)
7139{
7140 if (!ML_(client_signal_OK)(signo)) {
7141 SET_STATUS_Failure(VKI_EINVAL);
7142 return;
7143 }
7144
7145 /* Check to see if this gave us a pending signal. */
7146 *flags |= SfPollAfter;
7147
7148 if (VG_(clo_trace_signals))
florianb26101c2015-08-08 21:45:33 +00007149 VG_(message)(Vg_DebugMsg, "%s: sending signal %lu to thread %lu\n",
sewardj8eb8bab2015-07-21 14:44:28 +00007150 syscall_name, signo, target_lwp);
7151
7152 /* If we're sending SIGKILL, check to see if the target is one of our
7153 threads and handle it specially. */
7154 if (signo == VKI_SIGKILL && ML_(do_sigkill)(target_lwp, -1)) {
7155 SET_STATUS_Success(0);
7156 return;
7157 }
7158
7159 /* Ask to handle this syscall via the slow route, since that's the only one
7160 that sets tst->status to VgTs_WaitSys. If the result of doing the
7161 syscall is an immediate run of async_signalhandler() in m_signals.c,
7162 then we need the thread to be properly tidied away. */
7163 *flags |= SfMayBlock;
7164}
7165
7166#if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
7167#if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL_TAKES_PID)
7168PRE(sys_lwp_sigqueue)
7169{
7170 /* int lwp_sigqueue(pid_t target_pid, id_t target_lwp, int signal,
7171 void *value, int si_code, timespec_t *timeout);
7172 */
7173 PRINT("sys_lwp_sigqueue ( %ld, %ld, %ld, %#lx, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00007174 SARG1, SARG2, SARG3, ARG4, SARG5, ARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00007175 PRE_REG_READ6(long, "lwp_sigqueue", vki_pid_t, target_pid,
7176 vki_id_t, target_lwp, int, signal, void *, value, int, si_code,
7177 vki_timespec_t *, timeout);
7178
7179 if (ARG6)
7180 PRE_MEM_READ("lwp_sigqueue(timeout)", ARG6, sizeof(vki_timespec_t));
7181
7182 if ((ARG1 == 0) || (ARG1 == VG_(getpid)())) {
7183 do_lwp_sigqueue("lwp_sigqueue", ARG2, ARG3, status, flags);
7184 } else {
7185 /* Signal is sent to a different process. */
7186 if (VG_(clo_trace_signals))
7187 VG_(message)(Vg_DebugMsg, "lwp_sigqueue: sending signal %ld to "
florianb26101c2015-08-08 21:45:33 +00007188 "process %ld, thread %ld\n", SARG3, SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00007189 *flags |= SfMayBlock;
7190 }
7191}
7192
7193POST(sys_lwp_sigqueue)
7194{
7195 if (VG_(clo_trace_signals))
7196 VG_(message)(Vg_DebugMsg, "lwp_sigqueue: sent signal %ld to process %ld, "
florianb26101c2015-08-08 21:45:33 +00007197 "thread %ld\n", SARG3, SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00007198}
7199
7200#else
7201
7202PRE(sys_lwp_sigqueue)
7203{
7204 /* int lwp_sigqueue(id_t target_lwp, int signal, void *value,
7205 int si_code, timespec_t *timeout);
7206 */
7207 PRINT("sys_lwp_sigqueue ( %ld, %ld, %#lx, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00007208 SARG1, SARG2, ARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00007209 PRE_REG_READ5(long, "lwp_sigqueue", vki_id_t, target_lwp, int, signal,
7210 void *, value, int, si_code, vki_timespec_t *, timeout);
7211
7212 if (ARG5)
7213 PRE_MEM_READ("lwp_sigqueue(timeout)", ARG5, sizeof(vki_timespec_t));
7214
7215 do_lwp_sigqueue("lwp_sigqueue", ARG1, ARG2, status, flags);
7216}
7217
7218POST(sys_lwp_sigqueue)
7219{
7220 if (VG_(clo_trace_signals))
florianb26101c2015-08-08 21:45:33 +00007221 VG_(message)(Vg_DebugMsg, "lwp_sigqueue: sent signal %lu to thread %lu\n",
sewardj8eb8bab2015-07-21 14:44:28 +00007222 ARG2, ARG1);
7223}
7224
7225
7226#endif /* SOLARIS_LWP_SIGQUEUE_SYSCALL_TAKES_PID */
7227
7228#else
7229
7230PRE(sys_lwp_kill)
7231{
7232 /* int lwp_kill(id_t target_lwp, int signal); */
florianb26101c2015-08-08 21:45:33 +00007233 PRINT("sys_lwp_kill ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00007234 PRE_REG_READ2(long, "lwp_kill", vki_id_t, target_lwp, int, signal);
7235
7236 do_lwp_sigqueue("lwp_kill", ARG1, ARG2, status, flags);
7237}
7238
7239POST(sys_lwp_kill)
7240{
7241 if (VG_(clo_trace_signals))
florianb26101c2015-08-08 21:45:33 +00007242 VG_(message)(Vg_DebugMsg, "lwp_kill: sent signal %lu to thread %lu\n",
sewardj8eb8bab2015-07-21 14:44:28 +00007243 ARG2, ARG1);
7244}
7245#endif /* SOLARIS_LWP_SIGQUEUE_SYSCALL */
7246
7247PRE(sys_lwp_self)
7248{
7249 /* id_t lwp_self(void); */
7250 PRINT("sys_lwp_self ( )");
7251 PRE_REG_READ0(long, "lwp_self");
7252}
7253
7254PRE(sys_lwp_sigmask)
7255{
7256 /* int64_t lwp_sigmask(int how, uint_t bits0, uint_t bits1, uint_t bits2,
7257 uint_t bits3); */
7258 vki_sigset_t sigset;
florianb26101c2015-08-08 21:45:33 +00007259 PRINT("sys_lwp_sigmask ( %ld, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00007260 ARG4, ARG5);
7261 PRE_REG_READ5(long, "lwp_sigmask", int, how, vki_uint_t, bits0,
7262 vki_uint_t, bits1, vki_uint_t, bits2, vki_uint_t, bits3);
7263
7264 sigset.__sigbits[0] = ARG2;
7265 sigset.__sigbits[1] = ARG3;
7266 sigset.__sigbits[2] = ARG4;
7267 sigset.__sigbits[3] = ARG5;
7268
7269 SET_STATUS_from_SysRes(
7270 VG_(do_sys_sigprocmask)(tid, ARG1 /*how*/, &sigset, NULL)
7271 );
7272
7273 if (SUCCESS)
7274 *flags |= SfPollAfter;
7275}
7276
7277PRE(sys_lwp_private)
7278{
7279 /* int lwp_private(int cmd, int which, uintptr_t base); */
7280 ThreadState *tst = VG_(get_ThreadState)(tid);
7281 Int supported_base, supported_sel;
florianb26101c2015-08-08 21:45:33 +00007282 PRINT("sys_lwp_private ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00007283 PRE_REG_READ3(long, "lwp_private", int, cmd, int, which,
7284 uintptr_t, base);
7285
7286 /* Note: Only the %gs base is currently supported on x86 and the %fs base
7287 on amd64. Support for the %fs base on x86 and for the %gs base on amd64
7288 should be added. Anything else is probably a client program error. */
7289#if defined(VGP_x86_solaris)
7290 supported_base = VKI_LWP_GSBASE;
7291 supported_sel = VKI_LWPGS_SEL;
7292#elif defined(VGP_amd64_solaris)
7293 supported_base = VKI_LWP_FSBASE;
7294 supported_sel = 0;
7295#else
7296#error "Unknown platform"
7297#endif
7298 if (ARG2 != supported_base) {
7299 VG_(unimplemented)("Syswrap of the lwp_private call where which=%ld.",
florianb26101c2015-08-08 21:45:33 +00007300 SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00007301 /*NOTREACHED*/
7302 }
7303
7304 switch (ARG1 /*cmd*/) {
7305 case VKI_LWP_SETPRIVATE:
7306#if defined(VGP_x86_solaris)
7307 tst->os_state.thrptr = ARG3;
7308 ML_(update_gdt_lwpgs)(tid);
7309#elif defined(VGP_amd64_solaris)
7310 tst->arch.vex.guest_FS_CONST = ARG3;
7311#else
7312#error "Unknown platform"
7313#endif
7314 SET_STATUS_Success(supported_sel);
7315 break;
7316 case VKI_LWP_GETPRIVATE:
7317 {
7318 int thrptr;
7319#if defined(VGP_x86_solaris)
7320 thrptr = tst->os_state.thrptr;
7321#elif defined(VGP_amd64_solaris)
7322 thrptr = tst->arch.vex.guest_FS_CONST;
7323#else
7324#error "Unknown platform"
7325#endif
7326
7327 if (thrptr == 0) {
7328 SET_STATUS_Failure(VKI_EINVAL);
7329 return;
7330 }
7331
7332#if defined(VGP_x86_solaris)
7333 if (tst->arch.vex.guest_GS != supported_sel) {
7334 SET_STATUS_Failure(VKI_EINVAL);
7335 return;
7336 }
7337#elif defined(VGP_amd64_solaris)
7338 /* Valgrind on amd64 does not allow to change the gs register so
7339 a check that guest_GS is equal to supported_sel is not needed
7340 here. */
7341#else
7342#error "Unknown platform"
7343#endif
7344
7345 PRE_MEM_WRITE("lwp_private(base)", ARG3, sizeof(Addr));
7346 if (!ML_(safe_to_deref((void*)ARG3, sizeof(Addr)))) {
7347 SET_STATUS_Failure(VKI_EFAULT);
7348 return;
7349 }
7350 *(Addr*)ARG3 = thrptr;
7351 POST_MEM_WRITE((Addr)ARG3, sizeof(Addr));
7352 SET_STATUS_Success(0);
7353 break;
7354 }
7355 default:
7356 VG_(unimplemented)("Syswrap of the lwp_private call where cmd=%ld.",
florianb26101c2015-08-08 21:45:33 +00007357 SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007358 /*NOTREACHED*/
7359 break;
7360 }
7361}
7362
7363PRE(sys_lwp_wait)
7364{
7365 /* int lwp_wait(id_t lwpid, id_t *departed); */
7366 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00007367 PRINT("sys_lwp_wait ( %ld, %#lx )", SARG1, ARG2);
iraisr173bb6e2015-10-16 12:20:20 +00007368 PRE_REG_READ2(long, "lwp_wait", vki_id_t, lwpid, vki_id_t *, departed);
sewardj8eb8bab2015-07-21 14:44:28 +00007369 if (ARG2)
7370 PRE_MEM_WRITE("lwp_wait(departed)", ARG2, sizeof(vki_id_t));
7371}
7372
7373POST(sys_lwp_wait)
7374{
7375 POST_MEM_WRITE(ARG2, sizeof(vki_id_t));
7376}
7377
7378PRE(sys_lwp_mutex_wakeup)
7379{
7380 /* int lwp_mutex_wakeup(lwp_mutex_t *lp, int release_all); */
sewardj8eb8bab2015-07-21 14:44:28 +00007381 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00007382 PRINT("sys_lwp_mutex_wakeup ( %#lx, %ld )", ARG1, SARG2);
iraisr173bb6e2015-10-16 12:20:20 +00007383 PRE_REG_READ2(long, "lwp_mutex_wakeup", vki_lwp_mutex_t *, lp,
sewardj8eb8bab2015-07-21 14:44:28 +00007384 int, release_all);
iraisr173bb6e2015-10-16 12:20:20 +00007385 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t *) ARG1;
sewardj8eb8bab2015-07-21 14:44:28 +00007386 PRE_FIELD_READ("lwp_mutex_wakeup(lp->mutex_type)", lp->vki_mutex_type);
7387 PRE_FIELD_WRITE("lwp_mutex_wakeup(lp->mutex_waiters)",
7388 lp->vki_mutex_waiters);
7389}
7390
7391POST(sys_lwp_mutex_wakeup)
7392{
iraisr173bb6e2015-10-16 12:20:20 +00007393 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t *) ARG1;
sewardj8eb8bab2015-07-21 14:44:28 +00007394 POST_FIELD_WRITE(lp->vki_mutex_waiters);
7395}
7396
iraisr173bb6e2015-10-16 12:20:20 +00007397PRE(sys_lwp_cond_wait)
7398{
7399 /* int lwp_cond_wait(lwp_cond_t *cvp, lwp_mutex_t *mp, timespec_t *tsp,
7400 int check_park); */
7401 *flags |= SfMayBlock;
7402 PRINT("sys_lwp_cond_wait( %#lx, %#lx, %#lx, %ld )", ARG1, ARG2, ARG3, SARG4);
7403 PRE_REG_READ4(long, "lwp_cond_wait", vki_lwp_cond_t *, cvp,
7404 vki_lwp_mutex_t *, mp, vki_timespec_t *, tsp, int, check_part);
7405
7406 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7407 vki_lwp_mutex_t *mp = (vki_lwp_mutex_t *) ARG2;
7408 PRE_FIELD_READ("lwp_cond_wait(cvp->type)", cvp->vki_cond_type);
7409 PRE_FIELD_READ("lwp_cond_wait(cvp->waiters_kernel)",
7410 cvp->vki_cond_waiters_kernel);
7411 PRE_FIELD_READ("lwp_cond_wait(mp->mutex_type)", mp->vki_mutex_type);
7412 PRE_FIELD_WRITE("lwp_cond_wait(mp->mutex_waiters)", mp->vki_mutex_waiters);
7413 if (ARG3 != 0)
7414 PRE_MEM_READ("lwp_cond_wait(tsp)", ARG3, sizeof(vki_timespec_t));
7415}
7416
7417POST(sys_lwp_cond_wait)
7418{
7419 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7420 vki_lwp_mutex_t *mp = (vki_lwp_mutex_t *) ARG2;
7421 POST_FIELD_WRITE(cvp->vki_cond_waiters_kernel);
7422 POST_FIELD_WRITE(mp->vki_mutex_waiters);
7423 if (ARG3 != 0)
7424 POST_MEM_WRITE(ARG3, sizeof(vki_timespec_t));
7425}
7426
Elliott Hughesa0664b92017-04-18 17:46:52 -07007427PRE(sys_lwp_cond_signal)
7428{
7429 /* int lwp_cond_signal(lwp_cond_t *cvp); */
7430 *flags |= SfMayBlock;
7431 PRINT("sys_lwp_cond_signal( %#lx )", ARG1);
7432 PRE_REG_READ1(long, "lwp_cond_signal", vki_lwp_cond_t *, cvp);
7433
7434 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7435 PRE_FIELD_READ("lwp_cond_signal(cvp->type)", cvp->vki_cond_type);
7436 PRE_FIELD_READ("lwp_cond_signal(cvp->waiters_kernel)",
7437 cvp->vki_cond_waiters_kernel);
7438}
7439
7440POST(sys_lwp_cond_signal)
7441{
7442 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7443 POST_FIELD_WRITE(cvp->vki_cond_waiters_kernel);
7444}
7445
sewardj8eb8bab2015-07-21 14:44:28 +00007446PRE(sys_lwp_cond_broadcast)
7447{
7448 /* int lwp_cond_broadcast(lwp_cond_t *cvp); */
sewardj8eb8bab2015-07-21 14:44:28 +00007449 *flags |= SfMayBlock;
7450 PRINT("sys_lwp_cond_broadcast ( %#lx )", ARG1);
iraisr173bb6e2015-10-16 12:20:20 +00007451 PRE_REG_READ1(long, "lwp_cond_broadcast", vki_lwp_cond_t *, cvp);
sewardj8eb8bab2015-07-21 14:44:28 +00007452
iraisr173bb6e2015-10-16 12:20:20 +00007453 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
sewardj8eb8bab2015-07-21 14:44:28 +00007454 PRE_FIELD_READ("lwp_cond_broadcast(cvp->type)", cvp->vki_cond_type);
7455 PRE_FIELD_READ("lwp_cond_broadcast(cvp->waiters_kernel)",
7456 cvp->vki_cond_waiters_kernel);
7457 /*PRE_FIELD_WRITE("lwp_cond_broadcast(cvp->waiters_kernel)",
7458 cvp->vki_cond_waiters_kernel);*/
7459}
7460
7461POST(sys_lwp_cond_broadcast)
7462{
iraisr173bb6e2015-10-16 12:20:20 +00007463 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
sewardj8eb8bab2015-07-21 14:44:28 +00007464 POST_FIELD_WRITE(cvp->vki_cond_waiters_kernel);
7465}
7466
7467PRE(sys_pread)
7468{
7469 /* ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); */
7470 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00007471 PRINT("sys_pread ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00007472 PRE_REG_READ4(long, "pread", int, fildes, void *, buf,
7473 vki_size_t, nbyte, vki_off_t, offset);
7474 PRE_MEM_WRITE("pread(buf)", ARG2, ARG3);
7475
7476 /* Be strict. */
7477 if (!ML_(fd_allowed)(ARG1, "pread", tid, False))
7478 SET_STATUS_Failure(VKI_EBADF);
7479}
7480
7481POST(sys_pread)
7482{
7483 POST_MEM_WRITE(ARG2, RES);
7484}
7485
7486PRE(sys_pwrite)
7487{
7488 /* ssize_t pwrite(int fildes, const void *buf, size_t nbyte,
7489 off_t offset); */
7490 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00007491 PRINT("sys_pwrite ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00007492 PRE_REG_READ4(long, "pwrite", int, fildes, const void *, buf,
7493 vki_size_t, nbyte, vki_off_t, offset);
7494 PRE_MEM_READ("pwrite(buf)", ARG2, ARG3);
7495
7496 /* Be strict. */
7497 if (!ML_(fd_allowed)(ARG1, "pwrite", tid, False))
7498 SET_STATUS_Failure(VKI_EBADF);
7499}
7500
7501PRE(sys_getpagesizes)
7502{
7503 /* int getpagesizes(int legacy, size_t *buf, int nelem); */
florianb26101c2015-08-08 21:45:33 +00007504 PRINT("sys_getpagesizes ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00007505 PRE_REG_READ3(long, "getpagesizes", int, legacy, size_t *, buf,
7506 int, nelem);
7507 if (ARG2)
7508 PRE_MEM_WRITE("getpagesizes(buf)", ARG2, ARG3 * sizeof(vki_size_t));
7509}
7510
7511POST(sys_getpagesizes)
7512{
7513 if (ARG2)
7514 POST_MEM_WRITE(ARG2, RES * sizeof(vki_size_t));
7515}
7516
Elliott Hughesed398002017-06-21 14:41:24 -07007517PRE(sys_lgrpsys)
7518{
7519 /* Kernel: int lgrpsys(int subcode, long ia, void *ap); */
7520 switch (ARG1 /*subcode*/) {
7521 case VKI_LGRP_SYS_MEMINFO:
7522 PRINT("sys_lgrpsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
7523 PRE_REG_READ3(long, SC2("lgrpsys", "meminfo"), int, subcode,
7524 int, addr_count, vki_meminfo_t *, minfo);
7525 PRE_MEM_READ("lgrpsys(minfo)", ARG3, sizeof(vki_meminfo_t));
7526
7527 if (ML_(safe_to_deref)((vki_meminfo_t *) ARG3, sizeof(vki_meminfo_t))) {
7528 vki_meminfo_t *minfo = (vki_meminfo_t *) ARG3;
7529 PRE_MEM_READ("lgrpsys(minfo->mi_inaddr)",
7530 (Addr) minfo->mi_inaddr, SARG2 * sizeof(vki_uint64_t));
7531 PRE_MEM_READ("lgrpsys(minfo->mi_info_req)", (Addr) minfo->mi_info_req,
7532 minfo->mi_info_count * sizeof(vki_uint_t));
7533 PRE_MEM_WRITE("lgrpsys(minfo->mi_outdata)", (Addr) minfo->mi_outdata,
7534 SARG2 * minfo->mi_info_count * sizeof(vki_uint64_t));
7535 PRE_MEM_WRITE("lgrpsys(minfo->mi_validity)",
7536 (Addr) minfo->mi_validity, SARG2 * sizeof(vki_uint_t));
7537 }
7538 break;
7539 case VKI_LGRP_SYS_GENERATION:
7540 /* Liblgrp: lgrp_gen_t lgrp_generation(lgrp_view_t view); */
7541 PRINT("sys_lgrpsys ( %ld, %ld )", SARG1, SARG2);
7542 PRE_REG_READ2(long, SC2("lgrpsys", "generation"), int, subcode,
7543 vki_lgrp_view_t, view);
7544 break;
7545 case VKI_LGRP_SYS_VERSION:
7546 /* Liblgrp: int lgrp_version(int version); */
7547 PRINT("sys_lgrpsys ( %ld, %ld )", SARG1, SARG2);
7548 PRE_REG_READ2(long, SC2("lgrpsys", "version"), int, subcode,
7549 int, version);
7550 break;
7551 case VKI_LGRP_SYS_SNAPSHOT:
7552 /* Liblgrp: int lgrp_snapshot(void *buf, size_t bufsize); */
7553 PRINT("sys_lgrpsys ( %ld, %lu, %#lx )", SARG1, ARG2, ARG3);
7554 PRE_REG_READ3(long, SC2("lgrpsys", "snapshot"), int, subcode,
7555 vki_size_t, bufsize, void *, buf);
7556 PRE_MEM_WRITE("lgrpsys(buf)", ARG3, ARG2);
7557 break;
7558 default:
7559 VG_(unimplemented)("Syswrap of the lgrpsys call with subcode %ld.",
7560 SARG1);
7561 /*NOTREACHED*/
7562 break;
7563 }
7564}
7565
7566POST(sys_lgrpsys)
7567{
7568 switch (ARG1 /*subcode*/) {
7569 case VKI_LGRP_SYS_MEMINFO:
7570 {
7571 vki_meminfo_t *minfo = (vki_meminfo_t *) ARG3;
7572 POST_MEM_WRITE((Addr) minfo->mi_outdata,
7573 SARG2 * minfo->mi_info_count * sizeof(vki_uint64_t));
7574 POST_MEM_WRITE((Addr) minfo->mi_validity, SARG2 * sizeof(vki_uint_t));
7575 }
7576 break;
7577 case VKI_LGRP_SYS_GENERATION:
7578 case VKI_LGRP_SYS_VERSION:
7579 break;
7580 case VKI_LGRP_SYS_SNAPSHOT:
7581 POST_MEM_WRITE(ARG3, RES);
7582 break;
7583 default:
7584 vg_assert(0);
7585 break;
7586 }
7587}
7588
sewardj8eb8bab2015-07-21 14:44:28 +00007589PRE(sys_rusagesys)
7590{
7591 /* Kernel: int rusagesys(int code, void *arg1, void *arg2,
7592 void *arg3, void *arg4); */
7593 switch (ARG1 /*code*/) {
7594 case VKI__RUSAGESYS_GETRUSAGE:
7595 case VKI__RUSAGESYS_GETRUSAGE_CHLD:
7596 case VKI__RUSAGESYS_GETRUSAGE_LWP:
7597 /* Libc: int getrusage(int who, struct rusage *r_usage); */
florianb26101c2015-08-08 21:45:33 +00007598 PRINT("sys_rusagesys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00007599 PRE_REG_READ2(long, SC2("rusagesys", "getrusage"), int, code,
7600 struct vki_rusage *, r_usage);
7601 PRE_MEM_WRITE("rusagesys(r_usage)", ARG2, sizeof(struct vki_rusage));
7602 break;
7603
7604 case VKI__RUSAGESYS_GETVMUSAGE:
7605 /* Libc: int getvmusage(uint_t flags, time_t age,
7606 vmusage_t *buf, size_t *nres); */
florianb26101c2015-08-08 21:45:33 +00007607 PRINT("sys_rusagesys ( %ld, %lu, %ld, %#lx, %#lx )",
7608 SARG1, ARG2, SARG3, ARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00007609 PRE_REG_READ5(long, SC2("rusagesys", "getvmusage"), int, code,
7610 vki_uint_t, flags, vki_time_t, age,
7611 vki_vmusage_t *, buf, vki_size_t *, nres);
7612 PRE_MEM_READ("rusagesys(nres)", ARG5, sizeof(vki_size_t));
7613 /* PRE_MEM_WRITE("rusagesys(nres)", ARG5, sizeof(vki_size_t)); */
7614
7615 if (ML_(safe_to_deref)((void *) ARG5, sizeof(vki_size_t))) {
7616 vki_size_t *nres = (vki_size_t *) ARG5;
7617 PRE_MEM_WRITE("rusagesys(buf)", ARG4,
7618 *nres * sizeof(vki_vmusage_t));
7619 }
7620 *flags |= SfMayBlock;
7621 break;
7622
7623 default:
florianb26101c2015-08-08 21:45:33 +00007624 VG_(unimplemented)("Syswrap of the rusagesys call with code %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007625 /*NOTREACHED*/
7626 break;
7627 }
7628}
7629
7630POST(sys_rusagesys)
7631{
7632 switch (ARG1 /*code*/) {
7633 case VKI__RUSAGESYS_GETRUSAGE:
7634 case VKI__RUSAGESYS_GETRUSAGE_CHLD:
7635 case VKI__RUSAGESYS_GETRUSAGE_LWP:
7636 POST_MEM_WRITE(ARG2, sizeof(struct vki_rusage));
7637 break;
7638 case VKI__RUSAGESYS_GETVMUSAGE:
7639 {
7640 vki_size_t *nres = (vki_size_t *) ARG5;
7641 POST_MEM_WRITE(ARG5, sizeof(vki_size_t));
7642 POST_MEM_WRITE(ARG4, *nres * sizeof(vki_vmusage_t));
7643 }
7644 break;
7645 default:
7646 vg_assert(0);
7647 break;
7648 }
sewardj8eb8bab2015-07-21 14:44:28 +00007649}
7650
7651PRE(sys_port)
7652{
7653 /* Kernel: int64_t portfs(int opcode, uintptr_t a0, uintptr_t a1,
7654 uintptr_t a2, uintptr_t a3, uintptr_t a4); */
7655 Int opcode = ARG1 & VKI_PORT_CODE_MASK;
7656 *flags |= SfMayBlock;
7657 switch (opcode) {
7658 case VKI_PORT_CREATE:
florianb26101c2015-08-08 21:45:33 +00007659 PRINT("sys_port ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007660 PRE_REG_READ1(long, SC2("port", "create"), int, opcode);
7661 break;
7662 case VKI_PORT_ASSOCIATE:
7663 case VKI_PORT_DISSOCIATE:
florianb26101c2015-08-08 21:45:33 +00007664 PRINT("sys_port ( %ld, %ld, %ld, %#lx, %ld, %#lx )", SARG1, SARG2, SARG3,
7665 ARG4, SARG5, ARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00007666 if (opcode == VKI_PORT_ASSOCIATE) {
7667 PRE_REG_READ6(long, SC2("port", "associate"), int, opcode, int, a0,
7668 int, a1, uintptr_t, a2, int, a3, void *, a4);
7669 }
7670 else {
7671 PRE_REG_READ6(long, SC2("port", "dissociate"), int, opcode, int, a0,
7672 int, a1, uintptr_t, a2, int, a3, void *, a4);
7673 }
7674
7675 switch (ARG3 /*source*/) {
7676 case VKI_PORT_SOURCE_FD:
7677 if (!ML_(fd_allowed)(ARG4, "port", tid, False)) {
7678 SET_STATUS_Failure(VKI_EBADF);
7679 }
7680 break;
7681 case VKI_PORT_SOURCE_FILE:
7682 {
7683 struct vki_file_obj *fo = (struct vki_file_obj *)ARG4;
7684 PRE_MEM_READ("port(file_obj)", ARG4, sizeof(struct vki_file_obj));
7685 if (ML_(safe_to_deref)(&fo->fo_name, sizeof(fo->fo_name)))
7686 PRE_MEM_RASCIIZ("port(file_obj->fo_name)", (Addr)fo->fo_name);
7687 }
7688 break;
7689 default:
7690 VG_(unimplemented)("Syswrap of the port_associate/dissociate call "
florianb26101c2015-08-08 21:45:33 +00007691 "type %ld.", SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00007692 /*NOTREACHED*/
7693 break;
7694 }
7695 break;
7696 case VKI_PORT_SEND:
florianb26101c2015-08-08 21:45:33 +00007697 PRINT("sys_port ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00007698 PRE_REG_READ4(long, SC2("port", "send"), int, opcode, int, a0, int, a1,
7699 void *, a2);
7700 break;
7701 case VKI_PORT_SENDN:
florianb26101c2015-08-08 21:45:33 +00007702 PRINT("sys_port ( %ld, %#lx, %#lx, %lu, %lx, %#lx)", SARG1, ARG2, ARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00007703 ARG4, ARG5, ARG6);
7704 PRE_REG_READ6(long, SC2("port", "sendn"), int, opcode, int *, a0,
7705 int *, a1, vki_uint_t, a2, int, a3, void *, a4);
7706 PRE_MEM_READ("port(ports)", ARG2, ARG4 * sizeof(int));
7707 PRE_MEM_WRITE("port(errors)", ARG3, ARG4 * sizeof(int));
7708 break;
7709 case VKI_PORT_GET:
florianb26101c2015-08-08 21:45:33 +00007710 PRINT("sys_port ( %ld, %ld, %#lx, %ld, %ld, %#lx )", SARG1, SARG2, ARG3,
7711 SARG4, SARG5, ARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00007712 PRE_REG_READ6(long, SC2("port", "get"), int, opcode, int, a0,
7713 port_event_t *, a1, vki_time_t, a2, long, a3,
7714 timespec_t *, a4);
7715 PRE_MEM_WRITE("port(uevp)", ARG3, sizeof(vki_port_event_t));
7716 break;
7717 case VKI_PORT_GETN:
florianb26101c2015-08-08 21:45:33 +00007718 PRINT("sys_port ( %ld, %ld, %#lx, %lu, %lu, %#lx )", SARG1, SARG2, ARG3,
sewardj8eb8bab2015-07-21 14:44:28 +00007719 ARG4, ARG5, ARG6);
7720 PRE_REG_READ6(long, SC2("port", "getn"), int, opcode, int, a0,
7721 port_event_t *, a1, vki_uint_t, a2, vki_uint_t, a3,
7722 timespec_t *, a4);
7723 if (ARG6)
7724 PRE_MEM_READ("port(timeout)", ARG6, sizeof(vki_timespec_t));
7725 PRE_MEM_WRITE("port(uevp)", ARG3, ARG4 * sizeof(vki_port_event_t));
7726 break;
7727 case VKI_PORT_ALERT:
florianb26101c2015-08-08 21:45:33 +00007728 PRINT("sys_port ( %ld, %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, SARG4,
sewardj8eb8bab2015-07-21 14:44:28 +00007729 ARG5);
7730 PRE_REG_READ5(long, SC2("port", "alert"), int, opcode, int, a0, int, a1,
7731 int, a2, void *, a3);
7732 break;
7733 case VKI_PORT_DISPATCH:
florianb26101c2015-08-08 21:45:33 +00007734 // FIXME: check order: SARG2, SARG1 or SARG1, SARG2 ??
7735 PRINT("sys_port ( %ld, %ld, %ld, %ld, %#lx, %#lx )", SARG2, SARG1, SARG3,
7736 SARG4, ARG5, ARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00007737 PRE_REG_READ6(long, SC2("port", "dispatch"), int, opcode, int, a0,
7738 int, a1, int, a2, uintptr_t, a3, void *, a4);
7739 break;
7740 default:
florianb26101c2015-08-08 21:45:33 +00007741 VG_(unimplemented)("Syswrap of the port call with opcode %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007742 /*NOTREACHED*/
7743 break;
7744 }
7745
7746 /* Be strict. */
7747 if ((opcode != VKI_PORT_CREATE && opcode != VKI_PORT_SENDN) &&
7748 !ML_(fd_allowed)(ARG2, "port", tid, False))
7749 SET_STATUS_Failure(VKI_EBADF);
7750}
7751
7752POST(sys_port)
7753{
7754 Int opcode = ARG1 & VKI_PORT_CODE_MASK;
7755 switch (opcode) {
7756 case VKI_PORT_CREATE:
7757 if (!ML_(fd_allowed)(RES, "port", tid, True)) {
7758 VG_(close)(RES);
7759 SET_STATUS_Failure(VKI_EMFILE);
7760 }
7761 else if (VG_(clo_track_fds))
7762 ML_(record_fd_open_named)(tid, RES);
7763 break;
7764 case VKI_PORT_ASSOCIATE:
7765 case VKI_PORT_DISSOCIATE:
7766 case VKI_PORT_SEND:
7767 break;
7768 case VKI_PORT_SENDN:
7769 if (RES != ARG4) {
7770 /* If there is any error then the whole errors area is written. */
7771 POST_MEM_WRITE(ARG3, ARG4 * sizeof(int));
7772 }
7773 break;
7774 case VKI_PORT_GET:
7775 POST_MEM_WRITE(ARG3, sizeof(vki_port_event_t));
7776 break;
7777 case VKI_PORT_GETN:
7778 POST_MEM_WRITE(ARG3, RES * sizeof(vki_port_event_t));
7779 break;
7780 case VKI_PORT_ALERT:
7781 case VKI_PORT_DISPATCH:
7782 break;
7783 default:
florianb26101c2015-08-08 21:45:33 +00007784 VG_(unimplemented)("Syswrap of the port call with opcode %lu.", ARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007785 /*NOTREACHED*/
7786 break;
7787 }
7788}
7789
7790PRE(sys_pollsys)
7791{
7792 /* int pollsys(pollfd_t *fds, nfds_t nfds, timespec_t *timeout,
7793 sigset_t *set); */
7794 UWord i;
7795 struct vki_pollfd *ufds = (struct vki_pollfd *)ARG1;
7796
Elliott Hughesa0664b92017-04-18 17:46:52 -07007797 *flags |= SfMayBlock | SfPostOnFail;
sewardj8eb8bab2015-07-21 14:44:28 +00007798
7799 PRINT("sys_pollsys ( %#lx, %lu, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4);
7800 PRE_REG_READ4(long, "poll", pollfd_t *, fds, vki_nfds_t, nfds,
7801 timespec_t *, timeout, sigset_t *, set);
7802
7803 for (i = 0; i < ARG2; i++) {
7804 vki_pollfd_t *u = &ufds[i];
7805 PRE_FIELD_READ("poll(ufds.fd)", u->fd);
7806 /* XXX Check if it's valid? */
7807 PRE_FIELD_READ("poll(ufds.events)", u->events);
7808 PRE_FIELD_WRITE("poll(ufds.revents)", u->revents);
7809 }
7810
7811 if (ARG3)
7812 PRE_MEM_READ("poll(timeout)", ARG3, sizeof(vki_timespec_t));
Elliott Hughesa0664b92017-04-18 17:46:52 -07007813
7814 if (ARG4) {
sewardj8eb8bab2015-07-21 14:44:28 +00007815 PRE_MEM_READ("poll(set)", ARG4, sizeof(vki_sigset_t));
Elliott Hughesa0664b92017-04-18 17:46:52 -07007816
7817 const vki_sigset_t *guest_sigmask = (vki_sigset_t *) ARG4;
7818 if (!ML_(safe_to_deref)(guest_sigmask, sizeof(vki_sigset_t))) {
7819 ARG4 = 1; /* Something recognisable to POST() hook. */
7820 } else {
7821 vki_sigset_t *vg_sigmask =
7822 VG_(malloc)("syswrap.pollsys.1", sizeof(vki_sigset_t));
7823 ARG4 = (Addr) vg_sigmask;
7824 *vg_sigmask = *guest_sigmask;
7825 VG_(sanitize_client_sigmask)(vg_sigmask);
7826 }
7827 }
sewardj8eb8bab2015-07-21 14:44:28 +00007828}
7829
7830POST(sys_pollsys)
7831{
Elliott Hughesa0664b92017-04-18 17:46:52 -07007832 vg_assert(SUCCESS || FAILURE);
7833
7834 if (SUCCESS && (RES >= 0)) {
sewardj8eb8bab2015-07-21 14:44:28 +00007835 UWord i;
7836 vki_pollfd_t *ufds = (vki_pollfd_t*)ARG1;
7837 for (i = 0; i < ARG2; i++)
7838 POST_FIELD_WRITE(ufds[i].revents);
7839 }
Elliott Hughesa0664b92017-04-18 17:46:52 -07007840
7841 if ((ARG4 != 0) && (ARG4 != 1)) {
7842 VG_(free)((vki_sigset_t *) ARG4);
7843 }
sewardj8eb8bab2015-07-21 14:44:28 +00007844}
7845
7846PRE(sys_labelsys)
7847{
7848 /* Kernel: int labelsys(int op, void *a1, void *a2, void *a3,
7849 void *a4, void *a5); */
7850
7851 switch (ARG1 /*op*/) {
7852 case VKI_TSOL_SYSLABELING:
7853 /* Libc: int is_system_labeled(void); */
florianb26101c2015-08-08 21:45:33 +00007854 PRINT("sys_labelsys ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007855 PRE_REG_READ1(long, SC2("labelsys", "syslabeling"), int, op);
7856 break;
7857
7858 case VKI_TSOL_TNRH:
7859 /* Libtsnet: int tnrh(int cmd, tsol_rhent_t *buf); */
florianb26101c2015-08-08 21:45:33 +00007860 PRINT("sys_labelsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00007861 PRE_REG_READ3(long, SC2("labelsys", "tnrh"), int, op, int, cmd,
7862 vki_tsol_rhent_t *, buf);
7863 if (ARG2 != VKI_TNDB_FLUSH)
7864 PRE_MEM_READ("labelsys(buf)", ARG3, sizeof(vki_tsol_rhent_t));
7865 break;
7866
7867 case VKI_TSOL_TNRHTP:
7868 /* Libtsnet: int tnrhtp(int cmd, tsol_tpent_t *buf); */
florianb26101c2015-08-08 21:45:33 +00007869 PRINT("sys_labelsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00007870 PRE_REG_READ3(long, SC2("labelsys", "tnrhtp"), int, op, int, cmd,
7871 vki_tsol_tpent_t *, buf);
7872 if (ARG2 != VKI_TNDB_FLUSH)
7873 PRE_MEM_READ("labelsys(buf)", ARG3, sizeof(vki_tsol_tpent_t));
7874 break;
7875
7876 case VKI_TSOL_TNMLP:
7877 /* Libtsnet: int tnmlp(int cmd, tsol_mlpent_t *buf); */
florianb26101c2015-08-08 21:45:33 +00007878 PRINT("sys_labelsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00007879 PRE_REG_READ3(long, SC2("labelsys", "tnmlp"), int, op, int, cmd,
7880 vki_tsol_mlpent_t *, buf);
7881 PRE_MEM_READ("labelsys(buf)", ARG3, sizeof(vki_tsol_mlpent_t));
7882 break;
7883
7884 case VKI_TSOL_GETLABEL:
7885 /* Libtsol: int getlabel(const char *path, bslabel_t *label); */
7886 PRINT("sys_labelsys ( %ld, %#lx(%s), %#lx )",
florianb26101c2015-08-08 21:45:33 +00007887 SARG1, ARG2, (HChar *) ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00007888 PRE_REG_READ3(long, SC2("labelsys", "getlabel"), int, op,
7889 const char *, path, vki_bslabel_t *, label);
7890 PRE_MEM_RASCIIZ("labelsys(path)", ARG2);
7891 PRE_MEM_WRITE("labelsys(label)", ARG3, sizeof(vki_bslabel_t));
7892 break;
7893
7894 case VKI_TSOL_FGETLABEL:
7895 /* Libtsol: int fgetlabel(int fd, bslabel_t *label); */
florianb26101c2015-08-08 21:45:33 +00007896 PRINT("sys_labelsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00007897 PRE_REG_READ3(long, SC2("labelsys", "fgetlabel"), int, op,
7898 int, fd, vki_bslabel_t *, label);
7899 /* Be strict. */
7900 if (!ML_(fd_allowed)(ARG2, "labelsys(fgetlabel)", tid, False))
7901 SET_STATUS_Failure(VKI_EBADF);
7902 PRE_MEM_WRITE("labelsys(label)", ARG3, sizeof(vki_bslabel_t));
7903 break;
7904
7905#if defined(SOLARIS_TSOL_CLEARANCE)
7906 case VKI_TSOL_GETCLEARANCE:
7907 /* Libtsol: int getclearance(bslabel_t *clearance); */
florianb26101c2015-08-08 21:45:33 +00007908 PRINT("sys_labelsys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00007909 PRE_REG_READ2(long, SC2("labelsys", "getclearance"), int, op,
7910 vki_bslabel_t *, clearance);
7911 PRE_MEM_WRITE("labelsys(clearance)", ARG2, sizeof(vki_bslabel_t));
7912 break;
7913
7914 case VKI_TSOL_SETCLEARANCE:
7915 /* Libtsol: int setclearance(bslabel_t *clearance); */
florianb26101c2015-08-08 21:45:33 +00007916 PRINT("sys_labelsys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00007917 PRE_REG_READ2(long, SC2("labelsys", "setclearance"), int, op,
7918 vki_bslabel_t *, clearance);
7919 PRE_MEM_READ("labelsys(clearance)", ARG2, sizeof(vki_bslabel_t));
7920 break;
7921#endif /* SOLARIS_TSOL_CLEARANCE */
7922
7923 default:
florianb26101c2015-08-08 21:45:33 +00007924 VG_(unimplemented)("Syswrap of the labelsys call with op %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00007925 /*NOTREACHED*/
7926 break;
7927 }
7928}
7929
7930POST(sys_labelsys)
7931{
7932 switch (ARG1 /*op*/) {
7933 case VKI_TSOL_SYSLABELING:
7934 break;
7935
7936 case VKI_TSOL_TNRH:
7937 switch (ARG2 /*cmd*/) {
7938 case VKI_TNDB_LOAD:
7939 case VKI_TNDB_DELETE:
7940 case VKI_TNDB_FLUSH:
7941 break;
7942#if defined(SOLARIS_TNDB_GET_TNIP)
7943 case TNDB_GET_TNIP:
7944#endif /* SOLARIS_TNDB_GET_TNIP */
7945 case VKI_TNDB_GET:
7946 POST_MEM_WRITE(ARG3, sizeof(vki_tsol_rhent_t));
7947 break;
7948 default:
7949 vg_assert(0);
7950 break;
7951 }
7952 break;
7953
7954 case VKI_TSOL_TNRHTP:
7955 switch (ARG2 /*cmd*/) {
7956 case VKI_TNDB_LOAD:
7957 case VKI_TNDB_DELETE:
7958 case VKI_TNDB_FLUSH:
7959 break;
7960 case VKI_TNDB_GET:
7961 POST_MEM_WRITE(ARG3, sizeof(vki_tsol_tpent_t));
7962 break;
7963 default:
7964 vg_assert(0);
7965 break;
7966 }
7967 break;
7968
7969 case VKI_TSOL_TNMLP:
7970 switch (ARG2 /*cmd*/) {
7971 case VKI_TNDB_LOAD:
7972 case VKI_TNDB_DELETE:
7973 case VKI_TNDB_FLUSH:
7974 break;
7975 case VKI_TNDB_GET:
7976 POST_MEM_WRITE(ARG3, sizeof(vki_tsol_mlpent_t));
7977 break;
7978 default:
7979 vg_assert(0);
7980 break;
7981 }
7982 break;
7983
7984 case VKI_TSOL_GETLABEL:
7985 case VKI_TSOL_FGETLABEL:
7986 POST_MEM_WRITE(ARG3, sizeof(vki_bslabel_t));
7987 break;
7988
7989#if defined(SOLARIS_TSOL_CLEARANCE)
7990 case VKI_TSOL_GETCLEARANCE:
7991 POST_MEM_WRITE(ARG2, sizeof(vki_bslabel_t));
7992 break;
7993
7994 case VKI_TSOL_SETCLEARANCE:
7995 break;
7996#endif /* SOLARIS_TSOL_CLEARANCE */
7997
7998 default:
7999 vg_assert(0);
8000 break;
8001 }
8002}
8003
8004PRE(sys_acl)
8005{
8006 /* int acl(char *pathp, int cmd, int nentries, void *aclbufp); */
florianb26101c2015-08-08 21:45:33 +00008007 PRINT("sys_acl ( %#lx(%s), %ld, %ld, %#lx )", ARG1, (HChar *) ARG1, SARG2,
8008 SARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00008009
8010 PRE_REG_READ4(long, "acl", char *, pathp, int, cmd,
8011 int, nentries, void *, aclbufp);
8012 PRE_MEM_RASCIIZ("acl(pathp)", ARG1);
8013
8014 switch (ARG2 /*cmd*/) {
8015 case VKI_SETACL:
8016 if (ARG4)
8017 PRE_MEM_READ("acl(aclbufp)", ARG4, ARG3 * sizeof(vki_aclent_t));
8018 break;
8019 case VKI_GETACL:
8020 PRE_MEM_WRITE("acl(aclbufp)", ARG4, ARG3 * sizeof(vki_aclent_t));
8021 break;
8022 case VKI_GETACLCNT:
8023 break;
8024 case VKI_ACE_SETACL:
8025 if (ARG4)
8026 PRE_MEM_READ("acl(aclbufp)", ARG4, ARG3 * sizeof(vki_ace_t));
8027 break;
8028 case VKI_ACE_GETACL:
8029 PRE_MEM_WRITE("acl(aclbufp)", ARG4, ARG3 * sizeof(vki_ace_t));
8030 break;
8031 case VKI_ACE_GETACLCNT:
8032 break;
8033 default:
florianb26101c2015-08-08 21:45:33 +00008034 VG_(unimplemented)("Syswrap of the acl call with cmd %ld.", SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008035 /*NOTREACHED*/
8036 break;
8037 }
8038}
8039
8040POST(sys_acl)
8041{
8042 switch (ARG2 /*cmd*/) {
8043 case VKI_SETACL:
8044 break;
8045 case VKI_GETACL:
8046 POST_MEM_WRITE(ARG4, ARG3 * sizeof(vki_aclent_t));
8047 break;
8048 case VKI_GETACLCNT:
8049 break;
8050 case VKI_ACE_SETACL:
8051 break;
8052 case VKI_ACE_GETACL:
8053 POST_MEM_WRITE(ARG4, ARG3 * sizeof(vki_ace_t));
8054 break;
8055 case VKI_ACE_GETACLCNT:
8056 break;
8057 default:
8058 vg_assert(0);
8059 break;
8060 }
8061}
8062
8063PRE(sys_auditsys)
8064{
8065 /* Kernel: int auditsys(long code, long a1, long a2, long a3, long a4); */
8066 switch (ARG1 /*code*/) {
8067 case VKI_BSM_GETAUID:
8068 /* Libbsm: int getauid(au_id_t *auid); */
florianb26101c2015-08-08 21:45:33 +00008069 PRINT("sys_auditsys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008070 PRE_REG_READ2(long, SC2("auditsys", "getauid"), long, code,
8071 vki_au_id_t *, auid);
8072 PRE_MEM_WRITE("auditsys(auid)", ARG2, sizeof(vki_au_id_t));
8073 break;
8074 case VKI_BSM_SETAUID:
8075 /* Libbsm: int setauid(au_id_t *auid); */
florianb26101c2015-08-08 21:45:33 +00008076 PRINT("sys_auditsys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008077 PRE_REG_READ2(long, SC2("auditsys", "setauid"), long, code,
8078 vki_au_id_t *, auid);
8079 PRE_MEM_READ("auditsys(auid)", ARG2, sizeof(vki_au_id_t));
8080 break;
8081 case VKI_BSM_GETAUDIT:
8082 /* Libbsm: int getaudit(auditinfo_t *ai); */
florianb26101c2015-08-08 21:45:33 +00008083 PRINT("sys_auditsys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008084 PRE_REG_READ2(long, SC2("auditsys", "getaudit"), long, code,
8085 vki_auditinfo_t *, ai);
8086 PRE_MEM_WRITE("auditsys(ai)", ARG2, sizeof(vki_auditinfo_t));
8087 break;
8088 case VKI_BSM_SETAUDIT:
8089 /* Libbsm: int setaudit(auditinfo_t *ai); */
florianb26101c2015-08-08 21:45:33 +00008090 PRINT("sys_auditsys ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008091 PRE_REG_READ2(long, SC2("auditsys", "setaudit"), long, code,
8092 vki_auditinfo_t *, ai);
8093 PRE_MEM_READ("auditsys(ai)", ARG2, sizeof(vki_auditinfo_t));
8094 break;
8095 case VKI_BSM_AUDIT:
8096 /* Libbsm: int audit(void *record, int length); */
florianb26101c2015-08-08 21:45:33 +00008097 PRINT("sys_auditsys ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00008098 PRE_REG_READ3(long, SC2("auditsys", "audit"), long, code,
8099 void *, record, int, length);
8100 PRE_MEM_READ("auditsys(record)", ARG2, ARG3);
8101 break;
8102 case VKI_BSM_AUDITCTL:
8103 /* Libbsm: int auditon(int cmd, caddr_t data, int length); */
8104 PRINT("sys_auditsys ( %ld, %ld, %#lx, %ld )",
florianb26101c2015-08-08 21:45:33 +00008105 SARG1, SARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00008106
8107 switch (ARG2 /*cmd*/) {
8108 case VKI_A_GETPOLICY:
8109 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getpolicy"),
8110 long, code, int, cmd, vki_uint32_t *, policy);
8111 PRE_MEM_WRITE("auditsys(policy)", ARG3, sizeof(vki_uint32_t));
8112 break;
8113 case VKI_A_SETPOLICY:
8114 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setpolicy"),
8115 long, code, int, cmd, vki_uint32_t *, policy);
8116 PRE_MEM_READ("auditsys(policy)", ARG3, sizeof(vki_uint32_t));
8117 break;
8118 case VKI_A_GETKMASK:
8119 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getkmask"),
8120 long, code, int, cmd, vki_au_mask_t *, kmask);
8121 PRE_MEM_WRITE("auditsys(kmask)", ARG3, sizeof(vki_au_mask_t));
8122 break;
8123 case VKI_A_SETKMASK:
8124 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setkmask"),
8125 long, code, int, cmd, vki_au_mask_t *, kmask);
8126 PRE_MEM_READ("auditsys(kmask)", ARG3, sizeof(vki_au_mask_t));
8127 break;
8128 case VKI_A_GETQCTRL:
8129 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getqctrl"),
8130 long, code, int, cmd,
8131 struct vki_au_qctrl *, qctrl);
8132 PRE_MEM_WRITE("auditsys(qctrl)", ARG3,
8133 sizeof(struct vki_au_qctrl));
8134 break;
8135 case VKI_A_SETQCTRL:
8136 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setqctrl"),
8137 long, code, int, cmd,
8138 struct vki_au_qctrl *, qctrl);
8139 PRE_MEM_READ("auditsys(qctrl)", ARG3,
8140 sizeof(struct vki_au_qctrl));
8141 break;
8142 case VKI_A_GETCWD:
8143 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "getcwd"),
8144 long, code, int, cmd, char *, data, int, length);
8145 PRE_MEM_WRITE("auditsys(data)", ARG3, ARG4);
8146 break;
8147 case VKI_A_GETCAR:
8148 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "getcar"),
8149 long, code, int, cmd, char *, data, int, length);
8150 PRE_MEM_WRITE("auditsys(data)", ARG3, ARG4);
8151 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07008152#if defined(SOLARIS_AUDITON_STAT)
sewardj8eb8bab2015-07-21 14:44:28 +00008153 case VKI_A_GETSTAT:
8154 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getstat"),
8155 long, code, int, cmd, vki_au_stat_t *, stats);
8156 PRE_MEM_WRITE("auditsys(stats)", ARG3, sizeof(vki_au_stat_t));
8157 break;
8158 case VKI_A_SETSTAT:
8159 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setstat"),
8160 long, code, int, cmd, vki_au_stat_t *, stats);
8161 PRE_MEM_READ("auditsys(stats)", ARG3, sizeof(vki_au_stat_t));
8162 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07008163#endif /* SOLARIS_AUDITON_STAT */
sewardj8eb8bab2015-07-21 14:44:28 +00008164 case VKI_A_SETUMASK:
8165 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setumask"),
8166 long, code, int, cmd, vki_auditinfo_t *, umask);
8167 PRE_MEM_READ("auditsys(umask)", ARG3, sizeof(vki_auditinfo_t));
8168 break;
8169 case VKI_A_SETSMASK:
8170 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setsmask"),
8171 long, code, int, cmd, vki_auditinfo_t *, smask);
8172 PRE_MEM_READ("auditsys(smask)", ARG3, sizeof(vki_auditinfo_t));
8173 break;
8174 case VKI_A_GETCOND:
8175 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getcond"),
8176 long, code, int, cmd, int *, cond);
8177 PRE_MEM_WRITE("auditsys(cond)", ARG3, sizeof(int));
8178 break;
8179 case VKI_A_SETCOND:
8180 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setcond"),
8181 long, code, int, cmd, int *, state);
8182 PRE_MEM_READ("auditsys(cond)", ARG3, sizeof(int));
8183 break;
8184 case VKI_A_GETCLASS:
8185 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getclass"),
8186 long, code, int, cmd,
8187 vki_au_evclass_map_t *, classmap);
8188
8189 if (ML_(safe_to_deref((void *) ARG3,
8190 sizeof(vki_au_evclass_map_t)))) {
8191 vki_au_evclass_map_t *classmap =
8192 (vki_au_evclass_map_t *) ARG3;
8193 PRE_FIELD_READ("auditsys(classmap.ec_number)",
8194 classmap->ec_number);
8195 PRE_MEM_WRITE("auditsys(classmap)", ARG3,
8196 sizeof(vki_au_evclass_map_t));
8197 }
8198 break;
8199 case VKI_A_SETCLASS:
8200 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setclass"),
8201 long, code, int, cmd,
8202 vki_au_evclass_map_t *, classmap);
8203
8204 if (ML_(safe_to_deref((void *) ARG3,
8205 sizeof(vki_au_evclass_map_t)))) {
8206 vki_au_evclass_map_t *classmap =
8207 (vki_au_evclass_map_t *) ARG3;
8208 PRE_FIELD_READ("auditsys(classmap.ec_number)",
8209 classmap->ec_number);
8210 PRE_FIELD_READ("auditsys(classmap.ec_class)",
8211 classmap->ec_class);
8212 }
8213 break;
8214 case VKI_A_GETPINFO:
8215 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getpinfo"),
8216 long, code, int, cmd,
8217 struct vki_auditpinfo *, apinfo);
8218
8219 if (ML_(safe_to_deref((void *) ARG3,
8220 sizeof(struct vki_auditpinfo)))) {
8221 struct vki_auditpinfo *apinfo =
8222 (struct vki_auditpinfo *) ARG3;
8223 PRE_FIELD_READ("auditsys(apinfo.ap_pid)", apinfo->ap_pid);
8224 PRE_MEM_WRITE("auditsys(apinfo)", ARG3,
8225 sizeof(struct vki_auditpinfo));
8226 }
8227 break;
8228 case VKI_A_SETPMASK:
8229 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setpmask"),
8230 long, code, int, cmd,
8231 struct vki_auditpinfo *, apinfo);
8232 PRE_MEM_WRITE("auditsys(apinfo)", ARG3,
8233 sizeof(struct vki_auditpinfo));
8234 break;
8235 case VKI_A_GETPINFO_ADDR:
8236 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "getpinfo_addr"),
8237 long, code, int, cmd,
8238 struct vki_auditpinfo_addr *, apinfo, int, length);
8239
8240 if (ML_(safe_to_deref((void *) ARG3,
8241 sizeof(struct vki_auditpinfo_addr)))) {
8242 struct vki_auditpinfo_addr *apinfo_addr =
8243 (struct vki_auditpinfo_addr *) ARG3;
8244 PRE_FIELD_READ("auditsys(apinfo_addr.ap_pid)",
8245 apinfo_addr->ap_pid);
8246 PRE_MEM_WRITE("auditsys(apinfo_addr)", ARG3, ARG4);
8247 }
8248 break;
8249 case VKI_A_GETKAUDIT:
8250 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "getkaudit"),
8251 long, code, int, cmd,
8252 vki_auditinfo_addr_t *, kaudit, int, length);
8253 PRE_MEM_WRITE("auditsys(kaudit)", ARG3, ARG4);
8254 break;
8255 case VKI_A_SETKAUDIT:
8256 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "setkaudit"),
8257 long, code, int, cmd,
8258 vki_auditinfo_addr_t *, kaudit, int, length);
8259 PRE_MEM_READ("auditsys(kaudit)", ARG3, ARG4);
8260 break;
8261 case VKI_A_GETAMASK:
8262 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getamask"),
8263 long, code, int, cmd, vki_au_mask_t *, amask);
8264 PRE_MEM_WRITE("auditsys(amask)", ARG3, sizeof(vki_au_mask_t));
8265 break;
8266 case VKI_A_SETAMASK:
8267 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setamask"),
8268 long, code, int, cmd, vki_au_mask_t *, amask);
8269 PRE_MEM_READ("auditsys(amask)", ARG3, sizeof(vki_au_mask_t));
8270 break;
8271 default:
8272 VG_(unimplemented)("Syswrap of the auditsys(auditctl) call "
florianb26101c2015-08-08 21:45:33 +00008273 "with cmd %lu.", ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008274 /*NOTREACHED*/
8275 break;
8276 }
8277 break;
8278 case VKI_BSM_GETAUDIT_ADDR:
8279 /* Libbsm: int getaudit_addr(auditinfo_addr_t *ai, int len); */
florianb26101c2015-08-08 21:45:33 +00008280 PRINT("sys_auditsys ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00008281 PRE_REG_READ3(long, SC2("auditsys", "getaudit_addr"), long, code,
8282 vki_auditinfo_addr_t *, ai, int, len);
8283 PRE_MEM_WRITE("auditsys(ai)", ARG2, ARG3);
8284 break;
8285 case VKI_BSM_SETAUDIT_ADDR:
8286 /* Libbsm: int setaudit_addr(auditinfo_addr_t *ai, int len); */
florianb26101c2015-08-08 21:45:33 +00008287 PRINT("sys_auditsys ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00008288 PRE_REG_READ3(long, SC2("auditsys", "setaudit_addr"), long, code,
8289 vki_auditinfo_addr_t *, ai, int, len);
8290 PRE_MEM_READ("auditsys(ai)", ARG2, ARG3);
8291 break;
8292 case VKI_BSM_AUDITDOOR:
8293 /* Libbsm: int auditdoor(int fd); */
florianb26101c2015-08-08 21:45:33 +00008294 PRINT("sys_auditsys ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008295 PRE_REG_READ2(long, SC2("auditsys", "door"), long, code, int, fd);
8296
8297 /* Be strict. */
8298 if (!ML_(fd_allowed)(ARG2, SC2("auditsys", "door")"(fd)",
8299 tid, False))
8300 SET_STATUS_Failure(VKI_EBADF);
8301 break;
8302 default:
florianb26101c2015-08-08 21:45:33 +00008303 VG_(unimplemented)("Syswrap of the auditsys call with code %lu.", ARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00008304 /*NOTREACHED*/
8305 break;
8306 }
8307}
8308
8309POST(sys_auditsys)
8310{
8311 switch (ARG1 /*code*/) {
8312 case VKI_BSM_GETAUID:
8313 POST_MEM_WRITE(ARG2, sizeof(vki_au_id_t));
8314 break;
8315 case VKI_BSM_SETAUID:
8316 break;
8317 case VKI_BSM_GETAUDIT:
8318 POST_MEM_WRITE(ARG2, sizeof(vki_auditinfo_t));
8319 break;
8320 case VKI_BSM_SETAUDIT:
8321 case VKI_BSM_AUDIT:
8322 break;
8323 case VKI_BSM_AUDITCTL:
8324 switch (ARG2 /*cmd*/) {
8325 case VKI_A_GETPOLICY:
8326 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
8327 break;
8328 case VKI_A_SETPOLICY:
8329 break;
8330 case VKI_A_GETKMASK:
8331 POST_MEM_WRITE(ARG3, sizeof(vki_au_mask_t));
8332 break;
8333 case VKI_A_SETKMASK:
8334 break;
8335 case VKI_A_GETQCTRL:
8336 POST_MEM_WRITE(ARG3, sizeof(struct vki_au_qctrl));
8337 break;
8338 case VKI_A_SETQCTRL:
8339 break;
8340 case VKI_A_GETCWD:
8341 case VKI_A_GETCAR:
8342 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
8343 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07008344#if defined(SOLARIS_AUDITON_STAT)
sewardj8eb8bab2015-07-21 14:44:28 +00008345 case VKI_A_GETSTAT:
8346 POST_MEM_WRITE(ARG3, sizeof(vki_au_stat_t));
8347 break;
8348 case VKI_A_SETSTAT:
Elliott Hughesa0664b92017-04-18 17:46:52 -07008349#endif /* SOLARIS_AUDITON_STAT */
sewardj8eb8bab2015-07-21 14:44:28 +00008350 case VKI_A_SETUMASK:
8351 case VKI_A_SETSMASK:
8352 break;
8353 case VKI_A_GETCOND:
8354 POST_MEM_WRITE(ARG3, sizeof(int));
8355 break;
8356 case VKI_A_SETCOND:
8357 break;
8358 case VKI_A_GETCLASS:
8359 POST_MEM_WRITE(ARG3, sizeof(vki_au_evclass_map_t));
8360 break;
8361 case VKI_A_SETCLASS:
8362 break;
8363 case VKI_A_GETPINFO:
8364 POST_MEM_WRITE(ARG3, sizeof(struct vki_auditpinfo));
8365 break;
8366 case VKI_A_SETPMASK:
8367 break;
8368 case VKI_A_GETPINFO_ADDR:
8369 POST_MEM_WRITE(ARG3, sizeof(struct auditpinfo_addr));
8370 break;
8371 case VKI_A_GETKAUDIT:
8372 POST_MEM_WRITE(ARG3, sizeof(vki_auditinfo_addr_t));
8373 break;
8374 case VKI_A_SETKAUDIT:
8375 break;
8376 case VKI_A_GETAMASK:
8377 POST_MEM_WRITE(ARG3, sizeof(vki_au_mask_t));
8378 break;
8379 case VKI_A_SETAMASK:
8380 break;
8381 }
8382 break;
8383 case VKI_BSM_GETAUDIT_ADDR:
8384 POST_MEM_WRITE(ARG2, sizeof(vki_auditinfo_addr_t));
8385 break;
8386 case VKI_BSM_SETAUDIT_ADDR:
8387 break;
8388 case VKI_BSM_AUDITDOOR:
8389 break;
8390 }
8391}
8392
8393PRE(sys_p_online)
8394{
8395 /* int p_online(processorid_t processorid, int flag); */
florianb26101c2015-08-08 21:45:33 +00008396 PRINT("sys_p_online ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008397 PRE_REG_READ2(long, "p_online", vki_processorid_t, processorid, int, flag);
8398}
8399
8400PRE(sys_sigqueue)
8401{
8402 /* int sigqueue(pid_t pid, int signo, void *value,
8403 int si_code, timespec_t *timeout);
8404 */
8405 PRINT("sys_sigqueue ( %ld, %ld, %#lx, %ld, %#lx )",
florianb26101c2015-08-08 21:45:33 +00008406 SARG1, SARG2, ARG3, SARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +00008407 PRE_REG_READ5(long, "sigqueue", vki_pid_t, pid, int, signo,
8408 void *, value, int, si_code,
8409 vki_timespec_t *, timeout);
8410
8411 if (ARG5)
8412 PRE_MEM_READ("sigqueue(timeout)", ARG5, sizeof(vki_timespec_t));
8413
8414 if (!ML_(client_signal_OK)(ARG2)) {
8415 SET_STATUS_Failure(VKI_EINVAL);
8416 return;
8417 }
8418
8419 /* If we're sending SIGKILL, check to see if the target is one of
8420 our threads and handle it specially. */
8421 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) {
8422 SET_STATUS_Success(0);
8423 } else {
8424 SysRes res = VG_(do_syscall5)(SYSNO, ARG1, ARG2, ARG3, ARG4,
8425 ARG5);
8426 SET_STATUS_from_SysRes(res);
8427 }
8428
8429 if (VG_(clo_trace_signals))
8430 VG_(message)(Vg_DebugMsg,
Elliott Hughesed398002017-06-21 14:41:24 -07008431 "sigqueue: signal %ld queued for pid %ld\n",
8432 SARG2, SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00008433
8434 /* Check to see if this gave us a pending signal. */
8435 *flags |= SfPollAfter;
8436}
8437
8438PRE(sys_clock_gettime)
8439{
8440 /* int clock_gettime(clockid_t clock_id, struct timespec *tp); */
florianb26101c2015-08-08 21:45:33 +00008441 PRINT("sys_clock_gettime ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008442 PRE_REG_READ2(long, "clock_gettime", vki_clockid_t, clock_id,
8443 struct timespec *, tp);
8444 PRE_MEM_WRITE("clock_gettime(tp)", ARG2, sizeof(struct vki_timespec));
8445}
8446
8447POST(sys_clock_gettime)
8448{
8449 POST_MEM_WRITE(ARG2, sizeof(struct vki_timespec));
8450}
8451
8452PRE(sys_clock_settime)
8453{
8454 /* int clock_settime(clockid_t clock_id, const struct timespec *tp); */
florianb26101c2015-08-08 21:45:33 +00008455 PRINT("sys_clock_settime ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008456 PRE_REG_READ2(long, "clock_settime", vki_clockid_t, clock_id,
8457 const struct timespec *, tp);
8458 PRE_MEM_READ("clock_settime(tp)", ARG2, sizeof(struct vki_timespec));
8459}
8460
8461PRE(sys_clock_getres)
8462{
8463 /* int clock_getres(clockid_t clock_id, struct timespec *res); */
florianb26101c2015-08-08 21:45:33 +00008464 PRINT("sys_clock_getres ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008465 PRE_REG_READ2(long, "clock_getres", vki_clockid_t, clock_id,
8466 struct timespec *, res);
8467
8468 if (ARG2)
8469 PRE_MEM_WRITE("clock_getres(res)", ARG2, sizeof(struct vki_timespec));
8470}
8471
8472POST(sys_clock_getres)
8473{
8474 if (ARG2)
8475 POST_MEM_WRITE(ARG2, sizeof(struct vki_timespec));
8476}
8477
8478PRE(sys_timer_create)
8479{
8480 /* int timer_create(clockid_t clock_id,
8481 struct sigevent *evp, timer_t *timerid);
8482 */
florianb26101c2015-08-08 21:45:33 +00008483 PRINT("sys_timer_create ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00008484 PRE_REG_READ3(long, "timer_create", vki_clockid_t, clock_id,
8485 struct vki_sigevent *, evp, vki_timer_t *, timerid);
8486
8487 if (ARG2) {
8488 struct vki_sigevent *evp = (struct vki_sigevent *) ARG2;
8489 PRE_FIELD_READ("timer_create(evp.sigev_notify)", evp->sigev_notify);
8490 PRE_FIELD_READ("timer_create(evp.sigev_signo)", evp->sigev_signo);
8491 PRE_FIELD_READ("timer_create(evp.sigev_value.sival_int)",
8492 evp->sigev_value.sival_int);
8493
8494 /* Be safe. */
8495 if (ML_(safe_to_deref(evp, sizeof(struct vki_sigevent)))) {
8496 if ((evp->sigev_notify == VKI_SIGEV_PORT) ||
8497 (evp->sigev_notify == VKI_SIGEV_THREAD))
8498 PRE_MEM_READ("timer_create(evp.sigev_value.sival_ptr)",
8499 (Addr) evp->sigev_value.sival_ptr,
8500 sizeof(vki_port_notify_t));
8501 }
8502 }
8503
8504 PRE_MEM_WRITE("timer_create(timerid)", ARG3, sizeof(vki_timer_t));
8505}
8506
8507POST(sys_timer_create)
8508{
8509 POST_MEM_WRITE(ARG3, sizeof(vki_timer_t));
8510}
8511
8512PRE(sys_timer_delete)
8513{
8514 /* int timer_delete(timer_t timerid); */
florianb26101c2015-08-08 21:45:33 +00008515 PRINT("sys_timer_delete ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00008516 PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid);
8517}
8518
8519PRE(sys_timer_settime)
8520{
8521 /* int timer_settime(timer_t timerid, int flags,
8522 const struct itimerspec *value,
8523 struct itimerspec *ovalue);
8524 */
8525 PRINT("sys_timer_settime ( %ld, %ld, %#lx, %#lx )",
florianb26101c2015-08-08 21:45:33 +00008526 SARG1, SARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00008527 PRE_REG_READ4(long, "timer_settime", vki_timer_t, timerid,
8528 int, flags, const struct vki_itimerspec *, value,
8529 struct vki_itimerspec *, ovalue);
8530 PRE_MEM_READ("timer_settime(value)",
8531 ARG3, sizeof(struct vki_itimerspec));
8532 if (ARG4)
8533 PRE_MEM_WRITE("timer_settime(ovalue)",
8534 ARG4, sizeof(struct vki_itimerspec));
8535}
8536
8537POST(sys_timer_settime)
8538{
8539 if (ARG4)
8540 POST_MEM_WRITE(ARG4, sizeof(struct vki_itimerspec));
8541}
8542
8543PRE(sys_timer_gettime)
8544{
8545 /* int timer_gettime(timer_t timerid, struct itimerspec *value); */
florianb26101c2015-08-08 21:45:33 +00008546 PRINT("sys_timer_gettime ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008547 PRE_REG_READ2(long, "timer_gettime", vki_timer_t, timerid,
8548 struct vki_itimerspec *, value);
8549 PRE_MEM_WRITE("timer_gettime(value)",
8550 ARG2, sizeof(struct vki_itimerspec));
8551}
8552
8553POST(sys_timer_gettime)
8554{
8555 POST_MEM_WRITE(ARG2, sizeof(struct vki_itimerspec));
8556}
8557
8558PRE(sys_timer_getoverrun)
8559{
8560 /* int timer_getoverrun(timer_t timerid); */
florianb26101c2015-08-08 21:45:33 +00008561 PRINT("sys_timer_getoverrun ( %ld )", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00008562 PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid);
8563}
8564
8565PRE(sys_facl)
8566{
8567 /* int facl(int fildes, int cmd, int nentries, void *aclbufp); */
florianb26101c2015-08-08 21:45:33 +00008568 PRINT("sys_facl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +00008569
8570 PRE_REG_READ4(long, "facl", int, fildes, int, cmd,
8571 int, nentries, void *, aclbufp);
8572
8573 switch (ARG2 /*cmd*/) {
8574 case VKI_SETACL:
8575 if (ARG4)
8576 PRE_MEM_READ("facl(aclbufp)", ARG4, sizeof(vki_aclent_t));
8577 break;
8578 case VKI_GETACL:
8579 PRE_MEM_WRITE("facl(aclbufp)", ARG4, ARG3 * sizeof(vki_aclent_t));
8580 break;
8581 case VKI_GETACLCNT:
8582 break;
8583 case VKI_ACE_SETACL:
8584 if (ARG4)
8585 PRE_MEM_READ("facl(aclbufp)", ARG4, sizeof(vki_ace_t));
8586 break;
8587 case VKI_ACE_GETACL:
8588 PRE_MEM_WRITE("facl(aclbufp)", ARG4, ARG3 * sizeof(vki_ace_t));
8589 break;
8590 case VKI_ACE_GETACLCNT:
8591 break;
8592 default:
florianb26101c2015-08-08 21:45:33 +00008593 VG_(unimplemented)("Syswrap of the facl call with cmd %ld.", SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00008594 /*NOTREACHED*/
8595 break;
8596 }
8597
8598 /* Be strict. */
8599 if (!ML_(fd_allowed)(ARG1, "facl", tid, False))
8600 SET_STATUS_Failure(VKI_EBADF);
8601}
8602
8603POST(sys_facl)
8604{
8605 switch (ARG2 /*cmd*/) {
8606 case VKI_SETACL:
8607 break;
8608 case VKI_GETACL:
8609 POST_MEM_WRITE(ARG4, ARG3 * sizeof(vki_aclent_t));
8610 break;
8611 case VKI_GETACLCNT:
8612 break;
8613 case VKI_ACE_SETACL:
8614 break;
8615 case VKI_ACE_GETACL:
8616 POST_MEM_WRITE(ARG4, ARG3 * sizeof(vki_ace_t));
8617 break;
8618 case VKI_ACE_GETACLCNT:
8619 break;
8620 default:
8621 vg_assert(0);
8622 break;
8623 }
8624}
8625
8626static Int pre_check_and_close_fds(ThreadId tid, const HChar *name,
8627 vki_door_desc_t *desc_ptr,
8628 vki_uint_t desc_num)
8629{
8630 vki_uint_t i;
8631
8632 /* Verify passed file descriptors. */
8633 for (i = 0; i < desc_num; i++) {
8634 vki_door_desc_t *desc = &desc_ptr[i];
8635 if ((desc->d_attributes & DOOR_DESCRIPTOR) &&
8636 (desc->d_attributes & DOOR_RELEASE)) {
8637 Int fd = desc->d_data.d_desc.d_descriptor;
8638
8639 /* Detect and negate attempts by the client to close Valgrind's fds.
8640 Also if doing -d style logging (which is to fd = 2 = stderr),
8641 don't allow that to be closed either. */
8642 if (!ML_(fd_allowed)(fd, name, tid, False) ||
8643 (fd == 2 && VG_(debugLog_getLevel)() > 0))
8644 return VKI_EBADF;
8645 }
8646 }
8647
8648 /* All fds are allowed, record information about the closed ones.
8649
8650 Note: Recording information about any closed fds should generally happen
8651 in a post wrapper but it is not possible in this case because door calls
8652 are "very blocking", if the information was recorded after the syscall
8653 finishes then it would be out-of-date during the call, i.e. while the
8654 syscall is blocked in the kernel. Therefore, we record closed fds for
8655 this specific syscall in the PRE wrapper. Unfortunately, this creates
8656 a problem when the syscall fails, for example, door_call() can fail with
8657 EBADF or EFAULT and then no fds are released. If that happens the
8658 information about opened fds is incorrect. This should be very rare (I
8659 hope) and such a condition is also reported in the post wrapper. */
8660 if (VG_(clo_track_fds)) {
8661 for (i = 0; i < desc_num; i++) {
8662 vki_door_desc_t *desc = &desc_ptr[i];
8663 if ((desc->d_attributes & DOOR_DESCRIPTOR) &&
8664 (desc->d_attributes & DOOR_RELEASE)) {
8665 Int fd = desc->d_data.d_desc.d_descriptor;
8666 ML_(record_fd_close)(fd);
8667 }
8668 }
8669 }
8670
8671 return 0;
8672}
8673
8674static void post_record_fds(ThreadId tid, const HChar *name,
8675 vki_door_desc_t *desc_ptr, vki_uint_t desc_num)
8676{
8677 vki_uint_t i;
8678
8679 /* Record returned file descriptors. */
8680 for (i = 0; i < desc_num; i++) {
8681 vki_door_desc_t *desc = &desc_ptr[i];
8682 if (desc->d_attributes & DOOR_DESCRIPTOR) {
8683 Int fd = desc->d_data.d_desc.d_descriptor;
8684 if (!ML_(fd_allowed)(fd, name, tid, True)) {
8685 /* Unfortunately, we cannot recover at this point and have to fail
8686 hard. */
8687 VG_(message)(Vg_UserMsg, "The %s syscall returned an unallowed"
8688 "file descriptor %d.\n", name, fd);
8689 VG_(exit)(101);
8690 }
8691 else if (VG_(clo_track_fds))
8692 ML_(record_fd_open_named)(tid, fd);
8693 }
8694 }
8695}
8696
8697/* Handles repository door protocol request over client door fd. */
8698static void repository_door_pre_mem_door_call_hook(ThreadId tid, Int fd,
8699 void *data_ptr,
8700 SizeT data_size)
8701{
8702 vki_rep_protocol_request_t *p = (vki_rep_protocol_request_t *) data_ptr;
8703 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8704 "request->rpr_request)", p->rpr_request);
8705
8706 if (ML_(safe_to_deref)(p, sizeof(vki_rep_protocol_request_t))) {
8707 switch (p->rpr_request) {
8708 case VKI_REP_PROTOCOL_CLOSE:
8709 break;
8710 case VKI_REP_PROTOCOL_ENTITY_SETUP:
8711 {
8712 struct vki_rep_protocol_entity_setup *r =
8713 (struct vki_rep_protocol_entity_setup *) p;
8714 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8715 "entity_setup->rpr_entityid)", r->rpr_entityid);
8716 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8717 "entity_setup->rpr_entitytype)", r->rpr_entitytype);
8718 }
8719 break;
8720 case VKI_REP_PROTOCOL_ENTITY_NAME:
8721 {
8722 struct vki_rep_protocol_entity_name *r =
8723 (struct vki_rep_protocol_entity_name *) p;
8724 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8725 "entity_name->rpr_entityid)", r->rpr_entityid);
8726 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8727 "entity_name->rpr_answertype)", r->rpr_answertype);
8728 }
8729 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07008730#if (SOLARIS_REPCACHE_PROTOCOL_VERSION >= 24) && (SOLARIS_REPCACHE_PROTOCOL_VERSION <= 30)
8731 case VKI_REP_PROTOCOL_ENTITY_FMRI:
8732 {
8733 struct vki_rep_protocol_entity_fmri *r =
8734 (struct vki_rep_protocol_entity_fmri *) p;
8735 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8736 "entity_fmri->rpr_entityid)", r->rpr_entityid);
8737 }
8738 break;
8739#endif /* 24 <= SOLARIS_REPCACHE_PROTOCOL_VERSION =< 30 */
iraisr23e68ca2015-08-14 20:50:11 +00008740#if (SOLARIS_REPCACHE_PROTOCOL_VERSION >= 25)
iraisr03a6b142015-08-11 09:12:40 +00008741 case VKI_REP_PROTOCOL_ENTITY_GET_ROOT:
8742 {
8743 struct vki_rep_protocol_entity_root *r =
8744 (struct vki_rep_protocol_entity_root *) p;
8745 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8746 "entity_root->rpr_entityid)", r->rpr_entityid);
8747 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8748 "entity_root->rpr_outid)", r->rpr_outid);
8749 }
8750 break;
iraisr23e68ca2015-08-14 20:50:11 +00008751#endif /* SOLARIS_REPCACHE_PROTOCOL_VERSION >= 25 */
sewardj8eb8bab2015-07-21 14:44:28 +00008752 case VKI_REP_PROTOCOL_ENTITY_GET:
8753 {
8754 struct vki_rep_protocol_entity_get *r =
8755 (struct vki_rep_protocol_entity_get *) p;
8756 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8757 "entity_get->rpr_entityid)", r->rpr_entityid);
8758 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8759 "entity_get->rpr_object)", r->rpr_object);
8760 }
8761 break;
8762 case VKI_REP_PROTOCOL_ENTITY_GET_CHILD:
Elliott Hughesa0664b92017-04-18 17:46:52 -07008763#if (SOLARIS_REPCACHE_PROTOCOL_VERSION >= 31)
8764 case VKI_REP_PROTOCOL_ENTITY_GET_CHILD_COMPOSED:
8765#endif
sewardj8eb8bab2015-07-21 14:44:28 +00008766 {
8767 struct vki_rep_protocol_entity_get_child *r =
8768 (struct vki_rep_protocol_entity_get_child *) p;
8769 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8770 "entity_get_child->rpr_entityid)", r->rpr_entityid);
8771 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8772 "entity_get_child->rpr_childid)", r->rpr_childid);
8773 PRE_MEM_RASCIIZ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8774 "entity_get_child->rpr_name)", (Addr) r->rpr_name);
8775 }
8776 break;
8777 case VKI_REP_PROTOCOL_ENTITY_GET_PARENT:
8778 {
8779 struct vki_rep_protocol_entity_parent *r =
8780 (struct vki_rep_protocol_entity_parent *) p;
8781 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8782 "entity_get_parent->rpr_entityid)", r->rpr_entityid);
8783 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8784 "entity_get_parent->rpr_outid)", r->rpr_outid);
8785 }
8786 break;
8787 case VKI_REP_PROTOCOL_ENTITY_RESET:
8788 {
8789 struct vki_rep_protocol_entity_reset *r =
8790 (struct vki_rep_protocol_entity_reset *) p;
8791 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8792 "entity_reset->rpr_entityid)", r->rpr_entityid);
8793 }
8794 break;
8795 case VKI_REP_PROTOCOL_ENTITY_TEARDOWN:
8796 {
8797 struct vki_rep_protocol_entity_teardown *r =
8798 (struct vki_rep_protocol_entity_teardown *) p;
8799 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8800 "entity_teardown->rpr_entityid)", r->rpr_entityid);
8801 }
8802 break;
8803 case VKI_REP_PROTOCOL_ITER_READ:
8804 {
8805 struct vki_rep_protocol_iter_read *r =
8806 (struct vki_rep_protocol_iter_read *) p;
8807 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8808 "iter_read->rpr_iterid)", r->rpr_iterid);
8809 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8810 "iter_read->rpr_sequence)", r->rpr_sequence);
8811 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8812 "iter_read->rpr_entityid)", r->rpr_entityid);
8813 }
8814 break;
8815 case VKI_REP_PROTOCOL_ITER_READ_VALUE:
8816 {
8817 struct vki_rep_protocol_iter_read_value *r =
8818 (struct vki_rep_protocol_iter_read_value *) p;
8819 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8820 "iter_read_value->rpr_iterid)", r->rpr_iterid);
8821 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8822 "iter_read_value->rpr_sequence)", r->rpr_sequence);
8823 }
8824 break;
8825 case VKI_REP_PROTOCOL_ITER_RESET:
8826 case VKI_REP_PROTOCOL_ITER_SETUP:
8827 case VKI_REP_PROTOCOL_ITER_TEARDOWN:
8828 {
8829 struct vki_rep_protocol_iter_request *r =
8830 (struct vki_rep_protocol_iter_request *) p;
8831 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8832 "iter_request->rpr_iterid)", r->rpr_iterid);
8833 }
8834 break;
8835 case VKI_REP_PROTOCOL_ITER_START:
8836 {
8837 struct vki_rep_protocol_iter_start *r =
8838 (struct vki_rep_protocol_iter_start *) p;
8839 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8840 "iter_start->rpr_iterid)", r->rpr_iterid);
8841 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8842 "iter_start->rpr_entity)", r->rpr_entity);
8843 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8844 "iter_start->rpr_itertype)", r->rpr_itertype);
8845 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8846 "iter_start->rpr_flags)", r->rpr_flags);
8847 PRE_MEM_RASCIIZ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8848 "iter_start->rpr_pattern)", (Addr) r->rpr_pattern);
8849 }
8850 break;
8851 case VKI_REP_PROTOCOL_PROPERTY_GET_TYPE:
8852 case VKI_REP_PROTOCOL_PROPERTY_GET_VALUE:
8853 {
8854 struct vki_rep_protocol_property_request *r =
8855 (struct vki_rep_protocol_property_request *) p;
8856 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8857 "property_request->rpr_entityid)", r->rpr_entityid);
8858 }
8859 break;
8860 default:
8861 VG_(unimplemented)("Door wrapper of " VKI_REPOSITORY_DOOR_NAME
Elliott Hughesa0664b92017-04-18 17:46:52 -07008862 " where rpr_request=%#x.", p->rpr_request);
sewardj8eb8bab2015-07-21 14:44:28 +00008863 /* NOTREACHED */
8864 break;
8865 }
8866 }
8867}
8868
8869/* Handles repository door protocol response over client door fd. */
8870static void repository_door_post_mem_door_call_hook(ThreadId tid, Int fd,
8871 void *rbuf, SizeT rsize)
8872{
8873 /* :TODO: Ideally we would need to match the response type with the
8874 previous request because response itself does not contain any
8875 type identification.
8876 For now simply make defined whole response buffer. */
8877 POST_MEM_WRITE((Addr) rbuf, rsize);
8878}
8879
8880/* Pre-syscall checks for params->data_ptr contents of a door_call(). */
8881static void door_call_pre_mem_params_data(ThreadId tid, Int fd,
8882 void *data_ptr, SizeT data_size)
8883{
8884 const HChar *pathname;
8885
8886 /* Get pathname of the door file descriptor, if not already done.
8887 Needed to dissect door service on the pathname below. */
8888 if (!VG_(clo_track_fds) && !ML_(fd_recorded)(fd)) {
8889 ML_(record_fd_open_named)(tid, fd);
8890 }
8891 pathname = ML_(find_fd_recorded_by_fd)(fd);
8892
8893 /* Debug-only printing. */
8894 if (0) {
8895 VG_(printf)("PRE(door_call) with fd=%d and filename=%s\n",
8896 fd, pathname);
8897 }
8898
8899 if (VG_STREQ(pathname, VKI__PATH_KCFD_DOOR)) {
8900 vki_kcf_door_arg_t *p = (vki_kcf_door_arg_t *) data_ptr;
8901
8902 PRE_FIELD_READ("door_call(\"" VKI__PATH_KCFD_DOOR "\", "
8903 "kcf_door_arg_t->da_version)", p->da_version);
8904 PRE_FIELD_READ("door_call(\"" VKI__PATH_KCFD_DOOR "\", "
8905 "kcf_door_arg_t->da_iskernel)", p->da_iskernel);
8906 PRE_MEM_RASCIIZ("door_call(\"" VKI__PATH_KCFD_DOOR "\", "
8907 "kcf_door_arg_t->da_u.filename)",
8908 (Addr) p->vki_da_u.filename);
8909 } else if (VG_STREQ(pathname, VKI_NAME_SERVICE_DOOR)) {
8910 vki_nss_pheader_t *p = (vki_nss_pheader_t *) data_ptr;
8911
8912 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8913 "nss_pheader->nsc_callnumber)", p->nsc_callnumber);
8914 if (ML_(safe_to_deref)(p, sizeof(vki_nss_pheader_t))) {
8915 if ((p->nsc_callnumber & VKI_NSCDV2CATMASK) == VKI_NSCD_CALLCAT_APP) {
8916 /* request from an application towards nscd */
8917 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8918 "nss_pheader->p_version)", p->p_version);
8919 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8920 "nss_pheader->dbd_off)", p->dbd_off);
8921 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8922 "nss_pheader->dbd_len)", p->dbd_len);
8923 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8924 "nss_pheader->key_off)", p->key_off);
8925 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8926 "nss_pheader->key_len)", p->key_len);
8927 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8928 "nss_pheader->data_off)", p->data_off);
8929 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8930 "nss_pheader->data_len)", p->data_len);
8931 /* Fields ext_off and ext_len are set only sporadically. */
8932 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8933 "nss_pheader->pbufsiz)", p->pbufsiz);
8934 PRE_MEM_WRITE("door_call(\"" VKI_NAME_SERVICE_DOOR "\", pbuf)",
8935 (Addr) p, p->pbufsiz);
8936
8937 if (p->dbd_len > 0) {
8938 vki_nss_dbd_t *dbd
8939 = (vki_nss_dbd_t *) ((HChar *) p + p->dbd_off);
8940
8941 PRE_MEM_READ("door_call(\"" VKI_NAME_SERVICE_DOOR
8942 "\", nss_dbd)", (Addr) dbd, sizeof(vki_nss_dbd_t));
8943 if (ML_(safe_to_deref)(dbd, sizeof(vki_nss_dbd_t))) {
8944 if (dbd->o_name != 0)
8945 PRE_MEM_RASCIIZ("door_call(\"" VKI_NAME_SERVICE_DOOR
8946 "\", nss_dbd->o_name)", (Addr) ((HChar *) p
8947 + p->dbd_off + dbd->o_name));
8948 if (dbd->o_config_name != 0)
8949 PRE_MEM_RASCIIZ("door_call(\"" VKI_NAME_SERVICE_DOOR
8950 "\", nss_dbd->o_config_name)",
8951 (Addr) ((HChar *) p + p->dbd_off
8952 + dbd->o_config_name));
8953 if (dbd->o_default_config != 0)
8954 PRE_MEM_RASCIIZ("door_call(\"" VKI_NAME_SERVICE_DOOR
8955 "\", nss_dbd->o_default_config)",
8956 (Addr) ((HChar *) p + p->dbd_off +
8957 dbd->o_default_config));
8958 }
8959 }
8960
8961 PRE_MEM_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", nss->key)",
8962 (Addr) ((HChar *) p + p->key_off), p->key_len);
8963 } else {
8964 /* request from a child nscd towards parent nscd */
8965 VG_(unimplemented)("Door wrapper of child/parent nscd.");
8966 }
8967 }
8968 } else if (VG_STREQ(pathname, VKI_REPOSITORY_DOOR_NAME)) {
8969 vki_repository_door_request_t *p =
8970 (vki_repository_door_request_t *) data_ptr;
8971
8972 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8973 "request->rdr_version)", p->rdr_version);
8974 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8975 "request->rdr_request)", p->rdr_request);
8976 if (ML_(safe_to_deref)(p, sizeof(vki_repository_door_request_t))) {
8977 if (p->rdr_version == VKI_REPOSITORY_DOOR_VERSION) {
8978 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8979 "request->rdr_flags)", p->rdr_flags);
8980 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8981 "request->rdr_debug)", p->rdr_debug);
8982 } else {
8983 VG_(unimplemented)("Door wrapper of " VKI_REPOSITORY_DOOR_NAME
8984 " where version=%u.", p->rdr_version);
8985 }
8986 }
8987 } else {
8988 const OpenDoor *open_door = door_find_by_fd(fd);
8989 if ((open_door != NULL) && (open_door->pre_mem_hook != NULL)) {
8990 open_door->pre_mem_hook(tid, fd, data_ptr, data_size);
8991 } else {
8992 if (SimHintiS(SimHint_lax_doors, VG_(clo_sim_hints))) {
8993 /*
8994 * Be very lax about door syscall handling over unrecognized
8995 * door file descriptors. Does not require that full buffer
8996 * is initialized when writing. Without this, programs using
8997 * libdoor(3LIB) functionality with completely proprietary
8998 * semantics may report large number of false positives.
8999 */
9000 } else {
9001 static Int moans = 3;
9002
9003 /* generic default */
9004 if (moans > 0 && !VG_(clo_xml)) {
9005 moans--;
9006 VG_(umsg)(
9007"Warning: noted and generically handled door call\n"
9008" on file descriptor %d (filename: %s).\n"
9009" This could cause spurious value errors to appear.\n"
9010" See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.\n"
9011" Alternatively you may find '--sim-hints=lax-doors' option useful.\n",
9012 fd, pathname);
9013 }
9014 PRE_MEM_READ("door_call(params->data_ptr)",
9015 (Addr) data_ptr, data_size);
9016 }
9017 }
9018 }
9019}
9020
9021/* Post-syscall checks for params->rbuf contents of a door_call(). */
9022static void door_call_post_mem_params_rbuf(ThreadId tid, Int fd,
9023 void *rbuf, SizeT rsize,
9024 const vki_door_desc_t *desc_ptr,
9025 vki_uint_t desc_num)
9026{
9027 const HChar *pathname = ML_(find_fd_recorded_by_fd)(fd);
9028
9029 /* Debug-only printing. */
9030 if (0) {
9031 VG_(printf)("POST(door_call) with fd=%d and filename=%s\n",
9032 fd, pathname);
9033 }
9034
9035 if (VG_STREQ(pathname, VKI__PATH_KCFD_DOOR)) {
9036 vki_kcf_door_arg_t *p = (vki_kcf_door_arg_t *) rbuf;
9037
9038 POST_FIELD_WRITE(p->da_version);
9039 POST_FIELD_WRITE(p->vki_da_u.result.status);
9040 POST_MEM_WRITE((Addr) p->vki_da_u.result.signature,
9041 p->vki_da_u.result.siglen);
9042 } else if (VG_STREQ(pathname, VKI_NAME_SERVICE_DOOR)) {
9043 vki_nss_pheader_t *p = (vki_nss_pheader_t *) rbuf;
9044
9045 POST_FIELD_WRITE(p->nsc_callnumber);
9046 if (ML_(safe_to_deref)(p, sizeof(vki_nss_pheader_t))) {
9047 if ((p->nsc_callnumber & VKI_NSCDV2CATMASK) == VKI_NSCD_CALLCAT_APP) {
9048 /* response from nscd to an application */
9049 POST_FIELD_WRITE(p->p_status);
9050 POST_FIELD_WRITE(p->p_errno);
9051 POST_FIELD_WRITE(p->p_herrno);
9052 POST_FIELD_WRITE(p->dbd_off);
9053 POST_FIELD_WRITE(p->dbd_len);
9054 POST_FIELD_WRITE(p->key_off);
9055 POST_FIELD_WRITE(p->key_len);
9056 POST_FIELD_WRITE(p->data_off);
9057 POST_FIELD_WRITE(p->data_len);
9058 POST_FIELD_WRITE(p->ext_off);
9059 POST_FIELD_WRITE(p->ext_len);
9060 POST_FIELD_WRITE(p->pbufsiz);
9061
9062 if (p->pbufsiz <= rsize) {
9063 if (p->dbd_off < p->pbufsiz - sizeof(vki_nss_pheader_t)) {
9064 SizeT len = MIN(p->dbd_len, p->pbufsiz - p->dbd_off);
9065 POST_MEM_WRITE((Addr) ((HChar *) p + p->dbd_off), len);
9066 }
9067
9068 if (p->key_off < p->pbufsiz - sizeof(vki_nss_pheader_t)) {
9069 SizeT len = MIN(p->key_len, p->pbufsiz - p->key_off);
9070 POST_MEM_WRITE((Addr) ((HChar *) p + p->key_off), len);
9071 }
9072
9073 if (p->data_off < p->pbufsiz - sizeof(vki_nss_pheader_t)) {
9074 SizeT len = MIN(p->data_len, p->pbufsiz - p->data_off);
9075 POST_MEM_WRITE((Addr) ((HChar *) p + p->data_off), len);
9076 }
9077
9078 if (p->ext_off < p->pbufsiz - sizeof(vki_nss_pheader_t)) {
9079 SizeT len = MIN(p->ext_len, p->pbufsiz - p->ext_off);
9080 POST_MEM_WRITE((Addr) ((HChar *) p + p->ext_off), len);
9081 }
9082 }
9083 } else {
9084 /* response from parent nscd to a child nscd */
9085 VG_(unimplemented)("Door wrapper of child/parent nscd.");
9086 }
9087 }
9088 } else if (VG_STREQ(pathname, VKI_REPOSITORY_DOOR_NAME)) {
9089 POST_FIELD_WRITE(((vki_repository_door_response_t *) rbuf)->rdr_status);
9090 /* A new client door fd is passed over the global repository door. */
9091 if ((desc_ptr != NULL) && (desc_num > 0)) {
9092 if (desc_ptr[0].d_attributes & DOOR_DESCRIPTOR) {
9093 door_record_client(tid, desc_ptr[0].d_data.d_desc.d_descriptor,
9094 repository_door_pre_mem_door_call_hook,
9095 repository_door_post_mem_door_call_hook);
9096 }
9097 }
9098 } else {
9099 const OpenDoor *open_door = door_find_by_fd(fd);
9100 if ((open_door != NULL) && (open_door->post_mem_hook != NULL)) {
9101 open_door->post_mem_hook(tid, fd, rbuf, rsize);
9102 } else {
9103 /* generic default */
9104 POST_MEM_WRITE((Addr) rbuf, rsize);
9105 }
9106 }
9107}
9108
9109/* Pre-syscall checks for data_ptr contents in a door_return(). */
9110static void door_return_pre_mem_data(ThreadId tid, Addr server_procedure,
9111 void *data_ptr, SizeT data_size)
9112{
9113 if ((data_size == 0) || (server_procedure == 0)) {
9114 /* There is nothing to check. This usually happens during thread's
9115 first call to door_return(). */
9116 return;
9117 }
9118
9119 /* Get pathname of the door file descriptor based on the
9120 door server procedure (that's all we have).
9121 Needed to dissect door service on the pathname below. */
9122 const OpenDoor *open_door = door_find_by_proc(server_procedure);
9123 const HChar *pathname = (open_door != NULL) ? open_door->pathname : NULL;
9124 Int fd = (open_door != NULL) ? open_door->fd : -1;
9125
9126 /* Debug-only printing. */
9127 if (0) {
9128 VG_(printf)("PRE(door_return) with fd=%d and filename=%s "
9129 "(nr_doors_recorded=%u)\n",
9130 fd, pathname, nr_doors_recorded);
9131 }
9132
9133 if (VG_STREQ(pathname, VKI__PATH_KCFD_DOOR)) {
9134 vki_kcf_door_arg_t *p = (vki_kcf_door_arg_t *) data_ptr;
9135
9136 PRE_FIELD_READ("door_return(\"" VKI__PATH_KCFD_DOOR "\", "
9137 "kcf_door_arg_t->da_version)", p->da_version);
9138 PRE_FIELD_READ("door_return(\"" VKI__PATH_KCFD_DOOR "\", "
9139 "kcf_door_arg_t->da_u.result.status)",
9140 p->vki_da_u.result.status);
9141 PRE_MEM_READ("door_return(\"" VKI__PATH_KCFD_DOOR "\", "
9142 "kcf_door_arg_t->da_u.result.signature)",
9143 (Addr) p->vki_da_u.result.signature,
9144 p->vki_da_u.result.siglen);
9145 } else if (VG_STREQ(pathname, VKI_NAME_SERVICE_DOOR)) {
9146 vki_nss_pheader_t *p = (vki_nss_pheader_t *) data_ptr;
9147
9148 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9149 "nss_pheader->nsc_callnumber)", p->nsc_callnumber);
9150 if (ML_(safe_to_deref)(p, sizeof(vki_nss_pheader_t))) {
9151 if ((p->nsc_callnumber & VKI_NSCDV2CATMASK) == VKI_NSCD_CALLCAT_APP) {
9152 /* response from nscd to an application */
9153 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9154 "nss_pheader->p_status)", p->p_status);
9155 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9156 "nss_pheader->p_errno)", p->p_errno);
9157 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9158 "nss_pheader->p_herrno)", p->p_herrno);
9159 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9160 "nss_pheader->dbd_off)", p->dbd_off);
9161 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9162 "nss_pheader->dbd_len)", p->dbd_len);
9163 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9164 "nss_pheader->data_off)", p->data_off);
9165 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9166 "nss_pheader->data_len)", p->data_len);
9167 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9168 "nss_pheader->ext_off)", p->ext_off);
9169 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9170 "nss_pheader->ext_len)", p->ext_len);
9171 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9172 "nss_pheader->pbufsiz)", p->pbufsiz);
9173 PRE_MEM_WRITE("door_return(\"" VKI_NAME_SERVICE_DOOR "\", pbuf)",
9174 (Addr) p, p->pbufsiz);
9175 PRE_MEM_READ("door_return(\"" VKI_NAME_SERVICE_DOOR
9176 "\", nss->data)",
9177 (Addr) ((HChar *) p + p->data_off), p->data_len);
9178 PRE_MEM_READ("door_return(\"" VKI_NAME_SERVICE_DOOR
9179 "\", nss->ext)",
9180 (Addr) ((HChar *) p + p->ext_off), p->ext_len);
9181 } else {
9182 /* response from parent nscd to a child nscd */
9183 VG_(unimplemented)("Door wrapper of child/parent nscd.");
9184 }
9185 }
9186 } else if (VG_STREQ(pathname, VKI_REPOSITORY_DOOR_NAME)) {
9187 VG_(unimplemented)("Door wrapper of " VKI_REPOSITORY_DOOR_NAME);
9188 } else {
9189 if (SimHintiS(SimHint_lax_doors, VG_(clo_sim_hints))) {
9190 /*
9191 * Be very lax about door syscall handling over unrecognized
9192 * door file descriptors. Does not require that full buffer
9193 * is initialized when writing. Without this, programs using
9194 * libdoor(3LIB) functionality with completely proprietary
9195 * semantics may report large number of false positives.
9196 */
9197 } else {
9198 static Int moans = 3;
9199
9200 /* generic default */
9201 if (moans > 0 && !VG_(clo_xml)) {
9202 moans--;
9203 VG_(umsg)(
9204"Warning: noted and generically handled door return\n"
9205" on file descriptor %d (filename: %s).\n"
9206" This could cause spurious value errors to appear.\n"
9207" See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.\n"
9208" Alternatively you may find '--sim-hints=lax-doors' option useful.\n",
9209 fd, pathname);
9210 }
9211 PRE_MEM_READ("door_return(data_ptr)",
9212 (Addr) data_ptr, data_size);
9213 }
9214 }
9215}
9216
9217/* Post-syscall checks for data_ptr contents in a door_return(). */
9218static void door_return_post_mem_data(ThreadId tid, Addr server_procedure,
9219 void *data_ptr, SizeT data_size)
9220{
9221 const OpenDoor *open_door = door_find_by_proc(server_procedure);
9222 const HChar *pathname = (open_door != NULL) ? open_door->pathname : NULL;
9223
9224 /* Debug-only printing. */
9225 if (0) {
9226 Int fd = (open_door != NULL) ? open_door->fd : -1;
9227 VG_(printf)("POST(door_return) with fd=%d and filename=%s "
9228 "(nr_doors_recorded=%u)\n",
9229 fd, pathname, nr_doors_recorded);
9230 }
9231
9232 if (VG_STREQ(pathname, VKI__PATH_KCFD_DOOR)) {
9233 vki_kcf_door_arg_t *p = (vki_kcf_door_arg_t *) data_ptr;
9234
9235 POST_FIELD_WRITE(p->da_version);
9236 POST_FIELD_WRITE(p->da_iskernel);
9237 POST_MEM_WRITE((Addr) p->vki_da_u.filename,
9238 VG_(strlen)(p->vki_da_u.filename) + 1);
9239 } else if (VG_STREQ(pathname, VKI_NAME_SERVICE_DOOR)) {
9240 vki_nss_pheader_t *p = (vki_nss_pheader_t *) data_ptr;
9241
9242 POST_FIELD_WRITE(p->nsc_callnumber);
9243 if (ML_(safe_to_deref)(p, sizeof(vki_nss_pheader_t))) {
9244 if ((p->nsc_callnumber & VKI_NSCDV2CATMASK) == VKI_NSCD_CALLCAT_APP) {
9245 /* request from an application towards nscd */
9246 POST_FIELD_WRITE(p->p_version);
9247 POST_FIELD_WRITE(p->dbd_off);
9248 POST_FIELD_WRITE(p->dbd_len);
9249 POST_FIELD_WRITE(p->key_off);
9250 POST_FIELD_WRITE(p->key_len);
9251 POST_FIELD_WRITE(p->data_off);
9252 POST_FIELD_WRITE(p->data_len);
9253 POST_FIELD_WRITE(p->ext_off);
9254 POST_FIELD_WRITE(p->ext_len);
9255 POST_FIELD_WRITE(p->pbufsiz);
9256
9257 if (p->dbd_len > 0) {
9258 vki_nss_dbd_t *dbd
9259 = (vki_nss_dbd_t *) ((HChar *) p + p->dbd_off);
9260
9261 POST_MEM_WRITE((Addr) dbd, sizeof(vki_nss_dbd_t));
9262 if (ML_(safe_to_deref)(dbd, sizeof(vki_nss_dbd_t))) {
9263 SizeT headers_size = sizeof(vki_nss_pheader_t)
9264 + sizeof(vki_nss_dbd_t);
9265
9266 if (dbd->o_name != 0) {
9267 HChar *name = (HChar *) p + p->dbd_off + dbd->o_name;
9268 SizeT name_len = VG_(strlen)(name) + 1;
9269 if (name_len <= data_size - headers_size)
9270 POST_MEM_WRITE((Addr) name, name_len);
9271 }
9272 if (dbd->o_config_name != 0) {
9273 HChar *name = (HChar *) p + p->dbd_off + dbd->o_config_name;
9274 SizeT name_len = VG_(strlen)(name) + 1;
9275 if (name_len <= data_size - headers_size)
9276 POST_MEM_WRITE((Addr) name, name_len);
9277 }
9278 if (dbd->o_default_config != 0) {
9279 HChar *name = (HChar *) p + p->dbd_off
9280 + dbd->o_default_config;
9281 SizeT name_len = VG_(strlen)(name) + 1;
9282 if (name_len <= data_size - headers_size)
9283 POST_MEM_WRITE((Addr) name, name_len);
9284 }
9285 }
9286 }
9287
9288 if (p->key_len <= data_size - p->key_off)
9289 POST_MEM_WRITE((Addr) ((HChar *) p + p->key_off), p->key_len);
9290 } else {
9291 /* request from a child nscd towards parent nscd */
9292 VG_(unimplemented)("Door wrapper of child/parent nscd.");
9293 }
9294 }
9295 } else if (VG_STREQ(pathname, VKI_REPOSITORY_DOOR_NAME)) {
9296 VG_(unimplemented)("Door wrapper of " VKI_REPOSITORY_DOOR_NAME);
9297 } else {
9298 /* generic default */
9299 POST_MEM_WRITE((Addr) data_ptr, data_size);
9300 }
9301}
9302
9303PRE(sys_door)
9304{
9305 /* int doorfs(long arg1, long arg2, long arg3, long arg4, long arg5,
9306 long subcode); */
9307 ThreadState *tst = VG_(get_ThreadState)(tid);
9308 *flags |= SfMayBlock | SfPostOnFail;
9309
9310 PRINT("sys_door ( %#lx, %#lx, %#lx, %#lx, %#lx, %ld )", ARG1, ARG2, ARG3,
florianb26101c2015-08-08 21:45:33 +00009311 ARG4, ARG5, SARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00009312
9313 /* Macro PRE_REG_READ6 cannot be simply used because not all ARGs are used
9314 in door() syscall variants. Note that ARG6 (subcode) is used always. */
9315#define PRE_REG_READ_SIXTH_ONLY \
9316 if (VG_(tdict).track_pre_reg_read) { \
9317 PRA6("door", long, subcode); \
9318 }
9319
9320 switch (ARG6 /*subcode*/) {
9321 case VKI_DOOR_CREATE:
9322 PRE_REG_READ3(long, "door", long, arg1, long, arg2, long, arg3);
9323 PRE_REG_READ_SIXTH_ONLY;
9324 /* Note: the first argument to DOOR_CREATE is a server procedure.
9325 This could lead to a problem if the kernel tries to force the
9326 execution of this procedure, similarly to how signal handlers are
9327 executed. Fortunately, the kernel never does that (for user-space
9328 server procedures). The procedure is always executed by the standard
9329 library. */
9330 break;
9331 case VKI_DOOR_REVOKE:
9332 PRE_REG_READ1(long, "door", long, arg1);
9333 PRE_REG_READ_SIXTH_ONLY;
9334 if (!ML_(fd_allowed)(ARG1, "door_revoke", tid, False))
9335 SET_STATUS_Failure(VKI_EBADF);
9336 break;
9337 case VKI_DOOR_INFO:
9338 PRE_REG_READ2(long, "door", long, arg1, long, arg2);
9339 PRE_REG_READ_SIXTH_ONLY;
9340 PRE_MEM_WRITE("door_info(info)", ARG2, sizeof(vki_door_info_t));
9341 break;
9342 case VKI_DOOR_CALL:
9343 {
9344 PRE_REG_READ2(long, "door", long, arg1, long, arg2);
9345 PRE_REG_READ_SIXTH_ONLY;
9346
9347 Int rval = 0;
9348 vki_door_arg_t *params = (vki_door_arg_t*)ARG2;
9349
9350 if (!ML_(fd_allowed)(ARG1, "door_call", tid, False))
9351 rval = VKI_EBADF;
9352
9353 PRE_FIELD_READ("door_call(params->data_ptr)", params->data_ptr);
9354 PRE_FIELD_READ("door_call(params->data_size)", params->data_size);
9355 PRE_FIELD_READ("door_call(params->desc_ptr)", params->desc_ptr);
9356 PRE_FIELD_READ("door_call(params->desc_num)", params->desc_num);
9357 PRE_FIELD_READ("door_call(params->rbuf)", params->rbuf);
9358 PRE_FIELD_READ("door_call(params->rsize)", params->rsize);
9359
9360 if (ML_(safe_to_deref)(params, sizeof(*params))) {
9361 if (params->data_ptr)
9362 door_call_pre_mem_params_data(tid, ARG1, params->data_ptr,
9363 params->data_size);
9364
9365 if (params->desc_ptr) {
9366 SizeT desc_size = params->desc_num * sizeof(*params->desc_ptr);
9367 PRE_MEM_READ("door_call(params->desc_ptr)",
9368 (Addr)params->desc_ptr, desc_size);
9369
9370 /* Do not record information about closed fds if we are going
9371 to fail the syscall and so no fds will be closed. */
9372 if ((rval == 0) &&
9373 (ML_(safe_to_deref)(params->desc_ptr, desc_size))) {
9374 rval = pre_check_and_close_fds(tid, "door_call",
9375 params->desc_ptr,
9376 params->desc_num);
9377 }
9378 }
9379
9380 if (params->rbuf)
9381 PRE_MEM_WRITE("door_call(params->rbuf)", (Addr)params->rbuf,
9382 params->rsize);
9383 }
9384
9385 if (rval)
9386 SET_STATUS_Failure(rval);
9387 }
9388 break;
9389 case VKI_DOOR_BIND:
9390 PRE_REG_READ1(long, "door", long, arg1);
9391 PRE_REG_READ_SIXTH_ONLY;
9392 VG_(unimplemented)("DOOR_BIND");
9393 break;
9394 case VKI_DOOR_UNBIND:
9395 PRE_REG_READ0(long, "door");
9396 PRE_REG_READ_SIXTH_ONLY;
9397 VG_(unimplemented)("DOOR_UNBIND");
9398 break;
9399 case VKI_DOOR_UNREFSYS:
9400 PRE_REG_READ0(long, "door");
9401 PRE_REG_READ_SIXTH_ONLY;
9402 VG_(unimplemented)("DOOR_UNREFSYS");
9403 break;
9404 case VKI_DOOR_UCRED:
9405 PRE_REG_READ1(long, "door", long, arg1);
9406 PRE_REG_READ_SIXTH_ONLY;
9407 VG_(unimplemented)("DOOR_UCRED");
9408 break;
9409 case VKI_DOOR_RETURN:
9410 PRE_REG_READ6(long, "door", long, arg1, long, arg2, long, arg3,
9411 long, arg4, long, arg5, long, subcode);
9412
9413 /* Register %esp/%rsp is read and modified by the syscall. */
9414 VG_TRACK(pre_reg_read, Vg_CoreSysCall, tid, "door_return(sp)",
9415 VG_O_STACK_PTR, sizeof(UWord));
9416 /* Register %ebp/%rbp is not really read by the syscall, it is only
9417 written by it, but it is hard to determine when it is written so we
9418 make sure it is always valid prior to making the syscall. */
9419 VG_TRACK(pre_reg_read, Vg_CoreSysCall, tid, "door_return(bp)",
9420 VG_O_FRAME_PTR, sizeof(UWord));
9421
9422 door_return_pre_mem_data(tid, tst->os_state.door_return_procedure,
9423 (void *) ARG1, ARG2);
9424
9425 /* Do not tell the tool where the syscall is going to write the
9426 resulting data. It is necessary to skip this check because the data
9427 area starting at ARG4-ARG5 (of length ARG5) is usually on a client
9428 thread stack below the stack pointer and therefore it can be marked
9429 by a tool (for example, Memcheck) as inaccessible. It is ok to skip
9430 this check in this case because if there is something wrong with the
9431 data area then the syscall will fail or the error will be handled by
9432 POST_MEM_WRITE() in the post wrapper. */
9433 /*PRE_MEM_WRITE("door_return(sp)", ARG4 - ARG5, ARG5);*/
9434
9435 if (ARG3) {
9436 vki_door_return_desc_t *desc_env = (vki_door_return_desc_t*)ARG3;
9437
9438 PRE_MEM_READ("door_return(desc_env)", ARG3,
9439 sizeof(vki_door_return_desc_t));
9440
9441 if (ML_(safe_to_deref)(desc_env, sizeof(*desc_env)) &&
9442 desc_env->desc_ptr) {
9443 Int rval;
9444
9445 PRE_MEM_READ("door_return(desc_env->desc_ptr)",
9446 (Addr)desc_env->desc_ptr,
9447 desc_env->desc_num * sizeof(*desc_env->desc_ptr));
9448
9449 rval = pre_check_and_close_fds(tid, "door_return",
9450 desc_env->desc_ptr,
9451 desc_env->desc_num);
9452 if (rval)
9453 SET_STATUS_Failure(rval);
9454 }
9455 }
9456 tst->os_state.in_door_return = True;
9457 tst->os_state.door_return_procedure = 0;
9458 break;
9459 case VKI_DOOR_GETPARAM:
9460 PRE_REG_READ3(long, "door", long, arg1, long, arg2, long, arg3);
9461 PRE_REG_READ_SIXTH_ONLY;
9462 VG_(unimplemented)("DOOR_GETPARAM");
9463 break;
9464 case VKI_DOOR_SETPARAM:
9465 PRE_REG_READ3(long, "door", long, arg1, long, arg2, long, arg3);
9466 PRE_REG_READ_SIXTH_ONLY;
Elliott Hughesa0664b92017-04-18 17:46:52 -07009467 if (!ML_(fd_allowed)(ARG1, "door_setparam", tid, False))
9468 SET_STATUS_Failure(VKI_EBADF);
sewardj8eb8bab2015-07-21 14:44:28 +00009469 break;
9470 default:
florianb26101c2015-08-08 21:45:33 +00009471 VG_(unimplemented)("Syswrap of the door call with subcode %ld.", SARG6);
sewardj8eb8bab2015-07-21 14:44:28 +00009472 /*NOTREACHED*/
9473 break;
9474 }
9475
9476#undef PRE_REG_READ_SIXTH_ONLY
9477}
9478
9479POST(sys_door)
9480{
9481 ThreadState *tst = VG_(get_ThreadState)(tid);
9482
9483 vg_assert(SUCCESS || FAILURE);
9484
9485 /* Alter the tst->os_state.in_door_return flag. */
9486 if (ARG6 == VKI_DOOR_RETURN) {
9487 vg_assert(tst->os_state.in_door_return == True);
9488 tst->os_state.in_door_return = False;
9489
9490 /* Inform the tool that %esp/%rsp and %ebp/%rbp were (potentially)
9491 modified. */
9492 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, VG_O_STACK_PTR,
9493 sizeof(UWord));
9494 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, VG_O_FRAME_PTR,
9495 sizeof(UWord));
9496 }
9497 else
9498 vg_assert(tst->os_state.in_door_return == False);
9499
9500 if (FAILURE) {
9501 if (VG_(clo_track_fds)) {
9502 /* See the discussion in pre_check_and_close_fds() to understand this
9503 part. */
9504 Bool loss = False;
9505 switch (ARG6 /*subcode*/) {
9506 case VKI_DOOR_CALL:
9507 if (ERR == VKI_EFAULT || ERR == VKI_EBADF)
9508 loss = True;
9509 break;
9510 case VKI_DOOR_RETURN:
9511 if (ERR == VKI_EFAULT || ERR == VKI_EINVAL)
9512 loss = True;
9513 break;
9514 default:
9515 break;
9516 }
9517 if (loss)
9518 VG_(message)(Vg_UserMsg, "The door call failed with an "
9519 "unexpected error and information "
9520 "about open file descriptors can be "
9521 "now imprecise.\n");
9522 }
9523
9524 return;
9525 }
9526
9527 vg_assert(SUCCESS);
9528
9529 switch (ARG6 /*subcode*/) {
9530 case VKI_DOOR_CREATE:
9531 door_record_server(tid, ARG1, RES);
9532 break;
9533 case VKI_DOOR_REVOKE:
Elliott Hughesa0664b92017-04-18 17:46:52 -07009534 door_record_revoke(tid, ARG1);
sewardj8eb8bab2015-07-21 14:44:28 +00009535 if (VG_(clo_track_fds))
9536 ML_(record_fd_close)(ARG1);
9537 break;
9538 case VKI_DOOR_INFO:
9539 POST_MEM_WRITE(ARG2, sizeof(vki_door_info_t));
9540 break;
9541 case VKI_DOOR_CALL:
9542 {
9543 /* Note that all returned values are stored in the rbuf, i.e.
9544 data_ptr and desc_ptr points into this buffer. */
9545 vki_door_arg_t *params = (vki_door_arg_t*)ARG2;
9546
9547 if (params->rbuf) {
9548 Addr addr = (Addr)params->rbuf;
Elliott Hughesa0664b92017-04-18 17:46:52 -07009549 if (!VG_(am_find_anon_segment)(addr)) {
sewardj8eb8bab2015-07-21 14:44:28 +00009550 /* This segment is new and was mapped by the kernel. */
9551 UInt prot, flags;
9552 SizeT size;
9553
9554 prot = VKI_PROT_READ | VKI_PROT_WRITE | VKI_PROT_EXEC;
9555 flags = VKI_MAP_ANONYMOUS;
9556 size = VG_PGROUNDUP(params->rsize);
9557
9558 VG_(debugLog)(1, "syswrap-solaris", "POST(sys_door), "
9559 "new segment: vaddr=%#lx, size=%#lx, "
9560 "prot=%#x, flags=%#x, fd=%ld, offset=%#llx\n",
9561 addr, size, prot, flags, (UWord)-1, (ULong)0);
9562
9563 ML_(notify_core_and_tool_of_mmap)(addr, size, prot, flags,
9564 -1, 0);
9565
9566 /* Note: We don't notify the debuginfo reader about this
Elliott Hughesa0664b92017-04-18 17:46:52 -07009567 mapping because there is no debug information stored in
sewardj8eb8bab2015-07-21 14:44:28 +00009568 this segment. */
9569 }
9570
9571 door_call_post_mem_params_rbuf(tid, ARG1, (void *) addr,
9572 params->rsize, params->desc_ptr,
9573 params->desc_num);
9574 }
9575
9576 if (params->desc_ptr) {
9577 POST_MEM_WRITE((Addr)params->desc_ptr,
9578 params->desc_num * sizeof(vki_door_desc_t));
9579 post_record_fds(tid, "door_call", params->desc_ptr,
9580 params->desc_num);
9581 }
9582 }
9583 break;
9584 case VKI_DOOR_BIND:
9585 break;
9586 case VKI_DOOR_UNBIND:
9587 break;
9588 case VKI_DOOR_UNREFSYS:
9589 break;
9590 case VKI_DOOR_UCRED:
9591 break;
9592 case VKI_DOOR_RETURN:
9593 {
9594 struct vki_door_results *results
9595 = (struct vki_door_results*)VG_(get_SP)(tid);
9596
9597 tst->os_state.door_return_procedure = (Addr)results->pc;
9598
9599 POST_MEM_WRITE((Addr)results, sizeof(*results));
9600 if (results->data_ptr)
9601 door_return_post_mem_data(tid,
9602 tst->os_state.door_return_procedure,
9603 results->data_ptr,
9604 results->data_size);
9605 if (results->desc_ptr) {
9606 POST_MEM_WRITE((Addr)results->desc_ptr,
9607 results->desc_num * sizeof(vki_door_desc_t));
9608 post_record_fds(tid, "door_return", results->desc_ptr,
9609 results->desc_num);
9610 }
9611
9612 POST_MEM_WRITE((Addr)results->door_info,
9613 sizeof(*results->door_info));
9614 }
9615 break;
9616 case VKI_DOOR_GETPARAM:
9617 break;
9618 case VKI_DOOR_SETPARAM:
9619 break;
9620 default:
9621 vg_assert(0);
9622 break;
9623 }
9624}
9625
9626PRE(sys_schedctl)
9627{
9628 /* caddr_t schedctl(void); */
9629 /* This syscall returns an address that points to struct sc_shared.
9630 This per-thread structure is used as an interface between the libc and
9631 the kernel. */
9632 PRINT("sys_schedctl ( )");
9633 PRE_REG_READ0(long, "schedctl");
9634}
9635
9636POST(sys_schedctl)
9637{
9638 Addr a = RES;
9639 ThreadState *tst = VG_(get_ThreadState)(tid);
9640
9641 /* Stay sane. */
9642 vg_assert((tst->os_state.schedctl_data == 0) ||
9643 (tst->os_state.schedctl_data == a));
9644 tst->os_state.schedctl_data = a;
9645
9646 /* Returned address points to a block in a mapped page. */
Elliott Hughesa0664b92017-04-18 17:46:52 -07009647 if (!VG_(am_find_anon_segment)(a)) {
sewardj8eb8bab2015-07-21 14:44:28 +00009648 Addr page = VG_PGROUNDDN(a);
Elliott Hughesa0664b92017-04-18 17:46:52 -07009649 UInt prot = VKI_PROT_READ | VKI_PROT_WRITE;
9650# if defined(SOLARIS_SCHEDCTL_PAGE_EXEC)
9651 prot |= VKI_PROT_EXEC;
9652# endif /* SOLARIS_SCHEDCTL_PAGE_EXEC */
sewardj8eb8bab2015-07-21 14:44:28 +00009653 UInt flags = VKI_MAP_ANONYMOUS;
9654 /* The kernel always allocates one page for the sc_shared struct. */
9655 SizeT size = VKI_PAGE_SIZE;
9656
9657 VG_(debugLog)(1, "syswrap-solaris", "POST(sys_schedctl), new segment: "
9658 "vaddr=%#lx, size=%#lx, prot=%#x, flags=%#x, fd=-1, "
9659 "offset=0\n", page, size, prot, flags);
9660
9661 /* The kernel always places redzone before and after the allocated page.
9662 Check this assertion now; the tool can later request to allocate
9663 a Valgrind segment and aspacemgr will place it adjacent. */
Elliott Hughesa0664b92017-04-18 17:46:52 -07009664 const NSegment *seg = VG_(am_find_nsegment)(page - 1);
sewardj8eb8bab2015-07-21 14:44:28 +00009665 vg_assert(seg == NULL || seg->kind == SkResvn);
Elliott Hughesa0664b92017-04-18 17:46:52 -07009666 seg = VG_(am_find_nsegment)(page + VKI_PAGE_SIZE);
sewardj8eb8bab2015-07-21 14:44:28 +00009667 vg_assert(seg == NULL || seg->kind == SkResvn);
9668
9669 /* The address space manager works with whole pages. */
9670 VG_(am_notify_client_mmap)(page, size, prot, flags, -1, 0);
9671
9672 /* Note: It isn't needed to notify debuginfo about the new mapping
9673 because it's only an anonymous mapping. */
9674 /* Note: schedctl data are cleaned in two places:
9675 - for the tool when the thread exits
9676 - for the core in child's post-fork handler clean_schedctl_data(). */
9677 }
9678
9679 /* The tool needs per-thread granularity, not whole pages. */
9680 VG_TRACK(new_mem_mmap, a, sizeof(struct vki_sc_shared), True, True, True, 0);
9681 POST_MEM_WRITE(a, sizeof(struct vki_sc_shared));
9682}
9683
iraisr7d4aa192015-10-12 19:10:42 +00009684PRE(sys_pset)
9685{
9686 /* Kernel: int pset(int subcode, long arg1, long arg2, long arg3,
9687 long arg4); */
9688 switch (ARG1 /* subcode */) {
9689 case VKI_PSET_CREATE:
9690 /* Libc: int pset_create(psetid_t *newpset); */
9691 PRINT("sys_pset ( %ld, %#lx )", SARG1, ARG2);
9692 PRE_REG_READ2(long, SC2("pset", "create"), int, subcode,
9693 vki_psetid_t *, newpset);
9694 PRE_MEM_WRITE("pset(newpset)", ARG2, sizeof(vki_psetid_t));
9695 break;
9696 case VKI_PSET_DESTROY:
9697 /* Libc: int pset_destroy(psetid_t pset); */
9698 PRINT("sys_pset ( %ld, %ld )", SARG1, SARG2);
9699 PRE_REG_READ2(long, SC2("pset", "destroy"), int, subcode,
9700 vki_psetid_t, pset);
9701 break;
9702 case VKI_PSET_ASSIGN:
9703 /* Libc: int pset_assign(psetid_t pset, processorid_t cpu,
9704 psetid_t *opset); */
9705 PRINT("sys_pset ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
9706 PRE_REG_READ4(long, SC2("pset", "assign"), int, subcode,
9707 vki_psetid_t, pset, vki_processorid_t, cpu,
9708 vki_psetid_t *, opset);
9709 if (ARG4 != 0)
9710 PRE_MEM_WRITE("pset(opset)", ARG4, sizeof(vki_psetid_t));
9711 break;
9712 case VKI_PSET_INFO:
9713 /* Libc: int pset_info(psetid_t pset, int *type, uint_t *numcpus,
9714 processorid_t *cpulist); */
9715 PRINT("sys_pset ( %ld, %ld, %#lx, %#lx, %#lx )", SARG1, SARG2, ARG3,
9716 ARG4, ARG5);
9717 PRE_REG_READ5(long, SC2("pset", "info"), int, subcode, vki_psetid_t, pset,
9718 int *, type, vki_uint_t *, numcpus,
9719 vki_processorid_t *, cpulist);
9720 if (ARG3 != 0)
9721 PRE_MEM_WRITE("pset(type)", ARG3, sizeof(int));
9722 if (ARG4 != 0)
9723 PRE_MEM_WRITE("pset(numcpus)", ARG4, sizeof(vki_uint_t));
9724 if ((ARG4 != 0) && (ARG5 != 0)) {
9725 vki_uint_t *numcpus = (vki_uint_t *) ARG4;
9726 if (ML_(safe_to_deref(numcpus, sizeof(vki_uint_t)))) {
9727 PRE_MEM_WRITE("pset(cpulist)", ARG5,
9728 *numcpus * sizeof(vki_processorid_t));
9729 /* If cpulist buffer is not large enough, it will hold only as many
9730 entries as fit in the buffer. However numcpus will contain the
9731 real number of cpus which will be greater than originally passed
9732 in. Stash the original value in unused ARG6. */
9733 ARG6 = *numcpus;
9734 }
9735 }
9736 break;
9737 case VKI_PSET_BIND:
9738 /* Libc: int pset_bind(psetid_t pset, idtype_t idtype, id_t id,
9739 psetid_t *opset); */
9740 PRINT("sys_pset ( %ld, %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3,
9741 SARG4, ARG5);
9742 PRE_REG_READ5(long, SC2("pset", "bind"), int, subcode, vki_psetid_t, pset,
9743 vki_idtype_t, idtype, vki_id_t, id, vki_psetid_t *, opset);
9744 if (ARG5 != 0)
9745 PRE_MEM_WRITE("pset(opset)", ARG5, sizeof(vki_psetid_t));
9746 break;
9747 case VKI_PSET_BIND_LWP:
9748 /* Libc: int pset_bind_lwp(psetid_t pset, id_t id, pid_t pid,
9749 psetid_t *opset); */
9750 PRINT("sys_pset ( %ld, %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3,
9751 SARG4, ARG5);
9752 PRE_REG_READ5(long, SC2("pset", "bind_lwp"), int, subcode,
9753 vki_psetid_t, pset, vki_id_t, id, vki_pid_t, pid,
9754 vki_psetid_t *, opset);
9755 if (ARG5 != 0)
9756 PRE_MEM_WRITE("pset(opset)", ARG5, sizeof(vki_psetid_t));
9757 break;
9758 case VKI_PSET_GETLOADAVG:
9759 /* Libc: int pset_getloadavg(psetid_t pset, double loadavg[],
9760 int nelem); */
9761 PRINT("sys_pset ( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
9762 PRE_REG_READ4(long, SC2("pset", "getloadavg"), int, subcode,
Elliott Hughesa0664b92017-04-18 17:46:52 -07009763 vki_psetid_t, pset, int *, buf, int, nelem);
iraisr7d4aa192015-10-12 19:10:42 +00009764 if (ARG3 != 0)
Elliott Hughesa0664b92017-04-18 17:46:52 -07009765 PRE_MEM_WRITE("pset(buf)", ARG3, SARG4 * sizeof(int));
iraisr7d4aa192015-10-12 19:10:42 +00009766 break;
9767 case VKI_PSET_LIST:
9768 /* Libc: int pset_list(psetid_t *psetlist, uint_t *numpsets); */
9769 PRINT("sys_pset ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
9770 PRE_REG_READ3(long, SC2("pset", "list"), int, subcode,
9771 vki_psetid_t *, psetlist, vki_uint_t *, numpsets);
9772 if (ARG3 != 0)
9773 PRE_MEM_WRITE("pset(numpsets)", ARG3, sizeof(vki_uint_t));
9774 if ((ARG2 != 0) && (ARG3 != 0)) {
9775 vki_uint_t *numpsets = (vki_uint_t *) ARG3;
9776 if (ML_(safe_to_deref(numpsets, sizeof(vki_uint_t)))) {
9777 PRE_MEM_WRITE("pset(psetlist)", ARG2,
9778 *numpsets * sizeof(vki_psetid_t));
9779 /* If psetlist buffer is not large enough, it will hold only as many
9780 entries as fit in the buffer. However numpsets will contain the
9781 real number of processor sets which will be greater than
9782 originally passed in. Stash the original value in unused ARG6. */
9783 ARG6 = *numpsets;
9784 }
9785 }
9786 break;
9787# if defined(SOLARIS_PSET_GET_NAME)
9788 case VKI_PSET_GET_NAME:
9789 /* Libc: int pset_get_name(psetid_t psetid, char *buf, uint_t len); */
9790 PRINT("sys_pset ( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
9791 PRE_REG_READ4(long, SC2("pset", "get_name"), int, subcode,
9792 vki_psetid_t, pset, char *, buf, vki_uint_t, len);
9793 PRE_MEM_WRITE("pset(buf)", ARG3, ARG4);
9794 break;
9795# endif /* SOLARIS_PSET_GET_NAME */
9796 case VKI_PSET_SETATTR:
9797 /* Libc: int pset_setattr(psetid_t pset, uint_t attr); */
9798 PRINT("sys_pset ( %ld, %ld, %ld )", SARG1, SARG2, ARG3);
9799 PRE_REG_READ3(long, SC2("pset", "setattr"), int, subcode,
9800 vki_psetid_t, pset, vki_uint_t, attr);
9801 break;
9802 case VKI_PSET_GETATTR:
9803 /* Libc: int pset_getattr(psetid_t pset, uint_t *attr); */
9804 PRINT("sys_pset ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
9805 PRE_REG_READ3(long, SC2("pset", "getattr"), int, subcode,
9806 vki_psetid_t, pset, vki_uint_t *, attr);
9807 PRE_MEM_WRITE("pset(attr)", ARG3, sizeof(vki_uint_t));
9808 break;
9809 case VKI_PSET_ASSIGN_FORCED:
9810 /* Libc: int pset_assign_forced(psetid_t pset, processorid_t cpu,
9811 psetid_t *opset); */
9812 PRINT("sys_pset ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
9813 PRE_REG_READ4(long, SC2("pset", "assign_forced"), int, subcode,
9814 vki_psetid_t, pset, vki_processorid_t, cpu,
9815 vki_psetid_t *, opset);
9816 if (ARG4 != 0)
9817 PRE_MEM_WRITE("pset(opset)", ARG4, sizeof(vki_psetid_t));
9818 break;
9819 default:
9820 VG_(unimplemented)("Syswrap of pset syscall with subcode %ld.", SARG1);
9821 /*NOTREACHED*/
9822 break;
9823 }
9824}
9825
9826POST(sys_pset)
9827{
9828 switch (ARG1 /*subcode*/) {
9829 case VKI_PSET_CREATE:
9830 POST_MEM_WRITE(ARG2, sizeof(vki_psetid_t));
9831 break;
9832 case VKI_PSET_DESTROY:
9833 break;
9834 case VKI_PSET_ASSIGN:
9835 if (ARG4 != 0)
9836 POST_MEM_WRITE(ARG4, sizeof(vki_psetid_t));
9837 break;
9838 case VKI_PSET_INFO:
9839 if (ARG3 != 0)
9840 POST_MEM_WRITE(ARG3, sizeof(int));
9841 if (ARG4 != 0)
9842 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
9843 if ((ARG4 != 0) && (ARG5 != 0)) {
9844 vki_uint_t *numcpus = (vki_uint_t *) ARG4;
9845 POST_MEM_WRITE(ARG5, MIN(*numcpus, ARG6) * sizeof(vki_processorid_t));
9846 }
9847 break;
9848 case VKI_PSET_BIND:
9849 if (ARG5 != 0)
9850 POST_MEM_WRITE(ARG5, sizeof(vki_psetid_t));
9851 break;
9852 case VKI_PSET_BIND_LWP:
9853 if (ARG5 != 0)
9854 POST_MEM_WRITE(ARG5, sizeof(vki_psetid_t));
9855 break;
9856 case VKI_PSET_GETLOADAVG:
9857 if (ARG3 != 0)
Elliott Hughesa0664b92017-04-18 17:46:52 -07009858 POST_MEM_WRITE(ARG3, MIN(SARG4, VKI_LOADAVG_NSTATS) * sizeof(int));
iraisr7d4aa192015-10-12 19:10:42 +00009859 break;
9860 case VKI_PSET_LIST:
9861 if (ARG3 != 0)
9862 POST_MEM_WRITE(ARG3, sizeof(vki_uint_t));
9863 if ((ARG2 != 0) && (ARG3 != 0)) {
9864 vki_uint_t *numpsets = (vki_uint_t *) ARG3;
9865 POST_MEM_WRITE(ARG2, MIN(*numpsets, ARG6) * sizeof(vki_psetid_t));
9866 }
9867 break;
9868# if defined(SOLARIS_PSET_GET_NAME)
9869 case VKI_PSET_GET_NAME:
9870 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
9871 break;
9872# endif /* SOLARIS_PSET_GET_NAME */
9873 case VKI_PSET_SETATTR:
9874 break;
9875 case VKI_PSET_GETATTR:
9876 POST_MEM_WRITE(ARG3, sizeof(vki_uint_t));
9877 break;
9878 case VKI_PSET_ASSIGN_FORCED:
9879 if (ARG4 != 0)
9880 POST_MEM_WRITE(ARG4, sizeof(vki_psetid_t));
9881 break;
9882 default:
9883 vg_assert(0);
9884 break;
9885 }
9886}
9887
sewardj8eb8bab2015-07-21 14:44:28 +00009888PRE(sys_resolvepath)
9889{
9890 /* int resolvepath(const char *path, char *buf, size_t bufsiz); */
9891 PRINT("sys_resolvepath ( %#lx(%s), %#lx, %lu )", ARG1, (HChar *) ARG1, ARG2,
9892 ARG3);
9893 PRE_REG_READ3(long, "resolvepath", const char *, path, char *, buf,
9894 vki_size_t, bufsiz);
9895
9896 PRE_MEM_RASCIIZ("resolvepath(path)", ARG1);
9897 PRE_MEM_WRITE("resolvepath(buf)", ARG2, ARG3);
9898}
9899
9900POST(sys_resolvepath)
9901{
9902 POST_MEM_WRITE(ARG2, RES);
9903}
9904
9905PRE(sys_lwp_mutex_timedlock)
9906{
9907 /* int lwp_mutex_timedlock(lwp_mutex_t *lp, timespec_t *tsp,
9908 uintptr_t owner); */
9909 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t *)ARG1;
9910 *flags |= SfMayBlock;
9911 PRINT("lwp_mutex_timedlock ( %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3);
9912 PRE_REG_READ3(long, "lwp_mutex_timedlock", lwp_mutex_t *, lp,
9913 timespec_t *, tsp, uintptr_t, owner);
9914
9915 PRE_FIELD_READ("lwp_mutex_timedlock(lp->mutex_flag)", lp->vki_mutex_flag);
9916 PRE_FIELD_READ("lwp_mutex_timedlock(lp->mutex_type)", lp->vki_mutex_type);
9917 PRE_FIELD_WRITE("lwp_mutex_timedlock(lp->mutex_owner)",
9918 lp->vki_mutex_owner);
9919 PRE_FIELD_WRITE("lwp_mutex_timedlock(lp->mutex_ownerpid)",
9920 lp->vki_mutex_ownerpid);
9921 PRE_FIELD_READ("lwp_mutex_timedlock(lp->mutex_lockw)", lp->vki_mutex_lockw);
9922 /*PRE_FIELD_WRITE("lwp_mutex_timedlock(lp->mutex_lockw)",
9923 lp->vki_mutex_lockw);*/
9924 PRE_FIELD_READ("lwp_mutex_timedlock(lp->mutex_waiters)",
9925 lp->vki_mutex_waiters);
9926 /*PRE_FIELD_WRITE("lwp_mutex_timedlock(lp->mutex_waiters)",
9927 lp->vki_mutex_waiters);*/
9928 if (ARG2) {
9929 PRE_MEM_READ("lwp_mutex_timedlock(tsp)", ARG2, sizeof(vki_timespec_t));
9930 /*PRE_MEM_WRITE("lwp_mutex_timedlock(tsp)", ARG2,
9931 sizeof(vki_timespec_t));*/
9932 }
9933}
9934
9935POST(sys_lwp_mutex_timedlock)
9936{
9937 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t *)ARG1;
9938 POST_FIELD_WRITE(lp->vki_mutex_owner);
9939 POST_FIELD_WRITE(lp->vki_mutex_ownerpid);
9940 POST_FIELD_WRITE(lp->vki_mutex_lockw);
9941 POST_FIELD_WRITE(lp->vki_mutex_waiters);
9942 if (ARG2)
9943 POST_MEM_WRITE(ARG2, sizeof(vki_timespec_t));
9944}
9945
9946PRE(sys_lwp_rwlock_sys)
9947{
9948 /* int lwp_rwlock_sys(int subcode, lwp_rwlock_t *rwlp, timespec_t *tsp); */
9949 vki_lwp_rwlock_t *rwlp = (vki_lwp_rwlock_t *)ARG2;
9950 switch (ARG1 /*subcode*/) {
9951 case 0:
9952 case 1:
9953 case 2:
9954 case 3:
9955 *flags |= SfMayBlock;
9956 switch (ARG1 /*subcode*/) {
9957 case 0:
florianb26101c2015-08-08 21:45:33 +00009958 PRINT("sys_lwp_rwlock ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00009959 PRE_REG_READ3(long, SC2("lwp_rwlock", "rdlock"), int, subcode,
9960 lwp_rwlock_t *, rwlp, timespec_t *, tsp);
9961 break;
9962 case 1:
florianb26101c2015-08-08 21:45:33 +00009963 PRINT("sys_lwp_rwlock ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +00009964 PRE_REG_READ3(long, SC2("lwp_rwlock", "wrlock"), int, subcode,
9965 lwp_rwlock_t *, rwlp, timespec_t *, tsp);
9966 break;
9967 case 2:
florianb26101c2015-08-08 21:45:33 +00009968 PRINT("sys_lwp_rwlock ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00009969 PRE_REG_READ2(long, SC2("lwp_rwlock", "tryrdlock"), int, subcode,
9970 lwp_rwlock_t *, rwlp);
9971 break;
9972 case 3:
florianb26101c2015-08-08 21:45:33 +00009973 PRINT("sys_lwp_rwlock ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00009974 PRE_REG_READ2(long, SC2("lwp_rwlock", "trywrlock"), int, subcode,
9975 lwp_rwlock_t *, rwlp);
9976 break;
9977 default:
9978 vg_assert(0);
9979 break;
9980 }
9981
9982 PRE_FIELD_READ("lwp_rwlock(rwlp->rwlock_type)", rwlp->vki_rwlock_type);
9983 PRE_FIELD_READ("lwp_rwlock(rwlp->rwlock_readers)",
9984 rwlp->vki_rwlock_readers);
9985 /*PRE_FIELD_WRITE("lwp_rwlock(rwlp->rwlock_readers)",
9986 rwlp->vki_rwlock_readers);*/
9987
9988 PRE_FIELD_READ("lwp_rwlock(rwlp->mutex.mutex_type)",
9989 rwlp->mutex.vki_mutex_type);
9990 PRE_FIELD_WRITE("lwp_rwlock(rwlp->mutex.mutex_owner)",
9991 rwlp->mutex.vki_mutex_owner);
9992 PRE_FIELD_WRITE("lwp_rwlock(rwlp->mutex.mutex_ownerpid)",
9993 rwlp->mutex.vki_mutex_ownerpid);
9994 /* The mutex_lockw member is not really read by the kernel for this
9995 syscall but it seems better to mark it that way because when locking
9996 an rwlock the associated mutex has to be locked. */
9997 PRE_FIELD_READ("lwp_rwlock(rwlp->mutex.mutex_lockw)",
9998 rwlp->mutex.vki_mutex_lockw);
9999 /*PRE_FIELD_WRITE("lwp_rwlock(rwlp->mutex.mutex_lockw)",
10000 rwlp->mutex.vki_mutex_lockw);*/
10001 PRE_FIELD_READ("lwp_rwlock(rwlp->mutex.mutex_waiters)",
10002 rwlp->mutex.vki_mutex_waiters);
10003 /*PRE_FIELD_WRITE("lwp_rwlock(rwlp->mutex.mutex_waiters)",
10004 rwlp->mutex.vki_mutex_waiters);*/
10005
10006 if ((ARG1 == 0 || ARG1 == 1) && ARG3)
10007 PRE_MEM_READ("lwp_rwlock(tsp)", ARG3, sizeof(vki_timespec_t));
10008 break;
10009 case 4:
florianb26101c2015-08-08 21:45:33 +000010010 PRINT("sys_lwp_rwlock( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +000010011 PRE_REG_READ2(long, SC2("lwp_rwlock", "unlock"), int, subcode,
10012 lwp_rwlock_t *, rwlp);
10013 PRE_FIELD_READ("lwp_rwlock(rwlp->mutex.mutex_type)",
10014 rwlp->mutex.vki_mutex_type);
10015 PRE_FIELD_READ("lwp_rwlock(rwlp->rwlock_readers)",
10016 rwlp->vki_rwlock_readers);
10017 /*PRE_FIELD_WRITE("lwp_rwlock(rwlp->rwlock_readers)",
10018 rwlp->vki_rwlock_readers);*/
10019 break;
10020 default:
10021 VG_(unimplemented)("Syswrap of the lwp_rwlock_sys call with subcode %ld.",
florianb26101c2015-08-08 21:45:33 +000010022 SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +000010023 /*NOTREACHED*/
10024 break;
10025 }
10026}
10027
10028POST(sys_lwp_rwlock_sys)
10029{
10030 vki_lwp_rwlock_t *rwlp = (vki_lwp_rwlock_t *)ARG2;
10031 switch (ARG1 /*subcode*/) {
10032 case 0:
10033 case 1:
10034 case 2:
10035 case 3:
10036 POST_FIELD_WRITE(rwlp->vki_rwlock_readers);
10037 POST_FIELD_WRITE(rwlp->vki_rwlock_owner);
10038 POST_FIELD_WRITE(rwlp->vki_rwlock_ownerpid);
10039 POST_FIELD_WRITE(rwlp->mutex.vki_mutex_lockw);
10040 POST_FIELD_WRITE(rwlp->mutex.vki_mutex_waiters);
10041 break;
10042 case 4:
10043 POST_FIELD_WRITE(rwlp->vki_rwlock_readers);
10044 break;
10045 default:
10046 vg_assert(0);
10047 break;
10048 }
10049}
10050
10051PRE(sys_lwp_sema_timedwait)
10052{
10053 /* int lwp_sema_timedwait(lwp_sema_t *sema, timespec_t *timeout,
10054 int check_park); */
10055 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
10056 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010057 PRINT("sys_lwp_sema_timewait ( %#lx, %#lx, %ld )", ARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010058 PRE_REG_READ3(long, "lwp_sema_timedwait", lwp_sema_t *, sema,
10059 timespec_t *, timeout, int, check_park);
10060
10061 PRE_FIELD_READ("lwp_sema_timedwait(sema->type)", sema->vki_sema_type);
10062 PRE_FIELD_READ("lwp_sema_timedwait(sema->count)", sema->vki_sema_count);
10063 /*PRE_FIELD_WRITE("lwp_sema_timedwait(sema->count)",
10064 sema->vki_sema_count);*/
10065 PRE_FIELD_READ("lwp_sema_timedwait(sema->waiters)", sema->vki_sema_waiters);
10066 /*PRE_FIELD_WRITE("lwp_sema_timedwait(sema->waiters)",
10067 sema->vki_sema_waiters);*/
10068 if (ARG2) {
10069 PRE_MEM_READ("lwp_sema_timedwait(timeout)", ARG2,
10070 sizeof(vki_timespec_t));
10071 /*PRE_MEM_WRITE("lwp_sema_timedwait(timeout)", ARG2,
10072 sizeof(vki_timespec_t));*/
10073 }
10074}
10075
10076POST(sys_lwp_sema_timedwait)
10077{
10078 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
10079 POST_FIELD_WRITE(sema->vki_sema_count);
10080 POST_FIELD_WRITE(sema->vki_sema_waiters);
10081 if (ARG2)
10082 POST_MEM_WRITE(ARG2, sizeof(vki_timespec_t));
10083}
10084
10085PRE(sys_zone)
10086{
10087 /* Kernel: long zone(int cmd, void *arg1, void *arg2, void *arg3,
10088 void *arg4);
10089 */
10090 switch (ARG1 /*cmd*/) {
10091 case VKI_ZONE_CREATE:
10092 /* Libc: zoneid_t zone_create(const char *name, const char *root,
10093 const struct priv_set *privs,
10094 const char *rctls, size_t rctlsz,
10095 const char *zfs, size_t zfssz,
10096 int *extended_error, int match,
10097 int doi, const bslabel_t *label,
10098 int flags);
10099 Kernel: zoneid_t zone_create(zone_def *zd);
10100 */
florianb26101c2015-08-08 21:45:33 +000010101 PRINT("sys_zone ( %ld, %#lx )", SARG1, ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +000010102 PRE_REG_READ2(long, SC2("zone", "create"), int, cmd,
10103 vki_zone_def *, zd);
10104
10105 vki_zone_def *zd = (vki_zone_def *) ARG2;
10106 PRE_FIELD_READ("zone(zd.zone_name)", zd->zone_name);
10107 PRE_FIELD_READ("zone(zd.zone_root)", zd->zone_root);
10108 PRE_FIELD_READ("zone(zd.zone_privs)", zd->zone_privs);
10109 PRE_FIELD_READ("zone(zd.zone_privssz)", zd->zone_privssz);
10110 PRE_FIELD_READ("zone(zd.rctlbuf)", zd->rctlbuf);
10111 PRE_FIELD_READ("zone(zd.rctlbufsz)", zd->rctlbufsz);
10112 PRE_FIELD_READ("zone(zd.zfsbuf)", zd->zfsbuf);
10113 PRE_FIELD_READ("zone(zd.zfsbufsz)", zd->zfsbufsz);
10114 PRE_FIELD_READ("zone(zd.extended_error)", zd->extended_error);
10115 PRE_FIELD_READ("zone(zd.match)", zd->match);
10116 PRE_FIELD_READ("zone(zd.doi)", zd->doi);
10117 PRE_FIELD_READ("zone(zd.label)", zd->label);
10118 PRE_FIELD_READ("zone(zd.flags)", zd->flags);
10119
10120 if (ML_(safe_to_deref((void *)ARG2, sizeof(vki_zone_def)))) {
10121 if (zd->zone_name)
10122 PRE_MEM_RASCIIZ("zone(zd.zone_name)", (Addr) zd->zone_name);
10123 if (zd->zone_root)
10124 PRE_MEM_RASCIIZ("zone(zd.zone_root)", (Addr) zd->zone_root);
10125 PRE_MEM_READ("zone(zd.zone_privs)", (Addr) zd->zone_privs,
10126 zd->zone_privssz);
10127 PRE_MEM_READ("zone(zd.rctlbuf)", (Addr) zd->rctlbuf,
10128 zd->rctlbufsz);
10129 PRE_MEM_READ("zone(zd.zfsbuf)",
10130 (Addr) zd->zfsbuf, zd->zfsbufsz);
10131 if (zd->label)
10132 PRE_MEM_READ("zone(zd.label)", (Addr) zd->label,
10133 sizeof(vki_bslabel_t));
10134 }
10135 break;
10136 case VKI_ZONE_DESTROY:
10137 /* Libc: int zone_destroy(zoneid_t zoneid); */
florianb26101c2015-08-08 21:45:33 +000010138 PRINT("sys_zone ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +000010139 PRE_REG_READ2(long, SC2("zone", "destroy"), int, cmd,
10140 vki_zoneid_t, zoneid);
10141 break;
10142 case VKI_ZONE_GETATTR:
10143 /* Libc: ssize_t zone_getattr(zoneid_t zoneid, int attr,
10144 void *valp, size_t size);
10145 */
10146 PRINT("sys_zone ( %ld, %ld, %ld, %#lx, %ld )",
florianb26101c2015-08-08 21:45:33 +000010147 SARG1, SARG2, SARG3, ARG4, SARG5);
sewardj8eb8bab2015-07-21 14:44:28 +000010148 PRE_REG_READ5(long, SC2("zone", "getattr"), int, cmd,
10149 vki_zoneid_t, zoneid, int, attr, void *, valp,
10150 vki_size_t, size);
10151 PRE_MEM_WRITE("zone(valp)", ARG4, ARG5);
10152 break;
10153 case VKI_ZONE_ENTER:
10154 /* Libc: int zone_enter(zoneid_t zoneid); */
florianb26101c2015-08-08 21:45:33 +000010155 PRINT("sys_zone ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +000010156 PRE_REG_READ2(long, SC2("zone", "enter"), int, cmd,
10157 vki_zoneid_t, zoneid);
10158 break;
10159 case VKI_ZONE_LIST:
10160 /* Libc: int zone_list(zoneid_t *zonelist, uint_t *numzones); */
florianb26101c2015-08-08 21:45:33 +000010161 PRINT("sys_zone ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010162 PRE_REG_READ3(long, SC2("zone", "list"), int, cmd,
10163 vki_zoneid_t *, zonelist, vki_uint_t *, numzones);
10164
10165 PRE_MEM_WRITE("zone(numzones)", ARG3, sizeof(vki_uint_t));
10166
10167 if (ML_(safe_to_deref((void *) ARG3, sizeof(vki_uint_t)))) {
10168 if (ARG2)
10169 PRE_MEM_WRITE("zone(zonelist)", ARG2,
10170 *(vki_uint_t *) ARG3 * sizeof(vki_zoneid_t));
10171 }
10172 break;
10173 case VKI_ZONE_SHUTDOWN:
10174 /* Libc: int zone_shutdown(zoneid_t zoneid); */
florianb26101c2015-08-08 21:45:33 +000010175 PRINT("sys_zone ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +000010176 PRE_REG_READ2(long, SC2("zone", "shutdown"), int, cmd,
10177 vki_zoneid_t, zoneid);
10178 break;
10179 case VKI_ZONE_LOOKUP:
10180 /* Libc: zoneid_t zone_lookup(const char *name); */
iraisr7d4aa192015-10-12 19:10:42 +000010181 PRINT("sys_zone ( %ld, %#lx(%s) )", SARG1, ARG2, (HChar *) ARG2);
sewardj8eb8bab2015-07-21 14:44:28 +000010182 PRE_REG_READ2(long, SC2("zone", "lookup"), int, cmd,
10183 const char *, name);
10184 if (ARG2)
10185 PRE_MEM_RASCIIZ("zone(name)", ARG2);
10186 break;
10187 case VKI_ZONE_BOOT:
10188 /* Libc: int zone_boot(zoneid_t zoneid); */
florianb26101c2015-08-08 21:45:33 +000010189 PRINT("sys_zone ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +000010190 PRE_REG_READ2(long, SC2("zone", "boot"), int, cmd,
10191 vki_zoneid_t, zoneid);
10192 break;
10193 case VKI_ZONE_SETATTR:
10194 /* Libc: int zone_setattr(zoneid_t zoneid, int attr, void *valp,
10195 size_t size);
10196 */
florianb26101c2015-08-08 21:45:33 +000010197 PRINT("sys_zone ( %ld, %ld, %ld, %#lx, %lu )",
10198 SARG1, SARG2, SARG3, ARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +000010199 PRE_REG_READ5(long, SC2("zone", "setattr"), int, cmd,
10200 vki_zoneid_t, zoneid, int, attr, void *, valp,
10201 vki_size_t, size);
10202 PRE_MEM_READ("zone(valp)", ARG4, ARG5);
10203 break;
10204 case VKI_ZONE_ADD_DATALINK:
10205 /* Libc: int zone_add_datalink(zoneid_t zoneid,
10206 datalink_id_t linkid);
10207 */
florianb26101c2015-08-08 21:45:33 +000010208 PRINT("sys_zone ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010209 PRE_REG_READ3(long, SC2("zone", "add_datalink"), int, cmd,
10210 vki_zoneid_t, zoneid, vki_datalink_id_t, linkid);
10211 break;
10212 case VKI_ZONE_DEL_DATALINK:
10213 /* Libc: int zone_remove_datalink(zoneid_t zoneid,
10214 datalink_id_t linkid);
10215 */
florianb26101c2015-08-08 21:45:33 +000010216 PRINT("sys_zone ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010217 PRE_REG_READ3(long, SC2("zone", "del_datalink"), int, cmd,
10218 vki_zoneid_t, zoneid, vki_datalink_id_t, linkid);
10219 break;
10220 case VKI_ZONE_CHECK_DATALINK:
10221 /* Libc: int zone_check_datalink(zoneid_t *zoneidp,
10222 datalink_id_t linkid);
10223 */
florianb26101c2015-08-08 21:45:33 +000010224 PRINT("sys_zone ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010225 PRE_REG_READ3(long, SC2("zone", "check_datalink"), int, cmd,
10226 vki_zoneid_t *, zoneidp, vki_datalink_id_t, linkid);
10227 PRE_MEM_WRITE("zone(zoneidp)", ARG2, sizeof(vki_zoneid_t));
10228 break;
10229 case VKI_ZONE_LIST_DATALINK:
10230 /* Libc: int zone_list_datalink(zoneid_t zoneid, int *dlnump,
10231 datalink_id_t *linkids);
10232 */
florianb26101c2015-08-08 21:45:33 +000010233 PRINT("sys_zone ( %ld, %ld, %#lx, %#lx )", SARG1, SARG2, ARG3, ARG4);
sewardj8eb8bab2015-07-21 14:44:28 +000010234 PRE_REG_READ4(long, SC2("zone", "list_datalink"), int, cmd,
10235 vki_zoneid_t, zoneid, int *, dlnump,
10236 vki_datalink_id_t *, linkids);
10237
10238 PRE_MEM_WRITE("zone(dlnump)", ARG3, sizeof(int));
10239 if (ML_(safe_to_deref((void *) ARG3, sizeof(int)))) {
10240 if (ARG4)
10241 PRE_MEM_WRITE("zone(linkids)", ARG4,
10242 *(int *) ARG3 * sizeof(vki_datalink_id_t));
10243 }
10244 break;
10245#if defined(SOLARIS_ZONE_DEFUNCT)
10246 case VKI_ZONE_LIST_DEFUNCT:
10247 /* Libc: int zone_list_defunct(uint64_t *uniqidlist,
10248 uint_t *numzones);
10249 */
florianb26101c2015-08-08 21:45:33 +000010250 PRINT("sys_zone ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010251 PRE_REG_READ3(long, SC2("zone", "list_defunct"), int, cmd,
10252 vki_uint64_t *, uniqidlist, vki_uint_t *, numzones);
10253
10254 PRE_MEM_WRITE("zone(numzones)", ARG3, sizeof(vki_uint_t));
10255
10256 if (ML_(safe_to_deref((void *) ARG3, sizeof(vki_uint_t)))) {
10257 if (ARG2)
10258 PRE_MEM_WRITE("zone(uniqidlist)", ARG2,
10259 *(vki_uint_t *) ARG3 * sizeof(vki_uint64_t));
10260 }
10261 break;
10262 case VKI_ZONE_GETATTR_DEFUNCT:
10263 /* Libc: ssize_t zone_getattr_defunct(uint64_t uniqid, int attr,
10264 void *valp, size_t size);
10265 Kernel: ssize_t zone_getattr_defunct(uint64_t *uniqid, int attr,
10266 void *valp, size_t size);
10267 */
florianb26101c2015-08-08 21:45:33 +000010268 PRINT("sys_zone ( %ld, %#lx, %ld, %#lx, %lu )",
10269 SARG1, ARG2, SARG3, ARG4, ARG5);
sewardj8eb8bab2015-07-21 14:44:28 +000010270 PRE_REG_READ5(long, SC2("zone", "getattr_defunct"), int, cmd,
10271 vki_uint64_t *, uniqid, int, attr,
10272 void *, valp, vki_size_t, size);
10273
10274 PRE_MEM_READ("zone(uniqid)", ARG2, sizeof(vki_uint64_t));
10275 PRE_MEM_WRITE("zone(valp)", ARG4, ARG5);
10276 break;
10277#endif /* SOLARIS_ZONE_DEFUNCT */
10278 default:
florianb26101c2015-08-08 21:45:33 +000010279 VG_(unimplemented)("Syswrap of the zone call with cmd %ld.", SARG1);
sewardj8eb8bab2015-07-21 14:44:28 +000010280 /*NOTREACHED*/
10281 break;
10282 }
10283
10284}
10285
10286POST(sys_zone)
10287{
10288 switch (ARG1 /*cmd*/) {
10289 case VKI_ZONE_CREATE:
10290 case VKI_ZONE_DESTROY:
10291 break;
10292 case VKI_ZONE_GETATTR:
10293 POST_MEM_WRITE(ARG4, MIN(RES, ARG5));
10294 break;
10295 case VKI_ZONE_ENTER:
10296 break;
10297 case VKI_ZONE_LIST:
10298 POST_MEM_WRITE(ARG2, *(vki_uint_t *) ARG3 * sizeof(vki_zoneid_t));
10299 break;
10300 case VKI_ZONE_SHUTDOWN:
10301 case VKI_ZONE_LOOKUP:
10302 case VKI_ZONE_BOOT:
10303 case VKI_ZONE_SETATTR:
10304 case VKI_ZONE_ADD_DATALINK:
10305 case VKI_ZONE_DEL_DATALINK:
10306 break;
10307 case VKI_ZONE_CHECK_DATALINK:
10308 POST_MEM_WRITE(ARG2, sizeof(vki_zoneid_t));
10309 break;
10310 case VKI_ZONE_LIST_DATALINK:
10311 POST_MEM_WRITE(ARG4, *(int *) ARG3 * sizeof(vki_datalink_id_t));
10312 break;
10313#if defined(SOLARIS_ZONE_DEFUNCT)
10314 case VKI_ZONE_LIST_DEFUNCT:
10315 POST_MEM_WRITE(ARG2, *(vki_uint_t *) ARG3 * sizeof(vki_uint64_t));
10316 break;
10317 case VKI_ZONE_GETATTR_DEFUNCT:
10318 POST_MEM_WRITE(ARG4, MIN(RES, ARG5));
10319 break;
10320#endif /* SOLARIS_ZONE_DEFUNCT */
10321 default:
10322 vg_assert(0);
10323 break;
10324 }
10325}
10326
10327PRE(sys_getcwd)
10328{
10329 /* int getcwd(char *buf, size_t size); */
10330 /* Note: Generic getcwd() syswrap can't be used because it expects
10331 a different return value. */
10332 PRINT("sys_getcwd ( %#lx, %lu )", ARG1, ARG2);
10333 PRE_REG_READ2(long, "getcwd", char *, buf, vki_size_t, size);
10334 PRE_MEM_WRITE("getcwd(buf)", ARG1, ARG2);
10335}
10336
10337POST(sys_getcwd)
10338{
10339 POST_MEM_WRITE(ARG1, VG_(strlen)((HChar*)ARG1) + 1);
10340}
10341
10342PRE(sys_so_socket)
10343{
10344 /* int so_socket(int family, int type, int protocol, char *devpath,
10345 int version); */
florianb26101c2015-08-08 21:45:33 +000010346 PRINT("sys_so_socket ( %ld, %ld, %ld, %#lx(%s), %ld)", SARG1, SARG2, SARG3,
10347 ARG4, (HChar *) ARG4, SARG5);
sewardj8eb8bab2015-07-21 14:44:28 +000010348 PRE_REG_READ5(long, "socket", int, family, int, type, int, protocol,
10349 char *, devpath, int, version);
10350 if (ARG4)
10351 PRE_MEM_RASCIIZ("socket(devpath)", ARG4);
10352}
10353
10354POST(sys_so_socket)
10355{
10356 SysRes r;
10357 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
10358 SET_STATUS_from_SysRes(r);
10359}
10360
10361PRE(sys_so_socketpair)
10362{
10363 /* int so_socketpair(int sv[2]); */
10364 /* This syscall is used to connect two already created sockets together. */
10365 PRINT("sys_so_socketpair ( %#lx )", ARG1);
10366 PRE_REG_READ1(long, "socketpair", int *, sv);
10367 PRE_MEM_READ("socketpair(sv)", ARG1, 2 * sizeof(int));
10368 /*PRE_MEM_WRITE("socketpair(sv)", ARG1, 2 * sizeof(int));*/
10369 if (ML_(safe_to_deref)((void*)ARG1, 2 * sizeof(int))) {
10370 int *fds = (int*)ARG1;
10371 if (!ML_(fd_allowed)(fds[0], "socketpair", tid, False))
10372 SET_STATUS_Failure(VKI_EBADF);
10373 else if (!ML_(fd_allowed)(fds[1], "socketpair", tid, False))
10374 SET_STATUS_Failure(VKI_EBADF);
10375 }
10376}
10377
10378POST(sys_so_socketpair)
10379{
10380 /* The kernel can return new file descriptors, in such a case we have to
10381 validate them. */
10382 int *fds = (int*)ARG1;
10383 POST_MEM_WRITE(ARG1, 2 * sizeof(int));
10384 if (!ML_(fd_allowed)(fds[0], "socketpair", tid, True))
10385 SET_STATUS_Failure(VKI_EMFILE);
10386 if (!ML_(fd_allowed)(fds[1], "socketpair", tid, True))
10387 SET_STATUS_Failure(VKI_EMFILE);
10388 if (FAILURE) {
10389 /* One or both of the file descriptors weren't allowed, close newly
10390 created file descriptors but don't close the already recorded
10391 ones. */
10392 if (!ML_(fd_recorded)(fds[0]))
10393 VG_(close)(fds[0]);
10394 if (!ML_(fd_recorded)(fds[1]))
10395 VG_(close)(fds[1]);
10396 }
10397 else if (VG_(clo_track_fds)) {
10398 /* Everything went better than expected, record the newly created file
10399 descriptors. Note: If the kernel actually returns the original file
10400 descriptors, then ML_(record_fd_open_nameless) notices that these
10401 file descriptors have been already recorded. */
10402 ML_(record_fd_open_nameless)(tid, fds[0]);
10403 ML_(record_fd_open_nameless)(tid, fds[1]);
10404 }
10405}
10406
10407PRE(sys_bind)
10408{
10409 /* int bind(int s, struct sockaddr *name, socklen_t namelen,
10410 int version); */
florianb26101c2015-08-08 21:45:33 +000010411 PRINT("sys_bind ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +000010412 PRE_REG_READ4(long, "bind", int, s, struct sockaddr *, name,
10413 vki_socklen_t, namelen, int, version);
10414 ML_(generic_PRE_sys_bind)(tid, ARG1, ARG2, ARG3);
10415}
10416
10417PRE(sys_listen)
10418{
10419 /* int listen(int s, int backlog, int version); */
florianb26101c2015-08-08 21:45:33 +000010420 PRINT("sys_listen ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010421 PRE_REG_READ3(long, "listen", int, s, int, backlog, int, version);
10422}
10423
10424PRE(sys_accept)
10425{
10426#if defined(SOLARIS_NEW_ACCEPT_SYSCALL)
10427 /* int accept(int s, struct sockaddr *addr, socklen_t *addrlen,
10428 int version, int flags); */
10429 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010430 PRINT("sys_accept ( %ld, %#lx, %#lx, %ld, %ld )", SARG1, ARG2, ARG3, SARG4,
10431 SARG5);
sewardj8eb8bab2015-07-21 14:44:28 +000010432 PRE_REG_READ5(long, "accept", int, s, struct sockaddr *, addr,
10433 socklen_t *, addrlen, int, version, int, flags);
10434#else
10435 /* int accept(int s, struct sockaddr *addr, socklen_t *addrlen,
10436 int version); */
10437 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010438 PRINT("sys_accept ( %ld, %#lx, %#lx, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +000010439 PRE_REG_READ4(long, "accept", int, s, struct sockaddr *, addr,
10440 socklen_t *, addrlen, int, version);
10441#endif /* SOLARIS_NEW_ACCEPT_SYSCALL */
10442 ML_(generic_PRE_sys_accept)(tid, ARG1, ARG2, ARG3);
10443}
10444
10445POST(sys_accept)
10446{
10447 SysRes r;
10448 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
10449 ARG1, ARG2, ARG3);
10450 SET_STATUS_from_SysRes(r);
10451}
10452
10453PRE(sys_connect)
10454{
10455 /* int connect(int s, struct sockaddr *name, socklen_t namelen,
10456 int version); */
10457 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010458 PRINT("sys_connect ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +000010459 PRE_REG_READ4(long, "connect", int, s, struct sockaddr *, name,
10460 vki_socklen_t, namelen, int, version);
10461 ML_(generic_PRE_sys_connect)(tid, ARG1, ARG2, ARG3);
10462}
10463
10464PRE(sys_shutdown)
10465{
10466 /* Kernel: int shutdown(int sock, int how, int version);
10467 Libc: int shutdown(int sock, int how);
10468 */
10469 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010470 PRINT("sys_shutdown ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010471 PRE_REG_READ3(int, "shutdown", int, sock, int, how, int, version);
10472
10473 /* Be strict. */
10474 if (!ML_(fd_allowed)(ARG1, "shutdown", tid, False))
10475 SET_STATUS_Failure(VKI_EBADF);
10476}
10477
10478PRE(sys_recv)
10479{
10480 /* ssize_t recv(int s, void *buf, size_t len, int flags); */
10481 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010482 PRINT("sys_recv ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +000010483 PRE_REG_READ4(long, "recv", int, s, void *, buf, vki_size_t, len,
10484 int, flags);
10485 ML_(generic_PRE_sys_recv)(tid, ARG1, ARG2, ARG3);
10486}
10487
10488POST(sys_recv)
10489{
10490 ML_(generic_POST_sys_recv)(tid, RES, ARG1, ARG2, ARG3);
10491}
10492
10493PRE(sys_recvfrom)
10494{
10495 /* ssize_t recvfrom(int s, void *buf, size_t len, int flags,
10496 struct sockaddr *from, socklen_t *fromlen); */
10497 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010498 PRINT("sys_recvfrom ( %ld, %#lx, %lu, %ld, %#lx, %#lx )", SARG1, ARG2, ARG3,
10499 SARG4, ARG5, ARG6);
sewardj8eb8bab2015-07-21 14:44:28 +000010500 PRE_REG_READ6(long, "recvfrom", int, s, void *, buf, vki_size_t, len,
10501 int, flags, struct sockaddr *, from, socklen_t *, fromlen);
10502 ML_(generic_PRE_sys_recvfrom)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
10503}
10504
10505POST(sys_recvfrom)
10506{
10507 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
10508 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
10509}
10510
10511PRE(sys_recvmsg)
10512{
10513 /* ssize_t recvmsg(int s, struct msghdr *msg, int flags); */
10514 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010515 PRINT("sys_recvmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010516 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
10517 ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr*)ARG2);
10518}
10519
10520POST(sys_recvmsg)
10521{
10522 ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr*)ARG2, RES);
10523}
10524
10525PRE(sys_send)
10526{
10527 /* ssize_t send(int s, const void *msg, size_t len, int flags); */
10528 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010529 PRINT("sys_send ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +000010530 PRE_REG_READ4(long, "send", int, s, const void *, msg, vki_size_t, len,
10531 int, flags);
10532 ML_(generic_PRE_sys_send)(tid, ARG1, ARG2, ARG3);
10533}
10534
10535PRE(sys_sendmsg)
10536{
10537 /* ssize_t sendmsg(int s, const struct msghdr *msg, int flags); */
10538 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010539 PRINT("sys_sendmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
sewardj8eb8bab2015-07-21 14:44:28 +000010540 PRE_REG_READ3(long, "sendmsg", int, s, const struct msghdr *, msg,
10541 int, flags);
10542 ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr*)ARG2);
10543}
10544
10545PRE(sys_sendto)
10546{
10547 /* ssize_t sendto(int s, const void *msg, size_t len, int flags,
10548 const struct sockaddr *to, int tolen); */
10549 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010550 PRINT("sys_sendto ( %ld, %#lx, %lu, %ld, %#lx, %ld )", SARG1, ARG2, ARG3,
10551 SARG4, ARG5, SARG6);
sewardj8eb8bab2015-07-21 14:44:28 +000010552 PRE_REG_READ6(long, "sendto", int, s, const void *, msg, vki_size_t, len,
10553 int, flags, const struct sockaddr *, to, int, tolen);
10554 ML_(generic_PRE_sys_sendto)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
10555}
10556
10557PRE(sys_getpeername)
10558{
10559 /* Kernel: int getpeername(int s, struct sockaddr *name,
10560 socklen_t *namelen, int version);
10561 Libc: int getpeername(int s, struct sockaddr *name,
10562 socklen_t *namelen);
10563 */
10564 *flags |= SfMayBlock;
10565 PRINT("sys_getpeername ( %ld, %#lx, %#lx, %ld )",
florianb26101c2015-08-08 21:45:33 +000010566 SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +000010567 PRE_REG_READ4(long, "getpeername", int, s, struct vki_sockaddr *, name,
10568 vki_socklen_t *, namelen, int, version);
10569 ML_(buf_and_len_pre_check)(tid, ARG2, ARG3, "getpeername(name)",
10570 "getpeername(namelen)");
10571
10572 /* Be strict. */
10573 if (!ML_(fd_allowed)(ARG1, "getpeername", tid, False))
10574 SET_STATUS_Failure(VKI_EBADF);
10575}
10576
10577POST(sys_getpeername)
10578{
10579 ML_(buf_and_len_post_check)(tid, VG_(mk_SysRes_Success)(RES),
10580 ARG2, ARG3, "getpeername(namelen)");
10581}
10582
10583PRE(sys_getsockname)
10584{
10585 /* int getsockname(int s, struct sockaddr *name, socklen_t *namelen,
10586 int version); */
florianb26101c2015-08-08 21:45:33 +000010587 PRINT("sys_getsockname ( %ld, %#lx, %#lx, %ld )", SARG1, ARG2, ARG3, SARG4);
sewardj8eb8bab2015-07-21 14:44:28 +000010588 PRE_REG_READ4(long, "getsockname", int, s, struct sockaddr *, name,
10589 socklen_t *, namelen, int, version);
10590 ML_(generic_PRE_sys_getsockname)(tid, ARG1, ARG2, ARG3);
10591}
10592
10593POST(sys_getsockname)
10594{
10595 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
10596 ARG1, ARG2, ARG3);
10597}
10598
10599PRE(sys_getsockopt)
10600{
10601 /* int getsockopt(int s, int level, int optname, void *optval,
10602 socklen_t *optlen, int version); */
florianb26101c2015-08-08 21:45:33 +000010603 PRINT("sys_getsockopt ( %ld, %ld, %ld, %#lx, %#lx, %ld )", SARG1, SARG2,
10604 SARG3, ARG4, ARG5, SARG6);
sewardj8eb8bab2015-07-21 14:44:28 +000010605 PRE_REG_READ6(long, "getsockopt", int, s, int, level, int, optname,
10606 void *, optval, socklen_t *, option, int, version);
10607 if (ARG4)
10608 ML_(buf_and_len_pre_check)(tid, ARG4, ARG5, "getsockopt(optval)",
10609 "getsockopt(optlen)");
10610}
10611
10612POST(sys_getsockopt)
10613{
10614 if (ARG4)
10615 ML_(buf_and_len_post_check)(tid, VG_(mk_SysRes_Success)(RES), ARG4,
10616 ARG5, "getsockopt(optlen_out)");
10617}
10618
10619PRE(sys_setsockopt)
10620{
10621 /* int setsockopt(int s, int level, int optname, const void *optval,
10622 socklen_t optlen, int version); */
florianb26101c2015-08-08 21:45:33 +000010623 PRINT("sys_setsockopt ( %ld, %ld, %ld, %#lx, %lu, %ld )", SARG1, SARG2,
10624 SARG3, ARG4, ARG5, SARG6);
sewardj8eb8bab2015-07-21 14:44:28 +000010625 PRE_REG_READ6(long, "setsockopt", int, s, int, level, int, optname,
10626 const void *, optval, vki_socklen_t, optlen, int, version);
10627 ML_(generic_PRE_sys_setsockopt)(tid, ARG1, ARG2, ARG3, ARG4, ARG5);
10628}
10629
10630PRE(sys_lwp_mutex_register)
10631{
10632 /* int lwp_mutex_register(lwp_mutex_t *mp, caddr_t uaddr); */
10633 vki_lwp_mutex_t *mp = (vki_lwp_mutex_t*)ARG1;
10634 PRINT("sys_lwp_mutex_register ( %#lx, %#lx )", ARG1, ARG2);
10635 PRE_REG_READ2(long, "lwp_mutex_register", lwp_mutex_t *, mp,
10636 void *, uaddr);
10637 PRE_FIELD_READ("lwp_mutex_register(mp->mutex_type)", mp->vki_mutex_type);
10638}
10639
10640PRE(sys_uucopy)
10641{
10642 /* int uucopy(const void *s1, void *s2, size_t n); */
10643 PRINT("sys_uucopy ( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
10644 PRE_REG_READ3(long, "uucopy", const void *, s1, void *, s2, vki_size_t, n);
10645
10646 /* Stay away from V segments. */
10647 if (!ML_(valid_client_addr)(ARG1, ARG3, tid, "uucopy(s1)")) {
10648 SET_STATUS_Failure(VKI_EFAULT);
10649 }
10650 if (!ML_(valid_client_addr)(ARG2, ARG3, tid, "uucopy(s2)")) {
10651 SET_STATUS_Failure(VKI_EFAULT);
10652 }
10653
10654 if (FAILURE)
10655 return;
10656
10657 /* XXX This is actually incorrect, we should be able to copy undefined
10658 values through to their new destination. */
10659 PRE_MEM_READ("uucopy(s1)", ARG1, ARG3);
10660 PRE_MEM_WRITE("uucopy(s2)", ARG2, ARG3);
10661}
10662
10663POST(sys_uucopy)
10664{
10665 POST_MEM_WRITE(ARG2, ARG3);
10666}
10667
10668PRE(sys_umount2)
10669{
10670 /* int umount2(const char *file, int mflag); */
10671 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +000010672 PRINT("sys_umount2 ( %#lx(%s), %ld )", ARG1, (HChar *) ARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +000010673 PRE_REG_READ2(long, "umount2", const char *, file, int, mflag);
10674 PRE_MEM_RASCIIZ("umount2(file)", ARG1);
10675}
10676
10677PRE(fast_gethrtime)
10678{
10679 PRINT("fast_gethrtime ( )");
10680 PRE_REG_READ0(long, "gethrtime");
10681}
10682
10683PRE(fast_gethrvtime)
10684{
10685 PRINT("fast_gethrvtime ( )");
10686 PRE_REG_READ0(long, "gethrvtime");
10687}
10688
10689PRE(fast_gethrestime)
10690{
10691 /* Used by gettimeofday(3C). */
10692 PRINT("fast_gethrestime ( )");
10693 PRE_REG_READ0(long, "gethrestime");
10694}
10695
Elliott Hughesed398002017-06-21 14:41:24 -070010696PRE(fast_getlgrp)
10697{
10698 /* Fasttrap number shared between gethomelgroup() and getcpuid(). */
10699 PRINT("fast_getlgrp ( )");
10700 PRE_REG_READ0(long, "getlgrp");
10701}
10702
sewardj8eb8bab2015-07-21 14:44:28 +000010703#if defined(SOLARIS_GETHRT_FASTTRAP)
10704PRE(fast_gethrt)
10705{
10706 /* Used by gethrtime(3C) when tsp & tscp HWCAPs are present. */
10707 PRINT("fast_gethrt ( )");
10708 PRE_REG_READ0(long, "gethrt");
10709}
10710
10711POST(fast_gethrt)
10712{
10713 if (RES == 0)
10714 return;
10715
iraisre0365402015-09-25 20:12:26 +000010716 VG_(change_mapping_ownership)(RES, False);
sewardj8eb8bab2015-07-21 14:44:28 +000010717}
10718#endif /* SOLARIS_GETHRT_FASTTRAP */
10719
10720#if defined(SOLARIS_GETZONEOFFSET_FASTTRAP)
10721PRE(fast_getzoneoffset)
10722{
10723 /* Returns kernel's time zone offset data. */
10724 PRINT("fast_getzoneoffset ( )");
10725 PRE_REG_READ0(long, "get_zone_offset");
10726}
10727
10728POST(fast_getzoneoffset)
10729{
10730 if (RES == 0)
10731 return;
10732
iraisre0365402015-09-25 20:12:26 +000010733 VG_(change_mapping_ownership)(RES, False);
sewardj8eb8bab2015-07-21 14:44:28 +000010734}
10735#endif /* SOLARIS_GETZONEOFFSET_FASTTRAP */
10736
10737#undef PRE
10738#undef POST
10739
10740/* ---------------------------------------------------------------------
10741 The Solaris syscall table
10742 ------------------------------------------------------------------ */
10743
10744/* Add a Solaris-specific, arch-independent wrapper to a syscall table. */
10745#define SOLX_(sysno, name) \
10746 WRAPPER_ENTRY_X_(solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10747#define SOLXY(sysno, name) \
10748 WRAPPER_ENTRY_XY(solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10749
10750#if defined(VGP_x86_solaris)
10751/* Add an x86-solaris specific wrapper to a syscall table. */
10752#define PLAX_(sysno, name) \
10753 WRAPPER_ENTRY_X_(x86_solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10754#define PLAXY(sysno, name) \
10755 WRAPPER_ENTRY_XY(x86_solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10756
10757#elif defined(VGP_amd64_solaris)
10758/* Add an amd64-solaris specific wrapper to a syscall table. */
10759#define PLAX_(sysno, name) \
10760 WRAPPER_ENTRY_X_(amd64_solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10761#define PLAXY(sysno, name) \
10762 WRAPPER_ENTRY_XY(amd64_solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10763
10764#else
10765# error "Unknown platform"
10766#endif
10767
10768/*
10769 GEN : handlers are in syswrap-generic.c
10770 SOL : handlers are in this file
10771 X_ : PRE handler only
10772 XY : PRE and POST handlers
10773*/
10774
10775static SyscallTableEntry syscall_table[] = {
10776 SOLX_(__NR_exit, sys_exit), /* 1 */
10777#if defined(SOLARIS_SPAWN_SYSCALL)
10778 SOLX_(__NR_spawn, sys_spawn), /* 2 */
10779#endif /* SOLARIS_SPAWN_SYSCALL */
10780 GENXY(__NR_read, sys_read), /* 3 */
10781 GENX_(__NR_write, sys_write), /* 4 */
10782#if defined(SOLARIS_OLD_SYSCALLS)
10783 SOLXY(__NR_open, sys_open), /* 5 */
10784#endif /* SOLARIS_OLD_SYSCALLS */
10785 SOLXY(__NR_close, sys_close), /* 6 */
10786 SOLX_(__NR_linkat, sys_linkat), /* 7 */
10787#if defined(SOLARIS_OLD_SYSCALLS)
10788 GENX_(__NR_link, sys_link), /* 9 */
10789 GENX_(__NR_unlink, sys_unlink), /* 10 */
10790#endif /* SOLARIS_OLD_SYSCALLS */
10791 SOLX_(__NR_symlinkat, sys_symlinkat), /* 11 */
10792 GENX_(__NR_chdir, sys_chdir), /* 12 */
10793 SOLX_(__NR_time, sys_time), /* 13 */
10794#if defined(SOLARIS_OLD_SYSCALLS)
10795 GENX_(__NR_chmod, sys_chmod), /* 15 */
10796 GENX_(__NR_chown, sys_chown), /* 16 */
10797#endif /* SOLARIS_OLD_SYSCALLS */
10798 SOLX_(__NR_brk, sys_brk), /* 17 */
10799#if defined(SOLARIS_OLD_SYSCALLS)
10800 SOLXY(__NR_stat, sys_stat), /* 18 */
10801#endif /* SOLARIS_OLD_SYSCALLS */
10802 SOLX_(__NR_lseek, sys_lseek), /* 19 */
10803 GENX_(__NR_getpid, sys_getpid), /* 20 */
10804 SOLXY(__NR_mount, sys_mount), /* 21 */
10805 SOLXY(__NR_readlinkat, sys_readlinkat), /* 22 */
10806 GENX_(__NR_setuid, sys_setuid), /* 23 */
10807 GENX_(__NR_getuid, sys_getuid), /* 24 */
10808 SOLX_(__NR_stime, sys_stime), /* 25 */
10809 GENX_(__NR_alarm, sys_alarm), /* 27 */
10810#if defined(SOLARIS_OLD_SYSCALLS)
10811 SOLXY(__NR_fstat, sys_fstat), /* 28 */
10812#endif /* SOLARIS_OLD_SYSCALLS */
10813 GENX_(__NR_pause, sys_pause), /* 29 */
10814#if defined(SOLARIS_FREALPATHAT_SYSCALL)
10815 SOLXY(__NR_frealpathat, sys_frealpathat), /* 30 */
10816#endif /* SOLARIS_FREALPATHAT_SYSCALL */
10817 SOLX_(__NR_stty, sys_stty), /* 31 */
10818 SOLXY(__NR_gtty, sys_gtty), /* 32 */
10819#if defined(SOLARIS_OLD_SYSCALLS)
10820 GENX_(__NR_access, sys_access), /* 33 */
10821#endif /* SOLARIS_OLD_SYSCALLS */
10822 GENX_(__NR_kill, sys_kill), /* 37 */
10823 SOLX_(__NR_pgrpsys, sys_pgrpsys), /* 39 */
10824 SOLXY(__NR_pipe, sys_pipe), /* 42 */
10825 GENXY(__NR_times, sys_times), /* 43 */
10826 SOLX_(__NR_faccessat, sys_faccessat), /* 45 */
10827 GENX_(__NR_setgid, sys_setgid), /* 46 */
10828 GENX_(__NR_getgid, sys_getgid), /* 47 */
10829 SOLXY(__NR_mknodat, sys_mknodat), /* 48 */
10830 SOLXY(__NR_sysi86, sys_sysi86), /* 50 */
10831 SOLXY(__NR_shmsys, sys_shmsys), /* 52 */
10832 SOLXY(__NR_semsys, sys_semsys), /* 53 */
10833 SOLXY(__NR_ioctl, sys_ioctl), /* 54 */
10834 SOLX_(__NR_fchownat, sys_fchownat), /* 56 */
10835 SOLX_(__NR_fdsync, sys_fdsync), /* 58 */
10836 SOLX_(__NR_execve, sys_execve), /* 59 */
10837 GENX_(__NR_umask, sys_umask), /* 60 */
10838 GENX_(__NR_chroot, sys_chroot), /* 61 */
10839 SOLXY(__NR_fcntl, sys_fcntl), /* 62 */
10840 SOLX_(__NR_renameat, sys_renameat), /* 64 */
10841 SOLX_(__NR_unlinkat, sys_unlinkat), /* 65 */
10842 SOLXY(__NR_fstatat, sys_fstatat), /* 66 */
10843#if defined(VGP_x86_solaris)
10844 PLAXY(__NR_fstatat64, sys_fstatat64), /* 67 */
10845#endif /* VGP_x86_solaris */
10846 SOLXY(__NR_openat, sys_openat), /* 68 */
10847#if defined(VGP_x86_solaris)
10848 PLAXY(__NR_openat64, sys_openat64), /* 69 */
10849#endif /* VGP_x86_solaris */
10850 SOLXY(__NR_tasksys, sys_tasksys), /* 70 */
10851 SOLXY(__NR_getpagesizes, sys_getpagesizes), /* 73 */
10852 SOLXY(__NR_lwp_park, sys_lwp_park), /* 77 */
10853 SOLXY(__NR_sendfilev, sys_sendfilev), /* 78 */
10854#if defined(SOLARIS_LWP_NAME_SYSCALL)
10855 SOLXY(__NR_lwp_name, sys_lwp_name), /* 79 */
10856#endif /* SOLARIS_LWP_NAME_SYSCALL */
10857#if defined(SOLARIS_OLD_SYSCALLS)
10858 GENX_(__NR_rmdir, sys_rmdir), /* 79 */
10859 GENX_(__NR_mkdir, sys_mkdir), /* 80 */
10860#endif /* SOLARIS_OLD_SYSCALLS */
10861 GENXY(__NR_getdents, sys_getdents), /* 81 */
10862 SOLXY(__NR_privsys, sys_privsys), /* 82 */
10863 SOLXY(__NR_ucredsys, sys_ucredsys), /* 83 */
Elliott Hughesa0664b92017-04-18 17:46:52 -070010864 SOLXY(__NR_sysfs, sys_sysfs), /* 84 */
sewardj8eb8bab2015-07-21 14:44:28 +000010865 SOLXY(__NR_getmsg, sys_getmsg), /* 85 */
10866 SOLX_(__NR_putmsg, sys_putmsg), /* 86 */
10867#if defined(SOLARIS_OLD_SYSCALLS)
10868 SOLXY(__NR_lstat, sys_lstat), /* 88 */
10869 GENX_(__NR_symlink, sys_symlink), /* 89 */
10870 GENX_(__NR_readlink, sys_readlink), /* 90 */
10871#endif /* SOLARIS_OLD_SYSCALLS */
10872 GENX_(__NR_setgroups, sys_setgroups), /* 91 */
10873 GENXY(__NR_getgroups, sys_getgroups), /* 92 */
10874#if defined(SOLARIS_OLD_SYSCALLS)
10875 GENX_(__NR_fchmod, sys_fchmod), /* 93 */
10876 GENX_(__NR_fchown, sys_fchown), /* 94 */
10877#endif /* SOLARIS_OLD_SYSCALLS */
10878 SOLXY(__NR_sigprocmask, sys_sigprocmask), /* 95 */
Elliott Hughesed398002017-06-21 14:41:24 -070010879 SOLX_(__NR_sigsuspend, sys_sigsuspend), /* 96 */
sewardj8eb8bab2015-07-21 14:44:28 +000010880 GENXY(__NR_sigaltstack, sys_sigaltstack), /* 97 */
10881 SOLXY(__NR_sigaction, sys_sigaction), /* 98 */
10882 SOLXY(__NR_sigpending, sys_sigpending), /* 99 */
10883 SOLX_(__NR_context, sys_getsetcontext), /* 100 */
10884 SOLX_(__NR_fchmodat, sys_fchmodat), /* 101 */
10885 SOLX_(__NR_mkdirat, sys_mkdirat), /* 102 */
10886 SOLXY(__NR_statvfs, sys_statvfs), /* 103 */
10887 SOLXY(__NR_fstatvfs, sys_fstatvfs), /* 104 */
10888 SOLXY(__NR_nfssys, sys_nfssys), /* 106 */
10889 SOLXY(__NR_waitid, sys_waitid), /* 107 */
Elliott Hughesed398002017-06-21 14:41:24 -070010890 SOLX_(__NR_sigsendsys, sys_sigsendsys), /* 108 */
sewardj8eb8bab2015-07-21 14:44:28 +000010891#if defined(SOLARIS_UTIMESYS_SYSCALL)
10892 SOLX_(__NR_utimesys, sys_utimesys), /* 110 */
10893#endif /* SOLARIS_UTIMESYS_SYSCALL */
10894#if defined(SOLARIS_UTIMENSAT_SYSCALL)
10895 SOLX_(__NR_utimensat, sys_utimensat), /* 110 */
10896#endif /* SOLARIS_UTIMENSAT_SYSCALL */
10897 SOLXY(__NR_sigresend, sys_sigresend), /* 111 */
10898 SOLXY(__NR_priocntlsys, sys_priocntlsys), /* 112 */
10899 SOLX_(__NR_pathconf, sys_pathconf), /* 113 */
10900 SOLX_(__NR_mmap, sys_mmap), /* 115 */
10901 GENXY(__NR_mprotect, sys_mprotect), /* 116 */
10902 GENXY(__NR_munmap, sys_munmap), /* 117 */
iraisrc593e2f2015-10-15 09:37:14 +000010903 GENX_(__NR_fchdir, sys_fchdir), /* 120 */
sewardj8eb8bab2015-07-21 14:44:28 +000010904 GENXY(__NR_readv, sys_readv), /* 121 */
10905 GENX_(__NR_writev, sys_writev), /* 122 */
10906#if defined(SOLARIS_UUIDSYS_SYSCALL)
10907 SOLXY(__NR_uuidsys, sys_uuidsys), /* 124 */
10908#endif /* SOLARIS_UUIDSYS_SYSCALL */
10909 SOLX_(__NR_mmapobj, sys_mmapobj), /* 127 */
10910 GENX_(__NR_setrlimit, sys_setrlimit), /* 128 */
10911 GENXY(__NR_getrlimit, sys_getrlimit), /* 129 */
10912#if defined(SOLARIS_OLD_SYSCALLS)
10913 GENX_(__NR_lchown, sys_lchown), /* 130 */
10914#endif /* SOLARIS_OLD_SYSCALLS */
10915 SOLX_(__NR_memcntl, sys_memcntl), /* 131 */
10916 SOLXY(__NR_getpmsg, sys_getpmsg), /* 132 */
10917 SOLX_(__NR_putpmsg, sys_putpmsg), /* 133 */
10918#if defined(SOLARIS_OLD_SYSCALLS)
10919 SOLX_(__NR_rename, sys_rename), /* 134 */
10920#endif /* SOLARIS_OLD_SYSCALLS */
10921 SOLXY(__NR_uname, sys_uname), /* 135 */
10922 SOLX_(__NR_setegid, sys_setegid), /* 136 */
10923 SOLX_(__NR_sysconfig, sys_sysconfig), /* 137 */
10924 SOLXY(__NR_systeminfo, sys_systeminfo), /* 139 */
10925 SOLX_(__NR_seteuid, sys_seteuid), /* 141 */
10926 SOLX_(__NR_forksys, sys_forksys), /* 142 */
Elliott Hughesa0664b92017-04-18 17:46:52 -070010927#if defined(SOLARIS_GETRANDOM_SYSCALL)
10928 SOLXY(__NR_getrandom, sys_getrandom), /* 143 */
10929#endif /* SOLARIS_GETRANDOM_SYSCALL */
sewardj8eb8bab2015-07-21 14:44:28 +000010930 SOLXY(__NR_sigtimedwait, sys_sigtimedwait), /* 144 */
10931 SOLX_(__NR_yield, sys_yield), /* 146 */
10932 SOLXY(__NR_lwp_sema_post, sys_lwp_sema_post), /* 148 */
10933 SOLXY(__NR_lwp_sema_trywait, sys_lwp_sema_trywait), /* 149 */
10934 SOLX_(__NR_lwp_detach, sys_lwp_detach), /* 150 */
Elliott Hughesa0664b92017-04-18 17:46:52 -070010935 SOLXY(__NR_modctl, sys_modctl), /* 152 */
sewardj8eb8bab2015-07-21 14:44:28 +000010936 SOLX_(__NR_fchroot, sys_fchroot), /* 153 */
iraisrc0d46cd2015-09-25 21:04:45 +000010937#if defined(SOLARIS_SYSTEM_STATS_SYSCALL)
10938 SOLX_(__NR_system_stats, sys_system_stats), /* 154 */
10939#endif /* SOLARIS_SYSTEM_STATS_SYSCALL */
sewardj8eb8bab2015-07-21 14:44:28 +000010940 SOLXY(__NR_gettimeofday, sys_gettimeofday), /* 156 */
10941 GENXY(__NR_getitimer, sys_getitimer), /* 157 */
10942 GENXY(__NR_setitimer, sys_setitimer), /* 158 */
10943 SOLX_(__NR_lwp_create, sys_lwp_create), /* 159 */
10944 SOLX_(__NR_lwp_exit, sys_lwp_exit), /* 160 */
10945 SOLX_(__NR_lwp_suspend, sys_lwp_suspend), /* 161 */
10946 SOLX_(__NR_lwp_continue, sys_lwp_continue), /* 162 */
10947#if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
10948 SOLXY(__NR_lwp_sigqueue, sys_lwp_sigqueue), /* 163 */
10949#else
10950 SOLXY(__NR_lwp_kill, sys_lwp_kill), /* 163 */
10951#endif /* SOLARIS_LWP_SIGQUEUE_SYSCALL */
10952 SOLX_(__NR_lwp_self, sys_lwp_self), /* 164 */
10953 SOLX_(__NR_lwp_sigmask, sys_lwp_sigmask), /* 165 */
10954 SOLX_(__NR_lwp_private, sys_lwp_private), /* 166 */
10955 SOLXY(__NR_lwp_wait, sys_lwp_wait), /* 167 */
10956 SOLXY(__NR_lwp_mutex_wakeup, sys_lwp_mutex_wakeup), /* 168 */
iraisr173bb6e2015-10-16 12:20:20 +000010957 SOLXY(__NR_lwp_cond_wait, sys_lwp_cond_wait), /* 170 */
Elliott Hughesa0664b92017-04-18 17:46:52 -070010958 SOLXY(__NR_lwp_cond_signal, sys_lwp_cond_signal), /* 171 */
sewardj8eb8bab2015-07-21 14:44:28 +000010959 SOLX_(__NR_lwp_cond_broadcast, sys_lwp_cond_broadcast), /* 172 */
10960 SOLXY(__NR_pread, sys_pread), /* 173 */
10961 SOLX_(__NR_pwrite, sys_pwrite), /* 174 */
10962#if defined(VGP_x86_solaris)
10963 PLAX_(__NR_llseek, sys_llseek32), /* 175 */
10964#endif /* VGP_x86_solaris */
Elliott Hughesed398002017-06-21 14:41:24 -070010965 SOLXY(__NR_lgrpsys, sys_lgrpsys), /* 180 */
sewardj8eb8bab2015-07-21 14:44:28 +000010966 SOLXY(__NR_rusagesys, sys_rusagesys), /* 181 */
10967 SOLXY(__NR_port, sys_port), /* 182 */
10968 SOLXY(__NR_pollsys, sys_pollsys), /* 183 */
10969 SOLXY(__NR_labelsys, sys_labelsys), /* 184 */
10970 SOLXY(__NR_acl, sys_acl), /* 185 */
10971 SOLXY(__NR_auditsys, sys_auditsys), /* 186 */
10972 SOLX_(__NR_p_online, sys_p_online), /* 189 */
10973 SOLX_(__NR_sigqueue, sys_sigqueue), /* 190 */
Elliott Hughesed398002017-06-21 14:41:24 -070010974 SOLXY(__NR_clock_gettime, sys_clock_gettime), /* 191 */
sewardj8eb8bab2015-07-21 14:44:28 +000010975 SOLX_(__NR_clock_settime, sys_clock_settime), /* 192 */
10976 SOLXY(__NR_clock_getres, sys_clock_getres), /* 193 */
10977 SOLXY(__NR_timer_create, sys_timer_create), /* 194 */
10978 SOLX_(__NR_timer_delete, sys_timer_delete), /* 195 */
10979 SOLXY(__NR_timer_settime, sys_timer_settime), /* 196 */
10980 SOLXY(__NR_timer_gettime, sys_timer_gettime), /* 197 */
10981 SOLX_(__NR_timer_getoverrun, sys_timer_getoverrun), /* 198 */
10982 GENXY(__NR_nanosleep, sys_nanosleep), /* 199 */
10983 SOLXY(__NR_facl, sys_facl), /* 200 */
10984 SOLXY(__NR_door, sys_door), /* 201 */
10985 GENX_(__NR_setreuid, sys_setreuid), /* 202 */
10986 GENX_(__NR_setregid, sys_setregid), /* 202 */
10987 SOLXY(__NR_schedctl, sys_schedctl), /* 206 */
iraisr7d4aa192015-10-12 19:10:42 +000010988 SOLXY(__NR_pset, sys_pset), /* 207 */
sewardj8eb8bab2015-07-21 14:44:28 +000010989 SOLXY(__NR_resolvepath, sys_resolvepath), /* 209 */
10990 SOLXY(__NR_lwp_mutex_timedlock, sys_lwp_mutex_timedlock), /* 210 */
10991 SOLXY(__NR_lwp_sema_timedwait, sys_lwp_sema_timedwait), /* 211 */
10992 SOLXY(__NR_lwp_rwlock_sys, sys_lwp_rwlock_sys), /* 212 */
10993#if defined(VGP_x86_solaris)
10994 GENXY(__NR_getdents64, sys_getdents64), /* 213 */
10995 PLAX_(__NR_mmap64, sys_mmap64), /* 214 */
10996#if defined(SOLARIS_OLD_SYSCALLS)
10997 PLAXY(__NR_stat64, sys_stat64), /* 215 */
10998 PLAXY(__NR_lstat64, sys_lstat64), /* 216 */
10999 PLAXY(__NR_fstat64, sys_fstat64), /* 217 */
11000#endif /* SOLARIS_OLD_SYSCALLS */
11001 PLAXY(__NR_statvfs64, sys_statvfs64), /* 218 */
11002 PLAXY(__NR_fstatvfs64, sys_fstatvfs64), /* 219 */
11003#endif /* VGP_x86_solaris */
11004#if defined(VGP_x86_solaris)
11005 PLAX_(__NR_setrlimit64, sys_setrlimit64), /* 220 */
11006 PLAXY(__NR_getrlimit64, sys_getrlimit64), /* 221 */
11007 PLAXY(__NR_pread64, sys_pread64), /* 222 */
11008 PLAX_(__NR_pwrite64, sys_pwrite64), /* 223 */
11009#if defined(SOLARIS_OLD_SYSCALLS)
11010 PLAXY(__NR_open64, sys_open64), /* 225 */
11011#endif /* SOLARIS_OLD_SYSCALLS */
11012#endif /* VGP_x86_solaris */
11013 SOLXY(__NR_zone, sys_zone), /* 227 */
11014 SOLXY(__NR_getcwd, sys_getcwd), /* 229 */
11015 SOLXY(__NR_so_socket, sys_so_socket), /* 230 */
11016 SOLXY(__NR_so_socketpair, sys_so_socketpair), /* 231 */
11017 SOLX_(__NR_bind, sys_bind), /* 232 */
11018 SOLX_(__NR_listen, sys_listen), /* 233 */
11019 SOLXY(__NR_accept, sys_accept), /* 234 */
11020 SOLX_(__NR_connect, sys_connect), /* 235 */
11021 SOLX_(__NR_shutdown, sys_shutdown), /* 236 */
11022 SOLXY(__NR_recv, sys_recv), /* 237 */
11023 SOLXY(__NR_recvfrom, sys_recvfrom), /* 238 */
11024 SOLXY(__NR_recvmsg, sys_recvmsg), /* 239 */
11025 SOLX_(__NR_send, sys_send), /* 240 */
11026 SOLX_(__NR_sendmsg, sys_sendmsg), /* 241 */
11027 SOLX_(__NR_sendto, sys_sendto), /* 242 */
11028 SOLXY(__NR_getpeername, sys_getpeername), /* 243 */
11029 SOLXY(__NR_getsockname, sys_getsockname), /* 244 */
11030 SOLXY(__NR_getsockopt, sys_getsockopt), /* 245 */
11031 SOLX_(__NR_setsockopt, sys_setsockopt), /* 246 */
11032 SOLX_(__NR_lwp_mutex_register, sys_lwp_mutex_register), /* 252 */
11033 SOLXY(__NR_uucopy, sys_uucopy), /* 254 */
11034 SOLX_(__NR_umount2, sys_umount2) /* 255 */
11035};
11036
11037static SyscallTableEntry fasttrap_table[] = {
11038 SOLX_(__NR_gethrtime, fast_gethrtime), /* 3 */
11039 SOLX_(__NR_gethrvtime, fast_gethrvtime), /* 4 */
Elliott Hughesed398002017-06-21 14:41:24 -070011040 SOLX_(__NR_gethrestime, fast_gethrestime), /* 5 */
11041 SOLX_(__NR_getlgrp, fast_getlgrp) /* 6 */
sewardj8eb8bab2015-07-21 14:44:28 +000011042#if defined(SOLARIS_GETHRT_FASTTRAP)
11043 ,
11044 SOLXY(__NR_gethrt, fast_gethrt) /* 7 */
11045#endif /* SOLARIS_GETHRT_FASTTRAP */
11046#if defined(SOLARIS_GETZONEOFFSET_FASTTRAP)
11047 ,
11048 SOLXY(__NR_getzoneoffset, fast_getzoneoffset) /* 8 */
11049#endif /* SOLARIS_GETZONEOFFSET_FASTTRAP */
11050
11051};
11052
11053SyscallTableEntry *ML_(get_solaris_syscall_entry)(UInt sysno)
11054{
11055 const UInt syscall_table_size
11056 = sizeof(syscall_table) / sizeof(syscall_table[0]);
11057 const UInt fasttrap_table_size
11058 = sizeof(fasttrap_table) / sizeof(fasttrap_table[0]);
11059
11060 SyscallTableEntry *table;
11061 Int size;
11062
11063 switch (VG_SOLARIS_SYSNO_CLASS(sysno)) {
11064 case VG_SOLARIS_SYSCALL_CLASS_CLASSIC:
11065 table = syscall_table;
11066 size = syscall_table_size;
11067 break;
11068 case VG_SOLARIS_SYSCALL_CLASS_FASTTRAP:
11069 table = fasttrap_table;
11070 size = fasttrap_table_size;
11071 break;
11072 default:
11073 vg_assert(0);
11074 break;
11075 }
11076 sysno = VG_SOLARIS_SYSNO_INDEX(sysno);
11077 if (sysno < size) {
11078 SyscallTableEntry *sys = &table[sysno];
11079 if (!sys->before)
11080 return NULL; /* no entry */
11081 return sys;
11082 }
11083
11084 /* Can't find a wrapper. */
11085 return NULL;
11086}
11087
11088#endif // defined(VGO_solaris)
11089
11090/*--------------------------------------------------------------------*/
11091/*--- end ---*/
11092/*--------------------------------------------------------------------*/