{"record":{"id":"8f788636a5e01b76","repo":"elastic/elasticsearch","slug":"seccomp-seccomp-set-mode-filter-prctl-pr-set","errorCode":null,"errorMessage":"seccomp(SECCOMP_SET_MODE_FILTER): {}, prctl(PR_SET_SECCOMP): {}","messagePattern":"seccomp\\(SECCOMP_SET_MODE_FILTER\\): (.+?), prctl\\(PR_SET_SECCOMP\\): (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"warning","filePath":"libs/native/src/main/java/org/elasticsearch/nativeaccess/LinuxNativeAccess.java","lineNumber":319,"sourceCode":"            /* 8  */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch.execveat, 1, 0),                 // if (syscall == EXECVEAT) goto fail;\n            /* 9  */ BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),                                // pass: return OK;\n            /* 10 */ BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (EACCES & SECCOMP_RET_DATA)),  // fail: return EACCES;\n        };\n        // seccomp takes a long, so we pass it one explicitly to keep the JNA simple\n        SockFProg prog = linuxLibc.newSockFProg(insns);\n\n        int method = 1;\n        // install filter, if this works, after this there is no going back!\n        // first try it with seccomp(SECCOMP_SET_MODE_FILTER), falling back to prctl()\n        if (linuxLibc.syscall(arch.seccomp, SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, prog) != 0) {\n            method = 0;\n            int errno1 = libc.errno();\n            if (logger.isDebugEnabled()) {\n                logger.debug(\"seccomp(SECCOMP_SET_MODE_FILTER): {}, falling back to prctl(PR_SET_SECCOMP)...\", libc.strerror(errno1));\n            }\n            if (linuxLibc.prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog.segment().address(), 0, 0) != 0) {\n                int errno2 = libc.errno();\n                throw new UnsupportedOperationException(\n                    \"seccomp(SECCOMP_SET_MODE_FILTER): \" + libc.strerror(errno1) + \", prctl(PR_SET_SECCOMP): \" + libc.strerror(errno2)\n                );\n            }\n        }\n\n        // now check that the filter was really installed, we should be in filter mode.\n        if (linuxLibc.prctl(PR_GET_SECCOMP, 0, 0, 0, 0) != 2) {\n            throw new UnsupportedOperationException(\n                \"seccomp filter installation did not really succeed. seccomp(PR_GET_SECCOMP): \" + libc.strerror(libc.errno())\n            );\n        }\n\n        logger.debug(\"Linux seccomp filter installation successful, threads: [{}]\", method == 1 ? \"all\" : \"app\");\n        execSandboxState = method == 1 ? ExecSandboxState.ALL_THREADS : ExecSandboxState.EXISTING_THREADS;\n    }\n}\n","sourceCodeStart":301,"sourceCodeEnd":336,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/native/src/main/java/org/elasticsearch/nativeaccess/LinuxNativeAccess.java#L301-L336","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read both strerror values: errno1 (seccomp syscall) and errno2 (prctl fallback) — they often differ and pinpoint the issue.","If errno1 is EPERM with TSYNC, the prctl fallback should work for the current thread — check why errno2 also fails.","Check container runtime security policies: Docker seccomp profiles, Kubernetes PodSecurityPolicies/Admission policies.","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.","Run dmesg | grep -i seccomp to check for kernel-level audit messages about the denied filter.","If the sandbox is not required, accept the failure."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    nativeAccess.tryInstallExecSandbox();\n} catch (UnsupportedOperationException e) {\n    // Both seccomp() syscall and prctl() fallback failed.\n    // The message contains BOTH strerror values for diagnosis.\n    logger.warn(\"BPF seccomp filter installation failed: {}\", e.getMessage());\n}","preventionTips":["Check container runtime seccomp profiles allow the seccomp() syscall and PR_SET_SECCOMP.","For Docker, consider --security-opt seccomp=unconfined if the sandbox is not required, or use a profile that permits seccomp filter installation.","Verify os.arch is in the ARCHITECTURES map — an unsupported architecture produces wrong BPF constants.","Run dmesg | grep -i seccomp to find kernel-level denial messages.","Ensure all threads in the process have compatible credentials for TSYNC (or accept the prctl single-thread fallback)."],"tags":["linux","seccomp","security","native","kernel","bootstrap","bpf","filter-installation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}