mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-07 17:09:13 -10:00
Merge pull request #6983 from printf033/fix/android-confined-opath
Linux and Android anchor directories with O_PATH while preserving O_DIRECTORY, O_NOFOLLOW and O_CLOEXEC. The final parent is reopened through the pinned fd for existing fsync operations. Leaf regular-file and hard-link checks, atomic staging and symlink rejection remain intact; reviewed direct consumers and FD ownership on success and error paths.
Reviewed contributor head: 6cb8dff6fa. CI 38695208588: Ubuntu 19100 passed / 0 failed / 34 skipped plus 35 portable; macOS 19103 passed / 0 failed / 33 skipped; Windows 18356 passed / 0 failed / 27 skipped with one unrelated browser-launcher leak. Existing symlink/hard-link, parent-swap and confined-publication tests pass on Linux and macOS.
Source merge only: Android binary/device acceptance and resulting-main CI remain pending. Contributor syscall evidence is not a compiled Codewhale binary test. Preserve original commits and source branch.
This commit is contained in:
6 files changed
+60
-2
No files matched your search
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Contributors
|
||||
|
||||
- **[@printf033](https://github.com/printf033)** — replaced the SELinux-denied root-directory anchor of confined-file I/O with an `O_PATH` walk (Linux-cfg-gated) and a re-materialized final parent, restoring workflow journal, compaction checkpoint and artifact writes on Android/Termux ([#6983](https://github.com/codewhale-hq/Codewhale/pull/6983)); reported the Android confined-I/O failure with strace evidence and an on-device reproducer ([#6980](https://github.com/codewhale-hq/Codewhale/issues/6980)).
|
||||
|
||||
## [0.10.2] - 2026-10-10
|
||||
|
||||
- Desktop and HTTP app-server turns feed an existing shared pet companion when
|
||||
|
||||
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Contributors
|
||||
|
||||
- **[@printf033](https://github.com/printf033)** — replaced the SELinux-denied root-directory anchor of confined-file I/O with an `O_PATH` walk (Linux-cfg-gated) and a re-materialized final parent, restoring workflow journal, compaction checkpoint and artifact writes on Android/Termux ([#6983](https://github.com/codewhale-hq/Codewhale/pull/6983)); reported the Android confined-I/O failure with strace evidence and an on-device reproducer ([#6980](https://github.com/codewhale-hq/Codewhale/issues/6980)).
|
||||
|
||||
## [0.10.2] - 2026-10-10
|
||||
|
||||
- Desktop and HTTP app-server turns feed an existing shared pet companion when
|
||||
|
||||
@@ -116,7 +116,26 @@ impl WorkspaceFile {
|
||||
};
|
||||
// Use the established credential/artifact openat pattern, without
|
||||
// touching credentials or creating a second filesystem store.
|
||||
//
|
||||
// The anchor and every intermediate component are only pinned, never
|
||||
// read, and the final `openat` on the filename applies the real
|
||||
// access mode. On Linux, `O_PATH` pins a directory without read
|
||||
// permission, which keeps this working on Android: SELinux grants
|
||||
// apps search but not read on `/` and mount-point directories, so
|
||||
// `open("/", O_RDONLY|O_DIRECTORY)` fails with EACCES there and
|
||||
// every confined read/write was denied (#6980). O_PATH|O_DIRECTORY
|
||||
// still refuses non-directories (ENOTDIR), so the per-component type
|
||||
// check below is unchanged. Other Unixes have no O_PATH and keep the
|
||||
// readable-directory anchor.
|
||||
// SAFETY: static path and immediate ownership of a successful fd.
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
let fd = unsafe {
|
||||
libc::open(
|
||||
c"/".as_ptr(),
|
||||
libc::O_PATH | libc::O_DIRECTORY | libc::O_NOFOLLOW | libc::O_CLOEXEC,
|
||||
)
|
||||
};
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
let fd = unsafe {
|
||||
libc::open(
|
||||
c"/".as_ptr(),
|
||||
@@ -138,6 +157,13 @@ impl WorkspaceFile {
|
||||
return Err(invalid_path());
|
||||
};
|
||||
let name = std::ffi::CString::new(name.as_bytes())?;
|
||||
// Pin only: the caller opens the entry for real through
|
||||
// this directory fd; intermediate components need neither
|
||||
// read permission nor access to their contents. The flags
|
||||
// still reject non-directories on every platform.
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
let flags = libc::O_PATH | libc::O_DIRECTORY | libc::O_NOFOLLOW | libc::O_CLOEXEC;
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||
let flags = libc::O_RDONLY | libc::O_DIRECTORY | libc::O_NOFOLLOW | libc::O_CLOEXEC;
|
||||
// SAFETY: directory pins the parent; name is one component.
|
||||
let mut fd = unsafe { libc::openat(directory.as_raw_fd(), name.as_ptr(), flags) };
|
||||
@@ -162,6 +188,27 @@ impl WorkspaceFile {
|
||||
directory = unsafe { File::from_raw_fd(fd) };
|
||||
}
|
||||
}
|
||||
// The walk above pinned every component O_PATH, and O_PATH fds cannot
|
||||
// be fsynced (EBADF) or read. Reopen the file's immediate parent with
|
||||
// real access flags through the pinned walk so `sync_all`, `renameat`
|
||||
// and every other use of `directory` keeps working. This open cannot
|
||||
// follow a link or escape: it resolves "." inside the pinned parent
|
||||
// itself, and O_NOFOLLOW is irrelevant for an exact "." entry.
|
||||
{
|
||||
use std::os::fd::AsRawFd;
|
||||
let real_fd = unsafe {
|
||||
libc::openat(
|
||||
directory.as_raw_fd(),
|
||||
c".".as_ptr(),
|
||||
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_NOFOLLOW | libc::O_CLOEXEC,
|
||||
)
|
||||
};
|
||||
if real_fd < 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
// SAFETY: fd is freshly owned; the O_PATH fd it replaces is dropped.
|
||||
directory = unsafe { File::from_raw_fd(real_fd) };
|
||||
}
|
||||
Ok(Self {
|
||||
directory,
|
||||
filename: std::ffi::CString::new(
|
||||
|
||||
@@ -32,6 +32,8 @@ changelog or release notes, and this contributor record.
|
||||
|
||||
**Merged or adapted contributions**
|
||||
|
||||
- **[printf033](https://github.com/printf033)** — confined-file I/O on Android/Termux: SELinux-denied `open("/", O_RDONLY|O_DIRECTORY)` anchor replaced with an `O_PATH` walk (Linux-cfg-gated) plus a re-materialized final parent, restoring journal, compaction and artifact writes in search-only SELinux domains ([#6983](https://github.com/codewhale-hq/Codewhale/pull/6983)), with the diagnosis and on-device reproducer in [#6980](https://github.com/codewhale-hq/Codewhale/issues/6980).
|
||||
|
||||
</details>
|
||||
|
||||
<details open>
|
||||
|
||||
@@ -352,8 +352,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/CONTRIBUTORS.md",
|
||||
"sha256": "81cc78f58b7f9fb88607261ffb446faf9b807c55590ea41028b561a65683a078",
|
||||
"content": "# Contributors\n\nCodewhale is built in the open with a growing community of contributors. Every\nissue report and pull request is real project work — welcome at any experience\nlevel. This is the full per-PR contributor record, grouped into release/time\nbands with the newest band first so it stays scannable. Expand any band to see\neveryone.\n\nFor the live list, see the\n[GitHub contributors page](https://github.com/codewhale-hq/CodeWhale/graphs/contributors),\n[`AUTHOR_MAP`](https://github.com/codewhale-hq/CodeWhale/blob/main/.github/AUTHOR_MAP),\nand [CHANGELOG.md](../CHANGELOG.md).\n\n## Organizational thanks\n\n- **[DeepSeek](https://github.com/deepseek-ai)** — the models and support that got this project started. 感谢 DeepSeek 提供模型与支持。\n- **[DataWhale](https://github.com/datawhalechina)** 🐋 — for the support and for welcoming us into the Whale Brother family. 感谢 DataWhale 的支持。\n- **[OpenWarp](https://github.com/zerx-lab/warp)** — for prioritizing Codewhale support and collaborating on a better terminal-agent experience.\n- **[Open Design](https://github.com/nexu-io/open-design)** — for support and collaboration around design-forward agent workflows.\n\nThe maintainer rule: reports and PRs are real project work, even when the final\npatch has to be narrowed, delayed, or harvested into a maintainer branch.\nAdapted contributions keep visible credit in commits and PR bodies, the\nchangelog or release notes, and this contributor record.\n\n---\n\n## Contributors by time\n\n<details open>\n<summary><strong>Unreleased</strong></summary>\n\n**Merged or adapted contributions**\n\n</details>\n\n<details open>\n<summary><strong>v0.10.2 — terminal, recovery and reliability</strong></summary>\n\n**Contributions**\n\n- **[Sh1Zuku / SparkofSpike](https://github.com/SparkofSpike)** — live network-policy updates and goal milestone hand-back ([#6928](https://github.com/codewhale-hq/Codewhale/pull/6928), [#6930](https://github.com/codewhale-hq/Codewhale/pull/6930)), and a Codewhale home reached through a symlink or junction ([#6947](https://github.com/codewhale-hq/Codewhale/issues/6947)).\n- **[dajiaohuang](https://github.com/dajiaohuang)** — cache-write token accounting, with missing and explicit-zero usage preserved ([#6913](https://github.com/codewhale-hq/Codewhale/pull/6913)).\n- **[gaord](https://github.com/gaord)** — embedder-declared telemetry surface support without changing collection policy ([#6916](https://github.com/codewhale-hq/Codewhale/pull/6916)).\n- **[Lstarsky0](https://github.com/Lstarsky0)** — localized `/profile` replies across all 15 complete locale packs ([#6919](https://github.com/codewhale-hq/Codewhale/pull/6919)), and workflow gates that block their own role rejected at plan admission ([#6952](https://github.com/codewhale-hq/Codewhale/pull/6952)).\n- **[LIghtJUNction](https://github.com/LIghtJUNction)** — plugin shell install and in-TUI plugin OAuth sign-in with `/connect` and `/disconnect` ([#6950](https://github.com/codewhale-hq/Codewhale/pull/6950)).\n- **[jayanthvee](https://github.com/jayanthvee)** — Windows npm launcher guidance and targeted process shutdown ([#6906](https://github.com/codewhale-hq/Codewhale/pull/6906)).\n- **[asto18089](https://github.com/asto18089)** — reference fix for longer browser sign-in callback windows ([#6865](https://github.com/codewhale-hq/Codewhale/issues/6865)).\n\n**Reports and verification**\n\n- **[BX166](https://github.com/BX166)** — reported three provider failure modes measured on AICraft's own traffic: a cold model that reads as a dead connection, a listed model that fails on every call, and a response cut at the output ceiling that reports `stop` ([#6889](https://github.com/codewhale-hq/Codewhale/issues/6889)).\n\n</details>\n\n<details>\n<summary><strong>v0.10.1 — reliability and first-run fixes</strong></summary>\n\n**Merged or adapted contributions**\n\n- **[gaord](https://github.com/gaord)** — exposed call-specific workspace changes to Runtime clients ([#6817](https://github.com/codewhale-hq/Codewhale/pull/6817)) and canonical skill-detail/review routes ([#6869](https://github.com/codewhale-hq/Codewhale/pull/6869)).\n- **[asto18089](https://github.com/asto18089)** — fixed preferred search-language selection ([#6860](https://github.com/codewhale-hq/Codewhale/pull/6860)), image metadata for model input ([#6858](https://github.com/codewhale-hq/Codewhale/pull/6858)), automation deletion wording and retained-run cleanup ([#6864](https://github.com/codewhale-hq/Codewhale/pull/6864)), and compaction-anchor regression coverage ([#6857](https://github.com/codewhale-hq/Codewhale/pull/6857)).\n- **[aboimpinto](https://github.com/aboimpinto)** — extracted portable config/status/permission command contracts while preserving host-owned mutation and queue-worker readiness ([#6832](https://github.com/codewhale-hq/Codewhale/pull/6832)).\n- **[hodeswildsmith455-boop](httpsLine truncated
|
||||
"sha256": "4e7ff98061615c85fed9a013d93827f0e1f4d8eca09fa85c1c91e6309fa43d4a",
|
||||
"content": "# Contributors\n\nCodewhale is built in the open with a growing community of contributors. Every\nissue report and pull request is real project work — welcome at any experience\nlevel. This is the full per-PR contributor record, grouped into release/time\nbands with the newest band first so it stays scannable. Expand any band to see\neveryone.\n\nFor the live list, see the\n[GitHub contributors page](https://github.com/codewhale-hq/CodeWhale/graphs/contributors),\n[`AUTHOR_MAP`](https://github.com/codewhale-hq/CodeWhale/blob/main/.github/AUTHOR_MAP),\nand [CHANGELOG.md](../CHANGELOG.md).\n\n## Organizational thanks\n\n- **[DeepSeek](https://github.com/deepseek-ai)** — the models and support that got this project started. 感谢 DeepSeek 提供模型与支持。\n- **[DataWhale](https://github.com/datawhalechina)** 🐋 — for the support and for welcoming us into the Whale Brother family. 感谢 DataWhale 的支持。\n- **[OpenWarp](https://github.com/zerx-lab/warp)** — for prioritizing Codewhale support and collaborating on a better terminal-agent experience.\n- **[Open Design](https://github.com/nexu-io/open-design)** — for support and collaboration around design-forward agent workflows.\n\nThe maintainer rule: reports and PRs are real project work, even when the final\npatch has to be narrowed, delayed, or harvested into a maintainer branch.\nAdapted contributions keep visible credit in commits and PR bodies, the\nchangelog or release notes, and this contributor record.\n\n---\n\n## Contributors by time\n\n<details open>\n<summary><strong>Unreleased</strong></summary>\n\n**Merged or adapted contributions**\n\n- **[printf033](https://github.com/printf033)** — confined-file I/O on Android/Termux: SELinux-denied `open(\"/\", O_RDONLY|O_DIRECTORY)` anchor replaced with an `O_PATH` walk (Linux-cfg-gated) plus a re-materialized final parent, restoring journal, compaction and artifact writes in search-only SELinux domains ([#6983](https://github.com/codewhale-hq/Codewhale/pull/6983)), with the diagnosis and on-device reproducer in [#6980](https://github.com/codewhale-hq/Codewhale/issues/6980).\n\n</details>\n\n<details open>\n<summary><strong>v0.10.2 — terminal, recovery and reliability</strong></summary>\n\n**Contributions**\n\n- **[Sh1Zuku / SparkofSpike](https://github.com/SparkofSpike)** — live network-policy updates and goal milestone hand-back ([#6928](https://github.com/codewhale-hq/Codewhale/pull/6928), [#6930](https://github.com/codewhale-hq/Codewhale/pull/6930)), and a Codewhale home reached through a symlink or junction ([#6947](https://github.com/codewhale-hq/Codewhale/issues/6947)).\n- **[dajiaohuang](https://github.com/dajiaohuang)** — cache-write token accounting, with missing and explicit-zero usage preserved ([#6913](https://github.com/codewhale-hq/Codewhale/pull/6913)).\n- **[gaord](https://github.com/gaord)** — embedder-declared telemetry surface support without changing collection policy ([#6916](https://github.com/codewhale-hq/Codewhale/pull/6916)).\n- **[Lstarsky0](https://github.com/Lstarsky0)** — localized `/profile` replies across all 15 complete locale packs ([#6919](https://github.com/codewhale-hq/Codewhale/pull/6919)), and workflow gates that block their own role rejected at plan admission ([#6952](https://github.com/codewhale-hq/Codewhale/pull/6952)).\n- **[LIghtJUNction](https://github.com/LIghtJUNction)** — plugin shell install and in-TUI plugin OAuth sign-in with `/connect` and `/disconnect` ([#6950](https://github.com/codewhale-hq/Codewhale/pull/6950)).\n- **[jayanthvee](https://github.com/jayanthvee)** — Windows npm launcher guidance and targeted process shutdown ([#6906](https://github.com/codewhale-hq/Codewhale/pull/6906)).\n- **[asto18089](https://github.com/asto18089)** — reference fix for longer browser sign-in callback windows ([#6865](https://github.com/codewhale-hq/Codewhale/issues/6865)).\n\n**Reports and verification**\n\n- **[BX166](https://github.com/BX166)** — reported three provider failure modes measured on AICraft's own traffic: a cold model that reads as a dead connection, a listed model that fails on every call, and a response cut at the output ceiling that reports `stop` ([#6889](https://github.com/codewhale-hq/Codewhale/issues/6889)).\n\n</details>\n\n<details>\n<summary><strong>v0.10.1 — reliability and first-run fixes</strong></summary>\n\n**Merged or adapted contributions**\n\n- **[gaord](https://github.com/gaord)** — exposed call-specific workspace changes to Runtime clients ([#6817](https://github.com/codewhale-hq/Codewhale/pull/6817)) and canonical skill-detail/review routes ([#6869](https://github.com/codewhale-hq/Codewhale/pull/6869)).\n- **[asto18089](https://github.com/asto18089)** — fixed preferred search-language selection ([#6860](https://github.com/codewhale-hq/Codewhale/pull/6860)), image metadata for model input ([#6858](https://github.com/codewhale-hq/Codewhale/pull/6858)), automation Line truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/RELEASE_CHECKLIST.md",
|
||||
|
||||
@@ -36,6 +36,7 @@ export const RELEASE_CONTRIBUTORS: string[] = [
|
||||
*/
|
||||
export const UNRELEASED_CONTRIBUTORS: string[] = [
|
||||
"@aboimpinto",
|
||||
"@printf033",
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user