Archive for December, 2007

At OH-plex

December 22, 2007

The Christmas arrived at OpenedHand a week ago, in form of a Millenium Falcon, and on that occasion we had some (traditional British) fun together. This was my first chance to see the famous OH-plex live, the place where the ideas hatch for the near and far future of open-source mobile computing. The interior is full of things you’ve never seen and the reindeers help the elves with some of the heavier tasks we have to complete for our super-secret but top of the market corporate customers. There are surprisingly few actual PCs (I think I counted 2 or 3 desktops). Some pictures here.

The said traditional British Xmas goes like this: first thing in the morning you ride quad bikes, then do some archery and this is followed by laser-modded full-size shotgun shooting. Then, to top off the Christmas spirit you jump into a 4×4 jeep for some blindfolded driving in winter mud on a farm in Kent. Basically a day full of crazy fun and joy of celebrating a globe-wide cross-religion holiday.

To get to the place I landed at the London City Airport which is like a normal international airport except it’s squeezed in a space ten times smaller than a usual airport. That allows it to function relatively close to the city centre so you don’t have to travel far. The single runway is practically built *on* the Thames, surrounded by water from all sides and looks quite impressive.

It was very cool to see London after perhaps some ten years since my last visit, and the Thames river had a new feel after my (not so) recent lecture of “Two and a Half Men in a Boat” by Nigel Williams (great read, btw., and how the book got in my hands in the middle of wild wild south of France is a weird story).

Advertisements

Dereference them null pointers

December 3, 2007

Yesterday I played more with executables under Linux and was introduced to linker scripts. Soon it turned out that with a very simple linker script you can have a section starting at vma 0 (zero) in a non-relocatable binary. This wouldn’t be any interesting, but address 0 is where the NULL constant points. So now, if the section was readable and/or writable I could cast NULL to any pointer type, which, as we read below, yields a null pointer of that type, and I could dereference such pointer and read or assign a value to it. This still wouldn’t be interesting, but C defines very specific semantics for null pointers. I reached for the C99 specs (aka ISO/IEC 9899:1999), something I do very rarely, normally only when having a quarrel with someone on IRC, for example over portability to a hypothetical C environment. This is what is says about null pointers in 6.3.2.3.3 and 6.3.2.3.4:

3. An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
4. Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.

First point becomes false because we can now have an object or a function pointed to by a null pointer. Today I stumbled across a phrase in glibc man page for dlsym(3) that explicitly treats function pointers that equal NULL.

Further in ISO/IEC 9899:1999 in footnote 84) we read:

Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.

so the dereference is incorrect but is accepted by the C implementations. This is the case for a whole lot of operations that people’s C programs use. Another whole lot of operations have unpredictable outcome according to the specs but are relied on by thousands of popular programs. So perhaps the main fun from reading the different C specs, if there is any, is not in what it defines as C but rather what it doesn’t define. In any language specification there are parts defined as implementation-specific but this isn’t the best part, the best part is what is not defined as correct (but we often assume it is by generalisation), thus implicitly defined as incorrect or unpredictable, and what weird scenarios that makes possible. For example by my understanding of 6.3.2 in C99, it is entirely possible for two variables of the same type, to compare unequal even directly after assigning value of one to the other:

T a, b;
...
a = b;
a != b;

The last comparison can be true every time T is a pointer type and b doesn’t point at anything in particular. More things you didn’t know about C for example here.

Update: The ABI specification is another document that has something to say about the C implementation you use and what things are legal for you and for the compiler to do. For example regarding null pointers the “AMD64 Architecture” supplement to “System V ABI, Edition 4” has to say this:

A null pointer (for all types) has the value zero.

(…)

Programs that dereference null pointers are erroneous. although an implementation is not obliged to detect such erroneous behavior. Such programs may or may not fail on a particular system. To enhance portability, programmers are strongly cautioned not to rely on this behavior.

This makes things clearer but it doesn’t assure that a null pointer doesn’t point to any object of function.

I can see you gdb

December 1, 2007

So, as soon as the gllin binary was released for download, I came up with an evil plan – will for sure blog about it after it is executed. But first (as part of usual preparation for an evil plan) I needed to find out whether in a normal program under Linux the heap is executable, or rather what section is executable and writable. While attempting this I made a funny and completely unuseful observation which I’m going to share with you now. Here’s the test program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void sayhello(int world_number) {
        int local;
        static int stat;

        printf("Hello World %i! Local variable at %p and static at %p\n",
                        world_number, &local, &stat);
}

int main(int argc, char *argv[], char **envp) {
        void (*say[2])(int i) = { sayhello, malloc(0x1000) };

        memcpy(say[1], say[0], 0x50);
        say[0](0);
        say[1](1);
        return 0;
}

After “make hello” I have the ELF under ./hello and load it into gdb and inspect:

 $ gdb ./hello
GNU gdb 6.6
...
(gdb) break sayhello
Breakpoint 1 at 0x40068f: file hello.c, line 9.
(gdb) run
...
Breakpoint 1, sayhello (world_number=0) at hello.c:9
(gdb) up 
#1  ... in main (argc=1, argv=..., envp=...) at hello.c:17
(gdb) disassemble say[0] (say[0] + 15)
Dump of assembler code from 0x400684 to 0x400693:
0x0000000000400684 <sayhello+0>:        push   %rbp
0x0000000000400685 <sayhello+1>:        mov    %rsp,%rbp
0x0000000000400688 <sayhello+4>:        sub    $0x20,%rsp
0x000000000040068c <sayhello+8>:        mov    %edi,0xffffffffffffffec(%rbp)
0x000000000040068f <sayhello+11>:       lea    0xfffffffffffffffc(%rbp),%rdx
End of assembler dump.
(gdb) disassemble say[1] (say[1] + 15)
Dump of assembler code from 0x602010 to 0x60201f:
0x0000000000602010:     push   %rbp
0x0000000000602011:     mov    %rsp,%rbp
0x0000000000602014:     sub    $0x20,%rsp
0x0000000000602018:     mov    %edi,0xffffffffffffffec(%rbp)
0x000000000060201b:     int3
0x000000000060201c:     lea    0xfffffffffffffffc(%rbp),%edx
End of assembler dump.

You may now ask yourself the same question that I asked myself: WTF? or I may first explain what is happening above and you may ask the question then. We loaded the program into the debugger. The program was supposed to greet the world once and then call a copy of sayhello we made with memcpy(). We set a breakpoint at the start of the function and run the program. When it enters sayhello, it hits the break and we have a chance to look at the copy of the function. We step out of the sayhello frame so that we can access the say array. We disassemble the start of the original function and the start of its copy, and we see that they differ (!). Someone is messing in MY functions?! Or memcpy() is perhaps broken?!

No, it’s just gdb. When we set a breakpoint at sayhello it inserted the extra instruction (which I would have maybe recognised if I used x86 asm more often) to get notified in the right moment. We copied the function together with the breakpoint and we hit the original breakpoint. gdb then hid it from out eyes (first disassembly) but it didn’t know that we had secretly made a copy (second disassembly) and we now have a pretty little breakpoint of our own.

So what useful did we learn? Nothing really. That checksumming the program in runtime may sometimes work.

Good news is that memcpy() is fine and the world is safe. Pheww..