selftests/bpf: Test file_pos field in bpf_sysctl ctx
authorAndrey Ignatov <rdna@fb.com>
Fri, 8 Mar 2019 23:25:02 +0000 (15:25 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 12 Apr 2019 20:54:59 +0000 (13:54 -0700)
Test access to file_pos field of bpf_sysctl context, both read (incl.
narrow read) and write.

  # ./test_sysctl
  ...
  Test case: ctx:file_pos sysctl:read read ok .. [PASS]
  Test case: ctx:file_pos sysctl:read read ok narrow .. [PASS]
  Test case: ctx:file_pos sysctl:read write ok .. [PASS]
  ...

Signed-off-by: Andrey Ignatov <rdna@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/test_sysctl.c

index 95437b72404ff9cbc15e83a5529223d6a2db87d8..43008aae32d3d7cae8f039befe5c4c5a4108f17c 100644 (file)
@@ -30,6 +30,7 @@ struct sysctl_test {
        const char *sysctl;
        int open_flags;
        const char *newval;
+       const char *oldval;
        enum {
                LOAD_REJECT,
                ATTACH_REJECT,
@@ -130,6 +131,64 @@ static struct sysctl_test tests[] = {
                .open_flags = O_RDONLY,
                .result = LOAD_REJECT,
        },
+       {
+               .descr = "ctx:file_pos sysctl:read read ok",
+               .insns = {
+                       /* If (file_pos == X) */
+                       BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
+                                   offsetof(struct bpf_sysctl, file_pos)),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 2),
+
+                       /* return ALLOW; */
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_JMP_A(1),
+
+                       /* else return DENY; */
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .attach_type = BPF_CGROUP_SYSCTL,
+               .sysctl = "kernel/ostype",
+               .open_flags = O_RDONLY,
+               .result = SUCCESS,
+       },
+       {
+               .descr = "ctx:file_pos sysctl:read read ok narrow",
+               .insns = {
+                       /* If (file_pos == X) */
+                       BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
+                                   offsetof(struct bpf_sysctl, file_pos)),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 2),
+
+                       /* return ALLOW; */
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_JMP_A(1),
+
+                       /* else return DENY; */
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .attach_type = BPF_CGROUP_SYSCTL,
+               .sysctl = "kernel/ostype",
+               .open_flags = O_RDONLY,
+               .result = SUCCESS,
+       },
+       {
+               .descr = "ctx:file_pos sysctl:read write ok",
+               .insns = {
+                       /* file_pos = X */
+                       BPF_MOV64_IMM(BPF_REG_0, 2),
+                       BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
+                                   offsetof(struct bpf_sysctl, file_pos)),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .attach_type = BPF_CGROUP_SYSCTL,
+               .sysctl = "kernel/ostype",
+               .open_flags = O_RDONLY,
+               .oldval = "nux\n",
+               .result = SUCCESS,
+       },
        {
                .descr = "sysctl_get_name sysctl_value:base ok",
                .insns = {
@@ -848,6 +907,11 @@ static int access_sysctl(const char *sysctl_path,
 
                if (read(fd, buf, sizeof(buf)) == -1)
                        goto err;
+               if (test->oldval &&
+                   strncmp(buf, test->oldval, strlen(test->oldval))) {
+                       log_err("Read value %s != %s", buf, test->oldval);
+                       goto err;
+               }
        } else if (test->open_flags == O_WRONLY) {
                if (!test->newval) {
                        log_err("New value for sysctl is not set");