Skip to content

Commit

Permalink
Add -X option: --deny-syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
Moe-hacker committed Jan 13, 2025
1 parent 5aa5fed commit 620e61b
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 83 deletions.
1 change: 1 addition & 0 deletions Changelog
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# v3.9:
* Support part of bsd-style command-line usage.
* Fix built-in seccomp profile.
* Add `-X` option: `--deny-syscall`.
# v3.8:
* Support more platforms, currently supports: arm64, armv7, armhf, riscv64, i386, loong64, s390x, ppc64le and x86_64.
* Improve rootless container support.
Expand Down
4 changes: 2 additions & 2 deletions src/chroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ void ruri_run_chroot_container(struct RURI_CONTAINER *_Nonnull container)
mk_char_devs(container);
}
// Set up Seccomp BPF.
if (container->enable_seccomp) {
if (container->enable_default_seccomp || container->seccomp_denied_syscall[0] != NULL) {
ruri_setup_seccomp(container);
}
// Drop caps.
Expand Down Expand Up @@ -754,7 +754,7 @@ void ruri_run_rootless_chroot_container(struct RURI_CONTAINER *_Nonnull containe
setup_binfmt_misc(container);
}
// Set up Seccomp BPF.
if (container->enable_seccomp) {
if (container->enable_default_seccomp || container->seccomp_denied_syscall[0] != NULL) {
ruri_setup_seccomp(container);
}
// Drop caps.
Expand Down
28 changes: 22 additions & 6 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void ruri_init_config(struct RURI_CONTAINER *_Nonnull container)
}
cap_value_t nullcaplist[2] = { RURI_INIT_VALUE };
ruri_build_caplist(container->drop_caplist, false, nullcaplist, nullcaplist);
container->enable_seccomp = false;
container->enable_default_seccomp = false;
container->no_new_privs = false;
container->no_warnings = false;
container->enable_unshare = false;
Expand Down Expand Up @@ -73,6 +73,7 @@ void ruri_init_config(struct RURI_CONTAINER *_Nonnull container)
container->hidepid = RURI_INIT_VALUE;
container->timens_realtime_offset = 0;
container->timens_monotonic_offset = 0;
container->seccomp_denied_syscall[0] = NULL;
// Use the time now for container_id.
time_t tm = time(NULL);
// We need a int value for container_id, so use long%86400.
Expand Down Expand Up @@ -171,10 +172,10 @@ char *ruri_container_info_to_k2v(const struct RURI_CONTAINER *_Nonnull container
ret = k2v_add_comment(ret, "Default is true.");
ret = k2v_add_config(bool, ret, "use_rurienv", container->use_rurienv);
ret = k2v_add_newline(ret);
// enable_seccomp.
// enable_default_seccomp.
ret = k2v_add_comment(ret, "Enable built-in seccomp profile.");
ret = k2v_add_comment(ret, "Default is false.");
ret = k2v_add_config(bool, ret, "enable_seccomp", container->enable_seccomp);
ret = k2v_add_config(bool, ret, "enable_seccomp", container->enable_default_seccomp);
ret = k2v_add_newline(ret);
// hidepid.
ret = k2v_add_comment(ret, "Hide pid in /proc.");
Expand Down Expand Up @@ -318,6 +319,18 @@ char *ruri_container_info_to_k2v(const struct RURI_CONTAINER *_Nonnull container
ret = k2v_add_config(long, ret, "timens_monotonic_offset", container->timens_monotonic_offset);
ret = k2v_add_config(long, ret, "timens_realtime_offset", container->timens_realtime_offset);
ret = k2v_add_newline(ret);
// seccomp_denied_syscall.
for (int i = 0; true; i++) {
if (container->seccomp_denied_syscall[i] == NULL) {
len = i;
break;
}
}
ret = k2v_add_comment(ret, "Denied syscalls, use seccomp.");
ret = k2v_add_comment(ret, "For example, [\"syscall1\",\"syscall2\"] is valid.");
ret = k2v_add_comment(ret, "Set it to empty to disable.");
ret = k2v_add_config(char_array, ret, "deny_syscall", container->seccomp_denied_syscall, len);
ret = k2v_add_newline(ret);
return ret;
}
void ruri_read_config(struct RURI_CONTAINER *_Nonnull container, const char *_Nonnull path)
Expand Down Expand Up @@ -363,7 +376,7 @@ void ruri_read_config(struct RURI_CONTAINER *_Nonnull container, const char *_No
// Get no_new_privs.
container->no_new_privs = k2v_get_key(bool, "no_new_privs", buf);
// Get enable_seccomp.
container->enable_seccomp = k2v_get_key(bool, "enable_seccomp", buf);
container->enable_default_seccomp = k2v_get_key(bool, "enable_seccomp", buf);
// Get container_dir.
container->container_dir = k2v_get_key(char, "container_dir", buf);
// Get qemu_path.
Expand Down Expand Up @@ -433,6 +446,9 @@ void ruri_read_config(struct RURI_CONTAINER *_Nonnull container, const char *_No
if (charlen % 3 != 0) {
ruri_error("{red}Invalid char_devs format\n{clear}");
}
// Get seccomp_denied_syscall.
int seccomplen = k2v_get_key(char_array, "deny_syscall", buf, container->seccomp_denied_syscall, RURI_MAX_SECCOMP_DENIED_SYSCALL);
container->seccomp_denied_syscall[seccomplen] = NULL;
// Get time offset.
container->timens_realtime_offset = k2v_get_key(long, "timens_realtime_offset", buf);
container->timens_monotonic_offset = k2v_get_key(long, "timens_monotonic_offset", buf);
Expand Down Expand Up @@ -552,9 +568,9 @@ void ruri_correct_config(const char *_Nonnull path)
}
if (!have_key("enable_seccomp", buf)) {
ruri_warning("{green}No key enable_seccomp found, set to false\n{clear}");
container.enable_seccomp = false;
container.enable_default_seccomp = false;
} else {
container.enable_seccomp = k2v_get_key(bool, "enable_seccomp", buf);
container.enable_default_seccomp = k2v_get_key(bool, "enable_seccomp", buf);
}
if (!have_key("no_warnings", buf)) {
ruri_warning("{green}No key no_warnings found, set to false\n{clear}");
Expand Down
5 changes: 4 additions & 1 deletion src/include/ruri.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
#define RURI_MAX_ENVS (512 * 2)
#define RURI_MAX_MOUNTPOINTS (512 * 2)
#define RURI_MAX_CHAR_DEVS (128 * 3)
#define RURI_MAX_SECCOMP_DENIED_SYSCALL (2048)
// Include other headers.
#include "elf-magic.h"
#include "version.h"
Expand All @@ -126,7 +127,7 @@ struct RURI_CONTAINER {
// Set NO_NEW_PRIV bit.
bool no_new_privs;
// Enable built-in seccomp profile.
bool enable_seccomp;
bool enable_default_seccomp;
// Do not show warnings.
bool no_warnings;
// Unshare container.
Expand Down Expand Up @@ -176,6 +177,8 @@ struct RURI_CONTAINER {
// Timens offset.
time_t timens_realtime_offset;
time_t timens_monotonic_offset;
// Denied syscalls.
char *_Nonnull seccomp_denied_syscall[RURI_MAX_SECCOMP_DENIED_SYSCALL];
};
// For ruri_get_magic().
#define ruri_magicof(x) (x##_magic)
Expand Down
1 change: 1 addition & 0 deletions src/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ void ruri_show_helps(void)
cprintf("{base} -T, --timens-offset [monotonic] [realtime]...: Set time offset for timens(*12)\n");
cprintf("{base} -b, --background ............................: Fork to background\n");
cprintf("{base} -L, --logfile [file] ........................: Set log file of -b option\n");
cprintf("{base} -X, --deny-syscall [syscall] ................: Deny syscall, use seccomp\n");
cprintf("\n");
cprintf("{base}Note:\n");
cprintf("{base}(*1) : Will not work for unshare container without PID ns support\n");
Expand Down
48 changes: 46 additions & 2 deletions src/ruri.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ static void parse_args(int argc, char **_Nonnull argv, struct RURI_CONTAINER *_N
}
// Enable built-in seccomp profile.
else if (strcmp(argv[index], "-s") == 0 || strcmp(argv[index], "--enable-seccomp") == 0) {
container->enable_seccomp = true;
container->enable_default_seccomp = true;
}
// Run unshare container.
else if (strcmp(argv[index], "-u") == 0 || strcmp(argv[index], "--unshare") == 0) {
Expand Down Expand Up @@ -500,6 +500,27 @@ static void parse_args(int argc, char **_Nonnull argv, struct RURI_CONTAINER *_N
ruri_error("{red}Error: unknown char devices QwQ\n");
}
}
// Deny syscall.
else if (strcmp(argv[index], "-X") == 0 || strcmp(argv[index], "--deny-syscall") == 0) {
index++;
if (argv[index] != NULL) {
if (seccomp_syscall_resolve_name(argv[index]) == __NR_SCMP_ERROR) {
ruri_error("{red}Error: unknown syscall `%s`\nQwQ{clear}\n", argv[index]);
}
for (int i = 0; i < RURI_MAX_SECCOMP_DENIED_SYSCALL; i++) {
if (container->seccomp_denied_syscall[i] == NULL) {
container->seccomp_denied_syscall[i] = strdup(argv[index]);
container->seccomp_denied_syscall[i + 1] = NULL;
break;
}
if (i == (RURI_MAX_SECCOMP_DENIED_SYSCALL - 1)) {
ruri_error("{red}Too many syscalls QwQ\n");
}
}
} else {
ruri_error("{red}Error: unknown syscall QwQ\n");
}
}
// Time ns offset.
else if (strcmp(argv[index], "-T") == 0 || strcmp(argv[index], "--timens-offset") == 0) {
index++;
Expand Down Expand Up @@ -621,7 +642,7 @@ static void parse_args(int argc, char **_Nonnull argv, struct RURI_CONTAINER *_N
container->use_rurienv = false;
break;
case 's':
container->enable_seccomp = true;
container->enable_default_seccomp = true;
break;
case 'p':
privileged = true;
Expand Down Expand Up @@ -962,6 +983,29 @@ static void parse_args(int argc, char **_Nonnull argv, struct RURI_CONTAINER *_N
ruri_error("Invalid argument %s\n", argv[index]);
}
break;
case 'X':
if (i == (strlen(argv[index]) - 1)) {
if (index == argc - 1) {
ruri_error("{red}Please specify the syscall\n{clear}");
}
index++;
if (seccomp_syscall_resolve_name(argv[index]) == __NR_SCMP_ERROR) {
ruri_error("{red}Error: unknown syscall `%s`\nQwQ{clear}\n", argv[index]);
}
for (int i = 0; i < RURI_MAX_SECCOMP_DENIED_SYSCALL; i++) {
if (container->seccomp_denied_syscall[i] == NULL) {
container->seccomp_denied_syscall[i] = strdup(argv[index]);
container->seccomp_denied_syscall[i + 1] = NULL;
break;
}
if (i == (RURI_MAX_SECCOMP_DENIED_SYSCALL - 1)) {
ruri_error("{red}Too many syscalls QwQ\n");
}
}
} else {
ruri_error("Invalid argument %s\n", argv[index]);
}
break;
default:
ruri_error("Invalid argument %s\n", argv[index]);
}
Expand Down
17 changes: 15 additions & 2 deletions src/rurienv.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,17 @@ static char *build_container_info(const struct RURI_CONTAINER *_Nonnull containe
ret = k2v_add_config(bool, ret, "no_new_privs", container->no_new_privs);
// enable_seccomp.
ret = k2v_add_comment(ret, "Enable built-in seccomp profile.");
ret = k2v_add_config(bool, ret, "enable_seccomp", container->enable_seccomp);
ret = k2v_add_config(bool, ret, "enable_seccomp", container->enable_default_seccomp);
// seccomp_denied_syscall.
for (int i = 0; true; i++) {
if (container->seccomp_denied_syscall[i] == NULL) {
len = i;
break;
}
}
ret = k2v_add_comment(ret, "Denied syscalls, use seccomp.");
ret = k2v_add_config(char_array, ret, "deny_syscall", container->seccomp_denied_syscall, len);
ret = k2v_add_newline(ret);
// ns_pid.
ret = k2v_add_comment(ret, "PID owning unshare namespace.");
ret = k2v_add_config(int, ret, "ns_pid", container->ns_pid);
Expand Down Expand Up @@ -363,7 +373,10 @@ struct RURI_CONTAINER *ruri_read_info(struct RURI_CONTAINER *_Nullable container
// Get no_new_privs.
container->no_new_privs = k2v_get_key(bool, "no_new_privs", buf);
// Get enable_seccomp.
container->enable_seccomp = k2v_get_key(bool, "enable_seccomp", buf);
container->enable_default_seccomp = k2v_get_key(bool, "enable_seccomp", buf);
// Get seccomp_denied_syscall.
int seccomplen = k2v_get_key(char_array, "deny_syscall", buf, container->seccomp_denied_syscall, RURI_MAX_SECCOMP_DENIED_SYSCALL);
container->seccomp_denied_syscall[seccomplen] = NULL;
// Get ns_pid.
container->ns_pid = k2v_get_key(int, "ns_pid", buf);
ruri_log("{base}ns_pid: %d\n", container->ns_pid);
Expand Down
Loading

0 comments on commit 620e61b

Please sign in to comment.