Index: sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
index af397dfaa35b8c583b4c450bf69e1192d3a72bc9..239043eb270d57b8b60df714323f5a166a380ede 100644 |
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
@@ -59,9 +59,40 @@ bool KernelSupportsSeccompBPF() { |
return false; |
} |
+// LG introduced a buggy syscall, sys_set_media_ext, with the same number as |
+// seccomp. Return true if the current kernel has this buggy syscall. |
+// |
+// We want this to work with upcoming versions of seccomp, so we pass bogus |
+// flags that are unlikely to ever be used by the kernel. A normal kernel would |
+// return -EINVAL, but a buggy LG kernel would return 1. |
+bool KernelHasLGBug() { |
+#if defined(OS_ANDROID) |
+ // sys_set_media will see this as NULL, which should be a safe (non-crashing) |
+ // way to invoke it. A genuine seccomp syscall will see it as |
+ // SECCOMP_SET_MODE_STRICT. |
+ const unsigned int operation = 0; |
+ // Chosen by fair dice roll. Guaranteed to be random. |
+ const unsigned int flags = 0xf7a46a5c; |
+ const int rv = sys_seccomp(operation, flags, nullptr); |
+ // A genuine kernel would return -EINVAL (which would set rv to -1 and errno |
+ // to EINVAL), or at the very least return some kind of error (which would |
+ // set rv to -1). Any other behavior indicates that whatever code received |
+ // our syscall was not the real seccomp. |
+ if (rv != -1) { |
+ return true; |
+ } |
+#endif // defined(OS_ANDROID) |
+ |
+ return false; |
+} |
+ |
// Check if the kernel supports seccomp-filter via the seccomp system call |
// and the TSYNC feature to enable seccomp on all threads. |
bool KernelSupportsSeccompTsync() { |
+ if (KernelHasLGBug()) { |
+ return false; |
+ } |
+ |
errno = 0; |
const int rv = |
sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, nullptr); |