elastic/elasticsearch · warning · UnsupportedOperationException

seccomp(SECCOMP_SET_MODE_FILTER): {}, prctl(PR_SET_SECCOMP):

Error message

seccomp(SECCOMP_SET_MODE_FILTER): {}, prctl(PR_SET_SECCOMP): {}

What it means

Thrown during Linux seccomp sandbox setup in tryInstallExecSandbox(). This is the critical BPF filter installation step. The code first tries the modern seccomp(SECCOMP_SET_MODE_FILTER) syscall with the SECCOMP_FILTER_FLAG_TSYNC flag (applies to all threads). If that fails, it falls back to prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog_address). If BOTH fail, this combined error is thrown with both strerror messages (errno1 from seccomp, errno2 from prctl). The 10-instruction BPF program blocks fork/vfork/execve/execveat.

Source

Thrown at libs/native/src/main/java/org/elasticsearch/nativeaccess/LinuxNativeAccess.java:319

            /* 8  */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch.execveat, 1, 0),                 // if (syscall == EXECVEAT) goto fail;
            /* 9  */ BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),                                // pass: return OK;
            /* 10 */ BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (EACCES & SECCOMP_RET_DATA)),  // fail: return EACCES;
        };
        // seccomp takes a long, so we pass it one explicitly to keep the JNA simple
        SockFProg prog = linuxLibc.newSockFProg(insns);

        int method = 1;
        // install filter, if this works, after this there is no going back!
        // first try it with seccomp(SECCOMP_SET_MODE_FILTER), falling back to prctl()
        if (linuxLibc.syscall(arch.seccomp, SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, prog) != 0) {
            method = 0;
            int errno1 = libc.errno();
            if (logger.isDebugEnabled()) {
                logger.debug("seccomp(SECCOMP_SET_MODE_FILTER): {}, falling back to prctl(PR_SET_SECCOMP)...", libc.strerror(errno1));
            }
            if (linuxLibc.prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog.segment().address(), 0, 0) != 0) {
                int errno2 = libc.errno();
                throw new UnsupportedOperationException(
                    "seccomp(SECCOMP_SET_MODE_FILTER): " + libc.strerror(errno1) + ", prctl(PR_SET_SECCOMP): " + libc.strerror(errno2)
                );
            }
        }

        // now check that the filter was really installed, we should be in filter mode.
        if (linuxLibc.prctl(PR_GET_SECCOMP, 0, 0, 0, 0) != 2) {
            throw new UnsupportedOperationException(
                "seccomp filter installation did not really succeed. seccomp(PR_GET_SECCOMP): " + libc.strerror(libc.errno())
            );
        }

        logger.debug("Linux seccomp filter installation successful, threads: [{}]", method == 1 ? "all" : "app");
        execSandboxState = method == 1 ? ExecSandboxState.ALL_THREADS : ExecSandboxState.EXISTING_THREADS;
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Read both strerror values: errno1 (seccomp syscall) and errno2 (prctl fallback) — they often differ and pinpoint the issue.
  2. If errno1 is EPERM with TSYNC, the prctl fallback should work for the current thread — check why errno2 also fails.
  3. Check container runtime security policies: Docker seccomp profiles, Kubernetes PodSecurityPolicies/Admission policies.
  4. Verify os.arch matches a supported architecture in the ARCHITECTURES map (line 170) — an architecture mismatch means the BPF audit/limit/fork constants are wrong.
  5. Run dmesg | grep -i seccomp to check for kernel-level audit messages about the denied filter.
  6. If the sandbox is not required, accept the failure.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    nativeAccess.tryInstallExecSandbox();
} catch (UnsupportedOperationException e) {
    // Both seccomp() syscall and prctl() fallback failed.
    // The message contains BOTH strerror values for diagnosis.
    logger.warn("BPF seccomp filter installation failed: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling tryInstallExecSandbox() where both linuxLibc.syscall(arch.seccomp, SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, prog) and the fallback linuxLibc.prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog.segment().address(), 0, 0) return non-zero. The debug log at line 314-315 shows the first failure and the fallback attempt.

Common situations: Container seccomp profiles that block the seccomp() syscall and PR_SET_SECCOMP; kernels where the BPF program is rejected (architecture mismatch, invalid instruction encoding); AppArmor/SELinux denying BPF filter installation; the TSYNC flag failing because threads have different credentials (EPERM) and the prctl fallback also blocked.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/8f788636a5e01b76. Report an issue: GitHub.