diff options
author | mdempsky <mdempsky@chromium.org> | 2015-12-15 00:54:57 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-15 08:56:02 +0000 |
commit | 7a26cf2fd047825db18952e50678c30ad7711746 (patch) | |
tree | 56b01ca255586ca809ac682bafe91f7f030209b7 /sandbox | |
parent | 993e844de4724d946ef0e1aa395e429cfbcebe8d (diff) | |
download | chromium_src-7a26cf2fd047825db18952e50678c30ad7711746.zip chromium_src-7a26cf2fd047825db18952e50678c30ad7711746.tar.gz chromium_src-7a26cf2fd047825db18952e50678c30ad7711746.tar.bz2 |
bpf_dsl: implement CASES with C++11 variadic templates
I'm still holding out to be able to use initializer lists directly to
eliminate the helper macros, but at least using C++11 variadic
templates allows me to address some of the limitations of the current
approach. It also allows elimination of dependency on GCC extensions.
While here, convert Caser's paremeters to "const ResultExpr&" to be
consistent with the rest of the bpf_dsl.h.
Review URL: https://codereview.chromium.org/1528703002
Cr-Commit-Position: refs/heads/master@{#365211}
Diffstat (limited to 'sandbox')
-rw-r--r-- | sandbox/linux/bpf_dsl/bpf_dsl.h | 37 | ||||
-rw-r--r-- | sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc | 12 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc | 20 |
3 files changed, 29 insertions, 40 deletions
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl.h b/sandbox/linux/bpf_dsl/bpf_dsl.h index 917aeb4..2d3c9d4 100644 --- a/sandbox/linux/bpf_dsl/bpf_dsl.h +++ b/sandbox/linux/bpf_dsl/bpf_dsl.h @@ -212,15 +212,16 @@ class SANDBOX_EXPORT Caser { ~Caser() {} // Case adds a single-value "case" clause to the switch. - Caser<T> Case(T value, ResultExpr result) const; + Caser<T> Case(T value, const ResultExpr& result) const; // Cases adds a multiple-value "case" clause to the switch. // See also the SANDBOX_BPF_DSL_CASES macro below for a more idiomatic way // of using this function. - Caser<T> Cases(const std::vector<T>& values, ResultExpr result) const; + template <typename... Values> + Caser<T> CasesImpl(const ResultExpr& result, const Values&... values) const; // Terminate the switch with a "default" clause. - ResultExpr Default(ResultExpr result) const; + ResultExpr Default(const ResultExpr& result) const; private: Caser(const Arg<T>& arg, Elser elser) : arg_(arg), elser_(elser) {} @@ -239,17 +240,10 @@ class SANDBOX_EXPORT Caser { // use like: // Switch(arg).CASES((3, 5, 7), result)...; #define SANDBOX_BPF_DSL_CASES(values, result) \ - Cases(SANDBOX_BPF_DSL_CASES_HELPER values, result) - -// Helper macro to construct a std::vector from an initializer list. -// TODO(mdempsky): Convert to use C++11 initializer lists instead. -#define SANDBOX_BPF_DSL_CASES_HELPER(value, ...) \ - ({ \ - const __typeof__(value) bpf_dsl_cases_values[] = {value, __VA_ARGS__}; \ - std::vector<__typeof__(value)>( \ - bpf_dsl_cases_values, \ - bpf_dsl_cases_values + arraysize(bpf_dsl_cases_values)); \ - }) + CasesImpl(result, SANDBOX_BPF_DSL_CASES_HELPER values) + +// Helper macro to strip parentheses. +#define SANDBOX_BPF_DSL_CASES_HELPER(...) __VA_ARGS__ // ===================================================================== // Official API ends here. @@ -304,26 +298,23 @@ SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg) { } template <typename T> -Caser<T> Caser<T>::Case(T value, ResultExpr result) const { +Caser<T> Caser<T>::Case(T value, const ResultExpr& result) const { return SANDBOX_BPF_DSL_CASES((value), result); } template <typename T> -Caser<T> Caser<T>::Cases(const std::vector<T>& values, - ResultExpr result) const { +template <typename... Values> +Caser<T> Caser<T>::CasesImpl(const ResultExpr& result, + const Values&... values) const { // Theoretically we could evaluate arg_ just once and emit a more efficient // dispatch table, but for now we simply translate into an equivalent // If/ElseIf/Else chain. - BoolExpr test = BoolConst(false); - for (const T& value : values) { - test = AnyOf(test, arg_ == value); - } - return Caser<T>(arg_, elser_.ElseIf(test, result)); + return Caser<T>(arg_, elser_.ElseIf(AnyOf((arg_ == values)...), result)); } template <typename T> -ResultExpr Caser<T>::Default(ResultExpr result) const { +ResultExpr Caser<T>::Default(const ResultExpr& result) const { return elser_.Else(result); } diff --git a/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc index 005800a..a053773 100644 --- a/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc +++ b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc @@ -1728,13 +1728,11 @@ ResultExpr PthreadPolicyEquality::EvaluateSyscall(int sysno) const { CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM; const Arg<unsigned long> flags(0); - - // TODO(mdempsky): Rewrite to use Switch/CASES once it works. - return If(AnyOf(flags == kGlibcCloneMask, - flags == (kBaseAndroidCloneMask | CLONE_DETACHED), - flags == kBaseAndroidCloneMask), - Allow()) - .Else(Trap(PthreadTrapHandler, "Unknown mask")); + return Switch(flags) + .CASES((kGlibcCloneMask, (kBaseAndroidCloneMask | CLONE_DETACHED), + kBaseAndroidCloneMask), + Allow()) + .Default(Trap(PthreadTrapHandler, "Unknown mask")); } return Allow(); diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc index d6fd187..4b98366 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc @@ -264,7 +264,7 @@ ResultExpr RestrictGetSetpriority(pid_t target_pid) { const Arg<int> which(0); const Arg<int> who(1); return If(which == PRIO_PROCESS, - If(AnyOf(who == 0, who == target_pid), Allow()).Else(Error(EPERM))) + Switch(who).CASES((0, target_pid), Allow()).Default(Error(EPERM))) .Else(CrashSIGSYS()); } @@ -280,8 +280,9 @@ ResultExpr RestrictSchedTarget(pid_t target_pid, int sysno) { case __NR_sched_setparam: case __NR_sched_setscheduler: { const Arg<pid_t> pid(0); - return If(AnyOf(pid == 0, pid == target_pid), Allow()) - .Else(RewriteSchedSIGSYS()); + return Switch(pid) + .CASES((0, target_pid), Allow()) + .Default(RewriteSchedSIGSYS()); } default: NOTREACHED(); @@ -291,7 +292,7 @@ ResultExpr RestrictSchedTarget(pid_t target_pid, int sysno) { ResultExpr RestrictPrlimit64(pid_t target_pid) { const Arg<pid_t> pid(0); - return If(AnyOf(pid == 0, pid == target_pid), Allow()).Else(CrashSIGSYS()); + return Switch(pid).CASES((0, target_pid), Allow()).Default(CrashSIGSYS()); } ResultExpr RestrictGetrusage() { @@ -303,12 +304,11 @@ ResultExpr RestrictGetrusage() { ResultExpr RestrictClockID() { static_assert(4 == sizeof(clockid_t), "clockid_t is not 32bit"); const Arg<clockid_t> clockid(0); - return If(AnyOf(clockid == CLOCK_MONOTONIC, clockid == CLOCK_MONOTONIC_COARSE, - clockid == CLOCK_PROCESS_CPUTIME_ID, - clockid == CLOCK_REALTIME, clockid == CLOCK_REALTIME_COARSE, - clockid == CLOCK_THREAD_CPUTIME_ID), - Allow()) - .Else(CrashSIGSYS()); + return Switch(clockid) + .CASES((CLOCK_MONOTONIC, CLOCK_MONOTONIC_COARSE, CLOCK_PROCESS_CPUTIME_ID, + CLOCK_REALTIME, CLOCK_REALTIME_COARSE, CLOCK_THREAD_CPUTIME_ID), + Allow()) + .Default(CrashSIGSYS()); } } // namespace sandbox. |