- 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;
|
} io_req;
|
||||||
|
|
||||||
typedef i32 io_error;
|
typedef i32 io_error;
|
||||||
enum {
|
enum _io_error {
|
||||||
IO_OK = 0,
|
IO_OK = 0,
|
||||||
IO_ERR_UNKNOWN,
|
IO_ERR_UNKNOWN,
|
||||||
IO_ERR_OP, // unsupported operation
|
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(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 file_handle file_open_relative(file_handle base, str8 path, file_open_flags flags);
|
||||||
MP_API void file_close(file_handle file);
|
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);
|
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)
|
void file_close(file_handle file)
|
||||||
{
|
{
|
||||||
io_req req = {.op = IO_OP_CLOSE,
|
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_push(scratch.arena, &sep, STR8("/"));
|
||||||
str8_list pathElements = str8_split(scratch.arena, path, sep);
|
str8_list pathElements = str8_split(scratch.arena, path, sep);
|
||||||
|
|
||||||
result.fd = dirFd;
|
result.fd = dup(dirFd);
|
||||||
if(result.fd < 0)
|
if(result.fd < 0)
|
||||||
{
|
{
|
||||||
result.error = io_convert_errno(errno);
|
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);
|
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)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
mem_arena* arena = mem_scratch();
|
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_read(arena, path, test_string)) { return(-1); }
|
||||||
if(test_stat_size(path, test_string.len)) { return(-1); }
|
if(test_stat_size(path, test_string.len)) { return(-1); }
|
||||||
if(test_stat_type(arena, dataDir)) { return(-1); }
|
if(test_stat_type(arena, dataDir)) { return(-1); }
|
||||||
|
if(test_jail()) { return(-1); }
|
||||||
|
|
||||||
|
remove("./test.txt");
|
||||||
|
|
||||||
log_info("OK\n");
|
log_info("OK\n");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue