Index: sandbox/linux/seccomp-bpf/verifier.cc |
diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/seccomp-bpf/verifier.cc |
index 40a1aa20be7a8fcd196a7e89e3f72128c6aeb9ee..d40a79a9d2f2581353aae4901d2a870102561234 100644 |
--- a/sandbox/linux/seccomp-bpf/verifier.cc |
+++ b/sandbox/linux/seccomp-bpf/verifier.cc |
@@ -42,13 +42,48 @@ bool Verifier::VerifyBPF(const std::vector<struct sock_filter>& program, |
#endif |
#endif |
ErrorCode code = evaluate_syscall(sysnum, aux); |
- uint32_t computed_ret = EvaluateBPF(program, data, err); |
+ if (!VerifyErrorCode(program, &data, code, err)) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+bool Verifier::VerifyErrorCode(const std::vector<struct sock_filter>& program, |
+ struct arch_seccomp_data *data, |
+ const ErrorCode& code, const char **err) { |
+ if (code.error_type_ == ErrorCode::ET_SIMPLE || |
+ code.error_type_ == ErrorCode::ET_TRAP) { |
+ uint32_t computed_ret = EvaluateBPF(program, *data, err); |
if (*err) { |
return false; |
} else if (computed_ret != code.err()) { |
*err = "Exit code from BPF program doesn't match"; |
return false; |
} |
+ } else if (code.error_type_ == ErrorCode::ET_COND) { |
+ if (code.argno_ < 0 || code.argno_ >= 6) { |
+ *err = "Invalid argument number in error code"; |
+ return false; |
+ } |
+ switch (code.op_) { |
+ case ErrorCode::OP_EQUAL: |
+ data->args[code.argno_] = code.value_; |
+ if (!VerifyErrorCode(program, data, *code.passed_, err)) { |
+ return false; |
+ } |
+ data->args[code.argno_] = code.value_ ^ 0x55AA55AA; |
jln (very slow on Chromium)
2012/12/06 00:35:00
I most definitely need a comment here :)
Markus (顧孟勤)
2012/12/12 20:54:35
Done.
|
+ if (!VerifyErrorCode(program, data, *code.failed_, err)) { |
+ return false; |
+ } |
+ break; |
+ default: // TODO(markus): Additional ops, and checks for 32/64bit |
+ *err = "Unsupported operation in conditional error code"; |
+ return false; |
+ } |
+ } else { |
+ *err = "Attempting to return invalid error code from BPF program"; |
+ return false; |
} |
return true; |
} |
@@ -74,8 +109,21 @@ uint32_t Verifier::EvaluateBPF(const std::vector<struct sock_filter>& program, |
case BPF_JMP: |
Jmp(&state, insn, err); |
break; |
- case BPF_RET: |
- return Ret(&state, insn, err); |
+ case BPF_RET: { |
+ uint32_t r = Ret(&state, insn, err); |
+ switch (r & SECCOMP_RET_ACTION) { |
+ case SECCOMP_RET_TRAP: |
+ case SECCOMP_RET_ERRNO: |
+ case SECCOMP_RET_ALLOW: |
+ break; |
+ case SECCOMP_RET_KILL: // We don't ever generate this |
+ case SECCOMP_RET_TRACE: // We don't ever generate this |
+ case SECCOMP_RET_INVALID: // Should never show up in BPF program |
+ default: |
+ *err = "Unexpected return code found in BPF program"; |
+ return 0; |
+ } |
+ return r; } |
default: |
*err = "Unexpected instruction in BPF program"; |
break; |