https://bugs.kde.org/show_bug.cgi?id=424018

            Bug ID: 424018
           Summary: Valgrind crashes with --trace-syscalls=yes if syscalls
                    use PRINT %s with a non-dereferenceable string
           Product: valgrind
           Version: unspecified
          Platform: Other
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: general
          Assignee: jsew...@acm.org
          Reporter: pa...@free.fr
  Target Milestone: ---

SUMMARY

As a quick example, in the memcheck/tests/x86-linux directory if I run

../../../vg-in-place --trace-syscalls=yes ./scalar < scalar.c

then I get

-----------------------------------------------------                           
 11:         __NR_execve 3s 1m                                                  
-----------------------------------------------------                           
SYSCALL[13743,1](4) ... [async] --> Success(0x8b)                               
SYSCALL[13743,1](11) --13743-- VALGRIND INTERNAL ERROR: Valgrind received a
signal 11 (SIGSEGV) - exiting                   
--13743-- si_code=1;  Faulting address: 0x1;  sp: 0x8288bb28                    

valgrind: the 'impossible' happened:
   Killed by fatal signal           

host stacktrace:
==13743==    at 0x5801E368: myvprintf_str (m_debuglog.c:623)
==13743==    by 0x5801EBAD: vgPlain_debugLog_vprintf (m_debuglog.c:1027)
==13743==    by 0x58028850: vprintf_WRK (m_libcprint.c:647)             
==13743==    by 0x58028C11: vgPlain_printf (m_libcprint.c:671)          
==13743==    by 0x58070414: vgSysWrap_generic_sys_execve_before
(syswrap-generic.c:3152)
==13743==    by 0x58014F49: vgPlain_client_syscall (syswrap-main.c:1914)        
==13743==    by 0x580123F8: handle_syscall (scheduler.c:1208)                   
==13743==    by 0x58013A19: vgPlain_scheduler (scheduler.c:1526)                
==13743==    by 0x58076D03: run_a_thread_NORETURN (syswrap-linux.c:101)

The code in scalar.c is

   // __NR_execve 11
   GO(__NR_execve, "3s 1m");
   SY(__NR_execve, x0 + 1, x0 + 1, x0); FAIL;

The execve signature is

int execve(const char *filename, char *const argv[],
                  char *const envp[]);


As the stacktrace says, this is handled in syswrap-generic.c


   PRINT("sys_execve ( %#" FMT_REGWORD "x(%s), %#" FMT_REGWORD "x, %#"
         FMT_REGWORD "x )", ARG1, (HChar*)(Addr)ARG1, ARG2, ARG3);

The problem is with the "(%s)" dereferencing (HChar*)(Addr)ARG1, which is 1.

I suggest adding a new function such as

const HChar* ML_(sanitize_string)(Addr ptr)
{
   if (ML_(safe_to_deref)((const void *)ptr, 1)) {
      return (const HChar*)pr;
   } else {
      return "invalid string";
   }
}

and changing the PRINT to

   PRINT("sys_execve ( %#" FMT_REGWORD "x(%s), %#" FMT_REGWORD "x, %#"
         FMT_REGWORD "x )", ARG1, ML_(sanitize_sring)((Addr)ARG1), ARG2, ARG3);

I'm not providing a patch as there are many other similar examples.

It might also be possible to change VG_(printf) to handle non-dereferenceable
pointers. That would require fewer code changes at the expense of always
checking pointers.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to