Write FSBASE register

66 views
Skip to first unread message

Mohammad Ewais

unread,
May 10, 2022, 6:33:49 AM5/10/22
to DynamoRIO Users
Hi,

As the title suggests, I am trying to write the FSBASE register of the app, directly after a  new app thread gets created. 
As far as I know, there are only two ways to do so, the first being the arch_prctl system call, and the second being the wrfsbase instruction. 

So, here's what I do. I use drmgr_register_thread_init_event to create a TLS area for each thread. In the same function provided to it I try three different things separately (merged below for space):

dr_switch_to_app_state(dr_get_current_drcontext());
// I try reading here, this reads fine the original value of FSBASE and I am able to verify the variables fsbase_value and fs_value
asm inline("rdfsbase %0 \t\n"
       "movq %%fs, %1 \t\n"
       : "=&r"(fsbase_value), "=&r"(fs_value));
// This is trying the wrfsbase instruction, no effect
asm inline("wrfsbase %0 \t\n"
       :
       : "g" (SYSCALLREPLACEMENTS::virtual_tls));
// This is trying the syscall instead of the wrfsbase instruction, still no effect
asm inline("movq $0x9E, %%rax \t\n"
       "movq $0x1002, %%rdi \t\n"
       "movq %0, %%rsi \t\n"
       "syscall \t\n"
       :
       : "g" (SYSCALLREPLACEMENTS::virtual_tls)
       : "rax", "rdi", "rsi");

dr_switch_to_dr_state(dr_get_current_drcontext());


Googling a bit, it seems that wrfsbase and its family require enabling in the CR4 register. I don't know how check if it is enabled, but I will just assume it is not (even though its rdfsbase counterpart works fine).
But what about the syscall? Why does it not work? it does not produce any errors either, just no effect. What is the right way of creating a syscall in this condition? Or achieving what I want in general?

As a side question, I know DR uses the GS/GSBASE for its own TLS, but does it have any uses with FS/FSBASE that would cause interference with what I am doing?

Derek Bruening

unread,
May 10, 2022, 7:04:44 PM5/10/22
to Mohammad Ewais, DynamoRIO Users
Yes, FS is used for private library copies.  DR rewrites all uses of FS by the application, turning them into linear addresses.  It watches for application changes to the segment base and handles them specially.

For a client to change the application segment base outside of inserting application code to be executed in the code cache would require either:

1) Change dr_switch_to_app_state followed by _to_dr_state to support *changes* to the app state in between (today that is not the case).  This may need to be under a flag if it adds non-trivial overhead (Windows might).

2) Add a new explicit API routine.

I would suggest filing a feature proposal and then submitting a PR to implement.
 

--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dynamorio-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dynamorio-users/252139ca-80dc-40ba-a9ca-10310f4c1347n%40googlegroups.com.

Mohammad Ewais

unread,
May 23, 2022, 10:42:37 PM5/23/22
to DynamoRIO Users
I see.

But I still encounter an issue even when I try inserting an arch_prctl in the BB instrumentation instead of switching the contexts and making changes. I basically tried inserting the same sequence of instructions as the above:
mov RAX, 0x9E    // The syscall number for arch_prctl
mov RDI, 0x1002  // The command for ARCH_SET_FS
mov RSI, ADDRESS // my desired address

I can see that this code inserts fine, I can also instrument the syscall getting called and inspect the arguments to make sure they are correct. But somehow, the FSBASE is still never changed! Any reasons why?

Derek Bruening

unread,
May 24, 2022, 7:35:12 PM5/24/22
to Mohammad Ewais, DynamoRIO Users
Was the code inserted as app code?  Does the right thing happen with an app that actually has that same code?  The regression test I see by searching the code is suite/tests/client-interface/mbr_instrumentation_segment.c -- how does it compare?

Mohammad Ewais

unread,
May 25, 2022, 6:26:26 PM5/25/22
to DynamoRIO Users
The movs priot to the syscall are inserted as meta instructions, the syscall itself is inserted as a normal instruction. The rest of the BB is removed (carried over to the next BB instrumentation call). Like follows (ignoring translations for space):
instr_t* inst = INSTR_CREATE_mov_imm(drctx, opnd_create_reg(DR_REG_RAX), opnd_create_immed_uint(0x9E, OPSZ_8));
instrlist_meta_preinsert(bb, first, inst);
inst = INSTR_CREATE_mov_imm(drctx, opnd_create_reg(DR_REG_RDI), opnd_create_immed_uint(ARCH_SET_FS, OPSZ_8));
instrlist_meta_preinsert(bb, first, inst);
inst = INSTR_CREATE_mov_ld(drctx, opnd_create_reg(DR_REG_RSI), opnd_create_abs_addr(&MyTLSVariable, OPSZ_8));
instrlist_meta_preinsert(bb, first, inst);
inst = INSTR_CREATE_syscall(drctx);
instrlist_preinsert(bb, first, inst);


I have another app that uses the same syscall directly, works just fine. In that app I also just asm inline the same set of instructions, the movs followed by the syscall, as follows:
asm inline("movq $0x9E, %%rax \t\n"
                    "movq $0x1002, %%rdi \t\n"
                    "movq %0, %%rsi \t\n"
                    "syscall \t\n"
                    :
                    : "g" ((uint64_t)tls)
                    : "rax", "rdi", "rsi");

In both cases I can intercept the syscall and inspect it, they both have the same correct parameters, only difference is the first case does not actually change the FSBASE while the second does. It is worth noting that the rest of my instrumentation uses drutil_insert_get_mem_addr to get the addresses and play with them. Could it be that the inserted code somehow does not get tracked by DR correctly causing drutil_insert_get_mem_addr to get the old address? How does drutil_insert_get_mem_addr handle FS and GS?

I have been able to come up with a workaround that does not use arch_prctl for the moment (basically manipulating the output of drutil_insert_get_mem_addr to correct it and feed it to the app), but it would be cleaner to understand why this happens, and if fixable, I would like to use it instead as a solution.

Derek Bruening

unread,
May 25, 2022, 8:30:25 PM5/25/22
to Mohammad Ewais, DynamoRIO Users
On Wed, May 25, 2022 at 6:26 PM Mohammad Ewais <mohammad...@gmail.com> wrote:
The movs priot to the syscall are inserted as meta instructions, the syscall itself is inserted as a normal instruction. The rest of the BB is removed (carried over to the next BB instrumentation call). Like follows (ignoring translations for space):
instr_t* inst = INSTR_CREATE_mov_imm(drctx, opnd_create_reg(DR_REG_RAX), opnd_create_immed_uint(0x9E, OPSZ_8));
instrlist_meta_preinsert(bb, first, inst);
inst = INSTR_CREATE_mov_imm(drctx, opnd_create_reg(DR_REG_RDI), opnd_create_immed_uint(ARCH_SET_FS, OPSZ_8));
instrlist_meta_preinsert(bb, first, inst);
inst = INSTR_CREATE_mov_ld(drctx, opnd_create_reg(DR_REG_RSI), opnd_create_abs_addr(&MyTLSVariable, OPSZ_8));
instrlist_meta_preinsert(bb, first, inst);
inst = INSTR_CREATE_syscall(drctx);
instrlist_preinsert(bb, first, inst);


I have another app that uses the same syscall directly, works just fine. In that app I also just asm inline the same set of instructions, the movs followed by the syscall, as follows:
asm inline("movq $0x9E, %%rax \t\n"
                    "movq $0x1002, %%rdi \t\n"
                    "movq %0, %%rsi \t\n"
                    "syscall \t\n"
                    :
                    : "g" ((uint64_t)tls)
                    : "rax", "rdi", "rsi");

In both cases I can intercept the syscall and inspect it, they both have the same correct parameters, only difference is the first case does not actually change the FSBASE while the second does. It is worth noting that the rest of my instrumentation uses drutil_insert_get_mem_addr to get the addresses and play with them. Could it be that the inserted code somehow does not get tracked by DR correctly causing drutil_insert_get_mem_addr to get the old address? How does drutil_insert_get_mem_addr handle FS and GS?

Reply all
Reply to author
Forward
0 new messages