o_cloexec; preserve leading slashes in root-level paths

This commit is contained in:
Ryan Fleury
2025-11-07 16:37:30 -08:00
parent d4d2159389
commit 035e72306d
4 changed files with 327 additions and 312 deletions
+146 -146
View File
@@ -124,21 +124,21 @@ dmn_lnx_read_ehdr(int memory_fd, U64 addr, ELF_Hdr64 *ehdr_out)
{ {
switch(e_ident[ELF_Identifier_Class]) switch(e_ident[ELF_Identifier_Class])
{ {
default:{InvalidPath;}break; default:{InvalidPath;}break;
case ELF_Class_None: {}break; case ELF_Class_None: {}break;
case ELF_Class_32: case ELF_Class_32:
{
ELF_Hdr32 ehdr32 = {0};
if(dmn_lnx_read_struct(memory_fd, addr, &ehdr32))
{ {
*ehdr_out = elf_hdr64_from_hdr32(ehdr32); ELF_Hdr32 ehdr32 = {0};
is_read = 1; if(dmn_lnx_read_struct(memory_fd, addr, &ehdr32))
} {
}break; *ehdr_out = elf_hdr64_from_hdr32(ehdr32);
case ELF_Class_64: is_read = 1;
{ }
is_read = dmn_lnx_read_struct(memory_fd, addr, ehdr_out); }break;
}break; case ELF_Class_64:
{
is_read = dmn_lnx_read_struct(memory_fd, addr, ehdr_out);
}break;
} }
} }
} }
@@ -151,21 +151,21 @@ dmn_lnx_read_phdr(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr
B32 is_read = 0; B32 is_read = 0;
switch (elf_class) switch (elf_class)
{ {
case ELF_Class_None: break; case ELF_Class_None: break;
case ELF_Class_32: case ELF_Class_32:
{
ELF_Phdr32 phdr32 = {0};
if(dmn_lnx_read_struct(memory_fd, addr, &phdr32))
{ {
*phdr_out = elf_phdr64_from_phdr32(phdr32); ELF_Phdr32 phdr32 = {0};
is_read = 1; if(dmn_lnx_read_struct(memory_fd, addr, &phdr32))
} {
}break; *phdr_out = elf_phdr64_from_phdr32(phdr32);
case ELF_Class_64: is_read = 1;
{ }
is_read = dmn_lnx_read_struct(memory_fd, addr, phdr_out); }break;
}break; case ELF_Class_64:
default:{NotImplemented;}break; {
is_read = dmn_lnx_read_struct(memory_fd, addr, phdr_out);
}break;
default:{NotImplemented;}break;
} }
return is_read; return is_read;
} }
@@ -176,21 +176,21 @@ dmn_lnx_read_shdr(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr
B32 is_read = 0; B32 is_read = 0;
switch (elf_class) switch (elf_class)
{ {
case ELF_Class_None: break; case ELF_Class_None: break;
case ELF_Class_32: case ELF_Class_32:
{
ELF_Shdr32 shdr32 = {0};
if(dmn_lnx_read_struct(memory_fd, addr, &shdr32))
{ {
*shdr_out = elf_shdr64_from_shdr32(shdr32); ELF_Shdr32 shdr32 = {0};
is_read = 1; if(dmn_lnx_read_struct(memory_fd, addr, &shdr32))
} {
}break; *shdr_out = elf_shdr64_from_shdr32(shdr32);
case ELF_Class_64: is_read = 1;
{ }
is_read = dmn_lnx_read_struct(memory_fd, addr, shdr_out); }break;
}break; case ELF_Class_64:
default:{NotImplemented;}break; {
is_read = dmn_lnx_read_struct(memory_fd, addr, shdr_out);
}break;
default:{NotImplemented;}break;
} }
return is_read; return is_read;
} }
@@ -201,22 +201,22 @@ dmn_lnx_read_linkmap(int memory_fd, U64 addr, ELF_Class elf_class, GNU_LinkMap64
B32 is_read = 0; B32 is_read = 0;
switch(elf_class) switch(elf_class)
{ {
case ELF_Class_None: {}break; case ELF_Class_None: {}break;
case ELF_Class_32: case ELF_Class_32:
{
// TODO(rjf): endianness
GNU_LinkMap32 linkmap32 = {0};
if(dmn_lnx_read_struct(memory_fd, addr, &linkmap32))
{ {
*linkmap_out = gnu_linkmap64_from_linkmap32(linkmap32); // TODO(rjf): endianness
is_read = 1; GNU_LinkMap32 linkmap32 = {0};
} if(dmn_lnx_read_struct(memory_fd, addr, &linkmap32))
}break; {
case ELF_Class_64: *linkmap_out = gnu_linkmap64_from_linkmap32(linkmap32);
{ is_read = 1;
is_read = dmn_lnx_read_struct(memory_fd, addr, linkmap_out); }
}break; }break;
default:{NotImplemented;}break; case ELF_Class_64:
{
is_read = dmn_lnx_read_struct(memory_fd, addr, linkmap_out);
}break;
default:{NotImplemented;}break;
} }
return is_read; return is_read;
} }
@@ -227,21 +227,21 @@ dmn_lnx_read_dynamic(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dy
B32 is_read = 0; B32 is_read = 0;
switch(elf_class) switch(elf_class)
{ {
case ELF_Class_None:{}break; case ELF_Class_None:{}break;
case ELF_Class_32: case ELF_Class_32:
{
ELF_Dyn32 dyn32 = {0};
if(dmn_lnx_read_struct(memory_fd, addr, &dyn32))
{ {
*dyn_out = elf_dyn64_from_dyn32(dyn32); ELF_Dyn32 dyn32 = {0};
is_read = 1; if(dmn_lnx_read_struct(memory_fd, addr, &dyn32))
} {
}break; *dyn_out = elf_dyn64_from_dyn32(dyn32);
case ELF_Class_64: is_read = 1;
{ }
is_read = dmn_lnx_read_struct(memory_fd, addr, dyn_out); }break;
}break; case ELF_Class_64:
default:{NotImplemented;}break; {
is_read = dmn_lnx_read_struct(memory_fd, addr, dyn_out);
}break;
default:{NotImplemented;}break;
} }
return is_read; return is_read;
} }
@@ -252,21 +252,21 @@ dmn_lnx_read_symbol(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Sym64 *sym
B32 is_read = 0; B32 is_read = 0;
switch(elf_class) switch(elf_class)
{ {
case ELF_Class_None:{}break; case ELF_Class_None:{}break;
case ELF_Class_32: case ELF_Class_32:
{
ELF_Sym32 symbol32 = {0};
if(dmn_lnx_read_struct(memory_fd, addr, &symbol32))
{ {
*symbol_out = elf_sym64_from_sym32(symbol32); ELF_Sym32 symbol32 = {0};
is_read = 1; if(dmn_lnx_read_struct(memory_fd, addr, &symbol32))
} {
}break; *symbol_out = elf_sym64_from_sym32(symbol32);
case ELF_Class_64: is_read = 1;
{ }
is_read = dmn_lnx_read_struct(memory_fd, addr, symbol_out); }break;
}break; case ELF_Class_64:
default:{NotImplemented;}break; {
is_read = dmn_lnx_read_struct(memory_fd, addr, symbol_out);
}break;
default:{NotImplemented;}break;
} }
return is_read; return is_read;
} }
@@ -277,20 +277,20 @@ dmn_lnx_read_r_debug(int memory_fd, U64 addr, Arch arch, GNU_RDebugInfo64 *rdebu
B32 is_read = 0; B32 is_read = 0;
switch(gnu_rdebug_info_size_from_arch(arch)) switch(gnu_rdebug_info_size_from_arch(arch))
{ {
case 0: {} break; case 0: {} break;
case sizeof(GNU_RDebugInfo32): { case sizeof(GNU_RDebugInfo32): {
GNU_RDebugInfo32 rdebug32 = {0}; GNU_RDebugInfo32 rdebug32 = {0};
if(dmn_lnx_read_struct(memory_fd, addr, &rdebug32)) if(dmn_lnx_read_struct(memory_fd, addr, &rdebug32))
{
*rdebug_out = gnu_rdebug_info64_from_rdebug_info32(rdebug32);
is_read = 1;
}
}break;
case sizeof(GNU_RDebugInfo64):
{ {
*rdebug_out = gnu_rdebug_info64_from_rdebug_info32(rdebug32); is_read = dmn_lnx_read_struct(memory_fd, addr, rdebug_out);
is_read = 1; }break;
} default:{InvalidPath;}break;
}break;
case sizeof(GNU_RDebugInfo64):
{
is_read = dmn_lnx_read_struct(memory_fd, addr, rdebug_out);
}break;
default:{InvalidPath;}break;
} }
Assert(is_read); Assert(is_read);
return is_read; return is_read;
@@ -338,7 +338,7 @@ dmn_lnx_ehdr_from_pid(pid_t pid)
String8 exe_path = dmn_lnx_exe_path_from_pid(scratch.arena, pid); String8 exe_path = dmn_lnx_exe_path_from_pid(scratch.arena, pid);
if(exe_path.size != 0) if(exe_path.size != 0)
{ {
int exe_fd = open((char *)exe_path.str, O_RDONLY); int exe_fd = open((char *)exe_path.str, O_RDONLY|O_CLOEXEC);
if(exe_fd != -1) if(exe_fd != -1)
{ {
is_read = dmn_lnx_read_ehdr(exe_fd, 0, &exe); is_read = dmn_lnx_read_ehdr(exe_fd, 0, &exe);
@@ -358,7 +358,7 @@ dmn_lnx_auxv_from_pid(pid_t pid, ELF_Class elf_class)
// rjf: open aux data // rjf: open aux data
String8 auxv_path = push_str8f(scratch.arena, "/proc/%d/auxv", pid); String8 auxv_path = push_str8f(scratch.arena, "/proc/%d/auxv", pid);
int auxv_fd = open((char*)auxv_path.str, O_RDONLY); int auxv_fd = open((char*)auxv_path.str, O_RDONLY|O_CLOEXEC);
// rjf: scan aux data // rjf: scan aux data
if(auxv_fd >= 0) if(auxv_fd >= 0)
@@ -369,24 +369,24 @@ dmn_lnx_auxv_from_pid(pid_t pid, ELF_Class elf_class)
ELF_Auxv64 auxv = {0}; ELF_Auxv64 auxv = {0};
switch(elf_class) switch(elf_class)
{ {
case ELF_Class_None:{}break; case ELF_Class_None:{}break;
case ELF_Class_32: case ELF_Class_32:
{
ELF_Auxv32 auxv32 = {0};
if(read(auxv_fd, &auxv32, sizeof(auxv32)) != sizeof(auxv32))
{ {
goto brkloop; ELF_Auxv32 auxv32 = {0};
} if(read(auxv_fd, &auxv32, sizeof(auxv32)) != sizeof(auxv32))
auxv = elf_auxv64_from_auxv32(auxv32); {
}break; goto brkloop;
case ELF_Class_64: }
{ auxv = elf_auxv64_from_auxv32(auxv32);
if(read(auxv_fd, &auxv, sizeof(auxv)) != sizeof(auxv)) }break;
case ELF_Class_64:
{ {
goto brkloop; if(read(auxv_fd, &auxv, sizeof(auxv)) != sizeof(auxv))
} {
}break; goto brkloop;
default:{NotImplemented;}break; }
}break;
default:{NotImplemented;}break;
} }
// rjf: fill result // rjf: fill result
@@ -583,7 +583,7 @@ dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vbase)
} }
} }
exit:; exit:;
scratch_end(scratch); scratch_end(scratch);
return rdebug_vaddr; return rdebug_vaddr;
} }
@@ -611,8 +611,8 @@ dmn_lnx_read_probes(Arena *arena, int fd, U64 offset, U64 image_base)
ELF_Shdr64 stapsdt_base_shdr = {0}; ELF_Shdr64 stapsdt_base_shdr = {0};
ELF_Shdr64 stapsdt_shdr = {0}; ELF_Shdr64 stapsdt_shdr = {0};
for(U64 shdr_off = offset + ehdr.e_shoff, shdr_opl = shdr_off + ehdr.e_shentsize * ehdr.e_shnum; for(U64 shdr_off = offset + ehdr.e_shoff, shdr_opl = shdr_off + ehdr.e_shentsize * ehdr.e_shnum;
shdr_off < shdr_opl; shdr_off < shdr_opl;
shdr_off += ehdr.e_shentsize) { shdr_off += ehdr.e_shentsize) {
ELF_Shdr64 shdr = {0}; ELF_Shdr64 shdr = {0};
if(!dmn_lnx_read_shdr(fd, shdr_off, ehdr.e_ident[ELF_Identifier_Class], &shdr)) { goto exit; } if(!dmn_lnx_read_shdr(fd, shdr_off, ehdr.e_ident[ELF_Identifier_Class], &shdr)) { goto exit; }
@@ -712,7 +712,7 @@ dmn_lnx_read_probes(Arena *arena, int fd, U64 offset, U64 image_base)
probes.count += 1; probes.count += 1;
} }
exit:; exit:;
scratch_end(scratch); scratch_end(scratch);
return probes; return probes;
} }
@@ -1317,27 +1317,27 @@ dmn_lnx_set_single_step_flag(DMN_LNX_Entity *thread, B32 is_on)
B32 is_flag_set = 0; B32 is_flag_set = 0;
switch(thread->arch) switch(thread->arch)
{ {
case Arch_COUNT: case Arch_COUNT:
case Arch_Null: {} break; case Arch_Null: {} break;
case Arch_x64: case Arch_x64:
{
REGS_RegBlockX64 *reg_block = thread->reg_block;
if(is_on)
{ {
reg_block->rflags.u64 |= X64_RFlag_Trap; REGS_RegBlockX64 *reg_block = thread->reg_block;
} if(is_on)
else {
reg_block->rflags.u64 |= X64_RFlag_Trap;
}
else
{
reg_block->rflags.u64 &= ~X64_RFlag_Trap;
}
is_flag_set = dmn_lnx_thread_write_reg_block(thread, thread->reg_block);
}break;
case Arch_x86:
case Arch_arm32:
case Arch_arm64:
{ {
reg_block->rflags.u64 &= ~X64_RFlag_Trap; NotImplemented;
} }break;
is_flag_set = dmn_lnx_thread_write_reg_block(thread, thread->reg_block);
}break;
case Arch_x86:
case Arch_arm32:
case Arch_arm64:
{
NotImplemented;
}break;
} }
Assert(is_flag_set); Assert(is_flag_set);
return is_flag_set; return is_flag_set;
@@ -1452,7 +1452,7 @@ dmn_lnx_process_unloaded_modules(Arena *arena, DMN_EventList *events, DMN_LNX_En
} }
is_unmap_complete_finished = 1; is_unmap_complete_finished = 1;
exit:; exit:;
Assert(is_unmap_complete_finished); Assert(is_unmap_complete_finished);
scratch_end(scratch); scratch_end(scratch);
} }
@@ -1667,7 +1667,7 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
case LaunchStatus_Success: case LaunchStatus_Success:
{ {
ELF_Hdr64 exe_ehdr = dmn_lnx_ehdr_from_pid(pid); ELF_Hdr64 exe_ehdr = dmn_lnx_ehdr_from_pid(pid);
int memory_fd = open((char*)str8f(scratch.arena, "/proc/%d/mem", pid).str, O_RDWR); int memory_fd = open((char*)str8f(scratch.arena, "/proc/%d/mem", pid).str, O_RDWR|O_CLOEXEC);
DMN_LNX_ProcessAuxv auxv = dmn_lnx_auxv_from_pid(pid, exe_ehdr.e_ident[ELF_Identifier_Class]); DMN_LNX_ProcessAuxv auxv = dmn_lnx_auxv_from_pid(pid, exe_ehdr.e_ident[ELF_Identifier_Class]);
Arch arch = arch_from_elf_machine(exe_ehdr.e_machine); Arch arch = arch_from_elf_machine(exe_ehdr.e_machine);
U64 rdebug_vaddr = dmn_lnx_rdebug_vaddr_from_memory(memory_fd, auxv.base); U64 rdebug_vaddr = dmn_lnx_rdebug_vaddr_from_memory(memory_fd, auxv.base);
@@ -1702,7 +1702,7 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
String8 dl_path = {0}; String8 dl_path = {0};
{ {
int maps_fd = open((char *)str8f(scratch.arena, "/proc/%d/maps", pid).str, O_RDONLY); int maps_fd = open((char *)str8f(scratch.arena, "/proc/%d/maps", pid).str, O_RDONLY|O_CLOEXEC);
if(maps_fd != -1) if(maps_fd != -1)
{ {
struct stat st = {0}; struct stat st = {0};
@@ -1785,7 +1785,7 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
DMN_LNX_Probe **known_probes = push_array(process_arena, DMN_LNX_Probe *, DMN_LNX_ProbeType_Count); DMN_LNX_Probe **known_probes = push_array(process_arena, DMN_LNX_Probe *, DMN_LNX_ProbeType_Count);
{ {
DMN_LNX_ProbeList probes = {0}; DMN_LNX_ProbeList probes = {0};
int dl_fd = open((char *)dl_path.str, O_RDONLY); int dl_fd = open((char *)dl_path.str, O_RDONLY|O_CLOEXEC);
if(dl_fd >= 0) if(dl_fd >= 0)
{ {
probes = dmn_lnx_read_probes(process_arena, dl_fd, 0, auxv.base); probes = dmn_lnx_read_probes(process_arena, dl_fd, 0, auxv.base);
@@ -1797,9 +1797,9 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
DMN_LNX_Probe *p = &n->v; DMN_LNX_Probe *p = &n->v;
if(str8_match(p->provider, str8_lit("rtld"), 0)) if(str8_match(p->provider, str8_lit("rtld"), 0))
{ {
#define X(_N,_A,_S) if(str8_match(p->name, str8_lit(_S), 0)) { AssertAlways(p->args.count == _A); known_probes[DMN_LNX_ProbeType_##_N] = p; continue ; } #define X(_N,_A,_S) if(str8_match(p->name, str8_lit(_S), 0)) { AssertAlways(p->args.count == _A); known_probes[DMN_LNX_ProbeType_##_N] = p; continue ; }
DMN_LNX_Probe_XList DMN_LNX_Probe_XList
#undef X #undef X
} }
} }
} }
@@ -2251,7 +2251,7 @@ dmn_lnx_wait_for_events(Arena *arena, DMN_EventList *evts, pid_t tid, B32 wait_f
case DMN_EventKind_HandshakeComplete: case DMN_EventKind_HandshakeComplete:
case DMN_EventKind_LoadModule: case DMN_EventKind_LoadModule:
case DMN_EventKind_UnloadModule: case DMN_EventKind_UnloadModule:
{InvalidPath;}break; {InvalidPath;}break;
case DMN_EventKind_Trap: case DMN_EventKind_Trap:
case DMN_EventKind_Memory: case DMN_EventKind_Memory:
case DMN_EventKind_SetThreadName: case DMN_EventKind_SetThreadName:
+4 -4
View File
@@ -110,7 +110,7 @@ internal int
demon_lnx_open_memory_fd_for_pid(pid_t pid){ demon_lnx_open_memory_fd_for_pid(pid_t pid){
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
String8 memory_path = push_str8f(scratch.arena, "/proc/%i/mem", pid); String8 memory_path = push_str8f(scratch.arena, "/proc/%i/mem", pid);
int result = open((char*)memory_path.str, O_RDWR); int result = open((char*)memory_path.str, O_RDWR|O_CLOEXEC);
scratch_end(scratch); scratch_end(scratch);
return(result); return(result);
} }
@@ -126,7 +126,7 @@ demon_lnx_arch_from_pid(pid_t pid){
// handle to exe // handle to exe
int exe_fd = -1; int exe_fd = -1;
if (exe_path.size != 0){ if (exe_path.size != 0){
exe_fd = open((char*)exe_path.str, O_RDONLY); exe_fd = open((char*)exe_path.str, O_RDONLY|O_CLOEXEC);
} }
// elf identification // elf identification
@@ -199,7 +199,7 @@ demon_lnx_aux_from_pid(pid_t pid, Arch arch){
// open aux data // open aux data
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
String8 auxv_symbol_path = push_str8f(scratch.arena, "/proc/%d/auxv", pid); String8 auxv_symbol_path = push_str8f(scratch.arena, "/proc/%d/auxv", pid);
int aux_fd = open((char*)auxv_symbol_path.str, O_RDONLY); int aux_fd = open((char*)auxv_symbol_path.str, O_RDONLY|O_CLOEXEC);
// scan aux data // scan aux data
if (aux_fd >= 0){ if (aux_fd >= 0){
@@ -670,7 +670,7 @@ internal int
demon_lnx_open_maps(pid_t pid){ demon_lnx_open_maps(pid_t pid){
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
String8 path = push_str8f(scratch.arena, "/proc/%d/maps", pid); String8 path = push_str8f(scratch.arena, "/proc/%d/maps", pid);
int maps = open((char*)path.str, O_RDONLY); int maps = open((char*)path.str, O_RDONLY|O_CLOEXEC);
scratch_end(scratch); scratch_end(scratch);
return(maps); return(maps);
} }
+17 -3
View File
@@ -1977,12 +1977,26 @@ rdim_bake_path_tree_insert(RDIM_Arena *arena, RDIM_BakePathTree *tree, RDIM_Stri
RDI_U8 *opl = string.str + string.size; RDI_U8 *opl = string.str + string.size;
for(;ptr < opl;) for(;ptr < opl;)
{ {
// rjf: skip past slashes // rjf: skip past non-leading slashes
for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1); RDI_U32 leading_slash = 0;
if(ptr > string.str)
{
for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1);
}
else if(ptr < opl)
{
leading_slash = (*ptr == '/');
}
// rjf: save beginning of non-slash range // rjf: save beginning of path part
RDI_U8 *range_first = ptr; RDI_U8 *range_first = ptr;
// rjf: advance past leading slash
if(leading_slash)
{
ptr += 1;
}
// rjf: skip past non-slashes // rjf: skip past non-slashes
for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1); for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1);
+2 -1
View File
@@ -284,6 +284,7 @@ os_file_open(OS_AccessFlags flags, String8 path)
{ {
lnx_flags |= O_CREAT; lnx_flags |= O_CREAT;
} }
lnx_flags |= O_CLOEXEC;
int fd = open((char *)path_copy.str, lnx_flags, 0755); int fd = open((char *)path_copy.str, lnx_flags, 0755);
OS_Handle handle = {0}; OS_Handle handle = {0};
if(fd != -1) if(fd != -1)
@@ -652,7 +653,7 @@ os_shared_memory_alloc(U64 size, String8 name)
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
String8 name_copy = push_str8_copy(scratch.arena, name); String8 name_copy = push_str8_copy(scratch.arena, name);
int id = shm_open((char *)name_copy.str, O_RDWR | O_CREAT, 0666); int id = shm_open((char *)name_copy.str, O_RDWR|O_CREAT, 0666);
ftruncate(id, size); ftruncate(id, size);
OS_Handle result = {(U64)id}; OS_Handle result = {(U64)id};
scratch_end(scratch); scratch_end(scratch);