Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFE: allow filtering on the caller's instruction pointer #113

Open
pcmoore opened this issue Mar 20, 2018 · 3 comments
Open

RFE: allow filtering on the caller's instruction pointer #113

pcmoore opened this issue Mar 20, 2018 · 3 comments

Comments

@pcmoore
Copy link
Member

pcmoore commented Mar 20, 2018

In addition to the syscall number and syscall arguments the kernel makes the caller's IP available to seccomp-bpf filters, we should consider exposing this in libseccomp.

See a related request on the libseccomp mailing list:

@pcmoore pcmoore added this to the v2.5 milestone Mar 20, 2018
@pcmoore
Copy link
Member Author

pcmoore commented Mar 20, 2018

However we decide to expose this, we should make sure we support memory address ranges.

@pcmoore
Copy link
Member Author

pcmoore commented Mar 20, 2018

There is a question if we want to make this check per-syscall, or global for the entire filter. I suspect global would most likely be good enough for the time being. It would definitely be easier from an implementation perspective.

@sporksmith
Copy link

sporksmith commented Jun 15, 2023

+1 as a user interested in this. I would love not to have to write and maintain this monstrosity :). Disclaimer: this may well still have lurking bugs; I just fixed a previous version that was implicitly only comparing the most significant 32 bits; whoops.

EDIT: this definitely is wrong at the boundaries, since the instruction pointer points to the instruction after the syscall instruction. Correctly emulating the 64-bit arithmetic using BPF 32-bit operations to subtract 2 with borrowing (or add 2 with carry) would make this even more fiddly.

EDIT again: Actually this is simple enough to fix by adding 2 to the allowed address range boundaries when constructing the filter.

EDIT yet again: Actually according to the man page, the instruction_pointer that the filter sees is the address of the syscall instruction. (But the instruction pointer you see in your sigsys signal handler is definitely the instruction after). TLDR this is fiddly and complicated to get right. Anyone coming across this, take this code snippet with a large grain of salt.

shadow/shadow@9d24577

        /* if (IP_high > text_end_high) trap; */
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
                 offsetof(struct seccomp_data, instruction_pointer) + sizeof(int32_t)),
        BPF_JUMP(BPF_JMP + BPF_JGT + BPF_K, text_end_high,
                 /*true-skip=*/0, /*false-skip=*/1),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP),

        /* if (IP_high == text_end_high && IP_low >= text_end_low) trap; */
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
                 offsetof(struct seccomp_data, instruction_pointer) + sizeof(int32_t)),
        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, text_end_high,
                 /*true-skip=*/0, /*false-skip=*/3),
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, instruction_pointer)),
        BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, text_end_low,
                 /*true-skip=*/0, /*false-skip=*/1),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP),

        /* if (IP_high < text_start_high) trap; */
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
                 offsetof(struct seccomp_data, instruction_pointer) + sizeof(int32_t)),
        BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, text_start_high, /*true-skip=*/1, /*false-skip=*/0),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP),

        /* if (IP_high == text_start_high && IP_low < text_start_low) trap; */
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
                 offsetof(struct seccomp_data, instruction_pointer) + sizeof(int32_t)),
        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, text_start_high,
                 /*true-skip=*/0, /*false-skip=*/3),
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, instruction_pointer)),
        BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, text_start_low,
                 /*true-skip=*/1, /*false-skip=*/0),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP),

        /* Allow  */
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants