The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/1942

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Fix issue #1564 
To support limit syscall arguments, extend the version 2 file to the following format:

```
syscall_name default_action args:num [index,value,valueTwo,op]...
```

num: the number of the, the maximum of num is 6 (type uint, unsigned decimal integer)

For one arguments, [index,value,valueTwo,op]
index: the index for syscall arguments (type uint, unsigned decimal integer)
value: the value for syscall arguments  (type uint64, unsigned decimal integer)
valueTwo: the value for syscall arguments (type uint64, unsigned decimal integer)
op: the operator for syscall arguments (type string), a valid list of constants as of
libseccomp v2.3.2 is
SCMP_CMP_NE,SCMP_CMP_LE,SCMP_CMP_LE, SCMP_CMP_EQ, SCMP_CMP_GE,
SCMP_CMP_GT, SCMP_CMP_MASKED_EQ.
For example:

```
2
blacklist
reject_force_umount  # comment this to allow umount -f;  not recommended
[all]
kexec_load errno 1 args:3 [0,1,0,SCMP_CMP_LE][3,1,0,SCMP_CMP_GT][5,1,0,SCMP_CMP_MASKED_EQ]
open_by_handle_at errno 1
init_module errno 1
finit_module errno 1
delete_module errno 1
```
Signed-off-by: LiFeng <lifen...@huawei.com>
From cbea56a0bb5e38397168c66ea1ff86da1c8885bf Mon Sep 17 00:00:00 2001
From: LiFeng <lifen...@huawei.com>
Date: Thu, 23 Nov 2017 14:15:23 -0500
Subject: [PATCH] Fix issue #1564,add seccomp limit syscall argument
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

To support limit syscall arguments, extend the version 2 file to the following 
format:

```
syscall_name default_action args:num [index,value,valueTwo,op]...
```

num: the number of the, the maximum of num is 6。
for one arguments, [index,value,valueTwo,op]

index: the index for syscall arguments(type uint, unsigned decimal integer)
value: the value for syscall arguments (type uint64, unsigned decimal integer)
valueTwo: the value for syscall arguments (type uint64, unsigned decimal 
integer)
op: the operator for syscall arguments(string), a valid list of constants as of
libseccomp v2.3.2 is
SCMP_CMP_NE,SCMP_CMP_LE,SCMP_CMP_LE, SCMP_CMP_EQ, SCMP_CMP_GE,
SCMP_CMP_GT, SCMP_CMP_MASKED_EQ.
For example:

```
2
blacklist
reject_force_umount  # comment this to allow umount -f;  not recommended
[all]
kexec_load errno 1 args:3 
[0,1,0,SCMP_CMP_LE][3,1,0,SCMP_CMP_GT][5,1,0,SCMP_CMP_MASKED_EQ]
open_by_handle_at errno 1
init_module errno 1
finit_module errno 1
delete_module errno 1
```
Signed-off-by: LiFeng <lifen...@huawei.com>
---
 src/lxc/seccomp.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 191 insertions(+), 23 deletions(-)

diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c
index deacd1217..c7387e804 100644
--- a/src/lxc/seccomp.c
+++ b/src/lxc/seccomp.c
@@ -109,14 +109,13 @@ static const char *get_action_name(uint32_t action)
        }
 }
 
-static uint32_t get_and_clear_v2_action(char *line, uint32_t def_action)
+static uint32_t get_v2_action(char *line, uint32_t def_action)
 {
        char *p = strchr(line, ' ');
        uint32_t ret;
 
        if (!p)
                return def_action;
-       *p = '\0';
        p++;
        while (*p == ' ')
                p++;
@@ -129,6 +128,151 @@ static uint32_t get_and_clear_v2_action(char *line, 
uint32_t def_action)
        default: return ret;
        }
 }
+
+struct v2_rule_args {
+       uint32_t index;
+       uint64_t value;
+       uint64_t mask;
+       enum scmp_compare op;
+};
+
+struct seccomp_v2_rule {
+       uint32_t action;
+       uint32_t args_num;
+       struct v2_rule_args args_value[6];
+};
+
+static enum scmp_compare parse_v2_rule_op(char *s)
+{
+       enum scmp_compare ret;
+
+       if (strcmp(s, "SCMP_CMP_NE") == 0)
+               ret = SCMP_CMP_NE;
+       else if (strcmp(s, "SCMP_CMP_LT") == 0)
+               ret = SCMP_CMP_LT;
+       else if (strcmp(s, "SCMP_CMP_LE") == 0)
+               ret = SCMP_CMP_LE;
+       else if (strcmp(s, "SCMP_CMP_EQ") == 0)
+               ret = SCMP_CMP_EQ;
+       else if (strcmp(s, "SCMP_CMP_GE") == 0)
+               ret = SCMP_CMP_GE;
+       else if (strcmp(s, "SCMP_CMP_GT") == 0)
+               ret = SCMP_CMP_GT;
+       else if (strcmp(s, "SCMP_CMP_MASKED_EQ") == 0)
+               ret = SCMP_CMP_MASKED_EQ;
+       else
+               ret = -1;
+
+       return ret;
+}
+
+static uint32_t get_seccomp_arg_num(char *line)
+{
+       uint32_t num = -1;
+       char *tmp = NULL;
+       int ret = 0;
+
+       /*read optional args which follows the syscall*/
+       tmp = strstr(line, "args:");
+       if (!tmp) {
+               INFO("Seccomp rule include none args");
+               return 0;
+       }
+
+       ret = sscanf(tmp, "args:%u", &num);
+       if (ret != 1 || num > 6) {
+               INFO("Failed to interpret valid args number");
+               return -1;
+       }
+
+       return num;
+}
+
+static int get_seccomp_arg_value(char *key, struct v2_rule_args *rule_args)
+{
+       int ret = 0;
+       uint64_t value = 0;
+       uint64_t mask = 0;
+       enum scmp_compare op = 0;
+       uint32_t index = 0;
+       char s[30] = {0};
+       char *tmp = NULL;
+
+       memset(s, 0x00, sizeof(s));
+       tmp = strchr(key, '[');
+       if (!tmp) {
+               ERROR("Failed to interpret args.");
+               return -1;
+       }
+       ret = sscanf(tmp, "[%u,%llu,%llu,%30s", &index, (long long unsigned int 
*)&value, (long long unsigned int *)&mask, s);
+       if (ret != 4 || index >= 6) {
+               ERROR("Failed to interpret args value.");
+               return -1;
+       }
+
+       op = parse_v2_rule_op(s);
+       if (op == -1) {
+               ERROR("Failed to interpret args operator value.");
+               return -1;
+       }
+
+       rule_args->index = index;
+       rule_args->value = value;
+       rule_args->mask = mask;
+       rule_args->op = op;
+       return 0;
+}
+
+static int parse_v2_rules(char *line, uint32_t def_action, struct 
seccomp_v2_rule *rules)
+{
+       int ret = 0 ;
+       int i = 0;
+       char *tmp = NULL;
+       char *key = NULL;
+       char *saveptr = NULL;
+
+       tmp = strdup(line);
+       if (!tmp)
+               return -1;
+
+       /* read optional action which follows the syscall */
+       rules->action = get_v2_action(tmp, def_action);
+       if (rules->action == -1) {
+               ERROR("Failed to interpret action.");
+               ret = -1;
+               goto out;
+       }
+
+       rules->args_num = get_seccomp_arg_num(tmp);
+       if (rules->args_num == -1) {
+               ret = -1;
+               goto out;
+       }
+       if (rules->args_num == 0) {
+               ret = 0;
+               goto out;
+       }
+
+       for ((key = strtok_r(tmp, "]", &saveptr)), i = 0; key && i < 
rules->args_num; (key = strtok_r(NULL, "]", &saveptr)), i++) {
+               ret = get_seccomp_arg_value(key, &rules->args_value[i]);
+               if (ret) {
+                       ret = -1;
+                       goto out;
+               }
+       }
+       if (i != rules->args_num) {
+               ERROR("Failed to interpret sufficient parameters.");
+               ret = -1;
+               goto out;
+       }
+
+       ret = 0;
+out:
+       if (tmp)
+               free(tmp);
+       return ret;
+}
+
 #endif
 
 #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
@@ -260,9 +404,12 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, 
uint32_t default_policy_
 }
 
 bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx,
-                       uint32_t action)
+                       struct seccomp_v2_rule *rule)
 {
-       int nr, ret;
+       int nr, ret, i;
+       struct scmp_arg_cmp arg_cmp[6];
+
+       memset(arg_cmp, 0x00 ,sizeof(arg_cmp));
 
        ret = seccomp_arch_exist(ctx, arch);
        if (arch && ret != 0) {
@@ -272,6 +419,11 @@ bool do_resolve_add_rule(uint32_t arch, char *line, 
scmp_filter_ctx ctx,
                return false;
        }
 
+       /*get the syscall name*/
+       char *p = strchr(line, ' ');
+       if (p)
+               *p = '\0';
+
        if (strncmp(line, "reject_force_umount", 19) == 0) {
                INFO("Setting Seccomp rule to reject force umounts.");
                ret = seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EACCES), 
SCMP_SYS(umount2),
@@ -296,10 +448,24 @@ bool do_resolve_add_rule(uint32_t arch, char *line, 
scmp_filter_ctx ctx,
                WARN("This syscall will NOT be blacklisted.");
                return true;
        }
-       ret = seccomp_rule_add_exact(ctx, action, nr, 0);
+
+       for (i = 0; i < rule->args_num; i++) {
+               INFO("arg_cmp[%d]:SCMP_CMP(%u, %llu, %llu, %llu)", i,
+                     rule->args_value[i].index,
+                     (long long unsigned int)rule->args_value[i].op,
+                     (long long unsigned int)rule->args_value[i].mask,
+                     (long long unsigned int)rule->args_value[i].value);
+
+               if (SCMP_CMP_MASKED_EQ == rule->args_value[i].op)
+                       arg_cmp[i] = SCMP_CMP(rule->args_value[i].index, 
rule->args_value[i].op, rule->args_value[i].mask, rule->args_value[i].value);
+               else
+                       arg_cmp[i] = SCMP_CMP(rule->args_value[i].index, 
rule->args_value[i].op, rule->args_value[i].value);
+       }
+
+       ret = seccomp_rule_add_exact_array(ctx, rule->action, nr, 
rule->args_num, arg_cmp);
        if (ret < 0) {
                ERROR("Failed (%d) loading rule for %s (nr %d action %d(%s)): 
%s.",
-                     ret, line, nr, action, get_action_name(action), 
strerror(-ret));
+                     ret, line, nr, rule->action, 
get_action_name(rule->action), strerror(-ret));
                return false;
        }
        return true;
@@ -325,10 +491,11 @@ static int parse_config_v2(FILE *f, char *line, struct 
lxc_conf *conf)
        int ret;
        scmp_filter_ctx compat_ctx[2] = {NULL, NULL};
        bool blacklist = false;
-       uint32_t default_policy_action = -1, default_rule_action = -1, action;
+       uint32_t default_policy_action = -1, default_rule_action = -1;
        enum lxc_hostarch_t native_arch = get_hostarch(),
                            cur_rule_arch = native_arch;
        uint32_t compat_arch[2] = {SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE};
+       struct seccomp_v2_rule rule;
 
        if (strncmp(line, "blacklist", 9) == 0)
                blacklist = true;
@@ -580,19 +747,20 @@ static int parse_config_v2(FILE *f, char *line, struct 
lxc_conf *conf)
                if (cur_rule_arch == lxc_seccomp_arch_unknown)
                        continue;
 
+               memset(&rule, 0x00, sizeof(rule));
                /* read optional action which follows the syscall */
-               action = get_and_clear_v2_action(line, default_rule_action);
-               if (action == -1) {
-                       ERROR("Failed to interpret action.");
+               ret = parse_v2_rules(line, default_rule_action, &rule);
+               if (ret != 0) {
+                       ERROR("Failed to interpret seccomp rule.");
                        goto bad_rule;
                }
 
                if (cur_rule_arch == native_arch ||
                    cur_rule_arch == lxc_seccomp_arch_native ||
                    compat_arch[0] == SCMP_ARCH_NATIVE) {
-                       INFO("Adding native rule for %s action %d(%s).", line, 
action,
-                            get_action_name(action));
-                       if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, 
conf->seccomp_ctx, action))
+                       INFO("Adding native rule for %s action %d(%s).", line, 
rule.action,
+                            get_action_name(rule.action));
+                       if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, 
conf->seccomp_ctx, &rule))
                                goto bad_rule;
                }
                else if (cur_rule_arch != lxc_seccomp_arch_all) {
@@ -600,22 +768,22 @@ static int parse_config_v2(FILE *f, char *line, struct 
lxc_conf *conf)
                                cur_rule_arch == lxc_seccomp_arch_mips64n32 ||
                                cur_rule_arch == lxc_seccomp_arch_mipsel64n32 ? 
1 : 0;
 
-                       INFO("Adding compat-only rule for %s action %d(%s).", 
line, action,
-                            get_action_name(action));
-                       if (!do_resolve_add_rule(compat_arch[arch_index], line, 
compat_ctx[arch_index], action))
+                       INFO("Adding compat-only rule for %s action %d(%s).", 
line, rule.action,
+                            get_action_name(rule.action));
+                       if (!do_resolve_add_rule(compat_arch[arch_index], line, 
compat_ctx[arch_index], &rule))
                                goto bad_rule;
                }
                else {
-                       INFO("Adding native rule for %s action %d(%s).", line, 
action,
-                            get_action_name(action));
-                       if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, 
conf->seccomp_ctx, action))
+                       INFO("Adding native rule for %s action %d(%s).", line, 
rule.action,
+                            get_action_name(rule.action));
+                       if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, 
conf->seccomp_ctx, &rule))
                                goto bad_rule;
-                       INFO("Adding compat rule for %s action %d(%s).", line, 
action,
-                            get_action_name(action));
-                       if (!do_resolve_add_rule(compat_arch[0], line, 
compat_ctx[0], action))
+                       INFO("Adding compat rule for %s action %d(%s).", line, 
rule.action,
+                            get_action_name(rule.action));
+                       if (!do_resolve_add_rule(compat_arch[0], line, 
compat_ctx[0], &rule))
                                goto bad_rule;
                        if (compat_arch[1] != SCMP_ARCH_NATIVE &&
-                               !do_resolve_add_rule(compat_arch[1], line, 
compat_ctx[1], action))
+                               !do_resolve_add_rule(compat_arch[1], line, 
compat_ctx[1], &rule))
                                goto bad_rule;
                }
        }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to