1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Wrappers for generic Unix system calls ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- syswrap-generic.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2000-2011 Julian Seward 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) || defined(VGO_darwin) 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h" 37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h" // VG_(di_notify_*) 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h" // VG_(discard_translations) 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h" // VG_(brk_base), VG_(brk_limit) 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_errormgr.h" 46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_gdbserver.h" // VG_(gdbserver) 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcfile.h" 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h" 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" // VG_(get_SP) 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h" 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h" 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)() 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h" 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_ume.h" 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_types_n_macros.h" 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-generic.h" 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h" 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Returns True iff address range is something the client can 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown plausibly mess with: all of it is either already belongs to the 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client or is free or a reservation. */ 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(valid_client_addr)(Addr start, SizeT size, ThreadId tid, 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char *syscallname) 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ret; 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (size == 0) 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = VG_(am_is_valid_for_client_or_free_or_resvn) 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (start,size,VKI_PROT_NONE); 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%s: test=%#lx-%#lx ret=%d\n", 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscallname, start, start+size-1, (Int)ret); 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ret && syscallname != NULL) { 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried " 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "to modify addresses %#lx-%#lx\n", 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscallname, start, start+size-1); 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) { 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(client_signal_OK)(Int sigNo) 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* signal 0 is OK for kill */ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ret = sigNo >= 0 && sigNo <= VG_SIGVGRTUSERMAX; 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_(printf)("client_signal_OK(%d) -> %d\n", sigNo, ret); 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handy small function to help stop wrappers from segfaulting when 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown presented with bogus client addresses. Is not used for generating 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown user-visible errors. */ 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(safe_to_deref) ( void* start, SizeT size ) 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(am_is_valid_for_client)( (Addr)start, size, VKI_PROT_READ ); 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Doing mmap, mremap 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation, 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown munmap, mprotect (and mremap??) work at the page level. So addresses 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and lengths must be adjusted for this. */ 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mash around start and length so that the area exactly covers 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown an integral number of pages. If we don't do that, memcheck's 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown idea of addressible memory diverges from that of the 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel's, which causes the leak detector to crash. */ 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid page_align_addr_and_len( Addr* a, SizeT* len) 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ra; 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ra = VG_PGROUNDDN(*a); 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *len = VG_PGROUNDUP(*a + *len) - ra; 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *a = ra; 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void notify_core_of_mmap(Addr a, SizeT len, UInt prot, 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt flags, Int fd, Off64T offset) 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool d; 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 'a' is the return value from a real kernel mmap, hence: */ 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(a)); 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* whereas len is whatever the syscall supplied. So: */ 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len = VG_PGROUNDUP(len); 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = VG_(am_notify_client_mmap)( a, len, prot, flags, fd, offset ); 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)a, (ULong)len, 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "notify_core_of_mmap" ); 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, ULong di_handle) 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 164f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov SizeT fourgig = (1ULL << 32); 165f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov SizeT guardpage = 10 * fourgig; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool rr, ww, xx; 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 'a' is the return value from a real kernel mmap, hence: */ 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(a)); 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* whereas len is whatever the syscall supplied. So: */ 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len = VG_PGROUNDUP(len); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rr = toBool(prot & VKI_PROT_READ); 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ww = toBool(prot & VKI_PROT_WRITE); 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xx = toBool(prot & VKI_PROT_EXEC); 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 177f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#ifdef VGA_amd64 178f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov if (len >= fourgig + 2 * guardpage) { 179f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(printf)("Valgrind: ignoring NaCl's mmap(84G)\n"); 180f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov return; 181f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 182f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#endif // VGA_amd64 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_mmap, a, len, rr, ww, xx, di_handle ); 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* When a client mmap has been successfully done, this function must 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be called. It notifies both aspacem and the tool of the new 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mapping. 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown JRS 2008-Aug-14: But notice this is *very* obscure. The only place 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it is called from is POST(sys_io_setup). In particular, 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(generic_PRE_sys_mmap), in m_syswrap, is the "normal case" handler for 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client mmap. But it doesn't call this function; instead it does the 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown relevant notifications itself. Here, we just pass di_handle=0 to 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notify_tool_of_mmap as we have no better information. But really this 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown function should be done away with; problem is I don't understand what 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST(sys_io_setup) does or how it works. 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [However, this function is used lots for Darwin, because 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(generic_PRE_sys_mmap) cannot be used for Darwin.] 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(notify_core_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot, 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt flags, Int fd, Off64T offset ) 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX: unlike the other notify_core_and_tool* functions, this one doesn't 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // do anything with debug info (ie. it doesn't call VG_(di_notify_mmap)). 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Should it? --njn 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notify_core_of_mmap(a, len, prot, flags, fd, offset); 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notify_tool_of_mmap(a, len, prot, 0/*di_handle*/); 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(notify_core_and_tool_of_munmap) ( Addr a, SizeT len ) 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool d; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown page_align_addr_and_len(&a, &len); 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = VG_(am_notify_munmap)(a, len); 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( die_mem_munmap, a, len ); 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(di_notify_munmap)( a, len ); 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)a, (ULong)len, 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ML_(notify_core_and_tool_of_munmap)" ); 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(notify_core_and_tool_of_mprotect) ( Addr a, SizeT len, Int prot ) 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool rr = toBool(prot & VKI_PROT_READ); 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ww = toBool(prot & VKI_PROT_WRITE); 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool xx = toBool(prot & VKI_PROT_EXEC); 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool d; 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown page_align_addr_and_len(&a, &len); 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = VG_(am_notify_mprotect)(a, len, prot); 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx ); 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(di_notify_mprotect)( a, len, prot ); 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)a, (ULong)len, 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ML_(notify_core_and_tool_of_mprotect)" ); 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_MREMAP 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Expand (or shrink) an existing mapping, potentially moving it at 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the same time (controlled by the MREMAP_MAYMOVE flag). Nightmare. 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes do_mremap( Addr old_addr, SizeT old_len, 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr new_addr, SizeT new_len, 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord flags, ThreadId tid ) 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define MIN_SIZET(_aa,_bb) (_aa) < (_bb) ? (_aa) : (_bb) 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok, d; 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* old_seg; 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr advised; 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool f_fixed = toBool(flags & VKI_MREMAP_FIXED); 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool f_maymove = toBool(flags & VKI_MREMAP_MAYMOVE); 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("do_remap (old %#lx %ld) (new %#lx %ld) %s %s\n", 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_addr,old_len,new_addr,new_len, 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flags & VKI_MREMAP_MAYMOVE ? "MAYMOVE" : "", 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flags & VKI_MREMAP_FIXED ? "FIXED" : ""); 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_show_nsegments)(0, "do_remap: before"); 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (flags & ~(VKI_MREMAP_FIXED | VKI_MREMAP_MAYMOVE)) 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_IS_PAGE_ALIGNED(old_addr)) 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_len = VG_PGROUNDUP(old_len); 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_len = VG_PGROUNDUP(new_len); 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_len == 0) 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* kernel doesn't reject this, but we do. */ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old_len == 0) 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* reject wraparounds */ 289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (old_addr + old_len < old_addr) 290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov goto eINVAL; 291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (f_fixed == True && new_addr + new_len < new_len) 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* kernel rejects all fixed, no-move requests (which are 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown meaningless). */ 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f_fixed == True && f_maymove == False) 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Stay away from non-client areas. */ 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(valid_client_addr)(old_addr, old_len, tid, "mremap(old_addr)")) 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* In all remaining cases, if the old range does not fall within a 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown single segment, fail. */ 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_seg = VG_(am_find_nsegment)( old_addr ); 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old_addr < old_seg->start || old_addr+old_len-1 > old_seg->end) 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old_seg->kind != SkAnonC && old_seg->kind != SkFileC) 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(old_len > 0); 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(new_len > 0); 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(old_len)); 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(new_len)); 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(old_addr)); 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There are 3 remaining cases: 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * maymove == False 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new space has to be at old address, so: 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - shrink -> unmap end 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - same size -> do nothing 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - grow -> if can grow in-place, do so, else fail 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * maymove == True, fixed == False 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new space can be anywhere, so: 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - shrink -> unmap end 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - same size -> do nothing 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - grow -> if can grow in-place, do so, else 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown move to anywhere large enough, else fail 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * maymove == True, fixed == True 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new space must be at new address, so: 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if new address is not page aligned, fail 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if new address range overlaps old one, fail 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if new address range cannot be allocated, fail 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - else move to new address range with new size 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - else fail 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f_maymove == False) { 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* new space has to be at old address */ 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_len < old_len) 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto shrink_in_place; 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_len > old_len) 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto grow_in_place_or_fail; 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto same_in_place; 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f_maymove == True && f_fixed == False) { 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* new space can be anywhere */ 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_len < old_len) 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto shrink_in_place; 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_len > old_len) 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto grow_in_place_or_move_anywhere_or_fail; 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto same_in_place; 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f_maymove == True && f_fixed == True) { 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* new space can only be at the new address */ 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_IS_PAGE_ALIGNED(new_addr)) 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_addr+new_len-1 < old_addr || new_addr > old_addr+old_len-1) { 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no overlap */ 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_addr == 0) 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(am_get_advisory_client_simple) interprets zero to mean 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-fixed, which is not what we want */ 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown advised = VG_(am_get_advisory_client_simple)(new_addr, new_len, &ok); 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok || advised != new_addr) 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eNOMEM; 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(am_relocate_nooverlap_client) 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( &d, old_addr, old_len, new_addr, new_len ); 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( copy_mem_remap, old_addr, new_addr, 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MIN_SIZET(old_len,new_len) ); 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_len > old_len) 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len, 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_seg->hasR, old_seg->hasW, old_seg->hasX, 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0/*di_handle*/ ); 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK(die_mem_munmap, old_addr, old_len); 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) { 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( old_addr, old_len, "do_remap(1)" ); 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( new_addr, new_len, "do_remap(2)" ); 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( new_addr ); 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eNOMEM; 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* end of the 3 cases */ 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ vg_assert(0); 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown grow_in_place_or_move_anywhere_or_fail: 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* try growing it in-place */ 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr needA = old_addr + old_len; 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSizeT needL = new_len - old_len; 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(needL > 0); 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (needA == 0) 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(am_get_advisory_client_simple) interprets zero to mean 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-fixed, which is not what we want */ 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok ); 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(am_get_advisory_client_simple) (first arg == 0, meaning 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this-or-nothing) is too lenient, and may allow us to trash 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the next segment along. So make very sure that the proposed 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new area really is free. This is perhaps overly 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown conservative, but it fixes #129866. */ 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* segLo = VG_(am_find_nsegment)( needA ); 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* segHi = VG_(am_find_nsegment)( needA + needL - 1 ); 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segLo == NULL || segHi == NULL 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || segLo != segHi || segLo->kind != SkFree) 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = False; 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok && advised == needA) { 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(am_extend_map_client)( &d, (NSegment*)old_seg, needL ); 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_mmap, needA, needL, 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_seg->hasR, 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_seg->hasW, old_seg->hasX, 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0/*di_handle*/ ); 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( needA, needL, "do_remap(3)" ); 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( old_addr ); 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* that failed. Look elsewhere. */ 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown advised = VG_(am_get_advisory_client_simple)( 0, new_len, &ok ); 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool oldR = old_seg->hasR; 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool oldW = old_seg->hasW; 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool oldX = old_seg->hasX; 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assert new area does not overlap old */ 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(advised+new_len-1 < old_addr 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || advised > old_addr+old_len-1); 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(am_relocate_nooverlap_client) 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( &d, old_addr, old_len, advised, new_len ); 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( copy_mem_remap, old_addr, advised, 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MIN_SIZET(old_len,new_len) ); 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_len > old_len) 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len, 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oldR, oldW, oldX, 0/*di_handle*/ ); 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK(die_mem_munmap, old_addr, old_len); 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) { 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( old_addr, old_len, "do_remap(4)" ); 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( advised, new_len, "do_remap(5)" ); 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( advised ); 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eNOMEM; 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ vg_assert(0); 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown grow_in_place_or_fail: 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr needA = old_addr + old_len; 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT needL = new_len - old_len; 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (needA == 0) 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eINVAL; 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(am_get_advisory_client_simple) interprets zero to mean 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-fixed, which is not what we want */ 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok ); 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(am_get_advisory_client_simple) (first arg == 0, meaning 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this-or-nothing) is too lenient, and may allow us to trash 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the next segment along. So make very sure that the proposed 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new area really is free. */ 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* segLo = VG_(am_find_nsegment)( needA ); 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* segHi = VG_(am_find_nsegment)( needA + needL - 1 ); 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segLo == NULL || segHi == NULL 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || segLo != segHi || segLo->kind != SkFree) 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = False; 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok || advised != needA) 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eNOMEM; 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(am_extend_map_client)( &d, (NSegment*)old_seg, needL ); 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto eNOMEM; 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_mmap, needA, needL, 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_seg->hasR, old_seg->hasW, old_seg->hasX, 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0/*di_handle*/ ); 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( needA, needL, "do_remap(6)" ); 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( old_addr ); 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ vg_assert(0); 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shrink_in_place: 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres = VG_(am_munmap_client)( &d, old_addr+new_len, old_len-new_len ); 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sres; 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( die_mem_munmap, old_addr+new_len, old_len-new_len ); 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( old_addr+new_len, old_len-new_len, 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "do_remap(7)" ); 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( old_addr ); 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ vg_assert(0); 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown same_in_place: 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)( old_addr ); 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ vg_assert(0); 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eINVAL: 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eNOMEM: 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_ENOMEM ); 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef MIN_SIZET 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* HAVE_MREMAP */ 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown File-descriptor tracking 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* One of these is allocated for each open file descriptor. */ 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct OpenFd 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fd; /* The file descriptor */ 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *pathname; /* NULL if not a regular file or unknown */ 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext *where; /* NULL if inherited from parent */ 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct OpenFd *next, *prev; 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} OpenFd; 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* List of allocated file descriptors. */ 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic OpenFd *allocated_fds = NULL; 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Count of open file descriptors. */ 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int fd_count = 0; 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note the fact that a file descriptor was just closed. */ 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid record_fd_close(Int fd) 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OpenFd *i = allocated_fds; 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fd >= VG_(fd_hard_limit)) 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* Valgrind internal */ 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(i) { 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(i->fd == fd) { 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(i->prev) 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->prev->next = i->next; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated_fds = i->next; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(i->next) 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->next->prev = i->prev; 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(i->pathname) 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free) (VG_AR_CORE, i->pathname); 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free) (VG_AR_CORE, i); 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd_count--; 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = i->next; 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note the fact that a file descriptor was just opened. If the 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid is -1, this indicates an inherited fd. If the pathname is NULL, 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this either indicates a non-standard file (i.e. a pipe or socket or 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown some such thing) or that we don't know the filename. If the fd is 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown already open, then we're probably doing a dup2() to an existing fd, 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so just overwrite the existing one. */ 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd, char *pathname) 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OpenFd *i; 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fd >= VG_(fd_hard_limit)) 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* Valgrind internal */ 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check to see if this fd is already open. */ 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = allocated_fds; 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i) { 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i->fd == fd) { 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname); 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = i->next; 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not already one: allocate an OpenFd */ 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i == NULL) { 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = VG_(arena_malloc)(VG_AR_CORE, "syswrap.rfdowgn.1", sizeof(OpenFd)); 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->prev = NULL; 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->next = allocated_fds; 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(allocated_fds) allocated_fds->prev = i; 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated_fds = i; 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd_count++; 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->fd = fd; 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->pathname = VG_(arena_strdup)(VG_AR_CORE, "syswrap.rfdowgn.2", pathname); 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Record opening of an fd, and find its name. 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(record_fd_open_named)(ThreadId tid, Int fd) 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static HChar buf[VKI_PATH_MAX]; 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* name; 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX)) 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name = buf; 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name = NULL; 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_with_given_name)(tid, fd, name); 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Record opening of a nameless fd. 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(record_fd_open_nameless)(ThreadId tid, Int fd) 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_with_given_name)(tid, fd, NULL); 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *unix2name(struct vki_sockaddr_un *sa, UInt len, Char *name) 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sa == NULL || len == 0 || sa->sun_path[0] == '\0') { 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(name, "<unknown>"); 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(name, "%s", sa->sun_path); 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return name; 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *inet2name(struct vki_sockaddr_in *sa, UInt len, Char *name) 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sa == NULL || len == 0) { 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(name, "<unknown>"); 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt addr = VG_(ntohl)(sa->sin_addr.s_addr); 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (addr == 0) { 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(name, "<unbound>"); 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(name, "%u.%u.%u.%u:%u", 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (addr>>24) & 0xFF, (addr>>16) & 0xFF, 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (addr>>8) & 0xFF, addr & 0xFF, 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(ntohs)(sa->sin_port)); 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return name; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Try get some details about a socket. 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browngetsockdetails(Int fd) 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union u { 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr a; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr_in in; 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr_un un; 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } laddr; 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt llen; 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown llen = sizeof(laddr); 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&laddr, 0, llen); 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) { 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(laddr.a.sa_family) { 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_AF_INET: { 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static char lname[32]; 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static char pname[32]; 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr_in paddr; 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt plen = sizeof(struct vki_sockaddr_in); 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) { 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s\n", fd, 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inet2name(&(laddr.in), llen, lname), 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inet2name(&paddr, plen, pname)); 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound\n", 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd, inet2name(&(laddr.in), llen, lname)); 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_AF_UNIX: { 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static char lname[256]; 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s\n", fd, 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unix2name(&(laddr.un), llen, lname)); 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:\n", 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown laddr.a.sa_family, fd); 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Open socket %d:\n", fd); 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Dump out a summary, and a more detailed list, of open file descriptors. */ 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(show_open_fds) (void) 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OpenFd *i = allocated_fds; 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open at exit.\n", fd_count); 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i) { 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i->pathname) { 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s\n", i->fd, 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i->pathname); 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int val; 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt len = sizeof(val); 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(getsockopt)(i->fd, VKI_SOL_SOCKET, VKI_SO_TYPE, &val, &len) 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == -1) { 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Open file descriptor %d:\n", i->fd); 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getsockdetails(i->fd); 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(i->where) { 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)(i->where); 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, " <inherited from parent>\n"); 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = i->next; 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If /proc/self/fd doesn't exist (e.g. you've got a Linux kernel that doesn't 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have /proc support compiled in, or a non-Linux kernel), then we need to 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown find out what file descriptors we inherited from our parent process the 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hard way - by checking each fd in turn. */ 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid init_preopened_fds_without_proc_self_fd(void) 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_rlimit lim; 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt count; 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) { 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Hmm. getrlimit() failed. Now we're screwed, so just choose 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown an arbitrarily high number. 1024 happens to be the limit in 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the 2.4 Linux kernels. */ 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown count = 1024; 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown count = lim.rlim_cur; 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < count; i++) 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(fcntl)(i, VKI_F_GETFL, 0) != -1) 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_named)(-1, i); 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialize the list of open file descriptors with the file descriptors 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we inherited from out parent process. */ 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(init_preopened_fds)(void) 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// DDD: should probably use HAVE_PROC here or similar, instead. 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ret; 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_dirent d; 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes f; 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0); 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(f)) { 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_preopened_fds_without_proc_self_fd(); 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ((ret = VG_(getdents)(sr_Res(f), &d, sizeof(d))) != 0) { 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == -1) 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) { 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* s; 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fno = VG_(strtoll10)(d.d_name, &s); 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*s == '\0') { 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fno != sr_Res(f)) 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_named)(-1, fno); 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Warning: invalid file name in /proc/self/fd: %s\n", 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d.d_name); 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(lseek)(sr_Res(f), d.d_off, VKI_SEEK_SET); 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out: 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(sr_Res(f)); 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_preopened_fds_without_proc_self_fd(); 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *strdupcat ( HChar* cc, const Char *s1, const Char *s2, ArenaId aid ) 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1; 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *result = VG_(arena_malloc) ( aid, cc, len ); 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy) ( result, s1 ); 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcat) ( result, s2 ); 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return result; 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pre_mem_read_sendmsg ( ThreadId tid, Bool read, 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *msg, Addr base, SizeT size ) 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *outmsg = strdupcat ( "di.syswrap.pmrs.1", 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.sendmsg", msg, VG_AR_CORE ); 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, base, size ); 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free) ( VG_AR_CORE, outmsg ); 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pre_mem_write_recvmsg ( ThreadId tid, Bool read, 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *msg, Addr base, SizeT size ) 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *outmsg = strdupcat ( "di.syswrap.pmwr.1", 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.recvmsg", msg, VG_AR_CORE ); 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( read ) 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, base, size ); 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( outmsg, base, size ); 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free) ( VG_AR_CORE, outmsg ); 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid post_mem_write_recvmsg ( ThreadId tid, Bool read, 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *fieldName, Addr base, SizeT size ) 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( !read ) 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( base, size ); 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid msghdr_foreachfield ( 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid, 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_msghdr *msg, 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void (*foreach_func)( ThreadId, Bool, Char *, Addr, SizeT ) 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( !msg ) 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_name, sizeof( msg->msg_name ) ); 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_namelen, sizeof( msg->msg_namelen ) ); 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iov, sizeof( msg->msg_iov ) ); 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iovlen, sizeof( msg->msg_iovlen ) ); 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_control, sizeof( msg->msg_control ) ); 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_controllen, sizeof( msg->msg_controllen ) ); 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, False, "(msg)", (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) ); 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( msg->msg_name ) 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, False, 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(msg.msg_name)", 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)msg->msg_name, msg->msg_namelen ); 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( msg->msg_iov ) { 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_iovec *iov = msg->msg_iov; 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, True, 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(msg.msg_iov)", 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)iov, msg->msg_iovlen * sizeof( struct vki_iovec ) ); 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for ( i = 0; i < msg->msg_iovlen; ++i, ++iov ) 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, False, 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(msg.msg_iov[i])", 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)iov->iov_base, iov->iov_len ); 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( msg->msg_control ) 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown foreach_func ( tid, False, 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(msg.msg_control)", 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)msg->msg_control, msg->msg_controllen ); 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg) 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_cmsghdr *cm = VKI_CMSG_FIRSTHDR(msg); 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (cm) { 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cm->cmsg_level == VKI_SOL_SOCKET && 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cm->cmsg_type == VKI_SCM_RIGHTS ) { 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int *fds = (Int *) VKI_CMSG_DATA(cm); 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fdc = (cm->cmsg_len - VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr))) 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown / sizeof(int); 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < fdc; i++) 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if(VG_(clo_track_fds)) 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX: must we check the range on these fds with 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ML_(fd_allowed)()? 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_named)(tid, fds[i]); 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cm = VKI_CMSG_NXTHDR(msg, cm); 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GrP kernel ignores sa_len (at least on Darwin); this checks the rest */ 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pre_mem_read_sockaddr ( ThreadId tid, 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *description, 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr *sa, UInt salen ) 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *outmsg; 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr_un* sun = (struct vki_sockaddr_un *)sa; 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr_in* sin = (struct vki_sockaddr_in *)sa; 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr_in6* sin6 = (struct vki_sockaddr_in6 *)sa; 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NULL/zero-length sockaddrs are legal */ 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( sa == NULL || salen == 0 ) return; 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown outmsg = VG_(arena_malloc) ( VG_AR_CORE, "di.syswrap.pmr_sockaddr.1", 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strlen)( description ) + 30 ); 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "sa_family" ); 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t)); 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sa->sa_family) { 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_AF_UNIX: 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "sun_path" ); 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( outmsg, (Addr) sun->sun_path ); 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme max of sun_len-2? what about nul char? 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_AF_INET: 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "sin_port" ); 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, (Addr) &sin->sin_port, sizeof (sin->sin_port) ); 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "sin_addr" ); 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, (Addr) &sin->sin_addr, sizeof (sin->sin_addr) ); 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_AF_INET6: 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "sin6_port" ); 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr) &sin6->sin6_port, sizeof (sin6->sin6_port) ); 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "sin6_flowinfo" ); 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr) &sin6->sin6_flowinfo, sizeof (sin6->sin6_flowinfo) ); 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "sin6_addr" ); 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr) &sin6->sin6_addr, sizeof (sin6->sin6_addr) ); 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "sin6_scope_id" ); 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr) &sin6->sin6_scope_id, sizeof (sin6->sin6_scope_id) ); 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf) ( outmsg, description, "" ); 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( outmsg, (Addr) sa, salen ); 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free) ( VG_AR_CORE, outmsg ); 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Dereference a pointer to a UInt. */ 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt deref_UInt ( ThreadId tid, Addr a, Char* s ) 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt* a_p = (UInt*)a; 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( s, (Addr)a_p, sizeof(UInt) ); 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a_p == NULL) 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return *a_p; 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(buf_and_len_pre_check) ( ThreadId tid, Addr buf_p, Addr buflen_p, 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* buf_s, Char* buflen_s ) 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(tdict).track_pre_mem_write) { 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s); 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (buflen_in > 0) { 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_pre_mem_write( 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in ); 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(buf_and_len_post_check) ( ThreadId tid, SysRes res, 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr buf_p, Addr buflen_p, Char* s ) 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res) && VG_(tdict).track_post_mem_write) { 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt buflen_out = deref_UInt( tid, buflen_p, s); 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (buflen_out > 0 && buf_p != (Addr)NULL) { 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out ); 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Data seg end, for brk() 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* +--------+------------+ 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | anon | resvn | 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown +--------+------------+ 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ^ ^ ^ 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | | boundary is page aligned 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | VG_(brk_limit) -- no alignment constraint 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(brk_base) -- page aligned -- does not move 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Both the anon part and the reservation part are always at least 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown one page. 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the new data segment end to NEWBRK. If this succeeds, return 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NEWBRK, else return the current data segment end. */ 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr do_brk ( Addr newbrk ) 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* aseg; 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* rseg; 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr newbrkP; 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT delta; 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debug = False; 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\ndo_brk: brk_base=%#lx brk_limit=%#lx newbrk=%#lx\n", 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(brk_base), VG_(brk_limit), newbrk); 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) show_segments("in_brk"); 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (newbrk < VG_(brk_base)) 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Clearly impossible. */ 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (newbrk >= VG_(brk_base) && newbrk < VG_(brk_limit)) { 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shrinking the data segment. Be lazy and don't munmap the 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown excess area. */ 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const * seg = VG_(am_find_nsegment)(newbrk); 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg && seg->hasT) 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( newbrk, VG_(brk_limit) - newbrk, 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "do_brk(shrink)" ); 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Since we're being lazy and not unmapping pages, we have to 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zero out the area, so that if the area later comes back into 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown circulation, it will be filled with zeroes, as if it really 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown had been unmapped and later remapped. Be a bit paranoid and 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown try hard to ensure we're not going to segfault by doing the 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown write - check both ends of the range are in the same segment 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and that segment is writable. */ 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg) { 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pre: newbrk < VG_(brk_limit) 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown => newbrk <= VG_(brk_limit)-1 */ 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const * seg2; 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(newbrk < VG_(brk_limit)); 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg2 = VG_(am_find_nsegment)( VG_(brk_limit)-1 ); 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg2 && seg == seg2 && seg->hasW) 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)( (void*)newbrk, 0, VG_(brk_limit) - newbrk ); 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(brk_limit) = newbrk; 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return newbrk; 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* otherwise we're expanding the brk segment. */ 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(brk_limit) > VG_(brk_base)) 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aseg = VG_(am_find_nsegment)( VG_(brk_limit)-1 ); 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aseg = VG_(am_find_nsegment)( VG_(brk_limit) ); 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rseg = VG_(am_next_nsegment)( (NSegment*)aseg, True/*forwards*/ ); 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* These should be assured by setup_client_dataseg in m_main. */ 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(aseg); 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(rseg); 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(aseg->kind == SkAnonC); 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(rseg->kind == SkResvn); 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(aseg->end+1 == rseg->start); 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(newbrk >= VG_(brk_base)); 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (newbrk <= rseg->start) { 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* still fits within the anon segment. */ 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(brk_limit) = newbrk; 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return newbrk; 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (newbrk > rseg->end+1 - VKI_PAGE_SIZE) { 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* request is too large -- the resvn would fall below 1 page, 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which isn't allowed. */ 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newbrkP = VG_PGROUNDUP(newbrk); 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(newbrkP > rseg->start && newbrkP <= rseg->end+1 - VKI_PAGE_SIZE); 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delta = newbrkP - rseg->start; 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(delta > 0); 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(delta)); 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(am_extend_into_adjacent_reservation_client)( (NSegment*)aseg, delta ); 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) goto bad; 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(brk_limit) = newbrk; 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return newbrk; 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad: 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(brk_limit); 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vet file descriptors for sanity 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown> - what does the "Bool soft" parameter mean? 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown(Tom Hughes, 3 Oct 05): 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWhether or not to consider a file descriptor invalid if it is above 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownthe current soft limit. 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBasically if we are testing whether a newly created file descriptor is 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvalid (in a post handler) then we set soft to true, and if we are 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntesting whether a file descriptor that is about to be used (in a pre 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownhandler) is valid [viz, an already-existing fd] then we set it to false. 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThe point is that if the (virtual) soft limit is lowered then any 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownexisting descriptors can still be read/written/closed etc (so long as 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownthey are below the valgrind reserved descriptors) but no new 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndescriptors can be created above the new soft limit. 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown(jrs 4 Oct 05: in which case, I've renamed it "isNewFd") 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return true if we're allowed to use or create this fd */ 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(fd_allowed)(Int fd, const Char *syscallname, ThreadId tid, Bool isNewFd) 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool allowed = True; 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* hard limits always apply */ 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fd < 0 || fd >= VG_(fd_hard_limit)) 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allowed = False; 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* hijacking the output fds is never allowed */ 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fd == VG_(log_output_sink).fd || fd == VG_(xml_output_sink).fd) 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allowed = False; 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* if creating a new fd (rather than using an existing one), the 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown soft limit must also be observed */ 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isNewFd && fd >= VG_(fd_soft_limit)) 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allowed = False; 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this looks like it ought to be included, but causes problems: */ 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fd == 2 && VG_(debugLog_getLevel)() > 0) 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allowed = False; 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The difficulty is as follows: consider a program P which expects 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to be able to mess with (redirect) its own stderr (fd 2). 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Usually to deal with P we would issue command line flags to send 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown logging somewhere other than stderr, so as not to disrupt P. 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The problem is that -d unilaterally hijacks stderr with no 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown consultation with P. And so, if this check is enabled, P will 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown work OK normally but fail if -d is issued. 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Basically -d is a hack and you take your chances when using it. 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown It's very useful for low level debugging -- particularly at 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown startup -- and having its presence change the behaviour of the 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client is exactly what we don't want. */ 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* croak? */ 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((!allowed) && VG_(showing_core_errors)() ) { 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Warning: invalid file descriptor %d in syscall %s()\n", 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd, syscallname); 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fd == VG_(log_output_sink).fd && VG_(log_output_sink).fd >= 0) 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " Use --log-fd=<number> to select an alternative log fd.\n"); 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fd == VG_(xml_output_sink).fd && VG_(xml_output_sink).fd >= 0) 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " Use --xml-fd=<number> to select an alternative XML " 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "output fd.\n"); 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: consider always printing this stack trace, it's useful. 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Also consider also making this a proper core error, ie. 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // suppressible and all that. 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) { 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return allowed; 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Deal with a bunch of socket-related syscalls 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_socketpair) ( ThreadId tid, 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg2, UWord arg3 ) 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int socketpair(int d, int type, int protocol, int sv[2]); */ 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "socketcall.socketpair(sv)", 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg3, 2*sizeof(int) ); 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_socketpair) ( ThreadId tid, 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res, 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg2, UWord arg3 ) 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes r = res; 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fd1 = ((Int*)arg3)[0]; 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fd2 = ((Int*)arg3)[1]; 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sr_isError(res)); /* guaranteed by caller */ 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( arg3, 2*sizeof(int) ); 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(fd1, "socketcall.socketpair", tid, True) || 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown !ML_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) { 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(fd1); 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(fd2); 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r = VG_(mk_SysRes_Error)( VKI_EMFILE ); 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( arg3, 2*sizeof(int) ); 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) { 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_nameless)(tid, fd1); 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_nameless)(tid, fd2); 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_socket) ( ThreadId tid, SysRes res ) 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes r = res; 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sr_isError(res)); /* guaranteed by caller */ 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(sr_Res(res), "socket", tid, True)) { 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(sr_Res(res)); 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r = VG_(mk_SysRes_Error)( VKI_EMFILE ); 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_nameless)(tid, sr_Res(res)); 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_bind) ( ThreadId tid, 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int bind(int sockfd, struct sockaddr *my_addr, 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int addrlen); */ 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pre_mem_read_sockaddr( 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, "socketcall.bind(my_addr.%s)", 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (struct vki_sockaddr *) arg1, arg2 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_accept) ( ThreadId tid, 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int accept(int s, struct sockaddr *addr, int *addrlen); */ 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addr_p = arg1; 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addrlen_p = arg2; 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (addr_p != (Addr)NULL) 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(buf_and_len_pre_check) ( tid, addr_p, addrlen_p, 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.accept(addr)", 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.accept(addrlen_in)" ); 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_accept) ( ThreadId tid, 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res, 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes r = res; 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sr_isError(res)); /* guaranteed by caller */ 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(sr_Res(res), "accept", tid, True)) { 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(sr_Res(res)); 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r = VG_(mk_SysRes_Error)( VKI_EMFILE ); 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addr_p = arg1; 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addrlen_p = arg2; 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (addr_p != (Addr)NULL) 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(buf_and_len_post_check) ( tid, res, addr_p, addrlen_p, 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.accept(addrlen_out)" ); 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_nameless)(tid, sr_Res(res)); 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_sendto) ( ThreadId tid, 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2, 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg3, UWord arg4, UWord arg5 ) 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int sendto(int s, const void *msg, int len, 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int flags, 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct sockaddr *to, int tolen); */ 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "socketcall.sendto(msg)", 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1, /* msg */ 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2 /* len */ ); 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pre_mem_read_sockaddr( 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, "socketcall.sendto(to.%s)", 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (struct vki_sockaddr *) arg4, arg5 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_send) ( ThreadId tid, 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int send(int s, const void *msg, size_t len, int flags); */ 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "socketcall.send(msg)", 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1, /* msg */ 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2 /* len */ ); 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_recvfrom) ( ThreadId tid, 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2, 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg3, UWord arg4, UWord arg5 ) 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int recvfrom(int s, void *buf, int len, unsigned int flags, 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct sockaddr *from, int *fromlen); */ 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr buf_p = arg1; 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len = arg2; 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr from_p = arg4; 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr fromlen_p = arg5; 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "socketcall.recvfrom(buf)", buf_p, len ); 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (from_p != (Addr)NULL) 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(buf_and_len_pre_check) ( tid, from_p, fromlen_p, 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.recvfrom(from)", 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.recvfrom(fromlen_in)" ); 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_recvfrom) ( ThreadId tid, 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res, 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2, 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg3, UWord arg4, UWord arg5 ) 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr buf_p = arg1; 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len = arg2; 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr from_p = arg4; 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr fromlen_p = arg5; 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sr_isError(res)); /* guaranteed by caller */ 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (from_p != (Addr)NULL) 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(buf_and_len_post_check) ( tid, res, from_p, fromlen_p, 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.recvfrom(fromlen_out)" ); 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( buf_p, len ); 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_recv) ( ThreadId tid, 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int recv(int s, void *buf, int len, unsigned int flags); */ 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* man 2 recv says: 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The recv call is normally used only on a connected socket 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (see connect(2)) and is identical to recvfrom with a NULL 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from parameter. 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "socketcall.recv(buf)", 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1, /* buf */ 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2 /* len */ ); 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_recv) ( ThreadId tid, 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord res, 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (res >= 0 && arg1 != 0) { 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( arg1, /* buf */ 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2 /* len */ ); 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_connect) ( ThreadId tid, 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int connect(int sockfd, 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct sockaddr *serv_addr, int addrlen ); */ 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pre_mem_read_sockaddr( tid, 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.connect(serv_addr.%s)", 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (struct vki_sockaddr *) arg1, arg2); 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_setsockopt) ( ThreadId tid, 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2, 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg3, UWord arg4 ) 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int setsockopt(int s, int level, int optname, 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const void *optval, int optlen); */ 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "socketcall.setsockopt(optval)", 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg3, /* optval */ 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg4 /* optlen */ ); 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_getsockname) ( ThreadId tid, 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int getsockname(int s, struct sockaddr* name, int* namelen) */ 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr name_p = arg1; 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr namelen_p = arg2; 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Nb: name_p cannot be NULL */ 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p, 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.getsockname(name)", 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.getsockname(namelen_in)" ); 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_getsockname) ( ThreadId tid, 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res, 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr name_p = arg1; 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr namelen_p = arg2; 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sr_isError(res)); /* guaranteed by caller */ 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p, 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.getsockname(namelen_out)" ); 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_getpeername) ( ThreadId tid, 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int getpeername(int s, struct sockaddr* name, int* namelen) */ 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr name_p = arg1; 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr namelen_p = arg2; 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Nb: name_p cannot be NULL */ 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p, 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.getpeername(name)", 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.getpeername(namelen_in)" ); 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_getpeername) ( ThreadId tid, 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res, 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr name_p = arg1; 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr namelen_p = arg2; 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sr_isError(res)); /* guaranteed by caller */ 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p, 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "socketcall.getpeername(namelen_out)" ); 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_sendmsg) ( ThreadId tid, 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1 ) 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int sendmsg(int s, const struct msghdr *msg, int flags); */ 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_msghdr *msg = (struct vki_msghdr *)arg1; 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg ); 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_recvmsg) ( ThreadId tid, 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1 ) 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int recvmsg(int s, struct msghdr *msg, int flags); */ 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_msghdr *msg = (struct vki_msghdr *)arg1; 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg ); 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_recvmsg) ( ThreadId tid, 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1 ) 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_msghdr *msg = (struct vki_msghdr *)arg1; 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown msghdr_foreachfield( tid, msg, post_mem_write_recvmsg ); 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_cmsg_for_fds( tid, msg ); 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Deal with a bunch of IPC related syscalls 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_semop) ( ThreadId tid, 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int semop(int semid, struct sembuf *sops, unsigned nsops); */ 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "semop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) ); 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_semtimedop) ( ThreadId tid, 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg2, UWord arg3 ) 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int semtimedop(int semid, struct sembuf *sops, unsigned nsops, 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timespec *timeout); */ 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "semtimedop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) ); 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg3 != 0) 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "semtimedop(timeout)", arg3, sizeof(struct vki_timespec) ); 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt get_sem_count( Int semid ) 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_semid_ds buf; 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union vki_semun arg; 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't actually seem to be necessary, but gcc-4.4.0 20081017 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (experimental) otherwise complains that the use in the return 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown statement below is uninitialised. */ 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf.sem_nsems = 0; 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg.buf = &buf; 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef __NR_semctl 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg); 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0, 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_IPC_STAT, (UWord)&arg); 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf.sem_nsems; 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_semctl) ( ThreadId tid, 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg2, UWord arg3 ) 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int semctl(int semid, int semnum, int cmd, ...); */ 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union vki_semun arg = *(union vki_semun *)&arg3; 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt nsems; 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (arg2 /* cmd */) { 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_INFO) 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_INFO: 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEM_INFO: 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_INFO|VKI_IPC_64: 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEM_INFO|VKI_IPC_64: 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)", 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)arg.buf, sizeof(struct vki_seminfo) ); 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_STAT: 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SEM_STAT) 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEM_STAT: 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)", 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)arg.buf, sizeof(struct vki_semid_ds) ); 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_STAT|VKI_IPC_64: 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SEM_STAT) 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEM_STAT|VKI_IPC_64: 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)", 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)arg.buf, sizeof(struct vki_semid64_ds) ); 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_SET: 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "semctl(IPC_SET, arg.buf)", 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)arg.buf, sizeof(struct vki_semid_ds) ); 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_SET|VKI_IPC_64: 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "semctl(IPC_SET, arg.buf)", 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)arg.buf, sizeof(struct vki_semid64_ds) ); 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_GETALL: 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_GETALL|VKI_IPC_64: 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nsems = get_sem_count( arg0 ); 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "semctl(IPC_GETALL, arg.array)", 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)arg.array, sizeof(unsigned short) * nsems ); 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SETALL: 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SETALL|VKI_IPC_64: 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nsems = get_sem_count( arg0 ); 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "semctl(IPC_SETALL, arg.array)", 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)arg.array, sizeof(unsigned short) * nsems ); 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_semctl) ( ThreadId tid, 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord res, 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg2, UWord arg3 ) 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union vki_semun arg = *(union vki_semun *)&arg3; 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt nsems; 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (arg2 /* cmd */) { 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_INFO) 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_INFO: 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEM_INFO: 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_INFO|VKI_IPC_64: 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEM_INFO|VKI_IPC_64: 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) ); 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_STAT: 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SEM_STAT) 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEM_STAT: 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid_ds) ); 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_STAT|VKI_IPC_64: 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SEM_STAT|VKI_IPC_64: 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid64_ds) ); 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_GETALL: 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_GETALL|VKI_IPC_64: 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nsems = get_sem_count( arg0 ); 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( (Addr)arg.array, sizeof(unsigned short) * nsems ); 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt get_shm_size ( Int shmid ) 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef __NR_shmctl 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef VKI_IPC_64 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_shmid64_ds buf; 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef VGP_amd64_linux 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* See bug 222545 comment 7 */ 1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, 1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_IPC_STAT, (UWord)&buf); 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_IPC_STAT|VKI_IPC_64, (UWord)&buf); 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else /* !def VKI_IPC_64 */ 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_shmid_ds buf; 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf); 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif /* def VKI_IPC_64 */ 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_shmid_ds buf; 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_IPC_STAT, 0, (UWord)&buf); 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(__res)) 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf.shm_segsz; 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_shmat) ( ThreadId tid, 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* void *shmat(int shmid, const void *shmaddr, int shmflg); */ 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt segmentSize = get_shm_size ( arg0 ); 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord tmp; 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg1 == 0) { 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* arm-linux only: work around the fact that 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_get_advisory_client_simple) produces something that is 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_PAGE_SIZE aligned, whereas what we want is something 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_SHMLBA aligned, and VKI_SHMLBA >= VKI_PAGE_SIZE. Hence 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown increase the request size by VKI_SHMLBA - VKI_PAGE_SIZE and 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then round the result up to the next VKI_SHMLBA boundary. 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown See bug 222545 comment 15. So far, arm-linux is the only 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platform where this is known to be necessary. */ 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VKI_SHMLBA >= VKI_PAGE_SIZE); 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VKI_SHMLBA > VKI_PAGE_SIZE) { 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segmentSize += VKI_SHMLBA - VKI_PAGE_SIZE; 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = VG_(am_get_advisory_client_simple)(0, segmentSize, &ok); 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VKI_SHMLBA > VKI_PAGE_SIZE) { 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1 = VG_ROUNDUP(tmp, VKI_SHMLBA); 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1 = tmp; 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (!ML_(valid_client_addr)(arg1, segmentSize, tid, "shmat")) 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1 = 0; 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return arg1; 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_shmat) ( ThreadId tid, 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord res, 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1785f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root UInt segmentSize = VG_PGROUNDUP(get_shm_size(arg0)); 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( segmentSize > 0 ) { 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt prot = VKI_PROT_READ|VKI_PROT_WRITE; 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool d; 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg2 & VKI_SHM_RDONLY) 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prot &= ~VKI_PROT_WRITE; 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It isn't exactly correct to pass 0 for the fd and offset 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown here. The kernel seems to think the corresponding section 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown does have dev/ino numbers: 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 04e52000-04ec8000 rw-s 00000000 00:06 1966090 /SYSV00000000 (deleted) 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown However there is no obvious way to find them. In order to 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cope with the discrepancy, aspacem's sync checker omits the 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dev/ino correspondence check in cases where V does not know 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the dev/ino. */ 1802f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root d = VG_(am_notify_client_shmat)( res, segmentSize, prot ); 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we don't distinguish whether it's read-only or 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * read-write -- it doesn't matter really. */ 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False, 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0/*di_handle*/ ); 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)res, 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)VG_PGROUNDUP(segmentSize), 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ML_(generic_POST_sys_shmat)" ); 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_shmdt) ( ThreadId tid, UWord arg0 ) 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int shmdt(const void *shmaddr); */ 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ML_(valid_client_addr)(arg0, 1, tid, "shmdt"); 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 ) 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* s = VG_(am_find_nsegment)(arg0); 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s != NULL) { 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr s_start = s->start; 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT s_len = s->end+1 - s->start; 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool d; 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(s->kind == SkShmC); 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(s->start == arg0); 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = VG_(am_notify_munmap)(s_start, s_len); 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s = NULL; /* s is now invalid */ 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( die_mem_munmap, s_start, s_len ); 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d) 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)s_start, 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)s_len, 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ML_(generic_POST_sys_shmdt)" ); 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */ 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_shmctl) ( ThreadId tid, 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* int shmctl(int shmid, int cmd, struct shmid_ds *buf); */ 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (arg1 /* cmd */) { 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_INFO) 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_INFO: 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)", 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, sizeof(struct vki_shminfo) ); 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_INFO|VKI_IPC_64: 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)", 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, sizeof(struct vki_shminfo64) ); 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SHM_INFO) 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SHM_INFO: 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SHM_INFO|VKI_IPC_64: 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "shmctl(SHM_INFO, buf)", 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, sizeof(struct vki_shm_info) ); 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_STAT: 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SHM_STAT) 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SHM_STAT: 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)", 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, sizeof(struct vki_shmid_ds) ); 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_STAT|VKI_IPC_64: 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SHM_STAT|VKI_IPC_64: 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "shmctl(IPC_STAT, arg.buf)", 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, sizeof(struct vki_shmid64_ds) ); 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_SET: 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)", 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, sizeof(struct vki_shmid_ds) ); 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_SET|VKI_IPC_64: 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)", 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, sizeof(struct vki_shmid64_ds) ); 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_shmctl) ( ThreadId tid, 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord res, 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg0, UWord arg1, UWord arg2 ) 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (arg1 /* cmd */) { 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_INFO) 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_INFO: 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) ); 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_INFO|VKI_IPC_64: 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) ); 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SHM_INFO) 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SHM_INFO: 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SHM_INFO|VKI_IPC_64: 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( arg2, sizeof(struct vki_shm_info) ); 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_STAT: 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SHM_STAT) 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SHM_STAT: 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) ); 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64) 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_IPC_STAT|VKI_IPC_64: 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_SHM_STAT|VKI_IPC_64: 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( arg2, sizeof(struct vki_shmid64_ds) ); 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Generic handler for mmap 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Although mmap is specified by POSIX and the argument are generally 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * consistent across platforms the precise details of the low level 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * argument passing conventions differ. For example: 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - On x86-linux there is mmap (aka old_mmap) which takes the 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * arguments in a memory block and the offset in bytes; and 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * mmap2 (aka sys_mmap2) which takes the arguments in the normal 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * way and the offset in pages. 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - On ppc32-linux there is mmap (aka sys_mmap) which takes the 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * arguments in the normal way and the offset in bytes; and 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * mmap2 (aka sys_mmap2) which takes the arguments in the normal 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * way and the offset in pages. 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - On amd64-linux everything is simple and there is just the one 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * call, mmap (aka sys_mmap) which takes the arguments in the 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * normal way and the offset in bytes. 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 1971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * - On s390x-linux there is mmap (aka old_mmap) which takes the 1972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * arguments in a memory block and the offset in bytes. mmap2 1973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * is also available (but not exported via unistd.h) with 1974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * arguments in a memory block and the offset in pages. 1975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * To cope with all this we provide a generic handler function here 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * and then each platform implements one or more system call handlers 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * which call this generic routine after extracting and normalising 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the arguments. 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_mmap) ( ThreadId tid, 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg1, UWord arg2, UWord arg3, 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg4, UWord arg5, Off64T arg6 ) 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr advised; 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MapRequest mreq; 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool mreq_ok; 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_darwin) 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: we can't use this on Darwin, it has races: 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // * needs to RETRY if advisory succeeds but map fails 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (could have been some other thread in a nonblocking call) 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // * needs to not use fixed-position mmap() on Darwin 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (mmap will cheerfully smash whatever's already there, which might 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // be a new mapping from some other thread in a nonblocking call) 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("can't use ML_(generic_PRE_sys_mmap) on Darwin"); 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg2 == 0) { 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SuSV3 says: If len is zero, mmap() shall fail and no mapping 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shall be established. */ 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_IS_PAGE_ALIGNED(arg1)) { 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* zap any misaligned addresses. */ 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SuSV3 says misaligned addresses only cause the MAP_FIXED case 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to fail. Here, we catch them all. */ 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_IS_PAGE_ALIGNED(arg6)) { 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* zap any misaligned offsets. */ 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SuSV3 says: The off argument is constrained to be aligned and 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sized according to the value returned by sysconf() when 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown passed _SC_PAGESIZE or _SC_PAGE_SIZE. */ 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out what kind of allocation constraints there are 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (fixed/hint/any), and ask aspacem what we should do. */ 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mreq.start = arg1; 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mreq.len = arg2; 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg4 & VKI_MAP_FIXED) { 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mreq.rkind = MFixed; 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg1 != 0) { 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mreq.rkind = MHint; 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mreq.rkind = MAny; 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Enquire ... */ 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok ); 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!mreq_ok) { 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Our request was bounced, so we'd better fail. */ 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Otherwise we're OK (so far). Install aspacem's choice of 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address, and let the mmap go through. */ 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3, 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg4 | VKI_MAP_FIXED, 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg5, arg6); 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* A refinement: it may be that the kernel refused aspacem's choice 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of address. If we were originally asked for a hinted mapping, 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown there is still a last chance: try again at any address. 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Hence: */ 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mreq.rkind == MHint && sr_isError(sres)) { 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mreq.start = 0; 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mreq.len = arg2; 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mreq.rkind = MAny; 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok ); 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!mreq_ok) { 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Our request was bounced, so we'd better fail. */ 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* and try again with the kernel */ 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3, 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg4 | VKI_MAP_FIXED, 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg5, arg6); 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(sres)) { 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong di_handle; 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Notify aspacem. */ 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notify_core_of_mmap( 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)sr_Res(sres), /* addr kernel actually assigned */ 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, /* length */ 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg3, /* prot */ 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg4, /* the original flags value */ 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg5, /* fd */ 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg6 /* offset */ 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Load symbols? */ 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di_handle = VG_(di_notify_mmap)( (Addr)sr_Res(sres), 2081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov False/*allow_SkFileV*/, (Int)arg5 ); 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Notify the tool. */ 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notify_tool_of_mmap( 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)sr_Res(sres), /* addr kernel actually assigned */ 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2, /* length */ 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg3, /* prot */ 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di_handle /* so the tool can refer to the read debuginfo later, 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if it wants. */ 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Stay sane */ 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(sres) && (arg4 & VKI_MAP_FIXED)) 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sr_Res(sres) == arg1); 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sres; 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The Main Entertainment ... syscall wrappers 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note: the PRE() and POST() wrappers are for the actual functions 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown implementing the system calls in the OS kernel. These mostly have 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown names like sys_write(); a few have names like old_mmap(). See the 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown comment for ML_(syscall_table)[] for important info about the __NR_foo 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown constants and their relationship to the sys_foo() functions. 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Some notes about names used for syscalls and args: 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - For the --trace-syscalls=yes output, we use the sys_foo() name to avoid 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ambiguity. 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - For error messages, we generally use a somewhat generic name 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the syscall (eg. "write" rather than "sys_write"). This should be 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown good enough for the average user to understand what is happening, 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown without confusing them with names like "sys_write". 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Also, for error messages the arg names are mostly taken from the man 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pages (even though many of those man pages are really for glibc 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown functions of the same name), rather than from the OS kernel source, 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the same reason -- a user presented with a "bogus foo(bar)" arg 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will most likely look at the "foo" man page to see which is the "bar" 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg. 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that we use our own vki_* types. The one exception is in 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READn calls, where pointer types haven't been changed, because 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they don't need to be -- eg. for "foo*" to be used, the type foo need not 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be visible. 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XXX: some of these are arch-specific, and should be factored out. 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PRE(name) DEFN_PRE_TEMPLATE(generic, name) 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define POST(name) DEFN_POST_TEMPLATE(generic, name) 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Macros to support 64-bit syscall args split into two 32 bit values 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VG_LITTLEENDIAN) 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64(lo,hi) ( ((ULong)(lo)) | (((ULong)(hi)) << 32) ) 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64_FIRST(name) name##_low 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64_SECOND(name) name##_high 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VG_BIGENDIAN) 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64(hi,lo) ( ((ULong)(lo)) | (((ULong)(hi)) << 32) ) 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64_FIRST(name) name##_high 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64_SECOND(name) name##_low 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error Unknown endianness 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_exit) 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* simple; just make this thread exit */ 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("exit( %ld )", ARG1); 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(void, "exit", int, status); 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set the thread's status to be exiting, then claim that the 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall succeeded. */ 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->exitreason = VgSrc_ExitThread; 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.exitcode = ARG1; 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Success(0); 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_ni_syscall) 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("unimplemented (by the kernel) syscall: %s! (ni_syscall)\n", 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_SYSNUM_STRING(SYSNO)); 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "ni_syscall"); 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_ENOSYS ); 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_iopl) 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_iopl ( %ld )", ARG1); 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "iopl", unsigned long, level); 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fsync) 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_fsync ( %ld )", ARG1); 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "fsync", unsigned int, fd); 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fdatasync) 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_fdatasync ( %ld )", ARG1); 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "fdatasync", unsigned int, fd); 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_msync) 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_msync ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3); 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "msync", 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, start, vki_size_t, length, int, flags); 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "msync(start)", ARG1, ARG2 ); 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Nb: getpmsg() and putpmsg() are special additional syscalls used in early 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// versions of LiS (Linux Streams). They are not part of the kernel. 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Therefore, we have to provide this type ourself, rather than getting it 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// from the kernel sources. 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct vki_pmsg_strbuf { 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int maxlen; /* no. of bytes in buffer */ 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int len; /* no. of bytes returned */ 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_caddr_t buf; /* pointer to data */ 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpmsg) 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */ 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pmsg_strbuf *ctrl; 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pmsg_strbuf *data; 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getpmsg ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ5(int, "getpmsg", 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int, fd, struct strbuf *, ctrl, struct strbuf *, data, 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int *, bandp, int *, flagsp); 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctrl = (struct vki_pmsg_strbuf *)ARG2; 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data = (struct vki_pmsg_strbuf *)ARG3; 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ctrl && ctrl->maxlen > 0) 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen); 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (data && data->maxlen > 0) 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen); 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG4) 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int)); 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG5) 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int)); 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getpmsg) 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pmsg_strbuf *ctrl; 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pmsg_strbuf *data; 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctrl = (struct vki_pmsg_strbuf *)ARG2; 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data = (struct vki_pmsg_strbuf *)ARG3; 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES == 0 && ctrl && ctrl->len > 0) { 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len); 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES == 0 && data && data->len > 0) { 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( (Addr)data->buf, data->len); 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_putpmsg) 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */ 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pmsg_strbuf *ctrl; 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pmsg_strbuf *data; 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_putpmsg ( %ld, %#lx, %#lx, %ld, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5); 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ5(int, "putpmsg", 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int, fd, struct strbuf *, ctrl, struct strbuf *, data, 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int, band, int, flags); 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ctrl = (struct vki_pmsg_strbuf *)ARG2; 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data = (struct vki_pmsg_strbuf *)ARG3; 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ctrl && ctrl->len > 0) 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len); 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (data && data->len > 0) 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len); 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getitimer) 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_itimerval *value = (struct vki_itimerval*)ARG2; 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getitimer ( %ld, %#lx )", ARG1, ARG2); 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value); 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_WRITE( "getitimer(&value->it_interval)", &(value->it_interval)); 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_WRITE( "getitimer(&value->it_value)", &(value->it_value)); 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getitimer) 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != (Addr)NULL) { 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_itimerval *value = (struct vki_itimerval*)ARG2; 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_timeval_WRITE( &(value->it_interval) ); 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_timeval_WRITE( &(value->it_value) ); 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setitimer) 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_setitimer ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); 2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "setitimer", 2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int, which, 2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct itimerval *, value, struct itimerval *, ovalue); 2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != (Addr)NULL) { 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_itimerval *value = (struct vki_itimerval*)ARG2; 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_READ( "setitimer(&value->it_interval)", 2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &(value->it_interval)); 2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_READ( "setitimer(&value->it_value)", 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &(value->it_value)); 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG3 != (Addr)NULL) { 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3; 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_WRITE( "setitimer(&ovalue->it_interval)", 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &(ovalue->it_interval)); 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_WRITE( "setitimer(&ovalue->it_value)", 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &(ovalue->it_value)); 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_setitimer) 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG3 != (Addr)NULL) { 2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3; 2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_timeval_WRITE( &(ovalue->it_interval) ); 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_timeval_WRITE( &(ovalue->it_value) ); 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_chroot) 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_chroot ( %#lx )", ARG1); 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "chroot", const char *, path); 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "chroot(path)", ARG1 ); 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_madvise) 2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_madvise ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3); 2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "madvise", 2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, start, vki_size_t, length, int, advice); 2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_MREMAP 2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mremap) 2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: this is different to the glibc version described in the man pages, 2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // which lacks the fifth 'new_address' argument. 2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG4 & VKI_MREMAP_FIXED) { 2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_mremap ( %#lx, %llu, %ld, 0x%lx, %#lx )", 2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1, (ULong)ARG2, ARG3, ARG4, ARG5); 2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ5(unsigned long, "mremap", 2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, old_addr, unsigned long, old_size, 2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, new_size, unsigned long, flags, 2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, new_addr); 2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_mremap ( %#lx, %llu, %ld, 0x%lx )", 2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1, (ULong)ARG2, ARG3, ARG4); 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ4(unsigned long, "mremap", 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, old_addr, unsigned long, old_size, 2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, new_size, unsigned long, flags); 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_from_SysRes( 2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_mremap((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid) 2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* HAVE_MREMAP */ 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_nice) 2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_nice ( %ld )", ARG1); 2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "nice", int, inc); 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mlock) 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_mlock ( %#lx, %llu )", ARG1, (ULong)ARG2); 2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len); 2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_munlock) 2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_munlock ( %#lx, %llu )", ARG1, (ULong)ARG2); 2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len); 2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mlockall) 2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_mlockall ( %lx )", ARG1); 2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "mlockall", int, flags); 2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setpriority) 2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_setpriority ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); 2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio); 2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpriority) 2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getpriority ( %ld, %ld )", ARG1, ARG2); 2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "getpriority", int, which, int, who); 2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_pwrite64) 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if VG_WORDSIZE == 4 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_pwrite64 ( %ld, %#lx, %llu, %lld )", 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1, ARG2, (ULong)ARG3, MERGE64(ARG4,ARG5)); 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ5(ssize_t, "pwrite64", 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, const char *, buf, vki_size_t, count, 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset)); 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif VG_WORDSIZE == 8 2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_pwrite64 ( %ld, %#lx, %llu, %lld )", 2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1, ARG2, (ULong)ARG3, (Long)ARG4); 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ4(ssize_t, "pwrite64", 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, const char *, buf, vki_size_t, count, 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word, offset); 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unexpected word size 2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 ); 2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_sync) 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_sync ( )"); 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "sync"); 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fstatfs) 2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_fstatfs ( %ld, %#lx )",ARG1,ARG2); 2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "fstatfs", 2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, struct statfs *, buf); 2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) ); 2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_fstatfs) 2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); 2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fstatfs64) 2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_fstatfs64 ( %ld, %llu, %#lx )",ARG1,(ULong)ARG2,ARG3); 2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "fstatfs64", 2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, vki_size_t, size, struct statfs64 *, buf); 2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 ); 2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_fstatfs64) 2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG3, ARG2 ); 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getsid) 2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getsid ( %ld )", ARG1); 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "getsid", vki_pid_t, pid); 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_pread64) 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if VG_WORDSIZE == 4 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_pread64 ( %ld, %#lx, %llu, %lld )", 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1, ARG2, (ULong)ARG3, MERGE64(ARG4,ARG5)); 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ5(ssize_t, "pread64", 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, char *, buf, vki_size_t, count, 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset)); 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif VG_WORDSIZE == 8 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_pread64 ( %ld, %#lx, %llu, %lld )", 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1, ARG2, (ULong)ARG3, (Long)ARG4); 2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ4(ssize_t, "pread64", 2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, char *, buf, vki_size_t, count, 2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word, offset); 2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unexpected word size 2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 ); 2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_pread64) 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES > 0) { 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, RES ); 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mknod) 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_mknod ( %#lx(%s), 0x%lx, 0x%lx )", ARG1, (char*)ARG1, ARG2, ARG3 ); 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "mknod", 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, pathname, int, mode, unsigned, dev); 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 ); 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_flock) 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_flock ( %ld, %ld )", ARG1, ARG2 ); 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation); 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Pre_read a char** argument. 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2) 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_deref; 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr* a_p = (Addr*)a; 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) ); 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a_deref = *a_p; 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == a_deref) 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( s2, a_deref ); 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a += sizeof(char*); 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool i_am_the_only_thread ( void ) 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int c = VG_(count_living_threads)(); 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(c >= 1); /* stay sane */ 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return c == 1; 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Wait until all other threads disappear. */ 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(reap_threads)(ThreadId self) 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (!i_am_the_only_thread()) { 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Let other thread(s) run */ 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vg_yield)(); 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals)(self); 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(i_am_the_only_thread()); 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// XXX: prototype here seemingly doesn't match the prototype for i386-linux, 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// but it seems to work nonetheless... 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_execve) 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* path = NULL; /* path to executable */ 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char** envp = NULL; 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char** argv = NULL; 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char** arg2copy; 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* launcher_basename = NULL; 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, j, tot_args; 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool setuid_allowed, trace_this_child; 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )", ARG1, (char*)ARG1, ARG2, ARG3); 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(vki_off_t, "execve", 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *, filename, char **, argv, char **, envp); 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "execve(filename)", ARG1 ); 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pre_argv_envp( ARG2, tid, "execve(argv)", "execve(argv[i])" ); 2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG3 != 0) 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" ); 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Erk. If the exec fails, then the following will have made a 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mess of things which makes it hard for us to continue. The 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown right thing to do is piece everything together again in 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST(execve), but that's close to impossible. Instead, we make 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown an effort to check that the execve will work before actually 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doing it. */ 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check that the name at least begins in client-accessible storage. */ 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 == 0 /* obviously bogus */ 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || !VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) { 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EFAULT ); 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // debug-only printing 2571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (0) { 2572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("ARG1 = %p(%s)\n", (void*)ARG1, (HChar*)ARG1); 2573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (ARG2) { 2574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("ARG2 = "); 2575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int q; 2576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HChar** vec = (HChar**)ARG2; 2577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (q = 0; vec[q]; q++) 2578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("%p(%s) ", vec[q], vec[q]); 2579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("\n"); 2580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 2581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("ARG2 = null\n"); 2582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Decide whether or not we want to follow along 2586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { // Make 'child_argv' be a pointer to the child's arg vector 2587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // (skipping the exe name) 2588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HChar** child_argv = (HChar**)ARG2; 2589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (child_argv && child_argv[0] == NULL) 2590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov child_argv = NULL; 2591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG1, child_argv ); 2592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Do the important checks: it is a file, is executable, permissions are 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ok, etc. We allow setuid executables to run only in the case when 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // we are not simulating them, that is, they to be run natively. 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown setuid_allowed = trace_this_child ? False : True; 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(pre_exec_check)((const Char*)ARG1, NULL, setuid_allowed); 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) { 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( sr_Err(res) ); 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're tracing the child, and the launcher name looks bogus 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (possibly because launcher.c couldn't figure it out, see 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown comments therein) then we have no option but to fail. */ 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (trace_this_child 2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (VG_(name_of_launcher) == NULL 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || VG_(name_of_launcher)[0] != '/')) { 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */ 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* After this point, we can't recover if the execve fails. */ 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1); 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 2618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Terminate gdbserver if it is active. 2619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_vgdb) != Vg_VgdbNo) { 2620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // If the child will not be traced, we need to terminate gdbserver 2621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // to cleanup the gdbserver resources (e.g. the FIFO files). 2622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // If child will be traced, we also terminate gdbserver: the new 2623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Valgrind will start a fresh gdbserver after exec. 2624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdbserver) (0); 2625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Resistance is futile. Nuke all other threads. POSIX mandates 2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this. (Really, nuke them all, since the new process will make 2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown its own new thread.) */ 2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(nuke_all_threads_except)( tid, VgSrc_ExitThread ); 2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(reap_threads)(tid); 2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set up the child's exe path. 2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (trace_this_child) { 2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // We want to exec the launcher. Get its pre-remembered path. 2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown path = VG_(name_of_launcher); 2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(name_of_launcher) should have been acquired by m_main at 2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // startup. 2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(path); 2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown launcher_basename = VG_(strrchr)(path, '/'); 2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (launcher_basename == NULL || launcher_basename[1] == 0) { 2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown launcher_basename = path; // hmm, tres dubious 2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown launcher_basename++; 2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown path = (Char*)ARG1; 2652f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov if (VG_(clo_xml)) { 2653f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(printf_xml)("\n<execv/>\n\n</valgrindoutput>\n\n"); 2654f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } else { 2655f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(umsg)("execv called - the tool will now quit\n"); 2656f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set up the child's environment. 2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Remove the valgrind-specific stuff from the environment so the 2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc. 2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // This is done unconditionally, since if we are tracing the child, 2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // the child valgrind will set up the appropriate client environment. 2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: we make a copy of the environment before trying to mangle it 2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // as it might be in read-only memory (this was bug #101881). 2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Then, if tracing the child, set VALGRIND_LIB for it. 2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG3 == 0) { 2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envp = NULL; 2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envp = VG_(env_clone)( (Char**)ARG3 ); 2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (envp == NULL) goto hosed; 2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(env_remove_valgrind_env_stuff)( envp ); 2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (trace_this_child) { 2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set VALGRIND_LIB in ARG3 (the environment) 2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir)); 2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set up the child's args. If not tracing it, they are 2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // simply ARG2. Otherwise, they are 2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..] 2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // except that the first VG_(args_for_valgrind_noexecpass) args 2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // are omitted. 2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!trace_this_child) { 2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = (Char**)ARG2; 2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(args_for_valgrind) ); 2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 ); 2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(args_for_valgrind_noexecpass) 2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown <= VG_(sizeXA)( VG_(args_for_valgrind) ) ); 2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* how many args in total will there be? */ 2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // launcher basename 2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tot_args = 1; 2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // V's args 2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tot_args += VG_(sizeXA)( VG_(args_for_valgrind) ); 2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tot_args -= VG_(args_for_valgrind_noexecpass); 2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // name of client exe 2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tot_args++; 2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // args for client exe, skipping [0] 2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg2copy = (Char**)ARG2; 2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg2copy && arg2copy[0]) { 2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; arg2copy[i]; i++) 2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tot_args++; 2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // allocate 2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1", 2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (tot_args+1) * sizeof(HChar*) ); 2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (argv == 0) goto hosed; 2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // copy 2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv[j++] = launcher_basename; 2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) { 2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i < VG_(args_for_valgrind_noexecpass)) 2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i ); 2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv[j++] = (Char*)ARG1; 2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg2copy && arg2copy[0]) 2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; arg2copy[i]; i++) 2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv[j++] = arg2copy[i]; 2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argv[j++] = NULL; 2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // check 2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(j == tot_args+1); 2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* restore the DATA rlimit for the child */ 2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data)); 2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Set the signal state up for exec. 2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We need to set the real signal state to make sure the exec'd 2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process gets SIG_IGN properly. 2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Also set our real sigmask to match the client's sigmask so that 2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the exec'd child will get the right mask. First we need to 2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clear out any pending signals so they they don't get delivered, 2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which would confuse things. 2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XXX This is a bug - the signals should remain pending, and be 2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivered to the new process after exec. There's also a 2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown race-condition, since if someone delivers us a signal between 2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the sigprocmask and the execve, we'll still get the signal. Oh 2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown well. 2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t allsigs; 2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t info; 2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* What this loop does: it queries SCSS (the signal state that 2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the client _thinks_ the kernel is in) by calling 2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_sys_sigaction), and modifies the real kernel signal 2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state accordingly. */ 2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i < VG_(max_signal); i++) { 2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t sa_f; 2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t sa_t; 2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_sys_sigaction)(i, NULL, &sa_f); 2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(convert_sigaction_fromK_to_toK)(&sa_f, &sa_t); 2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sa_t.ksa_handler == VKI_SIG_IGN) 2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaction)(i, &sa_t, NULL); 2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa_t.ksa_handler = VKI_SIG_DFL; 2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigaction)(i, &sa_t, NULL); 2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&allsigs); 2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(VG_(sigtimedwait_zero)(&allsigs, &info) > 0) 2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ; 2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL); 2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char **cpp; 2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("exec: %s\n", path); 2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = argv; cpp && *cpp; cpp++) 2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("argv: %s\n", *cpp); 2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = envp; cpp && *cpp; cpp++) 2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("env: %s\n", *cpp); 2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_from_SysRes( 2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp) 2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we got here, then the execve failed. We've already made way 2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown too much of a mess to continue, so we have to abort. */ 2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hosed: 2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(FAILURE); 2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %ld\n", 2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1, (char*)ARG1, ARG2, ARG3, ERR); 2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from " 2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "execve() failing, so I'm dying.\n"); 2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), " 2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "or work out how to recover.\n"); 2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(101); 2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_access) 2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_access ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2); 2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "access", const char *, pathname, int, mode); 2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "access(pathname)", ARG1 ); 2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_alarm) 2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_alarm ( %ld )", ARG1); 2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(unsigned long, "alarm", unsigned int, seconds); 2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_brk) 2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr brk_limit = VG_(brk_limit); 2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr brk_new; 2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* libc says: int brk(void *end_data_segment); 2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kernel says: void* brk(void* end_data_segment); (more or less) 2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown libc returns 0 on success, and -1 (and sets errno) on failure. 2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Nb: if you ask to shrink the dataseg end below what it 2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown currently is, that always succeeds, even if the dataseg end 2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doesn't actually change (eg. brk(0)). Unless it seg faults. 2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Kernel returns the new dataseg end. If the brk() failed, this 2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will be unchanged from the old one. That's why calling (kernel) 2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown brk(0) gives the current dataseg end (libc brk() just returns 2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zero in that case). 2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Both will seg fault if you shrink it back into a text segment. 2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_brk ( %#lx )", ARG1); 2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(unsigned long, "brk", unsigned long, end_data_segment); 2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown brk_new = do_brk(ARG1); 2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Success( brk_new ); 2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (brk_new == ARG1) { 2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* brk() succeeded */ 2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (brk_new < brk_limit) { 2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* successfully shrunk the data segment. */ 2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( die_mem_brk, (Addr)ARG1, 2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown brk_limit-ARG1 ); 2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else 2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (brk_new > brk_limit) { 2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* successfully grew the data segment */ 2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_brk, brk_limit, 2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1-brk_limit, tid ); 2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* brk() failed */ 2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(brk_limit == brk_new); 2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_chdir) 2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_chdir ( %#lx(%s) )", ARG1,(char*)ARG1); 2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "chdir", const char *, path); 2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "chdir(path)", ARG1 ); 2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_chmod) 2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_chmod ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2); 2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode); 2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "chmod(path)", ARG1 ); 2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_chown) 2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_chown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3); 2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "chown", 2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, path, vki_uid_t, owner, vki_gid_t, group); 2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "chown(path)", ARG1 ); 2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_lchown) 2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_lchown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3); 2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "lchown", 2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, path, vki_uid_t, owner, vki_gid_t, group); 2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "lchown(path)", ARG1 ); 2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_close) 2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_close ( %ld )", ARG1); 2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "close", unsigned int, fd); 2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Detect and negate attempts by the client to close Valgrind's log fd */ 2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (!ML_(fd_allowed)(ARG1, "close", tid, False)) 2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If doing -d style logging (which is to fd=2), don't 2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allow that to be closed either. */ 2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (ARG1 == 2/*stderr*/ && VG_(debugLog_getLevel)() > 0) ) 2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EBADF ); 2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_close) 2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) record_fd_close(ARG1); 2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_dup) 2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_dup ( %ld )", ARG1); 2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "dup", unsigned int, oldfd); 2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_dup) 2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(RES, "dup", tid, True)) { 2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(RES); 2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EMFILE ); 2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) 2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_named)(tid, RES); 2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_dup2) 2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_dup2 ( %ld, %ld )", ARG1,ARG2); 2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "dup2", unsigned int, oldfd, unsigned int, newfd); 2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(ARG2, "dup2", tid, True)) 2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EBADF ); 2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_dup2) 2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) 2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_named)(tid, RES); 2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fchdir) 2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_fchdir ( %ld )", ARG1); 2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "fchdir", unsigned int, fd); 2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fchown) 2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_fchown ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); 2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "fchown", 2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, vki_uid_t, owner, vki_gid_t, group); 2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fchmod) 2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_fchmod ( %ld, %ld )", ARG1,ARG2); 2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode); 2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_newfstat) 2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_newfstat ( %ld, %#lx )", ARG1,ARG2); 2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf); 2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) ); 2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_newfstat) 2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); 2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic vki_sigset_t fork_saved_mask; 2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// In Linux, the sys_fork() function varies across architectures, but we 2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ignore the various args it gets, and so it looks arch-neutral. Hmm. 2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fork) 2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is_child; 2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int child_pid; 2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t mask; 2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_fork ( )"); 2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "fork"); 2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Block all signals during fork, so that we can fix things up in 3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the child without being interrupted. */ 3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&mask); 3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask); 3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) ); 3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!SUCCESS) return; 3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // RES is 0 for child, non-0 (the child's PID) for parent. 3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is_child = ( RES == 0 ? True : False ); 3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown child_pid = ( is_child ? -1 : RES ); 3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // RES is the child's pid. RESHI is 1 for child, 0 for parent. 3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is_child = RESHI; 3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown child_pid = RES; 3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_atfork_pre)(tid); 3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_child) { 3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_atfork_child)(tid); 3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* restore signal mask */ 3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); 3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If --child-silent-after-fork=yes was specified, set the 3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown output file descriptors to 'impossible' values. This is 3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown noticed by send_bytes_to_logging_sink in m_libcprint.c, which 3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown duly stops writing any further output. */ 3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_child_silent_after_fork)) { 3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(log_output_sink).is_socket) 3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(log_output_sink).fd = -1; 3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(xml_output_sink).is_socket) 3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(xml_output_sink).fd = -1; 3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_atfork_parent)(tid); 3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT(" fork: process %d created child %d\n", VG_(getpid)(), child_pid); 3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* restore signal mask */ 3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); 3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_ftruncate) 3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_ftruncate ( %ld, %ld )", ARG1,ARG2); 3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length); 3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_truncate) 3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_truncate ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2); 3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "truncate", 3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, path, unsigned long, length); 3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); 3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_ftruncate64) 3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if VG_WORDSIZE == 4 3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_ftruncate64 ( %ld, %lld )", ARG1, MERGE64(ARG2,ARG3)); 3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "ftruncate64", 3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, 3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length)); 3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_ftruncate64 ( %ld, %lld )", ARG1, (Long)ARG2); 3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "ftruncate64", 3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int,fd, UWord,length); 3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_truncate64) 3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if VG_WORDSIZE == 4 3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)MERGE64(ARG2, ARG3)); 3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "truncate64", 3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, path, 3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length)); 3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)ARG2); 3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "truncate64", 3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *,path, UWord,length); 3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 ); 3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getdents) 3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getdents ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3); 3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "getdents", 3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, struct linux_dirent *, dirp, 3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, count); 3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 ); 3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getdents) 3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES > 0) 3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, RES ); 3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getdents64) 3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getdents64 ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); 3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "getdents64", 3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, struct linux_dirent64 *, dirp, 3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, count); 3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getdents64(dirp)", ARG2, ARG3 ); 3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getdents64) 3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES > 0) 3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, RES ); 3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getgroups) 3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getgroups ( %ld, %#lx )", ARG1, ARG2); 3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list); 3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 > 0) 3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) ); 3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getgroups) 3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 > 0 && RES > 0) 3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) ); 3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getcwd) 3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Comment from linux/fs/dcache.c: 3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // NOTE! The user-level library version returns a character pointer. 3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The kernel system call just returns the length of the buffer filled 3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (which includes the ending '\0' character), or a negative error 3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // value. 3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Is this Linux-specific? If so it should be moved to syswrap-linux.c. 3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getcwd ( %#lx, %llu )", ARG1,(ULong)ARG2); 3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "getcwd", char *, buf, unsigned long, size); 3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getcwd(buf)", ARG1, ARG2 ); 3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getcwd) 3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES != (Addr)NULL) 3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG1, RES ); 3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_geteuid) 3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_geteuid ( )"); 3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "geteuid"); 3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getegid) 3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getegid ( )"); 3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "getegid"); 3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getgid) 3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getgid ( )"); 3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "getgid"); 3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpid) 3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getpid ()"); 3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "getpid"); 3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpgid) 3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getpgid ( %ld )", ARG1); 3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "getpgid", vki_pid_t, pid); 3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpgrp) 3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getpgrp ()"); 3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "getpgrp"); 3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getppid) 3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getppid ()"); 3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "getppid"); 3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2) 3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( a2, sizeof(struct vki_rlimit) ); 3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef _RLIMIT_POSIX_FLAG 3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Darwin will sometimes set _RLIMIT_POSIX_FLAG on getrlimit calls. 3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Unset it here to make the switch case below work correctly. 3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a1 &= ~_RLIMIT_POSIX_FLAG; 3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (a1) { 3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_RLIMIT_NOFILE: 3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ((struct vki_rlimit *)a2)->rlim_cur = VG_(fd_soft_limit); 3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ((struct vki_rlimit *)a2)->rlim_max = VG_(fd_hard_limit); 3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_RLIMIT_DATA: 3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *((struct vki_rlimit *)a2) = VG_(client_rlimit_data); 3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VKI_RLIMIT_STACK: 3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *((struct vki_rlimit *)a2) = VG_(client_rlimit_stack); 3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_old_getrlimit) 3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_old_getrlimit ( %ld, %#lx )", ARG1,ARG2); 3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "old_getrlimit", 3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, resource, struct rlimit *, rlim); 3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) ); 3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_old_getrlimit) 3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown common_post_getrlimit(tid, ARG1, ARG2); 3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getrlimit) 3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getrlimit ( %ld, %#lx )", ARG1,ARG2); 3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "getrlimit", 3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, resource, struct rlimit *, rlim); 3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) ); 3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getrlimit) 3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown common_post_getrlimit(tid, ARG1, ARG2); 3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getrusage) 3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getrusage ( %ld, %#lx )", ARG1,ARG2); 3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage); 3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) ); 3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getrusage) 3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES == 0) 3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) ); 3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_gettimeofday) 3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_gettimeofday ( %#lx, %#lx )", ARG1,ARG2); 3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "gettimeofday", 3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timeval *, tv, struct timezone *, tz); 3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme does darwin write to *tz anymore? 3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) 3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_WRITE( "gettimeofday(tv)", ARG1 ); 3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) 3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) ); 3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_gettimeofday) 3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES == 0) { 3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) 3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_timeval_WRITE( ARG1 ); 3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) 3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) ); 3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_settimeofday) 3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_settimeofday ( %#lx, %#lx )", ARG1,ARG2); 3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "settimeofday", 3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timeval *, tv, struct timezone *, tz); 3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) 3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_READ( "settimeofday(tv)", ARG1 ); 3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) { 3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) ); 3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* maybe should warn if tz->tz_dsttime is non-zero? */ 3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getuid) 3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_getuid ( )"); 3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "getuid"); 3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(PRE_unknown_ioctl)(ThreadId tid, UWord request, UWord arg) 3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't have any specific information on it, so 3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown try to do something reasonable based on direction and 3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size bits. The encoding scheme is described in 3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h . 3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown According to Simon Hausmann, _IOC_READ means the kernel 3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown writes a value to the ioctl value passed from the user 3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown space and the other way around with _IOC_WRITE. */ 3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt dir = _VKI_IOC_DIR(request); 3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = _VKI_IOC_SIZE(request); 3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strstr)(VG_(clo_sim_hints), "lax-ioctls") != NULL) { 3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Be very lax about ioctl handling; the only 3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * assumption is that the size is correct. Doesn't 3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * require the full buffer to be initialized when 3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * writing. Without this, using some device 3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * drivers with a large number of strange ioctl 3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * commands becomes very tiresome. 3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) { 3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request); 3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); 3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Int moans = 3; 3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (moans > 0 && !VG_(clo_xml)) { 3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown moans--; 3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx" 3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " with no size/direction hints\n", request); 3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" This could cause spurious value errors to appear.\n"); 3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)(" See README_MISSING_SYSCALL_OR_IOCTL for " 3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "guidance on writing a proper wrapper.\n" ); 3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request); 3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); 3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((dir & _VKI_IOC_WRITE) && size > 0) 3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "ioctl(generic)", arg, size); 3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((dir & _VKI_IOC_READ) && size > 0) 3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "ioctl(generic)", arg, size); 3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(POST_unknown_ioctl)(ThreadId tid, UInt res, UWord request, UWord arg) 3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We don't have any specific information on it, so 3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown try to do something reasonable based on direction and 3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size bits. The encoding scheme is described in 3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h . 3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown According to Simon Hausmann, _IOC_READ means the kernel 3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown writes a value to the ioctl value passed from the user 3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown space and the other way around with _IOC_WRITE. */ 3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt dir = _VKI_IOC_DIR(request); 3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = _VKI_IOC_SIZE(request); 3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (size > 0 && (dir & _VKI_IOC_READ) 3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && res == 0 3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && arg != (Addr)NULL) 3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE(arg, size); 3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If we're sending a SIGKILL to one of our own threads, then simulate 3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it rather than really sending the signal, so that the target thread 3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gets a chance to clean up. Returns True if we did the killing (or 3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown no killing is necessary), and False if the caller should use the 3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown normal kill syscall. 3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "pid" is any pid argument which can be passed to kill; group kills 3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (< -1, 0), and owner kills (-1) are ignored, on the grounds that 3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they'll most likely hit all the threads and we won't need to worry 3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown about cleanup. In truth, we can't fully emulate these multicast 3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kills. 3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "tgid" is a thread group id. If it is not -1, then the target 3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread must be in that thread group. 3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(do_sigkill)(Int pid, Int tgid) 3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst; 3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid; 3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pid <= 0) 3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid = VG_(lwpid_to_vgtid)(pid); 3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tid == VG_INVALID_THREADID) 3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* none of our threads */ 3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tst == NULL || tst->status == VgTs_Empty) 3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* hm, shouldn't happen */ 3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tgid != -1 && tst->os_state.threadgroup != tgid) 3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* not the right thread group */ 3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check to see that the target isn't already exiting. */ 3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(is_exiting)(tid)) { 3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Thread %d being killed with SIGKILL\n", 3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->tid); 3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->exitreason = VgSrc_FatalSig; 3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.fatalsig = VKI_SIGKILL; 3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(is_running_thread)(tid)) 3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_thread_out_of_syscall)(tid); 3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_kill) 3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_kill ( %ld, %ld )", ARG1,ARG2); 3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "kill", int, pid, int, sig); 3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(client_signal_OK)(ARG2)) { 3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EINVAL ); 3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're sending SIGKILL, check to see if the target is one of 3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown our threads and handle it specially. */ 3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) 3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Success(0); 3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* re syscall3: Darwin has a 3rd arg, which is a flag (boolean) 3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown affecting how posix-compliant the call is. I guess it is 3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown harmless to pass the 3rd arg on other platforms; hence pass 3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it on all. */ 3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_from_SysRes( VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3) ); 3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "kill: sent signal %ld to pid %ld\n", 3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG2, ARG1); 3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This kill might have given us a pending signal. Ask for a check once 3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the syscall is done. */ 3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfPollAfter; 3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_link) 3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_link ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2); 3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath); 3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "link(oldpath)", ARG1); 3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "link(newpath)", ARG2); 3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_newlstat) 3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_newlstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2); 3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf); 3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 ); 3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) ); 3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_newlstat) 3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); 3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mkdir) 3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_mkdir ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2); 3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode); 3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 ); 3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mprotect) 3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_mprotect ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3); 3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "mprotect", 3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, addr, vki_size_t, len, unsigned long, prot); 3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) { 3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_ENOMEM ); 3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_PROT_GROWSDOWN) 3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) { 3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Deal with mprotects on growable stack areas. 3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The critical files to understand all this are mm/mprotect.c 3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in the kernel and sysdeps/unix/sysv/linux/dl-execstack.c in 3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown glibc. 3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The kernel provides PROT_GROWSDOWN and PROT_GROWSUP which 3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown round the start/end address of mprotect to the start/end of 3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the underlying vma and glibc uses that as an easy way to 3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown change the protection of the stack by calling mprotect on the 3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last page of the stack with PROT_GROWSDOWN set. 3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The sanity check provided by the kernel is that the vma must 3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate. */ 3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP); 3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const *aseg = VG_(am_find_nsegment)(ARG1); 3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const *rseg; 3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(aseg); 3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (grows == VKI_PROT_GROWSDOWN) { 3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rseg = VG_(am_next_nsegment)( (NSegment*)aseg, False/*backwards*/ ); 3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (rseg && 3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rseg->kind == SkResvn && 3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rseg->smode == SmUpper && 3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rseg->end+1 == aseg->start) { 3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr end = ARG1 + ARG2; 3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG1 = aseg->start; 3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG2 = end - aseg->start; 3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG3 &= ~VKI_PROT_GROWSDOWN; 3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EINVAL ); 3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (grows == VKI_PROT_GROWSUP) { 3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rseg = VG_(am_next_nsegment)( (NSegment*)aseg, True/*forwards*/ ); 3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (rseg && 3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rseg->kind == SkResvn && 3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rseg->smode == SmLower && 3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aseg->end+1 == rseg->start) { 3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG2 = aseg->end - ARG1 + 1; 3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG3 &= ~VKI_PROT_GROWSUP; 3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EINVAL ); 3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* both GROWSUP and GROWSDOWN */ 3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EINVAL ); 3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VKI_PROT_GROWSDOWN) 3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_mprotect) 3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a = ARG1; 3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT len = ARG2; 3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int prot = ARG3; 3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(notify_core_and_tool_of_mprotect)(a, len, prot); 3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_munmap) 3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)(" munmap( %#lx )\n", ARG1); 3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_munmap ( %#lx, %llu )", ARG1,(ULong)ARG2); 3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "munmap", unsigned long, start, vki_size_t, length); 3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "munmap")) 3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EINVAL ); 3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_munmap) 3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a = ARG1; 3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT len = ARG2; 3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(notify_core_and_tool_of_munmap)( (Addr64)a, (ULong)len ); 3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mincore) 3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_mincore ( %#lx, %llu, %#lx )", ARG1,(ULong)ARG2,ARG3); 3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "mincore", 3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, start, vki_size_t, length, 3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char *, vec); 3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "mincore(vec)", ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE ); 3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_mincore) 3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE ); 3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_nanosleep) 3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock|SfPostOnFail; 3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_nanosleep ( %#lx, %#lx )", ARG1,ARG2); 3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "nanosleep", 3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timespec *, req, struct timespec *, rem); 3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "nanosleep(req)", ARG1, sizeof(struct vki_timespec) ); 3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) 3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "nanosleep(rem)", ARG2, sizeof(struct vki_timespec) ); 3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_nanosleep) 3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS || FAILURE); 3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0 && FAILURE && ERR == VKI_EINTR) 3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); 3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_open) 3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 & VKI_O_CREAT) { 3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 3-arg version 3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_open ( %#lx(%s), %ld, %ld )",ARG1,(char*)ARG1,ARG2,ARG3); 3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "open", 3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, filename, int, flags, int, mode); 3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 2-arg version 3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2); 3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "open", 3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, filename, int, flags); 3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "open(filename)", ARG1 ); 3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Handle the case where the open is of /proc/self/cmdline or 3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /proc/<pid>/cmdline, and just give it a copy of the fd for the 3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fake file we cooked up at startup (in m_main). Also, seek the 3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cloned fd back to the start. */ 3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar name[30]; 3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* arg1s = (Char*) ARG1; 3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)()); 3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ML_(safe_to_deref)( arg1s, 1 ) && 3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/cmdline")) 3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(dup)( VG_(cl_cmdline_fd) ); 3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_from_SysRes( sres ); 3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(sres)) { 3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET ); 3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (off < 0) 3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EMFILE ); 3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux) 3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Otherwise handle normally */ 3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_open) 3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(RES, "open", tid, True)) { 3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(RES); 3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EMFILE ); 3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) 3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1); 3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_read) 3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_read ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3); 3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(ssize_t, "read", 3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, char *, buf, vki_size_t, count); 3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(ARG1, "read", tid, False)) 3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EBADF ); 3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); 3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_read) 3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, RES ); 3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_write) 3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_write ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3); 3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(ssize_t, "write", 3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, fd, const char *, buf, vki_size_t, count); 3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* check to see if it is allowed. If not, try for an exemption from 3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --sim-hints=enable-outer (used for self hosting). */ 3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = ML_(fd_allowed)(ARG1, "write", tid, False); 3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok && ARG1 == 2/*stderr*/ 3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && VG_(strstr)(VG_(clo_sim_hints),"enable-outer")) 3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = True; 3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) 3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EBADF ); 3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); 3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_creat) 3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_creat ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2); 3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "creat", const char *, pathname, int, mode); 3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "creat(pathname)", ARG1 ); 3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_creat) 3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(RES, "creat", tid, True)) { 3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(RES); 3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EMFILE ); 3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_track_fds)) 3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1); 3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_poll) 3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* struct pollfd { 3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int fd; -- file descriptor 3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown short events; -- requested events 3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown short revents; -- returned events 3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown }; 3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int poll(struct pollfd *ufds, unsigned int nfds, int timeout) 3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1; 3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_poll ( %#lx, %ld, %ld )\n", ARG1,ARG2,ARG3); 3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "poll", 3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pollfd *, ufds, unsigned int, nfds, long, timeout); 3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < ARG2; i++) { 3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "poll(ufds.fd)", 3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) ); 3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "poll(ufds.events)", 3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)(&ufds[i].events), sizeof(ufds[i].events) ); 3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "poll(ufds.reventss)", 3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) ); 3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_poll) 3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES >= 0) { 3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1; 3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < ARG2; i++) 3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) ); 3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_readlink) 3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word saved = SYSNO; 3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_readlink ( %#lx(%s), %#lx, %llu )", ARG1,(char*)ARG1,ARG2,(ULong)ARG3); 3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "readlink", 3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, path, char *, buf, int, bufsiz); 3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "readlink(path)", ARG1 ); 3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 ); 3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Handle the case where readlink is looking at /proc/self/exe or 3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * /proc/<pid>/exe. 3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar name[25]; 3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* arg1s = (Char*) ARG1; 3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)()); 3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ML_(safe_to_deref)(arg1s, 1) && 3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/exe")) 3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd)); 3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name, 3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG2, ARG3)); 3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else 3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux) 3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Normal case */ 3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3)); 3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (SUCCESS && RES > 0) 3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, RES ); 3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_readv) 3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_iovec * vec; 3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_readv ( %ld, %#lx, %llu )",ARG1,ARG2,(ULong)ARG3); 3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(ssize_t, "readv", 3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, fd, const struct iovec *, vector, 3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, count); 3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) { 3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EBADF ); 3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "readv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) ); 3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) { 3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ToDo: don't do any of the following if the vector is invalid */ 3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vec = (struct vki_iovec *)ARG2; 3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < (Int)ARG3; i++) 3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "readv(vector[...])", 3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)vec[i].iov_base, vec[i].iov_len ); 3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_readv) 3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES > 0) { 3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_iovec * vec = (struct vki_iovec *)ARG2; 3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int remains = RES; 3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* RES holds the number of bytes read. */ 3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < (Int)ARG3; i++) { 3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nReadThisBuf = vec[i].iov_len; 3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nReadThisBuf > remains) nReadThisBuf = remains; 3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf ); 3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown remains -= nReadThisBuf; 3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (remains < 0) VG_(core_panic)("readv: remains < 0"); 3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_rename) 3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_rename ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2); 3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath); 3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 ); 3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 ); 3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_rmdir) 3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_rmdir ( %#lx(%s) )", ARG1,(char*)ARG1); 3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "rmdir", const char *, pathname); 3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 ); 3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_select) 3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_select ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); 3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ5(long, "select", 3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int, n, vki_fd_set *, readfds, vki_fd_set *, writefds, 3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_fd_set *, exceptfds, struct vki_timeval *, timeout); 3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX: this possibly understates how much memory is read. 3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) 3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "select(readfds)", 3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG2, ARG1/8 /* __FD_SETSIZE/8 */ ); 3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG3 != 0) 3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "select(writefds)", 3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG3, ARG1/8 /* __FD_SETSIZE/8 */ ); 3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG4 != 0) 3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "select(exceptfds)", 3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG4, ARG1/8 /* __FD_SETSIZE/8 */ ); 3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG5 != 0) 3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_READ( "select(timeout)", ARG5 ); 3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setgid) 3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_setgid ( %ld )", ARG1); 3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "setgid", vki_gid_t, gid); 3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setsid) 3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_setsid ( )"); 3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "setsid"); 3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setgroups) 3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("setgroups ( %llu, %#lx )", (ULong)ARG1, ARG2); 3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list); 3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 > 0) 3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) ); 3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setpgid) 3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("setpgid ( %ld, %ld )", ARG1, ARG2); 3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid); 3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setregid) 3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_setregid ( %ld, %ld )", ARG1, ARG2); 3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid); 3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setreuid) 3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_setreuid ( 0x%lx, 0x%lx )", ARG1, ARG2); 3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid); 3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setrlimit) 3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord arg1 = ARG1; 3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_setrlimit ( %ld, %#lx )", ARG1,ARG2); 3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "setrlimit", 3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned int, resource, struct rlimit *, rlim); 3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "setrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) ); 3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef _RLIMIT_POSIX_FLAG 3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Darwin will sometimes set _RLIMIT_POSIX_FLAG on setrlimit calls. 3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Unset it here to make the if statements below work correctly. 3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg1 &= ~_RLIMIT_POSIX_FLAG; 3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg1 == VKI_RLIMIT_NOFILE) { 3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(fd_hard_limit) || 3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ((struct vki_rlimit *)ARG2)->rlim_max != VG_(fd_hard_limit)) { 3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EPERM ); 3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fd_soft_limit) = ((struct vki_rlimit *)ARG2)->rlim_cur; 3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Success( 0 ); 3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (arg1 == VKI_RLIMIT_DATA) { 3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_data).rlim_max || 3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_data).rlim_max) { 3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EPERM ); 3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client_rlimit_data) = *(struct vki_rlimit *)ARG2; 3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Success( 0 ); 3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (arg1 == VKI_RLIMIT_STACK && tid == 1) { 3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_stack).rlim_max || 3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_stack).rlim_max) { 3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EPERM ); 3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur; 3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client_rlimit_stack) = *(struct vki_rlimit *)ARG2; 3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Success( 0 ); 3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setuid) 3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_setuid ( %ld )", ARG1); 3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "setuid", vki_uid_t, uid); 3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_newstat) 3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_newstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2); 3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf); 3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 ); 3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) ); 3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_newstat) 3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); 3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_statfs) 3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_statfs ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2); 3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf); 3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "statfs(path)", ARG1 ); 3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) ); 3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_statfs) 3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); 4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_statfs64) 4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_statfs64 ( %#lx(%s), %llu, %#lx )",ARG1,(char*)ARG1,(ULong)ARG2,ARG3); 4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "statfs64", 4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char *, path, vki_size_t, size, struct statfs64 *, buf); 4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 ); 4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 ); 4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_statfs64) 4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG3, ARG2 ); 4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_symlink) 4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_symlink ( %#lx(%s), %#lx(%s) )",ARG1,(char*)ARG1,ARG2,(char*)ARG2); 4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath); 4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 ); 4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 ); 4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_time) 4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* time_t time(time_t *t); */ 4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_time ( %#lx )",ARG1); 4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "time", int *, t); 4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) { 4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "time(t)", ARG1, sizeof(vki_time_t) ); 4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_time) 4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) { 4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG1, sizeof(vki_time_t) ); 4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_times) 4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_times ( %#lx )", ARG1); 4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "times", struct tms *, buf); 4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) { 4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) ); 4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_times) 4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) { 4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) ); 4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_umask) 4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_umask ( %ld )", ARG1); 4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "umask", int, mask); 4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_unlink) 4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_unlink ( %#lx(%s) )", ARG1,(char*)ARG1); 4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "unlink", const char *, pathname); 4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 ); 4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_newuname) 4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_newuname ( %#lx )", ARG1); 4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "uname", struct new_utsname *, buf); 4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_new_utsname) ); 4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_newuname) 4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) { 4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) ); 4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_waitpid) 4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_waitpid ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3); 4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(long, "waitpid", 4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_pid_t, pid, unsigned int *, status, int, options); 4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != (Addr)NULL) 4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "waitpid(status)", ARG2, sizeof(int) ); 4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_waitpid) 4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != (Addr)NULL) 4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(int) ); 4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_wait4) 4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_wait4 ( %ld, %#lx, %ld, %#lx )", ARG1,ARG2,ARG3,ARG4); 4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ4(long, "wait4", 4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_pid_t, pid, unsigned int *, status, int, options, 4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct rusage *, rusage); 4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != (Addr)NULL) 4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "wait4(status)", ARG2, sizeof(int) ); 4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG4 != (Addr)NULL) 4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "wait4(rusage)", ARG4, sizeof(struct vki_rusage) ); 4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_wait4) 4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != (Addr)NULL) 4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(int) ); 4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG4 != (Addr)NULL) 4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG4, sizeof(struct vki_rusage) ); 4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_writev) 4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_iovec * vec; 4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_writev ( %ld, %#lx, %llu )",ARG1,ARG2,(ULong)ARG3); 4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ3(ssize_t, "writev", 4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, fd, const struct iovec *, vector, 4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, count); 4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(fd_allowed)(ARG1, "writev", tid, False)) { 4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_Failure( VKI_EBADF ); 4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "writev(vector)", 4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARG2, ARG3 * sizeof(struct vki_iovec) ); 4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) { 4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ToDo: don't do any of the following if the vector is invalid */ 4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vec = (struct vki_iovec *)ARG2; 4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < (Int)ARG3; i++) 4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "writev(vector[...])", 4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)vec[i].iov_base, vec[i].iov_len ); 4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_utimes) 4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov FUSE_COMPATIBLE_MAY_BLOCK(); 4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_utimes ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2); 4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp); 4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 ); 4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) { 4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_READ( "utimes(tvp[0])", ARG2 ); 4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_timeval_READ( "utimes(tvp[1])", ARG2+sizeof(struct vki_timeval) ); 4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_acct) 4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_acct ( %#lx(%s) )", ARG1,(char*)ARG1); 4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ1(long, "acct", const char *, filename); 4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_RASCIIZ( "acct(filename)", ARG1 ); 4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_pause) 4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *flags |= SfMayBlock; 4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sys_pause ( )"); 4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ0(long, "pause"); 4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_sigaltstack) 4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRINT("sigaltstack ( %#lx, %#lx )",ARG1,ARG2); 4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_REG_READ2(int, "sigaltstack", 4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_stack_t *, ss, vki_stack_t *, oss); 4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG1 != 0) { 4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_stack_t *ss = (vki_stack_t *)ARG1; 4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_sp, sizeof(ss->ss_sp) ); 4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_flags, sizeof(ss->ss_flags) ); 4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_size, sizeof(ss->ss_size) ); 4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ARG2 != 0) { 4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PRE_MEM_WRITE( "sigaltstack(oss)", ARG2, sizeof(vki_stack_t) ); 4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_STATUS_from_SysRes( 4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1, 4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (vki_stack_t*)ARG2) 4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_sigaltstack) 4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(SUCCESS); 4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (RES == 0 && ARG2 != 0) 4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POST_MEM_WRITE( ARG2, sizeof(vki_stack_t)); 4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef PRE 4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef POST 4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux) || defined(VGO_darwin) 4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 4209