Lower 8 bits are always zero in stackguard value

Bug #1959841 reported by Sukbeom Kim
258
This bug affects 1 person
Affects Status Importance Assigned to Milestone
gcc-defaults (Ubuntu)
Invalid
Undecided
Unassigned

Bug Description

Lower 8bits are always zero in stack guard value, which makes stack protector cannot detect the following stack smashing:

```
#include <string.h>
int get_input(char *data)
{
        strcpy(data, "01234567");
        return 0;
}

// main.c
#include <stdio.h>
#include <stdlib.h>

void *__stack_chk_guard = (void *)0xdeadbeef;

void __stack_chk_fail(void)
{
    fprintf(stderr, "Stack smashing detected.\n");
    exit(1);
}

void get_input(char *data);

char main(void)
{
    char buffer[8] = { 0 };

    get_input(buffer);
    return buffer[0];
}

```

When I look into the problem with gdb, fs:0x28 (stack guard value) has always lower 8 bits like
```
0x007fffffffe190│+0x0000: 0x0000000000000d ("\r"?) ← $rsp
0x007fffffffe198│+0x0008: 0x3fd2300ef2282e00 <-
0x007fffffffe1a0│+0x0010: 0x0000000000000001 ← $rbp
0x007fffffffe1a8│+0x0018: 0x007ffff7db6fd0 → <__libc_start_call_main+128> mov edi, eax
0x007fffffffe1b0│+0x0020: 0x00555555554040 → (bad)
0x007fffffffe1b8│+0x0028: 0x0055555555519e → <main+0> endbr64
0x007fffffffe1c0│+0x0030: 0x0000000100000000
0x007fffffffe1c8│+0x0038: 0x007fffffffe2c8 → 0x007fffffffe577 → "/home/sukbeom/Workspace/arm/stack_protector/sp"
```

I don't know much about stack protector but I think this should be fixed. So I report this as a bug related to stack protector to get more information. Please let me know if there is anything wrong with my report.

I attach my system information:

$ lsb_release -rd
Description: Ubuntu 21.10
Release: 21.10

$ gcc -v
➜ linux git:(study) gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.2.0-7ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-ZPT0kp/gcc-11-11.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-ZPT0kp/gcc-11-11.2.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.2.0 (Ubuntu 11.2.0-7ubuntu2)

Thank you.

Revision history for this message
Sukbeom Kim (chaoxifer) wrote :

I'd like to close this issue.

I found that there is code like below in Linux Kernel (include/linux/random.h)

```
/*
 * On 64-bit architectures, protect against non-terminated C string overflows
 * by zeroing out the first byte of the canary; this leaves 56 bits of entropy.
 */
#ifdef CONFIG_64BIT
# ifdef __LITTLE_ENDIAN
# define CANARY_MASK 0xffffffffffffff00UL
# else /* big endian, 64 bits: */
# define CANARY_MASK 0x00ffffffffffffffUL
# endif
#else /* 32 bits: */
# define CANARY_MASK 0xffffffffUL
#endif
```

I found Stack overflow by NULL character is already handled by kernel code. This makes me confused.
Sorry for making noise to you.

Thank you,
Jason Kim

information type: Private Security → Public Security
Revision history for this message
Seth Arnold (seth-arnold) wrote :

Hello, the stack checking is intended to detect simplistic overwrites of stack control structures. If an attacker is able to overwrite a single NUL in the canary with a NUL supplied from an input string, but no further, then the stack control structures are still intact and undamaged. As far as the stack checking is concerned, this is a success.

The intention of the 'terminator canary' is that it would be difficult to cause a write with common string functions to go beyond the canary -- they'd stop on the newline, or the NUL, and wouldn't progress beyond that.

Can you get strcpy() to go beyond the canary, to the control structures?

Thanks

Revision history for this message
Seth Arnold (seth-arnold) wrote :

Ah, sorry, I see I lost a race condition :) thanks

Changed in gcc-defaults (Ubuntu):
status: New → Invalid
Revision history for this message
Sukbeom Kim (chaoxifer) wrote :

That's fine. Thanks for the kind explanation.

Thank you,
Jason Kim

To post a comment you must log in.
This report contains Public Security information  
Everyone can see this security related information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.