├── Makefile.all.am ├── Makefile.am ├── Makefile.in ├── Makefile.tool.am ├── README.md ├── capstone-3.0.4.patch ├── config.h ├── configure.ac ├── configure_capstone.sh ├── configure_valgrind.sh ├── copy.c ├── copy.h ├── make_capstone_options.py ├── secretgrind.h ├── tests ├── Makefile.am └── Makefile.in ├── tnt_asm.c ├── tnt_asm.h ├── tnt_file_filter.c ├── tnt_file_filter.h ├── tnt_include.h ├── tnt_libc.c ├── tnt_libc.h ├── tnt_main.c ├── tnt_malloc_wrappers.c ├── tnt_malloc_wrappers.h ├── tnt_mmap.c ├── tnt_mmap.h ├── tnt_strings.h ├── tnt_structs.h ├── tnt_subblock_helper.h ├── tnt_summary_names.c ├── tnt_summary_names.h ├── tnt_syswrap.c ├── tnt_syswrap.h ├── tnt_translate.c ├── tnt_wraps.c └── valgrind.patch /Makefile.all.am: -------------------------------------------------------------------------------- 1 | 2 | # This file should be included (directly or indirectly) by every 3 | # Makefile.am that builds programs. And also the top-level Makefile.am. 4 | 5 | #---------------------------------------------------------------------------- 6 | # Global stuff 7 | #---------------------------------------------------------------------------- 8 | 9 | inplacedir = $(top_builddir)/.in_place 10 | 11 | # This used to be required when Vex had a handwritten Makefile. It 12 | # shouldn't be needed any more, though. 13 | ##.NOTPARALLEL: 14 | 15 | #---------------------------------------------------------------------------- 16 | # noinst_PROGRAMS and noinst_DSYMS targets 17 | #---------------------------------------------------------------------------- 18 | 19 | # On Darwin, for a program 'p', the DWARF debug info is stored in the 20 | # directory 'p.dSYM'. This must be generated after the executable is 21 | # created, with 'dsymutil p'. We could redefine LINK with a script that 22 | # executes 'dsymutil' after linking, but that's a pain. Instead we use this 23 | # hook so that every time "make check" is run, we subsequently invoke 24 | # 'dsymutil' on all the executables that lack a .dSYM directory, or that are 25 | # newer than their corresponding .dSYM directory. 26 | build-noinst_DSYMS: $(noinst_DSYMS) 27 | for f in $(noinst_DSYMS); do \ 28 | if [ ! -e $$f.dSYM -o $$f -nt $$f.dSYM ] ; then \ 29 | echo "dsymutil $$f"; \ 30 | dsymutil $$f; \ 31 | fi; \ 32 | done 33 | 34 | # This is used by coregrind/Makefile.am and Makefile.tool.am for doing 35 | # "in-place" installs. It copies $(noinst_PROGRAMS) into $inplacedir. 36 | # It needs to be depended on by an 'all-local' rule. 37 | inplace-noinst_PROGRAMS: $(noinst_PROGRAMS) 38 | mkdir -p $(inplacedir); \ 39 | for f in $(noinst_PROGRAMS) ; do \ 40 | rm -f $(inplacedir)/$$f; \ 41 | ln -f -s ../$(subdir)/$$f $(inplacedir); \ 42 | done 43 | 44 | # Similar to inplace-noinst_PROGRAMS 45 | inplace-noinst_DSYMS: build-noinst_DSYMS 46 | mkdir -p $(inplacedir); \ 47 | for f in $(noinst_DSYMS); do \ 48 | rm -f $(inplacedir)/$$f.dSYM; \ 49 | ln -f -s ../$(subdir)/$$f.dSYM $(inplacedir); \ 50 | done 51 | 52 | # This is used by coregrind/Makefile.am and by /Makefile.am for doing 53 | # "make install". It copies $(noinst_PROGRAMS) into $prefix/lib/valgrind/. 54 | # It needs to be depended on by an 'install-exec-local' rule. 55 | install-noinst_PROGRAMS: $(noinst_PROGRAMS) 56 | $(mkinstalldirs) $(DESTDIR)$(pkglibdir); \ 57 | for f in $(noinst_PROGRAMS); do \ 58 | $(INSTALL_PROGRAM) $$f $(DESTDIR)$(pkglibdir); \ 59 | done 60 | 61 | # Similar to install-noinst_PROGRAMS. 62 | # Nb: we don't use $(INSTALL_PROGRAM) here because it doesn't work with 63 | # directories. XXX: not sure whether the resulting permissions will be 64 | # correct when using 'cp -R'... 65 | install-noinst_DSYMS: build-noinst_DSYMS 66 | $(mkinstalldirs) $(DESTDIR)$(pkglibdir); \ 67 | for f in $(noinst_DSYMS); do \ 68 | cp -R $$f.dSYM $(DESTDIR)$(pkglibdir); \ 69 | done 70 | 71 | # This needs to be depended on by a 'clean-local' rule. 72 | clean-noinst_DSYMS: 73 | for f in $(noinst_DSYMS); do \ 74 | rm -rf $$f.dSYM; \ 75 | done 76 | 77 | #---------------------------------------------------------------------------- 78 | # Flags 79 | #---------------------------------------------------------------------------- 80 | 81 | # Baseline flags for all compilations. Aim here is to maximise 82 | # performance and get whatever useful warnings we can out of gcc. 83 | # -fno-builtin is important for defeating LLVM's idiom recognition 84 | # that somehow causes VG_(memset) to get into infinite recursion. 85 | AM_CFLAGS_BASE = \ 86 | -O2 -g \ 87 | -Wall \ 88 | -Wmissing-prototypes \ 89 | -Wshadow \ 90 | -Wpointer-arith \ 91 | -Wstrict-prototypes \ 92 | -Wmissing-declarations \ 93 | @FLAG_W_NO_FORMAT_ZERO_LENGTH@ \ 94 | -fno-strict-aliasing \ 95 | -fno-builtin 96 | 97 | # These flags are used for building the preload shared objects. 98 | # The aim is to give reasonable performance but also to have good 99 | # stack traces, since users often see stack traces extending 100 | # into (and through) the preloads. 101 | if VGCONF_OS_IS_DARWIN 102 | AM_CFLAGS_PIC = -dynamic -O -g -fno-omit-frame-pointer -fno-strict-aliasing \ 103 | -mno-dynamic-no-pic -fpic -fPIC \ 104 | -fno-builtin 105 | else 106 | AM_CFLAGS_PIC = -fpic -O -g -fno-omit-frame-pointer -fno-strict-aliasing \ 107 | -fno-builtin 108 | endif 109 | 110 | 111 | # Flags for specific targets. 112 | # 113 | # Nb: the AM_CPPFLAGS_* values are suitable for building tools and auxprogs. 114 | # For building the core, coregrind/Makefile.am files add some extra things. 115 | # 116 | # Also: in newer versions of automake (1.10 onwards?) asm files ending with 117 | # '.S' are considered "pre-processed" (as opposed to those ending in '.s') 118 | # and so the CPPFLAGS are passed to the assembler. But this is not true for 119 | # older automakes (e.g. 1.8.5, 1.9.6), sigh. So we include 120 | # AM_CPPFLAGS_ in each AM_CCASFLAGS_ variable. This 121 | # means some of the flags are duplicated on systems with newer versions of 122 | # automake, but this does not really matter and seems hard to avoid. 123 | 124 | AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@ = \ 125 | -I$(top_srcdir) \ 126 | -I$(top_srcdir)/include \ 127 | -I$(top_srcdir)/VEX/pub \ 128 | -DVGA_@VGCONF_ARCH_PRI@=1 \ 129 | -DVGO_@VGCONF_OS@=1 \ 130 | -DVGP_@VGCONF_ARCH_PRI@_@VGCONF_OS@=1 \ 131 | -DVGPV_@VGCONF_ARCH_PRI@_@VGCONF_OS@_@VGCONF_PLATVARIANT@=1 132 | if VGCONF_HAVE_PLATFORM_SEC 133 | AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@ = \ 134 | -I$(top_srcdir) \ 135 | -I$(top_srcdir)/include \ 136 | -I$(top_srcdir)/VEX/pub \ 137 | -DVGA_@VGCONF_ARCH_SEC@=1 \ 138 | -DVGO_@VGCONF_OS@=1 \ 139 | -DVGP_@VGCONF_ARCH_SEC@_@VGCONF_OS@=1 \ 140 | -DVGPV_@VGCONF_ARCH_SEC@_@VGCONF_OS@_@VGCONF_PLATVARIANT@=1 141 | endif 142 | 143 | AM_FLAG_M3264_X86_LINUX = @FLAG_M32@ 144 | AM_CFLAGS_X86_LINUX = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY@ \ 145 | $(AM_CFLAGS_BASE) 146 | AM_CCASFLAGS_X86_LINUX = $(AM_CPPFLAGS_X86_LINUX) @FLAG_M32@ -g 147 | 148 | AM_FLAG_M3264_AMD64_LINUX = @FLAG_M64@ 149 | AM_CFLAGS_AMD64_LINUX = @FLAG_M64@ -fomit-frame-pointer \ 150 | @PREFERRED_STACK_BOUNDARY@ $(AM_CFLAGS_BASE) 151 | AM_CCASFLAGS_AMD64_LINUX = $(AM_CPPFLAGS_AMD64_LINUX) @FLAG_M64@ -g 152 | 153 | AM_FLAG_M3264_PPC32_LINUX = @FLAG_M32@ 154 | AM_CFLAGS_PPC32_LINUX = @FLAG_M32@ $(AM_CFLAGS_BASE) 155 | AM_CCASFLAGS_PPC32_LINUX = $(AM_CPPFLAGS_PPC32_LINUX) @FLAG_M32@ -g 156 | 157 | AM_FLAG_M3264_PPC64_LINUX = @FLAG_M64@ 158 | AM_CFLAGS_PPC64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) 159 | AM_CCASFLAGS_PPC64_LINUX = $(AM_CPPFLAGS_PPC64_LINUX) @FLAG_M64@ -g 160 | 161 | AM_FLAG_M3264_X86_FREEBSD = @FLAG_M32@ 162 | AM_CFLAGS_X86_FREEBSD = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY@ \ 163 | $(AM_CFLAGS_BASE) 164 | AM_CCASFLAGS_X86_FREEBSD = $(AM_CPPFLAGS_X86_FREEBSD) @FLAG_M32@ -g 165 | 166 | AM_FLAG_M3264_ARM_LINUX = @FLAG_M32@ 167 | AM_CFLAGS_ARM_LINUX = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY@ \ 168 | $(AM_CFLAGS_BASE) -marm -mcpu=cortex-a8 169 | AM_CCASFLAGS_ARM_LINUX = $(AM_CPPFLAGS_ARM_LINUX) @FLAG_M32@ \ 170 | -marm -mcpu=cortex-a8 -g 171 | 172 | AM_FLAG_M3264_AMD64_FREEBSD = @FLAG_M64@ 173 | AM_CFLAGS_AMD64_FREEBSD = @FLAG_M64@ -fomit-frame-pointer \ 174 | @PREFERRED_STACK_BOUNDARY@ $(AM_CFLAGS_BASE) 175 | AM_CCASFLAGS_AMD64_FREEBSD = $(AM_CPPFLAGS_AMD64_FREEBSD) @FLAG_M64@ -g 176 | 177 | 178 | AM_FLAG_M3264_X86_DARWIN = -arch i386 179 | AM_CFLAGS_X86_DARWIN = $(WERROR) -arch i386 $(AM_CFLAGS_BASE) \ 180 | -mmacosx-version-min=10.5 \ 181 | -fno-stack-protector -fno-pic -fno-PIC 182 | 183 | AM_CCASFLAGS_X86_DARWIN = $(AM_CPPFLAGS_X86_DARWIN) -arch i386 -g 184 | 185 | AM_FLAG_M3264_AMD64_DARWIN = -arch x86_64 186 | AM_CFLAGS_AMD64_DARWIN = $(WERROR) -arch x86_64 $(AM_CFLAGS_BASE) \ 187 | -mmacosx-version-min=10.5 -fno-stack-protector 188 | AM_CCASFLAGS_AMD64_DARWIN = $(AM_CPPFLAGS_AMD64_DARWIN) -arch x86_64 -g 189 | 190 | AM_FLAG_M3264_S390X_LINUX = @FLAG_M64@ 191 | AM_CFLAGS_S390X_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) 192 | AM_CCASFLAGS_S390X_LINUX = $(AM_CPPFLAGS_S390X_LINUX) -mzarch -march=z900 \ 193 | @FLAG_M64@ -g 194 | 195 | # Flags for the primary target. These must be used to build the 196 | # regtests and performance tests. In fact, these must be used to 197 | # build anything which is built only once on a dual-arch build. 198 | # 199 | AM_FLAG_M3264_PRI = $(AM_FLAG_M3264_@VGCONF_PLATFORM_PRI_CAPS@) 200 | AM_CPPFLAGS_PRI = $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) 201 | AM_CFLAGS_PRI = $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) 202 | AM_CCASFLAGS_PRI = $(AM_CCASFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) 203 | 204 | if VGCONF_HAVE_PLATFORM_SEC 205 | AM_FLAG_M3264_SEC = $(AM_FLAG_M3264_@VGCONF_PLATFORM_SEC_CAPS@) 206 | else 207 | AM_FLAG_M3264_SEC = 208 | endif 209 | 210 | 211 | # Baseline link flags for making vgpreload shared objects. 212 | # 213 | PRELOAD_LDFLAGS_COMMON_LINUX = -nodefaultlibs -shared -Wl,-z,interpose,-z,initfirst 214 | PRELOAD_LDFLAGS_COMMON_FREEBSD = -nodefaultlibs -shared -Wl,-z,interpose,-z,initfirst 215 | PRELOAD_LDFLAGS_COMMON_DARWIN = -dynamic -dynamiclib -all_load 216 | 217 | PRELOAD_LDFLAGS_X86_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ 218 | PRELOAD_LDFLAGS_AMD64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ 219 | PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ 220 | PRELOAD_LDFLAGS_PPC64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ 221 | PRELOAD_LDFLAGS_X86_FREEBSD = $(PRELOAD_LDFLAGS_COMMON_FREEBSD) @FLAG_M32@ 222 | PRELOAD_LDFLAGS_AMD64_FREEBSD= $(PRELOAD_LDFLAGS_COMMON_FREEBSD) @FLAG_M64@ 223 | PRELOAD_LDFLAGS_ARM_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ 224 | PRELOAD_LDFLAGS_X86_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386 225 | PRELOAD_LDFLAGS_AMD64_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch x86_64 226 | PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ 227 | 228 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | include $(top_srcdir)/Makefile.tool.am 2 | 3 | #---------------------------------------------------------------------------- 4 | # Headers 5 | #---------------------------------------------------------------------------- 6 | 7 | pkginclude_HEADERS = \ 8 | secretgrind.h 9 | 10 | noinst_HEADERS = \ 11 | tnt_include.h \ 12 | tnt_strings.h \ 13 | tnt_malloc_wrappers.h \ 14 | tnt_summary_names.h \ 15 | tnt_subblock_helper.h \ 16 | tnt_syswrap.h \ 17 | tnt_libc.h \ 18 | tnt_file_filter.h \ 19 | tnt_asm.h \ 20 | copy.h 21 | 22 | #---------------------------------------------------------------------------- 23 | # secretgrind- 24 | #---------------------------------------------------------------------------- 25 | 26 | noinst_PROGRAMS = secretgrind-@VGCONF_ARCH_PRI@-@VGCONF_OS@ 27 | if VGCONF_HAVE_PLATFORM_SEC 28 | noinst_PROGRAMS += secretgrind-@VGCONF_ARCH_SEC@-@VGCONF_OS@ 29 | endif 30 | 31 | SECRETGRIND_SOURCES_COMMON = \ 32 | tnt_syswrap.c \ 33 | tnt_malloc_wrappers.c \ 34 | tnt_main.c \ 35 | tnt_translate.c \ 36 | tnt_summary_names.c \ 37 | tnt_mmap.c \ 38 | tnt_libc.c \ 39 | tnt_file_filter.c \ 40 | tnt_asm.c \ 41 | copy.c 42 | 43 | 44 | secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES = $(SECRETGRIND_SOURCES_COMMON) 45 | secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS = \ 46 | $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) 47 | secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS = \ 48 | $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) -O2 49 | secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_DEPENDENCIES = \ 50 | $(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@) 51 | secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDADD = \ 52 | $(TOOL_LDADD_@VGCONF_PLATFORM_PRI_CAPS@) 53 | secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS = \ 54 | $(TOOL_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) 55 | secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LINK = \ 56 | ../coregrind/link_tool_exe_@VGCONF_OS@ \ 57 | @VALT_LOAD_ADDRESS_PRI@ \ 58 | $(LINK) \ 59 | $(secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) \ 60 | $(secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS) 61 | 62 | if VGCONF_HAVE_PLATFORM_SEC 63 | secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_SOURCES = $(SECRETGRIND_SOURCES_COMMON) 64 | secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS = \ 65 | $(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) 66 | secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS = \ 67 | $(AM_CFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) -O2 68 | secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_DEPENDENCIES = \ 69 | $(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@) 70 | secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDADD = \ 71 | $(TOOL_LDADD_@VGCONF_PLATFORM_SEC_CAPS@) 72 | secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS = \ 73 | $(TOOL_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) 74 | secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LINK = \ 75 | ../coregrind/link_tool_exe_@VGCONF_OS@ \ 76 | @VALT_LOAD_ADDRESS_SEC@ \ 77 | $(LINK) \ 78 | $(secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) \ 79 | $(secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS) 80 | endif 81 | 82 | tnt_main.o: CFLAGS += -fomit-frame-pointer 83 | 84 | #---------------------------------------------------------------------------- 85 | # vgpreload_secretgrind-.so 86 | #---------------------------------------------------------------------------- 87 | 88 | noinst_PROGRAMS += vgpreload_secretgrind-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so 89 | if VGCONF_HAVE_PLATFORM_SEC 90 | noinst_PROGRAMS += vgpreload_secretgrind-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so 91 | endif 92 | 93 | if VGCONF_OS_IS_DARWIN 94 | noinst_DSYMS = $(noinst_PROGRAMS) 95 | endif 96 | 97 | VGPRELOAD_SECRETGRIND_SOURCES_COMMON = tnt_wraps.c 98 | 99 | vgpreload_secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_SOURCES = \ 100 | $(VGPRELOAD_SECRETGRIND_SOURCES_COMMON) 101 | vgpreload_secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS = \ 102 | $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) 103 | vgpreload_secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS = \ 104 | $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) $(AM_CFLAGS_PIC) -O2 105 | vgpreload_secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_DEPENDENCIES = \ 106 | $(LIBREPLACEMALLOC_@VGCONF_PLATFORM_PRI_CAPS@) 107 | vgpreload_secretgrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LDFLAGS = \ 108 | $(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) \ 109 | $(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) 110 | if VGCONF_HAVE_PLATFORM_SEC 111 | vgpreload_secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_SOURCES = \ 112 | $(VGPRELOAD_SECRETGRIND_SOURCES_COMMON) 113 | vgpreload_secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS = \ 114 | $(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) 115 | vgpreload_secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS = \ 116 | $(AM_CFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) $(AM_CFLAGS_PIC) -O2 117 | vgpreload_secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_DEPENDENCIES = \ 118 | $(LIBREPLACEMALLOC_@VGCONF_PLATFORM_SEC_CAPS@) 119 | vgpreload_secretgrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LDFLAGS = \ 120 | $(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) \ 121 | $(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) 122 | endif 123 | 124 | tnt_wraps.o: CFLAGS += -fno-omit-frame-pointer 125 | 126 | -------------------------------------------------------------------------------- /Makefile.tool.am: -------------------------------------------------------------------------------- 1 | 2 | SUBDIRS = . tests 3 | 4 | include $(top_srcdir)/Makefile.all.am 5 | 6 | #---------------------------------------------------------------------------- 7 | # - stuff 8 | #---------------------------------------------------------------------------- 9 | 10 | TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@ = \ 11 | ../coregrind/libcoregrind-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a \ 12 | ../VEX/libvex-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a 13 | if VGCONF_HAVE_PLATFORM_SEC 14 | TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@ = \ 15 | ../coregrind/libcoregrind-@VGCONF_ARCH_SEC@-@VGCONF_OS@.a \ 16 | ../VEX/libvex-@VGCONF_ARCH_SEC@-@VGCONF_OS@.a 17 | endif 18 | 19 | 20 | TOOL_LDADD_COMMON = -lgcc -lcapstone -L./capstone-3.0.4/ 21 | TOOL_LDADD_@VGCONF_PLATFORM_PRI_CAPS@ = \ 22 | $(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@) $(TOOL_LDADD_COMMON) 23 | if VGCONF_HAVE_PLATFORM_SEC 24 | TOOL_LDADD_@VGCONF_PLATFORM_SEC_CAPS@ = \ 25 | $(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@) $(TOOL_LDADD_COMMON) 26 | endif 27 | 28 | 29 | # -Wl,--build-id=none is needed when linking tools on Linux. Without this 30 | # flag newer ld versions (2.20 and later) create a .note.gnu.build-id at the 31 | # default text segment address, which of course means the resulting executable 32 | # is unusable. So we have to tell ld not to generate that, with --build-id=none. 33 | TOOL_LDFLAGS_COMMON_LINUX = \ 34 | -static -nodefaultlibs -nostartfiles -u _start @FLAG_NO_BUILD_ID@ 35 | TOOL_LDFLAGS_COMMON_DARWIN = \ 36 | -nodefaultlibs -nostartfiles -Wl,-u,__start -Wl,-e,__start 37 | TOOL_LDFLAGS_COMMON_FREEBSD = -static \ 38 | -nodefaultlibs -nostartfiles -u _start @FLAG_NO_BUILD_ID@ 39 | 40 | TOOL_LDFLAGS_X86_LINUX = \ 41 | $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@ 42 | 43 | TOOL_LDFLAGS_X86_FREEBSD = \ 44 | $(TOOL_LDFLAGS_COMMON_FREEBSD) @FLAG_M32@ 45 | 46 | TOOL_LDFLAGS_AMD64_LINUX = \ 47 | $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@ 48 | 49 | TOOL_LDFLAGS_AMD64_FREEBSD = \ 50 | $(TOOL_LDFLAGS_COMMON_FREEBSD) @FLAG_M64@ 51 | 52 | TOOL_LDFLAGS_PPC32_LINUX = \ 53 | $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@ 54 | 55 | TOOL_LDFLAGS_PPC64_LINUX = \ 56 | $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@ 57 | 58 | TOOL_LDFLAGS_ARM_LINUX = \ 59 | $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@ 60 | 61 | TOOL_LDFLAGS_S390X_LINUX = \ 62 | $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@ 63 | 64 | TOOL_LDFLAGS_X86_DARWIN = \ 65 | $(TOOL_LDFLAGS_COMMON_DARWIN) -arch i386 66 | 67 | TOOL_LDFLAGS_AMD64_DARWIN = \ 68 | $(TOOL_LDFLAGS_COMMON_DARWIN) -arch x86_64 69 | 70 | # On Android we must ask for non-executable stack, not sure why. 71 | if VGCONF_PLATFORMS_INCLUDE_ARM_LINUX 72 | if VGCONF_PLATVARIANT_IS_ANDROID 73 | TOOL_LDFLAGS_ARM_LINUX += -Wl,-z,noexecstack 74 | endif 75 | endif 76 | 77 | # NB for 64-bit darwin. We may want to set -Wl,-pagezero_size to 78 | # something smaller than the default of 4G, so as to facilitate 79 | # loading clients who are also linked thusly (currently m_ume.c 80 | # will fail to load them). Although such setting is probably 81 | # better done in link_tool_exe.c. 82 | # 83 | # -Wl,-pagezero_size,0x100000000 84 | 85 | 86 | #---------------------------------------------------------------------------- 87 | # vgpreload_-.a stuff 88 | #---------------------------------------------------------------------------- 89 | 90 | LIBREPLACEMALLOC_X86_LINUX = \ 91 | ../coregrind/libreplacemalloc_toolpreload-x86-linux.a 92 | 93 | LIBREPLACEMALLOC_AMD64_LINUX = \ 94 | ../coregrind/libreplacemalloc_toolpreload-amd64-linux.a 95 | 96 | LIBREPLACEMALLOC_PPC32_LINUX = \ 97 | ../coregrind/libreplacemalloc_toolpreload-ppc32-linux.a 98 | 99 | LIBREPLACEMALLOC_PPC64_LINUX = \ 100 | ../coregrind/libreplacemalloc_toolpreload-ppc64-linux.a 101 | 102 | LIBREPLACEMALLOC_X86_FREEBSD = \ 103 | ../coregrind/libreplacemalloc_toolpreload-x86-freebsd.a 104 | 105 | LIBREPLACEMALLOC_ARM_LINUX = \ 106 | ../coregrind/libreplacemalloc_toolpreload-arm-linux.a 107 | 108 | LIBREPLACEMALLOC_AMD64_FREEBSD = \ 109 | ../coregrind/libreplacemalloc_toolpreload-amd64-freebsd.a 110 | LIBREPLACEMALLOC_X86_DARWIN = \ 111 | ../coregrind/libreplacemalloc_toolpreload-x86-darwin.a 112 | 113 | LIBREPLACEMALLOC_AMD64_DARWIN = \ 114 | ../coregrind/libreplacemalloc_toolpreload-amd64-darwin.a 115 | 116 | LIBREPLACEMALLOC_S390X_LINUX = \ 117 | ../coregrind/libreplacemalloc_toolpreload-s390x-linux.a 118 | 119 | 120 | LIBREPLACEMALLOC_LDFLAGS_X86_LINUX = \ 121 | -Wl,--whole-archive \ 122 | $(LIBREPLACEMALLOC_X86_LINUX) \ 123 | -Wl,--no-whole-archive 124 | 125 | LIBREPLACEMALLOC_LDFLAGS_AMD64_LINUX = \ 126 | -Wl,--whole-archive \ 127 | $(LIBREPLACEMALLOC_AMD64_LINUX) \ 128 | -Wl,--no-whole-archive 129 | 130 | LIBREPLACEMALLOC_LDFLAGS_PPC32_LINUX = \ 131 | -Wl,--whole-archive \ 132 | $(LIBREPLACEMALLOC_PPC32_LINUX) \ 133 | -Wl,--no-whole-archive 134 | 135 | LIBREPLACEMALLOC_LDFLAGS_PPC64_LINUX = \ 136 | -Wl,--whole-archive \ 137 | $(LIBREPLACEMALLOC_PPC64_LINUX) \ 138 | -Wl,--no-whole-archive 139 | 140 | LIBREPLACEMALLOC_LDFLAGS_ARM_LINUX = \ 141 | -Wl,--whole-archive \ 142 | $(LIBREPLACEMALLOC_ARM_LINUX) \ 143 | -Wl,--no-whole-archive 144 | 145 | LIBREPLACEMALLOC_LDFLAGS_X86_FREEBSD = \ 146 | -Wl,--whole-archive \ 147 | $(LIBREPLACEMALLOC_X86_FREEBSD) \ 148 | -Wl,--no-whole-archive 149 | 150 | LIBREPLACEMALLOC_LDFLAGS_AMD64_FREEBSD = \ 151 | -Wl,--whole-archive \ 152 | $(LIBREPLACEMALLOC_AMD64_FREEBSD) \ 153 | -Wl,--no-whole-archive 154 | LIBREPLACEMALLOC_LDFLAGS_X86_DARWIN = \ 155 | $(LIBREPLACEMALLOC_X86_DARWIN) 156 | 157 | LIBREPLACEMALLOC_LDFLAGS_AMD64_DARWIN = \ 158 | $(LIBREPLACEMALLOC_AMD64_DARWIN) 159 | 160 | LIBREPLACEMALLOC_LDFLAGS_S390X_LINUX = \ 161 | -Wl,--whole-archive \ 162 | $(LIBREPLACEMALLOC_S390X_LINUX) \ 163 | -Wl,--no-whole-archive 164 | 165 | #---------------------------------------------------------------------------- 166 | # General stuff 167 | #---------------------------------------------------------------------------- 168 | 169 | all-local: inplace-noinst_PROGRAMS inplace-noinst_DSYMS 170 | 171 | clean-local: clean-noinst_DSYMS 172 | 173 | install-exec-local: install-noinst_PROGRAMS install-noinst_DSYMS 174 | 175 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Secretgrind: a Valgrind analysis tool to detect secrets in memory 2 | ================================================================= 3 | 4 | Description: 5 | ----------- 6 | 7 | Secretgrind is a runtime analysis tool that uses taint to track sensitive data in memory. It builds upon [Taintgrind](https://github.com/wmkhoo/taintgrind) by Wei Ming Khoo. By default, Secretgrind propagates taint in two ways: 8 | 9 | 1. In "direct flow", ie during assignments: if a tainted (ie sensitive) variable `tainted_var` is copied to another variable `other_var`, then `other_var` takes the taint of `tainted_var`: 10 | 11 | ```c 12 | int non_tainted_var = 0; 13 | int tainted_var = 0; 14 | [...] // code that copies sensitive data to tainted_var 15 | int other_var = tainted_var; // other_var is now tainted 16 | int other_var2 = tainted_var & non_tainted_var; // other_var2 is now tainted 17 | int other_var3 = tainted_var | non_tainted_var; // other_var3 is now tainted 18 | int other_var4 = tainted_var ^ non_tainted_var; // other_var4 is now tainted 19 | // More generally, any binary operation results in taint propagation 20 | int other_varX = tainted_var __binOperation__ non_tainted_var // other_varX is now tainted 21 | ``` 22 | 23 | 2. In pointer arithmetic operations: think of this as a lookup table where the table is not sensitive but the index used for lookup is: 24 | ```c 25 | void bin2hex(u8 const * in, size_t const ilen, char *out) { 26 | char const *fmt = "0123456789ABCDEF"; // this table is not sensitive 27 | size_t i = 0; 28 | 29 | assert (in && out); 30 | assert ((ilen&1) == 0); 31 | 32 | for (i=0;i> 4) & 0x0F ]; // out[2*i] becomes tainted if the index in[i] is sensitive 34 | out[(2*i)+1] = fmt[ in[i] & 0x0F ]; // out[(2*i)+1] becomes tainted if the index in[i] is sensitive 35 | } 36 | out[2*i] = '\0'; 37 | } 38 | ``` 39 | 40 | Warnings: 41 | --------- 42 | 1. Secretgrind was tested on x86_64 Linux. If you encounter problems building/running it on different arch/platforms, create an issue [here](https://github.com/lmrs2/secretgrind/issues) 43 | 44 | 2. Do not run Secretgrind on untrusted software as the code has not been properly audited. There are a lot of memory-copy operations... 45 | 46 | Requirements: 47 | ------------ 48 | 1. Python must be installed on your machine for the installation process to complete 49 | 50 | 2. Please follow the instruction **in order**. You will get an error if you don't 51 | 52 | Installation: 53 | ------------- 54 | 55 | 1. Download [Valgrind](http://valgrind.org) and build 56 | 57 | 58 | [me@machine ~/] wget valgrind.org/downloads/valgrind-3.10.1.tar.bz2 59 | [me@machine ~/] diff <(sha256sum -b valgrind-3.10.1.tar.bz2) <(echo 'fa253dc26ddb661b6269df58144eff607ea3f76a9bcfe574b0c7726e1dfcb997 *valgrind-3.10.1.tar.bz2') 60 | An empty result means files are identical 61 | [me@machine ~/] tar jxvf valgrind-3.10.1.tar.bz2 62 | [me@machine ~/] cd valgrind-3.10.1 63 | 64 | 2. Git clone Secretgrind 65 | 66 | [me@machine ~/valgrind-3.10.1] git clone https://github.com/lmrs2/secretgrind.git 67 | [me@machine ~/valgrind-3.10.1] cd secretgrind 68 | 69 | 3. Download [Capstone](http://www.capstone-engine.org/) 70 | 71 | [me@machine ~/valgrind-3.10.1/secretgrind] wget https://github.com/aquynh/capstone/archive/3.0.4.tar.gz -O capstone-3.0.4.tar.gz 72 | [me@machine ~/valgrind-3.10.1/secretgrind] tar zxvf capstone-3.0.4.tar.gz 73 | 74 | 4. Configure and build Valgrind 75 | 76 | [me@machine ~/valgrind-3.10.1/secretgrind] sh configure_valgrind.sh 77 | [me@machine ~/valgrind-3.10.1] cd .. 78 | [me@machine ~/valgrind-3.10.1] ./autogen.sh 79 | [me@machine ~/valgrind-3.10.1] ./configure --prefix=`pwd`/inst 80 | [me@machine ~/valgrind-3.10.1] make && make install 81 | 82 | 83 | 5. Configure and build Capstone 84 | 85 | [me@machine ~/valgrind-3.10.1] cd secretgrind 86 | [me@machine ~/valgrind-3.10.1/secretgrind] sh configure_capstone.sh `pwd`/../inst // Note: obviously this should be the same as the one used to configure Valgrind! 87 | [me@machine ~/valgrind-3.10.1/secretgrind] cd capstone-3.0.4 88 | [me@machine ~/valgrind-3.10.1/secretgrind/capstone-3.0.4] sh make_capstone.sh 89 | 90 | 6. Configure and build Secretgrind 91 | 92 | [me@machine ~/valgrind-3.10.1/secretgrind/capstone-3.0.4] cd ../ 93 | [me@machine ~/valgrind-3.10.1/secretgrind] ../autogen.sh 94 | [me@machine ~/valgrind-3.10.1/secretgrind] ./configure --prefix=`pwd`/../inst // Note: obviously this should be the same as the one used to configure Valgrind and Capstone! 95 | [me@machine ~/valgrind-3.10.1/secretgrind] make && make install 96 | 97 | 98 | Usage 99 | ----- 100 | [me@machine ~/wherever/] alias secretgrind="~/valgrind-3.10.1/inst/bin/valgrind --tool=secretgrind" 101 | [me@machine ~/wherever/] secretgrind --help 102 | [me@machine ~/wherever/] secretgrind --file-filter=taintedfile.txt ./program_that_reads_tainted_file 103 | 104 | ... 105 | user options for Secretgrind: 106 | 107 | File options: 108 | --file-filter= list of files (full path) to taint, separated by comma [""] 109 | --file-taint-start=[0,800000] starting byte to taint (in hex) [0] 110 | --file-taint-len=[0,800000] number of bytes to taint from file-taint-start (in hex) [800000] 111 | --file-mmap-use-pagesize=[1,2^32] size to taint when mmap()'ing tainted file [4096] 112 | 113 | Taint options: 114 | --taint-df-only= no|yes propagate taint only thru 'direct flows' (df) [no]. Note: pointer arithmetic propagation not supported 115 | --taint-remove-on-release= no|yes remove taint when block is released (free(),mumap(file)) [no] 116 | --taint-warn-on-release= no|yes display live information when a block is released (free(),mumap(file)) yet tainted [no] 117 | --taint-show-source= no|yes show information when taint is received from file or secretgrind API [no] 118 | --taint-stdin= no|yes taint stdin input [no]. Note: --file-taint-start and --file-taint-len do not apply to stdin 119 | 120 | Trace options: 121 | --trace= no|yes print an instruction trace [no]. Slow, try using SG_PRINT_X_INST() instead 122 | --trace-taint-only= no|yes print only tainted instructions [yes]. Must be used in conjunction with --trace=yes. Slow, try using SG_PRINT_X_INST() instead 123 | 124 | Summary options: 125 | --summary= no|yes display a taint summary after execution [yes] 126 | --summary-verbose= no|yes print a detailed taint summary [no]. Tainted regions show as @0xAAAAAAAA_TYPE_PID_ValgrindThreadID, eg @0x4025000_mmap_10432_1 127 | --summary-main-only= yes|no print taint summary at the end of the main() function only [no] 128 | --summary-exit-only= yes|no print taint summary upon entering the exit() function only [no] 129 | --summary-total-only= no|yes taint summary only shows the total # bytes tainted [no] 130 | --summary-fix-inst= [1,ffffffff] try to fix the stack trace for instructions by giving a list of IDs separated by comma 131 | 132 | General options: 133 | --var-name= no|yes print variable names if possible [no]. Very slow, so try using in combination with SG_PRINT_X_INST() 134 | --mnemonics= no|yes display the mnemonics of the original instruction responsible for tainting data [no] 135 | --debug= no|yes print debug info [no] 136 | 137 | 138 | 139 | Examples 140 | -------- 141 | 1. Create a file containing tainted data: 142 | 143 | [me@machine ~/examples] echo "This is a tainted file." > tainted.txt 144 | 145 | 2. Consider the following code (call it test.c): 146 | ```c 147 | #include 148 | #include 149 | #include 150 | #include 151 | #include 152 | #include 153 | #include 154 | #include 155 | #include 156 | 157 | #define LEN (50) 158 | 159 | int main(int argc, char* argv[]) 160 | { 161 | char *s = 0; 162 | int fd = 0; 163 | ssize_t n = 0; 164 | 165 | if ( (s = malloc(LEN)) == 0) { 166 | printf("error malloc %d (%s)\n", errno, strerror(errno)); 167 | goto end; 168 | } 169 | 170 | if ( (fd = open (argv[1], O_RDWR )) < 0) { 171 | printf("error open %d (%s)\n", errno, strerror(errno)); 172 | goto end; 173 | } 174 | 175 | if ( (n = read(fd, s, LEN)) < 0) { 176 | printf("error read %d (%s)\n", errno, strerror(errno)); 177 | goto end; 178 | } 179 | 180 | end: 181 | if (fd>0) { close(fd); } 182 | if (s) { free(s); } 183 | 184 | return 0; 185 | } 186 | ``` 187 | 188 | 3. Compile as: 189 | 190 | [me@machine ~/examples] gcc -Wall -O0 test.c -o test 191 | 192 | 4. Run Secretgrind as: 193 | 194 | [me@machine ~/examples] secretgrind ./test tainted.txt 195 | [me@machine ~/examples] ... 196 | 197 | ==123== [TAINT SUMMARY] - On end main(): 198 | --------------------------------------------------- 199 | 200 | No bytes tainted 201 | 202 | ==123== [TAINT SUMMARY] - On exit(): 203 | --------------------------------------------------- 204 | 205 | No bytes tainted 206 | ==123== 207 | 208 | By default, Secretgrind only displays a short summary about bytes tainted after returning from the `main()` function (`==123== [TAINT SUMMARY] - On end main():`) and before `exit()`'ing the program (`==123== [TAINT SUMMARY] - On exit():`). The n-digit number `==123==` indicates the process ID of the process during execution; here it is 123. This run indicates `No bytes tainted` right after `main()` and before `exit()`'ing the program. This is normal since we have not indicated that the file tainted.txt should be considered tainted. 209 | 210 | 5. To tell Secretgind that tainted.txt is tainted, use the option **--file-filter=file1,file2,fileN** (the fullpath of files is necessary): 211 | 212 | [me@machine ~/examples] secretgrind --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 213 | [me@machine ~/examples] ... 214 | 215 | ==123== [TAINT SUMMARY] - On end main(): 216 | --------------------------------------------------- 217 | 218 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 219 | 220 | Total bytes tainted: 24 221 | 222 | ==123== [TAINT SUMMARY] - On exit(): 223 | --------------------------------------------------- 224 | 225 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 226 | 227 | Total bytes tainted: 24 228 | ==123== 229 | 230 | By default, Secretgrind provides a short summary of each tainted memory region. In this run, the 24 bytes of `range [0x51ec040 - 0x51ec057]` are tainted (this is the number of characters read from the file tainted.txt). It also indicates the "type" of the memory that is tainted, here `malloc` since the variable `char *s` was malloc()'ed. Other keywords you might see here are: `fmmap` for mapp()'ed files, `mmap` for non-file mapp()'ed memory regions, `stack`, `global`, and `other` for anything else. 231 | 232 | 6. To get more information about the taint, such as the stacktrace that led to it, or how the block was allocated (in the case of `malloc()`'ed and `mmap()`'ed regions), use option **--summary-verbose=yes**: 233 | 234 | [me@machine ~/examples] secretgrind --summary-verbose=yes --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 235 | [me@machine ~/examples] ... 236 | 237 | ==123== [TAINT SUMMARY] - On end main(): 238 | --------------------------------------------------- 239 | 240 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 241 | > (malloc) [0x51ec040 - 0x51ec057] (24 bytes): 0x51ec040 242 | tainted at 0x4F13F30: read (in /lib/x86_64-linux-gnu/libc-2.15.so) 243 | by 0x4007F2: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 244 | Parent block [0x51ec040 - 0x51ec071] (50 bytes): @0x51ec040_malloc_2030_1 245 | malloc()'ed at 0x4C2B3E4: malloc (vg_replace_malloc.c:296) 246 | by 0x40074C: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 247 | free()'ed at 0x4C2A2EA: free (vg_replace_malloc.c:473) 248 | by 0x40084D: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 249 | 250 | Total bytes tainted: 24 251 | 252 | ==123== [TAINT SUMMARY] - On exit(): 253 | --------------------------------------------------- 254 | 255 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 256 | > (malloc) [0x51ec040 - 0x51ec057] (24 bytes): 0x51ec040 257 | tainted at 0x4F13F30: read (in /lib/x86_64-linux-gnu/libc-2.15.so) 258 | by 0x4007F2: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 259 | Parent block [0x51ec040 - 0x51ec071] (50 bytes): @0x51ec040_malloc_2030_1 260 | malloc()'ed at 0x4C2B3E4: malloc (vg_replace_malloc.c:296) 261 | by 0x40074C: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 262 | free()'ed at 0x4C2A2EA: free (vg_replace_malloc.c:473) 263 | by 0x40084D: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 264 | 265 | Total bytes tainted: 24 266 | ==123== 267 | 268 | 269 | 270 | Taint after `main()` and before `exit()` may differ, and that is why Secretgrind displays both by default. But you can get Secretgrind to display only one of them through options **--summary-main-only=yes** or **--summary-exit-only=yes**: 271 | 272 | [me@machine ~/examples] secretgrind --summary-main-only=yes --summary-verbose=yes --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 273 | [me@machine ~/examples] ... 274 | 275 | ==123== [TAINT SUMMARY] - On end main(): 276 | --------------------------------------------------- 277 | 278 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 279 | > (malloc) [0x51ec040 - 0x51ec057] (24 bytes): 0x51ec040 280 | tainted at 0x4F13F30: read (in /lib/x86_64-linux-gnu/libc-2.15.so) 281 | by 0x4007F2: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 282 | Parent block [0x51ec040 - 0x51ec071] (50 bytes): @0x51ec040_malloc_2030_1 283 | malloc()'ed at 0x4C2B3E4: malloc (vg_replace_malloc.c:296) 284 | by 0x40074C: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 285 | free()'ed at 0x4C2A2EA: free (vg_replace_malloc.c:473) 286 | by 0x40084D: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 287 | 288 | Total bytes tainted: 24 289 | ==123== 290 | 291 | The tainted memory region `[0x51ec040 - 0x51ec057]` was tainted because of a call to `read()` in libc `/lib/x86_64-linux-gnu/libc-2.15.so`, and the call originated from the `main()` function. Furthermore, the tainted region belongs to the "parent" block `[0x51ec040 - 0x51ec071]` which is 50-byte long - this corresponds to the call to `malloc(LEN)`). The block was malloc()'ed by the `main()` function. There is a strange line `malloc (vg_replace_malloc.c:XXX)`: this is an artifact of Valgrind's instrumentation and can be ignored in practice. 292 | 293 | 7. Sometimes it can be difficult to pinpoint which instruction is responsible for the taint, especially when it is because of register pressure, calling convention, etc. So you can get Secretgrind to display instructions in the verbose summary with option **--mnemonics=yes**: 294 | 295 | [me@machine ~/examples] secretgrind --mnemonics=yes --summary-main-only=yes --summary-verbose=yes --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 296 | [me@machine ~/examples] ... 297 | 298 | ==123== [TAINT SUMMARY] - On end main(): 299 | --------------------------------------------------- 300 | 301 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 302 | > (malloc) [0x51ec040 - 0x51ec057] (24 bytes): 0x51ec040 303 | tainted at 0x4F13F30: read (in /lib/x86_64-linux-gnu/libc-2.15.so) 304 | by 0x4007F2: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 305 | tainted by instruction 'syscall ' (raw=0f 05, ID=_1cb37_) 306 | Parent block [0x51ec040 - 0x51ec071] (50 bytes): @0x51ec040_malloc_2491_1 307 | malloc()'ed at 0x4C2B3E4: malloc (vg_replace_malloc.c:296) 308 | by 0x40074C: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 309 | free()'ed at 0x4C2A2EA: free (vg_replace_malloc.c:473) 310 | by 0x40084D: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 311 | 312 | Total bytes tainted: 24 313 | ==123== 314 | 315 | There is now an extra line indicating the instruction was `syscall` (0f 05 in hex). There is also an instruction ID `_1cb37_`. If you ever see an inconsistent stacktrace (eg an empty one), then it is possible Secretgrind did not manage to retrieve the stacktrace correctly. If this happens, you can pass this instruction ID to **--summary-fix-inst=1cb37** to tell Secretgrind to try to fix the problem. It worked fine here, so we need not use **--summary-fix-inst**. In general, Secretgrind gets the stacktrace right so you should not have to use this option often in practice. Something you must be aware of if that your compiler may be inlining functions. So if you have a function `foo1() -> foo2() -> foo3() -> foo4()` in your source code, your compiler might inline calls as `foo1() -> foo2()`; where `foo2()` contains the code of `foo3()` and `foo4()`. Try looking at the binary (eg with objdump) to check this before you resort to **--summary-fix-inst**. 316 | 317 | 8. Secregrind can also retrieve the names (as they appear in the source code) of the variables that are tainted. This works for stack and global variables. It also makes Secretgrind much much slower, as it must look up the name of variables for each access to tainted memory. So use this option sparsely! Now update the code as follows (note the use of a new stack variable `stack_var` and `stack_var = s[4];` to assign it some tainted data): 318 | 319 | ```c 320 | #include 321 | #include 322 | #include 323 | #include 324 | #include 325 | #include 326 | #include 327 | #include 328 | #include 329 | 330 | #define LEN (50) 331 | 332 | int main(int argc, char* argv[]) 333 | { 334 | char *s = 0; 335 | int fd = 0; 336 | ssize_t n = 0; 337 | char stack_var = 0; 338 | 339 | if ( (s = malloc(LEN)) == 0) { 340 | printf("error malloc %d (%s)\n", errno, strerror(errno)); 341 | goto end; 342 | } 343 | 344 | if ( (fd = open (argv[1], O_RDWR )) < 0) { 345 | printf("error open %d (%s)\n", errno, strerror(errno)); 346 | goto end; 347 | } 348 | 349 | if ( (n = read(fd, s, LEN)) < 0) { 350 | printf("error read %d (%s)\n", errno, strerror(errno)); 351 | goto end; 352 | } 353 | 354 | stack_var = s[4]; // stack_var should now be tainted 355 | 356 | end: 357 | if (fd>0) { close(fd); } 358 | if (s) { free(s); } 359 | 360 | return 0; 361 | } 362 | 363 | ``` 364 | 365 | and recompile it as: 366 | 367 | [me@machine ~/examples] gcc -Wall -O0 test.c -o test 368 | 369 | Run Secretgrind and get it to display variable names with option **--var-name=yes**: 370 | 371 | [me@machine ~/examples] secretgrind --var-name=yes --mnemonics=yes --summary-main-only=yes --summary-verbose=yes --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 372 | [me@machine ~/examples] ... 373 | 374 | 375 | ==123== [TAINT SUMMARY] - On end main(): 376 | --------------------------------------------------- 377 | 378 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 379 | > (malloc) [0x51ec040 - 0x51ec057] (24 bytes): @0x51ec040_malloc_4208_1 380 | tainted at 0x4F13F30: read (in /lib/x86_64-linux-gnu/libc-2.15.so) 381 | by 0x4007F6: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 382 | tainted by instruction 'syscall ' (raw=0f 05, ID=_1cb38_) 383 | Parent block [0x51ec040 - 0x51ec071] (50 bytes): @0x51ec040_malloc_4208_1 384 | malloc()'ed at 0x4C2B3E4: malloc (vg_replace_malloc.c:296) 385 | by 0x400750: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 386 | free()'ed at 0x4C2A2EA: free (vg_replace_malloc.c:473) 387 | by 0x40085D: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 388 | 389 | ***(2) (stack) range [0xffefffb4b - 0xffefffb4b] (1 bytes) is tainted 390 | > (stack) [0xffefffb4b - 0xffefffb4b] (1 bytes): obj_test1@0xffefffb4b_unknownvar_4208_1 391 | tainted at 0x400838: main (in /auto/homes/lmrs2/zero_mem/VALGRIND/tests/test1) 392 | tainted by instruction 'movb %al, -0x25(%rbp)' (raw=88 45 db, ID=_1cb41_) 393 | 394 | Total bytes tainted: 25 395 | ==123== 396 | 397 | As expected, an extra byte is tainted, and it is a stack variable. However, Secretgrind is unable to show the original variable name `obj_test1@0xffefffb4b_unknownvar_4208_1`. Try recompiling with debugging information: 398 | 399 | [me@machine ~/examples] gcc -g -Wall -O0 test.c -o test 400 | 401 | Re-run Secretgrind: 402 | 403 | [me@machine ~/examples] secretgrind --var-name=yes --mnemonics=yes --summary-main-only=yes --summary-verbose=yes --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 404 | [me@machine ~/examples] ... 405 | 406 | ==123== [TAINT SUMMARY] - On end main(): 407 | --------------------------------------------------- 408 | 409 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 410 | [...] 411 | 412 | ***(2) (stack) range [0xffefffb4b - 0xffefffb4b] (1 bytes) is tainted 413 | > (stack) [0xffefffb4b - 0xffefffb4b] (1 bytes): test1.c:18:@0xffefffb4b:stack_var 414 | tainted at 0x400838: main (test1.c:35) 415 | tainted by instruction 'movb %al, -0x25(%rbp)' (raw=88 45 db, ID=_1cb41_) 416 | 417 | Total bytes tainted: 25 418 | ==123== 419 | 420 | Secretgrind is now able to retrieve the variable name as `test1.c:18:@0xffefffb4b:stack_var`: the variable is stored at address 0xffefffb4b, its name is `stack_var` and it was declared in the file test1.c at line 18. 421 | 422 | Now recompile test.c with optimization and re-run Secretgrind: 423 | 424 | [me@machine ~/examples] gcc -Wall -O2 test.c -o test 425 | [me@machine ~/examples] secretgrind --var-name=yes --mnemonics=yes --summary-verbose=yes --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 426 | [me@machine ~/examples] ... 427 | 428 | ==123== [TAINT SUMMARY] - On end main(): 429 | --------------------------------------------------- 430 | 431 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 432 | [...] 433 | 434 | Total bytes tainted: 24 435 | ==123== 436 | 437 | The stack variable is no longer tainted. The compiler has optimized the binary somehow: for example, it may be keeping `stack_var` in a register rather than on the stack; or it may have removed `stack_var` entirely as this does not affect the program in a "meaningful" way. 438 | 439 | 9. Secretgrind can also display a live trace of what is executed with option **--trace=yes**. The output can be overwhelming, so if you are only interested in the taint, it is good practice to use the option **--trace-taint-only=yes**: 440 | 441 | [me@machine ~/examples] gcc -Wall -O0 test.c -o test # we want to see stack_var 442 | [me@machine ~/examples] secretgrind --trace-taint-only=yes --trace=yes --var-name=yes --mnemonics=yes --summary-main-only=yes --summary-verbose=yes --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 443 | [me@machine ~/examples] ... 444 | 445 | ==123== 0x400834: 0f b6 40 04: movzbl 4(%rax), %eax ID _1cb40_: 446 | ==123== 0x400834: main (in /home/me/examples/test) | t14_9600 = LOAD I8 t10_10371 | 0x2000000000000000 | 0xff00000000000000 | t14_9600 <- @0x51ec040_malloc_123_1 447 | ==123== 0x400834: main (in /home/me/examples/test) | t29_5404 = 8Uto32 t14_9600 | 0x2000000000000000 | 0xff00000000000000 | t29_5404 <- t14_9600 448 | ==123== 0x400834: main (in /home/me/examples/test) | t13_11966 = t29_5404 | 0x2000000000000000 | 0xff00000000000000 | t13_11966 <- t29_5404 449 | ==123== 0x400834: main (in /home/me/examples/test) | t30_6184 = 32Uto64 t13_11966 | 0x2000000000000000 | 0xff00000000000000 | t30_6184 <- t13_11966 450 | ==123== 0x400834: main (in /home/me/examples/test) | t12_11569 = t30_6184 | 0x2000000000000000 | 0xff00000000000000 | t12_11569 <- t30_6184 451 | ==123== 0x400834: main (in /home/me/examples/test) | r16_1 = t12_11569 | 0x2000000000000000 | 0xff00000000000000 | r16_1 <- t12_11569 452 | 453 | ==123== 0x400838: 88 45 db: movb %al, -0x25(%rbp) ID _1cb41_: 454 | ==123== 0x400838: main (in /home/me/examples/test) | t17_9609 = r16_1 I8 | 0x2000000000000000 | 0xff00000000000000 | t17_9609 <- r16_1 455 | ==123== 0x400838: main (in /home/me/examples/test) | STORE t15_10583 = t17_9609 | 0x2000000000000000 | 0xff00000000000000 | obj_test1@0xffefffb4b_unknownvar_123_1 <- t17_9609 456 | 457 | ==123== [TAINT SUMMARY] - On end main(): 458 | --------------------------------------------------- 459 | [...] 460 | 461 | Secretgrind displays each instruction that is executed. The first that appears in the run is `0f b6 40 04: movzbl 4(%rax), %eax ID _1cb40_:`. This shows both the raw instruction in hex `0f b6 40 04`, its mnemonics `movzbl 4(%rax), %eax`, and an instruction ID `_1cb40_`. This correponds to `stack_var = s[4];` in the source code. Valgrind represents an instruction in [Single-Static-Assignment (SSA) form](https://en.wikipedia.org/wiki/Static_single_assignment_form). This is why you see multiple lines of "execution" for each instruction. As explained in [Taintgrind](https://github.com/wmkhoo/taintgrind), the output is a list of Valgrind IR (VEX) statements of the form: 462 | 463 | Address/Location | VEX-IRStmt | Runtime value(s) | Taint value(s) | Information flow 464 | t14_9600 = LOAD I8 t10_10371 | 0x2000000000000000 | 0xff00000000000000 | t14_9600 <- @0x51ec040_malloc_123_1 465 | 466 | Details of VEX operators and IRStmts can be found in VEX/pub/libvex_ir.h . Secretgrind displays runtime values as they appear in memory: for example, on an LE platform the integer 4 will show as 0x04000000; on a BE platform it will show as 0x00000004. Here, `t14_9600` is an 8-bit integer `I8` loaded with value 0x2000000000000000. 0x20 is the space character ' ', which is indeed the 5th character of the string "This is a tainted file." contained in tainted.txt . The value loaded in `t14_9600` is "variable" `@0x51ec040_malloc_123_1`: data at memory address 0x51ec040, which is of type `malloc`, allocated by process with pid `123` and Valgrind thread ID `1`, ie `s[4]` in the source code. 467 | 468 | 10. If you are only interested in the total number of bytes tainted, and not the summary, you can use **--summary-total-only=yes**; or you can disable the summary with **--summary=no**. 469 | 470 | 471 | Client requests 472 | --------------- 473 | 474 | 1. Secretgrind may be further controlled via client requests defined in secretgrind.h: 475 | 476 | SG_PRINT_ALL_INST() -> print all instructions 477 | SG_PRINT_TAINTED_INST() -> print tainted instructions 478 | SG_STOP_PRINT() -> stop all printing 479 | 480 | SG_MAKE_MEM_TAINTED(address, length) -> taint memory region 481 | SG_MAKE_MEM_UNTAINTED(address, length) -> untaint memory region 482 | 483 | SG_TAINT_SUMMARY(name) -> display a summary 484 | SG_READ_TAINT_STATE(name, address, length) -> display taint for 'length' bytes from 'address' 485 | 486 | However, you should use those sparsely: as they are inserted in your code at compilation time, they change the original program binary. For example, you might see stack variables not tainted when you use these APIs, but tainted when you do not - the stack may be used to push function arguments... 487 | 488 | To use those APIs, you must `#include "secretgrind.h"` in your file: 489 | 490 | ```c 491 | #include 492 | #include 493 | #include 494 | #include 495 | #include 496 | #include 497 | #include 498 | #include 499 | #include 500 | 501 | #define LEN (50) 502 | 503 | #include "secretgrind.h" // header file for APIs 504 | 505 | int main(int argc, char* argv[]) 506 | { 507 | char *s = 0; 508 | int fd = 0; 509 | ssize_t n = 0; 510 | char stack_var = 0; 511 | 512 | if ( (s = malloc(LEN)) == 0) { 513 | printf("error malloc %d (%s)\n", errno, strerror(errno)); 514 | goto end; 515 | } 516 | 517 | if ( (fd = open (argv[1], O_RDWR )) < 0) { 518 | printf("error open %d (%s)\n", errno, strerror(errno)); 519 | goto end; 520 | } 521 | 522 | SG_TAINT_SUMMARY("before we read"); // show taint summary 523 | 524 | if ( (n = read(fd, s, LEN)) < 0) { 525 | printf("error read %d (%s)\n", errno, strerror(errno)); 526 | goto end; 527 | } 528 | 529 | SG_TAINT_SUMMARY("after we read"); // show taint summary 530 | 531 | stack_var = s[4]; // stack_var should be tainted 532 | 533 | SG_READ_TAINT_STATE("stack_var taint", &stack_var, sizeof(stack_var)); 534 | 535 | end: 536 | if (fd>0) { close(fd); } 537 | if (s) { free(s); } 538 | 539 | SG_MAKE_MEM_UNTAINTED(&stack_var, sizeof(stack_var)); // untaint the stack_var 540 | 541 | SG_MAKE_MEM_TAINTED(&n, sizeof(n)); // taint n 542 | 543 | return 0; 544 | } 545 | ``` 546 | 547 | 2. Tell the compiler where to find the header file `secretgrind.h`, and compile as: 548 | 549 | gcc -I/home/me/valgrind-3.10.1/inst/include/valgrind -Wall -O0 -g test.c -o test # we want to see stack_var and names 550 | 551 | 3. Run, for example: 552 | 553 | [me@machine ~/examples] secretgrind --var-name=yes --summary-main-only=yes --summary-verbose=yes --mnemonics=yes --file-filter=/home/me/examples/tainted.txt ./test tainted.txt 554 | [me@machine ~/examples] ... 555 | 556 | ==123== [TAINT SUMMARY] - before we read: 557 | --------------------------------------------------- 558 | 559 | No bytes tainted 560 | 561 | ==123== [TAINT SUMMARY] - after we read: 562 | --------------------------------------------------- 563 | 564 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 565 | [...] 566 | Total bytes tainted: 24 567 | 568 | ==123== [TAINT STATE]: stack_var taint (1 bytes) 569 | range [0xffefffa33 - 0xffefffa33] (1 bytes) is NOT tainted 570 | 571 | ==123== [TAINT SUMMARY] - On end main(): 572 | --------------------------------------------------- 573 | 574 | ***(1) (malloc) range [0x51ec040 - 0x51ec057] (24 bytes) is tainted 575 | > (malloc) [0x51ec040 - 0x51ec057] (24 bytes): @0x51ec040_malloc_10382_1 576 | tainted at 0x4F13F30: read (in /lib/x86_64-linux-gnu/libc-2.15.so) 577 | by 0x400AD3: main (test1.c:34) 578 | tainted by instruction 'syscall ' (raw=0f 05, ID=_1cb45_) 579 | Parent block [0x51ec040 - 0x51ec071] (50 bytes): @0x51ec040_malloc_10382_1 580 | malloc()'ed at 0x4C2B3E4: malloc (vg_replace_malloc.c:296) 581 | by 0x400997: main (test1.c:22) 582 | free()'ed at 0x4C2A2EA: free (vg_replace_malloc.c:473) 583 | by 0x400C50: main (test1.c:47) 584 | 585 | ***(1) (stack) range [0xffefffa38 - 0xffefffa3f] (8 bytes) is tainted 586 | > (stack) [0xffefffa38 - 0xffefffa3f] (8 bytes): test1.c:19:@0xffefffa38:n 587 | tainted at 0x400D16: main (test1.c:51) 588 | tainted by API call 589 | 590 | 591 | Total bytes tainted: 32 592 | ==123== 593 | 594 | We see additional information: two `[TAINT SUMMARY]` in response to calls to `SG_TAINT_SUMMARY()`, one `[TAINT STATE]` for `SG_READ_TAINT_STATE()`. At the end of `main()`, `stack_var` is no longer tainted due to the call to `SG_MAKE_MEM_UNTAINTED()`, and 8 additional bytes are tainted due to the call to `SG_MAKE_MEM_TAINTED()`. The instruction responsible for tainting `n` is `API call` because it was tainted artificially by a call to `SG_MAKE_MEM_TAINTED()`. 595 | 596 | Notes 597 | ----- 598 | Secretgrind is based on [Taintgrind](https://github.com/wmkhoo/taintgrind) by Wei Ming Khoo. 599 | Taintgrind is based on [Valgrind](http://valgrind/org)'s MemCheck and work by Will Drewry on [Flayer](http://code.google.com/p/flayer/). 600 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* config.h. Generated from config.h.in by configure. */ 2 | /* config.h.in. Generated from configure.ac by autoheader. */ 3 | 4 | /* Define to 1 if you're using Bionic */ 5 | /* #undef BIONIC_LIBC */ 6 | 7 | /* DARWIN_VERS value for Mac OS X 10.5 */ 8 | /* #undef DARWIN_10_5 */ 9 | 10 | /* DARWIN_VERS value for Mac OS X 10.6 */ 11 | /* #undef DARWIN_10_6 */ 12 | 13 | /* DARWIN_VERS value for Mac OS X 10.7 */ 14 | /* #undef DARWIN_10_7 */ 15 | 16 | /* DARWIN_VERS value for Mac OS X 10.8 */ 17 | /* #undef DARWIN_10_8 */ 18 | 19 | /* Define to 1 if you're using Darwin */ 20 | /* #undef DARWIN_LIBC */ 21 | 22 | /* Darwin / Mac OS X version */ 23 | /* #undef DARWIN_VERS */ 24 | 25 | /* Disable intercept pthread_spin_lock() on MIPS32 and MIPS64. */ 26 | /* #undef DISABLE_PTHREAD_SPINLOCK_INTERCEPT */ 27 | 28 | /* configured to run as an inner Valgrind */ 29 | /* #undef ENABLE_INNER */ 30 | 31 | /* path to GDB */ 32 | #define GDB_PATH "/usr/bin/gdb" 33 | 34 | /* Define to 1 if you're using glibc 2.10.x */ 35 | /* #undef GLIBC_2_10 */ 36 | 37 | /* Define to 1 if you're using glibc 2.11.x */ 38 | /* #undef GLIBC_2_11 */ 39 | 40 | /* Define to 1 if you're using glibc 2.12.x */ 41 | /* #undef GLIBC_2_12 */ 42 | 43 | /* Define to 1 if you're using glibc 2.13.x */ 44 | /* #undef GLIBC_2_13 */ 45 | 46 | /* Define to 1 if you're using glibc 2.14.x */ 47 | /* #undef GLIBC_2_14 */ 48 | 49 | /* Define to 1 if you're using glibc 2.15.x */ 50 | #define GLIBC_2_15 1 51 | 52 | /* Define to 1 if you're using glibc 2.16.x */ 53 | /* #undef GLIBC_2_16 */ 54 | 55 | /* Define to 1 if you're using glibc 2.17.x */ 56 | /* #undef GLIBC_2_17 */ 57 | 58 | /* Define to 1 if you're using glibc 2.18.x */ 59 | /* #undef GLIBC_2_18 */ 60 | 61 | /* Define to 1 if you're using glibc 2.19.x */ 62 | /* #undef GLIBC_2_19 */ 63 | 64 | /* Define to 1 if you're using glibc 2.2.x */ 65 | /* #undef GLIBC_2_2 */ 66 | 67 | /* Define to 1 if you're using glibc 2.20.x */ 68 | /* #undef GLIBC_2_20 */ 69 | 70 | /* Define to 1 if you're using glibc 2.3.x */ 71 | /* #undef GLIBC_2_3 */ 72 | 73 | /* Define to 1 if you're using glibc 2.4.x */ 74 | /* #undef GLIBC_2_4 */ 75 | 76 | /* Define to 1 if you're using glibc 2.5.x */ 77 | /* #undef GLIBC_2_5 */ 78 | 79 | /* Define to 1 if you're using glibc 2.6.x */ 80 | /* #undef GLIBC_2_6 */ 81 | 82 | /* Define to 1 if you're using glibc 2.7.x */ 83 | /* #undef GLIBC_2_7 */ 84 | 85 | /* Define to 1 if you're using glibc 2.8.x */ 86 | /* #undef GLIBC_2_8 */ 87 | 88 | /* Define to 1 if you're using glibc 2.9.x */ 89 | /* #undef GLIBC_2_9 */ 90 | 91 | /* Define to 1 if gcc/as can do Altivec. */ 92 | /* #undef HAS_ALTIVEC */ 93 | 94 | /* Define to 1 if you have the header file. */ 95 | #define HAVE_ASM_UNISTD_H 1 96 | 97 | /* Define to 1 if as supports floating point phased out category. */ 98 | /* #undef HAVE_AS_PPC_FPPO */ 99 | 100 | /* Define to 1 if as supports mtocrf/mfocrf. */ 101 | /* #undef HAVE_AS_PPC_MFTOCRF */ 102 | 103 | /* Define to 1 if gcc supports __sync_bool_compare_and_swap() and 104 | __sync_add_and_fetch() for the primary target */ 105 | #define HAVE_BUILTIN_ATOMIC 1 106 | 107 | /* Define to 1 if g++ supports __sync_bool_compare_and_swap() and 108 | __sync_add_and_fetch() */ 109 | #define HAVE_BUILTIN_ATOMIC_CXX 1 110 | 111 | /* Define to 1 if you have the `clock_gettime' function. */ 112 | #define HAVE_CLOCK_GETTIME 1 113 | 114 | /* Define to 1 if you have the `CLOCK_MONOTONIC' constant. */ 115 | #define HAVE_CLOCK_MONOTONIC 1 116 | 117 | /* Define to 1 if you have the header file. */ 118 | #define HAVE_ENDIAN_H 1 119 | 120 | /* Define to 1 if you have the `epoll_create' function. */ 121 | #define HAVE_EPOLL_CREATE 1 122 | 123 | /* Define to 1 if you have the `epoll_pwait' function. */ 124 | #define HAVE_EPOLL_PWAIT 1 125 | 126 | /* Define to 1 if you have the `eventfd' function. */ 127 | #define HAVE_EVENTFD 1 128 | 129 | /* Define to 1 if you have the `eventfd_read' function. */ 130 | #define HAVE_EVENTFD_READ 1 131 | 132 | /* Define to 1 if you have the `getpagesize' function. */ 133 | #define HAVE_GETPAGESIZE 1 134 | 135 | /* Define to 1 if you have the header file. */ 136 | #define HAVE_INTTYPES_H 1 137 | 138 | /* Define to 1 if you have the `klogctl' function. */ 139 | #define HAVE_KLOGCTL 1 140 | 141 | /* Define to 1 if you have the `pthread' library (-lpthread). */ 142 | #define HAVE_LIBPTHREAD 1 143 | 144 | /* Define to 1 if you have the `rt' library (-lrt). */ 145 | #define HAVE_LIBRT 1 146 | 147 | /* Define to 1 if you have the `mallinfo' function. */ 148 | #define HAVE_MALLINFO 1 149 | 150 | /* Define to 1 if you have the `memchr' function. */ 151 | #define HAVE_MEMCHR 1 152 | 153 | /* Define to 1 if you have the header file. */ 154 | #define HAVE_MEMORY_H 1 155 | 156 | /* Define to 1 if you have the `memset' function. */ 157 | #define HAVE_MEMSET 1 158 | 159 | /* Define to 1 if you have the `mkdir' function. */ 160 | #define HAVE_MKDIR 1 161 | 162 | /* Define to 1 if you have a working `mmap' system call. */ 163 | #define HAVE_MMAP 1 164 | 165 | /* Define to 1 if you have the header file. */ 166 | #define HAVE_MQUEUE_H 1 167 | 168 | /* Define to 1 if you have the `mremap' function. */ 169 | #define HAVE_MREMAP 1 170 | 171 | /* Define to 1 if you have the `ppoll' function. */ 172 | #define HAVE_PPOLL 1 173 | 174 | /* Define to 1 if you have the `process_vm_readv' function. */ 175 | #define HAVE_PROCESS_VM_READV 1 176 | 177 | /* Define to 1 if you have the `process_vm_writev' function. */ 178 | #define HAVE_PROCESS_VM_WRITEV 1 179 | 180 | /* Define to 1 if you have the `pthread_barrier_init' function. */ 181 | #define HAVE_PTHREAD_BARRIER_INIT 1 182 | 183 | /* Define to 1 if you have the `pthread_condattr_setclock' function. */ 184 | #define HAVE_PTHREAD_CONDATTR_SETCLOCK 1 185 | 186 | /* Define to 1 if you have the `pthread_create@glibc2.0' function. */ 187 | /* #undef HAVE_PTHREAD_CREATE_GLIBC_2_0 */ 188 | 189 | /* Define to 1 if you have the `PTHREAD_MUTEX_ADAPTIVE_NP' constant. */ 190 | #define HAVE_PTHREAD_MUTEX_ADAPTIVE_NP 1 191 | 192 | /* Define to 1 if you have the `PTHREAD_MUTEX_ERRORCHECK_NP' constant. */ 193 | #define HAVE_PTHREAD_MUTEX_ERRORCHECK_NP 1 194 | 195 | /* Define to 1 if you have the `PTHREAD_MUTEX_RECURSIVE_NP' constant. */ 196 | #define HAVE_PTHREAD_MUTEX_RECURSIVE_NP 1 197 | 198 | /* Define to 1 if you have the `pthread_mutex_timedlock' function. */ 199 | #define HAVE_PTHREAD_MUTEX_TIMEDLOCK 1 200 | 201 | /* Define to 1 if pthread_mutex_t has a member __data.__kind. */ 202 | #define HAVE_PTHREAD_MUTEX_T__DATA__KIND 1 203 | 204 | /* Define to 1 if pthread_mutex_t has a member called __m_kind. */ 205 | /* #undef HAVE_PTHREAD_MUTEX_T__M_KIND */ 206 | 207 | /* Define to 1 if you have the `PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP' 208 | constant. */ 209 | #define HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 1 210 | 211 | /* Define to 1 if you have the `pthread_rwlock_t' type. */ 212 | #define HAVE_PTHREAD_RWLOCK_T 1 213 | 214 | /* Define to 1 if you have the `pthread_rwlock_timedrdlock' function. */ 215 | #define HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK 1 216 | 217 | /* Define to 1 if you have the `pthread_rwlock_timedwrlock' function. */ 218 | #define HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK 1 219 | 220 | /* Define to 1 if you have the `pthread_setname_np' function. */ 221 | #define HAVE_PTHREAD_SETNAME_NP 1 222 | 223 | /* Define to 1 if you have the `pthread_spin_lock' function. */ 224 | #define HAVE_PTHREAD_SPIN_LOCK 1 225 | 226 | /* Define to 1 if you have the `pthread_yield' function. */ 227 | #define HAVE_PTHREAD_YIELD 1 228 | 229 | /* Define to 1 if you have the `PTRACE_GETREGS' ptrace request. */ 230 | #define HAVE_PTRACE_GETREGS 1 231 | 232 | /* Define to 1 if you have the `readlinkat' function. */ 233 | #define HAVE_READLINKAT 1 234 | 235 | /* Define to 1 if you have the `semtimedop' function. */ 236 | #define HAVE_SEMTIMEDOP 1 237 | 238 | /* Define to 1 if libstd++ supports annotating shared pointers */ 239 | #define HAVE_SHARED_POINTER_ANNOTATION 1 240 | 241 | /* Define to 1 if you have the `signalfd' function. */ 242 | #define HAVE_SIGNALFD 1 243 | 244 | /* Define to 1 if you have the `sigwaitinfo' function. */ 245 | #define HAVE_SIGWAITINFO 1 246 | 247 | /* Define to 1 if you have the header file. */ 248 | #define HAVE_STDINT_H 1 249 | 250 | /* Define to 1 if you have the header file. */ 251 | #define HAVE_STDLIB_H 1 252 | 253 | /* Define to 1 if you have the `strchr' function. */ 254 | #define HAVE_STRCHR 1 255 | 256 | /* Define to 1 if you have the `strdup' function. */ 257 | #define HAVE_STRDUP 1 258 | 259 | /* Define to 1 if you have the header file. */ 260 | #define HAVE_STRINGS_H 1 261 | 262 | /* Define to 1 if you have the header file. */ 263 | #define HAVE_STRING_H 1 264 | 265 | /* Define to 1 if you have the `strpbrk' function. */ 266 | #define HAVE_STRPBRK 1 267 | 268 | /* Define to 1 if you have the `strrchr' function. */ 269 | #define HAVE_STRRCHR 1 270 | 271 | /* Define to 1 if you have the `strstr' function. */ 272 | #define HAVE_STRSTR 1 273 | 274 | /* Define to 1 if you have the `syscall' function. */ 275 | #define HAVE_SYSCALL 1 276 | 277 | /* Define to 1 if you have the header file. */ 278 | /* #undef HAVE_SYS_ENDIAN_H */ 279 | 280 | /* Define to 1 if you have the header file. */ 281 | #define HAVE_SYS_EPOLL_H 1 282 | 283 | /* Define to 1 if you have the header file. */ 284 | #define HAVE_SYS_EVENTFD_H 1 285 | 286 | /* Define to 1 if you have the header file. */ 287 | #define HAVE_SYS_KLOG_H 1 288 | 289 | /* Define to 1 if you have the header file. */ 290 | #define HAVE_SYS_PARAM_H 1 291 | 292 | /* Define to 1 if you have the header file. */ 293 | #define HAVE_SYS_POLL_H 1 294 | 295 | /* Define to 1 if you have the header file. */ 296 | #define HAVE_SYS_SIGNALFD_H 1 297 | 298 | /* Define to 1 if you have the header file. */ 299 | #define HAVE_SYS_SIGNAL_H 1 300 | 301 | /* Define to 1 if you have the header file. */ 302 | #define HAVE_SYS_STAT_H 1 303 | 304 | /* Define to 1 if you have the header file. */ 305 | #define HAVE_SYS_SYSCALL_H 1 306 | 307 | /* Define to 1 if you have the header file. */ 308 | #define HAVE_SYS_TIME_H 1 309 | 310 | /* Define to 1 if you have the header file. */ 311 | #define HAVE_SYS_TYPES_H 1 312 | 313 | /* can use __thread to define thread-local variables */ 314 | #define HAVE_TLS 1 315 | 316 | /* Define to 1 if you have the header file. */ 317 | #define HAVE_UNISTD_H 1 318 | 319 | /* Define to 1 if you have a usable header file. */ 320 | #define HAVE_USABLE_LINUX_FUTEX_H 1 321 | 322 | /* Define to 1 if you have the `utimensat' function. */ 323 | #define HAVE_UTIMENSAT 1 324 | 325 | /* Define to 1 if you're using Linux 2.4.x */ 326 | /* #undef KERNEL_2_4 */ 327 | 328 | /* Define to 1 if you're using Linux 2.6.x or Linux 3.x */ 329 | #define KERNEL_2_6 1 330 | 331 | /* configured default page size 4k */ 332 | #define MIPS_PAGE_SHIFT 12 333 | 334 | /* Define to 1 if your C compiler doesn't accept -c and -o together. */ 335 | /* #undef NO_MINUS_C_MINUS_O */ 336 | 337 | /* Name of package */ 338 | #define PACKAGE "valgrind" 339 | 340 | /* Define to the address where bug reports for this package should be sent. */ 341 | #define PACKAGE_BUGREPORT "valgrind-users@lists.sourceforge.net" 342 | 343 | /* Define to the full name of this package. */ 344 | #define PACKAGE_NAME "Valgrind" 345 | 346 | /* Define to the full name and version of this package. */ 347 | #define PACKAGE_STRING "Valgrind 3.9.0" 348 | 349 | /* Define to the one symbol short name of this package. */ 350 | #define PACKAGE_TARNAME "valgrind" 351 | 352 | /* Define to the home page for this package. */ 353 | #define PACKAGE_URL "" 354 | 355 | /* Define to the version of this package. */ 356 | #define PACKAGE_VERSION "3.9.0" 357 | 358 | /* Define to 1 if you have the ANSI C header files. */ 359 | #define STDC_HEADERS 1 360 | 361 | /* Define to 1 if you can safely include both and . */ 362 | #define TIME_WITH_SYS_TIME 1 363 | 364 | /* Version number of package */ 365 | #define VERSION "3.9.0" 366 | 367 | /* Temporary files directory */ 368 | #define VG_TMPDIR "/tmp" 369 | 370 | /* Define to `int' if doesn't define. */ 371 | /* #undef gid_t */ 372 | 373 | /* Define to `long int' if does not define. */ 374 | /* #undef off_t */ 375 | 376 | /* Define to `unsigned int' if does not define. */ 377 | /* #undef size_t */ 378 | 379 | /* Define to `int' if doesn't define. */ 380 | /* #undef uid_t */ 381 | -------------------------------------------------------------------------------- /configure_capstone.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ $# -ne 1 ] 3 | then 4 | echo "Error in $0 - Invalid Argument Count" 5 | echo "Usage: $0 " 6 | exit 7 | fi 8 | 9 | # example: sh configure_capstone.sh `pwd`/../inst 10 | 11 | VG_INST_DIR=$1 12 | 13 | CAPSTONE_VERSION="3.0.4" 14 | 15 | #- 1 Apply patches 16 | #================== 17 | # guide to patches http://www.cyberciti.biz/faq/appy-patch-file-using-patch-command/ 18 | # patches were created with 19 | # diff -rupN ./capstone/ ./capstone.patches/ > capstone.patch 20 | # then I removed the Makefile one and the VG_define coz it fails or complains 21 | 22 | patch -p1 < ./capstone-$CAPSTONE_VERSION.patch 23 | retval=$? 24 | if [ $retval -ne 0 ]; then 25 | echo "Return code was not zero but $retval" 26 | exit 27 | fi 28 | 29 | #-2 create make_capstone.sh with the rigth args 30 | python make_capstone_options.py --vginstdir $VG_INST_DIR --capstonedir capstone-$CAPSTONE_VERSION --outmakefile make_capstone.sh 31 | retval=$? 32 | if [ $retval -ne 0 ]; then 33 | echo "Return code was not zero but $retval" 34 | exit 35 | fi 36 | 37 | -------------------------------------------------------------------------------- /configure_valgrind.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #- 1 Apply patches 4 | #================== 5 | # guide to patches http://www.cyberciti.biz/faq/appy-patch-file-using-patch-command/ 6 | # patches were created with 7 | # cd ../coregrind/ 8 | # diff -u m_execontext.c m_execontext.c.patch > ../taintgrind/valgrind.patch 9 | 10 | cd ../coregrind/ 11 | patch < ../secretgrind/valgrind.patch 12 | retval=$? 13 | if [ $retval -ne 0 ]; then 14 | echo "Return code was not zero but $retval" 15 | exit 16 | fi 17 | 18 | echo SUCCESS 19 | -------------------------------------------------------------------------------- /copy.c: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------*/ 2 | /*-------------------------------- AVALANCHE -------------------------------------*/ 3 | /*--- Tracegring. Transforms IR tainted trace to STP declarations. copy.c ---*/ 4 | /*--------------------------------------------------------------------------------*/ 5 | 6 | /* 7 | This file is part of Tracegrind, the Valgrind tool, 8 | which tracks tainted data coming from the specified file 9 | and converts IR trace to STP declarations. 10 | 11 | Copyright (C) 2009 Ildar Isaev 12 | iisaev@ispras.ru 13 | 14 | This program is free software; you can redistribute it and/or 15 | modify it under the terms of the GNU General Public License as 16 | published by the Free Software Foundation; either version 2 of the 17 | License, or (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, but 20 | WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program; if not, write to the Free Software 26 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 | 02111-1307, USA. 28 | 29 | The GNU General Public License is contained in the file COPYING. 30 | */ 31 | 32 | #include "copy.h" 33 | #include "pub_tool_mallocfree.h" 34 | 35 | IRConst* mallocIRConst_U1(Bool bit) 36 | { 37 | IRConst* c = VG_(malloc)("IRConst", sizeof(IRConst)); 38 | c->tag = Ico_U1; 39 | c->Ico.U1 = bit; 40 | return c; 41 | } 42 | IRConst* mallocIRConst_U8(UChar u8) 43 | { 44 | IRConst* c = VG_(malloc)("IRConst", sizeof(IRConst)); 45 | c->tag = Ico_U8; 46 | c->Ico.U8 = u8; 47 | return c; 48 | } 49 | IRConst* mallocIRConst_U16(UShort u16) 50 | { 51 | IRConst* c = VG_(malloc)("IRConst", sizeof(IRConst)); 52 | c->tag = Ico_U16; 53 | c->Ico.U16 = u16; 54 | return c; 55 | } 56 | IRConst* mallocIRConst_U32(UInt u32) 57 | { 58 | IRConst* c = VG_(malloc)("IRConst", sizeof(IRConst)); 59 | c->tag = Ico_U32; 60 | c->Ico.U32 = u32; 61 | return c; 62 | } 63 | IRConst* mallocIRConst_U64(ULong u64) 64 | { 65 | IRConst* c = VG_(malloc)("IRConst", sizeof(IRConst)); 66 | c->tag = Ico_U64; 67 | c->Ico.U64 = u64; 68 | return c; 69 | } 70 | IRConst* mallocIRConst_F64(Double f64) 71 | { 72 | IRConst* c = VG_(malloc)("IRConst", sizeof(IRConst)); 73 | c->tag = Ico_F64; 74 | c->Ico.F64 = f64; 75 | return c; 76 | } 77 | IRConst* mallocIRConst_F64i(ULong f64i) 78 | { 79 | IRConst* c = VG_(malloc)("IRConst", sizeof(IRConst)); 80 | c->tag = Ico_F64i; 81 | c->Ico.F64i = f64i; 82 | return c; 83 | } 84 | IRConst* mallocIRConst_V128(UShort con) 85 | { 86 | IRConst* c = VG_(malloc)("IRConst", sizeof(IRConst)); 87 | c->tag = Ico_V128; 88 | c->Ico.V128 = con; 89 | return c; 90 | } 91 | 92 | 93 | 94 | IRCallee* mallocIRCallee(Int regparms, const HChar* name, void* addr) 95 | { 96 | IRCallee* ce = VG_(malloc)("IRCallee", sizeof(IRCallee)); 97 | ce->regparms = regparms; 98 | ce->name = name; 99 | ce->addr = addr; 100 | ce->mcx_mask = 0; 101 | return ce; 102 | } 103 | 104 | IRRegArray* mallocIRRegArray(Int base, IRType elemTy, Int nElems) 105 | { 106 | IRRegArray* arr = VG_(malloc)("IRRegArray", sizeof(IRRegArray)); 107 | arr->base = base; 108 | arr->elemTy = elemTy; 109 | arr->nElems = nElems; 110 | return arr; 111 | } 112 | 113 | IRExpr* mallocIRExpr_Binder(Int binder) { 114 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 115 | e->tag = Iex_Binder; 116 | e->Iex.Binder.binder = binder; 117 | return e; 118 | } 119 | IRExpr* mallocIRExpr_Get(Int off, IRType ty) { 120 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 121 | e->tag = Iex_Get; 122 | e->Iex.Get.offset = off; 123 | e->Iex.Get.ty = ty; 124 | return e; 125 | } 126 | IRExpr* mallocIRExpr_GetI(IRRegArray* descr, IRExpr* ix, Int bias) { 127 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 128 | e->tag = Iex_GetI; 129 | e->Iex.GetI.descr = descr; 130 | e->Iex.GetI.ix = ix; 131 | e->Iex.GetI.bias = bias; 132 | return e; 133 | } 134 | IRExpr* mallocIRExpr_RdTmp(IRTemp tmp) { 135 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 136 | e->tag = Iex_RdTmp; 137 | e->Iex.RdTmp.tmp = tmp; 138 | return e; 139 | } 140 | IRExpr* mallocIRExpr_Qop(IROp op, IRExpr* arg1, IRExpr* arg2, 141 | IRExpr* arg3, IRExpr* arg4) { 142 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 143 | e->tag = Iex_Qop; 144 | IRQop *details = VG_(malloc)("IRQop", sizeof(IRQop)); 145 | e->Iex.Qop.details = details; 146 | e->Iex.Qop.details->op = op; 147 | e->Iex.Qop.details->arg1 = arg1; 148 | e->Iex.Qop.details->arg2 = arg2; 149 | e->Iex.Qop.details->arg3 = arg3; 150 | e->Iex.Qop.details->arg4 = arg4; 151 | return e; 152 | } 153 | IRExpr* mallocIRExpr_Triop (IROp op, IRExpr* arg1, 154 | IRExpr* arg2, IRExpr* arg3) { 155 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 156 | e->tag = Iex_Triop; 157 | IRTriop *details = VG_(malloc)("IRTriop", sizeof(IRTriop)); 158 | e->Iex.Triop.details = details; 159 | e->Iex.Triop.details->op = op; 160 | e->Iex.Triop.details->arg1 = arg1; 161 | e->Iex.Triop.details->arg2 = arg2; 162 | e->Iex.Triop.details->arg3 = arg3; 163 | return e; 164 | } 165 | IRExpr* mallocIRExpr_Binop(IROp op, IRExpr* arg1, IRExpr* arg2) { 166 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 167 | e->tag = Iex_Binop; 168 | e->Iex.Binop.op = op; 169 | e->Iex.Binop.arg1 = arg1; 170 | e->Iex.Binop.arg2 = arg2; 171 | return e; 172 | } 173 | IRExpr* mallocIRExpr_Unop(IROp op, IRExpr* arg) { 174 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 175 | e->tag = Iex_Unop; 176 | e->Iex.Unop.op = op; 177 | e->Iex.Unop.arg = arg; 178 | return e; 179 | } 180 | IRExpr* mallocIRExpr_Load(IREndness end, IRType ty, IRExpr* addr) { 181 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 182 | e->tag = Iex_Load; 183 | e->Iex.Load.end = end; 184 | e->Iex.Load.ty = ty; 185 | e->Iex.Load.addr = addr; 186 | return e; 187 | } 188 | IRExpr* mallocIRExpr_Const(IRConst* con) { 189 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 190 | e->tag = Iex_Const; 191 | e->Iex.Const.con = con; 192 | return e; 193 | } 194 | IRExpr* mallocIRExpr_CCall(IRCallee* cee, IRType retty, IRExpr** args) { 195 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 196 | e->tag = Iex_CCall; 197 | e->Iex.CCall.cee = cee; 198 | e->Iex.CCall.retty = retty; 199 | e->Iex.CCall.args = args; 200 | return e; 201 | } 202 | IRExpr* mallocIRExpr_ITE(IRExpr* cond, IRExpr* iftrue, IRExpr* iffalse) { 203 | IRExpr* e = VG_(malloc)("IRExpr", sizeof(IRExpr)); 204 | e->tag = Iex_ITE; 205 | e->Iex.ITE.cond = cond; 206 | e->Iex.ITE.iftrue = iftrue; 207 | e->Iex.ITE.iffalse = iffalse; 208 | return e; 209 | } 210 | 211 | IRDirty* mallocEmptyIRDirty(void) { 212 | IRDirty* d = VG_(malloc)("IRExpr", sizeof(IRDirty)); 213 | d->cee = NULL; 214 | d->guard = NULL; 215 | d->args = NULL; 216 | d->tmp = IRTemp_INVALID; 217 | d->mFx = Ifx_None; 218 | d->mAddr = NULL; 219 | d->mSize = 0; 220 | d->nFxState = 0; 221 | return d; 222 | } 223 | 224 | 225 | 226 | IRStmt* mallocIRStmt_NoOp(void) 227 | { 228 | /* Just use a single static closure. */ 229 | static IRStmt static_closure; 230 | static_closure.tag = Ist_NoOp; 231 | return &static_closure; 232 | } 233 | IRStmt* mallocIRStmt_IMark(Addr64 addr, Int len) { 234 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 235 | s->tag = Ist_IMark; 236 | s->Ist.IMark.addr = addr; 237 | s->Ist.IMark.len = len; 238 | return s; 239 | } 240 | IRStmt* mallocIRStmt_AbiHint(IRExpr* base, Int len, IRExpr* nia) { 241 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 242 | s->tag = Ist_AbiHint; 243 | s->Ist.AbiHint.base = base; 244 | s->Ist.AbiHint.len = len; 245 | s->Ist.AbiHint.nia = nia; 246 | return s; 247 | } 248 | IRStmt* mallocIRStmt_Put(Int off, IRExpr* data) { 249 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 250 | s->tag = Ist_Put; 251 | s->Ist.Put.offset = off; 252 | s->Ist.Put.data = data; 253 | return s; 254 | } 255 | IRStmt* mallocIRStmt_PutI(IRRegArray* descr, IRExpr* ix, 256 | Int bias, IRExpr* data) { 257 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 258 | s->tag = Ist_PutI; 259 | IRPutI *details = VG_(malloc)("IRPutI", sizeof(IRPutI)); 260 | s->Ist.PutI.details = details; 261 | s->Ist.PutI.details->descr = descr; 262 | s->Ist.PutI.details->ix = ix; 263 | s->Ist.PutI.details->bias = bias; 264 | s->Ist.PutI.details->data = data; 265 | return s; 266 | } 267 | IRStmt* mallocIRStmt_WrTmp(IRTemp tmp, IRExpr* data) { 268 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 269 | s->tag = Ist_WrTmp; 270 | s->Ist.WrTmp.tmp = tmp; 271 | s->Ist.WrTmp.data = data; 272 | return s; 273 | } 274 | IRStmt* mallocIRStmt_Store(IREndness end, IRExpr* addr, IRExpr* data) { 275 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 276 | s->tag = Ist_Store; 277 | s->Ist.Store.end = end; 278 | s->Ist.Store.addr = addr; 279 | s->Ist.Store.data = data; 280 | return s; 281 | } 282 | IRStmt* mallocIRStmt_Dirty(IRDirty* d) 283 | { 284 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 285 | s->tag = Ist_Dirty; 286 | s->Ist.Dirty.details = d; 287 | return s; 288 | } 289 | IRStmt* mallocIRStmt_MBE(IRMBusEvent event) 290 | { 291 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 292 | s->tag = Ist_MBE; 293 | s->Ist.MBE.event = event; 294 | return s; 295 | } 296 | IRStmt* mallocIRStmt_Exit(IRExpr* guard, IRJumpKind jk, IRConst* dst) { 297 | IRStmt* s = VG_(malloc)("IRStmt", sizeof(IRStmt)); 298 | s->tag = Ist_Exit; 299 | s->Ist.Exit.guard = guard; 300 | s->Ist.Exit.jk = jk; 301 | s->Ist.Exit.dst = dst; 302 | return s; 303 | } 304 | 305 | IRExpr** shallowMallocIRExprVec(IRExpr** vec) 306 | { 307 | Int i; 308 | IRExpr** newvec; 309 | for (i = 0; vec[i]; i++) 310 | ; 311 | newvec = VG_(malloc)("IRExprVec", (i+1)*sizeof(IRExpr*)); 312 | for (i = 0; vec[i]; i++) 313 | newvec[i] = vec[i]; 314 | newvec[i] = NULL; 315 | return newvec; 316 | } 317 | 318 | IRExpr** deepMallocIRExprVec(IRExpr** vec) 319 | { 320 | Int i; 321 | IRExpr** newvec = shallowMallocIRExprVec( vec); 322 | for (i = 0; newvec[i]; i++) 323 | newvec[i] = deepMallocIRExpr(newvec[i]); 324 | return newvec; 325 | } 326 | 327 | IRConst* deepMallocIRConst(IRConst* c) 328 | { 329 | switch (c->tag) { 330 | case Ico_U1: return mallocIRConst_U1(c->Ico.U1); 331 | case Ico_U8: return mallocIRConst_U8(c->Ico.U8); 332 | case Ico_U16: return mallocIRConst_U16(c->Ico.U16); 333 | case Ico_U32: return mallocIRConst_U32(c->Ico.U32); 334 | case Ico_U64: return mallocIRConst_U64(c->Ico.U64); 335 | case Ico_F64: return mallocIRConst_F64(c->Ico.F64); 336 | case Ico_F64i: return mallocIRConst_F64i(c->Ico.F64i); 337 | case Ico_V128: return mallocIRConst_V128(c->Ico.V128); 338 | default: return NULL; 339 | } 340 | } 341 | 342 | IRCallee* deepMallocIRCallee(IRCallee* ce) 343 | { 344 | IRCallee* ce2 = mallocIRCallee(ce->regparms, ce->name, ce->addr); 345 | ce2->mcx_mask = ce->mcx_mask; 346 | return ce2; 347 | } 348 | 349 | IRRegArray* deepMallocIRRegArray(IRRegArray* d) 350 | { 351 | return mallocIRRegArray(d->base, d->elemTy, d->nElems); 352 | } 353 | 354 | IRExpr* deepMallocIRExpr(IRExpr* e) 355 | { 356 | switch (e->tag) { 357 | case Iex_Get: 358 | return mallocIRExpr_Get(e->Iex.Get.offset, e->Iex.Get.ty); 359 | case Iex_GetI: 360 | return mallocIRExpr_GetI(deepMallocIRRegArray(e->Iex.GetI.descr), 361 | deepMallocIRExpr(e->Iex.GetI.ix), 362 | e->Iex.GetI.bias); 363 | case Iex_RdTmp: 364 | return mallocIRExpr_RdTmp(e->Iex.RdTmp.tmp); 365 | case Iex_Qop: 366 | return mallocIRExpr_Qop(e->Iex.Qop.details->op, 367 | deepMallocIRExpr(e->Iex.Qop.details->arg1), 368 | deepMallocIRExpr(e->Iex.Qop.details->arg2), 369 | deepMallocIRExpr(e->Iex.Qop.details->arg3), 370 | deepMallocIRExpr(e->Iex.Qop.details->arg4)); 371 | case Iex_Triop: 372 | return mallocIRExpr_Triop(e->Iex.Triop.details->op, 373 | deepMallocIRExpr(e->Iex.Triop.details->arg1), 374 | deepMallocIRExpr(e->Iex.Triop.details->arg2), 375 | deepMallocIRExpr(e->Iex.Triop.details->arg3)); 376 | case Iex_Binop: 377 | return mallocIRExpr_Binop(e->Iex.Binop.op, 378 | deepMallocIRExpr(e->Iex.Binop.arg1), 379 | deepMallocIRExpr(e->Iex.Binop.arg2)); 380 | case Iex_Unop: 381 | return mallocIRExpr_Unop(e->Iex.Unop.op, 382 | deepMallocIRExpr(e->Iex.Unop.arg)); 383 | case Iex_Load: 384 | return mallocIRExpr_Load(e->Iex.Load.end, 385 | e->Iex.Load.ty, 386 | deepMallocIRExpr(e->Iex.Load.addr)); 387 | case Iex_Const: 388 | return mallocIRExpr_Const(deepMallocIRConst(e->Iex.Const.con)); 389 | case Iex_CCall: 390 | return mallocIRExpr_CCall(deepMallocIRCallee(e->Iex.CCall.cee), 391 | e->Iex.CCall.retty, 392 | deepMallocIRExprVec(e->Iex.CCall.args)); 393 | 394 | case Iex_ITE: 395 | return mallocIRExpr_ITE(deepMallocIRExpr(e->Iex.ITE.cond), 396 | deepMallocIRExpr(e->Iex.ITE.iftrue), 397 | deepMallocIRExpr(e->Iex.ITE.iffalse)); 398 | default: 399 | return NULL; 400 | } 401 | } 402 | 403 | IRDirty* deepMallocIRDirty(IRDirty* d) 404 | { 405 | Int i; 406 | IRDirty* d2 = mallocEmptyIRDirty(); 407 | d2->cee = deepMallocIRCallee(d->cee); 408 | d2->guard = deepMallocIRExpr(d->guard); 409 | d2->args = deepMallocIRExprVec(d->args); 410 | d2->tmp = d->tmp; 411 | d2->mFx = d->mFx; 412 | d2->mAddr = d->mAddr==NULL ? NULL : deepMallocIRExpr(d->mAddr); 413 | d2->mSize = d->mSize; 414 | d2->nFxState = d->nFxState; 415 | for (i = 0; i < d2->nFxState; i++) 416 | d2->fxState[i] = d->fxState[i]; 417 | return d2; 418 | } 419 | 420 | IRStmt* deepMallocIRStmt(IRStmt* s) 421 | { 422 | switch (s->tag) { 423 | case Ist_NoOp: 424 | return mallocIRStmt_NoOp(); 425 | case Ist_AbiHint: 426 | return mallocIRStmt_AbiHint(deepMallocIRExpr(s->Ist.AbiHint.base), 427 | s->Ist.AbiHint.len, 428 | deepMallocIRExpr(s->Ist.AbiHint.nia)); 429 | case Ist_IMark: 430 | return mallocIRStmt_IMark(s->Ist.IMark.addr, s->Ist.IMark.len); 431 | case Ist_Put: 432 | return mallocIRStmt_Put(s->Ist.Put.offset, 433 | deepMallocIRExpr(s->Ist.Put.data)); 434 | case Ist_PutI: 435 | return mallocIRStmt_PutI(deepMallocIRRegArray(s->Ist.PutI.details->descr), 436 | deepMallocIRExpr(s->Ist.PutI.details->ix), 437 | s->Ist.PutI.details->bias, 438 | deepMallocIRExpr(s->Ist.PutI.details->data)); 439 | case Ist_WrTmp: 440 | return mallocIRStmt_WrTmp(s->Ist.WrTmp.tmp, 441 | deepMallocIRExpr(s->Ist.WrTmp.data)); 442 | case Ist_Store: 443 | return mallocIRStmt_Store(s->Ist.Store.end, 444 | deepMallocIRExpr(s->Ist.Store.addr), 445 | deepMallocIRExpr(s->Ist.Store.data)); 446 | case Ist_Dirty: 447 | return mallocIRStmt_Dirty(deepMallocIRDirty(s->Ist.Dirty.details)); 448 | case Ist_MBE: 449 | return mallocIRStmt_MBE(s->Ist.MBE.event); 450 | case Ist_Exit: 451 | return mallocIRStmt_Exit(deepMallocIRExpr(s->Ist.Exit.guard), 452 | s->Ist.Exit.jk, 453 | deepMallocIRConst(s->Ist.Exit.dst)); 454 | default: 455 | return NULL; 456 | } 457 | } 458 | 459 | -------------------------------------------------------------------------------- /copy.h: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------*/ 2 | /*-------------------------------- AVALANCHE -------------------------------------*/ 3 | /*--- Tracegring. Transforms IR tainted trace to STP declarations. copy.h ---*/ 4 | /*--------------------------------------------------------------------------------*/ 5 | 6 | /* 7 | This file is part of Tracegrind, the Valgrind tool, 8 | which tracks tainted data coming from the specified file 9 | and converts IR trace to STP declarations. 10 | 11 | Copyright (C) 2009 Ildar Isaev 12 | iisaev@ispras.ru 13 | 14 | This program is free software; you can redistribute it and/or 15 | modify it under the terms of the GNU General Public License as 16 | published by the Free Software Foundation; either version 2 of the 17 | License, or (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, but 20 | WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program; if not, write to the Free Software 26 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 | 02111-1307, USA. 28 | 29 | The GNU General Public License is contained in the file COPYING. 30 | */ 31 | 32 | #ifndef __COPY_H 33 | #define __COPY_H 34 | 35 | #include "pub_tool_basics.h" 36 | #include "pub_tool_tooliface.h" 37 | #include "pub_tool_hashtable.h" 38 | #include "pub_tool_xarray.h" 39 | #include "pub_tool_clientstate.h" 40 | #include "pub_tool_libcfile.h" 41 | #include "pub_tool_vki.h" 42 | 43 | IRConst* mallocIRConst_U1(Bool bit); 44 | IRConst* mallocIRConst_U8(UChar u8); 45 | IRConst* mallocIRConst_U16(UShort u16); 46 | IRConst* mallocIRConst_U32(UInt u32); 47 | IRConst* mallocIRConst_U64(ULong u64); 48 | IRConst* mallocIRConst_F64(Double f64); 49 | IRConst* mallocIRConst_F64i(ULong f64i); 50 | IRConst* mallocIRConst_V128(UShort con); 51 | 52 | IRCallee* mallocIRCallee(Int regparms, const HChar* name, void* addr); 53 | 54 | IRRegArray* mallocIRRegArray(Int base, IRType elemTy, Int nElems); 55 | 56 | IRExpr* mallocIRExpr_Binder(Int binder); 57 | IRExpr* mallocIRExpr_Get(Int off, IRType ty); 58 | IRExpr* mallocIRExpr_GetI(IRRegArray* descr, IRExpr* ix, Int bias); 59 | IRExpr* mallocIRExpr_RdTmp(IRTemp tmp); 60 | IRExpr* mallocIRExpr_Qop(IROp op, IRExpr* arg1, IRExpr* arg2, IRExpr* arg3, IRExpr* arg4); 61 | IRExpr* mallocIRExpr_Triop(IROp op, IRExpr* arg1, IRExpr* arg2, IRExpr* arg3); 62 | IRExpr* mallocIRExpr_Binop(IROp op, IRExpr* arg1, IRExpr* arg2); 63 | IRExpr* mallocIRExpr_Unop(IROp op, IRExpr* arg); 64 | IRExpr* mallocIRExpr_Load(IREndness end, IRType ty, IRExpr* addr); 65 | IRExpr* mallocIRExpr_Const(IRConst* con); 66 | IRExpr* mallocIRExpr_CCall(IRCallee* cee, IRType retty, IRExpr** args); 67 | IRExpr* mallocIRExpr_ITE(IRExpr* cond, IRExpr* iftrue, IRExpr* iffalse); 68 | 69 | IRDirty* mallocEmptyIRDirty(void); 70 | 71 | 72 | 73 | IRStmt* mallocIRStmt_NoOp(void); 74 | IRStmt* mallocIRStmt_IMark(Addr64 addr, Int len); 75 | IRStmt* mallocIRStmt_AbiHint(IRExpr* base, Int len, IRExpr* nia); 76 | IRStmt* mallocIRStmt_Put(Int off, IRExpr* data); 77 | IRStmt* mallocIRStmt_PutI(IRRegArray* descr, IRExpr* ix, Int bias, IRExpr* data); 78 | IRStmt* mallocIRStmt_WrTmp(IRTemp tmp, IRExpr* data); 79 | IRStmt* mallocIRStmt_Store(IREndness end, IRExpr* addr, IRExpr* data); 80 | IRStmt* mallocIRStmt_Dirty(IRDirty* d); 81 | IRStmt* mallocIRStmt_MBE(IRMBusEvent event); 82 | IRStmt* mallocIRStmt_Exit(IRExpr* guard, IRJumpKind jk, IRConst* dst); 83 | 84 | IRExpr** shallowMallocIRExprVec(IRExpr** vec); 85 | 86 | IRExpr** deepMallocIRExprVec(IRExpr** vec); 87 | 88 | IRConst* deepMallocIRConst(IRConst* c); 89 | 90 | IRCallee* deepMallocIRCallee(IRCallee* ce); 91 | 92 | IRRegArray* deepMallocIRRegArray(IRRegArray* d); 93 | 94 | IRExpr* deepMallocIRExpr(IRExpr* e); 95 | 96 | IRDirty* deepMallocIRDirty(IRDirty* d); 97 | 98 | IRStmt* deepMallocIRStmt(IRStmt* s); 99 | 100 | #endif 101 | 102 | -------------------------------------------------------------------------------- /make_capstone_options.py: -------------------------------------------------------------------------------- 1 | from optparse import OptionParser 2 | import os, sys, traceback 3 | import errno 4 | import time 5 | import re 6 | 7 | USER_DELAY = 0.0 8 | 9 | def get_options(parser): 10 | 11 | # http://docs.python.org/2/library/optparse.html 12 | #usage = "usage: %prog [options] arg" 13 | #parser = OptionParser(usage) 14 | 15 | #parser.add_option('-n', "--nsamples", action="store", dest="nsamples", type="int", help='number of samples in FILENAME') 16 | 17 | parser.add_option("--vginstdir", 18 | action='store', 19 | dest='vginstdir', 20 | default = None, 21 | help='the Valgrind installation directory to use to configure Capstone') 22 | 23 | parser.add_option("--capstonedir", 24 | action='store', 25 | dest='capstonedir', 26 | default = None, 27 | help='the Capstone directory containing the source code') 28 | 29 | parser.add_option("--outmakefile", 30 | action='store', 31 | dest='outmakefile', 32 | default = None, 33 | help='the Capstone makefile to output') 34 | 35 | parser.add_option("-v", "--verbose", 36 | action="store_true", 37 | dest="verbose") 38 | 39 | 40 | return parser.parse_args() 41 | 42 | 43 | def check_options(parser, options, args): 44 | 45 | if options.vginstdir == None: 46 | parser.error("VGINSTDIR not supplied") 47 | 48 | if options.capstonedir == None: 49 | parser.error("CAPSTONEDIR not supplied") 50 | 51 | if options.outmakefile == None: 52 | parser.error("OUTMAKEFILE not supplied") 53 | 54 | def silentremove(filename): 55 | try: 56 | os.remove(filename) 57 | except OSError as e: # this would be "except OSError, e:" before Python 2.6 58 | if e.errno != errno.ENOENT: # errno.ENOENT = no such file or directory 59 | raise # re-raise exception if a different error occured 60 | 61 | def append_tailing_slash(indir): 62 | if indir[-1] != '/': 63 | indir += '/' 64 | return indir 65 | 66 | def get_flags(infile): 67 | flags = "" # "VGO_linux=1 VGA_amd64=1" 68 | flagstable = dict() 69 | 70 | # read content 71 | content = readfromfile(infile) 72 | 73 | # get VGO flags = OS flags 74 | vgoList = re.findall(r'-DVGO_[a-z,A-Z,0-9]*=\d', content) # eg -DVGO_linux=1 75 | for vgo in vgoList: 76 | flagstable[ vgo[2:] ] = 1 77 | 78 | # get VGA flags = architecture flags 79 | vgaList = re.findall(r'-DVGA_[a-z,A-Z,0-9]*=\d', content) # eg -DVGA_amd64=1 80 | for vga in vgaList: 81 | flagstable[ vga[2:] ] = 1 82 | 83 | # get VGP flags. Not sure what they are. We don't really need them at the moment anyway since the compilation works wihtout them 84 | # I put them anyway... 85 | vgpList = re.findall(r'-DVGP_[a-z,A-Z,0-9,_]*=\d', content) # eg -DVGP_amd64_linux=1 86 | for vgp in vgpList: 87 | flagstable[ vgp[2:] ] = 1 88 | 89 | for key in flagstable: 90 | flags += key + " " 91 | 92 | return flags 93 | 94 | def readfromfile(filename): 95 | with open(filename, "r") as f: 96 | return f.read() 97 | 98 | def save2file(content, filename): 99 | with open(filename, "w") as f: 100 | f.write(content) 101 | 102 | def print_progress_ok(s): 103 | print s.ljust(60) + "[OK]" 104 | time.sleep(USER_DELAY) 105 | 106 | def main(options): 107 | 108 | vginstdir = os.path.realpath(options.vginstdir) 109 | capstonedir = os.path.realpath(options.capstonedir) 110 | outmakefile = options.outmakefile 111 | 112 | # folders exists? 113 | if not os.path.isdir(vginstdir): 114 | raise Exception("folder '%s' does not exist" % vginstdir) 115 | 116 | if not os.path.isdir(capstonedir): 117 | raise Exception("folder '%s' does not exist" % capstonedir) 118 | 119 | # add tailing slash if need be 120 | vginstdir = append_tailing_slash(vginstdir) 121 | capstonedir = append_tailing_slash(capstonedir) 122 | 123 | # folder looks like valgrind installation folder? 124 | vginstdir_incval = vginstdir + "include/valgrind/" 125 | 126 | if not os.path.isdir(vginstdir_incval): 127 | raise Exception("'include/valgrind/' missing from folder '%s'. Was Valgrind compiled and installed in this folder?" % vginstdir) 128 | 129 | print_progress_ok("Validity of Valgrind's installation directory") 130 | # read the Makefile of Valgrind and extract 131 | # - the relevant options to pass to valgrind's headers 132 | # - platform flags :VGA_x86, VGA_amd64, VGA_ppc32, VGA_ppc64be, VGA_ppc64le, VGA_arm, VGA_arm64, VGA_s390x, VGA_mips32, VGA_mips64 133 | # - OS flags: ... 134 | # - the relevant options for capstone itself, so we compile only the platforms we need 135 | # (arm, aarch64, mips, powerpc, sparc, systemz, x86, xcore) 136 | # Well, I've decided it's just simpler to compile it all... TODO 137 | 138 | # I extract any flags that looks like -DVGO_***=1, eg -DVGO_linux=1 and -DVGA_***=1 139 | flags = get_flags("../Makefile") 140 | print_progress_ok("Flags recovery") 141 | 142 | # file content. 143 | # originally I used this to install. I've changed to a simple copy so it does not require root 144 | # sudo %s CAPSTONE_BUILD_CORE_ONLY=yes CAPTSTONE_SECRETGRIND_HEADER_DIR=%s CAPSTONE_STATIC=yes CAPSTONE_SHARED=no ./make.sh install 145 | # no longer copy the lib*.a 146 | # no longer copy the header files 147 | 148 | content = """ 149 | 150 | #!/bin/sh 151 | 152 | # WARNING: this was auto-generated. Do not change!!! 153 | 154 | # build static libs only 155 | %s CAPSTONE_BUILD_CORE_ONLY=yes CAPTSTONE_SECRETGRIND_HEADER_DIR=%s CAPSTONE_STATIC=yes CAPSTONE_SHARED=no ./make.sh 156 | 157 | """ % (flags, vginstdir_incval) 158 | 159 | #print content 160 | 161 | # save the file 162 | outmakefile = capstonedir + outmakefile 163 | silentremove(outmakefile) 164 | save2file(content, outmakefile) 165 | 166 | print_progress_ok("File creation") 167 | 168 | # create the symbolic link 169 | silentremove("../include/capstone") 170 | os.symlink(capstonedir + "include/", "../include/capstone") 171 | 172 | print_progress_ok("Include dir creation") 173 | 174 | # create the file that we'll use for building capstone with the correct options 175 | # CAPSTONE_ARCHS="arm aarch64 x86" TODO 176 | # CAPSTONE_COMPILE_TEMPLATE 177 | 178 | if __name__ == '__main__': 179 | 180 | parser = OptionParser() 181 | (options, args) = get_options(parser) 182 | check_options(parser, options, args) 183 | ret = 0 184 | 185 | try: 186 | 187 | main(options) 188 | 189 | print "SUCCESS" 190 | 191 | except Exception, e: 192 | ret = -1 193 | print "Exception: " + str(e) 194 | #except: 195 | # print "Exception caught" 196 | # traceback.print_exc(file=sys.stdout) 197 | #finally: 198 | #print 'finally' 199 | 200 | sys.exit(ret) 201 | #print 'Done ...' 202 | 203 | 204 | -------------------------------------------------------------------------------- /secretgrind.h: -------------------------------------------------------------------------------- 1 | /* 2 | * taintgrind.h 3 | * 4 | * Created on: Jun 12, 2012 5 | * Author: khilan 6 | */ 7 | 8 | #ifndef TAINTGRIND_H_ 9 | #define TAINTGRIND_H_ 10 | 11 | #include "valgrind.h" 12 | #include 13 | #include 14 | 15 | // compile for secretgrind 16 | #define _SECRETGRIND_ 1 17 | 18 | typedef enum { 19 | VG_USERREQ__TAINTGRIND_CREATE_SANDBOX, 20 | VG_USERREQ__TAINTGRIND_ENTER_PERSISTENT_SANDBOX, 21 | VG_USERREQ__TAINTGRIND_EXIT_PERSISTENT_SANDBOX, 22 | VG_USERREQ__TAINTGRIND_ENTER_EPHEMERAL_SANDBOX, 23 | VG_USERREQ__TAINTGRIND_EXIT_EPHEMERAL_SANDBOX, 24 | VG_USERREQ__TAINTGRIND_SHARED_FD, 25 | VG_USERREQ__TAINTGRIND_SHARED_VAR, 26 | VG_USERREQ__TAINTGRIND_UPDATE_SHARED_VAR, 27 | VG_USERREQ__TAINTGRIND_ALLOW_SYSCALL, 28 | VG_USERREQ__TAINTGRIND_ENTER_CALLGATE, 29 | VG_USERREQ__TAINTGRIND_EXIT_CALLGATE, 30 | VG_USERREQ__TAINTGRIND_MAKE_MEM_TAINTED, 31 | VG_USERREQ__TAINTGRIND_MAKE_MEM_UNTAINTED, 32 | #if _SECRETGRIND_ 33 | VG_USERREQ__TAINTGRIND_PRINT_ALL_INST, 34 | VG_USERREQ__TAINTGRIND_PRINT_TAINTED_INST, 35 | #else 36 | VG_USERREQ__TAINTGRIND_START_PRINT, 37 | #endif // _SECRETGRIND_ 38 | VG_USERREQ__TAINTGRIND_STOP_PRINT 39 | #if _SECRETGRIND_ 40 | , VG_USERREQ__TAINTGRIND_TAINT_SUMMARY 41 | , VG_USERREQ__TAINTGRIND_READ_TAINT_STATUS 42 | #endif 43 | 44 | } Vg_TaintGrindClientRequest; 45 | 46 | #define TNT_CREATE_SANDBOX() \ 47 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_CREATE_SANDBOX, 0, 0, 0, 0, 0) 48 | 49 | #define TNT_ENTER_PERSISTENT_SANDBOX() \ 50 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_ENTER_PERSISTENT_SANDBOX, 0, 0, 0, 0, 0) 51 | 52 | #define TNT_EXIT_PERSISTENT_SANDBOX() \ 53 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_EXIT_PERSISTENT_SANDBOX, 0, 0, 0, 0, 0) 54 | 55 | #define TNT_ENTER_EPHEMERAL_SANDBOX() \ 56 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_ENTER_EPHEMERAL_SANDBOX, 0, 0, 0, 0, 0) 57 | 58 | #define TNT_EXIT_EPHEMERAL_SANDBOX() \ 59 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_EXIT_EPHEMERAL_SANDBOX, 0, 0, 0, 0, 0) 60 | 61 | #define TNT_SHARED_FD(fd,perm) \ 62 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_SHARED_FD, fd, perm, 0, 0, 0) 63 | 64 | #define TNT_SHARED_VAR(var,perm) \ 65 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_SHARED_VAR, var, perm, 0, 0, 0) 66 | 67 | #define TNT_ENTER_CALLGATE() \ 68 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_ENTER_CALLGATE, 0, 0, 0, 0, 0) 69 | 70 | #define TNT_EXIT_CALLGATE() \ 71 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_EXIT_CALLGATE, 0, 0, 0, 0, 0) 72 | 73 | #define TNT_UPDATE_SHARED_VAR(var,value) \ 74 | { \ 75 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_UPDATE_SHARED_VAR,#var,0,0,0,0); \ 76 | var = value; \ 77 | } 78 | 79 | #define TNT_ALLOW_SYSCALL(syscallno) \ 80 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_ALLOWSYSCALL,syscallno,0,0,0,0); 81 | 82 | // Tainting/Untainting memory 83 | #if _SECRETGRIND_ 84 | 85 | # define SG_MAKE_MEM_TAINTED(addr, size) \ 86 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_MAKE_MEM_TAINTED,addr,size,0,0,0); 87 | 88 | # define SG_MAKE_MEM_UNTAINTED(addr, size) \ 89 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_MAKE_MEM_UNTAINTED,addr,size,0,0,0); 90 | 91 | #else 92 | 93 | # define TNT_MAKE_MEM_TAINTED(addr, size) \ 94 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_MAKE_MEM_TAINTED,addr,size,0,0,0); 95 | 96 | # define TNT_MAKE_MEM_UNTAINTED(addr, size) \ 97 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_MAKE_MEM_UNTAINTED,addr,size,0,0,0); 98 | 99 | #endif // _SECRETGRIND_ 100 | 101 | // Start/Stop printing output 102 | #if _SECRETGRIND_ 103 | 104 | # define SG_PRINT_ALL_INST() \ 105 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_PRINT_ALL_INST, 0, 0, 0, 0, 0) 106 | 107 | # define SG_PRINT_TAINTED_INST() \ 108 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_PRINT_TAINTED_INST, 0, 0, 0, 0, 0) 109 | 110 | # define SG_STOP_PRINT() \ 111 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_STOP_PRINT, 0, 0, 0, 0, 0) 112 | 113 | #else 114 | 115 | # define TNT_START_PRINT() \ 116 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_START_PRINT, 0, 0, 0, 0, 0) 117 | 118 | # define TNT_STOP_PRINT() \ 119 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_STOP_PRINT, 0, 0, 0, 0, 0) 120 | 121 | #endif // _SECRETGRIND_ 122 | 123 | 124 | 125 | 126 | 127 | 128 | #if _SECRETGRIND_ 129 | 130 | # define SG_TAINT_SUMMARY(s) \ 131 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_TAINT_SUMMARY, (char*)s, 0, 0, 0, 0) 132 | 133 | # define SG_READ_TAINT_STATE(text,addr,len) \ 134 | VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TAINTGRIND_READ_TAINT_STATUS, text, addr, len, 0, 0) 135 | 136 | #endif // _SECRETGRIND_ 137 | #endif /* TAINTGRIND_H_ */ 138 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmrs2/secretgrind/067d2317d2cd255fb003c688830ec3ba83c5a662/tests/Makefile.am -------------------------------------------------------------------------------- /tests/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.11.1 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, 6 | # Inc. 7 | # This Makefile.in is free software; the Free Software Foundation 8 | # gives unlimited permission to copy and/or distribute it, 9 | # with or without modifications, as long as this notice is preserved. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 13 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 | # PARTICULAR PURPOSE. 15 | 16 | @SET_MAKE@ 17 | VPATH = @srcdir@ 18 | pkgdatadir = $(datadir)/@PACKAGE@ 19 | pkgincludedir = $(includedir)/@PACKAGE@ 20 | pkglibdir = $(libdir)/@PACKAGE@ 21 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 22 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 23 | install_sh_DATA = $(install_sh) -c -m 644 24 | install_sh_PROGRAM = $(install_sh) -c 25 | install_sh_SCRIPT = $(install_sh) -c 26 | INSTALL_HEADER = $(INSTALL_DATA) 27 | transform = $(program_transform_name) 28 | NORMAL_INSTALL = : 29 | PRE_INSTALL = : 30 | POST_INSTALL = : 31 | NORMAL_UNINSTALL = : 32 | PRE_UNINSTALL = : 33 | POST_UNINSTALL = : 34 | build_triplet = @build@ 35 | host_triplet = @host@ 36 | subdir = tests 37 | DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in 38 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 39 | am__aclocal_m4_deps = $(top_srcdir)/configure.in 40 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 41 | $(ACLOCAL_M4) 42 | mkinstalldirs = $(install_sh) -d 43 | CONFIG_HEADER = $(top_builddir)/config.h 44 | CONFIG_CLEAN_FILES = 45 | CONFIG_CLEAN_VPATH_FILES = 46 | SOURCES = 47 | DIST_SOURCES = 48 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 49 | ACLOCAL = @ACLOCAL@ 50 | AMTAR = @AMTAR@ 51 | AR = @AR@ 52 | AUTOCONF = @AUTOCONF@ 53 | AUTOHEADER = @AUTOHEADER@ 54 | AUTOMAKE = @AUTOMAKE@ 55 | AWK = @AWK@ 56 | BOOST_CFLAGS = @BOOST_CFLAGS@ 57 | BOOST_LIBS = @BOOST_LIBS@ 58 | CC = @CC@ 59 | CCAS = @CCAS@ 60 | CCASDEPMODE = @CCASDEPMODE@ 61 | CCASFLAGS = @CCASFLAGS@ 62 | CCDEPMODE = @CCDEPMODE@ 63 | CFLAGS = @CFLAGS@ 64 | CPP = @CPP@ 65 | CPPFLAGS = @CPPFLAGS@ 66 | CXX = @CXX@ 67 | CXXDEPMODE = @CXXDEPMODE@ 68 | CXXFLAGS = @CXXFLAGS@ 69 | CYGPATH_W = @CYGPATH_W@ 70 | DEFAULT_SUPP = @DEFAULT_SUPP@ 71 | DEFS = @DEFS@ 72 | DEPDIR = @DEPDIR@ 73 | DIFF = @DIFF@ 74 | ECHO_C = @ECHO_C@ 75 | ECHO_N = @ECHO_N@ 76 | ECHO_T = @ECHO_T@ 77 | EGREP = @EGREP@ 78 | EXEEXT = @EXEEXT@ 79 | FLAG_FNO_STACK_PROTECTOR = @FLAG_FNO_STACK_PROTECTOR@ 80 | FLAG_M32 = @FLAG_M32@ 81 | FLAG_M64 = @FLAG_M64@ 82 | FLAG_MMMX = @FLAG_MMMX@ 83 | FLAG_MSSE = @FLAG_MSSE@ 84 | FLAG_NO_BUILD_ID = @FLAG_NO_BUILD_ID@ 85 | FLAG_UNLIMITED_INLINE_UNIT_GROWTH = @FLAG_UNLIMITED_INLINE_UNIT_GROWTH@ 86 | FLAG_W_EXTRA = @FLAG_W_EXTRA@ 87 | FLAG_W_NO_EMPTY_BODY = @FLAG_W_NO_EMPTY_BODY@ 88 | FLAG_W_NO_FORMAT_ZERO_LENGTH = @FLAG_W_NO_FORMAT_ZERO_LENGTH@ 89 | FLAG_W_NO_NONNULL = @FLAG_W_NO_NONNULL@ 90 | FLAG_W_NO_OVERFLOW = @FLAG_W_NO_OVERFLOW@ 91 | FLAG_W_NO_UNINITIALIZED = @FLAG_W_NO_UNINITIALIZED@ 92 | GDB = @GDB@ 93 | GLIBC_VERSION = @GLIBC_VERSION@ 94 | GREP = @GREP@ 95 | INSTALL = @INSTALL@ 96 | INSTALL_DATA = @INSTALL_DATA@ 97 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 98 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 99 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 100 | LDFLAGS = @LDFLAGS@ 101 | LIBOBJS = @LIBOBJS@ 102 | LIBS = @LIBS@ 103 | LN_S = @LN_S@ 104 | LTLIBOBJS = @LTLIBOBJS@ 105 | MAINT = @MAINT@ 106 | MAKEINFO = @MAKEINFO@ 107 | MKDIR_P = @MKDIR_P@ 108 | MPI_CC = @MPI_CC@ 109 | OBJEXT = @OBJEXT@ 110 | PACKAGE = @PACKAGE@ 111 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 112 | PACKAGE_NAME = @PACKAGE_NAME@ 113 | PACKAGE_STRING = @PACKAGE_STRING@ 114 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 115 | PACKAGE_URL = @PACKAGE_URL@ 116 | PACKAGE_VERSION = @PACKAGE_VERSION@ 117 | PATH_SEPARATOR = @PATH_SEPARATOR@ 118 | PERL = @PERL@ 119 | PREFERRED_STACK_BOUNDARY = @PREFERRED_STACK_BOUNDARY@ 120 | RANLIB = @RANLIB@ 121 | SED = @SED@ 122 | SET_MAKE = @SET_MAKE@ 123 | SHELL = @SHELL@ 124 | STRIP = @STRIP@ 125 | VALT_LOAD_ADDRESS_PRI = @VALT_LOAD_ADDRESS_PRI@ 126 | VALT_LOAD_ADDRESS_SEC = @VALT_LOAD_ADDRESS_SEC@ 127 | VERSION = @VERSION@ 128 | VGCONF_ARCH_PRI = @VGCONF_ARCH_PRI@ 129 | VGCONF_ARCH_SEC = @VGCONF_ARCH_SEC@ 130 | VGCONF_OS = @VGCONF_OS@ 131 | VGCONF_PLATFORM_PRI_CAPS = @VGCONF_PLATFORM_PRI_CAPS@ 132 | VGCONF_PLATFORM_SEC_CAPS = @VGCONF_PLATFORM_SEC_CAPS@ 133 | VGCONF_PLATVARIANT = @VGCONF_PLATVARIANT@ 134 | abs_builddir = @abs_builddir@ 135 | abs_srcdir = @abs_srcdir@ 136 | abs_top_builddir = @abs_top_builddir@ 137 | abs_top_srcdir = @abs_top_srcdir@ 138 | ac_ct_CC = @ac_ct_CC@ 139 | ac_ct_CXX = @ac_ct_CXX@ 140 | am__include = @am__include@ 141 | am__leading_dot = @am__leading_dot@ 142 | am__quote = @am__quote@ 143 | am__tar = @am__tar@ 144 | am__untar = @am__untar@ 145 | bindir = @bindir@ 146 | build = @build@ 147 | build_alias = @build_alias@ 148 | build_cpu = @build_cpu@ 149 | build_os = @build_os@ 150 | build_vendor = @build_vendor@ 151 | builddir = @builddir@ 152 | datadir = @datadir@ 153 | datarootdir = @datarootdir@ 154 | docdir = @docdir@ 155 | dvidir = @dvidir@ 156 | exec_prefix = @exec_prefix@ 157 | host = @host@ 158 | host_alias = @host_alias@ 159 | host_cpu = @host_cpu@ 160 | host_os = @host_os@ 161 | host_vendor = @host_vendor@ 162 | htmldir = @htmldir@ 163 | includedir = @includedir@ 164 | infodir = @infodir@ 165 | install_sh = @install_sh@ 166 | libdir = @libdir@ 167 | libexecdir = @libexecdir@ 168 | localedir = @localedir@ 169 | localstatedir = @localstatedir@ 170 | mandir = @mandir@ 171 | mkdir_p = @mkdir_p@ 172 | oldincludedir = @oldincludedir@ 173 | pdfdir = @pdfdir@ 174 | prefix = @prefix@ 175 | program_transform_name = @program_transform_name@ 176 | psdir = @psdir@ 177 | sbindir = @sbindir@ 178 | sharedstatedir = @sharedstatedir@ 179 | srcdir = @srcdir@ 180 | sysconfdir = @sysconfdir@ 181 | target_alias = @target_alias@ 182 | top_build_prefix = @top_build_prefix@ 183 | top_builddir = @top_builddir@ 184 | top_srcdir = @top_srcdir@ 185 | all: all-am 186 | 187 | .SUFFIXES: 188 | $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) 189 | @for dep in $?; do \ 190 | case '$(am__configure_deps)' in \ 191 | *$$dep*) \ 192 | ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ 193 | && { if test -f $@; then exit 0; else break; fi; }; \ 194 | exit 1;; \ 195 | esac; \ 196 | done; \ 197 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ 198 | $(am__cd) $(top_srcdir) && \ 199 | $(AUTOMAKE) --foreign tests/Makefile 200 | .PRECIOUS: Makefile 201 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 202 | @case '$?' in \ 203 | *config.status*) \ 204 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 205 | *) \ 206 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ 207 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ 208 | esac; 209 | 210 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 211 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 212 | 213 | $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 214 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 215 | $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) 216 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 217 | $(am__aclocal_m4_deps): 218 | tags: TAGS 219 | TAGS: 220 | 221 | ctags: CTAGS 222 | CTAGS: 223 | 224 | 225 | distdir: $(DISTFILES) 226 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 227 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 228 | list='$(DISTFILES)'; \ 229 | dist_files=`for file in $$list; do echo $$file; done | \ 230 | sed -e "s|^$$srcdirstrip/||;t" \ 231 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 232 | case $$dist_files in \ 233 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 234 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 235 | sort -u` ;; \ 236 | esac; \ 237 | for file in $$dist_files; do \ 238 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 239 | if test -d $$d/$$file; then \ 240 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 241 | if test -d "$(distdir)/$$file"; then \ 242 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 243 | fi; \ 244 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 245 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 246 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 247 | fi; \ 248 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 249 | else \ 250 | test -f "$(distdir)/$$file" \ 251 | || cp -p $$d/$$file "$(distdir)/$$file" \ 252 | || exit 1; \ 253 | fi; \ 254 | done 255 | check-am: all-am 256 | check: check-am 257 | all-am: Makefile 258 | installdirs: 259 | install: install-am 260 | install-exec: install-exec-am 261 | install-data: install-data-am 262 | uninstall: uninstall-am 263 | 264 | install-am: all-am 265 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 266 | 267 | installcheck: installcheck-am 268 | install-strip: 269 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 270 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 271 | `test -z '$(STRIP)' || \ 272 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 273 | mostlyclean-generic: 274 | 275 | clean-generic: 276 | 277 | distclean-generic: 278 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 279 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 280 | 281 | maintainer-clean-generic: 282 | @echo "This command is intended for maintainers to use" 283 | @echo "it deletes files that may require special tools to rebuild." 284 | clean: clean-am 285 | 286 | clean-am: clean-generic mostlyclean-am 287 | 288 | distclean: distclean-am 289 | -rm -f Makefile 290 | distclean-am: clean-am distclean-generic 291 | 292 | dvi: dvi-am 293 | 294 | dvi-am: 295 | 296 | html: html-am 297 | 298 | html-am: 299 | 300 | info: info-am 301 | 302 | info-am: 303 | 304 | install-data-am: 305 | 306 | install-dvi: install-dvi-am 307 | 308 | install-dvi-am: 309 | 310 | install-exec-am: 311 | 312 | install-html: install-html-am 313 | 314 | install-html-am: 315 | 316 | install-info: install-info-am 317 | 318 | install-info-am: 319 | 320 | install-man: 321 | 322 | install-pdf: install-pdf-am 323 | 324 | install-pdf-am: 325 | 326 | install-ps: install-ps-am 327 | 328 | install-ps-am: 329 | 330 | installcheck-am: 331 | 332 | maintainer-clean: maintainer-clean-am 333 | -rm -f Makefile 334 | maintainer-clean-am: distclean-am maintainer-clean-generic 335 | 336 | mostlyclean: mostlyclean-am 337 | 338 | mostlyclean-am: mostlyclean-generic 339 | 340 | pdf: pdf-am 341 | 342 | pdf-am: 343 | 344 | ps: ps-am 345 | 346 | ps-am: 347 | 348 | uninstall-am: 349 | 350 | .MAKE: install-am install-strip 351 | 352 | .PHONY: all all-am check check-am clean clean-generic distclean \ 353 | distclean-generic distdir dvi dvi-am html html-am info info-am \ 354 | install install-am install-data install-data-am install-dvi \ 355 | install-dvi-am install-exec install-exec-am install-html \ 356 | install-html-am install-info install-info-am install-man \ 357 | install-pdf install-pdf-am install-ps install-ps-am \ 358 | install-strip installcheck installcheck-am installdirs \ 359 | maintainer-clean maintainer-clean-generic mostlyclean \ 360 | mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am 361 | 362 | 363 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 364 | # Otherwise a system limit (for SysV at least) may be exceeded. 365 | .NOEXPORT: 366 | -------------------------------------------------------------------------------- /tnt_asm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Not sure if it's possible to get the guest architecture at run time. 4 | * The instrument() function in tnt_translate.c has a parameter 5 | * VexArchInfo* archinfo_host, but this is the host, not the guest. 6 | * This is called from VEX/priv/main_main.c 7 | * 8 | * So instead, I use a macro because that's the way valgrind seems to do 9 | * it internally at compilation time, see coregrind/m_machine.c 10 | * 11 | * So I copy their macros here and set the correct architecture, 12 | * then use capstone to disassemble [0]. An example can be found at [1]. 13 | * 14 | * For installation, see [2]. It may vary depending on your platform. 15 | * Headers should be installed under /capstone/ 16 | * 17 | * [0] http://www.capstone-engine.org 18 | * [1] http://www.capstone-engine.org/lang_c.html 19 | * [2] http://www.capstone-engine.org/documentation.html 20 | * 21 | * */ 22 | 23 | 24 | #include "pub_tool_tooliface.h" 25 | #include "pub_tool_libcassert.h" 26 | #include "pub_tool_libcprint.h" // VG_(*printf) 27 | 28 | #include "tnt_include.h" 29 | #include "tnt_asm.h" 30 | 31 | // capstone stuff 32 | #include 33 | #include 34 | 35 | /* 36 | as defined in capstone.h 37 | ======================== 38 | 39 | cs_arch: 40 | ------- 41 | CS_ARCH_ARM = 0, // ARM architecture (including Thumb, Thumb-2) 42 | CS_ARCH_ARM64, // ARM-64, also called AArch64 43 | CS_ARCH_MIPS, // Mips architecture 44 | CS_ARCH_X86, // X86 architecture (including x86 & x86-64) 45 | CS_ARCH_PPC, // PowerPC architecture 46 | CS_ARCH_SPARC, // Sparc architecture 47 | CS_ARCH_SYSZ, // SystemZ architecture 48 | CS_ARCH_XCORE, // XCore architecture 49 | CS_ARCH_MAX, 50 | CS_ARCH_ALL = 0xFFFF, // All architectures - for cs_support() 51 | 52 | cs_mode: 53 | ------- 54 | CS_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) 55 | CS_MODE_ARM = 0, // 32-bit ARM 56 | CS_MODE_16 = 1 << 1, // 16-bit mode (X86) 57 | CS_MODE_32 = 1 << 2, // 32-bit mode (X86) 58 | CS_MODE_64 = 1 << 3, // 64-bit mode (X86, PPC) 59 | CS_MODE_THUMB = 1 << 4, // ARM's Thumb mode, including Thumb-2 60 | CS_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series 61 | CS_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM 62 | CS_MODE_MICRO = 1 << 4, // MicroMips mode (MIPS) 63 | CS_MODE_MIPS3 = 1 << 5, // Mips III ISA 64 | CS_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA 65 | CS_MODE_MIPSGP64 = 1 << 7, // General Purpose Registers are 64-bit wide (MIPS) 66 | CS_MODE_V9 = 1 << 4, // SparcV9 mode (Sparc) 67 | CS_MODE_BIG_ENDIAN = 1 << 31, // big-endian mode 68 | CS_MODE_MIPS32 = CS_MODE_32, // Mips32 ISA (Mips) 69 | CS_MODE_MIPS64 = CS_MODE_64, // 70 | */ 71 | 72 | // global variables 73 | #define INVALID (-1) 74 | static csh handle = INVALID; 75 | static cs_insn *insn = (void*)INVALID; 76 | static cs_arch arch = INVALID; 77 | static cs_mode mode = INVALID; 78 | 79 | static Bool is_init(void) { 80 | return (handle != INVALID && arch != INVALID && mode != INVALID); 81 | } 82 | 83 | static void reset(void) { 84 | handle = INVALID; 85 | insn = (void*)INVALID; 86 | arch = INVALID; 87 | mode = INVALID; 88 | } 89 | 90 | /* 91 | * 92 | * # CAPSTONE_VALGRIND 93 | ifdef CAPSTONE_VALGRIND 94 | LDFLAGS += -nodefaultlibs -nostartfiles 95 | #hellow rold 96 | endif 97 | * 98 | * 99 | * */ 100 | Bool TNT_(asm_init)(void) { 101 | // here we set the global var 102 | 103 | /* 104 | * My understanding from reading coregrind/m_machine.c is that: 105 | * - x86 is only 32 bits 106 | * - amd64 is amd and x86-64 107 | * - the rest is self-explanatory 108 | * 109 | * see http://www.capstone-engine.org/lang_c.html for the mapping to capstone 110 | */ 111 | 112 | cs_err err = CS_ERR_OK; 113 | tl_assert ( ! is_init() ); 114 | reset(); 115 | 116 | #if defined(VGA_x86) 117 | 118 | arch = CS_ARCH_X86; 119 | mode = CS_MODE_32; 120 | 121 | #elif defined(VGA_amd64) 122 | 123 | arch = CS_ARCH_X86; 124 | mode = CS_MODE_64; 125 | 126 | #elif defined(VGA_ppc32) 127 | 128 | arch = CS_ARCH_PPC; 129 | mode = CS_MODE_32; 130 | 131 | #elif defined(VGA_ppc64be) || defined(VGA_ppc64le) 132 | 133 | arch = CS_ARCH_PPC; 134 | mode = CS_MODE_64; 135 | 136 | #elif defined(VGA_arm) 137 | 138 | arch = CS_ARCH_ARM; 139 | mode = CS_MODE_ARM | CS_MODE_THUMB; // default I think 140 | 141 | #elif defined(VGA_arm64) 142 | 143 | arch = CS_ARCH_ARM64; 144 | mode = CS_MODE_ARM; // need to check these 145 | 146 | #elif defined(VGA_s390x) 147 | 148 | arch = CS_ARCH_SYSZ; 149 | mode = CS_MODE_64; // check this 150 | 151 | #elif defined(VGA_mips32) 152 | 153 | arch = CS_ARCH_MIPS; 154 | mode = CS_MODE_MIPS32; 155 | 156 | #elif defined(VGA_mips64) 157 | 158 | arch = CS_ARCH_MIPS; 159 | mode = CS_MODE_MIPS64; 160 | 161 | #else 162 | Platform not supported! 163 | #endif 164 | 165 | if ( (err=cs_open(arch, mode, &handle)) != CS_ERR_OK) { 166 | VG_(printf)("Failed cs_open"); 167 | goto end; 168 | } 169 | 170 | // use AT&T syntax -- not sure this will fail on non-intel platforms... 171 | if ( (err=cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT)) != CS_ERR_OK) { 172 | VG_(printf)("Failed cs_option. Make your capstone was NOT compiled with CAPSTONE_X86_ATT_DISABLE"); 173 | goto end; 174 | } 175 | 176 | end: 177 | return (err==CS_ERR_OK); 178 | } 179 | 180 | void TNT_(asm_release)(void) { 181 | 182 | tl_assert ( is_init() ); 183 | cs_close(&handle); 184 | reset(); 185 | 186 | } 187 | 188 | Bool TNT_(asm_guest_pprint)(Addr a, SizeT len, char *out, SizeT olen) { 189 | 190 | tl_assert ( is_init() ); 191 | 192 | size_t count; 193 | Bool ret = False; 194 | 195 | // see http://www.capstone-engine.org/lang_c.html 196 | count = cs_disasm(handle, (uint8_t*)a, len, a, 0, &insn); 197 | if (count > 0) { 198 | size_t j; 199 | for (j = 0; j < count; j++) { 200 | VG_(snprintf)(out, olen, "%s %s", insn[j].mnemonic, insn[j].op_str); 201 | //VG_(snprintf)(out, olen, "0x%"PRIx64":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, 202 | // insn[j].op_str); 203 | } 204 | 205 | cs_free(insn, count); 206 | ret = True; 207 | } 208 | 209 | return ret; 210 | } 211 | -------------------------------------------------------------------------------- /tnt_asm.h: -------------------------------------------------------------------------------- 1 | #ifndef TNT_GUEST_ASM_H 2 | #define TNT_GUEST_ASM_H 3 | 4 | 5 | extern Bool TNT_(asm_init)(void); 6 | extern void TNT_(asm_release)(void); 7 | extern Bool TNT_(asm_guest_pprint)(Addr a, SizeT len, char *out, SizeT olen); 8 | 9 | #endif // TNT_GUEST_ASM_H 10 | -------------------------------------------------------------------------------- /tnt_file_filter.c: -------------------------------------------------------------------------------- 1 | #include "secretgrind.h" 2 | #include "tnt_include.h" 3 | #include "pub_tool_libcassert.h" 4 | #include "tnt_libc.h" 5 | #include "tnt_file_filter.h" 6 | 7 | #if _SECRETGRIND_ 8 | 9 | struct { 10 | HChar filter_list[MAX_FILE_FILTER][MAX_PATH]; 11 | SizeT len; 12 | } TNT_(clo_file_filter) = {}; 13 | 14 | 15 | Bool TNT_(file_filter_present)() { return TNT_(file_filter_get_length)()>0; } 16 | 17 | SizeT TNT_(file_filter_get_max_length)() { return LEN( TNT_(clo_file_filter).filter_list ); } 18 | 19 | SizeT TNT_(file_filter_get_length)() { return TNT_(clo_file_filter).len; } 20 | 21 | const char * TNT_(file_filter_get)( SizeT index ) { tl_assert( index < TNT_(file_filter_get_max_length)()); return &TNT_(clo_file_filter).filter_list[index][0]; } 22 | 23 | void TNT_(file_filter_set)( SizeT index, char *s ) { 24 | tl_assert( index < TNT_(file_filter_get_max_length)()); 25 | libc_strlcpy( TNT_(clo_file_filter).filter_list[index], s, sizeof(TNT_(clo_file_filter).filter_list[index]) ); 26 | TNT_(clo_file_filter).len = max(index+1, TNT_(clo_file_filter).len); 27 | } 28 | 29 | Bool TNT_(file_filter_all)() { 30 | SizeT i=0; 31 | for ( i=0; i= 0 && (ev) < N_PROF_EVENTS); \ 57 | /* crude and inaccurate check to ensure the same */ \ 58 | /* event isn't being used with > 1 name */ \ 59 | if (TNT_(event_ctr_name)[ev]) \ 60 | tl_assert(name == TNT_(event_ctr_name)[ev]); \ 61 | TNT_(event_ctr)[ev]++; \ 62 | TNT_(event_ctr_name)[ev] = (name); \ 63 | } while (False); 64 | 65 | #else 66 | 67 | # define PROF_EVENT(ev, name) /* */ 68 | 69 | #endif /* TNT_PROFILE_MEMORY */ 70 | 71 | 72 | /*------------------------------------------------------------*/ 73 | /*--- V and A bits (Victoria & Albert ?) ---*/ 74 | /*------------------------------------------------------------*/ 75 | 76 | /* The number of entries in the primary map can be altered. However 77 | we hardwire the assumption that each secondary map covers precisely 78 | 64k of address space. */ 79 | #define SM_SIZE 65536 /* DO NOT CHANGE */ 80 | #define SM_MASK (SM_SIZE-1) /* DO NOT CHANGE */ 81 | 82 | #define V_BIT_UNTAINTED 0 83 | #define V_BIT_TAINTED 1 84 | 85 | #define V_BITS8_UNTAINTED 0 86 | #define V_BITS8_TAINTED 0xFF 87 | 88 | #define V_BITS16_UNTAINTED 0 89 | #define V_BITS16_TAINTED 0xFFFF 90 | 91 | #define V_BITS32_UNTAINTED 0 92 | #define V_BITS32_TAINTED 0xFFFFFFFF 93 | 94 | #define V_BITS64_UNTAINTED 0ULL 95 | #define V_BITS64_TAINTED 0xFFFFFFFFFFFFFFFFULL 96 | 97 | 98 | /*------------------------------------------------------------*/ 99 | /*--- Instrumentation ---*/ 100 | /*------------------------------------------------------------*/ 101 | 102 | // Debug variable 103 | //int tnt_read; 104 | 105 | /* Functions/vars defined in tnt_main.c */ 106 | UChar get_vabits2( Addr a ); // Taintgrind: needed by TNT_(instrument) 107 | void TNT_(make_mem_noaccess)( Addr a, SizeT len ); 108 | void TNT_(make_mem_tainted)( Addr a, SizeT len ); 109 | void TNT_(make_mem_untainted)( Addr a, SizeT len ); 110 | 111 | VG_REGPARM(3) void TNT_(h32_exit_t) ( IRStmt *, UInt, UInt ); 112 | VG_REGPARM(3) void TNT_(h32_exit_c) ( IRStmt *, UInt, UInt ); 113 | VG_REGPARM(3) void TNT_(h32_next_t) ( IRExpr *, UInt, UInt ); 114 | VG_REGPARM(3) void TNT_(h32_next_c) ( IRExpr *, UInt, UInt ); 115 | VG_REGPARM(3) void TNT_(h32_store_tt) ( IRStmt *, UInt, UInt ); 116 | #if _SECRETGRIND_ 117 | VG_REGPARM(3) void TNT_(h32_store_v128or256_tt) ( IRStmt *, ULong, ULong ); 118 | VG_REGPARM(3) void TNT_(h32_store_v128or256_ct) ( IRStmt *, ULong, ULong ); 119 | VG_REGPARM(3) void TNT_(h32_store_v128or256_tc) ( IRStmt *, ULong, ULong ); 120 | VG_REGPARM(2) void TNT_(h32_store_v128or256_prepare_tt) (IRStmt *, UChar); 121 | VG_REGPARM(2) void TNT_(h32_store_v128or256_prepare_ct) (IRStmt *, UChar); 122 | VG_REGPARM(2) void TNT_(h32_store_v128or256_prepare_tc) (IRStmt *, UChar); 123 | #endif 124 | VG_REGPARM(3) void TNT_(h32_store_tc) ( IRStmt *, UInt, UInt ); 125 | VG_REGPARM(3) void TNT_(h32_store_ct) ( IRStmt *, UInt, UInt ); 126 | VG_REGPARM(3) void TNT_(h32_load_t) ( IRStmt *, UInt, UInt ); 127 | #if _SECRETGRIND_ 128 | VG_REGPARM(3) void TNT_(h32_load_v128or256_t) ( IRStmt *, UInt, UInt ); 129 | #endif 130 | VG_REGPARM(3) void TNT_(h32_load_c) ( IRStmt *, UInt, UInt ); 131 | VG_REGPARM(3) void TNT_(h32_get) ( IRStmt *, UInt, UInt ); 132 | VG_REGPARM(3) void TNT_(h32_geti) ( IRStmt *, UInt, UInt ); 133 | VG_REGPARM(3) void TNT_(h32_put_t) ( IRStmt *, UInt, UInt ); 134 | VG_REGPARM(3) void TNT_(h32_put_c) ( IRStmt *, UInt, UInt ); 135 | VG_REGPARM(3) void TNT_(h32_puti) ( UInt, UInt, UInt, UInt ); 136 | VG_REGPARM(3) void TNT_(h32_wrtmp_c) ( IRStmt *, UInt, UInt ); 137 | VG_REGPARM(3) void TNT_(h32_unop_t) ( IRStmt *, UInt, UInt ); 138 | VG_REGPARM(3) void TNT_(h32_unop_c) ( IRStmt *, UInt, UInt ); 139 | VG_REGPARM(3) void TNT_(h32_binop_tc) ( IRStmt *, UInt, UInt ); 140 | VG_REGPARM(3) void TNT_(h32_binop_ct) ( IRStmt *, UInt, UInt ); 141 | VG_REGPARM(3) void TNT_(h32_binop_tt) ( IRStmt *, UInt, UInt ); 142 | VG_REGPARM(3) void TNT_(h32_binop_cc) ( IRStmt *, UInt, UInt ); 143 | VG_REGPARM(3) void TNT_(h32_triop) ( IRStmt *, UInt, UInt ); 144 | VG_REGPARM(3) void TNT_(h32_qop) ( IRStmt *, UInt, UInt ); 145 | VG_REGPARM(3) void TNT_(h32_rdtmp) ( IRStmt *, UInt, UInt ); 146 | VG_REGPARM(3) void TNT_(h32_ite_tc) ( IRStmt *, UInt, UInt ); 147 | VG_REGPARM(3) void TNT_(h32_ite_ct) ( IRStmt *, UInt, UInt ); 148 | VG_REGPARM(3) void TNT_(h32_ite_tt) ( IRStmt *, UInt, UInt ); 149 | VG_REGPARM(3) void TNT_(h32_ite_cc) ( IRStmt *, UInt, UInt ); 150 | VG_REGPARM(3) void TNT_(h32_ccall) ( IRStmt *, UInt, UInt ); 151 | VG_REGPARM(3) void TNT_(h32_none) ( HChar *, UInt, UInt ); 152 | 153 | VG_REGPARM(3) void TNT_(h64_exit_t) ( IRStmt *, ULong, ULong ); 154 | VG_REGPARM(3) void TNT_(h64_exit_c) ( IRStmt *, ULong, ULong ); 155 | VG_REGPARM(3) void TNT_(h64_next_t) ( IRExpr *, ULong, ULong ); 156 | VG_REGPARM(3) void TNT_(h64_next_c) ( IRExpr *, ULong, ULong ); 157 | VG_REGPARM(3) void TNT_(h64_store_tt) ( IRStmt *, ULong, ULong ); 158 | #if _SECRETGRIND_ 159 | VG_REGPARM(3) void TNT_(h64_store_v128or256_tt) ( IRStmt *, ULong, ULong ); 160 | VG_REGPARM(3) void TNT_(h64_store_v128or256_ct) ( IRStmt *, ULong, ULong ); 161 | VG_REGPARM(3) void TNT_(h64_store_v128or256_tc) ( IRStmt *, ULong, ULong ); 162 | VG_REGPARM(2) void TNT_(h64_store_v128or256_prepare_tt) (IRStmt *, UChar); 163 | VG_REGPARM(2) void TNT_(h64_store_v128or256_prepare_ct) (IRStmt *, UChar); 164 | VG_REGPARM(2) void TNT_(h64_store_v128or256_prepare_tc) (IRStmt *, UChar); 165 | 166 | #endif 167 | VG_REGPARM(3) void TNT_(h64_store_tc) ( IRStmt *, ULong, ULong ); 168 | VG_REGPARM(3) void TNT_(h64_store_ct) ( IRStmt *, ULong, ULong ); 169 | VG_REGPARM(3) void TNT_(h64_load_c) ( IRStmt *, ULong, ULong ); 170 | #if _SECRETGRIND_ 171 | VG_REGPARM(3) void TNT_(h64_load_v128or256_t) ( IRStmt *, ULong, ULong ); 172 | VG_REGPARM(1) void TNT_(hxx_imark_t) ( IRStmt *); 173 | #endif 174 | VG_REGPARM(3) void TNT_(h64_load_t) ( IRStmt *, ULong, ULong ); 175 | VG_REGPARM(3) void TNT_(h64_get) ( IRStmt *, ULong, ULong ); 176 | VG_REGPARM(3) void TNT_(h64_geti) ( IRStmt *, ULong, ULong ); 177 | VG_REGPARM(3) void TNT_(h64_put_t) ( IRStmt *, ULong, ULong ); 178 | VG_REGPARM(3) void TNT_(h64_put_c) ( IRStmt *, ULong, ULong ); 179 | VG_REGPARM(3) void TNT_(h64_puti) ( ULong, ULong, ULong, ULong ); 180 | VG_REGPARM(3) void TNT_(h64_wrtmp_c) ( IRStmt *, ULong, ULong ); 181 | VG_REGPARM(3) void TNT_(h64_unop_t) ( IRStmt *, ULong, ULong ); 182 | VG_REGPARM(3) void TNT_(h64_unop_c) ( IRStmt *, ULong, ULong ); 183 | VG_REGPARM(3) void TNT_(h64_binop_tc) ( IRStmt *, ULong, ULong ); 184 | VG_REGPARM(3) void TNT_(h64_binop_ct) ( IRStmt *, ULong, ULong ); 185 | VG_REGPARM(3) void TNT_(h64_binop_tt) ( IRStmt *, ULong, ULong ); 186 | VG_REGPARM(3) void TNT_(h64_binop_cc) ( IRStmt *, ULong, ULong ); 187 | VG_REGPARM(3) void TNT_(h64_triop) ( IRStmt *, ULong, ULong ); 188 | VG_REGPARM(3) void TNT_(h64_qop) ( IRStmt *, ULong, ULong ); 189 | VG_REGPARM(3) void TNT_(h64_rdtmp) ( IRStmt *, ULong, ULong ); 190 | VG_REGPARM(3) void TNT_(h64_ite_tc) ( IRStmt *, ULong, ULong ); 191 | VG_REGPARM(3) void TNT_(h64_ite_ct) ( IRStmt *, ULong, ULong ); 192 | VG_REGPARM(3) void TNT_(h64_ite_tt) ( IRStmt *, ULong, ULong ); 193 | VG_REGPARM(3) void TNT_(h64_ite_cc) ( IRStmt *, ULong, ULong ); 194 | VG_REGPARM(3) void TNT_(h64_ccall) ( IRStmt *, ULong, ULong ); 195 | VG_REGPARM(3) void TNT_(h64_none) ( HChar *, ULong, ULong ); 196 | 197 | /* Strings used by tnt_translate, printed by tnt_main */ 198 | extern const char *IRType_string[]; 199 | extern const char *IREndness_string[]; 200 | extern const char *IRConst_string[]; 201 | extern const char *IROp_string[]; 202 | extern const char *IRExpr_string[]; 203 | extern const char *IRStmt_string[]; 204 | extern const char *IRJumpKind_string[]; 205 | 206 | /* Functions defined in tnt_translate, used by tnt_main */ 207 | extern Int extract_IRConst( IRConst* con ); 208 | extern ULong extract_IRConst64( IRConst* con ); 209 | 210 | /* V-bits load/store helpers */ 211 | VG_REGPARM(1) void TNT_(helperc_STOREV64be) ( Addr, ULong ); 212 | VG_REGPARM(1) void TNT_(helperc_STOREV64le) ( Addr, ULong ); 213 | VG_REGPARM(2) void TNT_(helperc_STOREV32be) ( Addr, UWord ); 214 | VG_REGPARM(2) void TNT_(helperc_STOREV32le) ( Addr, UWord ); 215 | VG_REGPARM(2) void TNT_(helperc_STOREV16be) ( Addr, UWord ); 216 | VG_REGPARM(2) void TNT_(helperc_STOREV16le) ( Addr, UWord ); 217 | VG_REGPARM(2) void TNT_(helperc_STOREV8) ( Addr, UWord ); 218 | 219 | VG_REGPARM(2) void TNT_(helperc_LOADV256be) ( /*OUT*/V256*, Addr ); 220 | VG_REGPARM(2) void TNT_(helperc_LOADV256le) ( /*OUT*/V256*, Addr ); 221 | VG_REGPARM(2) void TNT_(helperc_LOADV128be) ( /*OUT*/V128*, Addr ); 222 | VG_REGPARM(2) void TNT_(helperc_LOADV128le) ( /*OUT*/V128*, Addr ); 223 | VG_REGPARM(1) ULong TNT_(helperc_LOADV64be) ( Addr ); 224 | VG_REGPARM(1) ULong TNT_(helperc_LOADV64le) ( Addr ); 225 | VG_REGPARM(1) UWord TNT_(helperc_LOADV32be) ( Addr ); 226 | VG_REGPARM(1) UWord TNT_(helperc_LOADV32le) ( Addr ); 227 | VG_REGPARM(1) UWord TNT_(helperc_LOADV16be) ( Addr ); 228 | VG_REGPARM(1) UWord TNT_(helperc_LOADV16le) ( Addr ); 229 | VG_REGPARM(1) UWord TNT_(helperc_LOADV8) ( Addr ); 230 | #if _SECRETGRIND_ 231 | VG_REGPARM(1) UWord TNT_(helperc_LOADV8_extended) ( Addr a, UWord taint ); 232 | VG_REGPARM(1) UWord TNT_(helperc_LOADV16le_extended) ( Addr a, UWord taint ); 233 | VG_REGPARM(1) UWord TNT_(helperc_LOADV16be_extended) ( Addr a, UWord taint ); 234 | VG_REGPARM(1) UWord TNT_(helperc_LOADV32le_extended) ( Addr a, UWord taint ); 235 | VG_REGPARM(1) UWord TNT_(helperc_LOADV32be_extended) ( Addr a, UWord taint ); 236 | VG_REGPARM(1) ULong TNT_(helperc_LOADV64le_extended) ( Addr a, ULong taint ); 237 | VG_REGPARM(1) ULong TNT_(helperc_LOADV64be_extended) ( Addr a, ULong taint ); 238 | #endif 239 | void TNT_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len, 240 | Addr nia ); 241 | 242 | /* Taintgrind args */ 243 | #define MAX_PATH 256 244 | 245 | // Added by Laurent 246 | #define max(x,y) ((x)>(y)?(x):(y)) 247 | 248 | 249 | #if !_SECRETGRIND_ 250 | extern HChar TNT_(clo_file_filter)[MAX_PATH]; 251 | #endif 252 | extern Int TNT_(clo_filetaint_start); 253 | extern Int TNT_(clo_filetaint_len); 254 | extern Bool TNT_(clo_taint_all); 255 | extern Int TNT_(clo_after_kbb); 256 | extern Int TNT_(clo_before_kbb); 257 | extern Bool TNT_(clo_trace_taint_only); 258 | extern Bool TNT_(clo_critical_ins_only); 259 | extern Int TNT_(do_print); 260 | 261 | #define KRED "\e[31m" 262 | #define KMAG "\e[35m" 263 | #define KNRM "\e[0m" 264 | #define KGRN "\e[32m" 265 | #define KUDL "\e[4m" // underlined 266 | 267 | 268 | // see pub_tool_basic.h 269 | #define STR(x) #x 270 | #define UWORD_FMT(z) STR(l ## z) 271 | #define ADDR_FMT(z) UWORD_FMT(z) 272 | #define SIZE_FMT(z) UWORD_FMT(l ## z) 273 | #define UCHAR_FMT(z) STR(z) 274 | #define ULONG_FMT(z) STR(ll ## z) 275 | 276 | /* Functions defined in malloc_wrappers.c */ 277 | #define TNT_MALLOC_REDZONE_SZB 16 278 | 279 | #if 0 280 | /* For malloc()/new/new[] vs. free()/delete/delete[] mismatch checking. */ 281 | typedef 282 | enum { 283 | TNT_AllocMalloc = 0, 284 | TNT_AllocNew = 1, 285 | TNT_AllocNewVec = 2, 286 | TNT_AllocCustom = 3 287 | } 288 | TNT_AllocKind; 289 | #endif 290 | 291 | #if _SECRETGRIND_ 292 | typedef 293 | enum { 294 | SN_ADDR_UNKNOWN = 0, // DO NOT CHANGE THESE VALUES OR THEIR ORDERS -- i use them as index to arrays and assume this order 295 | SN_ADDR_GLOBAL, 296 | SN_ADDR_HEAP_MALLOC, 297 | SN_ADDR_MMAP_FILE, // mmap a file 298 | SN_ADDR_MMAP, // mmap which is not a file 299 | SN_ADDR_STACK, 300 | SN_ADDR_OTHER 301 | } 302 | sn_addr_type_t; 303 | 304 | 305 | #endif 306 | 307 | /* This describes a heap block. Nb: first two fields must match core's 308 | * VgHashNode. */ 309 | #if _SECRETGRIND_ 310 | 311 | // the maximum number of frames in a stack we want can record 312 | # define MAX_STACK_FRAME 50 313 | # define MAX_STACK_DESC_LEN 2048 314 | # define MAX_FIX_IDS 10 315 | # define MAX_FILE_FILTER 16 316 | 317 | typedef long ID_t; 318 | typedef 319 | struct { 320 | char mnemonics[32]; 321 | Addr addr; 322 | HChar len; 323 | ID_t ID; 324 | ExeContext *ec; // this is only filled when requested by user, because sometimes valgrind fails to give the fill stack trace after imark 325 | } 326 | Inst_t; 327 | #endif 328 | typedef 329 | struct _HP_Chunk { 330 | struct _HP_Chunk* next; // this is necessary for valgrind hashmap implementation: do not touch 331 | Addr data; // Address of the actual block. 332 | SizeT req_szB; // Size requested 333 | SizeT slop_szB; // Extra bytes given above those requested 334 | #if _SECRETGRIND_ 335 | ExeContext *stack_trace; // note: there does not seem to be a function to free this afters 336 | // the content of this trace depends on mem type. It can be the taint trace, the malloc/mmap trace 337 | sn_addr_type_t addrType; 338 | char vname[256]; 339 | char vdetailedname[1024]; 340 | Inst_t inst; 341 | 342 | unsigned int api :1; // this indicates that the block was tainted as the result of a call to TNT_MAKE_TAINTED() 343 | 344 | // this is for blocks that are allocated, ie malloc()'ed, mmap()'ed, etc 345 | // only valid for heap/file-mmap blocks at the moment:TODO for mmap 346 | struct { 347 | struct _HP_Chunk *parent; // for heap/file-mmap block, this contain its "parent" block 348 | unsigned int hasChild : 1; // for heap/file-mmap block, this indicates if it has a child pointing to it; and we should not free it 349 | // TODO: replace hasCHild with a linked list of blocks so that we can list all taint on non-free()'ed blocks 350 | unsigned int master : 1; // for heap/file-mmap blocks, this indicates it's a "master block" in the sense that it was mmap()'ed/malloc()'ed 351 | ExeContext * release_trace; // for heap/file-mmap blocks, contains the trace when the block was free()'ed/mumap()'ed. 0 means the block was not free()'ed 352 | }Alloc; 353 | 354 | #endif 355 | } 356 | HP_Chunk; 357 | #if 0 358 | /* Memory pool. Nb: first two fields must match core's VgHashNode. */ 359 | typedef 360 | struct _TNT_Mempool { 361 | struct _TNT_Mempool* next; 362 | Addr pool; // pool identifier 363 | SizeT rzB; // pool red-zone size 364 | Bool is_zeroed; // allocations from this pool are zeroed 365 | VgHashTable chunks; // chunks associated with this pool 366 | } 367 | TNT_Mempool; 368 | 369 | 370 | void* TNT_(new_block) ( ThreadId tid, 371 | Addr p, SizeT size, SizeT align, 372 | Bool is_zeroed, TNT_AllocKind kind, 373 | VgHashTable table); 374 | void TNT_(handle_free) ( ThreadId tid, 375 | Addr p, UInt rzB, TNT_AllocKind kind ); 376 | 377 | void TNT_(create_mempool) ( Addr pool, UInt rzB, Bool is_zeroed ); 378 | void TNT_(destroy_mempool) ( Addr pool ); 379 | void TNT_(mempool_alloc) ( ThreadId tid, Addr pool, 380 | Addr addr, SizeT size ); 381 | void TNT_(mempool_free) ( Addr pool, Addr addr ); 382 | void TNT_(mempool_trim) ( Addr pool, Addr addr, SizeT size ); 383 | void TNT_(move_mempool) ( Addr poolA, Addr poolB ); 384 | void TNT_(mempool_change) ( Addr pool, Addr addrA, Addr addrB, SizeT size ); 385 | Bool TNT_(mempool_exists) ( Addr pool ); 386 | 387 | TNT_Chunk* TNT_(get_freed_list_head)( void ); 388 | #endif 389 | 390 | extern void TNT_(stop_print)(void); 391 | extern void TNT_(start_print)(Bool all); 392 | 393 | #if _SECRETGRIND_ 394 | #define RAW_ADDR_FMT "0x%lx" 395 | extern Bool TNT_(is_mem_byte_tainted)(Addr a); 396 | extern ExeContext * TNT_(retrieveExeContext)(void); 397 | extern Bool TNT_(clo_verbose); 398 | extern Bool TNT_(clo_mnemonics); 399 | extern Bool TNT_(clo_taint_warn_on_release); 400 | extern Bool TNT_(clo_taint_show_source); 401 | extern Bool TNT_(clo_trace); 402 | extern SizeT TNT_(clo_mmap_pagesize); 403 | extern Bool TNT_(clo_summary_total_only); 404 | extern Inst_t TNT_(current_inst); 405 | extern Bool TNT_(clo_taint_stdin); 406 | extern ID_t TNT_(clo_list_inst_IDs)[MAX_FIX_IDS]; 407 | extern Bool TNT_(inst_need_fix)(long ID); 408 | extern Bool TNT_(mnemoReady); 409 | extern Bool TNT_(clo_taint_df_only); 410 | extern Bool TNT_(clo_taint_remove_on_release); 411 | extern Bool TNT_(clo_batchmode); 412 | extern Bool TNT_(clo_summary); 413 | extern Bool TNT_(clo_summary_verbose); 414 | extern Bool TNT_(clo_summary_exit_only); 415 | extern Bool TNT_(clo_summary_main_only); 416 | extern Bool TNT_(clo_summary_total_only); 417 | extern Bool TNT_(clo_var_name); 418 | extern const char * TNT_(addr_type_to_string)(sn_addr_type_t type); 419 | extern sn_addr_type_t TNT_(get_addr_type)(Addr a); 420 | extern void TNT_(get_object_name)(char *objname, SizeT n); 421 | extern void TNT_(record_receive_taint_for_addr)(Addr addr, SizeT len, Bool api, const char *srcname); 422 | extern void TNT_(display_receive_taint_for_addr)(Addr addr, SizeT len, const char *addrInfo, const char *srcname); 423 | extern IRType TNT_(getTypeOfIRExpr)(IRExpr* e); 424 | extern void TNT_(record_StackTrace)( char *out, SizeT size, SizeT max_n_ips, const char *msg ); 425 | extern Bool TNT_(isPowerOfTwo)(SizeT x); 426 | extern Bool TNT_(taint_file_params_are_default)(void); 427 | 428 | 429 | #define EMIT_ERROR(...) do { VG_(printf)(KRED); VG_(printf)(__VA_ARGS__); VG_(printf)(KNRM); }while(0) 430 | #define EMIT_INFO(...) do { VG_(printf)(KMAG); VG_(printf)(__VA_ARGS__); VG_(printf)(KNRM); }while(0) 431 | #define EMIT_SUCCESS(...) do { VG_(printf)(KGRN); VG_(printf)(__VA_ARGS__); VG_(printf)(KNRM); }while(0) 432 | 433 | #endif // _SECRETGRIND_ 434 | 435 | // some debug utility functions. Also useful for taintgrind 436 | #define LOG(...) do { /*VG_(printf)(__VA_ARGS__);*/ }while(0) 437 | 438 | #define LOG_MEM(PTR) do { LOG("%s -> [0x%lx]\n", #PTR, (long)PTR); }while(0) 439 | 440 | #define LOG_ENTER() do { LOG("ENTER \"%s\"\n", __PRETTY_FUNCTION__); }while(0) 441 | 442 | #define LOG_EXIT() do { LOG("EXIT \"%s\"\n", __PRETTY_FUNCTION__); }while(0) 443 | 444 | #define LOG_CALL(EXP) do { LOG("CALLING \"%s\"\n", #EXP); EXP; LOG("CALL to \"%s\" OK.\n", #EXP); }while(0) 445 | 446 | #define LOG_TRACE() LOG_ENTER() 447 | 448 | 449 | /* For tracking memory pools. */ 450 | //extern VgHashTable TNT_(mempool_list); 451 | 452 | /* Shadow memory functions */ 453 | Bool TNT_(check_mem_is_noaccess)( Addr a, SizeT len, Addr* bad_addr ); 454 | void TNT_(make_mem_noaccess) ( Addr a, SizeT len ); 455 | void TNT_(make_mem_undefined_w_otag)( Addr a, SizeT len, UInt otag ); 456 | void TNT_(make_mem_defined) ( Addr a, SizeT len ); 457 | void TNT_(copy_address_range_state) ( Addr src, Addr dst, SizeT len ); 458 | 459 | void TNT_(print_malloc_stats) ( void ); 460 | 461 | void* TNT_(malloc) ( ThreadId tid, SizeT n ); 462 | void* TNT_(__builtin_new) ( ThreadId tid, SizeT n ); 463 | void* TNT_(__builtin_vec_new) ( ThreadId tid, SizeT n ); 464 | void* TNT_(memalign) ( ThreadId tid, SizeT align, SizeT n ); 465 | void* TNT_(calloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ); 466 | void TNT_(free) ( ThreadId tid, void* p ); 467 | void TNT_(__builtin_delete) ( ThreadId tid, void* p ); 468 | void TNT_(__builtin_vec_delete) ( ThreadId tid, void* p ); 469 | void* TNT_(realloc) ( ThreadId tid, void* p, SizeT new_size ); 470 | SizeT TNT_(malloc_usable_size) ( ThreadId tid, void* p ); 471 | 472 | 473 | /* Functions defined in tnt_syswrap.c */ 474 | /* System call wrappers */ 475 | extern void TNT_(syscall_read)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 476 | extern void TNT_(syscall_write)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 477 | extern void TNT_(syscall_open)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 478 | extern void TNT_(syscall_close)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 479 | extern void TNT_(syscall_llseek)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 480 | extern void TNT_(syscall_lseek)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 481 | extern void TNT_(syscall_pread)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 482 | extern Bool TNT_(syscall_allowed_check)(ThreadId tid, int syscallno); 483 | extern void TNT_(syscall_recv)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 484 | extern void TNT_(syscall_recvfrom)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 485 | 486 | 487 | /* Functions defined in tnt_translate.c */ 488 | IRSB* TNT_(instrument)( VgCallbackClosure* closure, 489 | IRSB* bb_in, 490 | VexGuestLayout* layout, 491 | VexGuestExtents* vge, 492 | VexArchInfo* vai, 493 | IRType gWordTy, IRType hWordTy ); 494 | 495 | 496 | /* Client request handler */ 497 | extern Bool TNT_(handle_client_requests) ( ThreadId tid, UWord* arg, UWord* ret ); 498 | 499 | /* SOAAP-related data */ 500 | extern HChar* client_binary_name; 501 | #define FNNAME_MAX 100 502 | 503 | extern UInt persistent_sandbox_nesting_depth; 504 | extern UInt ephemeral_sandbox_nesting_depth; 505 | extern Bool have_created_sandbox; 506 | 507 | #define FD_MAX 256 508 | #define FD_MAX_PATH 256 509 | #define FD_READ 0x1 510 | #define FD_WRITE 0x2 511 | #define FD_STAT 0x4 512 | 513 | extern UInt shared_fds[]; 514 | 515 | #define VAR_MAX 100 516 | #define VAR_READ 0x1 517 | #define VAR_WRITE 0x2 518 | 519 | enum VariableType { Local = 3, Global = 4 }; 520 | enum VariableLocation { GlobalFromApplication = 5, GlobalFromElsewhere = 6 }; 521 | 522 | extern struct myStringArray shared_vars; 523 | extern UInt shared_vars_perms[]; 524 | extern HChar* next_shared_variable_to_update; 525 | 526 | #define IN_SANDBOX (persistent_sandbox_nesting_depth > 0 || ephemeral_sandbox_nesting_depth > 0) 527 | 528 | #define FD_SET_PERMISSION(fd,perm) shared_fds[fd] |= perm 529 | #define VAR_SET_PERMISSION(var_idx,perm) shared_vars_perms[var_idx] |= perm 530 | 531 | #define SYSCALLS_MAX 500 532 | extern Bool allowed_syscalls[]; 533 | #define IS_SYSCALL_ALLOWED(no) (allowed_syscalls[no] == True) 534 | 535 | extern UInt callgate_nesting_depth; 536 | #define IN_CALLGATE (nested_callgate_depth > 0) 537 | 538 | /* System call array */ 539 | extern const char* syscallnames[]; 540 | 541 | /* Utility functions */ 542 | #if _SECRETGRIND_ 543 | extern void TNT_(print_CurrentStackTrace) ( ThreadId tid, UInt max_n_ips, const char *msg ); 544 | extern void TNT_(print_MallocExeContext)( ExeContext* ec, UInt n_ips ); 545 | extern void TNT_(print_FreeParentExeContext)( ExeContext* ec, UInt n_ips ); 546 | extern void TNT_(print_MunmapParentExeContext)( ExeContext* ec, UInt n_ips ); 547 | extern void TNT_(print_MallocParentExeContext)( ExeContext* ec, UInt n_ips ); 548 | extern void TNT_(print_MmapParentExeContext)( ExeContext* ec, UInt n_ips ); 549 | extern void TNT_(print_MmapExeContext)( ExeContext* ec, UInt n_ips ); 550 | extern void TNT_(display_mem_region_of)(Addr a, SizeT len); 551 | extern void TNT_(describe_data)(Addr addr, HChar* varnamebuf, SizeT bufsize, HChar* detailedvarnamebuf, SizeT detailedbufsize, const char *fn, SizeT len, Bool api); 552 | extern HP_Chunk * TNT_(alloc_chunk_from_varnames)(Addr a, SizeT reqLen, SizeT slopLen, const char *name, const char *dname); 553 | extern HP_Chunk * TNT_(alloc_chunk_from_varnames_and_type)(Addr a, SizeT reqLen, SizeT slopLen, const char *name, const char *dname, sn_addr_type_t type, Bool api); 554 | extern void TNT_(alloc_chunk_from_fn_and_add_sum_block)(Addr a, SizeT reqLen, SizeT slopLen, Bool api, const char *fn); 555 | #else 556 | extern void TNT_(describe_data)(Addr addr, HChar* varnamebuf, UInt bufsize, enum VariableType* type, enum VariableLocation* loc); 557 | #endif // _SECRETGRIND_ 558 | extern void TNT_(get_fnname)(ThreadId tid, HChar* buf, UInt buf_size); 559 | extern void TNT_(check_fd_access)(ThreadId tid, UInt fd, Int fd_request); 560 | extern void TNT_(check_var_access)(ThreadId tid, HChar* varname, Int var_request, enum VariableType type, enum VariableLocation var_loc); 561 | 562 | #endif /* ndef __TNT_INCLUDE_H */ 563 | 564 | /*--------------------------------------------------------------------*/ 565 | /*--- end ---*/ 566 | /*--------------------------------------------------------------------*/ 567 | -------------------------------------------------------------------------------- /tnt_libc.c: -------------------------------------------------------------------------------- 1 | #include "pub_tool_libcbase.h" 2 | 3 | #include "secretgrind.h" 4 | #include "tnt_include.h" 5 | #include "tnt_libc.h" 6 | #include "pub_tool_stacktrace.h" 7 | #include "pub_tool_libcassert.h" 8 | #include "pub_tool_libcfile.h" 9 | #include "pub_tool_mallocfree.h" 10 | 11 | int errno = 0; 12 | 13 | /* -------------------------------------------- */ 14 | /* ----------- libc functions i want ---------- */ 15 | /* -------------------------------------------- */ 16 | 17 | 18 | static inline int 19 | isupper(char c) 20 | { 21 | return (c >= 'A' && c <= 'Z'); 22 | } 23 | 24 | static inline int 25 | isalpha(char c) 26 | { 27 | return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); 28 | } 29 | 30 | 31 | static inline int 32 | isspace(char c) 33 | { 34 | return (c == ' ' || c == '\t' || c == '\n' || c == '\12'); 35 | } 36 | 37 | static inline int 38 | isdigit(char c) 39 | { 40 | return (c >= '0' && c <= '9'); 41 | } 42 | 43 | /* -------------------------------------------- */ 44 | /* ----------------- strlcpy(l) ---------------- */ 45 | /* -------------------------------------------- */ 46 | 47 | SizeT libc_strlcpy(char *dst, const char *src, SizeT len) 48 | { 49 | SizeT srcLen = VG_(strlen)(src); 50 | SizeT dstLen = 0; 51 | dst[0] = '\0'; 52 | 53 | if (len) { 54 | VG_(strncpy)(dst, src, len-1); 55 | dst[VG_(strlen)(src)] = '\0'; 56 | } 57 | 58 | dstLen = VG_(strlen)(dst); 59 | return max(dstLen, srcLen); 60 | } 61 | 62 | /* -------------------------------------------- */ 63 | /* ----------------- strlcat(l) ---------------- */ 64 | /* -------------------------------------------- */ 65 | 66 | SizeT libc_strlcat(char *dst, const char *src, SizeT len) 67 | { 68 | SizeT srcLen = VG_(strlen)(src); 69 | SizeT dstLen = 0; 70 | 71 | if ( len ) { 72 | VG_(strncat)(dst, src, len-1); 73 | dst[VG_(strlen)(src)] = '\0'; 74 | } 75 | 76 | dstLen = VG_(strlen)(dst); 77 | tl_assert ( dstLen <= (SizeT)(-1) - srcLen ); 78 | return (dstLen + srcLen); /* count does not include NUL */ 79 | } 80 | 81 | /* -------------------------------------------- */ 82 | /* ----------------- strtol(l) ---------------- */ 83 | /* -------------------------------------------- */ 84 | 85 | // Note: copied from https://opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/strtol.c 86 | 87 | /* 88 | * Convert a string to a long integer. 89 | * 90 | * Ignores `locale' stuff. Assumes that the upper and lower case 91 | * alphabets and digits are each contiguous. 92 | */ 93 | long 94 | libc_strtol(nptr, endptr, base) 95 | const char *nptr; 96 | char **endptr; 97 | register int base; 98 | { 99 | register const char *s = nptr; 100 | register unsigned long acc; 101 | register int c; 102 | register unsigned long cutoff; 103 | register int neg = 0, any, cutlim; 104 | errno = EOK; 105 | 106 | /* 107 | * Skip white space and pick up leading +/- sign if any. 108 | * If base is 0, allow 0x for hex and 0 for octal, else 109 | * assume decimal; if base is already 16, allow 0x. 110 | */ 111 | do { 112 | c = *s++; 113 | } while (isspace(c)); 114 | if (c == '-') { 115 | neg = 1; 116 | c = *s++; 117 | } else if (c == '+') 118 | c = *s++; 119 | if ((base == 0 || base == 16) && 120 | c == '0' && (*s == 'x' || *s == 'X')) { 121 | c = s[1]; 122 | s += 2; 123 | base = 16; 124 | } else if ((base == 0 || base == 2) && 125 | c == '0' && (*s == 'b' || *s == 'B')) { 126 | c = s[1]; 127 | s += 2; 128 | base = 2; 129 | } 130 | if (base == 0) 131 | base = c == '0' ? 8 : 10; 132 | 133 | /* 134 | * Compute the cutoff value between legal numbers and illegal 135 | * numbers. That is the largest legal value, divided by the 136 | * base. An input number that is greater than this value, if 137 | * followed by a legal input character, is too big. One that 138 | * is equal to this value may be valid or not; the limit 139 | * between valid and invalid numbers is then based on the last 140 | * digit. For instance, if the range for longs is 141 | * [-2147483648..2147483647] and the input base is 10, 142 | * cutoff will be set to 214748364 and cutlim to either 143 | * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated 144 | * a value > 214748364, or equal but the next digit is > 7 (or 8), 145 | * the number is too big, and we will return a range error. 146 | * 147 | * Set any if any `digits' consumed; make it negative to indicate 148 | * overflow. 149 | */ 150 | cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; 151 | cutlim = cutoff % (unsigned long)base; 152 | cutoff /= (unsigned long)base; 153 | for (acc = 0, any = 0;; c = *s++) { 154 | if (isdigit(c)) 155 | c -= '0'; 156 | else if (isalpha(c)) 157 | c -= isupper(c) ? 'A' - 10 : 'a' - 10; 158 | else 159 | break; 160 | if (c >= base) 161 | break; 162 | if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 163 | any = -1; 164 | else { 165 | any = 1; 166 | acc *= base; 167 | acc += c; 168 | } 169 | } 170 | if (any < 0) { 171 | acc = neg ? LONG_MIN : LONG_MAX; 172 | errno = ERANGE; 173 | } else if (neg) 174 | acc = -acc; 175 | if (endptr != 0) 176 | *endptr = (char *)(any ? s - 1 : nptr); 177 | return (acc); 178 | } 179 | 180 | /* 181 | * Convert a string to an unsigned long integer. 182 | * 183 | * Ignores `locale' stuff. Assumes that the upper and lower case 184 | * alphabets and digits are each contiguous. 185 | */ 186 | unsigned long 187 | libc_strtoul(nptr, endptr, base) 188 | const char *nptr; 189 | char **endptr; 190 | register int base; 191 | { 192 | register const char *s = nptr; 193 | register unsigned long acc; 194 | register int c; 195 | register unsigned long cutoff; 196 | register int neg = 0, any, cutlim; 197 | errno = EOK; 198 | 199 | /* 200 | * See strtol for comments as to the logic used. 201 | */ 202 | do { 203 | c = *s++; 204 | } while (isspace(c)); 205 | if (c == '-') { 206 | neg = 1; 207 | c = *s++; 208 | } else if (c == '+') 209 | c = *s++; 210 | if ((base == 0 || base == 16) && 211 | c == '0' && (*s == 'x' || *s == 'X')) { 212 | c = s[1]; 213 | s += 2; 214 | base = 16; 215 | } else if ((base == 0 || base == 2) && 216 | c == '0' && (*s == 'b' || *s == 'B')) { 217 | c = s[1]; 218 | s += 2; 219 | base = 2; 220 | } 221 | if (base == 0) 222 | base = c == '0' ? 8 : 10; 223 | cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 224 | cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 225 | for (acc = 0, any = 0;; c = *s++) { 226 | if (isdigit(c)) 227 | c -= '0'; 228 | else if (isalpha(c)) 229 | c -= isupper(c) ? 'A' - 10 : 'a' - 10; 230 | else 231 | break; 232 | if (c >= base) 233 | break; 234 | if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 235 | any = -1; 236 | else { 237 | any = 1; 238 | acc *= base; 239 | acc += c; 240 | } 241 | } 242 | if (any < 0) { 243 | acc = ULONG_MAX; 244 | errno = ERANGE; 245 | } else if (neg) 246 | acc = -acc; 247 | if (endptr != 0) 248 | *endptr = (char *)(any ? s - 1 : nptr); 249 | return (acc); 250 | } 251 | 252 | /* -------------------------------------------- */ 253 | /* ----------------- basename(path) ----------- */ 254 | /* -------------------------------------------- */ 255 | 256 | char * libc_basename (path) 257 | char * path; 258 | { 259 | /*char *s = VG_(strrchr) (path, '/'); 260 | 261 | return (s == NULL) ? path : ++s;*/ 262 | return (char*)VG_(basename)(path); 263 | } 264 | 265 | /* -------------------------------------------- */ 266 | /* ----------------- strncat ----------------- */ 267 | /* -------------------------------------------- */ 268 | // copy from https://opensource.apple.com/source/Libc/Libc-262/i386/gen/strncat.c 269 | 270 | /* 271 | * Concatenate src on the end of dst. At most strlen(dst)+n+1 bytes 272 | * are written at dst (at most n+1 bytes being appended). Return dst. 273 | */ 274 | /*char * 275 | libc_strncat(dst, src, n) 276 | char *dst; 277 | const char *src; 278 | register SizeT n; 279 | { 280 | if (n != 0) { 281 | register char *d = dst; 282 | register const char *s = src; 283 | 284 | while (*d != 0) 285 | d++; 286 | do { 287 | if ((*d = *s++) == 0) 288 | break; 289 | d++; 290 | } while (--n != 0); 291 | *d = 0; 292 | } 293 | return (dst); 294 | }*/ 295 | 296 | 297 | /* -------------------------------------------- */ 298 | /* ----------------- realpath ----------------- */ 299 | /* -------------------------------------------- */ 300 | /* 301 | #if defined VGO_linux 302 | # include "vki/vki-linux.h" 303 | # define VKI_ELOOP (40) // not defined in vki-linux.h 304 | #else 305 | # error OS unknown 306 | #endif 307 | 308 | #if defined VGA_amd64 309 | # include "vki/vki-amd64-linux.h" 310 | #else 311 | # error arch unknown 312 | #endif 313 | 314 | // defined in tnt_syswrap.c 315 | extern void resolve_filename(Int fd, HChar *path, SizeT max); 316 | // defined in coregrind/m_syscall 317 | extern SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, 318 | UWord a4, UWord a5, UWord a6, 319 | UWord a7, UWord a8 ); 320 | 321 | char *libc_realpath(const char * filename, char * resolved) 322 | { 323 | Int fd; 324 | Int r; 325 | SysRes statres; 326 | struct vg_stat st1, st2; 327 | char buf[PATH_MAX]; 328 | char tmp[PATH_MAX]; 329 | 330 | if (!filename) { 331 | errno = VKI_EINVAL; 332 | return 0; 333 | } 334 | 335 | fd = VG_(fd_open)(filename, VKI_O_RDONLY|VKI_O_NONBLOCK, 0666); 336 | if (fd < 0) return 0; 337 | resolve_filename(fd, buf, sizeof(buf)); 338 | LOG("buf:%s\n", buf); 339 | 340 | // I don't call as below because I want to test for the error 341 | //r = VG_(readlink)(buf, tmp, sizeof tmp - 1); 342 | SysRes res = VG_(do_syscall)(__NR_readlink, (UWord)buf, (UWord)tmp, sizeof tmp - 1, 0,0,0,0,0); 343 | if ( sr_isError(res) && sr_Err(res) == VKI_EINVAL ) { 344 | // it's not a symbolic link, just copy the original 345 | return resolved ? VG_(strcpy)(resolved, filename) : VG_(strdup)("realpath-dup", filename); 346 | } 347 | r = sr_isError(res) ? -1 : sr_Res(res); 348 | LOG("readlink:%u\n", sr_Err(res)); 349 | if (r < 0) goto err; 350 | tmp[r] = 0; 351 | LOG("readlink:%s\n", tmp); 352 | 353 | VG_(fstat) (fd, &st1); 354 | statres = VG_(stat)( tmp, &st2 ); 355 | LOG("stat error:%d\n", sr_isError(statres)); 356 | if ( sr_isError(statres) || st1.dev != st2.dev || st1.ino != st2.ino) { 357 | if (!sr_Err(statres)) errno = VKI_ELOOP; 358 | goto err; 359 | } 360 | 361 | VG_(close)(fd); 362 | return resolved ? VG_(strcpy)(resolved, tmp) : VG_(strdup)("realpath-dup",tmp); 363 | 364 | err: 365 | VG_(close)(fd); 366 | return 0; 367 | } 368 | * */ 369 | 370 | -------------------------------------------------------------------------------- /tnt_libc.h: -------------------------------------------------------------------------------- 1 | #ifndef TNT_LIBC_H 2 | #define TNT_LIBC_H 3 | 4 | #include "pub_tool_basics.h" 5 | 6 | #define EOK 0 7 | #define ERANGE 1 8 | extern int errno; 9 | extern SizeT libc_strlcpy(char *dst, const char *src, SizeT len); 10 | extern long libc_strtol(const char *nptr, char **endptr, int base); 11 | extern unsigned long libc_strtoul(const char *nptr, char **endptr, int base); 12 | extern char * libc_basename(char *path); 13 | //extern char * libc_strncat(char *dst, const char *src, SizeT n); 14 | extern SizeT libc_strlcat(char *dst, const char *src, SizeT len); 15 | extern char *libc_realpath(const char * filename, char * resolved); 16 | #endif // TNT_LIBC_H 17 | -------------------------------------------------------------------------------- /tnt_malloc_wrappers.c: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------*/ 2 | //--- malloc/free wrappers for Taintgrind tnt_malloc_wrappers.c ---*/ 3 | //--------------------------------------------------------------------*/ 4 | 5 | /* 6 | This file is part of Taintgrind. 7 | usage of programs. 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License as 11 | published by the Free Software Foundation; either version 2 of the 12 | License, or (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, but 15 | WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 22 | 02111-1307, USA. 23 | 24 | The GNU General Public License is contained in the file COPYING. 25 | */ 26 | 27 | //------------------------------------------------------------// 28 | //--- malloc() et al replacement wrappers for Taintgrind ---// 29 | //------------------------------------------------------------// 30 | //--- Simplified version adapted from Massif. ---// 31 | //--- The main reason for replacing malloc etc. is to ---// 32 | //--- untaint data when free is called, and to copy taint ---// 33 | //--- state when realloc is called. ---// 34 | //------------------------------------------------------------// 35 | 36 | #include "pub_tool_basics.h" 37 | #include "pub_tool_hashtable.h" 38 | #include "pub_tool_libcbase.h" 39 | #include "pub_tool_libcassert.h" 40 | #include "pub_tool_mallocfree.h" 41 | #include "pub_tool_replacemalloc.h" 42 | #include "pub_tool_tooliface.h" 43 | #include "pub_tool_xarray.h" 44 | #include "pub_tool_threadstate.h" 45 | #include "pub_tool_libcprint.h" // VG_(message) 46 | #include "pub_tool_debuginfo.h" 47 | #include "pub_tool_execontext.h" 48 | #include "pub_tool_stacktrace.h" 49 | #include "pub_tool_libcproc.h" 50 | 51 | #include "tnt_include.h" 52 | #include "tnt_summary_names.h" 53 | #include "tnt_subblock_helper.h" 54 | #include "tnt_malloc_wrappers.h" 55 | 56 | static 57 | void* record_block( ThreadId tid, void* p, SizeT req_szB, SizeT slop_szB ); 58 | 59 | /* For tracking malloc'd blocks. Nb: it's quite important that it's a 60 | VgHashTable, because VgHashTable allows duplicate keys without complaint. 61 | This can occur if a user marks a malloc() block as also a custom block with 62 | MALLOCLIKE_BLOCK. */ 63 | static VgHashTable TNT_(malloc_list) = NULL; // HP_Chunks 64 | 65 | // this one is just to keep free()'ed chunks that have childs 66 | static VgHashTable TNT_(freed_wchild_list) = NULL; // HP_Chunks 67 | 68 | #if _SECRETGRIND_ 69 | 70 | static Addr g_heap_min = (Addr)(-1); 71 | static Addr g_heap_max = (Addr)0; 72 | 73 | #define UNKNOWN_MALLOCED_OBJ_FMT "@0x%lx_malloc_%u_%u" 74 | 75 | // dummy implementation for testing 76 | Bool TNT_(malloc_get_varname)(Addr a, char *pname, SizeT s, char *pdetailedname, SizeT ds) { 77 | 78 | Bool ret = False; 79 | HP_Chunk* hc = VG_(HT_lookup)( TNT_(malloc_list), (UWord)a ); 80 | if (hc) { 81 | LOG("malloc_get_varname 0x%lx chunk found '%s'\n", a, hc->vname); 82 | VG_(strncpy)(pname, hc->vname, s-1); 83 | pname[s-1] = '\0'; 84 | ret = True; 85 | } else { 86 | LOG("malloc_get_varname 0x%lx chunk NOT found, falling back to iteration\n", a); 87 | VG_(HT_ResetIter)(TNT_(malloc_list)); 88 | while ( (hc = VG_(HT_Next)(TNT_(malloc_list))) ) { 89 | if ( VG_(addr_is_in_block)(a, hc->data, hc->req_szB, hc->slop_szB) && hc->vname[0] != '\0') { 90 | 91 | LOG("Found addr 0x%lx in chunk thru iteration, offset %lu\n", a, a-hc->data); 92 | 93 | if (pname && s) { 94 | *pname = '\0'; 95 | VG_(snprintf)(pname, s, "%s[%lu]", hc->vname, a-hc->data); // TODO: check all written 96 | } 97 | 98 | if ( pdetailedname && ds) { 99 | *pdetailedname = '\0'; 100 | VG_(snprintf)(pdetailedname, ds, "%s[%lu]", hc->vdetailedname, a-hc->data); // TODO: check all written 101 | } 102 | 103 | ret = True; 104 | break; 105 | } 106 | } 107 | } 108 | 109 | return ret; 110 | } 111 | 112 | 113 | void TNT_(malloc_set_parent)(HP_Chunk *child, HP_Chunk *parent) { 114 | tl_assert (child && parent && parent->Alloc.master); 115 | // sanity checks, just in case: this should never happen coz it may create issues upon releasing 116 | tl_assert (child != parent); 117 | child->Alloc.parent = parent; 118 | parent->Alloc.hasChild = 1; 119 | } 120 | 121 | HP_Chunk * TNT_(malloc_get_parent_block)(Addr a, SizeT len) { 122 | 123 | HP_Chunk* hc = VG_(HT_lookup)( TNT_(malloc_list), (UWord)a ); 124 | if (hc) { 125 | LOG("malloc_get_parent_block 0x%lx chunk found '%s'\n", a, hc->vname); 126 | return hc; 127 | } else { 128 | LOG("malloc_get_parent_block 0x%lx chunk NOT found, falling back to iteration\n", a); 129 | VG_(HT_ResetIter)(TNT_(malloc_list)); 130 | while ( (hc = VG_(HT_Next)(TNT_(malloc_list))) ) { 131 | 132 | if ( !hc->Alloc.master ) { continue; } // not sure this is actually needed, since we're only looking at master blocks anyway... 133 | 134 | if ( VG_(addr_is_in_block)(a, hc->data, hc->req_szB, hc->slop_szB) && hc->vname[0] != '\0') { 135 | 136 | LOG("Found addr 0x%lx in chunk thru iteration, offset %lu\n", a, a-hc->data); 137 | // WARNING: for now assume the [addr, addr+len] does not overlap with multiple heap-allocated blocks 138 | // that is, the block is contained within the parent block completly 139 | tl_assert ( a <= (SizeT)(-1) - len ); // ensures no overflow 140 | tl_assert ( hc->data <= (SizeT)(-1) - hc->req_szB ); // ensures no overflow 141 | tl_assert ( a >= hc->data && a+len <= hc->data + hc->req_szB ); // Note: i dont account for the alignment space 142 | break; 143 | } 144 | } 145 | } 146 | 147 | tl_assert (hc && "hc NULL"); 148 | 149 | return hc; 150 | } 151 | 152 | void TNT_(malloc_reset_iter)(void) 153 | { 154 | VG_(HT_ResetIter)(TNT_(malloc_list)); 155 | } 156 | 157 | HP_Chunk * TNT_(malloc_get_next_chunk)(void) 158 | { 159 | return (HP_Chunk*) VG_(HT_Next)(TNT_(malloc_list)); 160 | } 161 | 162 | Bool TNT_(malloc_is_heap)(Addr a) 163 | { 164 | return VG_(addr_is_in_block)( a, g_heap_min, g_heap_max-g_heap_min+1, 0 ); 165 | } 166 | 167 | // use this function because heap range may change and we want to keep track of the entire range 168 | static __inline__ 169 | void update_heap_ranges(Addr a, SizeT len) 170 | { 171 | tl_assert ( sizeof(len) <= sizeof(a) ); 172 | tl_assert ( a <= (Addr)(-1) - len ); 173 | if (g_heap_max < a+len) { 174 | g_heap_max = a+len; 175 | } 176 | 177 | // update the low bound 178 | if ( g_heap_min > a) { 179 | g_heap_min = a; 180 | } 181 | } 182 | #endif 183 | 184 | static __inline__ 185 | void* alloc_and_record_block ( ThreadId tid, SizeT req_szB, SizeT req_alignB, 186 | Bool is_zeroed ) 187 | { 188 | SizeT actual_szB, slop_szB; 189 | void* p; 190 | 191 | #if _SECRETGRIND_ 192 | LOG("alloc_and_record_block req_szB %lu alignment %lu\n", req_szB, req_alignB); 193 | #endif 194 | 195 | if ((SSizeT)req_szB < 0) return NULL; 196 | 197 | // Allocate and zero if necessary. 198 | p = VG_(cli_malloc)( req_alignB, req_szB ); 199 | if (!p) { 200 | return NULL; 201 | } 202 | #if _SECRETGRIND_ 203 | LOG("malloc returned 0x%lx\n", (Addr)p); 204 | #endif 205 | 206 | if (is_zeroed) VG_(memset)(p, 0, req_szB); 207 | actual_szB = VG_(malloc_usable_size)(p); 208 | tl_assert(actual_szB >= req_szB); 209 | slop_szB = actual_szB - req_szB; 210 | 211 | // Record block. 212 | record_block(tid, p, req_szB, slop_szB); 213 | 214 | return p; 215 | } 216 | 217 | 218 | static __inline__ 219 | void unrecord_block ( void* p ) 220 | { 221 | #if _SECRETGRIND_ 222 | 223 | // remove the old chunk 224 | Bool tainted = False; 225 | HP_Chunk* hc = VG_(HT_remove)(TNT_(malloc_list), (UWord)p); 226 | tl_assert (hc); 227 | 228 | // mark the block as free()'ed and free the allocated block 229 | hc->Alloc.release_trace = TNT_(retrieveExeContext)(); 230 | VG_(cli_free)((void*)hc->data); // do not set hc->data = 0 as it contains an address we may want to read in the taint summary 231 | 232 | // warn if block is tainted. 233 | tainted = subblk_warn_if_tainted(hc, &TNT_(print_MallocExeContext), "free()'d", True); 234 | 235 | // remove taint if user asked to do so 236 | if ( TNT_(clo_taint_remove_on_release) ) { 237 | TNT_(make_mem_untainted)( (Addr)p, hc->req_szB + hc->slop_szB ); 238 | } 239 | 240 | if ( !tainted || TNT_(clo_taint_remove_on_release) ) { 241 | 242 | // if not tainted, free the hc only if it has no children 243 | if ( hc->Alloc.hasChild ) { 244 | // add it to the free()'ed list that have children 245 | VG_(HT_add_node)(TNT_(freed_wchild_list), hc); 246 | } else { 247 | // Actually free the chunk as we no longer need it 248 | VG_(free)( hc ); hc = NULL; 249 | } 250 | } 251 | 252 | #else 253 | // Remove HP_Chunk from malloc_list 254 | HP_Chunk* hc = VG_(HT_remove)(TNT_(malloc_list), (UWord)p); 255 | if (NULL == hc) { 256 | return; // must have been a bogus free() 257 | } 258 | 259 | // Untaint freed block 260 | TNT_(make_mem_untainted)( (Addr)p, hc->req_szB + hc->slop_szB ); 261 | 262 | // Actually free the chunk, and the heap block (if necessary) 263 | VG_(free)( hc ); hc = NULL; 264 | 265 | #endif 266 | } 267 | 268 | #if _SECRETGRIND_ 269 | static __inline__ 270 | Bool is_block_tainted(HP_Chunk *hc) { 271 | 272 | Addr curr_addr = (Addr)hc->data, end_addr = hc->data+hc->req_szB +hc->slop_szB; 273 | while ( curr_addr < end_addr ) { 274 | if ( TNT_(is_mem_byte_tainted)(curr_addr) ) { return True; } 275 | ++curr_addr; 276 | } 277 | return False; 278 | } 279 | #endif 280 | 281 | static __inline__ 282 | void* realloc_block ( ThreadId tid, void* p_old, SizeT new_req_szB ) 283 | { 284 | #if _SECRETGRIND_ 285 | // let's make it simple 286 | // I dont want to re-use the original hc, because 287 | // in the taint summary, it may make things harder 288 | // to folow in a trace. That is, we could think the block 289 | // was tainted after being reallocated, wherease it is before... 290 | HP_Chunk* hc; 291 | void* p_new; 292 | SizeT old_req_szB, old_slop_szB, new_slop_szB, new_actual_szB; 293 | 294 | // lookup the old block from hashMap 295 | // i dont remove it rightaway, as i call unrecord_block 296 | // which takes care of printing warning and keeping the block 297 | // if it's tainted 298 | hc = VG_(HT_lookup)(TNT_(malloc_list), (UWord)p_old); 299 | tl_assert (hc); 300 | old_req_szB = hc->req_szB; 301 | old_slop_szB = hc->slop_szB; 302 | 303 | // create new heap block 304 | p_new = VG_(cli_malloc)(VG_(clo_alignment), new_req_szB); 305 | tl_assert (p_new); 306 | 307 | // copy data from old to new block 308 | VG_(memcpy)(p_new, p_old, old_req_szB); 309 | new_actual_szB = VG_(malloc_usable_size)(p_new); 310 | tl_assert(new_actual_szB >= new_req_szB); 311 | new_slop_szB = new_actual_szB - new_req_szB; 312 | 313 | // untaint old block if necessary 314 | if ( TNT_(clo_taint_remove_on_release) ) { 315 | TNT_(make_mem_untainted)( (Addr)p_old, old_req_szB + old_slop_szB ); 316 | } 317 | 318 | // copy taint state 319 | TNT_(copy_address_range_state)( (Addr)p_old, (Addr)p_new, new_actual_szB ); 320 | 321 | // unrecord the old block 322 | unrecord_block(p_old); 323 | 324 | // record the new block 325 | record_block( tid, p_new, new_req_szB, new_slop_szB ); 326 | 327 | // record a BRAND-NEW block and push it to the summary if it contains taint 328 | // WARNING: we cannot push the block we just created, we ALWAYS need a different one 329 | hc = VG_(HT_lookup)(TNT_(malloc_list), (UWord)p_new); 330 | tl_assert (hc); 331 | if ( is_block_tainted(hc) ) { 332 | TNT_(alloc_chunk_from_fn_and_add_sum_block)((Addr)p_new, new_req_szB, new_slop_szB, False, "store"); 333 | } 334 | 335 | return p_new; 336 | #else 337 | HP_Chunk* hc; 338 | void* p_new; 339 | SizeT old_req_szB, old_slop_szB, new_slop_szB, new_actual_szB; 340 | 341 | // Remove the old block 342 | hc = VG_(HT_remove)(TNT_(malloc_list), (UWord)p_old); 343 | if (hc == NULL) { 344 | return NULL; // must have been a bogus realloc() 345 | } 346 | 347 | old_req_szB = hc->req_szB; 348 | old_slop_szB = hc->slop_szB; 349 | 350 | // Actually do the allocation, if necessary. 351 | if (new_req_szB <= old_req_szB + old_slop_szB) { 352 | // New size is smaller or same; block not moved. 353 | p_new = p_old; 354 | new_slop_szB = old_slop_szB + (old_req_szB - new_req_szB); 355 | 356 | } else { 357 | // New size is bigger; make new block, copy shared contents, free old. 358 | p_new = VG_(cli_malloc)(VG_(clo_alignment), new_req_szB); 359 | if (!p_new) { 360 | // Nb: if realloc fails, NULL is returned but the old block is not 361 | // touched. What an awful function. 362 | return NULL; 363 | } 364 | 365 | VG_(memcpy)(p_new, p_old, old_req_szB); 366 | 367 | VG_(cli_free)(p_old); 368 | new_actual_szB = VG_(malloc_usable_size)(p_new); 369 | tl_assert(new_actual_szB >= new_req_szB); 370 | new_slop_szB = new_actual_szB - new_req_szB; 371 | 372 | // Copy taint state 373 | TNT_(copy_address_range_state)( (Addr)p_old, (Addr)p_new, new_actual_szB ); 374 | 375 | # if _SECRETGRIND_ 376 | if ( TNT_(clo_taint_remove_on_release) ) { 377 | TNT_(make_mem_untainted)( (Addr)p_old, old_req_szB + old_slop_szB ); 378 | } 379 | # endif 380 | } 381 | 382 | if (p_new) { 383 | // Update HP_Chunk. 384 | hc->data = (Addr)p_new; 385 | hc->req_szB = new_req_szB; 386 | hc->slop_szB = new_slop_szB; 387 | } 388 | 389 | // Now insert the new hc (with a possibly new 'data' field) into 390 | // malloc_list. If this realloc() did not increase the memory size, we 391 | // will have removed and then re-added hc unnecessarily. But that's ok 392 | // because shrinking a block with realloc() is (presumably) much rarer 393 | // than growing it, and this way simplifies the growing case. 394 | VG_(HT_add_node)(TNT_(malloc_list), hc); 395 | return p_new; 396 | #endif 397 | } 398 | 399 | 400 | void* TNT_(malloc) ( ThreadId tid, SizeT szB ) 401 | { 402 | return alloc_and_record_block( tid, szB, VG_(clo_alignment), /*is_zeroed*/False ); 403 | } 404 | 405 | void* TNT_(__builtin_new) ( ThreadId tid, SizeT szB ) 406 | { 407 | return alloc_and_record_block( tid, szB, VG_(clo_alignment), /*is_zeroed*/False ); 408 | } 409 | 410 | void* TNT_(__builtin_vec_new) ( ThreadId tid, SizeT szB ) 411 | { 412 | return alloc_and_record_block( tid, szB, VG_(clo_alignment), /*is_zeroed*/False ); 413 | } 414 | 415 | void* TNT_(calloc) ( ThreadId tid, SizeT m, SizeT szB ) 416 | { 417 | return alloc_and_record_block( tid, m*szB, VG_(clo_alignment), /*is_zeroed*/True ); 418 | } 419 | 420 | void *TNT_(memalign) ( ThreadId tid, SizeT alignB, SizeT szB ) 421 | { 422 | return alloc_and_record_block( tid, szB, alignB, False ); 423 | } 424 | 425 | void TNT_(free) ( ThreadId tid __attribute__((unused)), void* p ) 426 | { 427 | unrecord_block(p); 428 | #if !_SECRETGRIND_ // done in unrecord_block if need be 429 | VG_(cli_free)(p); 430 | #endif 431 | } 432 | 433 | void TNT_(__builtin_delete) ( ThreadId tid, void* p ) 434 | { 435 | unrecord_block(p); 436 | #if !_SECRETGRIND_ // done in unrecord_block if need be 437 | VG_(cli_free)(p); 438 | #endif 439 | } 440 | 441 | void TNT_(__builtin_vec_delete) ( ThreadId tid, void* p ) 442 | { 443 | unrecord_block(p); 444 | #if !_SECRETGRIND_ // done in unrecord_block if need be 445 | VG_(cli_free)(p); 446 | #endif 447 | } 448 | 449 | void* TNT_(realloc) ( ThreadId tid, void* p_old, SizeT new_szB ) 450 | { 451 | return realloc_block(tid, p_old, new_szB); 452 | } 453 | 454 | SizeT TNT_(malloc_usable_size) ( ThreadId tid, void* p ) 455 | { 456 | HP_Chunk* hc = VG_(HT_lookup)( TNT_(malloc_list), (UWord)p ); 457 | 458 | return ( hc ? hc->req_szB + hc->slop_szB : 0 ); 459 | } 460 | 461 | static 462 | void* record_block( ThreadId tid, void* p, SizeT req_szB, SizeT slop_szB ) 463 | { 464 | // Make new HP_Chunk node, add to malloc_list 465 | HP_Chunk* hc = 0; 466 | 467 | #if _SECRETGRIND_ 468 | 469 | LOG("record_block %p, req_szB:%lu, slop_szB:%lu\n", p, req_szB, slop_szB); 470 | update_heap_ranges((Addr)p, req_szB + slop_szB); // assume no overflow... 471 | 472 | // Note: initially I wanted to create chunks only if verbose sumary was requested 473 | // This turned out no possible because realloc requires the previous block's 474 | // length to copy data and taint 475 | if ( /*TNT_(clo_summary_verbose)*/ True ) { 476 | 477 | char vname[128], vdname[128]; 478 | 479 | //if ( TNT_(clo_var_name) ) { 480 | 481 | //char objname[128]; 482 | 483 | //TNT_(get_object_name)(objname, sizeof(objname)); 484 | //VG_(snprintf)(vname, sizeof(vname), UNKNOWN_MALLOCED_OBJ_FMT, (Addr)p); 485 | //VG_(snprintf)(vdname, sizeof(vdname), UNKNOWN_MALLOCED_OBJ_FMT, (Addr)p); 486 | 487 | //TNT_(describe_data)((Addr)p, vname,sizeof(vname), vdname, sizeof(vdname), "", 0, False, True); 488 | 489 | //} else { 490 | 491 | // the problem is that the source-code pointer does not correspond to the malloc'ed mem region 492 | // the address of the mem region is stored in the pointer. Unless we can firgure out the addr that receives 493 | // the value, we cannot give the use a name for this malloc'ed region :( 494 | 495 | char objname[128]; 496 | 497 | TNT_(get_object_name)(objname, sizeof(objname)); 498 | VG_(snprintf)(vname, sizeof(vname), UNKNOWN_MALLOCED_OBJ_FMT, (Addr)p, VG_(getpid)(), VG_(get_running_tid)()); 499 | VG_(snprintf)(vdname, sizeof(vdname), UNKNOWN_MALLOCED_OBJ_FMT, (Addr)p, VG_(getpid)(), VG_(get_running_tid)()); 500 | // } 501 | 502 | hc = TNT_(alloc_chunk_from_varnames_and_type)((Addr)p, req_szB, slop_szB, vname, vdname, SN_ADDR_HEAP_MALLOC, False); 503 | hc->Alloc.master = 1; 504 | } 505 | 506 | // even if we're in batch mode, I still create a chunk to be able to test the validity of addresses 507 | if (hc) 508 | #else 509 | 510 | hc = VG_(malloc)("ms.main.rb.1", sizeof(HP_Chunk)); 511 | tl_assert ( hc && "hc NULL" ); 512 | hc->req_szB = req_szB; 513 | hc->slop_szB = slop_szB; 514 | hc->data = (Addr)p; 515 | 516 | #endif 517 | 518 | VG_(HT_add_node)(TNT_(malloc_list), hc); 519 | 520 | #if !_SECRETGRIND_ 521 | // Untaint malloc'd block 522 | TNT_(make_mem_untainted)( (Addr)p, hc->req_szB + hc->slop_szB ); 523 | #endif 524 | 525 | return p; 526 | } 527 | 528 | 529 | void TNT_(malloc_init)(void) { 530 | 531 | TNT_(malloc_list) = VG_(HT_construct)( "TNT_(malloc_list)" ); 532 | TNT_(freed_wchild_list) = VG_(HT_construct)( "TNT_(freed_wchild_list)" ); 533 | } 534 | 535 | void TNT_(malloc_release)(void) { 536 | 537 | // ======== malloc_list 538 | // first free all blocks allocated if they have not beed free()'ed yet 539 | // this may happen if the program under analysis leaks memory itself! 540 | VG_(HT_ResetIter)(TNT_(malloc_list)); 541 | HP_Chunk *hp = 0; 542 | while ( (hp=VG_(HT_Next)(TNT_(malloc_list))) ) { 543 | #if _SECRETGRIND_ 544 | if (hp->Alloc.release_trace == 0) { 545 | #endif // _SECRETGRIND_ 546 | VG_(cli_free)((void*)hp->data); 547 | //hp->release_trace = 1; WARNING: this is executed upon exit()'ing valgrind, we don't need to set a value; even if we did it'd return an erroneous value of fail (i've tried :)) 548 | } 549 | #if _SECRETGRIND_ 550 | } 551 | #endif // _SECRETGRIND_ 552 | 553 | // free the chunks 554 | VG_(HT_destruct)( TNT_(malloc_list), &VG_(free) ); // Note: most blocks have already been removed thru unrecord_block(), except those the user forgot to... 555 | 556 | // ========= freed_wchild_list 557 | // we do not nede to free the allocated blocks because we add only chunks that 558 | // have the block free()'ed to this list 559 | VG_(HT_destruct)( TNT_(freed_wchild_list), &VG_(free) ); // Note: most blocks have already been removed thru unrecord_block(), except those the user forgot to... 560 | } 561 | 562 | //--------------------------------------------------------------------// 563 | //--- end ---// 564 | //--------------------------------------------------------------------// 565 | -------------------------------------------------------------------------------- /tnt_malloc_wrappers.h: -------------------------------------------------------------------------------- 1 | #ifndef TNT_MALLOC_WRAPPERS_H 2 | #define TNT_MALLOC_WRAPPERS_H 3 | 4 | 5 | extern void TNT_(malloc_reset_iter)(void); 6 | extern HP_Chunk * TNT_(malloc_get_next_chunk)(void); 7 | extern Bool TNT_(malloc_is_heap)(Addr a); 8 | extern Bool TNT_(malloc_get_varname)(Addr a, char *pname, SizeT s, char *pdetailedname, SizeT ds); 9 | extern HP_Chunk * TNT_(malloc_get_parent_block)(Addr a, SizeT len); 10 | extern void TNT_(malloc_set_parent)(HP_Chunk *child, HP_Chunk *parent); 11 | extern void TNT_(malloc_init)(void); 12 | extern void TNT_(malloc_release)(void); 13 | 14 | #endif // TNT_MALLOC_WRAPPERS_H 15 | -------------------------------------------------------------------------------- /tnt_mmap.c: -------------------------------------------------------------------------------- 1 | #include "pub_tool_basics.h" 2 | #include "pub_tool_hashtable.h" 3 | #include "pub_tool_libcbase.h" 4 | #include "pub_tool_libcassert.h" 5 | #include "pub_tool_mallocfree.h" 6 | #include "pub_tool_replacemalloc.h" 7 | #include "pub_tool_tooliface.h" 8 | #include "pub_tool_xarray.h" 9 | #include "pub_tool_threadstate.h" 10 | #include "pub_tool_libcprint.h" // VG_(message) 11 | #include "pub_tool_debuginfo.h" 12 | 13 | #include "tnt_include.h" 14 | #include "tnt_mmap.h" 15 | 16 | #if _SECRETGRIND_ 17 | 18 | /* --------------- linked list ----------------- */ 19 | typedef 20 | struct { 21 | Addr addr; 22 | SizeT len; 23 | } 24 | val_t; 25 | 26 | typedef 27 | struct __list_el { 28 | val_t * val; 29 | struct __list_el * next; 30 | } 31 | item; 32 | 33 | static item *g_mmap_head=NULL, *g_mmap_tail=NULL; 34 | 35 | /* --------------------- private function ----------------------- */ 36 | static item * insert_head(item *curr, val_t * val) { 37 | 38 | if (curr) { 39 | item *head = VG_(malloc)("mmap", (sizeof(item))); 40 | if ( head ) { 41 | head->val = val; 42 | head->next = curr; 43 | } 44 | return head; 45 | } 46 | return NULL; 47 | } 48 | 49 | static item * insert_tail(item * curr, val_t * val) { 50 | 51 | if ( curr ) { 52 | item * tail = VG_(malloc)("mmap", (sizeof(item))); 53 | if ( tail ) { 54 | tail->next = NULL; 55 | tail->val = val; 56 | curr->next = tail; 57 | } 58 | return tail; 59 | } 60 | return NULL; 61 | } 62 | 63 | static item * init(val_t * val) { 64 | item * head = VG_(malloc)("mmap", (sizeof(item))); 65 | if ( head ) { 66 | head->next = NULL; 67 | head->val = val; 68 | } 69 | return head; 70 | } 71 | 72 | static void release(item *head) { 73 | while (head) { 74 | item *tmp = head->next; 75 | VG_(free)(head->val); 76 | VG_(free)(head); 77 | head = tmp; 78 | } 79 | } 80 | 81 | static item ** get_phead(void) { 82 | return &g_mmap_head; 83 | } 84 | 85 | static item ** get_ptail(void) { 86 | return &g_mmap_tail; 87 | } 88 | 89 | static val_t * new_val(Addr addr, SizeT len) { 90 | val_t * pval = VG_(malloc)("val", (sizeof(val_t))); 91 | tl_assert (pval); 92 | 93 | pval->addr = addr; 94 | pval->len = len; 95 | 96 | return pval; 97 | } 98 | 99 | 100 | /* ------------------------- public functions -------------------------- */ 101 | 102 | void TNT_(mmap_init)(void) { 103 | // nothing to do for now 104 | } 105 | 106 | void TNT_(mmap_release)(void) { 107 | release(g_mmap_head); 108 | g_mmap_head = g_mmap_tail = NULL; 109 | } 110 | 111 | Bool TNT_(mmap_is_region)(Addr a) { 112 | item *head = g_mmap_head; 113 | while (head) { 114 | if ( VG_(addr_is_in_block)( a, head->val->addr, head->val->len, 0 ) ) { return True; } 115 | head = head->next; 116 | } 117 | return False; 118 | } 119 | 120 | void TNT_(mmap_add_region)(Addr a, SizeT len) { 121 | 122 | item ** phead = get_phead(); // never NULL 123 | item ** ptail = get_ptail(); // never NULL 124 | val_t * val = new_val(a, len); // never NULL 125 | 126 | if (!(*phead)) { 127 | (*phead) = init(val); 128 | (*ptail) = (*phead); 129 | tl_assert ((*phead) && "phead is NULL"); 130 | } else { 131 | (*ptail) = insert_tail((*ptail), val); 132 | } 133 | 134 | } 135 | 136 | #endif // _SECRETGRIND_ 137 | -------------------------------------------------------------------------------- /tnt_mmap.h: -------------------------------------------------------------------------------- 1 | #ifndef TNT_MMAP_H 2 | #define TNT_MMAP_H 3 | 4 | #if _SECRETGRIND_ 5 | 6 | extern void TNT_(mmap_init)(void); 7 | extern void TNT_(mmap_release)(void); 8 | extern Bool TNT_(mmap_is_region)(Addr a); 9 | extern void TNT_(mmap_add_region)(Addr a, SizeT len); 10 | 11 | #endif // _SECRETGRIND_ 12 | 13 | #endif // TNT_mmap_H 14 | -------------------------------------------------------------------------------- /tnt_structs.h: -------------------------------------------------------------------------------- 1 | #ifndef __TNT_STRUCTS_H__ 2 | #define __TNT_STRUCTS_H__ 3 | 4 | //#include 5 | 6 | #define MAX_LEN 256 7 | #define STACK_SIZE 102400 8 | 9 | Int myStringArray_getIndex( struct myStringArray *a, HChar* string ); 10 | Int myStringArray_push( struct myStringArray *a, HChar* string ); 11 | 12 | //Stack of strings--------------------------------------- 13 | struct myStringArray{ 14 | char m[STACK_SIZE][MAX_LEN]; 15 | int size; 16 | // int get_index(char *string){ 17 | // for(int i = 0; i < size; i++ ){ 18 | // if( strstr(m[i], string) != NULL && strstr(string, m[i]) != NULL ) 19 | // return i; 20 | // } 21 | // //msg( "get_index: string %s not found\n", string ); 22 | // return -1; 23 | // }; 24 | // void push( char *item ){ 25 | // if( size >= STACK_SIZE ){ 26 | // VG_(printf)("***Error - myStringArray.push: max stack limit reached %d\n", STACK_SIZE); 27 | // return; 28 | // } 29 | // 30 | // qsnprintf( m[size], MAX_LEN-1, "%s", item ); 31 | // size++; 32 | // } 33 | // // Same as push, but only unique strings. No copies allowed 34 | // // returns: true if unique, false if already found 35 | // bool pushUnique( char *item ){ 36 | // 37 | // for(int i = 0; i < size; i++ ){ 38 | // if( strstr( m[i], item ) != NULL && 39 | // strstr( item, m[i] ) != NULL ){ 40 | // return false; 41 | // } 42 | // } 43 | // 44 | // push( item ); 45 | // return true; 46 | // } 47 | // char *pop( void ){ 48 | // size--; 49 | // return m[size]; 50 | // } 51 | // void chop( char *string ){ 52 | // char *p = string; 53 | // 54 | // while( *p != '\0' ){ 55 | // p++; 56 | // } 57 | // 58 | // if( p != string ){ 59 | // *(p-1) = '\0'; 60 | // } 61 | // } 62 | }; 63 | 64 | Int myStringArray_getIndex(struct myStringArray *a, HChar* string){ 65 | unsigned i; 66 | 67 | for( i = 0; i < a->size; i++ ){ 68 | #if _SECRETGRIND_ 69 | if( VG_(strcmp(string, a->m[i])) == 0 ) 70 | #else 71 | if( VG_(strstr)(a->m[i], string) != NULL && VG_(strstr)(string, a->m[i]) != NULL ) 72 | #endif // _SECRETGRIND_ 73 | return i; 74 | } 75 | //msg( "get_index: string %s not found\n", string ); 76 | return -1; 77 | }; 78 | 79 | Int myStringArray_push( struct myStringArray *a, HChar* string ){ 80 | Int idx; 81 | if( a->size >= STACK_SIZE ){ 82 | VG_(printf)("***Error - myStringArray.push: max stack limit reached %d\n", STACK_SIZE); 83 | //exit(-1); 84 | return -1; 85 | } 86 | // check if it already exists 87 | if ((idx = myStringArray_getIndex(a, string)) == -1) { 88 | VG_(snprintf)( a->m[a->size], MAX_LEN-1, "%s", string ); 89 | idx = a->size; 90 | a->size++; 91 | } 92 | return idx; 93 | } 94 | //End Stack of strings--------------------------------------------------- 95 | 96 | ////Stack of addresses----------------------------------------------------- 97 | //struct eaArray{ 98 | // ea_t m[STACK_SIZE]; 99 | // int size; 100 | // int get_index(ea_t addr){ 101 | // for(int i = 0; i < size; i++ ){ 102 | // if( addr == m[i] ) 103 | // return i; 104 | // } 105 | // return -1; 106 | // }; 107 | // 108 | // void push( ea_t item ){ 109 | // if( size >= STACK_SIZE ){ 110 | // msg("***Error - eaArray.push: max stack limit reached %d\n", STACK_SIZE); 111 | // return; 112 | // } 113 | // 114 | // m[size] = item; 115 | // size++; 116 | // } 117 | // 118 | // // Same as push, but only unique items. No copies allowed 119 | // // returns: true if unique, false if already found 120 | // bool pushUnique( ea_t item ){ 121 | // 122 | // for(int i = 0; i < size; i++ ){ 123 | // if( m[i] == item ){ 124 | // return false; 125 | // } 126 | // } 127 | // 128 | // push( item ); 129 | // return true; 130 | // } 131 | // 132 | // ea_t pop( void ){ 133 | // size--; 134 | // return m[size]; 135 | // } 136 | //}; 137 | 138 | //End Stack of Addresses---------------------------------- 139 | #endif 140 | -------------------------------------------------------------------------------- /tnt_subblock_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef TNT_SUBBLOCK_HELPER_H 2 | #define TNT_SUBBLOCK_HELPER_H 3 | 4 | #if _SECRETGRIND_ 5 | 6 | /* 7 | * these are function used by malloc and mmap files to display 8 | * sub block of tainted malloc'ed/mmap'ed regions to user 9 | */ 10 | 11 | typedef 12 | struct tainted_blk_lst { 13 | Addr addr; 14 | SizeT len; 15 | struct tainted_blk_lst * next; 16 | } 17 | tainted_blk; 18 | 19 | 20 | static __inline__ 21 | tainted_blk * subblk_is_tainted(HP_Chunk *hc) { 22 | tl_assert (hc); 23 | 24 | // for simplicity, i do it byte by byte. This is slow... TODO: improve this 25 | Addr curr_addr = (Addr)hc->data, end_addr = hc->data+hc->req_szB/* +hc->slop_szB*/; 26 | tainted_blk *tail = NULL, *head = NULL, *curr_blk = NULL; 27 | Bool taint = False; 28 | 29 | unsigned tot = 0; 30 | while ( curr_addr < end_addr ) { 31 | 32 | while ( curr_addr < end_addr && (taint = TNT_(is_mem_byte_tainted)(curr_addr)) == True ) { 33 | 34 | if ( UNLIKELY( !curr_blk ) ) { 35 | curr_blk = VG_(malloc)("tnt.curr_blk.rb.1", sizeof(tainted_blk)); 36 | tl_assert (curr_blk && "curr_blk NULL"); 37 | curr_blk->addr = curr_addr; 38 | curr_blk->len = 1; 39 | curr_blk->next = NULL; 40 | } else { 41 | ++curr_blk->len; 42 | } 43 | 44 | ++curr_addr; 45 | } 46 | 47 | // no taint here, record the blk if we got some tainted region 48 | if ( curr_blk ) { 49 | 50 | if ( UNLIKELY(!head) ) { head = curr_blk; } 51 | if ( LIKELY(tail) ) { tail->next = curr_blk; } 52 | tail = curr_blk; 53 | curr_blk = NULL; 54 | ++tot; 55 | } 56 | 57 | ++curr_addr; 58 | } 59 | 60 | return head; 61 | } 62 | 63 | 64 | static __inline__ 65 | Bool inner_subblk_warn_if_tainted(HP_Chunk *hc, void (*print_exe_context)( ExeContext* ec, UInt n_ips ), const char *msg, Bool addToSummary) 66 | { 67 | // check if any of the bytes in this block are tainted 68 | Bool tainted = False; 69 | tainted_blk * pblk = subblk_is_tainted(hc); 70 | if (pblk) { 71 | tainted = True; 72 | EMIT_ERROR("\nBlock [0x%lx - 0x%lx] (%s, %lu bytes) is %s\n", (Addr)hc->data, (Addr)hc->data+hc->req_szB-1, hc->vdetailedname, hc->req_szB, msg); 73 | tl_assert ( hc->stack_trace ); 74 | (*print_exe_context)( hc->stack_trace, VG_(get_ExeContext_n_ips)(hc->stack_trace) ); 75 | EMIT_INFO(" ---\n"); 76 | TNT_(print_CurrentStackTrace) ( VG_(get_running_tid)(), 20, msg ); 77 | EMIT_INFO("\n"); 78 | 79 | // WARNING: i've removed this line below now as we no longer add the parent malloc()'ed block to summary 80 | // instead I use the block containing the taint instruction and set the parent 81 | //if ( TNT_(clo_summary_verbose) && addToSummary) { TNT_(sum_add_block)(hc/*, hc->addrType*/); } 82 | 83 | while (pblk) { 84 | // read it 85 | EMIT_INFO(" > Tainted region [0x%lx - 0x%lx] (%lu bytes) -- indexes:[%lu - %lu]\n", pblk->addr, pblk->addr+pblk->len-1, 86 | pblk->len, pblk->addr-hc->data, pblk->addr+pblk->len-hc->data-1); 87 | tainted_blk *tmp = pblk->next; 88 | VG_(free)(pblk); // delete the blk after processing 89 | pblk = tmp; // next blk 90 | } 91 | EMIT_ERROR("\n"); 92 | } 93 | return tainted; 94 | } 95 | 96 | static __inline__ 97 | Bool subblk_warn_if_tainted(HP_Chunk *hc, void (*print_exe_context)( ExeContext* ec, UInt n_ips ), const char *msg, Bool addToSummary) 98 | { 99 | // WARNING: addToSummary no longer relevant; it's ignored now 100 | if ( UNLIKELY( TNT_(clo_taint_warn_on_release) ) ) { 101 | return inner_subblk_warn_if_tainted(hc, print_exe_context, msg, addToSummary); 102 | } else { 103 | // just check byte by byte (slow):TODO: improve it 104 | Addr curr_addr = (Addr)hc->data, end_addr = hc->data+hc->req_szB/* +hc->slop_szB*/; 105 | while ( curr_addr < end_addr ) { 106 | if ( TNT_(is_mem_byte_tainted)(curr_addr) ) { return True; } 107 | ++curr_addr; 108 | } 109 | return False; 110 | } 111 | } 112 | 113 | #endif // _SECRETGRIND_ 114 | 115 | #endif // TNT_SUBBLOCK_HELPER_H 116 | -------------------------------------------------------------------------------- /tnt_summary_names.c: -------------------------------------------------------------------------------- 1 | #include "pub_tool_basics.h" 2 | #include "pub_tool_hashtable.h" 3 | #include "pub_tool_libcbase.h" 4 | #include "pub_tool_libcassert.h" 5 | #include "pub_tool_mallocfree.h" 6 | #include "pub_tool_replacemalloc.h" 7 | #include "pub_tool_tooliface.h" 8 | #include "pub_tool_xarray.h" 9 | #include "pub_tool_threadstate.h" 10 | #include "pub_tool_libcprint.h" // VG_(message) 11 | #include "pub_tool_debuginfo.h" 12 | 13 | #include "tnt_include.h" 14 | #include "tnt_summary_names.h" 15 | 16 | #if _SECRETGRIND_ 17 | 18 | /* --------------- linked list ----------------- */ 19 | typedef HP_Chunk * val_t; 20 | 21 | typedef 22 | struct __list_el { 23 | val_t val; 24 | struct __list_el * next; 25 | } 26 | item; 27 | 28 | // 3 different lists, one for each type of mem region 29 | static item *g_heap_malloc_head=NULL, *g_heap_malloc_tail=NULL, *g_heap_curr_it=NULL; 30 | static item *g_other_head=NULL, *g_other_tail=NULL, *g_other_curr_it=NULL; 31 | static item *g_stack_head=NULL, *g_stack_tail=NULL, *g_stack_curr_it=NULL; 32 | static item *g_global_head=NULL, *g_global_tail=NULL, *g_global_curr_it=NULL; 33 | static item *g_mmap_file_head=NULL, *g_mmap_file_tail=NULL, *g_mmap_file_curr_it=NULL; 34 | static item *g_mmap_head=NULL, *g_mmap_tail=NULL, *g_mmap_curr_it=NULL; 35 | 36 | static item * insert_head(item *curr, val_t val) { 37 | 38 | if (curr) { 39 | item *head = VG_(malloc)("head", (sizeof(item))); 40 | if ( head ) { 41 | head->val = val; 42 | head->next = curr; 43 | } 44 | return head; 45 | } 46 | return NULL; 47 | } 48 | /* 49 | static item * insert_tail(item * curr, val_t val) { 50 | 51 | if ( curr ) { 52 | item * tail = VG_(malloc)(VG_(clo_alignment), (sizeof(item))); 53 | if ( tail ) { 54 | tail->next = NULL; 55 | tail->val = val; 56 | curr->next = tail; 57 | } 58 | return tail; 59 | } 60 | return NULL; 61 | } 62 | */ 63 | static item * init(val_t val) { 64 | item * head = VG_(malloc)("head", (sizeof(item))); 65 | if ( head ) { 66 | head->next = NULL; 67 | head->val = val; 68 | } 69 | return head; 70 | } 71 | 72 | static void free_item( item * it ) { 73 | 74 | if ( it ) { 75 | 76 | // release the chunk 77 | if ( it->val ) { 78 | VG_(free)(it->val); 79 | } 80 | 81 | // release the item 82 | VG_(free)(it); // note: there does not seem to be a function to free the ExeContext of the HP_Chunk... 83 | } 84 | } 85 | 86 | static void release(item *head) { 87 | while (head) { 88 | item *tmp = head->next; 89 | 90 | // Note: no need to free the address block from malloc because blocks added to the summary 91 | // NEVER have their blocks allocated directly, ie they only contain 92 | // the address value. It is malloc module that is in charge of free()'ing the actual mem blocks 93 | // release the chunk 94 | //if ( head->val ) { 95 | // VG_(free)(head->val); 96 | //} 97 | // release the item 98 | //VG_(free)(head); // note: there does not seem to be a function to free the ExeContext of the HP_Chunk... 99 | free_item( head ); 100 | head = tmp; 101 | } 102 | } 103 | 104 | /* --------------- names to keep for the summary ----------------- */ 105 | 106 | static item ** sum_get_phead(sn_addr_type_t type) { 107 | if ( type == SN_ADDR_HEAP_MALLOC ) { return &g_heap_malloc_head; } 108 | if ( type == SN_ADDR_MMAP_FILE ) { return &g_mmap_file_head; } 109 | if ( type == SN_ADDR_MMAP ) { return &g_mmap_head; } 110 | if ( type == SN_ADDR_OTHER ) { return &g_other_head; } 111 | if ( type == SN_ADDR_STACK ) { return &g_stack_head; } 112 | if ( type == SN_ADDR_GLOBAL ) { return &g_global_head; } 113 | tl_assert ( 0 && "invalid type" ); 114 | } 115 | 116 | static item ** sum_get_ptail(sn_addr_type_t type) { 117 | if ( type == SN_ADDR_HEAP_MALLOC ) { return &g_heap_malloc_tail; } 118 | if ( type == SN_ADDR_MMAP_FILE ) { return &g_mmap_file_tail; } 119 | if ( type == SN_ADDR_MMAP ) { return &g_mmap_tail; } 120 | if ( type == SN_ADDR_OTHER ) { return &g_other_tail; } 121 | if ( type == SN_ADDR_STACK ) { return &g_stack_tail; } 122 | if ( type == SN_ADDR_GLOBAL ) { return &g_global_tail; } 123 | tl_assert ( 0 && "invalid type" ); 124 | } 125 | 126 | static item ** sum_get_piter(sn_addr_type_t type) { 127 | if ( type == SN_ADDR_HEAP_MALLOC ) { return &g_heap_curr_it; } 128 | if ( type == SN_ADDR_MMAP_FILE ) { return &g_mmap_file_curr_it; } 129 | if ( type == SN_ADDR_MMAP ) { return &g_mmap_curr_it; } 130 | if ( type == SN_ADDR_OTHER ) { return &g_other_curr_it; } 131 | if ( type == SN_ADDR_STACK ) { return &g_stack_curr_it; } 132 | if ( type == SN_ADDR_GLOBAL ) { return &g_global_curr_it; } 133 | tl_assert ( 0 && "invalid type" ); 134 | } 135 | 136 | void TNT_(sum_names_reset_iter)(sn_addr_type_t type) { 137 | 138 | item ** pit = sum_get_piter(type); // never NULL 139 | item ** phead = sum_get_phead(type); // never NULL 140 | (*pit) = (*phead); 141 | } 142 | 143 | 144 | HP_Chunk * TNT_(sum_names_get_next_chunk)(sn_addr_type_t type) { 145 | 146 | item ** pit = sum_get_piter(type); // never NULL 147 | if ((*pit)) { 148 | HP_Chunk * hc = (*pit)->val; 149 | (*pit) = (*pit)->next; 150 | return hc; 151 | } 152 | return NULL; 153 | } 154 | 155 | void TNT_(sum_delete_block)(HP_Chunk *hc) { 156 | 157 | tl_assert (hc && "hc is NULL"); 158 | 159 | LOG_ENTER(); 160 | 161 | item ** phead = sum_get_phead(hc->addrType); // never NULL 162 | item * prev = NULL; 163 | 164 | // restart the iterator 165 | TNT_(sum_names_reset_iter)(hc->addrType); 166 | 167 | // get the iterator 168 | item ** pit = sum_get_piter(hc->addrType); // never NULL 169 | 170 | while ((*pit)) { 171 | 172 | HP_Chunk * curr = (*pit)->val; 173 | LOG("hc: 0x%lx, curr:0x%lx, curr->addr:0x%lx, length:%u\n", hc, curr, curr->data, curr->req_szB); 174 | 175 | if ( curr == hc ) { 176 | 177 | // we found the block to release - in fact we should also release all blocks that have it as parent:TODO 178 | if ( prev ) { 179 | prev->next = (*pit)->next; 180 | } else { 181 | // no previous block. In this case, we're the head 182 | tl_assert ((*phead) == (*pit) && "unexpected head"); 183 | (*phead) = (*pit)->next; // this may be null 184 | } 185 | 186 | // now erase the item and block 187 | free_item( (*pit) ); 188 | hc = NULL; 189 | 190 | break; 191 | } 192 | 193 | // record the prev 194 | prev = (*pit); 195 | 196 | // move forward to next item 197 | (*pit) = (*pit)->next; 198 | 199 | } 200 | 201 | tl_assert ( hc == NULL && "Could not find the block to delete" ); 202 | LOG_EXIT(); 203 | } 204 | 205 | void TNT_(sum_add_block)(HP_Chunk *hc) { 206 | tl_assert (hc && "hc is NULL"); 207 | 208 | LOG_ENTER(); 209 | 210 | //tl_assert ("type != hc->addrType" && type == hc->addrType); 211 | 212 | item ** phead = sum_get_phead(hc->addrType); // never NULL 213 | item ** ptail = sum_get_ptail(hc->addrType); // never NULL 214 | 215 | if (!(*phead)) { 216 | (*phead) = init(hc); 217 | (*ptail) = (*phead); 218 | tl_assert ((*phead) && "g_head is NULL"); 219 | } else { 220 | (*phead) = insert_head((*phead), hc); 221 | } 222 | LOG_EXIT(); 223 | } 224 | 225 | void TNT_(sum_names_init)(void) { 226 | // nothing to do for now 227 | } 228 | 229 | void TNT_(sum_names_release)(void) { 230 | release(g_heap_malloc_head); 231 | g_heap_malloc_head = g_heap_malloc_tail = NULL; 232 | 233 | release(g_mmap_file_head); 234 | g_mmap_file_head = g_mmap_file_tail = NULL; 235 | 236 | release(g_mmap_head); 237 | g_mmap_head = g_mmap_tail = NULL; 238 | 239 | release(g_other_head); 240 | g_other_head = g_other_tail = NULL; 241 | 242 | release(g_stack_head); 243 | g_stack_head = g_stack_tail = NULL; 244 | 245 | release(g_global_head); 246 | g_global_head = g_global_tail = NULL; 247 | } 248 | 249 | #endif // _SECRETGRIND_ 250 | -------------------------------------------------------------------------------- /tnt_summary_names.h: -------------------------------------------------------------------------------- 1 | #ifndef TNT_SUM_NAMES_H 2 | #define TNT_SUM_NAMES_H 3 | 4 | #if _SECRETGRIND_ 5 | 6 | extern void TNT_(sum_names_reset_iter)(sn_addr_type_t type); 7 | extern HP_Chunk * TNT_(sum_names_get_next_chunk)(sn_addr_type_t type); 8 | extern void TNT_(sum_names_init)(void); 9 | extern void TNT_(sum_names_release)(void); 10 | extern void TNT_(sum_add_block)(HP_Chunk *hc); 11 | extern void TNT_(sum_delete_block)(HP_Chunk *hc); 12 | 13 | #endif 14 | 15 | #endif // TNT_SUM_NAMES_H 16 | -------------------------------------------------------------------------------- /tnt_syswrap.h: -------------------------------------------------------------------------------- 1 | #ifndef TNT_SYSWRAP_H 2 | #define TNT_SYSWRAP_H 3 | 4 | extern void TNT_(syscall_mmap)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 5 | extern void TNT_(syscall_munmap)(ThreadId tid, UWord* args, UInt nArgs, SysRes res); 6 | extern void TNT_(syswrap_init)(void); 7 | extern void TNT_(syswrap_release)(void); 8 | extern Bool TNT_(syswrap_is_mmap_file_range)(Addr a); 9 | extern void TNT_(syswrap_mmap_set_parent)(HP_Chunk *child, HP_Chunk *parent); 10 | HP_Chunk * TNT_(syswrap_mmap_get_parent_block)(Addr a, SizeT len); 11 | 12 | #endif // TNT_SYSWRAP_H 13 | -------------------------------------------------------------------------------- /tnt_wraps.c: -------------------------------------------------------------------------------- 1 | /* 2 | * For replacement/wrappers to work, they must be loaded 3 | * in the address space of the prog under analysis [0]. This 4 | * means, for instance, that we must LD_PRELOAD it. Valgrind 5 | * offers this out of the box, thru the Makefile.am; the resulting 6 | * .XX is automatically pre loaded when launching taintgrind. 7 | * For details on MACRO, see [1,2]. 8 | * size_t is the equivalent of SizeT [0]. 9 | * 10 | * [0] http://valgrind.org/docs/manual/manual-core-adv.html 11 | * [1] pub_tool_redir.h 12 | * [2] pub_too_basic.h 13 | * 14 | * from pub_tool_redir.h 15 | * Z-encoding 16 | ~~~~~~~~~~ 17 | Z-encoding details: the scheme is like GHC's. It is just about 18 | readable enough to make a preprocessor unnecessary. First the 19 | "_vgrZU_" or "_vgrZZ_" prefix is added, and then the following 20 | characters are transformed. 21 | 22 | * --> Za (asterisk) 23 | : --> Zc (colon) 24 | . --> Zd (dot) 25 | - --> Zh (hyphen) 26 | + --> Zp (plus) 27 | (space) --> Zs (space) 28 | _ --> Zu (underscore) 29 | @ --> ZA (at) 30 | $ --> ZD (dollar) 31 | ( --> ZL (left) 32 | ) --> ZR (right) 33 | Z --> ZZ (Z) 34 | 35 | Everything else is left unchanged. 36 | * 37 | * WARNING: wrappers and replacements require the symbol 38 | * to be visible. Typically, in shared libraries, this would work. 39 | * If functions are inlined, eg libc's strlen, strcmp, etc, 40 | * then this won't work. 41 | */ 42 | 43 | #include "pub_tool_basics.h" 44 | #include "pub_tool_redir.h" 45 | #include "secretgrind.h" 46 | 47 | #include "valgrind.h" 48 | 49 | #include // printf when testing 50 | #include 51 | /* 52 | * for wrappers 53 | * - CALL_FN_W_W 54 | * - CALL_FN_v_WWWW 55 | * - ... 56 | * see ../include/valgrind.h 57 | * */ 58 | 59 | #define W_FUNC(L,ret_ty, f, args...) \ 60 | ret_ty I_WRAP_SONAME_FNNAME_ZU(L,f)(args); \ 61 | ret_ty I_WRAP_SONAME_FNNAME_ZU(L,f)(args) 62 | 63 | #define W_LIBC_FUNC(ret_ty, f, args...) W_FUNC(VG_Z_LIBC_SONAME,ret_ty,f,args) 64 | #define W_NONE_FUNC(ret_ty, f, args...) W_FUNC(NONE,ret_ty,f,args) 65 | 66 | // ========================================= 67 | // polarssl 68 | // ========================================= 69 | #define W_POLARSSL_FUNC(ret_ty, f, args...) W_FUNC(libmbedtlsZdsoZa/*libmbedtls.so.**/,ret_ty,f,args) 70 | 71 | // size_t mpi_msb( const mpi *X ) 72 | /*W_POLARSSL_FUNC(size_t, mpi_msb, const void * s) { 73 | size_t r; 74 | OrigFn fn; 75 | VALGRIND_GET_ORIG_FN(fn); 76 | TNT_PRINT_TAINTED_INST(); 77 | CALL_FN_W_W(r, fn, s); 78 | TNT_STOP_PRINT(); 79 | return r; 80 | }*/ 81 | 82 | /*W_POLARSSL_FUNC(void, mpi_mul_hlp, size_t i, void *s, void *d, uint64_t b ) { 83 | OrigFn fn; 84 | VALGRIND_GET_ORIG_FN(fn); 85 | TNT_PRINT_TAINTED_INST(); 86 | CALL_FN_v_WWWW(fn, i, s, d, b); 87 | TNT_STOP_PRINT(); 88 | }*/ 89 | 90 | /*W_NONE_FUNC(size_t, mpi_msb, const void * s) { 91 | size_t r; 92 | OrigFn fn; 93 | VALGRIND_GET_ORIG_FN(fn); 94 | TNT_PRINT_ALL_INST(); 95 | CALL_FN_W_W(r, fn, s); 96 | TNT_STOP_PRINT(); 97 | return r; 98 | }*/ 99 | 100 | // Note: when strlen uses SIMD instructions, the result is tainted 101 | // Turns out this the wrapper is not reliable because the calls 102 | // compilers drop a code "inline". 103 | // I found that using a wrapper is actually WORSE, because to pass the param 104 | // to the wrapper, a lot of tainted stuff is copied and it's hard to untaint it 105 | // as it is handled by valgrind itself... 106 | /*W_LIBC_FUNC(size_t, strlen, char* s) { 107 | size_t r; 108 | OrigFn fn; 109 | VALGRIND_GET_ORIG_FN(fn); 110 | CALL_FN_W_W(r, fn, s); 111 | TNT_MAKE_MEM_UNTAINTED(&r, sizeof(r)); 112 | return r; 113 | }*/ 114 | 115 | /*W_LIBC_FUNC(int, strcmp, char* str1, char* str2) { 116 | printf("compare's wrapper: args %s %s\n", (char*)str1, (char*)str2); 117 | return 0; 118 | } 119 | 120 | W_LIBC_FUNC(int, open, const char *path, int oflags) { 121 | 122 | int fd = -1; 123 | OrigFn fn; 124 | VALGRIND_GET_ORIG_FN(fn); 125 | printf("open's wrapper: args %s %d\n", path, oflags); 126 | CALL_FN_W_WW(fd, fn, path, oflags); 127 | printf("open's wrapper: result %d\n", fd); 128 | return fd; 129 | } 130 | 131 | W_NONE_FUNC(int, fact, int n) { 132 | 133 | int r; 134 | OrigFn fn; 135 | VALGRIND_GET_ORIG_FN(fn); 136 | printf("in wrapper1-pre: fact(%d)\n", n); 137 | CALL_FN_W_W(r, fn, n); 138 | printf("in wrapper1-post: fact(%d) = %d\n", n, r); 139 | return r; 140 | }*/ 141 | -------------------------------------------------------------------------------- /valgrind.patch: -------------------------------------------------------------------------------- 1 | --- m_execontext.c 2016-02-17 14:31:28.757895822 +0000 2 | +++ m_execontext.c.patch 2016-02-17 14:32:44.638673661 +0000 3 | @@ -201,6 +201,14 @@ 4 | VG_(pp_StackTrace)( ec->ips, ec->n_ips ); 5 | } 6 | 7 | +// Taintgrind support auto-generated through sh configure_valgrind.sh. Do not change!! 8 | +void VG_(apply_ExeContext)( void(*action)(UInt n, Addr ip), 9 | + ExeContext* ec, UInt n_ips ) 10 | +{ 11 | + VG_(apply_StackTrace)(action, NULL, ec->ips, 12 | + n_ips < ec->n_ips ? n_ips : ec->n_ips); 13 | +} 14 | + 15 | 16 | /* Compare two ExeContexts. Number of callers considered depends on res. */ 17 | Bool VG_(eq_ExeContext) ( VgRes res, ExeContext* e1, ExeContext* e2 ) 18 | --------------------------------------------------------------------------------