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
Bug only reproducible inside of release binary when compiled with musl in Alpine, with multiple threads enabled.
This file does exist and previous stat calls worked on the same file.
I've commented the code causing the segfault