- Added tests for sandboxing file io with file_open_at() and FILE_OPEN_RESTRICT
- Fixed bug in io_open_restrict() that closed the dir file descriptor, making it impossible to use it in subsequent calls.
This commit is contained in:
parent
b2d2d2a587
commit
b147aed85c
|
@ -74,7 +74,7 @@ typedef struct io_req
|
|||
} io_req;
|
||||
|
||||
typedef i32 io_error;
|
||||
enum {
|
||||
enum _io_error {
|
||||
IO_OK = 0,
|
||||
IO_ERR_UNKNOWN,
|
||||
IO_ERR_OP, // unsupported operation
|
||||
|
@ -127,6 +127,7 @@ MP_API io_cmp io_wait_single_req(io_req* req);
|
|||
//----------------------------------------------------------------
|
||||
|
||||
MP_API file_handle file_open(str8 path, file_open_flags flags);
|
||||
MP_API file_handle file_open_at(file_handle dir, str8 path, file_open_flags flags);
|
||||
MP_API file_handle file_open_relative(file_handle base, str8 path, file_open_flags flags);
|
||||
MP_API void file_close(file_handle file);
|
||||
|
||||
|
|
|
@ -25,6 +25,18 @@ file_handle file_open(str8 path, file_open_flags flags)
|
|||
return(cmp.handle);
|
||||
}
|
||||
|
||||
file_handle file_open_at(file_handle dir, str8 path, file_open_flags flags)
|
||||
{
|
||||
io_req req = {.op = IO_OP_OPEN_AT,
|
||||
.handle = dir,
|
||||
.size = path.len,
|
||||
.buffer = path.ptr,
|
||||
.openFlags = flags};
|
||||
|
||||
io_cmp cmp = io_wait_single_req(&req);
|
||||
return(cmp.handle);
|
||||
}
|
||||
|
||||
void file_close(file_handle file)
|
||||
{
|
||||
io_req req = {.op = IO_OP_CLOSE,
|
||||
|
|
|
@ -168,7 +168,7 @@ io_open_restrict_result io_open_restrict(int dirFd, str8 path, int flags, mode_t
|
|||
str8_list_push(scratch.arena, &sep, STR8("/"));
|
||||
str8_list pathElements = str8_split(scratch.arena, path, sep);
|
||||
|
||||
result.fd = dirFd;
|
||||
result.fd = dup(dirFd);
|
||||
if(result.fd < 0)
|
||||
{
|
||||
result.error = io_convert_errno(errno);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
..
|
|
@ -0,0 +1 @@
|
|||
Hello, world!
|
|
@ -1 +0,0 @@
|
|||
regular.txt
|
|
@ -0,0 +1 @@
|
|||
regular
|
|
@ -186,6 +186,62 @@ int test_stat_type(mem_arena* arena, str8 dataDir)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int test_jail()
|
||||
{
|
||||
log_info("test jail\n");
|
||||
|
||||
file_handle jail = file_open(STR8("./data/jail"), FILE_OPEN_READ);
|
||||
if(file_last_error(jail))
|
||||
{
|
||||
log_error("Can't open jail directory\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// Check legitimates open
|
||||
file_handle f = file_open_at(jail, STR8("/test.txt"), FILE_OPEN_READ | FILE_OPEN_RESTRICT);
|
||||
if(file_last_error(f) != IO_OK)
|
||||
{
|
||||
log_error("Can't open jail/test.txt\n");
|
||||
return(-1);
|
||||
}
|
||||
file_close(f);
|
||||
|
||||
f = file_open_at(jail, STR8("/dir1/../test.txt"), FILE_OPEN_READ | FILE_OPEN_RESTRICT);
|
||||
if(file_last_error(f) != IO_OK)
|
||||
{
|
||||
log_error("Can't open jail/dir1/../test.txt\n");
|
||||
return(-1);
|
||||
}
|
||||
file_close(f);
|
||||
|
||||
// Check escapes
|
||||
f = file_open_at(jail, STR8(".."), FILE_OPEN_READ | FILE_OPEN_RESTRICT);
|
||||
if(file_last_error(f) != IO_ERR_WALKOUT)
|
||||
{
|
||||
log_error("Escaped jail with relative path ..\n");
|
||||
return(-1);
|
||||
}
|
||||
file_close(f);
|
||||
|
||||
f = file_open_at(jail, STR8(".."), FILE_OPEN_READ | FILE_OPEN_RESTRICT);
|
||||
if(file_last_error(f) != IO_ERR_WALKOUT)
|
||||
{
|
||||
log_error("Escaped jail with relative path dir1/../..\n");
|
||||
return(-1);
|
||||
}
|
||||
file_close(f);
|
||||
|
||||
f = file_open_at(jail, STR8("/escape"), FILE_OPEN_READ | FILE_OPEN_RESTRICT);
|
||||
if(file_last_error(f) != IO_ERR_WALKOUT)
|
||||
{
|
||||
log_error("Escaped jail with symlink\n");
|
||||
return(-1);
|
||||
}
|
||||
file_close(f);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
mem_arena* arena = mem_scratch();
|
||||
|
@ -199,6 +255,9 @@ int main(int argc, char** argv)
|
|||
if(test_read(arena, path, test_string)) { return(-1); }
|
||||
if(test_stat_size(path, test_string.len)) { return(-1); }
|
||||
if(test_stat_type(arena, dataDir)) { return(-1); }
|
||||
if(test_jail()) { return(-1); }
|
||||
|
||||
remove("./test.txt");
|
||||
|
||||
log_info("OK\n");
|
||||
|
||||
|
|
Loading…
Reference in New Issue