aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2017-08-02 18:00:40 -0400
committerKees Cook <keescook@chromium.org>2017-08-14 16:46:42 -0400
commitdeb4de8b31bc5bf21efb6ac31150a01a631cd647 (patch)
tree71ba73a95233cd80446c01105e5242598d22feb2
parentf3f6e30669c048f47d51ea59df9946a91f551c4c (diff)
seccomp: Provide matching filter for introspection
Both the upcoming logging improvements and changes to RET_KILL will need to know which filter a given seccomp return value originated from. In order to delay logic processing of result until after the seccomp loop, this adds a single pointer assignment on matches. This will allow both log and RET_KILL logic to work off the filter rather than doing more expensive tests inside the time-critical run_filters loop. Running tight cycles of getpid() with filters attached shows no measurable difference in speed. Suggested-by: Tyler Hicks <tyhicks@canonical.com> Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Tyler Hicks <tyhicks@canonical.com>
-rw-r--r--kernel/seccomp.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 98b59b5db90b..1f3347fc2605 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -171,10 +171,14 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
171/** 171/**
172 * seccomp_run_filters - evaluates all seccomp filters against @sd 172 * seccomp_run_filters - evaluates all seccomp filters against @sd
173 * @sd: optional seccomp data to be passed to filters 173 * @sd: optional seccomp data to be passed to filters
174 * @match: stores struct seccomp_filter that resulted in the return value,
175 * unless filter returned SECCOMP_RET_ALLOW, in which case it will
176 * be unchanged.
174 * 177 *
175 * Returns valid seccomp BPF response codes. 178 * Returns valid seccomp BPF response codes.
176 */ 179 */
177static u32 seccomp_run_filters(const struct seccomp_data *sd) 180static u32 seccomp_run_filters(const struct seccomp_data *sd,
181 struct seccomp_filter **match)
178{ 182{
179 struct seccomp_data sd_local; 183 struct seccomp_data sd_local;
180 u32 ret = SECCOMP_RET_ALLOW; 184 u32 ret = SECCOMP_RET_ALLOW;
@@ -198,8 +202,10 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd)
198 for (; f; f = f->prev) { 202 for (; f; f = f->prev) {
199 u32 cur_ret = BPF_PROG_RUN(f->prog, sd); 203 u32 cur_ret = BPF_PROG_RUN(f->prog, sd);
200 204
201 if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION)) 205 if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION)) {
202 ret = cur_ret; 206 ret = cur_ret;
207 *match = f;
208 }
203 } 209 }
204 return ret; 210 return ret;
205} 211}
@@ -566,6 +572,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
566 const bool recheck_after_trace) 572 const bool recheck_after_trace)
567{ 573{
568 u32 filter_ret, action; 574 u32 filter_ret, action;
575 struct seccomp_filter *match = NULL;
569 int data; 576 int data;
570 577
571 /* 578 /*
@@ -574,7 +581,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
574 */ 581 */
575 rmb(); 582 rmb();
576 583
577 filter_ret = seccomp_run_filters(sd); 584 filter_ret = seccomp_run_filters(sd, &match);
578 data = filter_ret & SECCOMP_RET_DATA; 585 data = filter_ret & SECCOMP_RET_DATA;
579 action = filter_ret & SECCOMP_RET_ACTION; 586 action = filter_ret & SECCOMP_RET_ACTION;
580 587
@@ -638,6 +645,11 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
638 return 0; 645 return 0;
639 646
640 case SECCOMP_RET_ALLOW: 647 case SECCOMP_RET_ALLOW:
648 /*
649 * Note that the "match" filter will always be NULL for
650 * this action since SECCOMP_RET_ALLOW is the starting
651 * state in seccomp_run_filters().
652 */
641 return 0; 653 return 0;
642 654
643 case SECCOMP_RET_KILL: 655 case SECCOMP_RET_KILL: