17

Immediately before this instruction is executed fs contains 0x0.

Also I'd like to know how I can read from this memory area in GDB, what would the command for that be?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
ioctlvoid
  • 311
  • 1
  • 3
  • 7
  • 5
    http://stackoverflow.com/questions/10325713/why-does-this-memory-address-have-a-random-value – Abhineet Jan 19 '13 at 13:18
  • See http://stackoverflow.com/questions/10325713/why-does-this-memory-address-have-a-random-value for the first part – Anton Kovalenko Jan 19 '13 at 13:18
  • Thanks, from similar instructions I've seen it looks like it simply reads from [fs+0x28] into rax. Since fs is 0x0 this should translate to simply 0x28, however when I try to read from 0x28 in GDB I'm not allowed to do this, yet the program itself can execute this instruction. Hence it is probably not the correct understanding of what this instruction does? – ioctlvoid Jan 19 '13 at 13:27
  • 2
    As we speak of protected mode, "since fs is 0x0 it should fail" would be more correct, BUT: in 64-bit mode, no segmentation is used: there is a hidden "fs base" register instead, and the value of fs is irrelevant. – Anton Kovalenko Jan 19 '13 at 13:33
  • 3
    In Windows, FS is used to point at the beginning of thread information block. Reading from offsets at FS is a dirt cheap way of getting current thread ID, current time, last error, etc. Are you sure it's Linux code, not Windows? See http://en.wikipedia.org/wiki/Win32_Thread_Information_Block Also, FS value zero is perfectly legal in protected mode. As long as there's a segment descriptor at xDT[0]. – Seva Alekseyev Jan 19 '13 at 14:14
  • Yes I'm sure this is Linux code, generated by GCC. So the actual offset is read from a hidden "fs base" register? What register? How can I read this myself with assembly code? – ioctlvoid Jan 19 '13 at 21:07
  • How exactly did you obtain that instruction, or what is the program that will interpret it? – Ciro Santilli OurBigBook.com Jun 04 '15 at 13:32

1 Answers1

13

The fs and gs registers in modern OSes like Linux and Windows point to thread-specific and other OS-defined structures. Modifying the segment register is a protected instruction, so only the OS can set these up for you.

This question should help explain what exactly the point to: amd64 fs/gs registers in linux.

The actual value of the fs register isn't an address. It is a selector - an offset into the GDT, that describes what that segment can/cannot be used for. You cannot see what the values of the hidden fs base and limit registers are - they are internal CPU registers that are only updated by writing a new "selector" to fs (at which point the base/limit registers are updated from the GDT).

Community
  • 1
  • 1
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • Thanks, however how can I read this memory myself from within GDB? – ioctlvoid Jan 21 '13 at 14:34
  • 1
    On CPUs with the FSGSBASE feature, 64-bit code can use [`rdfsbase`](https://hjlebbink.github.io/x86doc/html/RDFSBASE_RDGSBASE.html) and `wrfsbase`. They're unprivileged. (I'm not sure how old that extension is.) – Peter Cordes Dec 06 '17 at 08:25
  • Also, modifying a segment register itself isn't privileged; you need the kernel's help because without FSGSBASE the kernel needs to update the base address for that segment description in the LDT, which is of course not accessible by user-space. If there was a second segment description that had the base address you wanted, I *think* you could use `mov fs, eax` in user-space and switch back and forth between multiple FS bases that with, without invoking the kernel. – Peter Cordes Dec 06 '17 at 08:31
  • @Peter I feel like you're stalking me :-) But really, thank you for following up on all of these answers; I learn a lot from your comments. I will try to remember to follow-up on this (and the others) when I have time. I think you are right about changing `fs`. – Jonathon Reinhart Dec 06 '17 at 13:17
  • Also related: [Finding the memory address of fs:28h](https://stackoverflow.com/q/76745613) is asking how to find the linear address of that location. For more detail on reading segment bases, see [Reading a segment register (%gs) which contains the pointer to a list](https://stackoverflow.com/q/76645203) . (And no, my older comment is probably wrong about `mov fs, eax` in 64-bit mode, unless that works for bases in the low 32 bits of address-space. It might still set a base, but normally the FS base is set via an MSR if not with `wrfsbase`) – Peter Cordes Jul 22 '23 at 23:22