Skip to content

Segfault when statically linked against musl  #19

@luke-goddard

Description

@luke-goddard

Bug only reproducible inside of release binary when compiled with musl in Alpine, with multiple threads enabled.

/**
 * This function will check the current file to see if it resides in a location 
 * that should be read only
 */
static void check_global_write(All_Results *ar, File_Info *fi)
{
    if (!has_global_write(fi))
        return;

    /* Check to see if the file is protected by any parent directories */
    char parent_buf[MAXSIZE] = {'\0'};
    char issue_buf[MAXSIZE + 50] = {'\0'};

    if (get_first_dir_that_protects_file(fi->location, parent_buf, ar))
    {
        /* The directory is protected */
        snprintf(issue_buf, (sizeof(issue_buf) - 1), "Found a protected world writable file in: %s", parent_buf);
        struct stat stats;
        if ((stat(parent_buf, &stats) != 0))
        {
            log_error_errno_loc(ar, "Failed to stat directory", parent_buf, errno);
            printf("%i -> %i -> %s -> %i -> %s\n", LOW, AUDIT, fi->location, ar == NULL, issue_buf);
            add_issue(LOW, AUDIT, fi->location, ar, issue_buf, "ENUMY failed to stat the parent directory");
            return;
        }
        struct passwd *data = getpwuid(stats.st_uid); <======== Segfault here 
        if (data == NULL)
        {
            log_error_errno_loc(ar, "Failed to stat directory", parent_buf, errno);
            add_issue(LOW, AUDIT, fi->location, ar, issue_buf, "ENUMY failed to got the owner of the directory");
            return;
        }
        add_issue(LOW, AUDIT, fi->location, ar, issue_buf, data->pw_name);
        return;
    }
debug extra-> src/all_scans.c:99:scan_file_for_issues(): Scanning file ->/home/luke/some_file
[!] - ERROR -> Failed to stat directory: No data available /home/luke/

This file does exist and previous stat calls worked on the same file.

$ gdb ouput/enumy64
@gdb-peda$ set follow-fork-mode parent 
@gdb-peda$ start -t 12 
@gdb-peda$ c
...Stopped reason: SIGSEGV
@gdb-peda$ backtrace 
#0  unmap_chunk (self=0x7ffffa5dc930) at src/malloc/malloc.c:515
#1  free (p=p@entry=0x7ffffa5dc940) at src/malloc/malloc.c:526
#2  0x00007ffff7fe0eb6 in realloc (p=0x7ffffa5dc940, n=<optimized out>, n@entry=0x32) at src/malloc/malloc.c:436
#3  0x00007ffff7fea1a6 in getdelim (s=s@entry=0x7ffff7ffe350 <line>, n=n@entry=0x7ffff7ffe318 <size>, delim=delim@entry=0xa, f=f@entry=0x7ffffa65b120) at src/stdio/getdelim.c:38
#4  0x00007ffff7fe276e in getline (s=s@entry=0x7ffff7ffe350 <line>, n=n@entry=0x7ffff7ffe318 <size>, f=f@entry=0x7ffffa65b120) at src/stdio/getline.c:5
#5  0x00007ffff7fe1961 in __getpwent_a (f=f@entry=0x7ffffa65b120, pw=pw@entry=0x7ffff7ffe320 <pw>, line=line@entry=0x7ffff7ffe350 <line>, size=size@entry=0x7ffff7ffe318 <size>, res=res@entry=0x7ffff7f33bb8) at src/passwd/getpwent_a.c:19
#6  0x00007ffff7fe9044 in __getpw_a (name=name@entry=0x0, uid=0x3e8, pw=pw@entry=0x7ffff7ffe320 <pw>, buf=buf@entry=0x7ffff7ffe350 <line>, size=size@entry=0x7ffff7ffe318 <size>, res=res@entry=0x7ffff7f33bb8) at src/passwd/getpw_a.c:36
#7  0x00007ffff7fe18f0 in getpwuid (uid=<optimized out>) at src/passwd/getpwent.c:28
#8  0x00007ffff7fdac56 in check_global_write (ar=0x7ffff8000860, fi=0x7ffffa6c6360) at src/scans/permissions_scan.c:80
#9  0x00007ffff7fdaa57 in permissions_scan (fi=0x7ffffa6c6360, ar=0x7ffff8000860, users=0x7ffff80ea500) at src/scans/permissions_scan.c:50
#10 0x00007ffff7fcf5b9 in scan_file_for_issues (thread_pool_args=0x7ffff8000940) at src/all_scans.c:106
#11 0x00007ffff7fd527b in thread_do (thread_p=0x7ffff8b25880) at src/thpool.c:362
#12 0x00007ffff7fe6270 in start (p=0x7ffff7f34ee8) at src/thread/pthread_create.c:192
#13 0x00007ffff7fe6f23 in __clone () at src/thread/x86_64/clone.s:22
@gdb-peda$ frame 8
@gdb-peda$ stats = {
  st_dev = 0x30,
  st_ino = 0x75c0,
  st_nlink = 0xc,
  st_mode = 0x41c0,
  st_uid = 0x3e8,
  st_gid = 0x3d9,
  __pad0 = 0x0,
  st_rdev = 0x0,
  st_size = 0x17c,
  st_blksize = 0x1000,
  st_blocks = 0x0,
  st_atim = {
    tv_sec = 0x5ed7a82e,
    tv_nsec = 0x3cbe13
  },
  st_mtim = {
    tv_sec = 0x5ed7a7b2,
    tv_nsec = 0x23cd2232
  },
  st_ctim = {
    tv_sec = 0x5ed7a7b2,
    tv_nsec = 0x23cd2232
  },
  __unused = {0x0, 0x0, 0x0}
}
data = 0x0
parent_buf = "/run/user/1000/", '\000' <repeats 2033 times>
issue_buf = "Found a protected world writable file in: /run/user/1000/", '\000' <repeats 2041 times>
@gdb-peda$ x/10i $rip-10
   0x7ffff7fe0eac <realloc+368>:        mov    edi,esp
   0x7ffff7fe0eae <realloc+370>:        mov    r12,r14
   0x7ffff7fe0eb1 <realloc+373>:        call   0x7ffff7fe0d05 <free>
=> 0x7ffff7fe0eb6 <realloc+378>:        add    rsp,0x18
   0x7ffff7fe0eba <realloc+382>:        mov    rax,r12

I've commented the code causing the segfault

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions