Skip to content

Commit 9d15f51

Browse files
committed
seccomp: apply all argument conditions
remove the arbitrary limit of 6 conditions. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
1 parent 9dff03e commit 9d15f51

3 files changed

Lines changed: 87 additions & 25 deletions

File tree

src/libcrun/seccomp.c

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -813,54 +813,65 @@ libcrun_generate_seccomp (struct libcrun_seccomp_gen_ctx_s *gen_ctx, libcrun_err
813813
else
814814
{
815815
size_t k;
816-
struct scmp_arg_cmp arg_cmp[6];
817816
bool multiple_args = false;
818817
uint32_t count[6] = {};
819818

820-
for (k = 0; k < seccomp->syscalls[i]->args_len && k < 6; k++)
819+
for (k = 0; k < seccomp->syscalls[i]->args_len; k++)
821820
{
822821
uint32_t index;
823822

824823
index = seccomp->syscalls[i]->args[k]->index;
825824
if (index >= 6)
826-
return crun_make_error (err, 0, "invalid seccomp index `%zu`", i);
825+
return crun_make_error (err, 0, "invalid seccomp index `%u`", index);
827826

828827
count[index]++;
829828
if (count[index] > 1)
830-
{
831-
multiple_args = true;
832-
break;
833-
}
829+
multiple_args = true;
834830
}
835831

836-
for (k = 0; k < seccomp->syscalls[i]->args_len && k < 6; k++)
832+
/* If multiple rules refer to the same argument, treat the rules are in OR. */
833+
if (multiple_args)
837834
{
838-
char *op = seccomp->syscalls[i]->args[k]->op;
835+
size_t r;
839836

840-
arg_cmp[k].arg = seccomp->syscalls[i]->args[k]->index;
841-
ret = get_seccomp_operator (op, &(arg_cmp[k].op), err);
842-
if (UNLIKELY (ret < 0))
843-
return ret;
844-
arg_cmp[k].datum_a = seccomp->syscalls[i]->args[k]->value;
845-
arg_cmp[k].datum_b = seccomp->syscalls[i]->args[k]->value_two;
846-
}
837+
for (r = 0; r < seccomp->syscalls[i]->args_len; r++)
838+
{
839+
struct scmp_arg_cmp arg_cmp;
840+
char *op = seccomp->syscalls[i]->args[r]->op;
847841

848-
if (! multiple_args)
849-
{
850-
ret = seccomp_rule_add_array (ctx, action, syscall, k, arg_cmp);
851-
if (UNLIKELY (ret < 0))
852-
return crun_make_error (err, -ret, "seccomp_rule_add_array");
842+
arg_cmp.arg = seccomp->syscalls[i]->args[r]->index;
843+
ret = get_seccomp_operator (op, &arg_cmp.op, err);
844+
if (UNLIKELY (ret < 0))
845+
return ret;
846+
arg_cmp.datum_a = seccomp->syscalls[i]->args[r]->value;
847+
arg_cmp.datum_b = seccomp->syscalls[i]->args[r]->value_two;
848+
849+
ret = seccomp_rule_add_array (ctx, action, syscall, 1, &arg_cmp);
850+
if (UNLIKELY (ret < 0))
851+
return crun_make_error (err, -ret, "seccomp_rule_add_array");
852+
}
853853
}
854854
else
855855
{
856-
size_t r;
856+
/* No index is repeated, so there are at most 6 distinct arguments. */
857+
const size_t args_len = seccomp->syscalls[i]->args_len;
858+
struct scmp_arg_cmp arg_cmp[6];
857859

858-
for (r = 0; r < k; r++)
860+
for (k = 0; k < args_len; k++)
859861
{
860-
ret = seccomp_rule_add_array (ctx, action, syscall, 1, &arg_cmp[r]);
862+
char *op = seccomp->syscalls[i]->args[k]->op;
863+
864+
arg_cmp[k].arg = seccomp->syscalls[i]->args[k]->index;
865+
ret = get_seccomp_operator (op, &(arg_cmp[k].op), err);
861866
if (UNLIKELY (ret < 0))
862-
return crun_make_error (err, -ret, "seccomp_rule_add_array");
867+
return ret;
868+
arg_cmp[k].datum_a = seccomp->syscalls[i]->args[k]->value;
869+
arg_cmp[k].datum_b = seccomp->syscalls[i]->args[k]->value_two;
863870
}
871+
872+
ret = seccomp_rule_add_array (ctx, action, syscall, args_len, arg_cmp);
873+
if (UNLIKELY (ret < 0))
874+
return crun_make_error (err, -ret, "seccomp_rule_add_array");
864875
}
865876
}
866877
}

tests/init.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,20 @@ main (int argc, char **argv)
501501
exit (0);
502502
}
503503

504+
if (strcmp (argv[1], "socket") == 0)
505+
{
506+
int fd;
507+
508+
if (argc < 3)
509+
error (EXIT_FAILURE, 0, "'socket' requires an argument");
510+
511+
fd = socket (atoi (argv[2]), SOCK_DGRAM, 0);
512+
if (fd < 0)
513+
error (EXIT_FAILURE, errno, "socket");
514+
close (fd);
515+
return 0;
516+
}
517+
504518
if (strcmp (argv[1], "printenv") == 0)
505519
{
506520
const char *value;

tests/test_seccomp.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,42 @@ def test_seccomp_syscall_args():
275275
return -1
276276

277277

278+
def test_seccomp_more_than_six_syscall_args():
279+
conf = base_config()
280+
add_all_namespaces(conf)
281+
282+
conf['linux']['seccomp'] = {
283+
'defaultAction': 'SCMP_ACT_ALLOW',
284+
'syscalls': [
285+
{
286+
'names': ['socket'],
287+
'action': 'SCMP_ACT_ERRNO',
288+
'errnoRet': 1,
289+
'args': [
290+
{'index': 0, 'value': value, 'op': 'SCMP_CMP_EQ'}
291+
for value in [0, 1, 3, 4, 5, 6, 7, 2]
292+
]
293+
}
294+
]
295+
}
296+
297+
conf['process']['args'] = ['/init', 'socket', '2']
298+
299+
try:
300+
run_and_get_output(conf)
301+
except subprocess.CalledProcessError as e:
302+
if e.output is not None and b'Operation not permitted' in e.output:
303+
return 0
304+
logger.info("socket was not blocked by seccomp")
305+
return -1
306+
except Exception as e:
307+
logger.info("Exception: %s", e)
308+
return -1
309+
310+
logger.info("socket was not blocked by seccomp")
311+
return -1
312+
313+
278314
def test_seccomp_multiple_syscalls():
279315
"""Test seccomp with multiple syscalls in one rule."""
280316
conf = base_config()
@@ -624,6 +660,7 @@ def test_seccomp_invalid_flag():
624660
"seccomp-log-action": test_seccomp_log_action,
625661
"seccomp-kill-action": test_seccomp_kill_action,
626662
"seccomp-syscall-args": test_seccomp_syscall_args,
663+
"seccomp-more-than-six-syscall-args": test_seccomp_more_than_six_syscall_args,
627664
"seccomp-multiple-syscalls": test_seccomp_multiple_syscalls,
628665
"seccomp-errno-default": test_seccomp_errno_default,
629666
"seccomp-comparison-ops": test_seccomp_comparison_ops,

0 commit comments

Comments
 (0)