{"record":{"id":"49f3cef2f493da6c","repo":"henrygd/beszel","slug":"chcon-failed-w","errorCode":null,"errorMessage":"chcon failed: %w","messagePattern":"chcon failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/ghupdate/selinux.go","lineNumber":31,"sourceCode":"\t\t// SELinux not enabled or getenforce not available\n\t\treturn nil\n\t}\n\tstate := strings.TrimSpace(string(out))\n\tif state == \"Disabled\" {\n\t\treturn nil\n\t}\n\n\tColorPrint(ColorYellow, \"SELinux is enabled; applying context…\")\n\n\t// Try persistent context via semanage+restorecon\n\tif success := trySemanageRestorecon(path); success {\n\t\treturn nil\n\t}\n\n\t// Fallback to temporary context via chcon\n\tif chconPath, err := exec.LookPath(\"chcon\"); err == nil {\n\t\tif err := exec.Command(chconPath, \"-t\", \"bin_t\", path).Run(); err != nil {\n\t\t\treturn fmt.Errorf(\"chcon failed: %w\", err)\n\t\t}\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"no SELinux tools available (semanage/restorecon or chcon)\")\n}\n\n// trySemanageRestorecon attempts to set persistent SELinux context using semanage and restorecon.\n// Returns true if successful, false otherwise.\nfunc trySemanageRestorecon(path string) bool {\n\tsemanagePath, err := exec.LookPath(\"semanage\")\n\tif err != nil {\n\t\treturn false\n\t}\n\n\trestoreconPath, err := exec.LookPath(\"restorecon\")\n\tif err != nil {\n\t\treturn false","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/ghupdate/selinux.go#L13-L49","documentation":"HandleSELinuxContext sets an SELinux context on the updated binary. When persistent tools (semanage/restorecon) are unavailable, it falls back to running `chcon -t bin_t <path>`; this error wraps a non-zero exit of chcon. The binary has been updated but its SELinux context could not be adjusted, which may prevent it from executing under enforcing SELinux.","triggerScenarios":"Calling HandleSELinuxContext on an SELinux-enabled system where semanage/restorecon are absent, chcon exists, but `chcon -t bin_t path` exits non-zero — e.g. permission denied, invalid path, or SELinux policy forbidding the transition.","commonSituations":"Running as non-root on an SELinux-enforcing host (chcon requires appropriate privileges); the binary path doesn't exist or was moved before this call; policy prevents setting bin_t on that location; minimal container images shipping chcon but no policy support.","solutions":["Run the update (and context fix) as root, or with CAP_MAC_ADMIN, so chcon can relabel the file.","Verify the target path exists and is a regular file before the context operation.","Install the persistent tooling instead: policycoreutils-python-utils (semanage/restorecon) so a durable rule is used.","If the environment isn't actually SELinux-enforcing, skip the call or set permissive mode (getenforce/setenforce 0) while updating."],"exampleFix":"// before: non-root relabel denied\n$ ./myapp update\n// chcon failed: exit status 1 (permission denied)\n\n// after: run with sufficient privileges\n$ sudo ./myapp update","handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(\"/sys/fs/selinux\"); err != nil {\n    return nil // not an SELinux system; skip HandleSELinuxContext\n}\nif _, err := exec.LookPath(\"chcon\"); err != nil {\n    return fmt.Errorf(\"no SELinux tooling installed\")\n}\nif os.Geteuid() != 0 {\n    return fmt.Errorf(\"relabeling requires root\")\n}","typeGuard":"func chconAvailable() bool {\n    _, err := exec.LookPath(\"chcon\")\n    return err == nil\n}","tryCatchPattern":"if err := HandleSELinuxContext(binPath); err != nil {\n    if strings.Contains(err.Error(), \"chcon failed\") {\n        log.Warn(\"could not relabel binary; run 'chcon -t bin_t' manually as root\", \"err\", err)\n    } else { return err }\n}","preventionTips":["Run self-updates as root on SELinux-enforcing hosts.","Install policycoreutils / policycoreutils-python-utils so persistent relabeling works.","Verify the binary path exists before relabeling.","Log this as a warning, not fatal — the update itself succeeded."],"tags":["selinux","security","permissions","linux"],"backgroundTag":"selinux-context-failed","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}