You are here: Home ยป Blog

The GS segment and stack smashing protection

Posted on Tuesday, March 31 2015 at 14:59 | Category: Linux, C | 1 Comment(s)

When disassembling (32 bit i386 / x86) code on Linux, we sometimes come across instructions like

...
call   *%gs:0x10
...
movl    %gs:0x14, %eax
...

Here, gs refers to the Thread Control Block (TCB) header which stores per-CPU and thread local data (Thread Local Storage, TLS). The Thread Control Block header is a structure which is defined in the C library, for example in eglibc-2.19/nptl/sysdeps/i386/tls.h (slightly simplified and added the gs segment offsets):

typedef struct {
  void *tcb;              /* gs:0x00 Pointer to the TCB. */
  dtv_t *dtv;             /* gs:0x04 */
  void *self;             /* gs:0x08 Pointer to the thread descriptor.  */
  int multiple_threads;   /* gs:0x0c */
  uintptr_t sysinfo;      /* gs:0x10 Syscall interface */
  uintptr_t stack_guard;  /* gs:0x14 Random value used for stack protection */
  uintptr_t pointer_guard;/* gs:0x18 Random value used for pointer protection */
  int gscope_flag;        /* gs:0x1c */
  int private_futex;      /* gs:0x20 */
  void *__private_tm[4];  /* gs:0x24 Reservation of some values for the TM ABI.  */
  void *__private_ss;     /* gs:0x34 GCC split stack support.  */
} tcbhead_t;

Lets take a closer look at gs:0x10 which I mentioned above: The stack_guard member contains a random value which is used to protect against stack smashing - consider the following sample which contains an obvious buffer overflow:

#include <string.h>

int main() {
   char buffer[4];
   strcpy(buffer, "Hello World");
   return 0;
}

When we compile and run this application, we will get a runtime error:

$ gcc -m32 -o smash smash.c
$ ./smash 
*** stack smashing detected ***: ./smash terminated
Aborted (core dumped)

Lets look at the code which is generated by the compiler:

$ gcc -m32 -S -o smash.S smash.c
The following is the (simplified and commented) smash.S file:
main:
; Set up the stack
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $16, %esp

; Set up stack guard
        movl    %gs:20, %eax       ; load random value
        movl    %eax, 12(%esp)     ; store value as a guard variable 
        xorl    %eax, %eax         ; make sure that noone can read the random value afterwards
;...
; strcpy ommitted (this overwrites 12(%esp) since the string is too large for the buffer)
;...

; Check stack guard against value from TCB
        movl    12(%esp), %edx     ; load previously stored value from stack
        xorl    %gs:20, %edx       ; check if still the same
        je      .L3                ; yes, then fine
        call    __stack_chk_fail   ; print error message and abort()
.L3:
        leave
        ret

As we see, the compiler inserts instructions at the beginning of the function to set up the stack guard variable, and it inserts instructions at the end of the function to check if the value has changed meanwhile (means, if any code within the function has written beyond the area allocated for local variables and hence has potentially overwritten the return address for the current function).

The generation of the stack protection code can be disabled by passing the -fno-stack-protector option to gcc - this is something which should, of course, normally not be done but it can sometimes be useful in order to analyze certain security issues.


Returning values from a bash function

Posted on Thursday, July 10 2014 at 16:09 | Category: Linux | 0 Comment(s)

bash does not provide a return statement to return custom values from a function. The return statement is only used to return a numeric status code to the calling function which can be retrieved with $?.

Long story made short, use a recent bash version (>= 4.3) and use the declare -n statement to declare a reference to the variable where the result will be stored, and pass the name of this variable as a parameter to the function:


#!/bin/bash

someFunction() {
    declare -n __resultVar=$1
    local someValue="Hello World"

    # The next statement assigns the value of the local variable to the variable
    # passed as parameter
    __resultVar=${someValue}
}

# call the function and pass the name of the result variable
someFunction theResult
echo ${theResult}

Name service request caching with nscd

Posted on Monday, July 07 2014 at 17:08 | Category: Linux | 0 Comment(s)

Sometimes it is still easiest (especially when there is only a command line terminal available) to directly edit files like /etc/passwd, /etc/hosts etc. with a plain text editor. When I today just wanted to change the login shell of a user on an Oracle Enterprise Linux installation, I simply changed /bin/csh to /bin/bash for the corresponding entry in /etc/passwd.

However, the surprise was that the new entry was not considered when re-logging in. This is where nscd comes into play. From the man page:

NSCD(8)                    Linux Programmer's Manual                   NSCD(8)

NAME
       /usr/sbin/nscd - name service cache daemon

DESCRIPTION
       Nscd  is a daemon that provides a cache for the most common name service requests.  ...

Among those most common name service requests are lookups into the /etc/hosts, /etc/group and /etc/hosts files.

Actually the nscd daemon also watches the respective files for changes, but it might take several minutes until it picks up the modified files.To clear the nscd cache immediately, simply call nscd with the -i switch and the name of the lookup database which needs to be reloaded:

$ /usr/sbin/nscd -i passwd

By the way, stopping and re-starting the nscd daemon through /etc/init.d/nscd is not enough - the daemon still remembers its cached entries afterwards.


New Linux installation

Posted on Saturday, January 03 2009 at 00:49 | Category: Linux | 0 Comment(s)

A couple of weeks ago, I installed kubuntu 8.10 as my primary operating system. My debian installation was quite outdated, because I did not change much in the last - well - two years or so. I really needed a stable system, but now it was time to update to a recent distribution. Even though I have a 64 bit CPU, I decided to install the 32 bit version of Kubuntu. The main reason was that in the past I often had issues with software which was not yet available for 64 bit Linux. The plan is to use a stable 32 bit system for daily usage, and create either chroot environments for other usage (like a debian unstable environment) or even use virtual machines when necessary. Installation of Kubuntu was quite straight forward, and I will talk about some of the less straight forward things in some upcoming posts.


Displaying results 5 to 8 out of 14