Page 1 of 1

Question about local variables and paging...

Posted: Wed Jan 10, 2007 8:55 pm
by ajforgue
I didn't think this would be an issue, but I have a local variable in some function called buffer:

Code: Select all

char buffer[8] = {0xd,0xe,0xa,0xd,0xb,0xe,0xe,0xf};
The deadbeef is there for a memory dump.

This buffer variable is in a static member function in a class (C++ Kernel). Usually this function works fine. But after I enable my own paging that maps only what I need (the kernel intially starts with 4MB identity mapped) like video memory, kernel pages, and the free page stack, calling this function page faults. If I remove that local variable, it's fine. When I check the bochs log, I get this:

Code: Select all

00016288115-@c0100b47-[CPU  ]: page fault for address 00000014 @ c0100b47
00016288115-@c0100b47-[CPU  ]: exception(0x0E)
00016288115-@c0100b41-[CPU  ]: interrupt(): vector = 14, INT = 0, EXT = 1
00016288115-@c0100b41-[CPU  ]: page fault for address 00000070 @ c0100b41
00016288115-@c0100b41-[CPU  ]: exception(0x0E)
00016288115-@c0100b41-[CPU  ]: interrupt(): vector = 8, INT = 0, EXT = 1
00016288115-@c0100b41-[CPU  ]: page fault for address 00000040 @ c0100b41
00016288115-@c0100b41-[CPU  ]: exception(0x0E)
00016288115-@c0100b41-[CPU  ]: protected mode
00016288115-@c0100b41-[CPU  ]: CS.d_b = 32 bit
00016288115-@c0100b41-[CPU  ]: SS.d_b = 32 bit
00016288115-@c0100b41-[CPU  ]: | EAX=00000030  EBX=00002000  ECX=00109000  EDX=00000001
00016288115-@c0100b41-[CPU  ]: | ESP=c0107f98  EBP=00067ee4  ESI=000544c1  EDI=000544c2
00016288115-@c0100b41-[CPU  ]: | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf AF pf cf
00016288115-@c0100b41-[CPU  ]: | SEG selector     base    limit G D
00016288115-@c0100b41-[CPU  ]: | SEG sltr(index|ti|rpl)     base    limit G D
00016288115-@c0100b41-[CPU  ]: |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00016288115-@c0100b41-[CPU  ]: |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00016288115-@c0100b41-[CPU  ]: |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00016288115-@c0100b41-[CPU  ]: |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00016288115-@c0100b41-[CPU  ]: |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00016288115-@c0100b41-[CPU  ]: |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00016288115-@c0100b41-[CPU  ]: | EIP=c0100b41 (c0100b41)
00016288115-@c0100b41-[CPU  ]: | CR0=0x80000011 CR1=0 CR2=0x00000040
00016288115-@c0100b41-[CPU  ]: | CR3=0x00109000 CR4=0x00000010
00016288115-@c0100b41-[CPU  ]: >> mov eax, dword ptr gs:0x14 : 65A114000000
The code disassembly is here (mixed with source):

Code: Select all

   char Convert::Blah(char x, char y)
c0100b2e:   83 ec 1c                sub    esp,0x1c
c0100b31:   8b 44 24 20             mov    eax,DWORD PTR [esp+32]
c0100b35:   8b 54 24 24             mov    edx,DWORD PTR [esp+36]
c0100b39:   88 44 24 08             mov    BYTE PTR [esp+8],al
c0100b3d:   88 54 24 04             mov    BYTE PTR [esp+4],dl
c0100b41:   65 a1 14 00 00 00       mov    eax,gs:0x14
c0100b47:   89 44 24 18             mov    DWORD PTR [esp+24],eax
c0100b4b:   31 c0                   xor    eax,eax
   {
      char buffer[8] = {0xd,0xe,0xa,0xd,0xb,0xe,0xe,0xf};
c0100b4d:   c6 44 24 10 0d          mov    BYTE PTR [esp+16],0xd
c0100b52:   c6 44 24 11 0e          mov    BYTE PTR [esp+17],0xe
c0100b57:   c6 44 24 12 0a          mov    BYTE PTR [esp+18],0xa
c0100b5c:   c6 44 24 13 0d          mov    BYTE PTR [esp+19],0xd
c0100b61:   c6 44 24 14 0b          mov    BYTE PTR [esp+20],0xb
c0100b66:   c6 44 24 15 0e          mov    BYTE PTR [esp+21],0xe
c0100b6b:   c6 44 24 16 0e          mov    BYTE PTR [esp+22],0xe
c0100b70:   c6 44 24 17 0f          mov    BYTE PTR [esp+23],0xf
      return (x+y) & 0x7F;
c0100b75:   0f b6 54 24 08          movzx  edx,BYTE PTR [esp+8]
c0100b7a:   0f b6 44 24 04          movzx  eax,BYTE PTR [esp+4]
c0100b7f:   8d 04 02                lea    eax,[edx+eax]
c0100b82:   0f be c0                movsx  eax,al
c0100b85:   83 e0 7f                and    eax,0x7f
   }
c0100b88:   8b 54 24 18             mov    edx,DWORD PTR [esp+24]
c0100b8c:   65 33 15 14 00 00 00    xor    edx,DWORD PTR gs:0x14
c0100b93:   74 05                   je     c0100b9a <ForgueOS::Convert::Blah(char, char)+0x6c>
c0100b95:   e8 dc f5 ff ff          call   c0100176 <__stack_chk_fail>
c0100b9a:   83 c4 1c                add    esp,0x1c
c0100b9d:   c3                      ret
I have no idea why it'd try to load eax with gs:0x14.

Perhaps something with my linker script?...

I really have no idea what could be causing this or what. I've been hacking on this for a few days now and it's driving me insane, any help is appreciated.

Posted: Wed Jan 10, 2007 11:09 pm
by smbogan
I'm just curious but why are your segment limits only 0xfffff? instead of 0xffffffff? Your point was to have your kernel access all memory right? And is your DX correct at the start of memory + 1?

Posted: Thu Jan 11, 2007 3:54 am
by Jules
How are you compiling? If memory serves, gcc uses the GS register to point to a thread-local information block for getting access to thread local variables (among other things). From my reading of the spec, I think %gs:14 would point to a thread-local variable of some kind.

I think the key to understanding this behaviour is in tracking what it does with the value:


mov eax,gs:0x14
mov DWORD PTR [esp+24],eax
[...]
mov edx,DWORD PTR [esp+24]
xor edx,DWORD PTR gs:0x14
[... do something else if the result is zero, i.e. the value is unchanged]
call c0100176 <__stack_chk_fail>

Are you compiling with some kind of stack canary system?

Posted: Thu Jan 11, 2007 8:58 pm
by ajforgue
Thanks guys, both of your comments needed fixing. The canary system was the cause, and compiling with -fno-stack-protector in GCC fixed the problem. Is that just band-aiding the problem or is it a side effect from enabling paging that breaks the canary system?

Posted: Fri Jan 12, 2007 10:16 am
by Candy
ajforgue wrote:Thanks guys, both of your comments needed fixing. The canary system was the cause, and compiling with -fno-stack-protector in GCC fixed the problem. Is that just band-aiding the problem or is it a side effect from enabling paging that breaks the canary system?
Since when does GCC include a canary by default?

Posted: Fri Jan 12, 2007 10:52 am
by ajforgue
Ubuntu does by default
Implementation: Implemented
Release goal: Accepted for edgy

Posted: Fri Jan 12, 2007 11:54 am
by Brynet-Inc
OpenBSD Also includes ProPolice default..

http://en.wikipedia.org/wiki/Stack-smas ... oPolice.29