summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authormdempsky <mdempsky@chromium.org>2015-12-15 00:54:57 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-15 08:56:02 +0000
commit7a26cf2fd047825db18952e50678c30ad7711746 (patch)
tree56b01ca255586ca809ac682bafe91f7f030209b7 /sandbox
parent993e844de4724d946ef0e1aa395e429cfbcebe8d (diff)
downloadchromium_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.h37
-rw-r--r--sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc12
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc20
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.