-
Notifications
You must be signed in to change notification settings - Fork 1
feat(uname): implement uname builtin (Linux only, proc-based) #146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
1f2f188
feat(uname): implement uname builtin (Linux only, proc-based)
matt-dz 2c6a0c3
refactor(uname): use ProcProvider.ReadKernelFile instead of raw os calls
matt-dz 16d1026
fix(uname): show clear platform error on non-Linux systems
matt-dz 6244031
test(uname): add comprehensive unit and scenario tests
matt-dz 69d2faa
fix(uname): reject extra positional operands
matt-dz 1bd4097
fix(proc): bound ReadKernelFile reads to 4 KiB
matt-dz a90396b
fix(test): map context cancellation to non-zero exit in runScriptCtx
matt-dz 4a6940b
fix(proc): reject non-regular files in ReadKernelFile
matt-dz 7bf18fa
fix(proc): stat before open in ReadKernelFile to prevent FIFO hang
matt-dz 70d0acd
fix(proc): atomic open+fstat in ReadKernelFile to close TOCTOU race
matt-dz 98f6320
refactor(uname): move kernel reads to builtins/internal/procsyskernel
matt-dz 8f3aad1
fix(procsyskernel): reject ".." in procPath for defence-in-depth
matt-dz f1a0208
fix(uname): use GNU-compatible long flag names instead of one-letter
matt-dz 251be0f
fix(procsyskernel): validate name is a plain basename
matt-dz 0b2917e
fix(uname): match GNU error format and enable bash comparison
matt-dz c02f36e
fix(uname): fall back to runtime.GOARCH for -m when proc file missing
matt-dz bb3c3b8
revert(uname): remove runtime.GOARCH fallback for -m
matt-dz 3a96e33
docs(uname): note /proc/sys/kernel/arch availability since Linux 2.6
matt-dz c3a1e11
fix(uname): include long option names in --help output
matt-dz 2407658
docs(test): add comments explaining skip_assert_against_bash in uname…
matt-dz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| // Unless explicitly stated otherwise all files in this repository are licensed | ||
| // under the Apache License Version 2.0. | ||
| // This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
| // Copyright 2026-present Datadog, Inc. | ||
|
|
||
| // Package procsyskernel reads Linux kernel information from /proc/sys/kernel/. | ||
| // | ||
| // This package is in builtins/internal/ and is therefore exempt from the | ||
| // builtinAllowedSymbols allowlist check. It may use OS-specific APIs freely. | ||
| // | ||
| // # Sandbox bypass | ||
| // | ||
| // ReadFile intentionally bypasses the AllowedPaths sandbox (callCtx.OpenFile) | ||
| // and calls os.OpenFile directly. This is safe because procPath is always a | ||
| // kernel-managed pseudo-filesystem root (/proc by default) that is hardcoded | ||
| // by the caller — it is never derived from user-supplied input and cannot be | ||
| // redirected by a shell script. The caller is responsible for ensuring that | ||
| // procPath remains a safe, non-user-controlled path. | ||
| package procsyskernel | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "io" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "syscall" | ||
| ) | ||
|
|
||
| // ReadFile reads a single-line value from a /proc/sys/kernel/ pseudo-file. | ||
| // name is the filename (e.g. "ostype", "hostname"). procPath is the base | ||
| // proc path (e.g. "/proc" or "/host/proc"). | ||
| // | ||
| // The file is opened with O_NONBLOCK to prevent blocking on FIFOs, then | ||
| // validated via fstat to reject non-regular files. Reads are bounded to | ||
| // 4 KiB. The returned value is trimmed of trailing whitespace. | ||
| func ReadFile(procPath, name string) (string, error) { | ||
| // Defence-in-depth: reject ".." in the original path before Clean | ||
| // so traversal like "/proc/../etc/passwd" is caught. Matches the | ||
| // equivalent guard in procnetroute and procnetsocket. | ||
| if strings.Contains(procPath, "..") { | ||
| return "", fmt.Errorf("procsyskernel: unsafe procPath %q (must not contain \"..\" components)", procPath) | ||
| } | ||
| // Reject path components in name — must be a plain basename (e.g. "ostype"). | ||
| if name != filepath.Base(name) || strings.Contains(name, "..") { | ||
| return "", fmt.Errorf("procsyskernel: unsafe name %q (must be a plain filename)", name) | ||
| } | ||
| path := filepath.Join(filepath.Clean(procPath), "sys", "kernel", name) | ||
| // Open with O_NONBLOCK to prevent blocking on FIFOs, then validate | ||
| // the file type via fstat on the opened fd. This is atomic — no | ||
| // TOCTOU gap between type check and open. | ||
| f, err := os.OpenFile(path, os.O_RDONLY|syscall.O_NONBLOCK, 0) | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
| defer f.Close() | ||
| info, err := f.Stat() | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
| if !info.Mode().IsRegular() && info.Mode().Type()&os.ModeCharDevice == 0 { | ||
| // Allow regular files and char devices (proc pseudo-files appear as | ||
| // char devices on some configurations). Reject FIFOs, sockets, etc. | ||
| return "", fmt.Errorf("not a regular file: %s", path) | ||
| } | ||
| // Proc kernel files are tiny single-line values. Cap at 4 KiB. | ||
| data, err := io.ReadAll(io.LimitReader(f, 4096)) | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
| return strings.TrimRight(string(data), " \t\r\n"), nil | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.