4141
4242#define SHIVA_DT_NEEDED DT_LOOS + 10
4343#define SHIVA_DT_SEARCH DT_LOOS + 11
44+ #define SHIVA_DT_ORIG_INTERP DT_LOOS + 12
4445
4546#define SHIVA_SIGNATURE 0x31f64
4647
@@ -69,6 +70,7 @@ struct shiva_prelink_ctx {
6970 char * output_exec ;
7071 char * search_path ;
7172 char * interp_path ;
73+ char * orig_interp_path ;
7274 struct {
7375 elfobj_t elfobj ;
7476 } bin ;
@@ -123,6 +125,8 @@ elf_segment_copy(elfobj_t *elfobj, uint8_t *dst, struct elf_segment segment)
123125 return true;
124126}
125127
128+ #define NEW_DYN_COUNT 3
129+
126130bool
127131shiva_prelink (struct shiva_prelink_ctx * ctx )
128132{
@@ -142,6 +146,19 @@ shiva_prelink(struct shiva_prelink_ctx *ctx)
142146 uint8_t * old_dynamic_segment ;
143147 size_t old_dynamic_size , dynamic_index ;
144148
149+ ctx -> orig_interp_path = elf_interpreter_path (& ctx -> bin .elfobj );
150+ if (ctx -> orig_interp_path == NULL ) {
151+ fprintf (stderr , "elf_interpreter_path() failed\n" );
152+ return false;
153+ }
154+ /*
155+ * We must do this or it will get overwritten later by an strcpy
156+ */
157+ ctx -> orig_interp_path = strdup (ctx -> orig_interp_path );
158+ if (ctx -> orig_interp_path == NULL ) {
159+ perror ("strdup" );
160+ return false;
161+ }
145162 if (elf_flags (& ctx -> bin .elfobj , ELF_DYNAMIC_F ) == false) {
146163 fprintf (stderr , "Currently we do not support static ELF executable\n" );
147164 return false;
@@ -162,7 +179,7 @@ shiva_prelink(struct shiva_prelink_ctx *ctx)
162179 } else if (segment .type == PT_DYNAMIC ) {
163180 found_dynamic = true;
164181 ctx -> new_segment .dyn_size = elf_dtag_count (& ctx -> bin .elfobj ) * sizeof (ElfW (Dyn ));
165- ctx -> new_segment .dyn_size += (sizeof (ElfW (Dyn )) * 2 );
182+ ctx -> new_segment .dyn_size += (sizeof (ElfW (Dyn )) * NEW_DYN_COUNT );
166183 ctx -> new_segment .dyn_offset = 0 ;
167184
168185 old_dynamic_size = elf_dtag_count (& ctx -> bin .elfobj ) * sizeof (ElfW (Dyn ));
@@ -183,9 +200,10 @@ shiva_prelink(struct shiva_prelink_ctx *ctx)
183200 /*
184201 * Make room for the two new additional dynamic entries
185202 */
186- ctx -> new_segment .filesz += sizeof (ElfW (Dyn )) * 2 ;
203+ ctx -> new_segment .filesz += sizeof (ElfW (Dyn )) * NEW_DYN_COUNT ;
187204 ctx -> new_segment .filesz += strlen (ctx -> input_patch ) + 1 ;
188205 ctx -> new_segment .filesz += strlen (ctx -> search_path ) + 1 ;
206+ ctx -> new_segment .filesz += strlen (ctx -> orig_interp_path ) + 1 ;
189207 /*
190208 * Mark the index of this segment so that we can modify it
191209 * to match the new dynamic segment location once we know it.
@@ -319,7 +337,9 @@ shiva_prelink(struct shiva_prelink_ctx *ctx)
319337 return false;
320338 }
321339
322- ElfW (Dyn ) dyn [3 ];
340+ #define NEW_DYN_ENTRY_SZ 4
341+
342+ ElfW (Dyn ) dyn [NEW_DYN_ENTRY_SZ ];
323343
324344 /*
325345 * Write out new dynamic entry for SHIVA_DT_SEARCH and
@@ -328,9 +348,13 @@ shiva_prelink(struct shiva_prelink_ctx *ctx)
328348 dyn [0 ].d_tag = SHIVA_DT_SEARCH ;
329349 dyn [0 ].d_un .d_ptr = ctx -> new_segment .vaddr + ctx -> new_segment .dyn_size ;
330350 dyn [1 ].d_tag = SHIVA_DT_NEEDED ;
331- dyn [1 ].d_un .d_ptr = ctx -> new_segment .vaddr + ctx -> new_segment .dyn_size + strlen (ctx -> search_path ) + 1 ;
332- dyn [2 ].d_tag = DT_NULL ;
333- dyn [2 ].d_un .d_ptr = 0x0 ;
351+ dyn [1 ].d_un .d_ptr = ctx -> new_segment .vaddr +
352+ ctx -> new_segment .dyn_size + strlen (ctx -> search_path ) + 1 ;
353+ dyn [2 ].d_tag = SHIVA_DT_ORIG_INTERP ;
354+ dyn [2 ].d_un .d_ptr = ctx -> new_segment .vaddr + ctx -> new_segment .dyn_size +
355+ strlen (ctx -> search_path ) + 1 + strlen (ctx -> input_patch ) + 1 ;
356+ dyn [3 ].d_tag = DT_NULL ;
357+ dyn [3 ].d_un .d_ptr = 0x0 ;
334358
335359 if (write (fd , & dyn [0 ], sizeof (dyn )) < 0 ) {
336360 perror ("write 4." );
@@ -345,6 +369,13 @@ shiva_prelink(struct shiva_prelink_ctx *ctx)
345369 return false;
346370 }
347371
372+ printf ("Writing out original interp path: %s\n" , ctx -> orig_interp_path );
373+
374+ if (write (fd , ctx -> orig_interp_path ,
375+ strlen (ctx -> orig_interp_path ) + 1 ) < 0 ) {
376+ perror ("write 7." );
377+ return false;
378+ }
348379 if (fchown (fd , st .st_uid , st .st_gid ) < 0 ) {
349380 perror ("fchown" );
350381 return false;
0 commit comments