diff --git a/research/h25-native-view-facts/INVENTORY.json b/research/h25-native-view-facts/INVENTORY.json new file mode 100644 index 0000000000..26d2b77e03 --- /dev/null +++ b/research/h25-native-view-facts/INVENTORY.json @@ -0,0 +1,342 @@ +{ + "files": { + "NOTICE.md": { + "bytes": 1096, + "git_blob_sha1": "895e4d6b860a87d8a4b6cba2f80fe743877177c3", + "mode": "100644", + "sha256": "6e234acd3008d4b5bf47f3cc99390131a7f22b5f5e75000a17d816fc0b50cd8c" + }, + "PROVENANCE.json": { + "bytes": 19812, + "git_blob_sha1": "f98d273b2da6fbe917cddd65f91aa022c8c547d8", + "mode": "100644", + "sha256": "fffa9c37c0be89d0a8e10701fe6f42ba2dd3ffbd941e87002fd624b689c15fbc" + }, + "README.md": { + "bytes": 8825, + "git_blob_sha1": "55fc14d597b4aa0b932813fac75f4e9df4aae8d6", + "mode": "100644", + "sha256": "aad30f63f68d448272bb9fc58ffe980666ba8bee9dc8fe079e2c749f00c561fd" + }, + "controls/OPERATION-PLAN-v1.md": { + "bytes": 6749, + "git_blob_sha1": "a0d8f20390a58bbf860130593f829233b0645412", + "mode": "100644", + "sha256": "9fe746735348bdc4e0097c374db8596575fdf32a62f94fad71e96d5d4b59746f" + }, + "controls/changed_policy_control.c.txt": { + "bytes": 7089, + "git_blob_sha1": "60fe0790054742810f2cd00693ff3a478088e6b3", + "mode": "100644", + "sha256": "5a2529728985028865276d116f5c567e3c613e4f8f0356f9070857206318c2eb" + }, + "controls/native_fact_control.c.txt": { + "bytes": 7734, + "git_blob_sha1": "04ef74d436651be730dbc4a56ca24f1c2381a820", + "mode": "100644", + "sha256": "b7b7cfe5ebbebead55791b121b2fdb5e15d2736aafaa4a2e781e99de44ffd5fd" + }, + "evidence/ACTUAL-POLICY-LEDGER.json": { + "bytes": 4715, + "git_blob_sha1": "3817d8b7f9e9b9d369269662e87c5222c6c62042", + "mode": "100644", + "sha256": "51e025a94f367f4d2610439f2183ed8af8ccc560dadb1e23e74fa44592288a3d" + }, + "evidence/PARENT-ADMISSION.json": { + "bytes": 2315, + "git_blob_sha1": "9158cd6b0b5f70a6242939b91b44838ea00580c0", + "mode": "100644", + "sha256": "5f23c8d4277a1ff781f94a33b2c65bb1651997b79354b89ba558c338a8ce2c53" + }, + "evidence/PRE-RETIREMENT.json": { + "bytes": 280, + "git_blob_sha1": "b5524b3eca28d2024bd087c402092beb779ccdbe", + "mode": "100644", + "sha256": "b8fa6c00550948a43649cb280b710947dc0132b63a25b7123ce6bec8b3633e36" + }, + "evidence/RESULT.json": { + "bytes": 1541, + "git_blob_sha1": "b36e09db5ee2ca38975b00a8acd7497ec25ae8e4", + "mode": "100644", + "sha256": "5d853d07aaaaccddaa6c071129e3680da4cf6968d435918b167d4de397f4ff07" + }, + "evidence/native_controls_outer_owner.py.txt": { + "bytes": 3663, + "git_blob_sha1": "aa6941d7c22224fd6f852df443ebdfa1a246aa2d", + "mode": "100644", + "sha256": "a053760af494243276906d80a52515a7f1f7b5130b383ffa41ac114770c61dfa" + }, + "evidence/run_native_proposal_controls.py.txt": { + "bytes": 8306, + "git_blob_sha1": "4b8b3a3a4e3d948f20199e86262eb1bb50c3e827", + "mode": "100644", + "sha256": "16bb421046a08a96efe328e8c60193bc0983fc5ade948a370e3924bcf4f173b2" + }, + "evidence/steps/changed_policy_control-BINARY-PIN.json": { + "bytes": 101, + "git_blob_sha1": "2e3ef59cb1c36d6749a31531fb3bcca947dc4182", + "mode": "100644", + "sha256": "afa55d83c4c660693357a5c32a75cf0fdd6a06f2f72f4642e2a36cd5d7739451" + }, + "evidence/steps/compile-changed_policy_control/BIRTH.json": { + "bytes": 61, + "git_blob_sha1": "4555512755a6b8ed9ce22f1619b74ec608712332", + "mode": "100644", + "sha256": "823840626d21cf6f505ffb97241945a7f582a4e9173fb1e67dd11e8f10de96ff" + }, + "evidence/steps/compile-changed_policy_control/RESULT.json": { + "bytes": 263, + "git_blob_sha1": "81c9b875d6608d0b0b697f60cbac17d7151bc67a", + "mode": "100644", + "sha256": "00b279d15adfd6730222914ee8616b713301b42f0d3fd677352d0d9d805a197b" + }, + "evidence/steps/compile-changed_policy_control/START.json": { + "bytes": 752, + "git_blob_sha1": "99a74fc659eaa37b72a57e6d715e5fad9611767e", + "mode": "100644", + "sha256": "89056e04bc4b553a49a84e5d69dc723d9c4ac768c6ed2f5a491acd2d4cecebeb" + }, + "evidence/steps/compile-changed_policy_control/stderr.raw": { + "bytes": 5437, + "git_blob_sha1": "fb900b90c891a01393d89defd70d797b46b7c7e2", + "mode": "100644", + "sha256": "fa440e57a7f79241f2d70d431bd116cccc35298b0cb6815309ee3d9e5bb7eff6" + }, + "evidence/steps/compile-changed_policy_control/stdout.raw": { + "bytes": 0, + "git_blob_sha1": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "mode": "100644", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/compile-native_fact_control/BIRTH.json": { + "bytes": 62, + "git_blob_sha1": "d695ac8e7bdf9a032f13e211fdf7ce8d1163155d", + "mode": "100644", + "sha256": "b23dab1d5961c920e59899abdadb23dce4c7ec27879f1e8c89d2a66592d65cdf" + }, + "evidence/steps/compile-native_fact_control/RESULT.json": { + "bytes": 259, + "git_blob_sha1": "d2f5d77f9ac368a93747ac1f4e43b4a72ab9068c", + "mode": "100644", + "sha256": "5137a06c4b9d8762971cd0358414ec3f425daa33829aad1eac0d863222fa14e6" + }, + "evidence/steps/compile-native_fact_control/START.json": { + "bytes": 746, + "git_blob_sha1": "a7812d2a7b4580c9f921500820a1c1032bd0041c", + "mode": "100644", + "sha256": "8e8c37b906bf2c46d5af3bc134c515917b77219b24631aec85756aeb7da27e1b" + }, + "evidence/steps/compile-native_fact_control/stderr.raw": { + "bytes": 5433, + "git_blob_sha1": "67137b6890809327787ed2c2177c90bd10fecc1d", + "mode": "100644", + "sha256": "3f46ee589b4952248f3bbae97f3ec184540065b704a010781b3b52c9bd23cc45" + }, + "evidence/steps/compile-native_fact_control/stdout.raw": { + "bytes": 0, + "git_blob_sha1": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "mode": "100644", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/native_fact_control-BINARY-PIN.json": { + "bytes": 101, + "git_blob_sha1": "a98664fa64712662465dd9cdfe4739ebeed67ab2", + "mode": "100644", + "sha256": "d7759172dd0335674673e70a94ca1bda2e54e36dbc2e62e1d190c7451c126eb3" + }, + "evidence/steps/run-changed_policy_control/BIRTH.json": { + "bytes": 62, + "git_blob_sha1": "21941b558cbc58467acdbf2648ed1a296641ad52", + "mode": "100644", + "sha256": "e5a1c038e757cf92e750439369495ab1ca23eb5ca72fdfe458a2b7bec32f8360" + }, + "evidence/steps/run-changed_policy_control/RESULT.json": { + "bytes": 258, + "git_blob_sha1": "8be0813eb01630e14ba122eb92c6cc089ccfa399", + "mode": "100644", + "sha256": "845b43883e4cecac25a6d1367f2803f0253d52f38a30e425df1b6e0d6d6f3d69" + }, + "evidence/steps/run-changed_policy_control/START.json": { + "bytes": 392, + "git_blob_sha1": "e48ebaa9b0e691d73c21173db08e770b39c10e69", + "mode": "100644", + "sha256": "a4d6e61ecef7497c7f5b7f7edf0952aec47d33ac8a7ff99b9b3228d0f8f8c18c" + }, + "evidence/steps/run-changed_policy_control/stderr.raw": { + "bytes": 0, + "git_blob_sha1": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "mode": "100644", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/run-changed_policy_control/stdout.raw": { + "bytes": 0, + "git_blob_sha1": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "mode": "100644", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/run-native_fact_control/BIRTH.json": { + "bytes": 62, + "git_blob_sha1": "d399801a53bc1cd7c5e7d6e7db71d855195f1615", + "mode": "100644", + "sha256": "65ff47c679a2d53b86171634bcaf6fb0db4bb3f5ff506868287572f47216840c" + }, + "evidence/steps/run-native_fact_control/RESULT.json": { + "bytes": 255, + "git_blob_sha1": "769562cb629549c1c326a5aefaaed44ed1fd14c2", + "mode": "100644", + "sha256": "d788050e64135b4aabc6a078ccf9db9881ee86be947007352cd0be6199f9eded" + }, + "evidence/steps/run-native_fact_control/START.json": { + "bytes": 389, + "git_blob_sha1": "68fc3ab737f0f9b13cacbefa5a49ea1027b7a78e", + "mode": "100644", + "sha256": "e296e8af3c879c3c04566e62309612890d9f1234c7c8e0481317651222825062" + }, + "evidence/steps/run-native_fact_control/stderr.raw": { + "bytes": 0, + "git_blob_sha1": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "mode": "100644", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/run-native_fact_control/stdout.raw": { + "bytes": 64, + "git_blob_sha1": "3a7b948b1aaf3013019481bc46d0df0e631c92ee", + "mode": "100644", + "sha256": "e938ab0debc79b2a1578b478231fb7fa9919cdfd0849d7922e4b75c9d4bc9110" + }, + "proof/COMPILER-SCRATCH-LINEAGE.md": { + "bytes": 4432, + "git_blob_sha1": "680efeee5b07547250e992be731e03dc2c2953ae", + "mode": "100644", + "sha256": "9abb05a5f3b0aa86f08f6844a7a01287fbc80dfe246f6facafa973cbf9549902" + }, + "proof/CONFIG-AND-INHERITANCE-LEMMAS-v1.md": { + "bytes": 12380, + "git_blob_sha1": "acda67b317cad21cead6fcbf4357b037d81d4b94", + "mode": "100644", + "sha256": "a5e697ed5d3bc443069f0ec7d929dd56f61804c3a764894ebc9db84741700dfb" + }, + "proof/KERNEL-LEMMAS-v1.md": { + "bytes": 17084, + "git_blob_sha1": "fc3f02f2fe48522b3306f8e900a3e818cae6b6ee", + "mode": "100644", + "sha256": "3fa107a85ad5f682cb9ea7ebe5ac562e1ab1c686272d363ef4c33470e1b49b52" + }, + "proof/LSM-ACQUISITION-ABI-v1.md": { + "bytes": 3176, + "git_blob_sha1": "d6948ce884417b066cf98a166103f69897b6924e", + "mode": "100644", + "sha256": "f886e5c749e07f3cd410f5403d4147a535209bfccd8381249c832ba9a2f0c303" + }, + "proof/METADATA-PRIMITIVE-LEMMA-v1.md": { + "bytes": 5559, + "git_blob_sha1": "063f102a1436b162860131795488883bdaa5b962", + "mode": "100644", + "sha256": "c7c5d4002035ef647b6129c1be244900870f6a4b1da1cd84c37112d05cf69500" + }, + "proof/MOUNT-CENSUS-LEMMA-v1.md": { + "bytes": 6903, + "git_blob_sha1": "e487e3a83abfc11c5c4efba6e104850651960a7d", + "mode": "100644", + "sha256": "2598bbb04d8a68ca6a1148547de0a9f0c790012518afb309e0796f7ad5b67f9d" + }, + "proof/NATIVE-ENTRY-INVARIANTS.md": { + "bytes": 18911, + "git_blob_sha1": "68166dedee8ca2c9182c6f9ac22c206add0f1284", + "mode": "100644", + "sha256": "62c31378b5ddf7c4237c44b29cfa9de5fc63a155f5c9da5fe3e97645724e0019" + }, + "proof/ORIGINAL-NATIVE-CONSUMERS.md": { + "bytes": 16325, + "git_blob_sha1": "c1860f7d5ef26817986b3e5bc82ed5f557b3b723", + "mode": "100644", + "sha256": "f93404aadfed12de369d422c68916b1697d5b3b11006f62301d79428ce153f58" + }, + "proof/ROOT-REFERENCE-LEMMA.md": { + "bytes": 8458, + "git_blob_sha1": "31b37c4377ad828902017d337d29d4d2a04c6c9d", + "mode": "100644", + "sha256": "8a2602008726347232e89812fb959974785d21b5c012f6b8fb4a336fe1a05534" + }, + "proof/TMPDIR-CALLER-LEMMA-v1.md": { + "bytes": 2940, + "git_blob_sha1": "3f54f1efae712ed4b2ac607a53f25d8ad590801d", + "mode": "100644", + "sha256": "e5488995cff1a186f3fde4f167aee5091b9dbdebac27eea0f26769af490e8943" + }, + "proof/primary/INDEX.json": { + "bytes": 12652, + "git_blob_sha1": "ff7bf8311cb06eeebd2569f2e84ab367c21c0a0f", + "mode": "100644", + "sha256": "ad8f24992e56ee040b11faee080b49d5959b63664ee4e4672f1664db11e2bbc5" + }, + "proof/primary/SHA256SUMS.txt": { + "bytes": 4912, + "git_blob_sha1": "fe1bc4e14ab625d5a318d3dc739db8608d6743c5", + "mode": "100644", + "sha256": "18cfbd9a955097e25246142beebdc0e964ad7e6beeff3707ad452d53e4c39377" + }, + "proof/remaining-binutils-source-transfer.md": { + "bytes": 2639, + "git_blob_sha1": "0bea8a1c0ee4a874eb59e7e751406449c6c025ec", + "mode": "100644", + "sha256": "7381e32912f0e2157a210348100b94a61e79e96be97940ff9a170754100b9080" + }, + "review/ACTUAL-NATIVE-ACQUISITION-REVIEW-v1.md": { + "bytes": 13275, + "git_blob_sha1": "0c517b2f34edd054cedfc2c24400c7222c4684bc", + "mode": "100644", + "sha256": "7a713c65cf1ba2827b872f0c73efb64e07ed2d87b370b1afe898667e4091f35a" + }, + "review/NATIVE-PROPOSAL-GUARD-REVIEW-v1.md": { + "bytes": 5777, + "git_blob_sha1": "356b3f3c3617bb7751e9746301b8fdb2f984d96c", + "mode": "100644", + "sha256": "81eee191ae1706932ab8b75b6c2de74e8014550e8cf43ab2846ff6e9bc51e435" + }, + "review/NEW-MOCK-RESULT-READBACK-v1.md": { + "bytes": 2091, + "git_blob_sha1": "f7f901061538e0b7d5f79252ee482d8dee0715d4", + "mode": "100644", + "sha256": "d6db1530ef6f7babda64ce794c6fdf828df8e256b06aae2a10b00a724dcf7e0b" + }, + "source/ACQUISITION-CONSTRUCTION.md": { + "bytes": 11068, + "git_blob_sha1": "c278ff8370ff94ab647f086ac1f559983739c031", + "mode": "100644", + "sha256": "71bd6cf1633bee944095394cfc466d7c51ac3f28f606bbffb1fa65f842628964" + }, + "source/EXACT-NATIVE-CHANGE.diff": { + "bytes": 22431, + "git_blob_sha1": "f0e6de1fd2208a1c301178fca42e4bbea334efc2", + "mode": "100644", + "sha256": "d364b986ae881b0064aae2b161ab6ec1589eddbca921b059bad43313d7344dc6" + }, + "source/VIEW-ENTRY-CONTRACT-v1.md": { + "bytes": 33378, + "git_blob_sha1": "5a19adce5b026fbafa84a0f40d83d2c828f8c08e", + "mode": "100644", + "sha256": "b9e3a1b4356158503140f85ca6442328914451b60e48c5a5eef0fe358a2014c8" + }, + "source/native-profile.json": { + "bytes": 4911, + "git_blob_sha1": "61a7c079563610bf97e4a1076363a5eea10efab9", + "mode": "100644", + "sha256": "02d6c3a7d0c3194a5935341b63f09d79b84957353c584b4a23a7db25c6286ebe" + }, + "source/science_view_entry.c.txt": { + "bytes": 53074, + "git_blob_sha1": "5af0bc368c7394351f7ab746e50bd1467a260774", + "mode": "100644", + "sha256": "e1740fc6c901e09477ff0d934a920ca51dfe1a4b199d14e3433e155f1ef30fb2" + }, + "verify_integrity.py": { + "bytes": 984, + "git_blob_sha1": "f3d423d63388dd4033f5ff55729aa0eca70df824", + "mode": "100644", + "sha256": "08a6b3615ae19f61dd2ea58172d22b539cc2ef79ffa25e3635b71d6505e0fdf5" + } + }, + "schema": "native-view-facts-integrity-v1", + "scope": "exact archive bytes only, no native/scientific qualification" +} diff --git a/research/h25-native-view-facts/NOTICE.md b/research/h25-native-view-facts/NOTICE.md new file mode 100644 index 0000000000..895e4d6b86 --- /dev/null +++ b/research/h25-native-view-facts/NOTICE.md @@ -0,0 +1,7 @@ +# Attribution and license + +Retain the original native entry and custody lineage of Chris R / Clear1nsight, Douglas R. Colkitt and the repository contributors, including unpaidmoon / Cursor-Grok's primary-preserving cleanup. Immediate predecessors are PRs #6819 and #6818; the original investigation is PR #6321. The exact compiler-source/data predecessors remain credited through PRs #6362, #6366, #6434 and #6454. + +Prepared with substantial ChatGPT Pro, OpenAI Codex and GPT-6.1-sol Max source implementation and independent agent review assistance. These are scoped AI source reviews and finite observations, not human or proof-kernel acceptance. + +New contribution material is Apache-2.0, consistent with the repository. Existing notices remain in the copied source. Kernel implementations are external Linux v6.12 references under their own licenses; the entry uses the public syscall ABI. The exact external source index and hashes are supplied for acquisition, rather than representing those source bodies as part of this export. No GCC-derived executable implementation is relicensed here. diff --git a/research/h25-native-view-facts/PROVENANCE.json b/research/h25-native-view-facts/PROVENANCE.json new file mode 100644 index 0000000000..f98d273b2d --- /dev/null +++ b/research/h25-native-view-facts/PROVENANCE.json @@ -0,0 +1,276 @@ +{ + "actual_kernel_probe": false, + "base": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "created_utc": "2026-11-07T01:05:24.934244+00:00", + "external_sources": "Linux v6.12 source bodies are not included; reacquire using proof/primary index and exact Git/SHA256 identities. Original complete scientific payload remains external at pinned predecessor PRs.", + "original_whole_caller_accepted": false, + "schema": "native-view-facts-source-export-v1", + "source_bytes": { + "controls/OPERATION-PLAN-v1.md": { + "bytes": 6749, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/OPERATION-PLAN-v1.md", + "sha256": "9fe746735348bdc4e0097c374db8596575fdf32a62f94fad71e96d5d4b59746f" + }, + "controls/changed_policy_control.c.txt": { + "bytes": 7089, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/changed_policy_control.c", + "sha256": "5a2529728985028865276d116f5c567e3c613e4f8f0356f9070857206318c2eb" + }, + "controls/native_fact_control.c.txt": { + "bytes": 7734, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/native_fact_control.c", + "sha256": "b7b7cfe5ebbebead55791b121b2fdb5e15d2736aafaa4a2e781e99de44ffd5fd" + }, + "evidence/ACTUAL-POLICY-LEDGER.json": { + "bytes": 4715, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native-accounting/LEDGER-001.json", + "sha256": "51e025a94f367f4d2610439f2183ed8af8ccc560dadb1e23e74fa44592288a3d" + }, + "evidence/PARENT-ADMISSION.json": { + "bytes": 2315, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/control/NATIVE-PROPOSAL-CONTROL-ADMISSION-v1.json", + "sha256": "5f23c8d4277a1ff781f94a33b2c65bb1651997b79354b89ba558c338a8ce2c53" + }, + "evidence/PRE-RETIREMENT.json": { + "bytes": 280, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native-outer/PRE-RETIREMENT.json", + "sha256": "b8fa6c00550948a43649cb280b710947dc0132b63a25b7123ce6bec8b3633e36" + }, + "evidence/RESULT.json": { + "bytes": 1541, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/RESULT.json", + "sha256": "5d853d07aaaaccddaa6c071129e3680da4cf6968d435918b167d4de397f4ff07" + }, + "evidence/native_controls_outer_owner.py.txt": { + "bytes": 3663, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/validation/native_controls_outer_owner.py", + "sha256": "a053760af494243276906d80a52515a7f1f7b5130b383ffa41ac114770c61dfa" + }, + "evidence/run_native_proposal_controls.py.txt": { + "bytes": 8306, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/validation/run_native_proposal_controls.py", + "sha256": "16bb421046a08a96efe328e8c60193bc0983fc5ade948a370e3924bcf4f173b2" + }, + "evidence/steps/changed_policy_control-BINARY-PIN.json": { + "bytes": 101, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/changed_policy_control-BINARY-PIN.json", + "sha256": "afa55d83c4c660693357a5c32a75cf0fdd6a06f2f72f4642e2a36cd5d7739451" + }, + "evidence/steps/compile-changed_policy_control/BIRTH.json": { + "bytes": 61, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-changed_policy_control/BIRTH.json", + "sha256": "823840626d21cf6f505ffb97241945a7f582a4e9173fb1e67dd11e8f10de96ff" + }, + "evidence/steps/compile-changed_policy_control/RESULT.json": { + "bytes": 263, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-changed_policy_control/RESULT.json", + "sha256": "00b279d15adfd6730222914ee8616b713301b42f0d3fd677352d0d9d805a197b" + }, + "evidence/steps/compile-changed_policy_control/START.json": { + "bytes": 752, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-changed_policy_control/START.json", + "sha256": "89056e04bc4b553a49a84e5d69dc723d9c4ac768c6ed2f5a491acd2d4cecebeb" + }, + "evidence/steps/compile-changed_policy_control/stderr.raw": { + "bytes": 5437, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-changed_policy_control/stderr.raw", + "sha256": "fa440e57a7f79241f2d70d431bd116cccc35298b0cb6815309ee3d9e5bb7eff6" + }, + "evidence/steps/compile-changed_policy_control/stdout.raw": { + "bytes": 0, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-changed_policy_control/stdout.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/compile-native_fact_control/BIRTH.json": { + "bytes": 62, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-native_fact_control/BIRTH.json", + "sha256": "b23dab1d5961c920e59899abdadb23dce4c7ec27879f1e8c89d2a66592d65cdf" + }, + "evidence/steps/compile-native_fact_control/RESULT.json": { + "bytes": 259, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-native_fact_control/RESULT.json", + "sha256": "5137a06c4b9d8762971cd0358414ec3f425daa33829aad1eac0d863222fa14e6" + }, + "evidence/steps/compile-native_fact_control/START.json": { + "bytes": 746, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-native_fact_control/START.json", + "sha256": "8e8c37b906bf2c46d5af3bc134c515917b77219b24631aec85756aeb7da27e1b" + }, + "evidence/steps/compile-native_fact_control/stderr.raw": { + "bytes": 5433, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-native_fact_control/stderr.raw", + "sha256": "3f46ee589b4952248f3bbae97f3ec184540065b704a010781b3b52c9bd23cc45" + }, + "evidence/steps/compile-native_fact_control/stdout.raw": { + "bytes": 0, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-native_fact_control/stdout.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/native_fact_control-BINARY-PIN.json": { + "bytes": 101, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/native_fact_control-BINARY-PIN.json", + "sha256": "d7759172dd0335674673e70a94ca1bda2e54e36dbc2e62e1d190c7451c126eb3" + }, + "evidence/steps/run-changed_policy_control/BIRTH.json": { + "bytes": 62, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-changed_policy_control/BIRTH.json", + "sha256": "e5a1c038e757cf92e750439369495ab1ca23eb5ca72fdfe458a2b7bec32f8360" + }, + "evidence/steps/run-changed_policy_control/RESULT.json": { + "bytes": 258, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-changed_policy_control/RESULT.json", + "sha256": "845b43883e4cecac25a6d1367f2803f0253d52f38a30e425df1b6e0d6d6f3d69" + }, + "evidence/steps/run-changed_policy_control/START.json": { + "bytes": 392, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-changed_policy_control/START.json", + "sha256": "a4d6e61ecef7497c7f5b7f7edf0952aec47d33ac8a7ff99b9b3228d0f8f8c18c" + }, + "evidence/steps/run-changed_policy_control/stderr.raw": { + "bytes": 0, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-changed_policy_control/stderr.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/run-changed_policy_control/stdout.raw": { + "bytes": 0, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-changed_policy_control/stdout.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/run-native_fact_control/BIRTH.json": { + "bytes": 62, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-native_fact_control/BIRTH.json", + "sha256": "65ff47c679a2d53b86171634bcaf6fb0db4bb3f5ff506868287572f47216840c" + }, + "evidence/steps/run-native_fact_control/RESULT.json": { + "bytes": 255, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-native_fact_control/RESULT.json", + "sha256": "d788050e64135b4aabc6a078ccf9db9881ee86be947007352cd0be6199f9eded" + }, + "evidence/steps/run-native_fact_control/START.json": { + "bytes": 389, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-native_fact_control/START.json", + "sha256": "e296e8af3c879c3c04566e62309612890d9f1234c7c8e0481317651222825062" + }, + "evidence/steps/run-native_fact_control/stderr.raw": { + "bytes": 0, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-native_fact_control/stderr.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "evidence/steps/run-native_fact_control/stdout.raw": { + "bytes": 64, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-native_fact_control/stdout.raw", + "sha256": "e938ab0debc79b2a1578b478231fb7fa9919cdfd0849d7922e4b75c9d4bc9110" + }, + "proof/COMPILER-SCRATCH-LINEAGE.md": { + "bytes": 4432, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/COMPILER-SCRATCH-LINEAGE-v1.md", + "sha256": "9abb05a5f3b0aa86f08f6844a7a01287fbc80dfe246f6facafa973cbf9549902" + }, + "proof/CONFIG-AND-INHERITANCE-LEMMAS-v1.md": { + "bytes": 12380, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/CONFIG-AND-INHERITANCE-LEMMAS-v1.md", + "sha256": "a5e697ed5d3bc443069f0ec7d929dd56f61804c3a764894ebc9db84741700dfb" + }, + "proof/KERNEL-LEMMAS-v1.md": { + "bytes": 17084, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/KERNEL-LEMMAS-v1.md", + "sha256": "3fa107a85ad5f682cb9ea7ebe5ac562e1ab1c686272d363ef4c33470e1b49b52" + }, + "proof/LSM-ACQUISITION-ABI-v1.md": { + "bytes": 3176, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/LSM-ACQUISITION-ABI-v1.md", + "sha256": "f886e5c749e07f3cd410f5403d4147a535209bfccd8381249c832ba9a2f0c303" + }, + "proof/METADATA-PRIMITIVE-LEMMA-v1.md": { + "bytes": 5559, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/METADATA-PRIMITIVE-LEMMA-v1.md", + "sha256": "c7c5d4002035ef647b6129c1be244900870f6a4b1da1cd84c37112d05cf69500" + }, + "proof/MOUNT-CENSUS-LEMMA-v1.md": { + "bytes": 6903, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/MOUNT-CENSUS-LEMMA-v1.md", + "sha256": "2598bbb04d8a68ca6a1148547de0a9f0c790012518afb309e0796f7ad5b67f9d" + }, + "proof/NATIVE-ENTRY-INVARIANTS.md": { + "bytes": 18911, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/NATIVE-ENTRY-INVARIANTS-v1.md", + "sha256": "62c31378b5ddf7c4237c44b29cfa9de5fc63a155f5c9da5fe3e97645724e0019" + }, + "proof/ORIGINAL-NATIVE-CONSUMERS.md": { + "bytes": 16325, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/ORIGINAL-NATIVE-CONSUMERS-v1.md", + "sha256": "f93404aadfed12de369d422c68916b1697d5b3b11006f62301d79428ce153f58" + }, + "proof/ROOT-REFERENCE-LEMMA.md": { + "bytes": 8458, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/ROOT-REFERENCE-LEMMA-v1.md", + "sha256": "8a2602008726347232e89812fb959974785d21b5c012f6b8fb4a336fe1a05534" + }, + "proof/TMPDIR-CALLER-LEMMA-v1.md": { + "bytes": 2940, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/TMPDIR-CALLER-LEMMA-v1.md", + "sha256": "e5488995cff1a186f3fde4f167aee5091b9dbdebac27eea0f26769af490e8943" + }, + "proof/primary/INDEX.json": { + "bytes": 12652, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/INDEX-v7.json", + "sha256": "ad8f24992e56ee040b11faee080b49d5959b63664ee4e4672f1664db11e2bbc5" + }, + "proof/primary/SHA256SUMS.txt": { + "bytes": 4912, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/SOURCE-SHA256SUMS-v6.txt", + "sha256": "18cfbd9a955097e25246142beebdc0e964ad7e6beeff3707ad452d53e4c39377" + }, + "proof/remaining-binutils-source-transfer.md": { + "bytes": 2639, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/binutils/REVIEW-v1.md", + "sha256": "7381e32912f0e2157a210348100b94a61e79e96be97940ff9a170754100b9080" + }, + "review/ACTUAL-NATIVE-ACQUISITION-REVIEW-v1.md": { + "bytes": 13275, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/ACTUAL-NATIVE-ACQUISITION-REVIEW-v1.md", + "sha256": "7a713c65cf1ba2827b872f0c73efb64e07ed2d87b370b1afe898667e4091f35a" + }, + "review/NATIVE-PROPOSAL-GUARD-REVIEW-v1.md": { + "bytes": 5777, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/NATIVE-PROPOSAL-GUARD-REVIEW-v1.md", + "sha256": "81eee191ae1706932ab8b75b6c2de74e8014550e8cf43ab2846ff6e9bc51e435" + }, + "review/NEW-MOCK-RESULT-READBACK-v1.md": { + "bytes": 2091, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/NEW-MOCK-RESULT-READBACK-v1.md", + "sha256": "d6db1530ef6f7babda64ce794c6fdf828df8e256b06aae2a10b00a724dcf7e0b" + }, + "source/ACQUISITION-CONSTRUCTION.md": { + "bytes": 11068, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/ACTUAL-ACQUISITION-CONSTRUCTION-v1.md", + "sha256": "71bd6cf1633bee944095394cfc466d7c51ac3f28f606bbffb1fa65f842628964" + }, + "source/EXACT-NATIVE-CHANGE.diff": { + "bytes": 22431, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/proposal/native-entry-simplification.patch", + "sha256": "d364b986ae881b0064aae2b161ab6ec1589eddbca921b059bad43313d7344dc6" + }, + "source/VIEW-ENTRY-CONTRACT-v1.md": { + "bytes": 33378, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/proposal/VIEW-ENTRY-CONTRACT-v1.md", + "sha256": "b9e3a1b4356158503140f85ca6442328914451b60e48c5a5eef0fe358a2014c8" + }, + "source/native-profile.json": { + "bytes": 4911, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/proposal/native.json", + "sha256": "02d6c3a7d0c3194a5935341b63f09d79b84957353c584b4a23a7db25c6286ebe" + }, + "source/science_view_entry.c.txt": { + "bytes": 53074, + "original_path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/proposal/science_view_entry.c", + "sha256": "e1740fc6c901e09477ff0d934a920ca51dfe1a4b199d14e3433e155f1ef30fb2" + } + }, + "source_scope": "exact frozen native proposal, conditional source proof, two new mocked controls and actual bounded results", + "substantial_AI_assistance": [ + "ChatGPT Pro", + "OpenAI Codex", + "GPT-6.1-sol Max" + ] +} diff --git a/research/h25-native-view-facts/README.md b/research/h25-native-view-facts/README.md new file mode 100644 index 0000000000..55fc14d597 --- /dev/null +++ b/research/h25-native-view-facts/README.md @@ -0,0 +1,53 @@ +# Bounded native security and mount facts + +This source archive supplies a concrete successor native-entry proposal that acquires and checks its active security-module and mount subjects. It also supplies conditional kernel proofs and the actual results of two new mocked-constructor controls. It is a completed native prerequisite within a larger caller-preservation investigation. The complete compiler/caller proof and connected parent integration remain open. The proposal is not installed or selected as a production image. + +## Implemented construction + +The entry acquires the complete two-ID capability/Landlock module result. It uses 129 enumeration slots to enforce a 128-mount bound, validates returned statmount masks and type-string extents, rejects unanalysed or idmapped classes, and joins held file descriptors to genuine unique mount IDs. It checks the before/after topology against exactly two owned artifact/usage clones. These decisions are derived inside the source owner from actual syscall results, not supplied compatible flags. + +The selected prospective model is Linux v6.12 on native LP64 x86-64, capability plus Landlock, no miscellaneous binary-format handler, no core-dump implementation and no module loading. For that different model the successor removes the predecessor's private binfmt-instance and forced CORE setup. It preserves inherited CORE limits and ordinary self resource-limit operations. PR #6819 remains credited for its separately selected built-in-binfmt model. No workstation configuration was changed. + +The source and proof distinguish acquired facts from original native trust premises. In particular, null initial Landlock domain, initial seccomp mode zero, no effective ancestor cgroup BPF attachment, genuine source/build/image association and the closed native interval remain explicit unissued qualification conditions. Module membership and successful mount setup do not prove those states. The finite filesystem catalogue does not imply arbitrary compiler or helper effects are harmless. + +The complete source resource calculation is 31 lifetime FD births within cap 96, peak 13 tracked / 15 actual FDs, the existing 48-error cap, and 268 successful-path acquisition calls within a 288-attempt bound. These are source bounds, not measured native fit or zero physical cost. The entry's error/once-close owner, actual object checks, final image authentication, real Landlock success witness and final filter remain in the existing owner. + +## Proof and source identity + +`source/science_view_entry.c.txt` is the exact reviewed 53,074-byte proposal, SHA256 `e1740fc6c901e09477ff0d934a920ca51dfe1a4b199d14e3433e155f1ef30fb2`. The C and control snapshots are inert `.txt` files. `source/EXACT-NATIVE-CHANGE.diff` compares this proposal with the unchanged predecessor C at SHA256 `60af72915efea62f46ea376e2ba7ed0c616f99b09ca1beec0f4b0d8173609410`. The source/profile/contract and original controls have not been silently repinned or adopted into the full caller. + +The proof documents establish the copied-root/proc-reference relation, capability/label and inherited-Landlock distinctions, disabled dispatch/core/module consequences, ordinary metadata write checks, mount-census ABI/completeness, and actual original compiler TMPDIR lineage. The original driver sets artifact-local TMPDIR before its three compiler families; no writable `/tmp` exception was added. External kernel bodies are acquired through `proof/primary/INDEX.json` and checked against its Git identities plus `SHA256SUMS.txt`; those external bodies are intentionally not copied into this package. + +## Actual validation + +One independently admitted serial attempt compiled and ran each of two NEW controls once. All four steps returned zero, completed both raw EOFs, had known waits and recorded no errors. The policy control produced empty stdout/stderr. The native-fact control produced its exact 64-byte success line and empty stderr. Each compilation retained five `-Wmisleading-indentation` warnings; both complete streams are included and were independently read. The command deliberately retained that warning class while treating other enabled warnings as errors. This is not a warning-free build. + +The controls call the actual proposed helpers/filter constructor through mocked native boundaries. Their independent oracles cover complete/extra/duplicate module results, enumeration saturation and malformed fields, idmapping and unknown classes, held-FD identity/mount joins, two-clone topology and metadata recurrences, query capacity, raw errors and changed self-resource filter arguments. They never invoke the production namespace entry or actual kernel-security queries. Predecessor controls were not rerun. + +The outer owner retires its still-owned entire process group on every guard exit. Its deliberate exit 137 is cleanup, not the test oracle; acceptance comes from the four exact result records and raw captures. Two rejected wrapper lifetime designs were corrected before the single attempt. The exact accepted guard/outer source and reviews are retained. + +The conservative new policy debit is 64 seconds: recorded aggregate 1,520.890533479 / 2,400 seconds, remaining 879.109466521. The actual outer tool wait was 0.644983519 seconds. Policy debit is not complete physical cost; source preparation, Pro/agent review, reporting, network, publication, final metadata and historical gaps remain `OPEN_NOT_ZERO`. + +Integrity only, from a fresh exported checkout: + +```sh +python3 -B research/h25-native-view-facts/verify_integrity.py +``` + +No native or scientific replay is registered. Native reproduction needs a separately authorized fresh layout and reviewed compiler/guard envelope. The recorded absolute-path wrapper is evidence of the actual local attempt, not a portable execution command. Materializing or repinning snapshots requires a fresh binding review; do not rerun into the recorded existing directories. The control snapshots include the source through their recorded proposal/controls layout. + +## Scope, lineage and remaining work + +Original investigation: [PR #6321](https://github.com/CrocSwap/integer-mult-bounds/pull/6321). Immediate entry predecessor: [PR #6819](https://github.com/CrocSwap/integer-mult-bounds/pull/6819), exact head `65b0c1b71e849cbbe2160c211811d18d43e25e55`. Connected source/optimized-refusal predecessor: [PR #6818](https://github.com/CrocSwap/integer-mult-bounds/pull/6818), exact head `1479ccf2ec0bc29b7bf741a2d613d79e1f9ec19e`. Complete original caller selection: [PR #6744](https://github.com/CrocSwap/integer-mult-bounds/pull/6744). Canonical publication base is `7c49fe32c55de02c2c873655c804b16e4c3fef0a`. + +The delivered scope is refined to this independently accepted native acquisition implementation; the original whole-caller objective and criteria are unchanged. Pro constructed further finite GCC driver/configuration and temporary-fallback arguments. The first remaining mathematical transfer concerns the exact applied Ubuntu binutils 2.42-4ubuntu2.10 assembler/linker/BFD bodies and configuration. The ordered 54-patch series and source archives are retained, but the patch bodies and applied runtime units were not reviewed in this bounded round. Package-byte identity alone does not prove preservation of the inspected upstream effect frontiers. + +The full parent compiler-property/specs/fallback acquisition and checked query-output protocol are also not implemented in the frozen caller graph. Thus no complete caller-source acceptance, current native qualification, full baseline/candidate equality, measured optimization or new mathematical multiplication bound is claimed. The original activity count is unchanged. See `proof/remaining-binutils-source-transfer.md` for the exact resolving input, rather than repeating an unchanged missing-proof audit. + +## Open next questions + +1. Review the exact retained Ubuntu binutils patch bodies in order and the affected applied assembler/linker/BFD runtime units and configuration. Establish the specific I/O, cleanup, option/script/plugin and output/chmod frontier transfer. This is the next mathematical dependency; another current-host PASS or a generic GCC diagnostic does not replace it. +2. Join the completed compiler/native theorem and genuine factual acquisition to the existing parent, loader and role-contract owners, including the explicit temporary-fallback class and complete checked query transport. Preserve the original commands, distinct error protocols, one-use token, interval, writers and retention. +3. Independently accept that complete graph before genuine current-image/resource/funding/native/scientific admission. This archive supplies no authority or automatic next research round. + +See `NOTICE.md` for predecessor credit, source licenses and substantial AI assistance. diff --git a/research/h25-native-view-facts/controls/OPERATION-PLAN-v1.md b/research/h25-native-view-facts/controls/OPERATION-PLAN-v1.md new file mode 100644 index 0000000000..a0d8f20390 --- /dev/null +++ b/research/h25-native-view-facts/controls/OPERATION-PLAN-v1.md @@ -0,0 +1,34 @@ +# Changed-branch component operation proposal — not admitted or executed + +The parent requested a concrete source proposal while Pro completes the full construction. The selected predecessor C remains unchanged at SHA256 `60af72915efea62f46ea376e2ba7ed0c616f99b09ca1beec0f4b0d8173609410`. The sibling `proposal/` directory contains editable **proposal copies** and three actual unified diffs; none has been applied to a selected implementation. + +## Proposed changed source + +`native-entry-simplification.patch` removes entry-installed CORE(1,1), the private binfmt context owner and its obsolete status/build fields, and the CORE-specific self-resource denials. It retains the actual namespace/view/stdin/capability/NNP/Landlock owner, the checked `landlocked=true` assignment only after successful restrict-self, the error/close barriers, final image authentication and the fixed final exec. It restores ordinary self setrlimit arguments for all resources. prlimit64 retains its existing pid-zero self slice, with all resource and pointer arguments passed to native kernel validation. Positive nonzero-PID self aliases are not claimed admitted; no inspected original resource consumer requires them and classic seccomp cannot identify all future descendant self PIDs dynamically. + +`native-profile-simplification.patch` and `native-contract-simplification.patch` remove the incompatible built-in-binformat and CORE-installation claims and replace them with the exact prospective same-kernel configuration. Their text expressly requires genuine original native qualification and the completed finite theorem. This metadata is not a compatibility flag or a host assertion. The source proposal does not add chroot or a `/tmp` write exception; the current root-reference proof and original compiler TMPDIR lineage are retained. + +The constructive acquisition proposal adds actual LSM enumeration, two bounded mount censuses and nine initial plus two clone object joins. Registry slots become 31, including initial FD0 adoption and five additional association anchors; peak stays 13 tracked / 15 actual FDs because those anchors close before final cwd/stdin and Landlock acquisition. New acquisition attempts reserve from a separate 288-position bound, with at most 268 on the maximum successful path. The unchanged once-close/error helpers and their existing predecessor evidence are reused by exact source comparison. The eight prior dispatch mock groups remain closed evidence for their old C subject. They are not silently retargeted to a successor lacking that helper and are not requested for rerun. + +## Meaningful new control source + +`changed_policy_control.c` includes the actual proposed entry C and calls its real `install_seccomp` constructor. It mocks only the native install boundary and forbids an unexpected direct syscall/close from the control path. A separate small forward-only cBPF evaluator checks the actual emitted instructions against explicit operation oracles; it does not reimplement the entry's resource-dispatch source. + +The changed-branch oracles require: + +1. Self setrlimit, including CORE and invalid resource/pointer values, reaches the native kernel decision rather than a new policy error. +2. Pid-zero prlimit queries and mutations, including CORE, high-word pointers and invalid resources, are admitted without inspecting their resource/pointer content. Nonzero process targets remain denied; the selected pid_t low32 normalization case stays explicit. +3. Shortening the resource branches does not bypass default lockdown, exact clone tuples, clone3 ENOSYS or architecture/x32 gating. Removed setup syscalls do not become available to science. +4. A mocked install error retains its actual errno and leaves `filtered` false. It cannot manufacture a successful restriction witness. + +No namespace, resource-limit, mount or real filter-install syscall is used by these control bodies. They do not test the prospective kernel's actual feature/configuration or execute the native entry path. A component pass would establish only compilation and these source/policy consequences, not a kernel association, full Q proof, scientific result or source-native executable equivalence of a control binary. + +`native_fact_control.c` separately includes the actual proposed owner and calls its actual LSM/census/result/object-join/graph helpers. Its syscall and fstat boundaries are mocked for every reached acquisition. Explicit operation oracles check the complete two-ID LSM result and wrong count/duplicate/extra results; raw E2BIG and EACCES ordering; 129-slot enumeration and saturated refusal; duplicate IDs and mixed namespace results; missing returned-mask bits; invalid string offset and NUL extent; idmapped or delegated classes; actual held-object request shape and unique-ID join; absent unique-ID result bit, unknown returned ID and changed inode; the exact two-clone relation; writable-base, wrong-parent and wrong-backing recurrences; and capacity reservation before a syscall. The synthetic mount graph contains one original root and two exact clones, so expected results are independent finite facts rather than a second implementation of the traversal. This component does not turn mocked data into a genuine original native association. + +## Proposed admission sequence and bounds + +No compile, run, import or test is authorized by this document. After the completed Pro construction and exact independent review, the parent may separately admit **one** guarded C compilation and **one** bounded execution for each of these two exact component sources under the existing policy budget. The exact compiler/flags/guarded command must be selected and recorded by the original parent; there is no shell script or automatic execution here. Proposed enclosing ceilings are 30 seconds for the two compilations together and 2 seconds for each small control, subject to the actual existing guard, memory/output caps and remaining budget. These are proposed ceilings, not measured fit or a new grant. + +The actual selected native entry must not be executed by that component operation, and the control executable must never be reused as its native image. Its mocked install boundary is deliberately a different compiled subject. Loader/compiler/start/exit/capture costs still enter the existing enclosing bill. A failure preserves raw output/error and ends that admitted operation; it does not trigger retry, another budget or scientific execution. + +For source-only review now, inspect the three diffs, compare the predecessor/proposal hashes, verify that once-close and Landlock-success code is unchanged, and check the independent evaluator's explicit expected actions. No control has been run to obtain the current proposal. diff --git a/research/h25-native-view-facts/controls/changed_policy_control.c.txt b/research/h25-native-view-facts/controls/changed_policy_control.c.txt new file mode 100644 index 0000000000..60fe079005 --- /dev/null +++ b/research/h25-native-view-facts/controls/changed_policy_control.c.txt @@ -0,0 +1,116 @@ +/* PROPOSED, UNEXECUTED controls of the actual proposed policy constructor. + * No namespace/limit/mount/seccomp syscall is executed by these controls. + * The native install boundary is mocked; a small independent forward-only + * cBPF evaluator checks the emitted policy against explicit operation oracles. + * Compile/run only after exact independent GO and parent guarded admission. */ +#define prctl changed_mock_prctl +#define syscall changed_mock_syscall +#define close changed_mock_close +#define main changed_unused_entry_main +#include "../proposal/science_view_entry.c" +#undef main +#undef close +#undef syscall +#undef prctl +#include + +static struct sock_fprog captured; +static int failures,install_calls,install_errno,unexpected_native_calls; +static void check(bool value,const char *label) { + if(!value){fprintf(stderr,"control failure: %s\n",label);failures++;} +} +int changed_mock_prctl(int operation,...) { + va_list ap;va_start(ap,operation); + int mode=va_arg(ap,int);struct sock_fprog *filter=va_arg(ap,struct sock_fprog *); + install_calls++; + check(operation==PR_SET_SECCOMP&&mode==SECCOMP_MODE_FILTER,"only filter installation is reached"); + check(filter&&filter->filter==program&&filter->len==program_count&&filter->len>0, + "actual constructor supplies its emitted program"); + if(filter)captured=*filter; + va_end(ap); + if(install_errno){errno=install_errno;return -1;}return 0; +} +long changed_mock_syscall(long operation,...) { + (void)operation;unexpected_native_calls++;errno=ENOSYS;return -1; +} +int changed_mock_close(int descriptor) { + (void)descriptor;unexpected_native_calls++;errno=EBADF;return -1; +} +static uint32_t evaluate(const struct seccomp_data *input) { + uint32_t accumulator=0;size_t pc=0; + for(size_t steps=0;steps<=captured.len&&pccode) { + case BPF_LD|BPF_W|BPF_ABS: + if(instruction->k>sizeof(*input)-sizeof accumulator) { + check(false,"load stays within seccomp input");return UINT32_MAX; + } + memcpy(&accumulator,(const unsigned char *)input+instruction->k,sizeof accumulator); + pc++;break; + case BPF_JMP|BPF_JEQ|BPF_K: + pc+=1+(accumulator==instruction->k?instruction->jt:instruction->jf);break; + case BPF_JMP|BPF_JSET|BPF_K: + pc+=1+((accumulator&instruction->k)?instruction->jt:instruction->jf);break; + case BPF_RET|BPF_K: + return instruction->k; + default: + check(false,"only reviewed forward cBPF instructions occur");return UINT32_MAX; + } + } + check(false,"program reaches a bounded return");return UINT32_MAX; +} +static struct seccomp_data call(int number,uint64_t a0,uint64_t a1,uint64_t a2,uint64_t a3) { + struct seccomp_data input={.nr=number,.arch=AUDIT_ARCH_X86_64}; + input.args[0]=a0;input.args[1]=a1;input.args[2]=a2;input.args[3]=a3; + return input; +} +static void expect(struct seccomp_data input,uint32_t action,const char *label) { + check(evaluate(&input)==action,label); +} +static void reset_constructor(void) { + program_count=error_count=0;filtered=false;uncertain=error_overflow=false; + captured=(struct sock_fprog){0};install_calls=install_errno=unexpected_native_calls=0; +} +int main(void) { + reset_constructor(); + check(install_seccomp()&&filtered&&install_calls==1&&!error_count, + "actual proposed constructor commits only successful installation"); + /* These are operation oracles, not a reimplementation of the resource + * filter. Pointer/resource contents are opaque to seccomp and must reach + * native kernel validation, including its original EFAULT/EINVAL cases. */ + expect(call(SYS_setrlimit,RLIMIT_CORE,0,0,0),SECCOMP_RET_ALLOW,"self CORE NULL pointer reaches kernel"); + expect(call(SYS_setrlimit,RLIMIT_CORE,UINT64_C(0x100000000),0,0),SECCOMP_RET_ALLOW,"self CORE high-word pointer reaches kernel"); + expect(call(SYS_setrlimit,RLIMIT_FSIZE,7,0,0),SECCOMP_RET_ALLOW,"original child FSIZE setter admitted"); + expect(call(SYS_setrlimit,UINT64_MAX,3,0,0),SECCOMP_RET_ALLOW,"invalid resource retains native errno owner"); + expect(call(SYS_prlimit64,0,RLIMIT_CORE,0,9),SECCOMP_RET_ALLOW,"self CORE query admitted"); + expect(call(SYS_prlimit64,0,RLIMIT_CORE,UINT64_C(0x100000000),0),SECCOMP_RET_ALLOW,"self CORE mutation admitted"); + expect(call(SYS_prlimit64,0,RLIMIT_FSIZE,11,13),SECCOMP_RET_ALLOW,"original self FSIZE query/mutation admitted"); + expect(call(SYS_prlimit64,0,UINT64_MAX,17,19),SECCOMP_RET_ALLOW,"prlimit invalid resource retains native errno owner"); + expect(call(SYS_prlimit64,UINT64_C(0x100000000),RLIMIT_CORE,7,0),SECCOMP_RET_ALLOW,"pid_t low32 normalization preserves self"); + expect(call(SYS_prlimit64,1234,RLIMIT_CORE,0,7),SECCOMP_RET_ERRNO|EPERM,"nonzero process query remains excluded"); + expect(call(SYS_prlimit64,1234,RLIMIT_FSIZE,7,0),SECCOMP_RET_ERRNO|EPERM,"nonzero process mutation remains excluded"); + /* Adjacent branches ensure that shortening the resource dispatch did not + * bypass the existing lockdown/default or architecture discriminator. */ + enum {NR_FSOPEN=430,NR_FSCONFIG=431,NR_FSMOUNT=432,NR_FSPICK=433}; + const int excluded[]={NR_FSOPEN,NR_FSCONFIG,NR_FSMOUNT,NR_FSPICK,SYS_mount, + SYS_mount_setattr,SYS_open_tree,SYS_setns,SYS_unshare,SYS_pidfd_getfd, + SV_NR_STATMOUNT,SV_NR_LISTMOUNT,SV_NR_LSM_LIST_MODULES}; + for(size_t i=0;i + +static int failures, mock_errno, mock_mode, mock_calls; +int fact_mock_fstat(int fd,struct stat *st) { + (void)fd;memset(st,0,sizeof *st);st->st_dev=makedev(8,1);st->st_ino=99;st->st_mode=S_IFREG|0600;return 0; +} +static void check(bool value,const char *label) { + if(!value){fprintf(stderr,"control failure: %s\n",label);failures++;} +} +static struct sv_statmount_buffer mount_buffer(uint64_t id,uint64_t parent,const char *type) { + struct sv_statmount_buffer b={0}; + b.h=(struct sv_statmount_head){.size=512+(uint32_t)strlen(type)+1, + .mask=SV_STATMOUNT_MASK,.dev_major=8,.dev_minor=1,.magic=0xef53, + .id=id,.parent=parent,.propagation=MS_PRIVATE,.ns=9}; + memcpy(b.str,type,strlen(type)+1);return b; +} +long fact_mock_syscall(long operation,...) { + va_list ap;va_start(ap,operation);mock_calls++; + if(mock_errno){va_end(ap);errno=mock_errno;return -1;} + if(operation==SV_NR_LSM_LIST_MODULES) { + uint64_t *ids=va_arg(ap,uint64_t *);uint32_t *bytes=va_arg(ap,uint32_t *); + unsigned flags=va_arg(ap,unsigned); + check(*bytes==16&&flags==0,"LSM request uses actual fixed capacity and flags"); + ids[0]=110;ids[1]=100;*bytes=16;va_end(ap);return mock_mode==1?1:2; + } + if(operation==SV_NR_LISTMOUNT) { + struct sv_mnt_request *req=va_arg(ap,struct sv_mnt_request *); + uint64_t *ids=va_arg(ap,uint64_t *);size_t slots=va_arg(ap,size_t); + unsigned flags=va_arg(ap,unsigned); + check(req->size==32&&!req->spare&&req->id==UINT64_MAX&&!req->param&&!req->ns&& + slots==129&&flags==0,"listmount requests M plus one from current actual root"); + ids[0]=1;ids[1]=mock_mode==3?1:2;va_end(ap);return mock_mode==2?129:2; + } + if(operation==SV_NR_STATMOUNT) { + struct sv_mnt_request *req=va_arg(ap,struct sv_mnt_request *); + struct sv_statmount_buffer *b=va_arg(ap,struct sv_statmount_buffer *); + size_t capacity=va_arg(ap,size_t);unsigned flags=va_arg(ap,unsigned); + check(req->size==32&&!req->spare&&!req->ns&&req->param==0x63&& + capacity==sizeof *b&&flags==0,"statmount requests only callback-free selected fields"); + *b=mount_buffer(req->id,1,"ext4"); + if(mock_mode==4&&req->id==2)b->h.ns=10; + va_end(ap);return 0; + } + if(operation==SYS_statx) { + int fd=va_arg(ap,int);const char *path=va_arg(ap,const char *); + int flags=va_arg(ap,int);unsigned mask=va_arg(ap,unsigned); + struct sv_statx *sx=va_arg(ap,struct sv_statx *); + check(fd==77&&!*path&&flags==(AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW)&&mask==0x4103, + "object join requests actual held FD and unique mount mask"); + memset(sx,0,sizeof *sx);sx->mask=mask;sx->mode=S_IFREG|0600;sx->ino=99; + sx->dev_major=8;sx->dev_minor=1;sx->mount_id=1; + if(mock_mode==5)sx->mask&=~0x4000U; + if(mock_mode==6)sx->mount_id=999; + if(mock_mode==7)sx->ino=100; + va_end(ap);return 0; + } + va_end(ap);check(false,"unexpected native acquisition");errno=ENOSYS;return -1; +} +static void reset(void) { + error_count=0;uncertain=error_overflow=lsm_checked=topology_checked=false; + native_queries_started=native_queries_completed=0;mock_errno=mock_mode=mock_calls=0; + memset(&mounts_before,0,sizeof mounts_before);memset(&mounts_after,0,sizeof mounts_after); +} +static struct sv_mount_row row(uint64_t id,uint64_t parent,uint64_t attr) { + struct sv_statmount_buffer b=mount_buffer(id,parent,"ext4");struct sv_mount_row r; + b.h.attr=attr;check(decode_mount(&b,id,&r),"fixture passes actual decoder");return r; +} +int main(void) { + reset();check(read_lsm_stack()&&lsm_checked&&native_queries_started==1&&native_queries_completed==1, + "real LSM owner commits complete exact stack only"); + reset();mock_mode=1;check(!read_lsm_stack()&&!lsm_checked&&error_count==1, + "partial LSM count cannot witness selected stack"); + reset();mock_errno=E2BIG;check(!read_lsm_stack()&&!lsm_checked&&error_count==1&&errors[0].number==E2BIG&& + native_queries_started==1&&native_queries_completed==0,"LSM raw capacity errno precedes failure projection"); + uint64_t duplicate[2]={100,100};check(!valid_lsm_result(2,16,duplicate),"duplicate module ID refused"); + uint64_t extra[2]={100,110};check(!valid_lsm_result(3,24,extra),"additional module cannot be truncated away"); + + reset();check(census(&mounts_before)&&mounts_before.count==2&&native_queries_started==3, + "actual census owner acquires every unsaturated row"); + check(graph_rooted(&mounts_before,1),"actual parent graph reaches held root"); + uint64_t joined=0; + check(join_object(77,&mounts_before,SV_FS_LOCAL,&joined)&&joined==1,"actual object join uses returned unique mount ID"); + mock_mode=5;check(!join_object(77,&mounts_before,SV_FS_LOCAL,&joined),"missing unique-ID result bit refused"); + mock_mode=6;check(!join_object(77,&mounts_before,SV_FS_LOCAL,&joined),"uncatalogued returned unique ID refused"); + mock_mode=7;check(!join_object(77,&mounts_before,SV_FS_LOCAL,&joined),"different actual descriptor inode refused"); + reset();mock_mode=2;check(!census(&mounts_before)&&mock_calls==1,"M plus one saturation refuses before any row query"); + reset();mock_mode=3;check(!census(&mounts_before),"duplicate enumerated ID refused"); + reset();mock_mode=4;check(!census(&mounts_before),"mixed namespace rows refused"); + reset();mock_errno=EACCES;check(!census(&mounts_before)&&error_count==1&&errors[0].number==EACCES, + "listmount actual primary errno retained"); + struct sv_statmount_buffer b=mount_buffer(1,1,"ext4");struct sv_mount_row decoded; + reset();b.h.fs_type=64;check(!decode_mount(&b,1,&decoded),"type offset outside returned string region refused"); + b=mount_buffer(1,1,"ext4");b.h.mask&=~UINT64_C(0x40);check(!decode_mount(&b,1,&decoded),"missing namespace result bit refused"); + b=mount_buffer(1,1,"ext4");b.h.attr=SV_MOUNT_IDMAP;check(!decode_mount(&b,1,&decoded),"idmapped class refused"); + b=mount_buffer(1,1,"fuse");check(!decode_mount(&b,1,&decoded),"unanalysed delegated class refused"); + b=mount_buffer(1,1,"ext4");memset(b.str,'x',sizeof b.str);b.h.size=sizeof b; + check(!decode_mount(&b,1,&decoded),"unterminated type refused within fixed returned extent"); + + reset();mounts_before.count=1;mounts_before.row[0]=row(1,1,0); + mounts_after.count=3;mounts_after.row[0]=row(1,1,3); + mounts_after.row[1]=row(2,1,2);mounts_after.row[2]=row(3,1,2); + check(exact_view_relation(1,1,1,2,3),"exact two attached clones and base readonly relation accepted"); + mounts_after.row[0].h.attr=2;check(!exact_view_relation(1,1,1,2,3),"writable base recurrence refused"); + mounts_after.row[0].h.attr=3;mounts_after.row[1].h.parent=3; + check(!exact_view_relation(1,1,1,2,3),"clone attached under wrong mount refused"); + mounts_after.row[1].h.parent=1;mounts_after.row[2].h.dev_minor=2; + check(!exact_view_relation(1,1,1,2,3),"different clone backing superblock refused"); + reset();native_queries_started=SV_MAX_QUERIES; + check(!read_lsm_stack()&&mock_calls==0&&errors[0].number==E2BIG,"query capacity reserved before native call"); + if(failures)return 1; + puts("unselected native fact control: finite operation oracles passed");return 0; +} diff --git a/research/h25-native-view-facts/evidence/ACTUAL-POLICY-LEDGER.json b/research/h25-native-view-facts/evidence/ACTUAL-POLICY-LEDGER.json new file mode 100644 index 0000000000..3817d8b7f9 --- /dev/null +++ b/research/h25-native-view-facts/evidence/ACTUAL-POLICY-LEDGER.json @@ -0,0 +1,84 @@ +{ + "actual_component_results_accepted_by_parent": true, + "actual_namespace_or_kernel_probe": false, + "actual_outer_tool_exit": 137, + "actual_raw_captures": [ + { + "bytes": 5437, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-changed_policy_control/stderr.raw", + "sha256": "fa440e57a7f79241f2d70d431bd116cccc35298b0cb6815309ee3d9e5bb7eff6" + }, + { + "bytes": 0, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-changed_policy_control/stdout.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "bytes": 5433, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-native_fact_control/stderr.raw", + "sha256": "3f46ee589b4952248f3bbae97f3ec184540065b704a010781b3b52c9bd23cc45" + }, + { + "bytes": 0, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/compile-native_fact_control/stdout.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "bytes": 0, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-changed_policy_control/stderr.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "bytes": 0, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-changed_policy_control/stdout.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "bytes": 0, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-native_fact_control/stderr.raw", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "bytes": 64, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/run-native_fact_control/stdout.raw", + "sha256": "e938ab0debc79b2a1578b478231fb7fa9919cdfd0849d7922e4b75c9d4bc9110" + } + ], + "baseline_policy_seconds": "1456.890533479", + "cap_seconds": 2400, + "combined_policy_seconds": "1520.890533479", + "expected_whole_owned_group_retirement_exit": 137, + "finalized_utc": "2026-11-07T01:00:40.746648+00:00", + "independent_result_review": { + "bytes": 2091, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/NEW-MOCK-RESULT-READBACK-v1.md", + "sha256": "d6db1530ef6f7babda64ce794c6fdf828df8e256b06aae2a10b00a724dcf7e0b" + }, + "new_budget": false, + "new_nonrefundable_policy_debit_seconds": "64", + "no_refunds": true, + "original_caller_execution": false, + "original_credit_delta": 0, + "outer_pre_retirement": { + "bytes": 280, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native-outer/PRE-RETIREMENT.json", + "sha256": "b8fa6c00550948a43649cb280b710947dc0132b63a25b7123ce6bec8b3633e36" + }, + "outer_tool_wall_seconds": 0.644983519, + "outside_preparation_Pro_agents_review_reporting_publication_final_metadata_historical_costs": "OPEN_NOT_ZERO", + "physical_costs": "OPEN_NOT_ZERO", + "prior_reservation": { + "bytes": 1117, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native-accounting/LEDGER-000.json", + "sha256": "9a5eeb51ba34e824f57b8824a7247ae2cb7e0ea516b2c9e6cfa788d8c47b7006" + }, + "remaining_policy_seconds": "879.109466521", + "reserved_outstanding_seconds": 0, + "result": { + "bytes": 1541, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/RESULT.json", + "sha256": "5d853d07aaaaccddaa6c071129e3680da4cf6968d435918b167d4de397f4ff07" + }, + "schema": "guarded-native-proposal-component-actual-ledger-v1", + "whole_source_accepted": false +} diff --git a/research/h25-native-view-facts/evidence/PARENT-ADMISSION.json b/research/h25-native-view-facts/evidence/PARENT-ADMISSION.json new file mode 100644 index 0000000000..9158cd6b0b --- /dev/null +++ b/research/h25-native-view-facts/evidence/PARENT-ADMISSION.json @@ -0,0 +1,44 @@ +{ + "authorized_utc": "2026-11-07T00:58:03.672780+00:00", + "baseline_actual_ledger": { + "bytes": 561, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/native-dispatch-closure-20261106T2206Z/execution-mock/LEDGER-001.json", + "sha256": "dcf67ced06c8223ee3c45237a9872ef72db246bf2c8a24183935e13d3ed8988e" + }, + "baseline_policy_seconds": "1456.890533479", + "cap_seconds": 2400, + "combined_policy_seconds": "1520.890533479", + "component_success_requires": "All four exact step RESULTs, known waits, complete raw captures, expected control bytes, unchanged reviewed pins; expected group-retirement exit alone gives no PASS.", + "debit_seconds": "64", + "execution_GO": true, + "expected_cleanup_terminal_exit": 137, + "guard_sha256": "16bb421046a08a96efe328e8c60193bc0983fc5ade948a370e3924bcf4f173b2", + "independent_guard_vote": "compiler_confinement_feasibility scoped GO at 2026-11-07T00:56:36Z; matching immutable review record being frozen before review cutoff", + "independent_native_review": { + "bytes": 13275, + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/review/proof/ACTUAL-NATIVE-ACQUISITION-REVIEW-v1.md", + "sha256": "7a713c65cf1ba2827b872f0c73efb64e07ed2d87b370b1afe898667e4091f35a" + }, + "new_budget": false, + "original_caller_execution": false, + "original_credit_delta": 0, + "outer_argv": [ + "/usr/bin/timeout", + "--signal=TERM", + "--kill-after=5s", + "45s", + "/usr/bin/python3.12", + "-S", + "-s", + "-P", + "-B", + "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/validation/native_controls_outer_owner.py" + ], + "outer_sha256": "a053760af494243276906d80a52515a7f1f7b5130b383ffa41ac114770c61dfa", + "parent_authorization": "User explicitly requested proof construction, implementation, verification and upstream; this admits only the two NEW independently accepted mocked constructor sources, never production/science.", + "physical_costs": "OPEN_NOT_ZERO", + "production_entry_or_kernel_probe": false, + "remaining_policy_seconds": "879.109466521", + "schema": "new-native-proposal-mock-admission-v1", + "whole_source_accepted": false +} diff --git a/research/h25-native-view-facts/evidence/PRE-RETIREMENT.json b/research/h25-native-view-facts/evidence/PRE-RETIREMENT.json new file mode 100644 index 0000000000..b5524b3eca --- /dev/null +++ b/research/h25-native-view-facts/evidence/PRE-RETIREMENT.json @@ -0,0 +1,11 @@ +{ + "elapsed_seconds": 0.715204460953828, + "errors": [], + "group_owner_pid": 2, + "guard_known_wait": true, + "guard_pid": 4, + "guard_returncode": 0, + "held_outer_group": 2, + "manager_pid": 3, + "protocol": "whole group SIGKILL after guard exit; external parent finalizes" +} diff --git a/research/h25-native-view-facts/evidence/RESULT.json b/research/h25-native-view-facts/evidence/RESULT.json new file mode 100644 index 0000000000..b36e09db5e --- /dev/null +++ b/research/h25-native-view-facts/evidence/RESULT.json @@ -0,0 +1,75 @@ +{ + "kernel_or_namespace_probe": false, + "new_control_sources": 2, + "original_caller_execution": false, + "original_credit_delta": 0, + "production_entry_executed": false, + "status": "PASS", + "steps": [ + { + "EOF": [ + "stderr", + "stdout" + ], + "complete": true, + "errors": [], + "known_wait": true, + "name": "compile-changed_policy_control", + "raw_bytes": { + "stderr": 5437, + "stdout": 0 + }, + "returncode": 0, + "wall_seconds": 0.4236460330430418 + }, + { + "EOF": [ + "stderr", + "stdout" + ], + "complete": true, + "errors": [], + "known_wait": true, + "name": "run-changed_policy_control", + "raw_bytes": { + "stderr": 0, + "stdout": 0 + }, + "returncode": 0, + "wall_seconds": 0.014959915017243475 + }, + { + "EOF": [ + "stderr", + "stdout" + ], + "complete": true, + "errors": [], + "known_wait": true, + "name": "compile-native_fact_control", + "raw_bytes": { + "stderr": 5433, + "stdout": 0 + }, + "returncode": 0, + "wall_seconds": 0.188497138035018 + }, + { + "EOF": [ + "stderr", + "stdout" + ], + "complete": true, + "errors": [], + "known_wait": true, + "name": "run-native_fact_control", + "raw_bytes": { + "stderr": 0, + "stdout": 64 + }, + "returncode": 0, + "wall_seconds": 0.00869330100249499 + } + ], + "whole_source_accepted": false +} diff --git a/research/h25-native-view-facts/evidence/native_controls_outer_owner.py.txt b/research/h25-native-view-facts/evidence/native_controls_outer_owner.py.txt new file mode 100644 index 0000000000..aa6941d7c2 --- /dev/null +++ b/research/h25-native-view-facts/evidence/native_controls_outer_owner.py.txt @@ -0,0 +1,85 @@ +"""Retire one private timeout-owned verification group on every guard exit. + +Run ONLY as the direct child of the recorded GNU timeout group owner. This +manager deliberately kills its own still-owned group after saving pre-retirement +evidence. The external Codex parent independently finalizes the prepaid ledger. +""" +from pathlib import Path +import hashlib +import json +import os +import signal +import subprocess +import time + +W = Path('/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453') +R = W / 'outputs/caller-proof-construction-20261106T2330Z' +GUARD = R / 'validation/run_native_proposal_controls.py' + + +def save(path, value): + with path.open('x') as stream: + json.dump(value, stream, indent=2, sort_keys=True) + stream.write('\n') + path.chmod(0o444) + + +def main(): + admission = json.loads((R / 'control/NATIVE-PROPOSAL-CONTROL-ADMISSION-v1.json').read_text()) + if admission['outer_sha256'] != hashlib.sha256(Path(__file__).read_bytes()).hexdigest(): + raise ValueError('exact reviewed outer owner') + if admission['guard_sha256'] != hashlib.sha256(GUARD.read_bytes()).hexdigest(): + raise ValueError('exact reviewed guard') + group = os.getpgrp() + # GNU timeout's default mode holds this group leader while waiting for this + # manager. Refuse an ambient/inherited group before creating any child. + if group != os.getppid() or group == os.getpid() or group <= 1: + raise ValueError('direct child of the recorded private timeout group owner required') + def retire_group(signum=None, frame=None): + try: + os.killpg(group, signal.SIGKILL) + except BaseException: + while True: + signal.pause() + # A timeout TERM must not release the group owner before the +5 KILL. + # Retire the held whole group immediately, before any child is created. + signal.signal(signal.SIGTERM, retire_group) + folder = R / 'verification-native-outer' + folder.mkdir(exist_ok=False) + process = None + errors = [] + row = {'manager_pid': os.getpid(), 'held_outer_group': group, + 'group_owner_pid': os.getppid(), 'guard_known_wait': False, + 'protocol': 'whole group SIGKILL after guard exit; external parent finalizes'} + streams = [] + started = time.monotonic() + try: + for name in ('stdout', 'stderr'): + streams.append((folder / (name + '.raw')).open('xb', buffering=0)) + process = subprocess.Popen(['/usr/bin/python3.12', '-S', '-s', '-P', '-B', str(GUARD)], + cwd=W, env={'PATH': '/usr/bin:/bin', 'LC_ALL': 'C', 'LANG': 'C'}, + stdin=subprocess.DEVNULL, stdout=streams[0], stderr=streams[1], close_fds=True) + row['guard_pid'] = process.pid + process.wait(timeout=43) + row['guard_known_wait'] = True + row['guard_returncode'] = process.returncode + except BaseException as error: + errors.append({'type': type(error).__name__, 'message': str(error)}) + finally: + for stream in streams: + try: + stream.close() + except BaseException as error: + errors.append({'type': type(error).__name__, 'message': str(error)}) + row.update({'errors': errors, 'elapsed_seconds': time.monotonic() - started}) + try: + save(folder / 'PRE-RETIREMENT.json', row) + finally: + # The timeout leader remains our parent and holds the numeric group + # identity here. Kill all members, including this manager/owner, + # before any such identity can be released or recycled. + retire_group() + + +if __name__ == '__main__': + main() diff --git a/research/h25-native-view-facts/evidence/run_native_proposal_controls.py.txt b/research/h25-native-view-facts/evidence/run_native_proposal_controls.py.txt new file mode 100644 index 0000000000..4b8b3a3a4e --- /dev/null +++ b/research/h25-native-view-facts/evidence/run_native_proposal_controls.py.txt @@ -0,0 +1,186 @@ +"""Verification envelope for two frozen new mocked-constructor controls. + +External parent: timeout TERM at 45 seconds, KILL after 5 seconds, one owned +group, immutable 64-second reservation and unconditional final accounting. +Children keep that group. No production entry or actual kernel probe is run. +""" +from pathlib import Path +import hashlib +import json +import os +import resource +import selectors +import signal +import stat +import subprocess +import time + +W = Path('/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453') +R = W / 'outputs/caller-proof-construction-20261106T2330Z' +B = R / 'proof/native-entry-invariants' +D = R / 'verification-native' +COMPILER = Path('/usr/bin/x86_64-linux-gnu-gcc-13') +PINS = { + B / 'proposal/science_view_entry.c': 'e1740fc6c901e09477ff0d934a920ca51dfe1a4b199d14e3433e155f1ef30fb2', + B / 'controls/changed_policy_control.c': '5a2529728985028865276d116f5c567e3c613e4f8f0356f9070857206318c2eb', + B / 'controls/native_fact_control.c': 'b7b7cfe5ebbebead55791b121b2fdb5e15d2736aafaa4a2e781e99de44ffd5fd', + COMPILER: '1b99826121ae6682a634e5efe09bd3e3df58ce58e0b28f849114ab5b89139c26'} +CAP = 65536 + + +def save(path, value): + with path.open('x') as stream: + json.dump(value, stream, indent=2, sort_keys=True) + stream.write('\n') + path.chmod(0o444) + + +def error_value(error, site): + return {'site': site, 'type': type(error).__name__, 'message': str(error)} + + +def verify_pins(): + for path, expected in PINS.items(): + value = path.lstat() + if not stat.S_ISREG(value.st_mode) or value.st_size > 2 * 1024 * 1024: + raise ValueError('bounded regular reviewed source/tool') + if hashlib.sha256(path.read_bytes()).hexdigest() != expected: + raise ValueError('reviewed source/tool changed: ' + str(path)) + + +def limits(cpu): + resource.setrlimit(resource.RLIMIT_CPU, (cpu, cpu)) + resource.setrlimit(resource.RLIMIT_AS, (536870912, 536870912)) + resource.setrlimit(resource.RLIMIT_FSIZE, (4194304, 4194304)) + resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) + resource.setrlimit(resource.RLIMIT_NOFILE, (64, 64)) + + +def run(name, argv, wall, cpu, expected_stdout=None): + folder = D / name + folder.mkdir() + errors = [] + streams = {} + counts = {'stdout': 0, 'stderr': 0} + eof = set() + process = None + selector = None + known_wait = False + body_ok = False + started = time.monotonic() + def attempt(site, function): + try: + return function() + except BaseException as error: + errors.append(error_value(error, site)) + return None + try: + verify_pins() + for key in counts: + streams[key] = (folder / (key + '.raw')).open('xb', buffering=0) + save(folder / 'START.json', {'state': 'BIRTH_PENDING', 'argv': argv, + 'child_wall_seconds': wall, 'CPU_seconds': cpu, 'AS_bytes': 536870912, + 'FSIZE_bytes': 4194304, 'raw_cap_each': CAP, + 'inherits_external_guard_process_group': os.getpgrp()}) + process = subprocess.Popen(argv, cwd=W, + env={'PATH': '/usr/bin:/bin', 'LC_ALL': 'C', 'LANG': 'C', + 'TMPDIR': str(D / 'scratch')}, + stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + close_fds=True, preexec_fn=lambda: limits(cpu)) + save(folder / 'BIRTH.json', {'pid': process.pid, + 'inherits_external_guard_process_group': os.getpgrp()}) + selector = selectors.DefaultSelector() + for key, pipe in (('stdout', process.stdout), ('stderr', process.stderr)): + os.set_blocking(pipe.fileno(), False) + selector.register(pipe, selectors.EVENT_READ, key) + end = time.monotonic() + wall + while selector.get_map(): + remaining = end - time.monotonic() + if remaining <= 0: + raise TimeoutError('owned child/EOF deadline') + for item, _ in selector.select(min(0.1, remaining)): + key = item.data + block = os.read(item.fileobj.fileno(), min(4096, CAP + 1 - counts[key])) + if not block: + selector.unregister(item.fileobj) + eof.add(key) + continue + # Persist each prefix before the next read. An outer kill must + # not erase captured bytes held only in Python memory. + written = streams[key].write(block) + if written != len(block): + raise OSError('short raw capture write') + counts[key] += len(block) + if counts[key] > CAP: + raise ValueError('raw cap exceeded; prefix retained') + process.wait(timeout=max(0.001, end - time.monotonic())) + known_wait = True + if process.returncode != 0 or eof != set(counts): + raise ValueError('control/tool did not complete with zero exit and both EOFs') + verify_pins() + body_ok = True + except BaseException as error: + errors.append(error_value(error, 'body')) + if process is not None and not known_wait: + attempt('kill-owned-unreaped-child', process.kill) + if attempt('wait-owned-child', lambda: process.wait(timeout=2)) is not None: + known_wait = True + finally: + if selector is not None: + attempt('selector-close', selector.close) + if process is not None: + for pipe in (process.stdout, process.stderr): + if pipe is not None: + attempt('pipe-close', pipe.close) + for key, stream in streams.items(): + attempt('raw-' + key + '-close', stream.close) + attempt('raw-' + key + '-freeze', lambda key=key: (folder / (key + '.raw')).chmod(0o444)) + if expected_stdout is not None and body_ok and not errors: + try: + if (folder / 'stdout.raw').read_bytes() != expected_stdout or (folder / 'stderr.raw').read_bytes() != b'': + raise ValueError('exact new control terminal bytes') + except BaseException as error: + errors.append(error_value(error, 'terminal-bytes')) + row = {'name': name, 'complete': body_ok and not errors, 'errors': errors, + 'returncode': None if process is None else process.returncode, + 'known_wait': known_wait, 'EOF': sorted(eof), 'raw_bytes': counts, + 'wall_seconds': time.monotonic() - started} + save(folder / 'RESULT.json', row) + return row + + +def main(): + admission = json.loads((R / 'control/NATIVE-PROPOSAL-CONTROL-ADMISSION-v1.json').read_text()) + if admission['guard_sha256'] != hashlib.sha256(Path(__file__).read_bytes()).hexdigest() or admission['execution_GO'] is not True: + raise ValueError('exact reviewed parent component admission') + D.mkdir(exist_ok=False) + (D / 'scratch').mkdir(mode=0o700) + rows = [] + for stem, expected in (('changed_policy_control', b''), + ('native_fact_control', b'unselected native fact control: finite operation oracles passed\n')): + binary = D / stem + row = run('compile-' + stem, + [str(COMPILER), '-std=c11', '-O0', '-Wall', '-Wextra', '-Werror', + '-Wno-error=misleading-indentation', str(B / 'controls' / (stem + '.c')), + '-o', str(binary)], 15, 10) + rows.append(row) + if not row['complete']: + break + binary.chmod(0o500) + save(D / (stem + '-BINARY-PIN.json'), {'bytes': binary.stat().st_size, + 'sha256': hashlib.sha256(binary.read_bytes()).hexdigest()}) + row = run('run-' + stem, [str(binary)], 2, 1, expected) + rows.append(row) + if not row['complete']: + break + result = {'status': 'PASS' if len(rows) == 4 and all(row['complete'] for row in rows) else 'FAILED_NO_RETRY', + 'steps': rows, 'new_control_sources': 2, 'production_entry_executed': False, + 'kernel_or_namespace_probe': False, 'original_caller_execution': False, + 'whole_source_accepted': False, 'original_credit_delta': 0} + save(D / 'RESULT.json', result) + print(json.dumps(result, sort_keys=True)) + return 0 if result['status'] == 'PASS' else 1 + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/research/h25-native-view-facts/evidence/steps/changed_policy_control-BINARY-PIN.json b/research/h25-native-view-facts/evidence/steps/changed_policy_control-BINARY-PIN.json new file mode 100644 index 0000000000..2e3ef59cb1 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/changed_policy_control-BINARY-PIN.json @@ -0,0 +1,4 @@ +{ + "bytes": 62344, + "sha256": "206d2ec1ae4724c51f03fb0c929f22d8d6013626ffd300735b818e75ce87862a" +} diff --git a/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/BIRTH.json b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/BIRTH.json new file mode 100644 index 0000000000..4555512755 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/BIRTH.json @@ -0,0 +1,4 @@ +{ + "inherits_external_guard_process_group": 2, + "pid": 5 +} diff --git a/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/RESULT.json b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/RESULT.json new file mode 100644 index 0000000000..81c9b875d6 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/RESULT.json @@ -0,0 +1,16 @@ +{ + "EOF": [ + "stderr", + "stdout" + ], + "complete": true, + "errors": [], + "known_wait": true, + "name": "compile-changed_policy_control", + "raw_bytes": { + "stderr": 5437, + "stdout": 0 + }, + "returncode": 0, + "wall_seconds": 0.4236460330430418 +} diff --git a/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/START.json b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/START.json new file mode 100644 index 0000000000..99a74fc659 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/START.json @@ -0,0 +1,21 @@ +{ + "AS_bytes": 536870912, + "CPU_seconds": 10, + "FSIZE_bytes": 4194304, + "argv": [ + "/usr/bin/x86_64-linux-gnu-gcc-13", + "-std=c11", + "-O0", + "-Wall", + "-Wextra", + "-Werror", + "-Wno-error=misleading-indentation", + "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/changed_policy_control.c", + "-o", + "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/changed_policy_control" + ], + "child_wall_seconds": 15, + "inherits_external_guard_process_group": 2, + "raw_cap_each": 65536, + "state": "BIRTH_PENDING" +} diff --git a/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/stderr.raw b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/stderr.raw new file mode 100644 index 0000000000..fb900b90c8 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/stderr.raw @@ -0,0 +1,36 @@ +In file included from /home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/changed_policy_control.c:10: +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'query_result': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:154:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 154 | if(result<0)return failed(site);native_queries_completed++;return true; + | ^~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:154:37: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 154 | if(result<0)return failed(site);native_queries_completed++;return true; + | ^~~~~~~~~~~~~~~~~~~~~~~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'stat_fd': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:239:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 239 | if(fstat(fd,out)<0)return failed(site);return true; + | ^~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:239:44: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 239 | if(fstat(fd,out)<0)return failed(site);return true; + | ^~~~~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'mount_row': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:493:5: warning: this 'for' clause does not guard... [-Wmisleading-indentation] + 493 | for(size_t i=0;icount;i++)if(c->row[i].h.id==id)return &c->row[i];return NULL; + | ^~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:493:75: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for' + 493 | for(size_t i=0;icount;i++)if(c->row[i].h.id==id)return &c->row[i];return NULL; + | ^~~~~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'll_rule': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:643:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 643 | if(syscall(SYS_landlock_add_rule,rules,1,&path,0)<0)return failed(site);return true; + | ^~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:643:77: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 643 | if(syscall(SYS_landlock_add_rule,rules,1,&path,0)<0)return failed(site);return true; + | ^~~~~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'report_failure': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:791:9: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 791 | if(n==0)break;at+=(size_t)n; + | ^~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:791:23: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 791 | if(n==0)break;at+=(size_t)n; + | ^~ diff --git a/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/stdout.raw b/research/h25-native-view-facts/evidence/steps/compile-changed_policy_control/stdout.raw new file mode 100644 index 0000000000..e69de29bb2 diff --git a/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/BIRTH.json b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/BIRTH.json new file mode 100644 index 0000000000..d695ac8e7b --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/BIRTH.json @@ -0,0 +1,4 @@ +{ + "inherits_external_guard_process_group": 2, + "pid": 11 +} diff --git a/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/RESULT.json b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/RESULT.json new file mode 100644 index 0000000000..d2f5d77f9a --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/RESULT.json @@ -0,0 +1,16 @@ +{ + "EOF": [ + "stderr", + "stdout" + ], + "complete": true, + "errors": [], + "known_wait": true, + "name": "compile-native_fact_control", + "raw_bytes": { + "stderr": 5433, + "stdout": 0 + }, + "returncode": 0, + "wall_seconds": 0.188497138035018 +} diff --git a/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/START.json b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/START.json new file mode 100644 index 0000000000..a7812d2a7b --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/START.json @@ -0,0 +1,21 @@ +{ + "AS_bytes": 536870912, + "CPU_seconds": 10, + "FSIZE_bytes": 4194304, + "argv": [ + "/usr/bin/x86_64-linux-gnu-gcc-13", + "-std=c11", + "-O0", + "-Wall", + "-Wextra", + "-Werror", + "-Wno-error=misleading-indentation", + "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/native_fact_control.c", + "-o", + "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/native_fact_control" + ], + "child_wall_seconds": 15, + "inherits_external_guard_process_group": 2, + "raw_cap_each": 65536, + "state": "BIRTH_PENDING" +} diff --git a/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/stderr.raw b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/stderr.raw new file mode 100644 index 0000000000..67137b6890 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/stderr.raw @@ -0,0 +1,36 @@ +In file included from /home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/native_fact_control.c:7: +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'query_result': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:154:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 154 | if(result<0)return failed(site);native_queries_completed++;return true; + | ^~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:154:37: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 154 | if(result<0)return failed(site);native_queries_completed++;return true; + | ^~~~~~~~~~~~~~~~~~~~~~~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'stat_fd': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:239:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 239 | if(fstat(fd,out)<0)return failed(site);return true; + | ^~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:239:44: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 239 | if(fstat(fd,out)<0)return failed(site);return true; + | ^~~~~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'mount_row': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:493:5: warning: this 'for' clause does not guard... [-Wmisleading-indentation] + 493 | for(size_t i=0;icount;i++)if(c->row[i].h.id==id)return &c->row[i];return NULL; + | ^~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:493:75: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for' + 493 | for(size_t i=0;icount;i++)if(c->row[i].h.id==id)return &c->row[i];return NULL; + | ^~~~~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'll_rule': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:643:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 643 | if(syscall(SYS_landlock_add_rule,rules,1,&path,0)<0)return failed(site);return true; + | ^~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:643:77: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 643 | if(syscall(SYS_landlock_add_rule,rules,1,&path,0)<0)return failed(site);return true; + | ^~~~~~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c: In function 'report_failure': +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:791:9: warning: this 'if' clause does not guard... [-Wmisleading-indentation] + 791 | if(n==0)break;at+=(size_t)n; + | ^~ +/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/proof/native-entry-invariants/controls/../proposal/science_view_entry.c:791:23: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' + 791 | if(n==0)break;at+=(size_t)n; + | ^~ diff --git a/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/stdout.raw b/research/h25-native-view-facts/evidence/steps/compile-native_fact_control/stdout.raw new file mode 100644 index 0000000000..e69de29bb2 diff --git a/research/h25-native-view-facts/evidence/steps/native_fact_control-BINARY-PIN.json b/research/h25-native-view-facts/evidence/steps/native_fact_control-BINARY-PIN.json new file mode 100644 index 0000000000..a98664fa64 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/native_fact_control-BINARY-PIN.json @@ -0,0 +1,4 @@ +{ + "bytes": 62352, + "sha256": "da174813085059fb057f0beebac22fa5e37cf405a4bc9e0c1ea53008c5e91e5d" +} diff --git a/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/BIRTH.json b/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/BIRTH.json new file mode 100644 index 0000000000..21941b558c --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/BIRTH.json @@ -0,0 +1,4 @@ +{ + "inherits_external_guard_process_group": 2, + "pid": 10 +} diff --git a/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/RESULT.json b/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/RESULT.json new file mode 100644 index 0000000000..8be0813eb0 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/RESULT.json @@ -0,0 +1,16 @@ +{ + "EOF": [ + "stderr", + "stdout" + ], + "complete": true, + "errors": [], + "known_wait": true, + "name": "run-changed_policy_control", + "raw_bytes": { + "stderr": 0, + "stdout": 0 + }, + "returncode": 0, + "wall_seconds": 0.014959915017243475 +} diff --git a/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/START.json b/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/START.json new file mode 100644 index 0000000000..e48ebaa9b0 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/START.json @@ -0,0 +1,12 @@ +{ + "AS_bytes": 536870912, + "CPU_seconds": 1, + "FSIZE_bytes": 4194304, + "argv": [ + "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/changed_policy_control" + ], + "child_wall_seconds": 2, + "inherits_external_guard_process_group": 2, + "raw_cap_each": 65536, + "state": "BIRTH_PENDING" +} diff --git a/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/stderr.raw b/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/stderr.raw new file mode 100644 index 0000000000..e69de29bb2 diff --git a/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/stdout.raw b/research/h25-native-view-facts/evidence/steps/run-changed_policy_control/stdout.raw new file mode 100644 index 0000000000..e69de29bb2 diff --git a/research/h25-native-view-facts/evidence/steps/run-native_fact_control/BIRTH.json b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/BIRTH.json new file mode 100644 index 0000000000..d399801a53 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/BIRTH.json @@ -0,0 +1,4 @@ +{ + "inherits_external_guard_process_group": 2, + "pid": 16 +} diff --git a/research/h25-native-view-facts/evidence/steps/run-native_fact_control/RESULT.json b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/RESULT.json new file mode 100644 index 0000000000..769562cb62 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/RESULT.json @@ -0,0 +1,16 @@ +{ + "EOF": [ + "stderr", + "stdout" + ], + "complete": true, + "errors": [], + "known_wait": true, + "name": "run-native_fact_control", + "raw_bytes": { + "stderr": 0, + "stdout": 64 + }, + "returncode": 0, + "wall_seconds": 0.00869330100249499 +} diff --git a/research/h25-native-view-facts/evidence/steps/run-native_fact_control/START.json b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/START.json new file mode 100644 index 0000000000..68fc3ab737 --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/START.json @@ -0,0 +1,12 @@ +{ + "AS_bytes": 536870912, + "CPU_seconds": 1, + "FSIZE_bytes": 4194304, + "argv": [ + "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/caller-proof-construction-20261106T2330Z/verification-native/native_fact_control" + ], + "child_wall_seconds": 2, + "inherits_external_guard_process_group": 2, + "raw_cap_each": 65536, + "state": "BIRTH_PENDING" +} diff --git a/research/h25-native-view-facts/evidence/steps/run-native_fact_control/stderr.raw b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/stderr.raw new file mode 100644 index 0000000000..e69de29bb2 diff --git a/research/h25-native-view-facts/evidence/steps/run-native_fact_control/stdout.raw b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/stdout.raw new file mode 100644 index 0000000000..3a7b948b1a --- /dev/null +++ b/research/h25-native-view-facts/evidence/steps/run-native_fact_control/stdout.raw @@ -0,0 +1 @@ +unselected native fact control: finite operation oracles passed diff --git a/research/h25-native-view-facts/proof/COMPILER-SCRATCH-LINEAGE.md b/research/h25-native-view-facts/proof/COMPILER-SCRATCH-LINEAGE.md new file mode 100644 index 0000000000..680efeee5b --- /dev/null +++ b/research/h25-native-view-facts/proof/COMPILER-SCRATCH-LINEAGE.md @@ -0,0 +1,32 @@ +# The selected full caller installs its compiler scratch environment + +This lemma concerns the immutable full scientific driver already identified by row 17 of the existing 31-function map. No case census, compiler, import, probe or runtime observation has been performed. It corrects the proposed inference from the runner's initial six-key environment to the environment actually inherited by the compiler children. + +## Source facts and conclusion + +The runner starts the original command with `env = dict(LAUNCH_ENV)` and no TMPDIR key. That fact is correct. It does not imply that a compiler invoked later by the Python program has the same unmodified mapping: the selected original program changes its own `os.environ` before invoking any of the three compiler families. + +In `integration/scientific_driver.py`, `main_epoch` performs the following ordered original operations: + +- Line 951 selects `compiler_tmp = output / 'compiler-tmp'`. +- Line 952 exclusively creates that directory with the original `mkdir`. +- Line 953 sets `os.environ['TMPDIR'] = str(compiler_tmp)`. +- Line 1027 invokes `native_packet.prepare` for the three metadata builds. +- Line 1030 invokes `backend.build_native` for the GF2 build. +- Line 1052 invokes the authenticated guarded-adapter preparation which reaches the original `adapters.build_encoder` for the trace build. + +The older function retained in the same immutable file has the same ordering at lines 453–455 and 543/548/574. The selected original `main_epoch` is not inferred from that older function: its own body contains the concrete operations above. + +Neither `cold_build_evidence.run`, `native_backend.build_native` nor `adapters.build_encoder` supplies an alternate `env` to its subprocess call. The metadata helper's `Popen` and the two separate PIPE/text producers' `subprocess.run` therefore inherit the **then-current** process environment, which contains the original program's TMPDIR assignment. This proves that the caller supplies the same scratch directory to all three selected compiler families. It preserves their different commands, evidence and timeout contracts; it does not route them through a new common compiler wrapper. + +The early optimized full refusal does not enter `main_epoch` and does not execute these compilers. Its initial native-TCB controls create only their own fixture, as shown in `ORIGINAL-NATIVE-CONSUMERS-v1.md`. The separate eight cold-build toy cases use explicit Python children, not these GCC compilation paths. The unchanged source/context map still determines which other original contexts pass through the view; this lemma does not make two outer invocations execute every separate context. + +## Relation to the actual native view + +The `output` leaf is beneath the declared artifact parent. The compiler-tmp directory is consequently beneath that same writable clone. The entry's artifact Landlock rule grants the needed directory/file create/read/write/remove rights and its syscall policy admits those operations. The same-ID mapping keeps the underlying creator UID and permission checks; source/hash/header inputs elsewhere remain readable through the copied root. + +For a selected ordinary local-filesystem/security model in which this original mkdir yields the intended caller-owned searchable/writable scratch directory, the new mount boundary does not itself make that directory read-only. No `/tmp` writable clone or new environment mutation is required merely because the **initial launcher** environment lacks TMPDIR. + +The remaining actual compiler consequence is precise: derive from each selected GCC/helper/interpreter implementation that its temporary-file choice uses the provided usable TMPDIR, or enumerate any independent fixed scratch path it actually reaches. A wrapper that ignores TMPDIR is not certified by the caller assignment, and an unusable TMPDIR can have an original fallback whose preservation needs its own argument. These are concrete compiler/permission cases in the existing finite model, not evidence that the current caller inevitably uses `/tmp`. + +No broader host write exception should be introduced on the incorrect premise that the original full driver never sets TMPDIR. The constructive starting point is the existing original assignment, its artifact-path lineage and the actual selected compiler's temporary-path algorithm. The scientific source and original environment semantics remain unchanged. diff --git a/research/h25-native-view-facts/proof/CONFIG-AND-INHERITANCE-LEMMAS-v1.md b/research/h25-native-view-facts/proof/CONFIG-AND-INHERITANCE-LEMMAS-v1.md new file mode 100644 index 0000000000..acda67b317 --- /dev/null +++ b/research/h25-native-view-facts/proof/CONFIG-AND-INHERITANCE-LEMMAS-v1.md @@ -0,0 +1,59 @@ +Concrete lemmas for the prospective disabled-misc, disabled-core model + +This is a constructive addendum to `KERNEL-LEMMAS-v1.md`, SHA256 `3fa107a85ad5f682cb9ea7ebe5ac562e1ab1c686272d363ef4c33470e1b49b52`. It examines Pro's still-being-constructed alternative model; it does not adopt an incomplete answer or authorize a native edit. All references are exact Linux `v6.12` bodies retained under `primary/`. `INDEX-v4.json` and `SOURCE-SHA256SUMS-v3.txt` pin their repository paths, Git blobs, full bytes and physical lines. + +**L8 — `CONFIG_BINFMT_MISC=n` removes miscellaneous dispatch for both executions.** + +Hypotheses: the actual original environment and transformed environment are associated with the same selected stock kernel source/configuration, with `CONFIG_BINFMT_MISC=n`, `CONFIG_MODULES=n`, and the required native ELF/script formats built in. This is an explicit prospective operating-TCB selection. It does not assert that an already selected host has this configuration. The proposed successor omits the current entry's private-binfmt construction; otherwise its mandatory `fsopen("binfmt_misc")` would be inconsistent with this model. + +Conclusion: no ancestor miscellaneous handler, including an old preopened F interpreter, can alter the original-versus-transformed dispatch. There is no miscellaneous implementation to register, not merely an unobserved empty registry. Consequently no binfmt-registry query or handler-equivalence compatibility flag is needed for this branch. Original ELF, script/interpreter, loader and failed-exec behavior still use their actual selected source and must retain their finite caller resolution; this lemma does not replace those paths with another command. + +Proof: [`fs/Kconfig.binfmt`](https://github.com/torvalds/linux/blob/v6.12/fs/Kconfig.binfmt), lines 145–169, defines the miscellaneous handler as a tristate feature. [`fs/Makefile`](https://github.com/torvalds/linux/blob/v6.12/fs/Makefile), line 35, includes `binfmt_misc.o` only through `obj-$(CONFIG_BINFMT_MISC)`. With the option disabled, that implementation and its initialization/registration are absent. `CONFIG_MODULES=n` also prevents loading it later. The source-selected native model excludes unreviewed replacement kernel code under the original T1/T2 and no-hostile-administration premises. Both P and V use this same kernel; the conclusion does not depend on trusting a compiler or reading a caller-supplied handler list. + +**L9 — `CONFIG_COREDUMP=n` preserves the absence of the core bit, file and pipe-handler path.** + +Hypotheses: both P and V use the same selected kernel with `CONFIG_COREDUMP=n`. The successor removes the current entry's CORE `(1,1)` installation and preserves the original inherited limit tuple and original self-limit operations. Ordinary fatal signals, original wait ownership and actual selected compiler/helper consumers remain in scope; no arbitrary native-totality or no-crash assumption is added. + +Conclusion: disabling the common kernel feature in both executions removes the relevant core-file and core-pipe-helper dispatch. A normal fatal signal retains its signal exit status without the coredump-success bit in both executions. Thus a `WCOREDUMP`-dependent retained diagnostic has the same false core-bit input; this is a constructive closure of that specific diagnostic branch, not an unsupported assertion that every other diagnostic is equal. It does not require identifying the installed compiler as GCC 13.2 merely to establish the kernel status-bit relation. + +Proof: `Kconfig.binfmt`, lines 171–177, defines `COREDUMP` independently. `fs/Makefile`, line 46, builds `coredump.o` only under that option. [`include/linux/coredump.h`](https://github.com/torvalds/linux/blob/v6.12/include/linux/coredump.h), lines 64–70, supplies an empty inline `do_coredump` when it is disabled. [`kernel/signal.c`](https://github.com/torvalds/linux/blob/v6.12/kernel/signal.c), lines 2889–2918, invokes that function for the core-class fatal signal, then calls `do_group_exit(signr)`. [`kernel/exit.c`](https://github.com/torvalds/linux/blob/v6.12/kernel/exit.c), lines 1053–1099, shows ordinary exit codes encoded in the high byte and fatal group-exit propagation. The no-op dump path neither writes a core image nor invokes the pipe core helper nor introduces the dump-success status bit. Signal notification's `CLD_DUMPED` branch at `signal.c`, lines 2104–2111, depends on that low-byte bit. + +The existing GCC 13.2 `collect_wait` WCOREDUMP diagnostic is therefore a real consumer with an unchanged core-bit branch under these hypotheses. Actual raw process output, the other wait fields and every required failure/cleanup relation remain genuine observations. `proc_coredump_connector` is still called at `signal.c`, line 2894; this lemma does not falsely say all fault notifications disappear. That remaining common-kernel notification is the same operation in P and V, and any relevant external-effect premise must retain the original operating-TCB scope. + +`CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=n` is not a substitute. Its stanza at `Kconfig.binfmt`, lines 77–97, changes the default inclusion of partial ELF segments; it does not disable core dumping. `CONFIG_ELFCORE` similarly concerns ELF support objects. The decisive selected switch here is `CONFIG_COREDUMP=n`. + +The old special CORE syscall restrictions are no longer required for suppressing a pipe helper under this model. If the implementation removes them, it must retain ordinary `setrlimit` support and self-only `prlimit64` semantics where required, rather than accidentally deleting those syscalls from the allowlist. If it retains any extra restriction, the original reached-operation proof must justify it. This is a source patch-scope consequence, not an edit instruction or executed experiment. + +**L10 — `CONFIG_MODULES=n` closes module-autoload delegation, not every usermode helper.** + +Hypotheses: the selected actual kernel/configuration is the same for P and V and has `CONFIG_MODULES=n`. + +Conclusion: the original failed-format search does not invoke a module-loader helper, and generic `request_module`/`request_module_nowait` calls take the no-module stub. This removes that particular out-of-domain delegated process path without a broker or trusted compiler exception. It does not prove that every unrelated kernel helper API is disabled. + +Proof: [`include/linux/kmod.h`](https://github.com/torvalds/linux/blob/v6.12/include/linux/kmod.h), lines 19–33, uses the real loader interface only under `CONFIG_MODULES`; otherwise both request functions return `-ENOSYS`. [`fs/exec.c`](https://github.com/torvalds/linux/blob/v6.12/fs/exec.c), lines 1730–1773, sets `need_retry = IS_ENABLED(CONFIG_MODULES)` and enters the `request_module("binfmt-%04x", ...)` retry only when true. With the option disabled, it returns the actual handler-search result without that request. Missing-path `ENOENT` remains before this format search. The exact finite source/ELF/script/interpreter closure and its failure consumers remain the main theorem's responsibility. + +**L11 — The small stack has no readable `/proc//attr/current` subject hook.** + +Hypotheses: L1's complete active stack is exactly capability plus Landlock under the pinned stock implementation; the actual target process is live and the proc object is genuine. + +Conclusion: a successful subject-byte read cannot be required as evidence for this model. The owning association should derive the absence of a subject-producing hook from the genuinely acquired stack and selected hook semantics, rather than call an unsupported read and label its error compatible. This is a correction to the added environment-association observer, not removal of an original scientific check. + +Proof: [`security/security.c`](https://github.com/torvalds/linux/blob/v6.12/security/security.c), lines 4228–4239, dispatches `security_getprocattr` only to registered hooks and otherwise returns `LSM_RET_DEFAULT(getprocattr)`. [`include/linux/lsm_hook_defs.h`](https://github.com/torvalds/linux/blob/v6.12/include/linux/lsm_hook_defs.h), line 291, sets that default to `-EINVAL`. Capability's complete hook list at `commoncap.c`, lines 1444–1465, has no `getprocattr`. Landlock's setup at `landlock-setup.c`, lines 34–43, installs only its credential/task/filesystem/network lists; the exact corresponding lists in `landlock-cred.c`, `landlock-task.c`, `landlock-fs.c` and `landlock-net.c` contain no such hook. `proc-base.c`, lines 2775–2793, propagates the resulting negative value from the actual read. The current added `_security_subject`, lines 534–555 of the environment-association source, unconditionally reads that file; it therefore needs this explicit model branch. An ordinary serialized string or boolean cannot create the module association or the conclusion. + +**L4a — Checked setup success proves absence of an applicable inherited filesystem domain.** + +This strengthens the inherited-state argument without inventing an omniscient introspector. Actual C `enter_namespaces`, lines 355–369, calls `mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)` and sets `root_private` only after success. `namespace.c`, lines 3759–3778, calls `security_sb_mount` before completing that operation. `landlock-fs.c`, lines 1335–1342, rejects whenever its filesystem-applicable domain is non-null. Under the selected stock hook semantics, actual checked success therefore implies no such domain at that point. The entry has one task and cannot have its credentials changed by another thread; its trusted setup performs no `restrict_self` until the specified installation. The fact can be derived from the existing source branch, not supplied as a compatible label. Setup failure remains a paid qualification failure and never counts as the original scientific negative. + +The exact weaker conclusion must be retained: it does not prove the whole inherited domain is null. `landlock-ruleset.h`, lines 274–332, filters applicable domains by the union of their explicit masks. Its lines 364–370 add initially-denied filesystem rights, notably REFER, per layer when checking a filesystem-active merged domain. Thus an old network-only layer can matter after a new filesystem layer is added. Do not silently discard that layer. + +Two constructive ways to discharge this remaining branch are available. The simple model can select a genuinely associated null initial domain at the original T1 native boundary. A more general theorem can prove that required reference operations are same-directory (which do not request REFER: `landlock-fs.c`, lines 1121–1143) or handle every remaining old-layer REFER consequence explicitly. Successful mount setup alone is not enough to assert that all later cross-directory references are allowed. + +**L4b — Required signals within one inherited science domain are allowed by the new scope.** + +Hypotheses: the signal's sender and target are science tasks born after the single domain installation and retain that same domain hierarchy; no intervening extra restriction is introduced; ordinary UID/signal permissions are unchanged. This covers a parent signaling its own retained subprocesses if the actual caller map establishes that target set. + +Conclusion: the new `LANDLOCK_SCOPE_SIGNAL` flag does not reject that intra-domain signal. It still denies out-of-domain signals as intended. + +Proof: `landlock-task.c`, lines 125–178, compares client/server hierarchy levels and pointers. For identical domain hierarchies they are equal at every compared scoped layer, so `domain_is_scoped` returns false. Lines 256–282 reject only when that predicate is true. Credential transfer keeps that domain reference. The same argument applies to inherited old signal-only layers common to both tasks; it does not assume the old layers absent or permit signaling arbitrary outside targets. + +These are exact usable proof steps for the prospective configuration. Their actual current image/configuration/initial-state association remains a later genuine original qualification. No host policy change, kernel build, source implementation, compiler/native execution, probe, test, archive decoding or new spending occurred here. Pro's completed main theorem and the independently reviewed connected correction remain to follow within the existing fixed window. diff --git a/research/h25-native-view-facts/proof/KERNEL-LEMMAS-v1.md b/research/h25-native-view-facts/proof/KERNEL-LEMMAS-v1.md new file mode 100644 index 0000000000..fc3f02f2fe --- /dev/null +++ b/research/h25-native-view-facts/proof/KERNEL-LEMMAS-v1.md @@ -0,0 +1,71 @@ +Constructive kernel lemmas for the joined caller + +These lemmas are contributions to the authorized proof-construction effort. They do not assume that a complete published proof already exists. Each lemma separates concrete hypotheses from a conclusion and gives an exact source argument that the parent and Pro can compose with the original case map. They do not require a current-host experiment or grant one. The original T1/T2 native association remains the genuine external qualification boundary for actual source/configuration/images and initial state. + +All kernel references below are Linux `v6.12`, acquired as complete UTF-8 bodies from the GitHub API. `primary/INDEX-v2.json` records each repository path, tag, Git blob SHA and physical line count; `primary/SOURCE-SHA256SUMS-v1.txt` records full retained-file SHA256 values. Line references in this document are physical lines of those exact retained bodies, not normalized web-renderer positions. The versioned upstream links identify the original source. + +**L1 — A small active security stack is a concrete, distinguishable model.** + +Hypotheses: the genuine original native qualifier associates the actual kernel with the selected unmodified source semantics; original no-hostile-administration/interposition premises hold; a successfully acquired complete `lsm_list_modules` result contains precisely the selected `capability` and `landlock` module IDs. The acquisition must use flags zero, a bounded actual user buffer, the returned size/count, and preserve real failures rather than substitute a caller-supplied list. Initial Landlock and seccomp state are separate hypotheses, addressed below. + +Conclusion: the active LSM dispatch cannot secretly contain AppArmor, SELinux, Smack, Yama or a BPF LSM transition that is absent from that complete list. The conditional AppArmor NNP countermodel is outside this selected model. The result is a factual module-selection branch, not a compatibility assertion and not a claim about the current host. + +Proof: [`security/lsm_syscalls.c`](https://github.com/torvalds/linux/blob/v6.12/security/lsm_syscalls.c), lines 96–120, copies all `lsm_active_cnt` IDs, reports the required byte count, rejects nonzero flags and insufficient space, and contains no capability check. [`security/security.c`](https://github.com/torvalds/linux/blob/v6.12/security/security.c), lines 323–324 and 615–645, declares the active count `__ro_after_init`, registers each module ID with its hooks, and marks `security_add_hooks` as `__init`. Under the selected stock source and original exclusion of hostile kernel replacement, registration is an initialization operation. This proves the specific active-hook selection. It does not infer that a listed Landlock module has no per-task domain, or that an inherited seccomp filter is absent. + +**L2 — Fresh user-namespace separation closes ancestor proc magic links.** + +Hypotheses: the trusted entry creates a fresh child user namespace before any descendant; after setup it has empty capability sets and cannot recover namespace/capability authority; no outside actor is introduced into that fresh namespace contrary to the original exclusion interval. Same-namespace descendants are born only after the final view and restrictions. Pre-view file, directory, mount and namespace references are retired as the actual C owner specifies. The self-task case is handled by L3, not by pretending it needs an ancestor ptrace check. + +Conclusion: a science task cannot recover an ancestor or sibling user namespace's writable root, cwd, executable or FD path through `/proc/` merely because the kernel UID is the same and the target is dumpable. Same fresh-namespace descendants expose only their inherited final-view references, subject to the reference-closure invariant. + +Proof: [`fs/proc/base.c`](https://github.com/torvalds/linux/blob/v6.12/fs/proc/base.c), lines 709–723 and 1795–1815, requires `ptrace_may_access(..., PTRACE_MODE_READ_FSCREDS)` before the task link's `nd_jump_link`. Its root/cwd producers are at lines 222–249. [`fs/proc/fd.c`](https://github.com/torvalds/linux/blob/v6.12/fs/proc/fd.c), lines 175–193 and the link inode setup, uses the target file's actual `f_path` through that same proc-link machinery. [`security/commoncap.c`](https://github.com/torvalds/linux/blob/v6.12/security/commoncap.c), lines 135–156, permits the capability-subset shortcut only when the caller and target have the same `user_ns`; otherwise it requires `CAP_SYS_PTRACE` in the target namespace. Its `cap_capable`, lines 67–103, rejects a child-namespace caller seeking authority in an ancestor or unrelated same-level namespace. Numeric UID equality is therefore insufficient. + +Landlock provides a second source argument: [`security/landlock/task.c`](https://github.com/torvalds/linux/blob/v6.12/security/landlock/task.c), lines 35–95, permits a landlocked caller's ptrace access only to the same or a more restricted descendant domain. An outside unconstrained ancestor does not satisfy that relation. This additional argument does not replace the fresh-namespace and reference partition. + +**L3 — The actual entry does not overmount `/`; its self-root is not a hidden old-root escape.** + +Hypotheses: the selected namespace primitive has its documented successful postcondition, with the task root/cwd belonging to the copied namespace; the current exact entry is `science_view_entry.c`, SHA256 `60af72915efea62f46ea376e2ba7ed0c616f99b09ca1beec0f4b0d8173609410`; its setup operations succeed as specified. The native author owns the complete `unshare` call-chain/invariant mapping. + +Conclusion: the proposed counterexample based on attaching a new full root above an unchanged old `task.fs.root` does not describe this source. No `chroot` repair follows from that hypothesis. A proc self-root link still requires its own actual-reference argument, but the relevant root mount here is the one changed read-only in place. + +Proof: actual `make_view` opens `/` and calls recursive `mount_setattr` on that copied root. The only `move_mount` attachments are the exact artifact parent and usage file. It never attaches a replacement full-root mount. [`fs/namespace.c`](https://github.com/torvalds/linux/blob/v6.12/fs/namespace.c), lines 3916–3994, copies the mount topology and remaps the supplied task `fs_struct` root/pwd mount pointers to the matching copied mounts while retaining the same dentries. `clone_mnt`, lines 1285–1345, retains the same superblock and root dentry and copies the mount ID mapping. `mount_setattr_commit`, lines 4573–4593, updates the targeted mount flags and, when recursive, every mount in that copied subtree. The read-only flag is added to the existing copied root mount, rather than hidden by a newly attached root. The two child mount attachments do not undo that root flag. Actual `make_view` separately re-resolves cwd and replaces old devnull stdin; old-root FD and mapping retirement remains an explicit source invariant. + +This conclusion is about the actual constructor. It is not a universal statement that overmounting `/` always changes `task.fs.root`, and it does not rely on that false generalization. + +**L4 — Inherited Landlock state has a precise setup branch; new domains accumulate.** + +Hypotheses: the selected Landlock implementation is active. For the simple small-stack construction, the genuine original initial-state qualification selects a null initial domain. A strictly weaker setup hypothesis is that the inherited domain has no applicable filesystem component; any inherited network/signal/task effects would then need their own unchanged-case argument. Membership of `landlock` in the active list does not establish either initial-state fact. + +Conclusion: an inherited filesystem-applicable Landlock domain would reject the constructor's move-mount operations. A network-only domain does not trigger that particular filesystem hook. On successful installation, the entry's new domain is inherited by subsequent credential copies/exec/fork and cannot erase older restrictions. + +Proof: [`security/landlock/fs.c`](https://github.com/torvalds/linux/blob/v6.12/security/landlock/fs.c), lines 399–406, computes `get_current_fs_domain` using the `any_fs` access mask. Lines 1335–1384 reject mount, move-mount, unmount, remount and pivot-root if that applicable domain exists; `namespace.c`, lines 4271–4273, calls `security_move_mount` before attachment. Thus the setup failure is a direct hook consequence, not guessed inherited state. [`security/landlock/cred.c`](https://github.com/torvalds/linux/blob/v6.12/security/landlock/cred.c), lines 17–46, transfers the referenced old domain into prepared/transferred credentials. [`security/landlock/syscalls.c`](https://github.com/torvalds/linux/blob/v6.12/security/landlock/syscalls.c), lines 473–524, permits `restrict_self` under NNP or the specified capability, prepares credentials, merges the existing domain and commits the result. [`security/landlock/ruleset.c`](https://github.com/torvalds/linux/blob/v6.12/security/landlock/ruleset.c), lines 439–480 and 528–578, copies the prior layers and hierarchy and adds a new layer. Access is an intersection, not a reset. + +A proof may therefore use an explicitly selected null initial domain at the original native entry cut, with later genuine association. It must not claim that the new source can infer that hidden state from the active-module list. This is a constructive model clause, not an instruction to probe the host or invent an omniscient runtime observer. + +**L5 — Mount clones preserve the inode subjects used by the new Landlock rules.** + +Hypotheses: the constructor succeeds under L3/L4; required path operations resolve within the resulting copied tree or its exact two writable clones; no forbidden old reference, automount replacement or external topology entrant is introduced. The entry adds its rules through the final-view handles. The required operation class is read/execute anywhere in that tree; ordinary file/directory/symlink/FIFO creation, writes, truncation, removal and within-artifact references; exact usage-file read/write/truncation; and the specifically admitted devnull operations. This is a class statement whose actual original call coverage must be supplied by the caller proof. + +Conclusion: cloning the mount tree does not itself make those rules refer to different inode objects. Broad read/execute can be allowed at the final root while artifact writes are allowed at the artifact root, usage writes at the exact usage inode, and devnull access at its exact inode. It does not grant metadata control outside the read-only view or authorize arbitrary filesystems/delegation effects. + +Proof: `namespace.c`'s `clone_mnt`, lines 1285–1345, preserves the superblock, root dentry and ID mapping. [`security/landlock/fs.c`](https://github.com/torvalds/linux/blob/v6.12/security/landlock/fs.c), lines 248–347, keys path rules by the backing inode's Landlock object, not a numeric mount ID or original pathname string. `find_rule`, lines 358–376, looks up the same backing-inode object. The access walk, lines 753–909, accumulates permissions from inode rules, walks dentry parents, and crosses mount roots with `follow_up`; it requires the requested rights in every active layer. Because the entry adds its root and exception rules after attachment, every allowed class has an actual rule on its final-view target/ancestor. The artifact rule is encountered at its cloned root before crossing to the copied parent; the usage rule is on the file itself. `hook_file_open`, lines 1496–1565, derives the actual read/write/execute request and records optional truncate/device rights for later FD-local checks. Truncation of an already opened file uses that stored right, not an invented present-path grant. + +For link/rename, the two-path algorithm additionally checks that the move cannot gain access; within one artifact domain the source and destination share the same permitted hierarchy. Cross-domain or cross-mount links are not silently declared permitted by this lemma. Inherited pipes and other internal pseudo-filesystems use the explicitly recognized internal-filesystem branch, while their lifetime/writer ownership remains the genuine relay/guardian argument. + +**L6 — Ordinary unprivileged exec has no capability, set-ID or secure-loader transition in the small-stack branch.** + +Hypotheses: the original and transformed executions have the same non-root underlying real/effective/saved/fs UID and GID; original inheritable/permitted/effective/ambient capabilities are empty; every reached executable/interpreter in the associated finite closure has no set-ID mode and no file capability xattr; ordinary selected filesystem reads return the corresponding absent-capability result. The new entry drops capability sets/bounding authority, locks its securebits, sets NNP and adds NOSUID. The active security stack is precisely the L1 branch, and Landlock grants the required exec/read class as in L5. These are concrete initial/file facts, not an assumption that exec is compatible. + +Conclusion: the relevant capability/credential hooks compute the same underlying unprivileged exec credentials and no new `secureexec`/`AT_SECURE` privilege transition for these images. NNP/NOSUID do not introduce the AppArmor subset denial in this branch, because that hook is absent. They also do not suppress an original set-ID/capability transition, because the hypothesized finite images have none. The lemma says nothing about arbitrary status-file observations of NNP, CapBnd, Seccomp or namespace IDs; actual original consumers must still be mapped. + +Proof: [`fs/exec.c`](https://github.com/torvalds/linux/blob/v6.12/fs/exec.c), lines 1612–1661, handles set-ID only after `mnt_may_suid`/NNP checks and only when those mode bits exist. With no such mode, the original path makes no credential change; the new early returns have the same result. [`security/commoncap.c`](https://github.com/torvalds/linux/blob/v6.12/security/commoncap.c), lines 724–764 and 886–974, clears the proposed permitted set, treats the absent file capability result as no file capability, applies root-special handling only to the namespace root identity, and limits NNP downgrades to actual set-ID or capability-gaining transitions. Both are absent under the hypotheses. The resulting effective/permitted/ambient sets remain empty, UID/GID remain the same underlying kernel IDs, and the privilege-elevated `secureexec` condition is false. Clearing the bounding set does not alter an absent file/inheritable capability grant. Existing source-currentness and actual-image qualification must establish the finite file facts; another compiler's image pin does not establish them. + +**L7 — Capability plus Landlock does not invent security-label xattrs on ordinary creation.** + +Hypotheses: L1's exact active stack; ordinary selected filesystem creation; no default ACL or other creation metadata effect on the actual associated parents unless separately proved; same underlying creator IDs, umask and requested mode; L5 grants the required path-creation rights. The original metadata association supplies the relevant observed parent/object attributes or a separate genuine original native qualifier covers the exact filesystem primitive. + +Conclusion: the selected LSM stack itself adds no AppArmor/SELinux/Smack-style creation label or differing security xattr to the new regular file/directory. This closes that specific security-label branch; it does not erase or waive POSIX default ACL, filesystem-native attributes, unmapped named ACL conversion or retained-tree negatives. + +Proof: `commoncap.c`, lines 1444–1465, and `landlock-fs.c`, lines 1650–1679, enumerate the relevant registered hooks. Neither registers `inode_init_security`; Landlock's creation hooks check path access and return permission results, not metadata values. `security.c`, lines 1809–1853, obtains creation xattrs only from registered `inode_init_security` hooks, with the no-xattr case returning without installing a label. Therefore the selected LSM stack supplies none. Filesystem default ACL inheritance is a separate native/filesystem operation and is explicitly retained as a factual/consequence clause. + +The useful composition is now concrete: L1 removes unknown LSM transitions; L4 states the necessary initial-domain branch; L6 proves the ordinary unprivileged exec credential result; L7 removes LSM-generated creation labels; L3/L5 preserve the final mount and inode/rule subjects; L2 plus actual reference closure prevents ancestor proc aliases. These are proved slices that Pro can use while constructing the full original observation implication. Original executable resolution/dispatch, exact primitive coverage, required faults, ordinary filesystem semantics and genuine association are to be joined by that main theorem rather than renamed compatible fields. No component publication or whole-caller acceptance is inferred from this handoff. diff --git a/research/h25-native-view-facts/proof/LSM-ACQUISITION-ABI-v1.md b/research/h25-native-view-facts/proof/LSM-ACQUISITION-ABI-v1.md new file mode 100644 index 0000000000..d6948ce884 --- /dev/null +++ b/research/h25-native-view-facts/proof/LSM-ACQUISITION-ABI-v1.md @@ -0,0 +1,13 @@ +Concrete LP64 acquisition lemma + +Under the selected Linux `v6.12` x86-64 ABI, `lsm_list_modules` is syscall number `461`. Its arguments are an actual `u64 *` ID buffer, an actual `u32 *` byte-size field, and `u32 flags`. The source of this ABI is `primary/syscall_64.tbl`, physical line 387, Git blob `7093ee21c0d1c0410dbf17a77cb70a6bc6736f04`, SHA256 `980ce3115028c71c5618e7864d262017bde8103bcfe7b413147a14fd312c92ac`. This is the native LP64 call, not an x32 or compatibility syscall. + +The exact expected module IDs for the proposed small-stack branch are `LSM_ID_CAPABILITY = 100` and `LSM_ID_LANDLOCK = 110`, from `primary/lsm-uapi.h`, physical lines 54 and 64, Git blob `938593dfd5daf46e81011e1e69845c10bd89bc1b`, SHA256 `a19a8afbe91fbc57d8245a23c6e37ebd11b3cfc068771288beace8b24f3c09bb`. + +A concrete bounded acquisition can use an actual 16-byte two-ID buffer and an actual four-byte size field initialized to 16, with flags zero. The branch's successful fact is the real syscall returning count 2, returned byte size 16, and exactly the two distinct IDs `{100, 110}`. It is not a caller-supplied Python list. A larger stack yields the actual insufficient-buffer branch; an unsupported ABI, inherited filter or other failure retains the actual errno and does not become a successful small-stack observation. Capacity/error ownership, syscall result and observed data must be tied to the genuine source-private parent invocation. These statements specify the interface for future source implementation; no call was made during this review. + +`primary/lsm_syscalls.c`, lines 96–120, verifies flags, reads the provided size, returns the required size, checks capacity and copies every active ID. `primary/security.c`, lines 323–324 and 615–645, establishes the selected initialization-only registration. Therefore, under the original genuine kernel/source association and no-hostile-administration interval, one successful actual query distinguishes the active hook set. It need not use an unrestricted textual policy parser or a privileged service. The same immutable active stack applies to the original and transformed process on that kernel. + +This acquisition does not expose per-task Landlock domains or inherited seccomp rules. It cannot justify silently discarding an old Landlock layer. The existing checked private-mount branch witnesses absence of an applicable inherited filesystem domain, with the separate REFER caveat documented in `CONFIG-AND-INHERITANCE-LEMMAS-v1.md`. A null-initial-domain native model or an exact reached-operation argument must handle that remaining state. The source-defined semantic conclusion is distinct from actual current-kernel qualification, and neither the buffer nor a serialized representation creates authority. + +The complete exact retained source index is `primary/INDEX-v5.json`, SHA256 `f9cd2170254668e02472484e84abc62bb8c42cf280ad20b7694572158e7da0ee`; full-byte checksums are `primary/SOURCE-SHA256SUMS-v4.txt`, SHA256 `3e69f19e091d49a07278c3fb159ff188c4bce572016a432c920a04c106aed5fb`. These are source references for the ongoing main proof, not an independently sufficient component route or execution admission. diff --git a/research/h25-native-view-facts/proof/METADATA-PRIMITIVE-LEMMA-v1.md b/research/h25-native-view-facts/proof/METADATA-PRIMITIVE-LEMMA-v1.md new file mode 100644 index 0000000000..063f102a14 --- /dev/null +++ b/research/h25-native-view-facts/proof/METADATA-PRIMITIVE-LEMMA-v1.md @@ -0,0 +1,29 @@ +L12 — Mount-write mediation for ordinary metadata primitives + +Hypotheses: use the selected exact Linux `v6.12` VFS semantics; the actual successful constructor has the final copied namespace with all ordinary mounts read-only except the exact artifact parent and usage clones; old regular-file, directory and mount references are retired; self/ancestor proc-reference closure is established as in L2/L3; no unreviewed delegated filesystem or administrative topology interposition is introduced. This lemma concerns ordinary namespace file objects. The explicitly admitted stdout/stderr pipe endpoints are a separate internal-filesystem channel and are not falsely described as read-only mounts. + +Conclusion: allowing `chmod`, ownership, timestamp and xattr syscall families does not let an ordinary final-view path or an O_RDONLY/O_PATH file reference mutate a read-only external file. These syscalls perform a VFS mount-write check before their inode metadata operation. They remain available on the artifact/usage exceptions, subject to normal permission and operation-specific checks. Thus the proof need not claim that Landlock can filter metadata, and it need not exempt a compiler from confinement. + +The exact primitive proof is: + +| Primitive family | Exact retained source and physical lines | Required step before mutation | +|---|---|---| +| `chmod`, `fchmod`, `fchmodat`, `fchmodat2` | `primary/open.c`, `chmod_common` 636–664 and `vfs_fchmod` 666–670; syscall wrappers route to that common operation | `mnt_want_write(path->mnt)` precedes the LSM/`notify_change` operation. The FD form uses the actual `file->f_path`. | +| `chown`, `lchown`, `fchownat` | `primary/open.c`, 811–850 | Path resolution is followed by `mnt_want_write(path.mnt)` before `chown_common`. | +| `fchown` | `primary/open.c`, 853–863 | `mnt_want_write_file(file)` precedes the ownership operation. | +| `utime`, `utimes`, `utimensat`, FD timestamp forms | `primary/utimes.c`, `vfs_utimes` 20–77 and `do_utimes_fd` 109–123 | After validating the times, `mnt_want_write(path->mnt)` precedes `notify_change`. The FD form passes its actual `f_path`; world-write permission or an O_RDONLY FD is not an exemption. A no-change/error fast path is not a mutation. | +| `setxattr`, `lsetxattr` | `primary/xattr.c`, 633–683, particularly 652–660 | The resolved path must obtain mount-write access before `do_setxattr`. | +| `fsetxattr` | `primary/xattr.c`, 686–715 | The actual file must obtain mount-write access before the xattr operation. | +| `removexattr`, `lremovexattr`, `fremovexattr` | `primary/xattr.c`, 910–974 | Both path and FD variants obtain mount-write access before removal. | + +`primary/namespace.c`, `__mnt_is_readonly` 381–384, tests the mount or superblock read-only state. `mnt_get_write_access`, 453–498, checks that state with the writer-transition synchronization and returns `-EROFS` on a read-only mount. The ordinary wrappers above use the corresponding mount-write API. Existing writer FDs require their separate reference-closure argument: merely changing a different copied mount would not revoke an old writable-mount reference. That is why closing old descriptors and replacing stdin's original devnull reference are substantive source steps. + +The `/dev/null` character sink illustrates the distinction. Opening a character device for data output can be legitimate even through a read-only mount; the exact admitted sink still has its ordinary null behavior. Its inode metadata operations nevertheless follow the mount-write checks above. Reopening stdin through the final view removes the old writable-mount timestamp route without changing the underlying null sink. The final ioctl whitelist supplies the separate device-operation restriction. + +The two inherited anonymous pipe endpoints should be stated as an admitted channel exception, not silently included in the ordinary read-only-file theorem. Their payload and FD-local effects remain subject to the exact relay/guardian lifetime and bounded-capture owner. An internal pipe inode is not a pathname alias to a retained regular capture or source file. The complete proof should not make the stronger unsupported assertion that every possible metadata bit of every anonymous kernel object is immutable. This refinement does not relax a required capture/source/retention oracle. + +For compatibility, original required metadata operations on science output must remain within the writable artifact tree and use the same actual IDs, requested mode, umask and selected filesystem semantics. L7 addresses the selected LSM creation-label branch; the original metadata association and remaining proof must retain ACL/default-ACL, copied-attribute and retention-refusal consequences. This lemma is about the confinement check, not a universal metadata-equality claim. + +Primary upstream files: [open.c](https://github.com/torvalds/linux/blob/v6.12/fs/open.c), [utimes.c](https://github.com/torvalds/linux/blob/v6.12/fs/utimes.c), [xattr.c](https://github.com/torvalds/linux/blob/v6.12/fs/xattr.c), and [namespace.c](https://github.com/torvalds/linux/blob/v6.12/fs/namespace.c). Complete Git blob and SHA256 pins are in `primary/INDEX-v6.json`, SHA256 `e1bd43774de853703ff8d6ea53b263609afecaa192a897d143cb68424cc8c2cb`, and `primary/SOURCE-SHA256SUMS-v5.txt`, SHA256 `98650e2ae84416fc655c890323a701f07a0a4f2a014a2796244b7d9ef7a15ef9`. + +This is source reasoning only. No metadata syscall, kernel/host probe, implementation, compiler/native execution, test or archive operation was performed. diff --git a/research/h25-native-view-facts/proof/MOUNT-CENSUS-LEMMA-v1.md b/research/h25-native-view-facts/proof/MOUNT-CENSUS-LEMMA-v1.md new file mode 100644 index 0000000000..e487e3a83a --- /dev/null +++ b/research/h25-native-view-facts/proof/MOUNT-CENSUS-LEMMA-v1.md @@ -0,0 +1,25 @@ +L14 — A bounded mount census can acquire the selected topology without unknown show callbacks + +Hypotheses: exact selected Linux `v6.12` native LP64 semantics; genuine actual entry with its private mount namespace and no untrusted concurrent namespace actor; capability plus Landlock as the complete active stack; existing checked setup succeeds. Query before capability drop and before descendants. The original native qualifier owns the association to the kernel semantics. This is a source construction, not a host observation. + +Conclusion: `listmount` plus selected `statmount` fields can supply actual mount IDs, parent relations, mount flags including idmapping, propagation, filesystem type and namespace identity. The basic/type/namespace query below does not call an unanalysed filesystem `show_options`, `show_path` or statfs operation. Unknown filesystem classes can be rejected or sent to a separately proved branch before optional filesystem callbacks are requested. Object correspondence must still use real descriptor results and the original reference/interval argument. + +Exact ABI: `primary/syscall_64.tbl`, lines 383–384, assigns native syscall numbers `457` to statmount and `458` to listmount. `primary/mount-uapi.h`, lines 155–197, defines the fixed 512-byte statmount header and 32-byte `mnt_id_req` version 1. Set request size 32 and spare zero. For the current namespace use `mnt_ns_id = 0`. For initial list enumeration use `mnt_id = LSMT_ROOT = UINT64_MAX`, `param = 0`, flags zero. For a particular returned mount ID, statmount's `param` is the requested mask. + +The basic/type/namespace mask is `0x63`: `STATMOUNT_SB_BASIC = 0x1`, `STATMOUNT_MNT_BASIC = 0x2`, `STATMOUNT_FS_TYPE = 0x20`, `STATMOUNT_MNT_NS_ID = 0x40`. Require the returned mask to contain the requested fields, not merely a successful syscall return. `MOUNT_ATTR_IDMAP` is `0x00100000`; an explicit non-idmapped branch checks that bit is absent. For string fields, the returned offset is relative to `str[]` after the fixed 512-byte header, not relative to the start of the buffer. Validate total returned size, offset, bounded NUL termination, and the selected exact type name. Do not read unrequested or out-of-range fields. + +Source proof: `primary/namespace.c`, lines 4887–4958, derives attributes from the actual mount flags and ID mapping; `statmount_sb_basic` reads the superblock's device/magic/selected flags directly, while `statmount_mnt_basic` reads the actual unique IDs, parent IDs and propagation. `statmount_fs_type`, lines 5001–5007, copies `sb->s_type->name`. Namespace identity is the actual namespace sequence, lines 5009–5013. By contrast `statmount_mnt_root`, lines 4969–4989, calls `show_path`, and `statmount_mnt_opts`, lines 5015–5040, may call the filesystem's `show_options`; the proposed mask deliberately does not request them. + +`do_statmount`, lines 5152–5217, calls `security_sb_statfs` before filling fields. This is an LSM permission hook, not the underlying filesystem's statfs method. In the selected complete capability/Landlock hook lists no `sb_statfs` implementation is registered, so the default hook result introduces no unknown filesystem callback. The same applies to `do_listmount`'s hook. The kernel list walk itself traverses namespace mount objects and reachability relations while holding the namespace read lock. + +Completeness must be real. If the source bound is M mounts, provide M+1 slots or use a bounded terminating cursor protocol. Accept only a returned count that proves the bound was not saturated. A full M-slot result cannot be called complete. Keep the IDs distinct, validate every reported ID/parent/namespace relation, and retain native failures as qualification failures. `listmount` enumerates mounts reachable from the caller's actual root; do not silently call that every hidden object in the entire kernel. The root/old-reference/proc closure supplies why excluded unreachable paths cannot later become science aliases. + +The before/after relation is explicit. Take the initial census after private propagation and before the two attachments. The source-owned change consists of adding read-only/nosuid on the copied base tree and attaching only the two exact artifact/usage clones, with all other attributes preserved. The second census must match that declared relation, not merely repeat a path/inode list. The entry has one task and creates no descendant until after the final restrictions; the final filter denies later mount/namespace APIs. No outside entrant is allowed under the original native interval. These source invariants own the copied-namespace interval. They do not extend research EX into global authority over host remounts; the unchanged original source/currentness/no-interposition premise still covers the relevant original-side interval. + +A real held-FD `statx` can join an object to the census using `STATX_MNT_ID_UNIQUE = 0x4000`, with `AT_EMPTY_PATH` and the corresponding returned-mask check. `primary/stat.c`, lines 248–258, sets the unique mount ID from the actual resolved path's mount. Device/inode identity alone is not this join. Also note that statx first calls `vfs_getattr`; it is not a callback-free substitute for the census. Use it only for the already qualified object/FS classes, or after safe census classification, and preserve its actual errors. Existing entry image/role/proc prerequisites remain genuine original native inputs before that later join. + +For the new config-file evidence, anchor an authenticated genuine proc root and ensure `config.gz` is a member of that same mount, through no-cross-mount relative open or an actual unique-mount-ID join. A proc magic number alone does not rule out a bind-mounted different proc member. The actual kernel/build association remains T1; the exact embedded configuration bytes corroborate it. This is a bounded source repair, not a request to probe or change the host. + +Primary upstream sources: [namespace.c](https://github.com/torvalds/linux/blob/v6.12/fs/namespace.c), [mount UAPI](https://github.com/torvalds/linux/blob/v6.12/include/uapi/linux/mount.h), [stat.c](https://github.com/torvalds/linux/blob/v6.12/fs/stat.c), [stat UAPI](https://github.com/torvalds/linux/blob/v6.12/include/uapi/linux/stat.h), and [x86-64 syscall table](https://github.com/torvalds/linux/blob/v6.12/arch/x86/entry/syscalls/syscall_64.tbl). The exact retained 33-body index is `primary/INDEX-v7.json`, SHA256 `ad8f24992e56ee040b11faee080b49d5959b63664ee4e4672f1664db11e2bbc5`; full checksums are `primary/SOURCE-SHA256SUMS-v6.txt`, SHA256 `18cfbd9a955097e25246142beebdc0e964ad7e6beeff3707ad452d53e4c39377`. + +No query, implementation, import/test, compiler/native operation or host/kernel/process probe occurred during this source proof. The lemma is usable in the ongoing construction and supplies no whole-source or execution acceptance by itself. diff --git a/research/h25-native-view-facts/proof/NATIVE-ENTRY-INVARIANTS.md b/research/h25-native-view-facts/proof/NATIVE-ENTRY-INVARIANTS.md new file mode 100644 index 0000000000..68166dedee --- /dev/null +++ b/research/h25-native-view-facts/proof/NATIVE-ENTRY-INVARIANTS.md @@ -0,0 +1,112 @@ +# Constructed invariants of the actual native entry + +The subject is `outputs/native-dispatch-closure-20261106T2206Z/implementation/native/science_view_entry.c`, SHA256 `60af72915efea62f46ea376e2ba7ed0c616f99b09ca1beec0f4b0d8173609410`. Its hash was read back in this round. The predecessor remains closed. No C source change, import of a project module, control, compiler, native operation, kernel/host/policy/namespace probe or protected runtime read is performed by this proof construction. + +These are reusable source lemmas, not an assertion that the complete theorem already follows from a profile. They give the entry's actual transition relation and positive consequences for specific original consumers. The independent kernel lemmas supply the indicated primitive semantics; the parent/Pro construction composes the finite dispatch, security, filesystem and original-observation theorem. No compiler receives an exemption or an assumption that its arbitrary effects are harmless. + +## Subjects and interpretation + +Let `t` be the authentic freshly launched entry task. Let `A` be the actual artifact-parent inode, `U` the actual usage inode, and `C` the actual cwd path and inode passed by its genuine runner. Let `M` be the copied mount namespace and `N` the new one-ID user namespace. Let `S` be the native FD registry. A registry slot records a custody operation, so the initial FD0 adoption is counted even though it is not a newly allocated kernel FD. + +For a trace of the C source, define `Ready` to be the program point immediately before its final `execve` at line 714, reached with `okay == true`. Define `SetupError` to be its non-exec exit path. A killed, interrupted or unobserved process is not assigned `Ready` or completed cleanup by this definition. Actual process exit, relay EOF, forest retirement and owner release remain observations of the original outer owners. + +The native primitive hypotheses used below are the precise selected Linux v6.12 syscall semantics, actual entry/native-image association, and the original trusted setup interval. For the partial-correctness lemmas, a successful syscall means that specific native call actually returned successfully, not an externally supplied success flag. A whole proof of admission/success for an environment must derive those outcomes from its concrete native/resource/security facts. It cannot insert the desired observation equality as a premise. + +## N1. Success is dominated by every mandatory setup owner + +**Hypotheses.** The actual code executes with ordinary C short-circuit semantics and the selected native primitives; execution reaches `Ready`. + +**Conclusion.** Native start, exact argv validation, CORE installation, entry/time authentication, namespace entry, private dispatch creation/close, view construction, capability removal, Landlock installation, known closure, final FD census, final time reauthentication and seccomp installation all completed successfully in that order. + +**Proof.** In `main` at lines 686–714, every producer of a later phase is guarded by `okay`. Every mandatory function result is conjoined into it; no assignment later changes a false `okay` back to true. At the three `close_all` boundaries, either an error or uncertainty forces false. The final `execve` is inside the last `if (okay)`. Consequently no failed setup branch can skip its failure and enter science through another call site. The C source contains no task creation call and no other successful exec path. The successful process replacing this entry is the exact GNU time path and argv prefix checked by `argv_shape` at lines 672–684, with the original trailing command passed unchanged and `environ` passed through rather than rewritten. + +This is a useful dominance result even when setup can fail: the failure is an actual paid setup error, not a scientific refusal invented by the entry. + +## N2. Descriptor ownership is monotone and unknown close cannot become success + +**Hypotheses.** The actual source begins with its statically initialized registry and executes its explicit native FD operations. A negative acquisition has the selected syscall's negative-result/no-returned-FD semantics. + +**Conclusion.** Every setup FD is reserved before acquisition and recorded immediately on return. The only descriptor state transitions are `PENDING -> FAILED` or `PENDING -> OPEN -> RETIRED -> CLOSED/UNCERTAIN`. A numeric FD is never closed twice by this registry while ownership is uncertain. At `Ready`, the actual descriptors are precisely the reestablished FD0 and original two pipe writers. + +**Proof.** `reserve`, `acquired` and `close_once` at lines 117–137 define those transitions directly. Before the native close, `close_once` changes `OPEN` to `RETIRED`; an error changes it to `UNCERTAIN`, records the actual errno and sets the global uncertainty bit. `close_all` at lines 138–142 selects only `OPEN` setup FDs above 2. It therefore cannot retry an uncertain integer, including one the kernel might already have closed. A close failure causes the owning function to return false or is caught by the subsequent mandatory error/uncertainty barrier. There is no later native acquisition on such a failed setup route. + +The initial census in `native_start` rejects every inherited FD above 2 except its own registered census descriptor. FD1 and FD2 must be distinct blocking FIFO write ends. FD0 must be the exact major/minor `1:3` character sink opened read-only. No source function closes FD1 or FD2. During stdin replacement the fresh sink is opened while old FD0 is still occupied; old FD0 is then explicitly retired and once-closed before the successful `dup3` to 0. Hence an unrelated setup acquisition cannot silently occupy a standard slot. All other known setup holders are closed before the final census, and the one later time-image FD is also once-closed before `Ready`. + +The two pipe writers are genuine runner-created capabilities by the original launch owner, not authority inferred from inode type alone. The C source independently validates their native shape and excludes a regular capture or control socket. Failure records preserve raw errno sites and custody states; they cannot establish final exit or release. + +## N3. Exact object authority and backing identities survive the view + +**Hypotheses.** The authentic runner has created `A` and `U` and supplied their actual native device/inode observations. Execution reaches `Ready`. + +**Conclusion.** `A` was an empty, caller-owned `0700` directory, `U` an empty, caller-owned `0600` single-link regular file, and the science leaf was absent. The view's writable clones expose those same actual backing objects at those exact paths. The final cwd has the original pathname and backing identity. FD0 names the same genuine devnull backing object through the final view; its original open file description has been replaced and closed with explicit custody. + +**Proof.** `validate_owned_paths` at lines 438–464 uses canonical absolute paths and no-symlink/no-magic-link `openat2` resolution, compares actual descriptor observations with the supplied device/inode values, checks modes/types/ownership/emptiness and requires `ENOENT` for the absent leaf. No caller-supplied FD is admitted. `make_view` at lines 466–493 opens the clone sources only after namespace copying, creates exactly the two detached clones and installs each on its actual opened target. Its final stat comparisons retain device, inode, mode, ownership, link, size and modification/change time fields. It reopens cwd through the final paths and restores its exact string. + +`reestablish_stdin` at lines 412–436 retains the actual device/inode/rdev/type/mode relation while accounting for UID/GID representation across the namespace. It preserves O_RDONLY, NONBLOCK status and CLOEXEC clear. Its new FD0 avoids the old devnull mount reference without pretending to preserve an arbitrary stdin OFD. The selected genuine devnull producer has no shared-position or OFD-identity consumer. This restriction is a fixed launch contract, not a new scientific-input test. + +The cross-user-namespace object comparison at lines 183–187 treats only UID/GID representation specially. Each native image hash separately checks full stable owner fields in its own context. Device/inode/mode/link/size/timestamps and complete image bytes are still compared, so this does not normalize a raw original receipt or waive original owner association. + +## N4. The root reference is itself protected, including self proc links + +**Hypotheses.** The selected kernel implements the successful unshare and mount-attribute operations used by this entry; `Ready` is reached. + +**Conclusion.** The task's own filesystem root is a copied mount whose attributes were changed in place to read-only and nosuid. Its own `/proc/self/root`, including O_PATH/openat aliases, does not reintroduce the parent's writable root mount. + +**Proof.** This is proved in `ROOT-REFERENCE-LEMMA-v1.md`, including the exact `ksys_unshare -> unshare_nsproxy_namespaces -> create_new_namespaces -> copy_mnt_ns` filesystem-structure argument. The current C implementation does not overmount a full new root; only `A` and `U` are attached as writable exceptions. A chroot correction is therefore not demanded by this proof step. This self-reference argument is separate from the ancestor-task ptrace/capability argument. + +## N5. The private dispatch owner prevents ancestor-handler recovery + +**Hypotheses.** The selected built-in registered Linux v6.12 binfmt_misc implementation is genuinely associated; the entry reaches `Ready` without an external entrant or export during trusted setup. + +**Conclusion.** Its current user namespace owns an empty binfmt_misc instance; ancestor registrations, including preopened F interpreters, are not selected by its later misc-format lookup. No visible mount or surviving fs-context FD was created. Science cannot reconfigure or import another registry through an admitted interface. + +**Proof.** N1 establishes successful `create_private_binfmt_dispatch` at lines 371–397 after namespace creation and before view/drop/descendants. That helper owns one actual `fsopen`/CREATE/once-close sequence. Under the selected primitive lemma, the first successful CREATE publishes an empty namespace-local instance which survives context close until namespace destruction. Final default-deny seccomp does not admit fsopen, fsconfig, fsmount, fspick, setns, unshare, mount APIs or descriptor-transfer interfaces. No registry mount is attached. Existing copied registry paths are read-only and receive no Landlock write permission. + +This conclusion is confinement, not automatic exec preservation. The original environment's finite ordinary/misc dispatch outcomes still need to be related to this empty lookup. No claim that every compiler or every Linux format is unaffected is used. If CREATE fails after partial publication, N1 prevents `Ready`; the helper records its actual error before the one close and leaves actual namespace retirement to the existing outer owner. It does not label that setup error an optimized scientific refusal. + +## N6. Post-exec rights are explicit and inherited + +**Hypotheses.** `Ready` is reached; subsequent primitives have the selected cap/NNP/Landlock/seccomp inheritance semantics. + +**Conclusion.** The branch has empty effective/permitted/inheritable capability sets, cleared ambient and recognized bounding sets, locked NOROOT/NO_SETUID_FIXUP securebits and NNP. It has explicit global read/execute rights, artifact write rights, exact usage write/truncate rights, the exact devnull sink exception and the two inherited pipe writers. It has no ordinary content-write or metadata-mutation authority over source, captures or administration through the copied mounts. Later process creation cannot select another user/mount/cgroup namespace through an admitted clone tuple or syscall. + +**Proof.** `drop_privilege` at lines 495–514 installs and reads back the capability/NNP state. `install_landlock` at lines 520–542 handles the complete selected ABI6 filesystem rights, both TCP rights and both scopes. Its four actual inode/path rules are: root READ/READ_DIR/EXECUTE; `A` ordinary file/directory/symlink/FIFO write/create/remove/REFER/truncate; `U` read/write/truncate; devnull read/write/ioctl subject to the final six-request filter. No network or broader write rule is added. Mount attributes enforce metadata writes outside the two clones; Landlock is not falsely credited with confining chmod/xattr/timestamps by itself. + +`install_seccomp` at lines 563–644 rejects alternate architectures and x32, gives clone3 ENOSYS and allows exactly the normalized low32 legacy tuples `003d0f00`, `00004111` and `01200011`. Ordinary fork/vfork retain their original argument treatment. The complete tuple tests do not admit a new-namespace/cgroup flag union. The remaining syscall allowlist and argument filters are literal source data, not an approval callback. Namespace/mount/context operations, sockets/SCM_RIGHTS, ptrace/process_vm, pidfd_getfd and unreviewed async interfaces are not on that list. + +By induction on allowed task creation and exec, descendants retain the namespace and mandatory restrictions. A later executable has no compiler exemption. Session/group operations that the original subprocess paths may need remain allowed, but do not change cgroup membership or the inherited policy. The original guardian, rather than a process-group-only assumption, still owns whole-domain retirement. + +## N7. Required local operation classes remain admitted by the filter + +This lemma is deliberately about the filter's exact allowance. It does not assume that an LSM, filesystem, executable or decoder subsequently succeeds. The complete model derives those effects separately. + +| Original operation class | Actual admitted native interfaces | Constructed consequence | +|---|---|---| +| File/source/header/native-image reads and stat fingerprints | open/openat/openat2, read/pread/readv, fstat/stat/newfstatat/statx, close, readlink, getdents/getdents64 | The new filter does not itself replace the selected reader's original error, content or fingerprint check | +| Artifact and evidence production | mkdir/mkdirat, open/create, write/pwrite/writev, fsync/fdatasync, rename/renameat/renameat2, unlink/rmdir, truncate/ftruncate, chmod/fchmod/fchmodat/fchmodat2, timestamps and xattr calls | The original calls can run inside `A`; copied mounts rather than a pointer-string seccomp test constrain other targets | +| Metadata helper's child-only FSIZE | setrlimit with resource != CORE; prlimit64 for self pid 0 and non-CORE resources | Its resource 1 callback and readback are admitted, while CORE changes remain denied | +| Process/thread creation and teardown | exact clone fallback tuples, ordinary fork/vfork, execve/execveat, wait4/waitid, exit/exit_group, set_tid_address, set_robust_list, rseq, futex, signal and memory primitives | The original live-thread control is not intentionally replaced by a clone3 or ordinary-thread denial | +| PIPE/text producer I/O and timeout | pipe/pipe2, dup variants, poll/select/pselect/ppoll/epoll, read/write, waits, nanosleep/clock_nanosleep, clocks and signal operations | The two PIPE/text producers keep their original communicate/timeout/decoding owner instead of being converted to raw-file helpers | +| Process identity/group observations | getpid/gettid/getppid/getpgrp/getpgid/getsid and genuine proc reads | No new PID namespace or new entry-created process is introduced to falsify the original role/group relation | + +The metadata raw-file producer remains distinct from both sysconfig/shlex/PATH PIPE/text producers. Admission of these syscall classes does not prove their separate compiler/helper/spec/interpreter resolution closures equal; no such identification is made here. + +## N8. New setup errors cannot satisfy the original terminal classifier + +**Hypotheses.** An entry setup error reaches its ordinary non-exec exit; the genuine runner/receiver source in the existing 31-function map performs the final check. + +**Conclusion.** That failure cannot be accepted as either complete normal science or the original optimized full-entry refusal. + +**Proof.** The native failure branch emits only its failure evidence and exits 78, with no scientific exec or successful receipt. `fresh_runner._poll_child` records the actual wait tuple before decoding and commits the actual exit. `full_result_receiver.validate_terminal` requires exit 0 for normal science or exit 1 for optimized refusal, plus complete cleanup/EOF/closure. Optimized refusal additionally requires the exact original traceback boundary and suffix. Exit 78 fails the common terminal test before either success branch. A signal or unresolved native wait also fails rather than being normalized to the original refusal. These are existing function-map rows 25 and 27, not new failure consumers. + +This result preserves the distinction between setup failure and original negative observations; it does not prove that every supported environment will have successful setup. Numerical native/resource/security admission remains an owned later edge in the complete construction. + +## N9. Error order, capacity and actual release remain explicit + +The native error array appends the saved errno at the point of failure. A CREATE primary is appended before a close can change errno; later close errors append in order. A full array marks uncertainty. No status flag is used as evidence that a partially published kernel object is absent. Actual release of namespaces, mounts, FD0 and pipe writers is never established by the native failure projection itself. + +The success path consumes 27 registry slots, including initial stdin adoption. Its peak is 13 registered live FDs, or 15 including the two pipe writers. The context closes before view handles, so the dispatch repair adds one lifetime slot without increasing the peak. The 96-slot and 48-error caps are unchanged; the previous exact birth/close calculation remains applicable. All source setup, failure, closure and kernel-retirement tails remain in the original enclosing attempt/cost union with physical cost `OPEN_NOT_ZERO`. + +## Composition boundary + +N1–N9 give concrete facts and a proved transition structure for the actual entry. Together with the consumer lemmas in `ORIGINAL-NATIVE-CONSUMERS-v1.md`, they close specific possible representation, self-root, first-refusal and process-control contradictions. They do not replace the full finite dispatch/security/filesystem/fault construction or the original parent/native association cut. No new C correction follows from these source facts as of this version. If the parent/Pro theorem identifies an actual failed primitive or operation consequence, the correction must be made at that exact existing owner and the affected lemma updated. diff --git a/research/h25-native-view-facts/proof/ORIGINAL-NATIVE-CONSUMERS.md b/research/h25-native-view-facts/proof/ORIGINAL-NATIVE-CONSUMERS.md new file mode 100644 index 0000000000..c1860f7d5e --- /dev/null +++ b/research/h25-native-view-facts/proof/ORIGINAL-NATIVE-CONSUMERS.md @@ -0,0 +1,98 @@ +# Native-entry invariants at the actual original consumers + +This construction reuses the existing 31-function map, `outputs/caller-observation-closure-20261106T2252Z/review/original-cases/FUNCTION-PINS-v1.json`, SHA256 `a85400c0261568a7bbdf14ddd0083d9754c7b27446f20c8f7fa3f2d24d290fe4`, and its finite case map, SHA256 `23677e5924e72e9d76a16c1d6026120ee90ab6780911847bc2f8b96d0983cdc0`. No original case census is repeated or context count changed. The original 52 body / 65 context map remains the exact predecessor record at `be1b2fd75556f2f4bbe73cfa63ef0fcd7a9e3dcd4bbd7166ebf5dd68cf2a7653`. + +All stage paths below are relative to the predecessor's `implementation/bindings/stages/joined-full-candidate-v1`. Its immutable scientific bodies are read only. The entry subject is the actual C hash `60af72915efea62f46ea376e2ba7ed0c616f99b09ca1beec0f4b0d8173609410`. The source invariants N1–N9 are in `NATIVE-ENTRY-INVARIANTS-v1.md`. + +## C1. Namespace UID/GID representation does not falsify these stat consumers + +**Hypotheses.** A selected original read path still resolves to its same backing regular inode through the copied view; no relevant source bytes, inode attributes or original custody interval has changed. The selected native reader executes the same captured primitive. This is a concrete file/path relation, not an assumption that its original predicate returns true. + +**Conclusion.** A change limited to the user-namespace representation of inode UID/GID cannot change the following consumers' stat predicate, hash value or first stat/hash refusal. Their actual source never reads the affected UID/GID fields. + +**Derivation.** Define the projections exactly as the source defines them: + +- Root `integration/full_driver.py`, `_fingerprint` at line 476 and `_hash_regular` at lines 480–507, uses `(dev, ino, size, mtime, ctime)`, separately requires regular-file type and bounds, hashes the actual bytes and verifies the same projected tuple after reading. +- Provider `integration/probe_binding_v3.py`, `_fingerprint` at line 242 and `_hash_regular` at lines 246–273, uses that same projection and separate type/size/hash checks. Its `_audit_files` at lines 290–294 compares actual byte hash and count for the runtime/header/binary triples; it does not compare an expected root UID. +- `areas/cache-validity/probe-native/native_tcb_v1.py`, `_fingerprint` at line 125 and `_hash_file` at lines 129–154, adds mode to the projection and returns the actual device/inode/mode/times/hash/size record. It has no UID/GID field in this fingerprint or returned file record. +- `integration/native_packet.py`, `_file` around lines 137–155, compares device/inode/mode/size/times and returns hash, bytes and permission mode; `_dependencies`, existing function-map row 1, then compares the declared hash and size. +- `integration/cold_build_evidence.py`, `_fingerprint` at line 33 and `_snapshot`, existing map row 11, use device/inode/mode/size/times. The reader/writer equality test uses the actual device/inode and regular-file type, not a UID representation. + +The copied mounts retain the same backing objects; read-only/nosuid are mount attributes and do not rewrite the inode's mode or contents. Therefore each displayed projection is unchanged by UID/GID representation alone. Applying the same byte reader then gives the same byte sequence and digest or the same original content/bound/stability refusal. This proves the stated local implication directly from the fields actually used. It does not assert that every copied ACL or every native security effect is harmless. + +The supplementary exact source pins read back for these reached callees are: + +| Source | SHA256 | +|---|---| +| Root `integration/full_driver.py` | `f5a2d33f2b4d3651f214156a0e7094c2bb516ce2d5ab7698d18c11f98f35dee0` | +| Provider `integration/probe_binding_v3.py` | `9cbb7368f89e71d1e6cc46db5dc77efed3e03ed2a801c98c88fe316e4d9f3ef2` | +| `native_tcb_v1.py` | `865943df5cfdbf9383362d7fb2b76c6d0fd895cf0a0e20d550a26b579606b5d7` | +| `native_tcb_controls_v1.py` | `63b1804caa7f89915662a1424f788c3becad13520e1f63212a338fb45aaa2c5a` | + +These callee pins are already literal authenticated dependencies of map row 16, `_initial_native_tcb`. Recording the concrete field use does not create additional original contexts or replace its original source checks. + +## C2. Actual native mapping/header checks remain genuine within each invocation + +**Hypotheses.** The same selected Python/native image and startup loader closure are executed through the final view; the actual source/native qualification supplies their factual association. File-backed executable mappings are not changed during the original audit interval. The read relation in C1 holds for the declared files and headers. + +**Conclusion.** The initial-TCB helper's mapping/current-file consistency proof and provider's runtime/header checks use genuine current objects after the entry, rather than a declaration from the entry or a historical inode constant. + +**Proof.** The helper reads `/proc/self/maps`, parses actual executable file-backed mappings, requires their exact path set to equal the declared inventory, reads each actual file and compares its actual device/inode to the corresponding mapping rows, then reads mappings again and requires before/after equality. N1's successful exec removes the entry's old address space; N2 leaves no native image FD behind. N4 establishes the protected task-root reference. Nothing in the entry injects a Python module or supplies a substitute mapping record. The provider's `/proc/self/exe` is the actual executed Python object, and `_audit_files` calls the same original readers on its literal runtime/header triples. + +ASLR addresses, module IDs, timing samples and actual PID fields are preserved as genuine raw observations of their own invocation. This proof does **not** rewrite those receipts, assume historical cross-invocation addresses are equal or replace the original observation relation with universal byte equality of unrelated runtime diagnostics. The main theorem must apply the original consumer projection; this lemma establishes the exact source/current-object checks that projection reaches. + +The same interpreter pathname, image bytes, source/stdlib selection, argv and environment also preserve the inputs to original `sysconfig` suffix/include evaluation. The entry changes no Python configuration source, PATH, locale, TMPDIR or argv element of the original trailing command. The original suffix/header equality test is still performed by `native_packet.prepare` (map row 2); it is reused, not replaced by a second implementation. Actual exec/security success and each compiler command's resolution are separate derived steps, not consequences of the suffix check alone. + +## C3. All five early initial-TCB controls retain their actual boundaries + +**Hypotheses.** C1–C2 and the ordinary artifact read/write/create/close/unlink relation hold for the original exclusively created `output/initial-tcb-controls` directory. The original pristine Root primitive identity relation holds. These hypotheses identify the exact operation and ownership relations; they do not assert the expected control result. + +**Conclusion and proof by the unchanged control branches.** The source-pinned `native_tcb_controls_v1.run_controls` performs: + +1. **Positive native closure.** Its unchanged helper obtains the actual mapping/file agreement proved in C2, so the original status/count/private-ABI assertions observe that genuine agreement. +2. **Wrong file digest.** The control flips one expected digest character without changing the actual bytes. C1 gives the same actual digest, hence the unchanged digest comparison raises the original `file digest differs` refusal. +3. **Missing declared map.** The control removes one declared file while C2's actual mapped-path set still contains it. The set comparison therefore fails at the original `mapped file closure differs` boundary, before file hashing. +4. **Root hash alias.** The control substitutes the original forbidden Python function into Root's hash alias. The unchanged pristine-Root identity check rejects that changed alias before the forbidden function executes, then the control restores the actual old reference. No native UID or mount flag enters this identity predicate. +5. **Isolated reader drift.** The control creates its own fixture inside that directory, reads a chunk, truncates the same fixture to one byte through another writable descriptor and then checks the original fingerprint/count. The changed size makes the unchanged reader reject `file changed during hashing`; its finally block unlinks the fixture. N6 grants write/truncate/unlink inside the artifact tree and N7 admits those syscalls. The control does not mutate a system native file or its mapping. + +This is a source derivation of these five existing cases, not a control execution. It also explains why the optimized full entry must retain early output creation: `_initial_native_tcb` (map row 16) and these controls run before `_epoch_sc4_full_entry` rejects optimization. N3 keeps the science leaf absent for that original exclusive mkdir. No entry-side optimized refusal is added. + +## C4. Genuine task census and the original live-thread refusal + +**Hypotheses.** The original branch starts with the selected single Python task, and ordinary selected glibc/Python thread creation has its stated native behavior and resources. N1–N7 hold. + +**Conclusion.** `cold_build_evidence._one_thread` (map row 8) still observes genuine task identities: it accepts exactly the original one-task state and rejects the original actual worker-thread fixture before Popen. No inevitable UID/PID mismatch is introduced by the entry. + +**Proof.** That function lists `/proc/self/task`, rejects on a second entry, and compares the remaining name with `str(os.getpid())`. It does not inspect UID/GID, parent namespaces or the host process census. The entry creates neither a PID namespace nor an extra task. Its final exec replaces the already launched process. Its exact clone policy allows the selected ordinary thread fallback, rather than denying all clone. Consequently a real second worker remains a second actual proc task, and the original `len(tasks) <= 1` guard remains the first helper refusal. The original control still owns setting and joining that worker in its finally block. This argument is separate from the private-user-namespace representation of an unrelated inode owner. + +`Phases.memory` at scientific-driver lines 349–362 reads `/proc/self/status` but consumes only the `VmRSS` row, its kB unit and the actual self `getrusage` high-water value. It does not compare proc Uid/Gid/Groups text. The entry leaves this genuine proc filesystem and PID namespace in place. The diagnostic values need not be numerically identical to an unrelated fresh run; their cost/fit and original comparison role remain unchanged and paid. + +## C5. The helper's child-only FSIZE and group relation is constructive + +**Hypotheses.** The actual inherited FSIZE tuple satisfies the original helper's `>= 16 MiB` precondition. The original preexec closure and pristine resource builtins retain their identities. The selected process primitives have their ordinary semantics. N1–N7 hold. + +**Conclusion.** The helper can install its exact `(16 MiB, 16 MiB)` tuple in the child while its original parent tuple and process group remain unchanged; the native entry does not replace this with a different compiler contract. + +**Proof.** `_limit_callback` and `_check_limit_callback` (map rows 9–10) capture resource ID 1 and the immutable tuple before launch, then validate actual closure/default/code/builtin identities. The new seccomp resource filter admits every self `setrlimit` whose resource is not CORE, including resource 1, and admits self prlimit queries/mutations for that resource. The entry itself changes no FSIZE tuple. The child callback is used by the original `Popen(..., start_new_session=False)`, so it does not create a new group/session. The entry also creates neither, and no PID namespace is introduced. The source's original child-limit/group control therefore keeps both its actual child readback and actual unchanged-parent assertions. + +This does not give the GF2 or trace producers a 16 MiB child contract: neither calls this helper. Their separate PIPE/text/90-second contracts remain exactly as the existing map states. + +## C6. Original evidence contracts and negative operation classes remain distinct + +The following is a source composition rule, not an assertion that every possible compiler succeeds. Given a proved relation for the concrete exec/loader/security/creation operations of one row, use that row's actual consumer. Never replace it with another producer's evidence behavior. + +| Original source owner and map rows | Existing evidence order that the native proof preserves | Actual negative consequence | +|---|---|---| +| Metadata `native_packet.prepare -> cold_build_evidence.run`, rows 1–4 and 8–12 | Intent, journal and exclusive regular raw files precede Popen; actual poll/wait and bounded snapshots; original primary rethrow plus ordered secondary close/evidence notices | Nonzero is original CalledProcessError; startup retains spawn entered/returned distinction; timeout/overflow prefixes stay non-final until the original outer owner retires the forest | +| GF2 `native_backend.build_native`, row 5 | Separately evaluates sysconfig CC/shlex, uses PIPE/text/timeout 90; writes build.json only after subprocess.run returns | Startup/timeout/decode exceptions occur before build.json; nonzero writes it first then raises the original native compilation requirement | +| Trace guarded authority -> `adapters.build_encoder`, rows 6–7 | Independently evaluates its own sysconfig CC/shlex; preserves PIPE/text/timeout 90 and source checks | Keeps its distinct first check and RuntimeError; does not acquire the GF2 producer's explicit empty-compiler check or metadata helper's raw-file journal | +| Separate toy `command_for/run_case/closure_identity_case`, rows 13–15 | Original explicit Python child constructor, actual raw bytes including NUL/non-UTF8, separate queue/context placement | Normal, nonzero 7, timeout, oversized log, missing executable, live thread, child limit/group and closure-identity outcomes retain their original consumers and multiplicities | +| Final original/outer consumers, rows 18–20 and 25–27 | Original main finally/STOP/late-last checks precede genuine terminal validation; actual wait and complete EOF/retirement remain required | No early receipt or new native setup failure can stand in for final original disposition; N8 proves the native exit-78 exclusion | + +For the toy startup case specifically, the command is the absent absolute path beneath its fresh output. The selected kernel's path lookup returns ENOENT before any format handler receives file bytes. The new filter permits execve and the relevant ancestors are in the declared artifact view, so this case needs the ordinary lookup/permission relation, not a fictional invalid-format handler comparison. The exact binary-format equivalence proof remains necessary for real executable/helper paths. + +## Scope of these constructed consequences + +C1–C6 discharge useful local steps: the actually observed stat fields, genuine proc task relation, five early TCB controls, child-only FSIZE/group behavior, distinct evidence owners and setup-error classifier. They do not add an absence-of-ACL preflight, strip metadata, normalize raw receipts, assume every compiler path equals the absolute metadata GCC path, or claim the two outer commands run all 65 separate original contexts. + +The exact executable/helper/spec/interpreter and security/creation/fault/topology relations are inputs from the parent/Pro finite model, interpreted at the original native qualifier and genuine owner. Source construction is active; no current environment, kernel feature, runtime fit, control/science execution, whole S10.03 acceptance or original credit is claimed here. No actual failed native proof step in these consumers currently demands a C change. The prospective simpler kernel model being discussed by Pro is evaluated separately and has not been applied to the frozen C subject. diff --git a/research/h25-native-view-facts/proof/ROOT-REFERENCE-LEMMA.md b/research/h25-native-view-facts/proof/ROOT-REFERENCE-LEMMA.md new file mode 100644 index 0000000000..31b37c4377 --- /dev/null +++ b/research/h25-native-view-facts/proof/ROOT-REFERENCE-LEMMA.md @@ -0,0 +1,46 @@ +# The entry's own proc root names the protected copied mount + +This is a constructive source lemma for the actual native entry, SHA256 `60af72915efea62f46ea376e2ba7ed0c616f99b09ca1beec0f4b0d8173609410`, from the closed native-dispatch predecessor. It resolves the proposed self-proc-root escape for that implementation. It neither executes a namespace operation nor changes the C source. + +## Statement and hypotheses + +Let `t` be the fresh, single-threaded entry task. Let `r_old` denote the root path in `t->fs` before the successful `unshare(CLONE_NEWNS)`, and let `r_new` denote the corresponding copied path afterwards. Assume the selected Linux v6.12 semantics, successful setup through the entry's recursive read-only `mount_setattr`, and the existing setup interval in which only the authenticated entry performs namespace operations. These are hypotheses about the indicated mechanism and trace, not a supplied compatibility flag or a claim about the installed host. + +**Conclusion:** after that successful operation, the mount component of the root path returned by the task's own `/proc/self/root` has the newly installed read-only attribute. Following this magic link, opening it with `O_PATH`, resolving a relative path through such a descriptor, or passing its resolved path to a metadata syscall does not recover `r_old.mnt`. No additional `chroot` is required for this root-reference property. Writable artifact and usage mounts remain the two explicitly installed exceptions below that root; they do not replace the root path. + +## The actual implementation changes attributes in place + +The C source calls `unshare(CLONE_NEWNS)` in `enter_namespaces` at lines 355–369. In `make_view` at lines 466–493 it creates detached clones of the artifact parent and usage file only. It then opens `/` and adds recursive `RDONLY | NOSUID` attributes to that opened mount. The only subsequent `move_mount` calls attach those two writable clones to their exact existing artifact and usage paths. + +In particular, this implementation does **not** attach a second root tree over `/`. The root reference cannot become stale merely because of a hypothetical root overmount that this code never performs. The subsequent cwd and stdin replacement closes their distinct pre-view reference issues; the root proof below follows the actual root path itself. + +## Derivation of the root's ownership lineage + +1. In Linux v6.12, `ksys_unshare` adds `CLONE_FS` when `CLONE_NEWNS` is requested. Its `unshare_fs` step provides a private `fs_struct` if sharing requires one. If the existing structure is already private, the absence of a newly allocated structure does not skip root remapping. +2. `unshare_nsproxy_namespaces` calls `create_new_namespaces` with the actual target filesystem structure: the newly allocated one when present, otherwise `current->fs`. `create_new_namespaces` passes that same structure to `copy_mnt_ns`. This closes the null-argument ambiguity in the unshare call chain. See [fork.c](https://github.com/torvalds/linux/blob/v6.12/kernel/fork.c) and [nsproxy.c](https://github.com/torvalds/linux/blob/v6.12/kernel/nsproxy.c). +3. `copy_mnt_ns` first copies the mount topology. In its second traversal, when an old mount matches the supplied filesystem structure's root mount, it replaces that root mount reference with the corresponding new mount reference. It similarly remaps the cwd mount. The old references are put after the traversal. Thus the task's root and cwd are not left on the parent's writable mount objects. The retained primary source is `review/proof/primary/namespace.c`, SHA256 `4e6809884d475aeb6b65a35897d55ffe7c11dd6f06d74b5784b84f3d0dc978e6`, with this function at lines 3916–3993. +4. The initial successful user-namespace creation also rules out silently starting from an unrelated chroot root in the selected source. `create_user_ns` rejects `current_chrooted()`. That predicate compares the task's root with its namespace root after following root mount stacking. This is a derived property of successful setup, rather than a new user request to alter the root. See [user_namespace.c](https://github.com/torvalds/linux/blob/v6.12/kernel/user_namespace.c) and `current_chrooted` in [namespace.c](https://github.com/torvalds/linux/blob/v6.12/fs/namespace.c). + +The copied mount keeps the corresponding backing superblock and root dentry. This explains why original device/inode and pathname observations can remain genuine even though mount ownership and mount attributes have changed. It is not an assertion of equality between unrelated fresh output inodes. + +## The root FD and the attribute update refer to that copied root + +The entry opens `/` after namespace copying. In the selected namei implementation, an absolute path starts from the task's filesystem root. An `O_PATH` open uses the ordinary path lookup; a slash-only path has no filename component that can identify an unrelated mount. `mount_setattr` then resolves the empty pathname from that actual FD. No string prefix is used as mount authority. + +`do_mount_setattr` operates on the resolved mount, and `mount_setattr_commit` writes the recalculated attributes into the mount objects themselves. With recursive operation it also visits their subordinate mounts. It does not allocate a replacement root path or leave an earlier writable copy in `t->fs`. After successful return, `r_new.mnt` itself therefore has `MNT_READONLY`. Existing stricter attributes are not cleared by the entry's zero `attr_clr`. + +The relevant primary sources are `path_init`, `nd_jump_root`, `do_o_path` and the slash-only path handling in [namei.c](https://github.com/torvalds/linux/blob/v6.12/fs/namei.c), together with `do_mount_setattr` and `mount_setattr_commit` in [namespace.c](https://github.com/torvalds/linux/blob/v6.12/fs/namespace.c). The retained namespace file places `mount_setattr_commit` at line 4573 and its mount-attribute write at line 4582. + +## Following `/proc/self/root` preserves the protected reference + +The proc implementation obtains this link's target through `proc_root_link`, which calls `get_task_root`; that operation reads the task's **current** filesystem root. `proc_pid_get_link` passes the acquired path to `nd_jump_link`. The latter installs the supplied path in the lookup state; it does not reconstruct a path from the ancestor namespace or recover a discarded parent mount reference. See [proc/base.c](https://github.com/torvalds/linux/blob/v6.12/fs/proc/base.c) and [namei.c](https://github.com/torvalds/linux/blob/v6.12/fs/namei.c). + +This argument deliberately does not depend on denying the task access to its own proc link. Self access may succeed. The returned mount is already the protected copied mount. A subsequent `openat` from an `O_PATH` descriptor uses that descriptor's actual path, so it likewise starts on the protected mount. A metadata operation that follows the magic link reaches the same copied mount and its mount-write checks. Crossing into the artifact or usage mount reaches the already declared writable exception; crossing to another ordinary copied mount reaches one covered by the recursive update. + +The ancestor-task proc argument remains separate: it uses the namespace-sensitive ptrace/capability checks and the no-prior-descendant/inherited-policy invariant. It must not be substituted for this self-reference proof. + +## Consequence for source correction and original observations + +There is no established self-root escape in the actual in-place construction, and this proof step demands no C correction. Adding `chroot("/")` would introduce another setup operation and failure edge without repairing a demonstrated defect here. If a successor changes the mechanism to overmount a new root, this lemma must be reassessed; matching backing inode alone would not prove mount-reference equality. + +The conclusion preserves the original root pathname and backing identity, original cwd pathname after its explicit reset, genuine proc visibility and PID namespace, and process/session/group relationships. It does not claim universal filesystem/LSM compatibility or equality of arbitrary runtime diagnostics. The independent filesystem and native-effect lemmas still supply the VFS consequences for each reached metadata operation, and the complete caller theorem still supplies the finite original-consumer projection. No runtime, kernel feature, resource-fit or execution admission is issued by this source lemma. diff --git a/research/h25-native-view-facts/proof/TMPDIR-CALLER-LEMMA-v1.md b/research/h25-native-view-facts/proof/TMPDIR-CALLER-LEMMA-v1.md new file mode 100644 index 0000000000..3f54f1efae --- /dev/null +++ b/research/h25-native-view-facts/proof/TMPDIR-CALLER-LEMMA-v1.md @@ -0,0 +1,15 @@ +L13 — The full normal caller establishes compiler TMPDIR before the three builds + +Hypotheses: use the exact original selected full normal scientific caller and authentic existing call graph. No foreign callback or environment substitution is introduced; the original source-currentness and genuine authority dispatch remain in force. This lemma concerns the full normal caller, not an independently launched build wrapper with a different caller. + +Conclusion: the absence of `TMPDIR` from the six-key initial launch environment does not imply that these three reached compiler families use `/tmp`. Their wrappers inherit the environment after the actual caller sets its owned compiler temporary directory. A new writable `/tmp` exception is not justified by inspecting the wrapper bodies alone. + +Exact source: P's `implementation/bindings/stages/joined-full-candidate-v1/integration/scientific_driver.py`, SHA256 `fa9f473320e9df3a2328bd8388f12eca4e7fc3eeed9289f7fdbf2eeb32a7452f`. + +At physical lines 950–953, `main_epoch` binds the output, creates `output / 'compiler-tmp'`, and assigns `os.environ['TMPDIR'] = str(compiler_tmp)`. At lines 1026–1030 it then invokes the three metadata builds through `native_packet.prepare` and the backend's `build_native`. At lines 1031–1052 it constructs the genuine existing authority dispatch that invokes the guarded adapter preparation; the exact original case map establishes its direct `adapters.build_encoder` target. The three producer wrappers pass no alternative `env`, so their actual subprocesses inherit that caller environment. The original `run_data_lane` path likewise sets its compiler temporary directory at line 455. + +This is a source-order proof, not an observed runtime environment. The actual temporary directory still needs the ordinary original path/currentness/ownership association. It lies under the science output within the admitted writable artifact tree; the readonly ordinary root does not itself deny that directory. The selected GCC/libiberty/build semantics must still establish how this fixed environment is interpreted. External specs, configured CC options and helper resolution can alter behavior and remain part of the concrete main compiler theorem. This lemma does not dismiss that distinct specs countermodel. + +The optimized full caller is not claimed to execute these normal-main builds. Its exact startup prefix and original guard refusal remain separately mapped. Likewise, a separate unchanged direct-wrapper control is retained by identity/source reuse or its actual selector; it is not silently moved under a new `/tmp` allowance. + +P is the closed predecessor `outputs/native-dispatch-closure-20261106T2206Z`. Its original scientific sources are read-only references here. No source edit, project import, test, compiler/native operation, probe or archive decoding occurred. No whole-source or runtime acceptance is inferred from this local lemma. diff --git a/research/h25-native-view-facts/proof/primary/INDEX.json b/research/h25-native-view-facts/proof/primary/INDEX.json new file mode 100644 index 0000000000..ff7bf8311c --- /dev/null +++ b/research/h25-native-view-facts/proof/primary/INDEX.json @@ -0,0 +1,303 @@ +{ + "schema": "kernel-primary-source-pins-v7", + "acquisition": "GitHub fetch_file UTF8 full exact body; no execution", + "sources": [ + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-fs.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/fs.c", + "git_blob_sha": "e31b97a9f175aad782517d52b92aa03dc66736c6", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/fs.c", + "lines": 1706 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-cred.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/cred.c", + "git_blob_sha": "db9fe7d906ba665f35dc0e63c4551ea79a866a27", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/cred.c", + "lines": 53 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-task.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/task.c", + "git_blob_sha": "dc7dab78392edca0dcf72cdc53d5fa188a00e9be", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/task.c", + "lines": 325 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-syscalls.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/syscalls.c", + "git_blob_sha": "c097d356fa4535c578b6c7f9116c231972be5bd4", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/syscalls.c", + "lines": 532 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/namespace.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/namespace.c", + "git_blob_sha": "d26f5e6d2ca35f83205aa24ac4955c7f5ec937f5", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/namespace.c", + "lines": 5824 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/lsm_syscalls.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/lsm_syscalls.c", + "git_blob_sha": "8440948a690c98e26b16249f25958f27fc23fc3d", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/lsm_syscalls.c", + "lines": 120 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/security.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/security.c", + "git_blob_sha": "c5981e558bc2643b485778edf5c5c20f725ccb00", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/security.c", + "lines": 5980 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-ruleset.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/ruleset.c", + "git_blob_sha": "a93bdbf52fff856a346d7aa6bb3e4df1e61103c1", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/ruleset.c", + "lines": 738 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-common.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/common.h", + "git_blob_sha": "0eb1d34c2eaefeb3942a576ef0f89ef37901bd27", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/common.h", + "lines": 22 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-cred.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/cred.h", + "git_blob_sha": "bf755459838a557348541183864a1885cd52f89d", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/cred.h", + "lines": 58 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/commoncap.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/commoncap.c", + "git_blob_sha": "cefad323a0b1b76908d28d1d4335471db0c796ea", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/commoncap.c", + "lines": 1478 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/proc-base.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/proc/base.c", + "git_blob_sha": "b31283d81c52ea2a984519dac166d9bcbb7c99a8", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/proc/base.c", + "lines": 4011 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/proc-fd.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/proc/fd.c", + "git_blob_sha": "5e391cbca7a3be0cb02f55e96d6728ad98e3ea16", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/proc/fd.c", + "lines": 426 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/exec.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/exec.c", + "git_blob_sha": "6c53920795c2e70c18c2f220b2a1ea15cf028373", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/exec.c", + "lines": 2171 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/Kconfig.binfmt", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/Kconfig.binfmt", + "git_blob_sha": "bd2f530e574086ff5b6d67fd0b906b5196271f58", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/Kconfig.binfmt", + "lines": 187 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/fs-Makefile", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/Makefile", + "git_blob_sha": "61679fd587b7e32ec977de193f56ebc67ed80aed", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/Makefile", + "lines": 132 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/coredump.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "include/linux/coredump.h", + "git_blob_sha": "45e598fe34766ff5e4f8ac34def49250973b8e62", + "url": "https://github.com/torvalds/linux/blob/v6.12/include/linux/coredump.h", + "lines": 78 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/signal.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "kernel/signal.c", + "git_blob_sha": "cbabb2d05e0ac840e6415fd4ae495bd936db252d", + "url": "https://github.com/torvalds/linux/blob/v6.12/kernel/signal.c", + "lines": 4905 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/kmod.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "include/linux/kmod.h", + "git_blob_sha": "68f69362d427caaaefc2565127a7a4158433e5f5", + "url": "https://github.com/torvalds/linux/blob/v6.12/include/linux/kmod.h", + "lines": 35 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/lsm_hook_defs.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "include/linux/lsm_hook_defs.h", + "git_blob_sha": "9eca013aa5e1f654050d8981d71543943c347a47", + "url": "https://github.com/torvalds/linux/blob/v6.12/include/linux/lsm_hook_defs.h", + "lines": 460 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/module-Makefile", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "kernel/module/Makefile", + "git_blob_sha": "50ffcc413b54504db946af4dce3b41dc4aece1a5", + "url": "https://github.com/torvalds/linux/blob/v6.12/kernel/module/Makefile", + "lines": 25 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-setup.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/setup.c", + "git_blob_sha": "28519a45b11ffb9c0674bf7c212999847c74d0fa", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/setup.c", + "lines": 49 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-ruleset.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/ruleset.h", + "git_blob_sha": "631e24d4ffe969a2946879238c117ddaf34d51f0", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/ruleset.h", + "lines": 397 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/exit.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "kernel/exit.c", + "git_blob_sha": "619f0014c33be4c88f7d110622124cb5a489e532", + "url": "https://github.com/torvalds/linux/blob/v6.12/kernel/exit.c", + "lines": 1974 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-net.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "security/landlock/net.c", + "git_blob_sha": "d5dcc4407a197b88d0478b9e6e102d6833bfd8f9", + "url": "https://github.com/torvalds/linux/blob/v6.12/security/landlock/net.c", + "lines": 183 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/lsm-uapi.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "include/uapi/linux/lsm.h", + "git_blob_sha": "938593dfd5daf46e81011e1e69845c10bd89bc1b", + "url": "https://github.com/torvalds/linux/blob/v6.12/include/uapi/linux/lsm.h", + "lines": 93 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/syscall_64.tbl", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "arch/x86/entry/syscalls/syscall_64.tbl", + "git_blob_sha": "7093ee21c0d1c0410dbf17a77cb70a6bc6736f04", + "url": "https://github.com/torvalds/linux/blob/v6.12/arch/x86/entry/syscalls/syscall_64.tbl", + "lines": 433 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/open.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/open.c", + "git_blob_sha": "5da4df2f9b18a637ed83cde8f2fe52f9034f5290", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/open.c", + "lines": 1655 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/utimes.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/utimes.c", + "git_blob_sha": "99b26f792b89676fe75903ae38d8bcf4f7ffec4c", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/utimes.c", + "lines": 300 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/xattr.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/xattr.c", + "git_blob_sha": "05ec7e7d9e87e219b2874ac80d858cbe3f856c71", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/xattr.c", + "lines": 1415 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/mount-uapi.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "include/uapi/linux/mount.h", + "git_blob_sha": "225bc366ffcbf0319929e2f55f1fbea88e4d7b81", + "url": "https://github.com/torvalds/linux/blob/v6.12/include/uapi/linux/mount.h", + "lines": 217 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/stat-uapi.h", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "include/uapi/linux/stat.h", + "git_blob_sha": "887a2528644168a3f0f16752e6b21958a89e0bac", + "url": "https://github.com/torvalds/linux/blob/v6.12/include/uapi/linux/stat.h", + "lines": 205 + }, + { + "local": "outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/stat.c", + "repository": "torvalds/linux", + "ref": "v6.12", + "path": "fs/stat.c", + "git_blob_sha": "41e598376d7e3d1a43641d0dd5ad467154e34364", + "url": "https://github.com/torvalds/linux/blob/v6.12/fs/stat.c", + "lines": 952 + } + ] +} diff --git a/research/h25-native-view-facts/proof/primary/SHA256SUMS.txt b/research/h25-native-view-facts/proof/primary/SHA256SUMS.txt new file mode 100644 index 0000000000..fe1bc4e14a --- /dev/null +++ b/research/h25-native-view-facts/proof/primary/SHA256SUMS.txt @@ -0,0 +1,33 @@ +ee32b028443ffe64ee694263dccc4e55c512f928ad03618288e002762299b44f outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-fs.c +3835e93570c9950506f3ef7ce661f6e1955381d2bd2df6e64a2a8ad9aca6a0c4 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-cred.c +e11096efbf2507d95e537387a39a1d33f4e28d479f77465b5f543e6ac59728ec outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-task.c +2ecfe8a975df57c8cc766f16bdaf5bd0bb9c2d6ea46851f1707fc0b6632b5571 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-syscalls.c +4e6809884d475aeb6b65a35897d55ffe7c11dd6f06d74b5784b84f3d0dc978e6 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/namespace.c +7eeafca0d9bab0c2604e48a0826c7815080936bfd680be0af054a54356b19171 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/lsm_syscalls.c +4502c95ba0a1ceeb3fb72bde8e2f5a8452fda859eb2454c318d72e09fba120b8 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/security.c +0cf9f67a9c641917f46cf8a91acad55eafcaf7ed2e3e446756bf5661307d81b4 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-ruleset.c +e6c78c3a46f76939d685cfe7bd11c71a5aa9528c1c6c9d784300e7fb542c7693 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-common.h +55eb6f50a656e0ee994e1a67003465a6d6c9ab3325d4c8d15894aee4935ab075 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-cred.h +f8dba4df187cd446bc336dfeed000b41bdd0a9afd8b8d985d9c9d502cec587d7 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/commoncap.c +3cd005fa6ce3bd17f10acf67d6e4344013da11b4814a269d239d9c1182ad0c68 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/proc-base.c +72d4ce6b4cfef31b7366baf467c42f363b86e1bc0e55e443c178584cf68534ef outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/proc-fd.c +98f1bd0885d273637457bd6709d393b8deefd2b009ac273f9fc3d26d8509ccb5 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/exec.c +10c2f90686710cf89ea0ffe553bfb3fac0994f8631af106fdc21330930296187 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/Kconfig.binfmt +2db1160e9bf2e34f2a75d9494626ca54371a31e3b07141362d42459f036c1864 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/fs-Makefile +e45c5bcae2bd832a49c29e1cc7abb5ce3c73616fcefa48d7a7c32cfd086deb7d outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/coredump.h +e93c014e2354c8806dfe3504c4f274cab250df0251745e1fd9af9c60616e9326 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/signal.c +28be64ad90b5d62b1dbad620e6dbda2443277d9474dd1420142cd3a9ce638013 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/kmod.h +ab01388507f9d4275cef5f6fe40d3110967beb4831a8b7f91866f9288a3bd0a0 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/lsm_hook_defs.h +3c6166fab71f512aa26afa03e85ca255d2c708bcd98f1ea535fde32535cec420 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/module-Makefile +3229d04a6da222be27d6d5ef8f54e1d44552471b69738f1506247a424535ed67 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-setup.c +8b78c417df0b42d5228849aed159880269cf5a073acedc2e1bc1dd7f3dd31ad8 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-ruleset.h +7c28bfc644117470b9cbe6d46c84580de98225755bbb227e61d638ea7104025d outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/exit.c +c75d317578bc8e8cd56e514c0f24ae36957eed6125656d95e9dc92b8df2aa60d outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/landlock-net.c +a19a8afbe91fbc57d8245a23c6e37ebd11b3cfc068771288beace8b24f3c09bb outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/lsm-uapi.h +980ce3115028c71c5618e7864d262017bde8103bcfe7b413147a14fd312c92ac outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/syscall_64.tbl +587769343f2fc32552fb8593138c72f47110de8b7933f921a0bf9b627282b59a outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/open.c +46bf2d1bf8bb22f604cc6ca05877010b987f9b90389f64cf275f0782598bab44 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/utimes.c +cee119de83def362e4921842dbad608e5f35e1689c06600fa4815e3a7c158de0 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/xattr.c +c44f36eadd0996b677b7266d2dafee3c2a9f13d0d391e7169e43241563d5fde5 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/mount-uapi.h +74682cc2c75d6680f51800d28b21cca27f19fef021d02d206adeec851832b0fe outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/stat-uapi.h +e5ea2ed4a1e8c59aa5ae6f132e5e220c068379dd2ba9c3eedda4f5b92ef6d5b5 outputs/caller-proof-construction-20261106T2330Z/review/proof/primary/stat.c diff --git a/research/h25-native-view-facts/proof/remaining-binutils-source-transfer.md b/research/h25-native-view-facts/proof/remaining-binutils-source-transfer.md new file mode 100644 index 0000000000..0bea8a1c0e --- /dev/null +++ b/research/h25-native-view-facts/proof/remaining-binutils-source-transfer.md @@ -0,0 +1,13 @@ +Bounded binutils source-transfer review froze2026-11-07T00:58:18.042231+00:00; strictcut00:59:31.856797UTC. **Ordered Ubuntu patch/recipe inputs recovered; the exact H effect-transfer lemma is not discharged.** + +Exactretainedsourcepackage2.42-4ubuntu2.10 has plainorderedseries1573B SHA471736d5ca682f59e71bd3a3eb6b3d8f2913cde6df64358ade1fc1f5b2c32a39, rules74935B4e63c6a9...,rules.defs7318B7e95a7b7...,andchangelog. Serieshas54noncommententries; all54have regular-membermetadata in110rowMEMBERS52c618a3.... Noneofthe54patchbodies is inthatselectedplaintextdirectory; appliedgas/ld/BFDruntimebodiesareabsentthere. CompletearchivesarealreadyretainedandDSCpinned: orig27567160Bf6e4d41... andDebian196552B6acc777.... Theywerenotdecodedinthisreview. + +Rules.defs selectsplugins/threads/jansson/deterministicarchives/newdtags andotherbaseflags; rules404-414addsshared/systemzlib/build/host/pkgversion;511-543containsnativeconfigurephaseconditionaltarget/gold/PGO/gprofng. Buildinfo46687B8dcaeb49... statesUbuntuamd64,parallel4,noudeb. Thesearepositive concreteconfigurationinputs,notageneratedconfigoreffectcorrespondenceproof. NoMake/configure/shellrecipewasexecuted. + +Savedofficialpackage-memberrecord3437B7ade5b65... matchesoriginalas745768B21aff249...andld.bfd1359128Be9ceb054... byteforbyte andlinksbuild32324448. Itdisclaimssignature,reproducibilityandconfigured-rulecompleteness; itdoesnotcoverlibbfd11f084/1479888. NativeimageassociationremainstheoriginalT1owningobligation,nocurrenthostPASSrequiredhere. + +Theexactmissingstepis54patchbody→orderedapplication→affectedruntimeunits/configdispatch→preservationofthealreadyinspectedassemblerI/O/cleanup,linkeroption/script/plugin,andBFDoutput/chmodfrontiers. Branchupdates,metadataandCVEfilenamescannotestablishunaffectedness. Minimuminputiseithertheseexactappliedaffectedunitsandconfigurationderivation,oranexistingauthenticproofboundtothesameUbuntuimage/buildsubjectandfrontiers. Upstream2.42orareleaseannouncementcannotreplaceit. + +Namedpriorpublicinput-constructorspacketREADME31/33/47haspackageassociation/selectedcoldtextscope,explicitlyleavingeffectiveconfiguration/linkerloader/originalqualificationopen. NoexactremotePRheadorexistingwholeeffectproofisclaimed. Source/buildprovenanceleadsandall54orderedmembernames/sizesarefrozenintheJSON. + +Noarchivesweredecoded,noimplementation/native/compiler/science/host/proc/originalmoduleexecutionornetworkmutationoccurred. Sourcewindowisnotreopened. Guard943seconds/budgetunchanged,zerooriginalcredit,parentgoal48unchanged,costsOPEN_NOT_ZERO. ThisdoesnotclaimbinutilsviolatesH; itidentifiesthepreciseunresolvedsourceinput/compositionstep. diff --git a/research/h25-native-view-facts/review/ACTUAL-NATIVE-ACQUISITION-REVIEW-v1.md b/research/h25-native-view-facts/review/ACTUAL-NATIVE-ACQUISITION-REVIEW-v1.md new file mode 100644 index 0000000000..0c517b2f34 --- /dev/null +++ b/research/h25-native-view-facts/review/ACTUAL-NATIVE-ACQUISITION-REVIEW-v1.md @@ -0,0 +1,83 @@ +# Independent review of the actual native acquisition proposal + +Review content frozen at 2026-11-07T00:48:17Z. This is a source review of the already frozen, unselected proposal. The first acceptance message was delivered after the 00:44:31 source cutoff; this review requests no source change, backdating or extension. No compiler, project import, control, native entry, kernel operation or host probe was executed by this reviewer. + +## Disposition + +**ACCEPT the bounded local native acquisition construction. GO for source admissibility of one separately admitted, bounded compile and mocked operation check of the two new control objects.** The parent must supply the exact source, compiler, operation, guard and resource admission before execution. This vote does not authorize running the production entry, creating namespaces, acquiring actual host LSM/mount facts, running science or qualifying the complete caller. + +The source is a concrete constructor rather than a fields-only compatibility certificate. Actual syscalls acquire the LSM stack, complete bounded mount views and actual held-object mount IDs. The source derives and checks its two-clone topology relation before the final inherited restrictions and exec. I found no consequential local counterexample to those claims under the explicit selected hypotheses below. + +This vote supplies no whole S10.03 acceptance or original activity credit. Compiler resolution/specification/helper/library semantics, complete metadata and negative-case observations, genuine configuration/image association and numerical fit remain separate conjuncts of the ongoing construction. + +## Exact reviewed objects + +All paths below are relative to this round, `outputs/caller-proof-construction-20261106T2330Z`. + +| Object | SHA256 | Review scope | +|---|---|---| +| `proof/native-entry-invariants/proposal/science_view_entry.c` | `e1740fc6c901e09477ff0d934a920ca51dfe1a4b199d14e3433e155f1ef30fb2` | Actual local source, including final acquisition and failure owners | +| `proof/native-entry-invariants/proposal/VIEW-ENTRY-CONTRACT-v1.md` | `b9e3a1b4356158503140f85ca6442328914451b60e48c5a5eef0fe358a2014c8` | Exact hypotheses, interface, consequence and resource boundaries | +| `proof/native-entry-invariants/proposal/native.json` | `02d6c3a7d0c3194a5935341b63f09d79b84957353c584b4a23a7db25c6286ebe` | Explicit prospective profile and unissued actual association | +| `proof/native-entry-invariants/ACTUAL-ACQUISITION-CONSTRUCTION-v1.md` | `71bd6cf1633bee944095394cfc466d7c51ac3f28f606bbffb1fa65f842628964` | Current frozen explanatory readback | +| `proof/native-entry-invariants/controls/native_fact_control.c` | `b7b7cfe5ebbebead55791b121b2fdb5e15d2736aafaa4a2e781e99de44ffd5fd` | Complete mocked acquisition/helper control | +| `proof/native-entry-invariants/controls/changed_policy_control.c` | `5a2529728985028865276d116f5c567e3c613e4f8f0356f9070857206318c2eb` | Complete actual filter constructor plus independent evaluator | + +The current prose/profile/contract hashes supersede earlier working hashes in messages. The actual C is still the exact `e1740fc6...` object. The selected predecessor remains distinct; this review does not silently adopt the proposal into the caller graph. + +## Hypotheses and the local conclusion + +The prospective original and transformed routes share the same genuinely associated Linux v6.12 native x86-64 LP64 source/configuration/image, with `CONFIG_BINFMT_MISC=n`, `CONFIG_COREDUMP=n` and `CONFIG_MODULES=n`. Original T1 supplies the genuine fresh trusted launch, actual loaded entry/runtime/objects, no prior descendant and the applicable no-interposition interval. The exact selected initial subject has a null Landlock domain, seccomp mode 0 and no effective cgroup BPF attachment on the science ancestry. These are unissued native state facts, not conclusions of the active LSM query, successful setup or supplied JSON. + +The contract states these premises expressly at lines 37–45, 63–65 and 100–108. The profile states them at lines 12–24 and leaves runtime admission UNISSUED at line 26. This is an admissible conditional local theorem, not evidence that any current workstation satisfies the model. In particular, the active LSM list cannot reveal a REFER-only inherited Landlock layer, an inherited seccomp program or ancestor cgroup BPF. + +Under these premises and actual successful completion, the additional constructor establishes the exact selected active LSM stack; the complete reachable bounded private mount view; the nine required object-to-mount joins; and the exact relation between the before and after views. The original trusted native primitive semantics and actual owning operations supply identity facts that a list of matching superblock fields alone cannot prove. + +## Finite source matrix + +| Edge | Exact source spans | Independent finding | +|---|---|---| +| Native ABI and fixed storage | C 80–117 | Native syscall numbers 457, 458 and 461; 32-byte request, 512-byte statmount head, 256-byte statx with mount ID at offset 144; 128 rows per census; 129 enumeration slots; no dynamic unbounded list or parser | +| Query ownership and raw errno | C 135–165 | Reserve before call; syscall failure enters the ordered collector immediately; nonnegative completion is counted before semantic validation; checked LSM flag is committed only after exact result validation | +| Complete active stack | C 156–165 | Real two-ID/16-byte call with flags zero; return count 2 and returned size 16 required; exactly distinct IDs 100 and 110 in either order; no truncation or successful error substitution | +| Decoder and complete enumeration | C 485–528 | Correct relative string-region interpretation and bounded NUL; required mask `0x63`; nonzero queried IDs and one namespace; private, non-idmapped, finite type catalogue; `M+1` saturation refused before per-row reads | +| Actual root and object joins | C 529–555, 580–591 | Finite parent chains reach the actual root mount; actual held FD is queried with unique-ID statx and joined to the real census; fstat device/inode/mode corroborated; expected local/proc/device classes and proc magic checked | +| Exact owned view relation | C 557–605 | Old IDs/parents/backing fields/type/namespace survive; exact RDONLY/NOSUID additions; exactly two new distinct clone IDs; source and target rows joined through actual owner handles; exact parent/attributes checked | +| Old references and final restrictions | C 173–218, 606–665, 809–841 | Anchors once-close before final cwd/stdin reset; old-view image FDs close before namespace entry; copied root is modified in place, not overmounted; actual restrict-self success precedes final filter and unchanged time exec | +| Resource and failure bounds | C 75–79, 147–154, 167–192, 783–784; construction prose 41–49 | Finite attempts, FD births, live descriptors, error and report storage; uncertainty stops science; no success receipt, cleanup retry or zero-cost exit claim | +| Original resource/syscall transfer | C 688–704, 723–757 | No added CORE tuple; self resource arguments reach native validation, pid-zero prlimit only; existing native ABI, clone and default denials remain separate from the new read-only acquisition | +| Actual scope of profile | Contract 49–65, 100–114; profile 18–26 | Finite prospective filesystem/state subject, not universal arbitrary filesystem/helper safety or a current-host observation | + +The primary-source provenance is the retained `review/proof/LSM-ACQUISITION-ABI-v1.md` and `MOUNT-CENSUS-LEMMA-v1.md`, with their exact Linux v6.12 source index. The syscall result layout is not inferred from installed headers. + +## Consequential qualifications + +The statmount mask asks only for superblock/basic/type/namespace fields. It avoids filesystem `show_options`, `show_path` and filesystem-statfs callbacks; the permission hook still exists and has no implementation in the selected complete capability/Landlock stack. The held-object statx calls do invoke `vfs_getattr`. The construction correctly preserves the original T1 qualification of those specific already-used objects and does not claim that their later mount join retroactively authenticates already-loaded entry code. + +The before/after catalogue covers the mounts reachable from the selected actual root. It is not a census of every hidden kernel mount or old reference. Closure instead uses the actual fresh single-task launch, namespace copy remapping of root/cwd, no old setup FD surviving the pre-namespace close barrier, the unchanged reference owner and no interposition during setup. This is why the rejected root-overmount hypothesis requires no chroot repair: the source does not attach a replacement root mount. + +Matching device/magic/superblock flags is not arbitrary superblock identity evidence. The stronger local fact comes from actual `open_tree` on the held source and actual `move_mount` of that returned descriptor at the held target. The observed relation checks that precise owning operation; the contract says so explicitly at construction lines 35–39. + +The finite mount catalogue may reject a different operating subject. This does not itself establish a new scientific refusal in the selected common original/transformed subject. Membership and the full effect proof must be genuinely associated before execution. No current-host catalogue membership is claimed, and no refusal is relabelled as the original optimized scientific outcome. + +## Resource arithmetic and lifetime + +The successful maximum path uses at most 268 added query attempts: +one LSM call + two listmount calls + 126 before rows + 128 after rows + nine original object joins + two clone joins. The capacity is 288. The constructor refuses before adding clones if the initial census exceeds 126. Every oversized/malformed branch stops before a later unchecked acquisition. + +The exact registry bill is 31 lifetime FD births in capacity 96, peak 13 tracked live FDs including stdin, or 15 actual including the two inherited writers. Before the five anchors close, the tracked peak is lower. Cleanup attempts at most 12 nonstdio closes plus the primary failure, within the 48-error collector. FD0 and the two writer releases still require actual process exit and external wait. The new census arrays and bounded temporary buffers are source-finite; numerical fit, setup cost, reporting and process-exit tails remain OPEN_NOT_ZERO. + +The acquired-query counters cover the added acquisition family. They do not pretend to count all syscalls or physical work. + +## Mocked control admissibility + +I read both complete control files. `native_fact_control.c` lines 4–10 rename the included actual source's syscall/fstat boundaries and main. Lines 14–67 supply only bounded deterministic native responses. Its main at lines 78–121 calls the real acquisition/decoder/join/relation helpers, not the entry main. It checks a complete stack, incomplete count, raw E2BIG, duplicate/additional IDs, unsaturated enumeration, actual unique-ID join, missing result bit, unlisted mount ID, changed inode, saturation before row query, duplicate/mixed namespace rows, raw EACCES, bad string extent, missing namespace mask, idmap, unknown type, unterminated type, exact clone relation, writable-base recurrence, wrong parent, changed backing fields and pre-call query capacity. All reached acquisition calls are mocked. + +`changed_policy_control.c` lines 6–14 rename actual prctl/syscall/close boundaries and main. Lines 22–38 capture the actual filter install and reject unexpected native setup. The independent forward-only evaluator at lines 39–61 interprets the emitted program rather than copying the filter decision code. Explicit operation oracles at lines 74–115 check native resource arguments, normalized pid-zero behavior, nonzero target denial, denied setup/query syscalls, required clone tuples, a prohibited tuple union, x32/alternate-architecture rejection and raw install errno without a success flag. + +Neither test invokes the production main, namespace creation, real mount/LSM/statx query, real seccomp installation or science. The included production code has no constructor that executes on inclusion. The controls use ordinary bounded process stdio for their own reports. The source therefore supports a narrowly guarded compile and mocked operation attempt of these new objects, once the parent supplies its concrete guard and admission. This is not an unchanged predecessor control rerun and is not an actual kernel-compatibility experiment. + +## Remaining whole-caller boundary + +The local constructor is now implemented source, not a proposed acquisition port. The complete theorem still needs its finite original compiler/spec/environment/helper resolution and fault/effect arguments; copied/default ACL and retained metadata consequences including original negative fixtures; genuinely associated original native/kernel/state facts; parent/receiver/custody integration; and actual guarded numerical evidence when execution is later admitted. This report does not turn those conjuncts into supplied booleans, declare them false for lack of a current run, or substitute this local acceptance for the original complete assertion-enabled caller review. + diff --git a/research/h25-native-view-facts/review/NATIVE-PROPOSAL-GUARD-REVIEW-v1.md b/research/h25-native-view-facts/review/NATIVE-PROPOSAL-GUARD-REVIEW-v1.md new file mode 100644 index 0000000000..356b3f3c36 --- /dev/null +++ b/research/h25-native-view-facts/review/NATIVE-PROPOSAL-GUARD-REVIEW-v1.md @@ -0,0 +1,55 @@ +# Independent admission review for the two new native proposal controls + +The exact corrected guard was accepted in the parent message at 2026-11-07T00:56:36Z. This record concerns one verification attempt, not the production entry or science. + +## Scope and exact objects + +GO is limited to one compile and one mocked run of EACH of the two new controls, in the fixed order already present in the guard. There is no retry or execution of the production entry, actual namespace/LSM/mount acquisition, compiler property query, original scientific command or unchanged predecessor control. + +- Guard: `validation/run_native_proposal_controls.py`, SHA256 `16bb421046a08a96efe328e8c60193bc0983fc5ade948a370e3924bcf4f173b2`. +- External group owner: `validation/native_controls_outer_owner.py`, SHA256 `a053760af494243276906d80a52515a7f1f7b5130b383ffa41ac114770c61dfa`. +- Included production proposal: `e1740fc6c901e09477ff0d934a920ca51dfe1a4b199d14e3433e155f1ef30fb2`. +- Changed-policy control: `5a2529728985028865276d116f5c567e3c613e4f8f0356f9070857206318c2eb`. +- Native-fact control: `b7b7cfe5ebbebead55791b121b2fdb5e15d2736aafaa4a2e781e99de44ffd5fd`. +- Compiler image pin: `1b99826121ae6682a634e5efe09bd3e3df58ce58e0b28f849114ab5b89139c26`. + +The parent must freeze the exact matching admission before its single launch. The guard and outer owner check their own admitted source hashes. All verification work is additional real work; no new budget or original credit is granted. + +## Resource and capture envelope + +The actual parent command is the default private-group GNU timeout form: + +```text +/usr/bin/timeout --signal=TERM --kill-after=5s 45s /usr/bin/python3.12 -S -s -P -B +``` + +An immutable 64-second reservation is created outside that group before launch. The independent external parent finalizes and debits it after tool return even if imports, close or metadata serialization terminate the managed processes. The baseline before this attempt is 1456.890533479 of 2400 seconds. This review does not assert that execution has occurred or update that ledger. + +Each compile has child wall 15 seconds and CPU 10 seconds; each mocked run has wall 2 seconds and CPU 1 second. Each child has AS 512 MiB, FSIZE 4 MiB, CORE 0 and NOFILE 64. Sources and compiler are checked before and after each step. The clean child environment uses the private TMPDIR without repurposing HOME. + +The cap for each raw stream is 65,536 bytes with one additional byte retained to detect overflow. Exclusive unbuffered files persist each read prefix before the next read. Short capture writes, overflow, missing EOF, bad wait or changed source pins cannot qualify a successful step. Ordered cleanup preserves secondary errors. All warning bytes remain raw evidence; the explicit misleading-indentation warning class is not promoted to an unobserved warning-free claim. + +## Exact failure repairs reviewed + +The initial guard `d6e44bf360eb7549d264a64a30bd465f7dacb13725892602a03ea9061a8746a7` killed and waited only its direct compiler on failure. A compiler helper could remain in the inherited group after the guard returned early, preventing the ordinary timeout from proving group retirement. It also supplied HOME. Neither issue required a change to the frozen native proposal. + +The intermediate outer owner `105768e150cbed09ead5899c7c7eb01b9f98e77b10138ddf6ad51df5d4866b1d` repaired ordinary and error-return group ownership but had a default-TERM deadline branch. Its direct death at the outer TERM could allow the monitor to finish before the delayed KILL while a descendant ignored TERM. + +The final outer source makes the ownership concrete: + +1. Before creating a child, lines 33–37 require its process group to equal its actual parent PID, distinct from itself and greater than 1. Under the exact parent command, that parent is the still-live GNU timeout group leader. +2. Lines 38–46 install a TERM handler that SIGKILLs this verified own group. The handler is installed before any guard or compiler birth. +3. The guard and every admitted child inherit that same group; no new session or group is created by these sources. +4. Normal/error guard completion reaches the same group-retirement operation in the outer finally block at lines 68–81. It occurs while the timeout parent still holds the numeric group identity. +5. If the kill operation itself raises, the owner keeps the identity chain alive rather than releasing it for reuse; the prepaid outer deadline remains responsible for its terminal attempt. + +This closes the two precise source lifetime branches. It neither targets another group nor uses a stale numeric ID after releasing its owner. + +A group kill request is not a self-issued universal physical-release certificate. The external parent must retain actual tool/wait and raw/result evidence, mark any unknown or incomplete terminal state honestly, and not infer original G-domain retirement or source qualification from this component wrapper. + +## Success interpretation and disposition + +The outer group's exit 137 is expected deliberate cleanup. It is not the control oracle. Success requires the four actual guarded step results, zero direct compile/control returns, known waits, both EOFs, the exact two control stdout/stderr expectations, stable pins and retained warnings/errors. Missing result or pre-retirement evidence remains incomplete. + +**GO for the exact single bounded component attempt, conditional on the parent's matching frozen admission, immutable reservation and independent finalization.** No rerun is authorized. This reviewer performed no compile, mock execution or kernel operation. The local source acceptance remains in `ACTUAL-NATIVE-ACQUISITION-REVIEW-v1.md`; the complete caller theorem and original S10.03 remain separate. + diff --git a/research/h25-native-view-facts/review/NEW-MOCK-RESULT-READBACK-v1.md b/research/h25-native-view-facts/review/NEW-MOCK-RESULT-READBACK-v1.md new file mode 100644 index 0000000000..f7f9010615 --- /dev/null +++ b/research/h25-native-view-facts/review/NEW-MOCK-RESULT-READBACK-v1.md @@ -0,0 +1,18 @@ +# Independent passive readback of the new mocked controls + +Actual readback completed at 2026-11-07T00:58:50Z, before the 00:59:31 review cutoff. This reviewer did not execute or rerun any control. + +The parent-produced `verification-native/RESULT.json` has SHA256 `5d853d07aaaaccddaa6c071129e3680da4cf6968d435918b167d4de397f4ff07`. It records PASS for the exact two new controls and four ordered steps. Every step has return code 0, known wait, both EOFs, complete true and no recorded errors. The compile steps retained 5,437 and 5,433 bytes of stderr respectively. I read both complete raw warning streams: each contains five misleading-indentation warnings at proposal C lines 154, 239, 493, 643 and 791, with their source notes. The warned sequential statements have the intended reviewed control flow. No warning-free claim is warranted. + +The changed-policy control has empty stdout and stderr (both SHA256 `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`). The native-fact control has empty stderr and exactly these 64 stdout bytes: + +```text +unselected native fact control: finite operation oracles passed +``` + +That stdout has SHA256 `e938ab0debc79b2a1578b478231fb7fa9919cdfd0849d7922e4b75c9d4bc9110`. + +The outer `PRE-RETIREMENT.json` records the guard's known wait, return code 0, no errors, and the held timeout group/manager relationship. Its record precedes deliberate group retirement. Exit 137 is the separately specified cleanup terminal, not the four-step test oracle. External prepaid accounting and any physical terminal uncertainty remain the parent's independently retained responsibility. + +**ACCEPT the observed component result in its exact mocked scope.** The actual helper/constructor controls passed; no production entry, actual kernel/namespace/LSM/mount probe, original caller or compiler-property query was executed by them. The result explicitly preserves whole-source accepted false and original credit delta 0. It does not discharge the applied Ubuntu binutils source-transfer lemma or the remaining connected parent/compiler/fallback changes. + diff --git a/research/h25-native-view-facts/source/ACQUISITION-CONSTRUCTION.md b/research/h25-native-view-facts/source/ACQUISITION-CONSTRUCTION.md new file mode 100644 index 0000000000..c278ff8370 --- /dev/null +++ b/research/h25-native-view-facts/source/ACQUISITION-CONSTRUCTION.md @@ -0,0 +1,51 @@ +# Actual acquisition construction for the unselected native proposal + +This document describes the concrete C proposal in `proposal/science_view_entry.c`. It is an unapplied successor of predecessor SHA256 `60af72915efea62f46ea376e2ba7ed0c616f99b09ca1beec0f4b0d8173609410`. It does not change the selected implementation, establish the current host's membership in the model, authorize execution or supply complete caller acceptance. No compiler, import, control execution, native operation or host/kernel probe was performed by this author. + +The construction uses the completed Pro response at `../../consultation/RESPONSE-v1.md`, the independent `../../review/proof/LSM-ACQUISITION-ABI-v1.md`, and `../../review/proof/MOUNT-CENSUS-LEMMA-v1.md` (SHA256 `2598bbb04d8a68ca6a1148547de0a9f0c790012518afb309e0796f7ad5b67f9d`). Their exact retained primary-source index and physical source lines are the provenance of the syscall ABI and callback claims. These sources describe Linux v6.12, not the currently installed kernel. + +## Hypotheses and conclusion + +The original genuine native qualifier associates both routes with the same selected Linux v6.12 LP64 x86-64 kernel and its images, with binary-format misc, core dumping and module loading compiled out. The original fresh trusted launch has the inspected one-task/no-prior-descendant and actual object/loader/source qualifications. The selected original T1 subject has a **null initial Landlock domain**, **initial seccomp mode 0**, and **no effective cgroup BPF attachment on the actual science ancestry**. These state premises are currently unissued native facts. LSM enumeration, setup success and JSON data do not establish them; the proposal performs no ancestor-policy acquisition. The actual no-interposition interval excludes an outside actor entering or mutating the private mount namespace. Original compiler resolution, helper/library contents, source exclusion, metadata/ACL consequences, cgroup/lifetime ownership and actual resource fit retain their separate proof obligations. + +Conditional on those hypotheses, successful completion of the proposed setup establishes these additional actual facts before GNU time: the active LSM set is exactly capability and Landlock; the reachable private mount topology fits the declared bound and finite non-idmapped catalogue; each of nine held objects joins to a real mount ID of the required class; and the source-owned mount change consists precisely of making the existing copied tree read-only/nosuid and adding the two exact owned clones. These facts are useful inputs to the complete theorem. They are not a universal compiler harmlessness statement or a replacement for actual original T1 association. + +## Active stack acquisition + +The actual syscall is native 461, flags zero, with a real two-element `uint64_t` buffer and a real `uint32_t` size field initialized to 16. Success requires actual return count 2, returned bytes 16 and the two distinct IDs 100 and 110 in either order. A larger stack, unsupported kernel, inherited denial or malformed result cannot become a selected success. Attempt reservation precedes the syscall; a raw failure records its errno before any cleanup. `lsm_checked` is assigned only after all result checks succeed. + +The kernel's initialization-only LSM registration and this full result bind the source hook set. The result does not reveal per-task Landlock state or inherited seccomp rules. The independent inheritance proof gives the narrower implication that successful mount setup excludes an applicable inherited filesystem-handling domain. It does not exclude a REFER-only inherited domain. This construction therefore retains original T1 null-domain membership explicitly; it does not invent a compatible flag or infer total nullness from successful mount setup. + +## Safe census and concrete object joins + +After actual user and mount namespace entry and recursive private propagation, the owner holds root, cwd, artifact parent, exact usage inode, proc root, devnull, entry path, time path and Python path. The latter five are additional registered O_PATH anchors. No outside or supplied descriptor is accepted. + +`listmount` uses the version 1 32-byte request, current namespace, root sentinel, zero cursor and flags. It allocates 129 positions for a 128-mount bound and accepts only a positive returned count at most 128. Thus an apparent full bounded result cannot hide a 129th reachable mount. Before cloning, the count is further bounded by 126 to reserve two positions. Returned IDs are nonzero and strictly ascending. + +For each ID, `statmount` requests exactly `0x63`. The 512-byte header, requested returned-mask bits, queried ID, common nonzero namespace, returned total extent, relative filesystem-type string offset and bounded NUL are checked. No MNT_OPTS, MNT_ROOT or MNT_POINT field is requested. The source's superblock/basic/type/namespace paths do not call filesystem `show_options`, `show_path` or the filesystem statfs implementation. The `security_sb_statfs` permission hook still executes; the actual selected complete LSM stack has no registered implementation and its source default is zero. + +The finite model accepts ordinary local ext4/tmpfs mounts, genuine proc, device devtmpfs/devpts and auxiliary sysfs/cgroup2. Every row must be non-idmapped, private and without propagation peer/master IDs. This selection deliberately does not purport to classify an arbitrary delegated filesystem or arbitrary operation as harmless. The complete compiler proof still has to establish every reached operation and search/dependency effect, even through a catalogue member. An unsupported mount class produces a paid setup failure, not an original optimized refusal. + +Each held object is queried with actual `statx(AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW)` for unique mount ID, type, mode and inode. The source requires those returned mask bits and compares mode, device and inode with the actual FD's fstat. It then looks up the returned unique mount ID in the actual census and checks the expected class. Proc's joined superblock magic must also be genuine proc. Root/cwd/artifact/usage/entry/time/Python use the local class; proc and devnull use their distinct classes. + +This is an actual object-to-mount join, rather than an inference from path text or equal device numbers alone. `statx` invokes `vfs_getattr`, so the original T1 qualification of these specific ordinary/proc/device objects remains an explicit hypothesis. The later join does not retroactively authenticate an unqualified already-loaded entry. Python's path association is not a new Python byte/dependency authentication mechanism. The compiler theorem must still associate the remaining helper and library closure, with each original compiler contract unchanged. + +## Exact topology relation and reference closure + +After the two source-owned attachments, a second complete census and the actual attached-clone FD joins are acquired. Every old ID must remain present with the same parent, type, namespace and superblock device/magic/flags and exactly its original attributes plus RDONLY and NOSUID. The two new IDs must be distinct and absent from the old graph. Each new row preserves the source row's backing fields and attributes plus NOSUID and has its exact original target mount as parent. The new count is exactly the old count plus two. Every nonroot parent chain must terminate at the actual held root ID within the finite bound. + +The native owner supplies the stronger backing-object fact: `open_tree` clones the actual held target path, and `move_mount` attaches that very descriptor at the actual held target. Equal observed superblock fields alone are not asserted to prove equality of arbitrary superblock objects. The acquisition checks detect divergence from the declared source operation; the original trusted owner and interval tie its handles to those actual operations. + +The root-reference lemma applies unchanged. The program does not overmount `/`; `copy_mnt_ns` remaps the caller's actual root and cwd, and recursive mount attributes change those copied mounts in place. Its self proc root therefore refers to the protected root. Existing object/cwd/readback and stdin replacement checks still run. Five new association anchors are once-closed before final cwd/stdin and Landlock setup; all other setup FDs close through the existing barriers. No prior descendant exists; future descendants inherit restrictions. Later seccomp denies namespace/mount/import operations. The complete old-reference/proc argument closes unreachable aliases rather than calling listmount a census of hidden objects in the entire kernel. + +## Error ordering, exact bounds and controls + +The FD owner, ordered error collector and once-close state transitions are unchanged. Every added O_PATH acquisition reserves its slot before the actual open. Native query acquisition has its own fixed 288-position attempt bound, reserved before the syscall. Nonnegative results increment its completion count before later semantic checks; failed calls retain raw errno immediately. These counters count the added acquisition calls, not all process syscalls or physical work. + +The maximum successful path consumes 268 new acquisition positions: one LSM call, two list calls, 126 before and 128 after statmount calls, nine initial object joins and two clone joins. Fixed census storage holds 128 rows per view. A list buffer has 129 uint64 slots; each statmount buffer is 576 bytes. No unbounded mount list, string parser or allocation loop is introduced. + +Lifetime FD births total 31 in the existing cap 96: the prior simplification's 26 plus five anchors. Before closing anchors, peak is 12 tracked live FDs including stdin, while the later unchanged Landlock phase still determines the peak of 13 tracked and 15 actual including the two relay writers. At most 12 cleanup closes plus a primary error fit within the existing 48-error cap. An uncertain close is never retried or called complete. Native namespace/mount/reference release still requires the external actual wait; report/exit/setup costs stay OPEN_NOT_ZERO. + +Failure JSON preserves the actual new attempt/completion counts, census counts and checked LSM/topology flags. No success receipt is introduced. `landlocked` remains assigned only after actual restrict-self success. A later setup failure, close failure or exec failure remains a paid pre-science failure with raw ordered evidence. + +Two proposed control sources remain unexecuted. `changed_policy_control.c` checks the actual fixed seccomp constructor through a mocked install boundary and independent cBPF operation oracles. `native_fact_control.c` checks the actual LSM/census/decoder/relation helpers against finite complete/incomplete/malformed/errno/capacity cases, with all reached syscalls mocked. Neither is the genuine native entry image or an actual kernel observation. Their operation plan requires independent GO and later parent guarded admission under the existing budget; it grants no execution permission itself. diff --git a/research/h25-native-view-facts/source/EXACT-NATIVE-CHANGE.diff b/research/h25-native-view-facts/source/EXACT-NATIVE-CHANGE.diff new file mode 100644 index 0000000000..f0e6de1fd2 --- /dev/null +++ b/research/h25-native-view-facts/source/EXACT-NATIVE-CHANGE.diff @@ -0,0 +1,353 @@ +--- a/implementation/native/science_view_entry.c ++++ b/implementation/native/science_view_entry.c +@@ -6,6 +6,9 @@ + * See VIEW-ENTRY-CONTRACT-v1.md for the fixed argv, external trust premises, + * Linux-v6.12 source basis and the still-unassociated Q_sigma environment. + * No metadata broker, supplied descriptor, compatible flag or ACL stripping. ++ * Both routes select CONFIG_BINFMT_MISC=n, CONFIG_COREDUMP=n and ++ * CONFIG_MODULES=n. Genuine native qualification must associate that exact ++ * semantic kernel subject; neither this entry nor JSON data detects it. + */ + #define _GNU_SOURCE + #include +@@ -41,9 +44,6 @@ + #error The entry is the reviewed native LP64 x86-64 ABI only + #endif + _Static_assert(sizeof(void *) == 8 && sizeof(long) == 8, "LP64 required"); +-#if !defined(SYS_fsopen) || !defined(SYS_fsconfig) +-#error Selected Linux x86-64 build headers must declare fsopen and fsconfig syscall numbers +-#endif + + /* Selected v6.12 UAPI shapes, intentionally independent of libc header age. */ + struct sv_mount_attr { uint64_t attr_set, attr_clr, propagation, userns_fd; }; +@@ -56,10 +56,6 @@ + #define SV_MOVE_TO_EMPTY 0x40U + #define SV_MOUNT_RDONLY UINT64_C(1) + #define SV_MOUNT_NOSUID UINT64_C(2) +-/* Linux-v6.12 include/uapi/linux/mount.h values. Local names avoid requiring +- * mutually varying libc/kernel mount-header enum definitions in one TU. */ +-#define SV_FSOPEN_CLOEXEC 1U +-#define SV_FSCONFIG_CMD_CREATE 6U + #define SV_FS_EXEC (UINT64_C(1)<<0) + #define SV_FS_WRITE (UINT64_C(1)<<1) + #define SV_FS_READ (UINT64_C(1)<<2) +@@ -84,6 +80,41 @@ + /* Native x86-64 Linux-v6.12 syscall table. This metadata operation is safe + * under the same final mount-write checks as chmod/fchmod/fchmodat. */ + #define SV_NR_FCHMODAT2 452 ++#define SV_NR_STATMOUNT 457 ++#define SV_NR_LISTMOUNT 458 ++#define SV_NR_LSM_LIST_MODULES 461 ++#define SV_MAX_MOUNTS 128U ++#define SV_MAX_QUERIES 288U ++#define SV_MOUNT_IDMAP UINT64_C(0x00100000) ++#define SV_STATMOUNT_MASK UINT64_C(0x63) ++#define SV_STATX_MASK 0x4103U ++struct sv_mnt_request { uint32_t size, spare; uint64_t id, param, ns; }; ++struct sv_statmount_head { ++ uint32_t size, opts; uint64_t mask; ++ uint32_t dev_major, dev_minor; uint64_t magic; ++ uint32_t sb_flags, fs_type; uint64_t id, parent; ++ uint32_t old_id, old_parent; uint64_t attr, propagation, peer, master, from; ++ uint32_t root, point; uint64_t ns, spare[49]; ++}; ++struct sv_statmount_buffer { struct sv_statmount_head h; char str[64]; }; ++struct sv_statx_time { int64_t sec; uint32_t nsec; int32_t reserved; }; ++struct sv_statx { ++ uint32_t mask, blocksize; uint64_t attr; ++ uint32_t links, uid, gid; uint16_t mode, spare; ++ uint64_t ino, size, blocks, attr_mask; struct sv_statx_time times[4]; ++ uint32_t rdev_major, rdev_minor, dev_major, dev_minor; ++ uint64_t mount_id, tail[13]; ++}; ++_Static_assert(sizeof(struct sv_mnt_request)==32,"v6.12 request ABI"); ++_Static_assert(sizeof(struct sv_statmount_head)==512,"v6.12 statmount head"); ++_Static_assert(offsetof(struct sv_statmount_buffer,str)==512,"statmount string base"); ++_Static_assert(sizeof(struct sv_statx)==256&&offsetof(struct sv_statx,mount_id)==144,"v6.12 statx ABI"); ++enum sv_fs_class { SV_FS_UNKNOWN, SV_FS_LOCAL, SV_FS_PROC, SV_FS_DEVICE, SV_FS_AUX }; ++struct sv_mount_row { struct sv_statmount_head h; char type[16]; enum sv_fs_class class; }; ++struct sv_census { size_t count; struct sv_mount_row row[SV_MAX_MOUNTS]; }; ++static struct sv_census mounts_before, mounts_after; ++static unsigned native_queries_started, native_queries_completed; ++static bool lsm_checked, topology_checked; + + extern char **environ; + enum sv_fd_state { SV_UNUSED, SV_PENDING, SV_OPEN, SV_RETIRED, SV_CLOSED, SV_FAILED, SV_UNCERTAIN }; +@@ -95,7 +126,6 @@ + static bool uncertain, error_overflow, user_entered, mount_entered; + static bool root_private, root_readonly, artifact_attached, usage_attached; + static bool landlocked, filtered; +-static bool dispatch_attempted, dispatch_created, dispatch_context_closed; + static uid_t uid; + static gid_t gid; + static int stdin_status_flags; +@@ -114,6 +144,26 @@ + errno = EPROTO; + return failed(site); + } ++/* Non-FD acquisitions have a separate fixed attempt budget. Reserve before ++ * the syscall; a failed syscall's errno is recorded before cleanup. */ ++static bool begin_query(void) { ++ if(native_queries_started==SV_MAX_QUERIES){errno=E2BIG;return failed("native-query-capacity");} ++ native_queries_started++;return true; ++} ++static bool query_result(long result,const char *site) { ++ if(result<0)return failed(site);native_queries_completed++;return true; ++} ++static bool valid_lsm_result(long count,uint32_t bytes,const uint64_t ids[2]) { ++ return count==2&&bytes==16&&((ids[0]==100&&ids[1]==110)||(ids[0]==110&&ids[1]==100)); ++} ++static bool read_lsm_stack(void) { ++ uint64_t ids[2]={0,0};uint32_t bytes=sizeof ids; ++ if(!begin_query())return false; ++ long result=syscall(SV_NR_LSM_LIST_MODULES,ids,&bytes,0U); ++ if(!query_result(result,"actual-lsm-list-modules"))return false; ++ if(!require(valid_lsm_result(result,bytes,ids),"exact-capability-landlock-active-stack"))return false; ++ lsm_checked=true;return true; ++} + static int reserve(const char *site) { + if (fd_count == SV_MAX_FDS) { errno=EMFILE; failed("fd-registry-capacity"); return -1; } + size_t slot=fd_count++; +@@ -337,14 +387,6 @@ + return true; + } + +-static bool core_profile(void) { +- struct rlimit inherited,selected={1,1},actual; +- if(getrlimit(RLIMIT_CORE,&inherited)<0)return failed("inherited-core-limit"); +- if(!require(inherited.rlim_max==RLIM_INFINITY||inherited.rlim_max>=1,"core-one-compatible-inherited-hard-limit"))return false; +- if(setrlimit(RLIMIT_CORE,&selected)<0)return failed("install-core-one-profile"); +- if(getrlimit(RLIMIT_CORE,&actual)<0)return failed("core-one-readback"); +- return require(actual.rlim_cur==1&&actual.rlim_max==1,"exact-protected-core-one-profile"); +-} + static bool write_mapping(const char *path,const char *bytes,size_t count,const char *site) { + int fd=opened(path,O_WRONLY|O_NOFOLLOW,site);if(fd<0)return false; + /* A proc ID-map write is one operation, never a partial-write retry. */ +@@ -368,34 +410,6 @@ + if(mount(NULL,"/",NULL,MS_REC|MS_PRIVATE,NULL)<0)return failed("recursive-private-root"); + root_private=true;return true; + } +-static bool create_private_binfmt_dispatch(void) { +- /* The selected operating TCB is Linux-v6.12 CONFIG_BINFMT_MISC=y with +- * successful built-in filesystem registration. This is a precise source +- * selection, never a supplied flag or host-support claim: get_fs_type must +- * find the registered implementation without request_module. Actual image +- * association is a separate mandatory parent admission before execution. +- * +- * In our fresh user namespace bm_fill_super initializes an empty list and +- * publishes user_ns->binfmt_misc. No fsmount/visible mount is constructed. +- * Closing this unattached context drops its superblock, not that namespace +- * instance. It continues to shadow every ancestor handler until userns +- * destruction; later creation/registration/import is denied by lockdown. +- */ +- if(!require(user_entered&&mount_entered&&root_private&&!dispatch_attempted&& +- !root_readonly&&!landlocked&&!filtered,"once-private-dispatch-before-view-and-lockdown"))return false; +- int slot=reserve("private-binfmt-fsopen");if(slot<0)return false; +- dispatch_attempted=true; +- int context=acquired(slot,syscall(SYS_fsopen,"binfmt_misc",SV_FSOPEN_CLOEXEC)); +- if(context<0)return false; +- bool created=true; +- if(syscall(SYS_fsconfig,context,SV_FSCONFIG_CMD_CREATE,NULL,NULL,0)<0) { +- /* Save the actual create errno BEFORE the once-close can replace it. */ +- created=failed("private-binfmt-fsconfig-create"); +- } else dispatch_created=true; +- bool closed=close_once(context); +- if(closed)dispatch_context_closed=true; +- return created&&closed&&!uncertain; +-} + static int clone_mount(int fd,const char *site) { + int slot=reserve(site);if(slot<0)return -1; + return acquired(slot,syscall(SYS_open_tree,fd,"",SV_EMPTY_PATH|SV_OPEN_TREE_CLONE|O_CLOEXEC)); +@@ -463,22 +477,133 @@ + if(errno!=ENOENT)return failed("science-leaf-absence-query"); + return true; + } ++/* This finite catalogue selects sigma0; it does not assert that arbitrary ++ * operations on every listed filesystem are harmless. LOCAL is the selected ++ * ext4/tmpfs ordinary-file class; PROC/DEVICE are joined to their exact roles. ++ * AUX mounts are catalogued but receive no writable clone or special grant. ++ * Delegated and unanalysed filesystem classes take a paid setup failure. */ ++static enum sv_fs_class fs_class(const char *name) { ++ if(!strcmp(name,"ext4")||!strcmp(name,"tmpfs"))return SV_FS_LOCAL; ++ if(!strcmp(name,"proc"))return SV_FS_PROC; ++ if(!strcmp(name,"devtmpfs")||!strcmp(name,"devpts"))return SV_FS_DEVICE; ++ if(!strcmp(name,"sysfs")||!strcmp(name,"cgroup2"))return SV_FS_AUX; ++ return SV_FS_UNKNOWN; ++} ++static const struct sv_mount_row *mount_row(const struct sv_census *c,uint64_t id) { ++ for(size_t i=0;icount;i++)if(c->row[i].h.id==id)return &c->row[i];return NULL; ++} ++static bool decode_mount(const struct sv_statmount_buffer *b,uint64_t id,struct sv_mount_row *out) { ++ if(!require(b->h.size>512&&b->h.size<=sizeof *b&& ++ (b->h.mask&SV_STATMOUNT_MASK)==SV_STATMOUNT_MASK&&b->h.id==id&&id&&b->h.ns, ++ "statmount-complete-basic-type-namespace"))return false; ++ size_t strings=b->h.size-512; ++ if(!require(b->h.fs_typestr+b->h.fs_type; ++ const char *end=memchr(name,0,strings-b->h.fs_type); ++ if(!require(end&&end!=name&&(size_t)(end-name)type,"statmount-bounded-type"))return false; ++ memset(out,0,sizeof *out);out->h=b->h;memcpy(out->type,name,(size_t)(end-name));out->class=fs_class(out->type); ++ return require(out->class!=SV_FS_UNKNOWN&&!(out->h.attr&SV_MOUNT_IDMAP)&& ++ out->h.propagation==MS_PRIVATE&&!out->h.peer&&!out->h.master, ++ "selected-nonidmapped-private-mount-class"); ++} ++static bool census(struct sv_census *out) { ++ uint64_t ids[SV_MAX_MOUNTS+1]={0}; ++ struct sv_mnt_request req={.size=sizeof req,.id=UINT64_MAX}; ++ if(!begin_query())return false; ++ long n=syscall(SV_NR_LISTMOUNT,&req,ids,(size_t)SV_MAX_MOUNTS+1,0U); ++ if(!query_result(n,"complete-listmount"))return false; ++ if(!require(n>0&&(unsigned long)n<=SV_MAX_MOUNTS,"listmount-unsaturated-bound"))return false; ++ out->count=(size_t)n; ++ for(size_t i=0;icount;i++) { ++ if(!require(ids[i]&&(i==0||ids[i]>ids[i-1]),"listmount-distinct-ascending-ids"))return false; ++ req=(struct sv_mnt_request){.size=sizeof req,.id=ids[i],.param=SV_STATMOUNT_MASK}; ++ struct sv_statmount_buffer b={0}; ++ if(!begin_query())return false; ++ long result=syscall(SV_NR_STATMOUNT,&req,&b,sizeof b,0U); ++ if(!query_result(result,"actual-statmount-basic-type-namespace")|| ++ !require(result==0,"statmount-zero-success")||!decode_mount(&b,ids[i],&out->row[i]))return false; ++ if(i&&!require(out->row[i].h.ns==out->row[0].h.ns,"one-actual-private-mount-namespace"))return false; ++ } ++ return true; ++} ++static bool graph_rooted(const struct sv_census *c,uint64_t root) { ++ if(!require(mount_row(c,root)!=NULL,"actual-root-mount-in-census"))return false; ++ for(size_t i=0;icount;i++) { ++ uint64_t next=c->row[i].h.id;size_t steps=0; ++ while(next!=root&&stepscount) { ++ const struct sv_mount_row *r=mount_row(c,next); ++ if(!require(r&&r->h.parent!=next,"reachable-mount-parent"))return false; ++ next=r->h.parent;steps++; ++ } ++ if(!require(next==root,"mount-parent-chain-terminates-at-actual-root"))return false; ++ } ++ return true; ++} ++static bool join_object(int fd,const struct sv_census *c,enum sv_fs_class expected,uint64_t *id) { ++ /* statx invokes vfs_getattr: original T1 already qualifies these actual ++ * ordinary/proc/device objects. The safe census precedes this later join. */ ++ struct stat st;struct sv_statx sx={0}; ++ if(!stat_fd(fd,&st,"join-object-fstat")||!begin_query())return false; ++ long result=syscall(SYS_statx,fd,"",AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW,SV_STATX_MASK,&sx); ++ if(!query_result(result,"join-object-statx-unique-mount"))return false; ++ if(!require(result==0&&(sx.mask&SV_STATX_MASK)==SV_STATX_MASK&&sx.mount_id&& ++ sx.ino==(uint64_t)st.st_ino&&sx.mode==(uint16_t)st.st_mode&& ++ sx.dev_major==major(st.st_dev)&&sx.dev_minor==minor(st.st_dev),"statx-actual-object-and-unique-id"))return false; ++ const struct sv_mount_row *r=mount_row(c,sx.mount_id); ++ if(!require(r&&r->class==expected,"held-object-selected-mount-class"))return false; ++ if(expected==SV_FS_PROC&&!require(r->h.magic==SV_PROC_MAGIC,"joined-genuine-proc-superblock"))return false; ++ *id=sx.mount_id;return true; ++} ++static bool same_mount_backing(const struct sv_mount_row *a,const struct sv_mount_row *b) { ++ return a->h.dev_major==b->h.dev_major&&a->h.dev_minor==b->h.dev_minor&& ++ a->h.magic==b->h.magic&&a->h.sb_flags==b->h.sb_flags&&a->h.ns==b->h.ns&& ++ a->class==b->class&&!strcmp(a->type,b->type); ++} ++static bool exact_view_relation(uint64_t root,uint64_t art,uint64_t use,uint64_t ac,uint64_t uc) { ++ if(!require(mounts_before.count<=SV_MAX_MOUNTS-2&&mounts_after.count==mounts_before.count+2&& ++ ac!=uc&&!mount_row(&mounts_before,ac)&&!mount_row(&mounts_before,uc),"exactly-two-new-clone-ids"))return false; ++ for(size_t i=0;ih.id); ++ if(!require(b&&same_mount_backing(a,b)&&a->h.parent==b->h.parent&& ++ b->h.attr==(a->h.attr|SV_MOUNT_RDONLY|SV_MOUNT_NOSUID),"base-mount-only-readonly-nosuid-change"))return false; ++ } ++ const struct sv_mount_row *a=mount_row(&mounts_before,art),*u=mount_row(&mounts_before,use); ++ const struct sv_mount_row *ca=mount_row(&mounts_after,ac),*cu=mount_row(&mounts_after,uc); ++ if(!require(a&&u&&ca&&cu&&same_mount_backing(a,ca)&&same_mount_backing(u,cu)&& ++ ca->h.parent==art&&cu->h.parent==use&&ca->h.attr==(a->h.attr|SV_MOUNT_NOSUID)&& ++ cu->h.attr==(u->h.attr|SV_MOUNT_NOSUID),"exact-owned-clone-backing-parent-and-flags"))return false; ++ return graph_rooted(&mounts_after,root); ++} + static bool make_view(char **argv) { + /* Open all writable-clone sources only AFTER copy_mnt_ns has remapped root + * and cwd, so no retained path points into the parent's writable mounts. */ + int art=-1,use=-1,cwd=-1; + if(!validate_owned_paths(argv,&art,&use,&cwd))return false; ++ int root=opened("/",O_PATH|O_DIRECTORY|O_NOFOLLOW,"copied-root-handle");if(root<0)return false; ++ int anchors[5];const char *paths[5]={"/proc","/dev/null",argv[2],argv[6],argv[28]}; ++ const char *sites[5]={"association-proc-root","association-devnull","association-entry","association-time","association-python"}; ++ for(size_t i=0;i<5;i++){anchors[i]=role_open(paths[i],O_PATH,sites[i]);if(anchors[i]<0)return false;} ++ if(!census(&mounts_before)||!require(mounts_before.count<=SV_MAX_MOUNTS-2,"reserve-two-mount-slots"))return false; ++ int handles[9]={root,cwd,art,use,anchors[0],anchors[1],anchors[2],anchors[3],anchors[4]}; ++ enum sv_fs_class classes[9]={SV_FS_LOCAL,SV_FS_LOCAL,SV_FS_LOCAL,SV_FS_LOCAL,SV_FS_PROC,SV_FS_DEVICE,SV_FS_LOCAL,SV_FS_LOCAL,SV_FS_LOCAL}; ++ uint64_t ids[9]; ++ for(size_t i=0;i<9;i++)if(!join_object(handles[i],&mounts_before,classes[i],&ids[i]))return false; ++ if(!graph_rooted(&mounts_before,ids[0]))return false; + int artclone=clone_mount(art,"detached-artifact-mount");if(artclone<0)return false; + int useclone=clone_mount(use,"detached-usage-mount");if(useclone<0)return false; + if(!mount_attributes(artclone,SV_MOUNT_NOSUID,0,"artifact-clone-nosuid")|| + !mount_attributes(useclone,SV_MOUNT_NOSUID,0,"usage-clone-nosuid"))return false; +- int root=opened("/",O_PATH|O_DIRECTORY|O_NOFOLLOW,"copied-root-handle");if(root<0)return false; + if(!mount_attributes(root,SV_MOUNT_RDONLY|SV_MOUNT_NOSUID,SV_RECURSIVE,"recursive-readonly-nosuid-copied-tree"))return false; + root_readonly=true; + if(!attach_mount(artclone,art,"attach-exact-writable-artifact"))return false; + artifact_attached=true; + if(!attach_mount(useclone,use,"attach-exact-writable-usage"))return false; + usage_attached=true; ++ uint64_t ac,uc; ++ if(!census(&mounts_after)||!join_object(artclone,&mounts_after,SV_FS_LOCAL,&ac)|| ++ !join_object(useclone,&mounts_after,SV_FS_LOCAL,&uc)||!exact_view_relation(ids[0],ids[2],ids[3],ac,uc))return false; ++ topology_checked=true; ++ for(size_t i=0;i<5;i++)if(!close_once(anchors[i]))return false; + /* Re-resolve through final paths. Do not fchdir a pre-attachment handle. */ + int final_cwd=role_open(cwd_path,O_PATH|O_DIRECTORY,"final-view-cwd");if(final_cwd<0)return false; + struct stat a,u,c,r; +@@ -570,14 +695,12 @@ + !SV_EQ(0x003d0f00U,0,1)||!SV_RET(SV_ALLOW)|| + !SV_EQ(0x00004111U,0,1)||!SV_RET(SV_ALLOW)|| + !SV_EQ(0x01200011U,0,1)||!SV_RET(SV_ALLOW)||!SV_RET(SV_DENY)||!SV_LOAD_NR())return false; +- /* setrlimit affects self only; CORE is sealed even against lowering to 0. */ +- if(!SV_EQ(SYS_setrlimit,0,4)||!SV_LOAD_ARG(0)||!SV_EQ(RLIMIT_CORE,0,1)|| +- !SV_RET(SV_DENY)||!SV_RET(SV_ALLOW)||!SV_LOAD_NR())return false; +- /* prlimit64 pid_t normalizes to low32. Only pid=0; a CORE query has NULL +- * new_limit in both pointer words. Other self resources retain arguments. */ +- if(!SV_EQ(SYS_prlimit64,0,12)||!SV_LOAD_ARG(0)||!SV_EQ(0,1,0)||!SV_RET(SV_DENY)|| +- !SV_LOAD_ARG(1)||!SV_EQ(RLIMIT_CORE,0,6)||!SV_LOAD_ARG(2)||!SV_EQ(0,1,0)|| +- !SV_RET(SV_DENY)||!SV_LOAD_ARG_HI(2)||!SV_EQ(0,1,0)||!SV_RET(SV_DENY)|| ++ /* Core dumping is compiled out on both routes. Preserve ordinary self ++ * setrlimit arguments, including CORE; kernel hard-limit checks apply. */ ++ if(!allow_number(SYS_setrlimit))return false; ++ /* The original selected resource wrappers use pid=0 (self). Preserve all ++ * query/mutation arguments. Nonzero process targets remain unavailable. */ ++ if(!SV_EQ(SYS_prlimit64,0,4)||!SV_LOAD_ARG(0)||!SV_EQ(0,1,0)||!SV_RET(SV_DENY)|| + !SV_RET(SV_ALLOW)||!SV_LOAD_NR())return false; + /* fcntl retains ordinary descriptor/lock/pipe commands, never ownership, + * signal delivery, leases or notification. */ +@@ -651,14 +774,14 @@ + char out[SV_REPORT_CAP];size_t used=0; + #define APPEND(...) do { int amount=snprintf(out+used,sizeof out-used,__VA_ARGS__); \ + if(amount<0||(size_t)amount>=sizeof out-used){uncertain=true;goto emit;} used+=(size_t)amount; } while(0) +- APPEND("{\"schema\":\"h25-native-view-setup-failure-v1\",\"exit\":78,\"science_started\":false,\"uncertain\":%s,\"error_overflow\":%s,\"user_entered\":%s,\"mount_entered\":%s,\"root_private\":%s,\"root_readonly\":%s,\"artifact_attached\":%s,\"usage_attached\":%s,\"landlocked\":%s,\"filtered\":%s,\"private_dispatch_attempted\":%s,\"private_dispatch_created\":%s,\"private_dispatch_context_closed\":%s,\"errors\":[", ++ APPEND("{\"schema\":\"h25-native-view-setup-failure-v1\",\"exit\":78,\"science_started\":false,\"uncertain\":%s,\"error_overflow\":%s,\"user_entered\":%s,\"mount_entered\":%s,\"root_private\":%s,\"root_readonly\":%s,\"artifact_attached\":%s,\"usage_attached\":%s,\"landlocked\":%s,\"filtered\":%s,\"errors\":[", + uncertain?"true":"false",error_overflow?"true":"false",user_entered?"true":"false",mount_entered?"true":"false", +- root_private?"true":"false",root_readonly?"true":"false",artifact_attached?"true":"false",usage_attached?"true":"false",landlocked?"true":"false",filtered?"true":"false", +- dispatch_attempted?"true":"false",dispatch_created?"true":"false",dispatch_context_closed?"true":"false"); ++ root_private?"true":"false",root_readonly?"true":"false",artifact_attached?"true":"false",usage_attached?"true":"false",landlocked?"true":"false",filtered?"true":"false"); + for(size_t i=0;i exclusive runner layout and relay -> this entry/view -> original GNU time and complete scientific command -> real process/writer retirement and terminal receiver -> original retained-tree seal/archive/restoration/oracles/readback. This entry alone supplies no original activity credit. + +## Fixed native argv and genuine parent inputs + +The runner passes this exact prefix, followed by the original GNU time argv without modification: + +```text +ENTRY + --entry-image ENTRY_PATH ENTRY_SHA256 ENTRY_BYTES + --time-image /usr/bin/time TIME_SHA256 TIME_BYTES + --read-root ORIGINAL_CWD + --artifact-parent ARTIFACT_PARENT ACTUAL_DEVICE ACTUAL_INODE + --science-leaf science + --usage USAGE_PATH ACTUAL_DEVICE ACTUAL_INODE + -- + /usr/bin/time -f ORIGINAL_JSON_FORMAT -o USAGE_PATH -- /usr/bin/python3.12 ... +``` + +`--` is argv index21; the unchanged time argv starts at22. At most160 arguments and65536 total argument bytes are accepted. Each argument is less than PATH_MAX. The exact format is `{"user_seconds":%U,"system_seconds":%S,"kernel_max_rss_kib":%M,"exit":%x}`. The source requires the fixed switches, observer path, Python path, format, `-o` destination and inner delimiter. Complete command/profile/role inverses remain the genuine parent's responsibility; the native prefix is not an alternative command authority. + +`--read-root` is the exact original cwd assertion; its retained name avoids another API change. The selected read/execute scope is `/`, not just that directory. The original cwd, frozen input, reference, loader, library, proc and source paths remain readable. This policy protects writer ownership, source currentness and lifetime containment; it does not claim read confidentiality for unrelated accessible objects. Outer captures may be read but may not be reopened **for writing** or mutated. Prior Pro expressly permits broader tool-tree read/execute when every image inherits the write/lifetime restrictions. This does not make compilers trusted. + +The joined parent authenticates the actual entry source/image association, exact time and original scientific/native images, source/profile/command tuple, and the current objects it creates. Its profile DATA has exactly `schema=joined-native-entry-profile-v1`, `entry_path`, `entry_sha256`, `entry_bytes`, `time_path=/usr/bin/time`, `time_sha256`, `time_bytes`, `source_sha256` and `association_sha256`. The profile hash or the presence of these fields cannot establish that association. Current native memory, loader and installed kernel are external original qualification obligations. + +The runner itself exclusively creates an empty0700 artifact parent and a regular0600 empty single-link usage file, obtains device/inode from actual `fstat`, and retires/closes its creating usage descriptor before launch. The original `science` child remains absent. Captures are siblings outside the artifact parent and remain relay-owned regular0600 files. No capture FD enters this process. `Popen(close_fds=True)` leaves exactly the admitted three descriptors; the entry independently checks a complete bounded descriptor census. No arbitrary approved FD or fourth setup channel exists. + +Entry checks are concrete: role paths are absolute without dot, dot-dot, repeated slash, trailing slash or symlink components; `openat2` uses NO_SYMLINKS|NO_MAGICLINKS. Opened artifact/usage descriptors must match the actual numbers passed, ownership, type, modes, empty directory/file and unique usage link. The entry compares actual getcwd to the admitted original cwd. Path inputs are not evidence of exclusive creation; that fact comes from the real runner's creation/custody chain. + +The entry hashes the complete opened entry image with a16MiB cap, checks stable descriptor metadata, and compares it to `/proc/self/exe`'s actual object. It hashes the opened GNU time image, closes all pre-view FDs, then reopens and rehashes time in the final view and checks the same identity. Both images must be regular, executable, not group/other writable and not setuid/setgid. Existing image link counts are observed and compared for stability; no unnecessary unique-link rule is imposed on a system executable. Each hash preserves stable uid/gid fields within its own namespace. The cross-user-namespace comparison preserves device/inode/mode/link/size/timestamps and full bytes while accounting for translated uid/gid representations: an originally root-owned image is not falsely required to report UID0 inside the one-ID map. Namespace/mount operations do not change kernel inode ownership; original owner qualification remains with the real outer parent. The final path exec requires the original no-external-mutation/exclusive-ownership premise through exec; a supplied hash cannot close a mutable-image race or authenticate already-loaded code. Native-memory/image qualification is still required before execution. + +## Owning setup sequence + +1. Acquire the actual complete active LSM list with native syscall 461, a two-ID buffer and a 16-byte size field. Accept only count 2, returned size 16 and the distinct IDs 100 (capability) and 110 (Landlock), in either order. A larger stack, absent ABI or inherited denial remains an actual setup failure. Then check actual unprivileged equal real/effective/saved UID and GID, empty initial capability sets, genuine proc superblock, exactly one native task and no direct child. The authenticated fresh launch plus the entry's absence of any task-creation call supplies the no-prior-descendant premise. `/dev/null` stdin must be read-only with native major/minor 1:3. Stdout/stderr must be distinct blocking FIFO write ends with CLOEXEC clear, not regular captures or sockets. +2. Preserve inherited resource limits, including CORE. The selected prospective kernel on both original and transformed routes has `CONFIG_COREDUMP=n`; no entry-installed CORE tuple, readback or hard-CORE-below-1 refusal is used. Ordinary self setrlimit and pid-zero prlimit64 queries/mutations retain all arguments for every resource, including CORE, subject to the original kernel hard-limit checks. The exact disabled-core signal/wait/file-effect lemma and finite original fault consumers belong to the complete proof; this document does not detect a host configuration. +3. `unshare(CLONE_NEWUSER)`; write one mapping `uid uid 1`; write `deny` to setgroups before the one mapping `gid gid 1`; check the same numeric IDs. The underlying UID/GID are preserved. Other IDs, supplementary-group representations and named ACL values are not claimed to have unchanged user-namespace representations. No setgroups call clears the original kernel supplementary group list. +4. `unshare(CLONE_NEWNS)` copies the original mount tree and remaps root/cwd. Do not create a PID namespace, pivot_root, chroot, session, process group or child. Set recursive private propagation. The selected prospective kernel has `CONFIG_BINFMT_MISC=n` and `CONFIG_MODULES=n` on both routes, so this entry performs no binary-format filesystem-context operation, registry publication or module request. It proceeds directly to the existing view owner; no substitute broker or visible registry mount is introduced. +5. Resolve and validate writable clone sources **in the copied namespace**. Hold actual root, cwd, artifact, usage, proc root, devnull and entry/time/Python image objects. Acquire a complete pre-change mount census and join those nine objects to its unique mount IDs. Then create detached nonrecursive `open_tree(CLONE|CLOEXEC|AT_EMPTY_PATH)` clones of exactly the empty artifact parent and exact usage file. Add NOSUID to each; no preexisting stricter flag is cleared. +6. On the copied root, `mount_setattr(AT_EMPTY_PATH|AT_RECURSIVE)` adds RDONLY|NOSUID. Attach the two detached clones by exact O_PATH/owned directory target handles with move_mount EMPTY_PATH flags. No writable clone of a capture directory, cwd, source tree or administration tree is made. The parent-created science leaf stays absent for the unchanged scientific exclusive mkdir. +7. Acquire a second complete census and the actual unique mount IDs of the two attached clone descriptors. Require the exact before/after relation described below, then once-close the five additional association anchors. Re-resolve cwd through the final view, check root, cwd, artifact and usage backing identities, and restore that exact cwd. Reopen the same genuine `/dev/null` through the final read-only view, explicitly retire/once-close the old FD0, then dup the new handle to 0 without an implicit close. Read back same backing device/inode/rdev/type/mode, namespace-aware ownership, O_RDONLY, original NONBLOCK status and CLOEXEC clear. A failed old-FD close is uncertain and stops setup; it is never retried or declared complete. Close every other setup/directory/mount FD once. Descendants have not yet been created. +8. Clear ambient and recognized bounding capabilities, lock NOROOT and NO_SETUID_FIXUP securebits, clear effective/permitted/inheritable sets, read back empty sets and install/read back no_new_privs. Install Landlock, close its rule/path/ruleset descriptors, perform another census and authenticate GNU time through the final view. +9. Install the final LP64 seccomp filter and exec the unchanged GNU time command. Successful exec replaces the entry's old executable and mappings and leaves only admitted stdin and two relay writers. Time opens the admitted existing usage inode itself. The original wait owner, PID namespace, genuine proc PID/task data and process-group/session relationships are preserved. + +Unsupported setup fails before GNU time/science. No host configuration is changed, fallback helper is launched or narrower ACL-free scientific-input rule introduced. A negative mount syscall does not become successful setup; attached mounts and namespace flags remain evidence until the parent observes actual process exit. + +## Concrete mount acquisition and its selected scope + +The source uses the exact native Linux v6.12 32-byte `mnt_id_req` version 1 with zero spare and namespace fields. `listmount` (458) starts at `LSMT_ROOT = UINT64_MAX`, cursor zero and flags zero. A 129-ID buffer proves completeness for the 128-mount bound only when the returned positive count is at most 128. A saturated 129 result refuses. The pre-change census additionally reserves two positions, so it must contain at most 126 mounts. IDs must be nonzero, distinct and ascending. + +For every ID, `statmount` (457) requests mask `0x63` only: superblock basic fields, mount basic fields, filesystem type and namespace ID. The source checks success zero, all required returned bits, the exact queried ID, one nonzero namespace ID, a returned total size within the 576-byte buffer, a type offset relative to the 512-byte header's following string region, and a bounded NUL. No mount-option, mount-root or filesystem `show_options`, `show_path` or filesystem-statfs callback is requested. The LSM `sb_statfs` permission hook still occurs; the actual complete capability/Landlock stack and its selected source hook lists supply its zero default result. Compile-time assertions pin the 32-byte request, 512-byte head and 256-byte statx layouts. + +The finite selected catalogue is ordinary local `ext4`/`tmpfs`, genuine `proc`, device `devtmpfs`/`devpts`, and auxiliary `sysfs`/`cgroup2`. All reported mounts must lack `MOUNT_ATTR_IDMAP`, have private propagation and no peer/master IDs. This is a restrictive prospective semantic subject, not a universal harmless-filesystem theorem or a current-host description. The nine concrete object joins require local mounts for root, cwd, artifact, usage and three images; proc for the proc root; and the device class for devnull. Auxiliary mounts receive no writable clone or exception. Unanalysed or delegated classes refuse setup. The actual compiler source/helper effect proof still owns every operation reached through broad reads and execution. + +The held-object join requests `STATX_MNT_ID_UNIQUE`, type, mode and inode on each actual FD with EMPTY_PATH and SYMLINK_NOFOLLOW. It requires all returned bits and compares the actual device, inode and mode to that FD's actual fstat result, then joins the unique mount ID to the census and selected class. `statx` calls `vfs_getattr`; the original T1 qualification of these actual ordinary/proc/device objects is a hypothesis, rather than a claim that statx is callback-free. The genuine proc superblock magic is checked on its joined row. Python's path join is an object/mount fact, not a replacement for original image/dependency authentication. + +Every pre-change row must remain present with unchanged unique ID, parent, superblock device/magic/flags, namespace and type, and exactly its old attributes plus RDONLY|NOSUID. The two new IDs must be distinct, absent from the old census, preserve their source mount's backing fields and old attributes plus NOSUID, and have the exact source target mount as parent. The census count must increase by exactly two. Every nonroot parent chain must terminate at the actual held root ID within the census bound. The caller's root row may itself have an outside parent because listmount describes the actual reachable view, not all hidden kernel objects. + +These checks run inside the single-task private namespace, before capability drop or descendants. The source owns the two mount operations in that interval. The original no-interposition/native-trust interval excludes an outside entrant or mutation; later seccomp denies mount/namespace APIs. The self-root/remapped-root and once-closed-old-reference lemmas supply why unreachable mounts cannot become later aliases. No chroot or root overmount is introduced. + +The source also requires a **null initial Landlock domain as an original T1 fact** for this sigma0 subject. The active LSM list does not expose per-task domains. Successful mount setup proves absence of an applicable inherited filesystem-handling domain, but does not prove total domain nullness: a REFER-only inherited domain can remain consequential for reparenting. This proposal does not replace that premise with a supplied compatible flag or infer it from mount success. An alternate model would need an exact proof for every reached REFER operation. Genuine original kernel/configuration/image qualification and exact embedded-config acquisition remain separate parent obligations. + +The selected original genuine T1 state also has **initial seccomp mode 0** and **no effective cgroup BPF attachment on the actual science ancestry**. These are precise unissued native state premises, not observations established by the new constructor. Active LSM IDs do not exclude classic seccomp or cgroup BPF. A successful set of sampled operations cannot prove that every relevant ancestor policy is absent or equivalent. This proposal accepts no supplied boolean for that state and claims no host or ancestor-policy query. A separately source-associated kernel with BPF syscall support compiled out could provide a different constructive branch, but this proposal does not silently select or prove that additional configuration. + +## Confinement composition and alias argument + +The final mount tree is recursively private/read-only/NOSUID except the two exact writable clones. VFS mount-write checks, rather than Landlock metadata promises, confine chmod/chown/timestamp/xattr mutations. Required metadata operations remain permitted in the artifact view. The source never strips an ACL, rewrites xattrs, mediates metadata, relocates scientific output out of retention or changes the retention oracle. Existing stricter NOEXEC/NODEV/readonly/etc. flags are never cleared. + +Landlock requires ABI>=6 plus a separately associated compatible successor semantics. It handles all16 ABI6 filesystem rights, both TCP rights, and both signal/abstract Unix scopes. `/` gets READ_FILE|READ_DIR|EXECUTE. The artifact parent additionally gets write/truncate/remove/create regular/dir/symlink/FIFO and REFER. The usage file gets read/write/truncate; no write/create/remove authority is granted over its parent. The exact `/dev/null` object gets read/write for CPython DEVNULL's read/write open and IOCTL_DEV subject to the final filter's six harmless requests, preserving native TCGETS/isatty ENOTTY rather than replacing it with a Landlock denial. No network rule is added. Device/socket creation rights and general device ioctl rights are not granted. + +Every accessible ordinary alias uses the final mount tree and is read-only outside the two admitted clones. Pre-view file/directory/mount/namespace FDs are closed and the trusted entry creates no writable file mapping. This includes replacing stdin's original open file description: even O_RDONLY `/dev/null` on the old writable mount could support a NOW timestamp change through its0666 permissions. The reopened final-view stdin preserves the same backing sink, byte/error behavior and selected status flags. The selected genuine devnull producer has no stdin-OFD identity consumer or shared-position observation; an arbitrary stdin pipe/file/OFD is outside this fixed launch profile. No unknown close is called complete. Prior executable mappings disappear at final exec. Existing aliases of artifact/usage elsewhere in the copied tree are read-only; a hard link cannot acquire writable cross-mount authority, and usage starts with one link. Source image and scientific source single-link/currentness checks remain original checks. + +Proc is genuine and stays in the original PID namespace. A proc root/cwd/exe/FD link to an ancestor-user-namespace task requires the ptrace check. The child user namespace's matching kernel UID does not satisfy commoncap's same-user-namespace cap-subset case, and it has no capability in an ancestor user namespace. Landlock additionally denies ptrace access to tasks outside its inherited domain. Initial namespace map_files access requires initial-user-namespace capability. There is no prior descendant in the new user namespace; all same-new-namespace descendants are born after the complete restrictions and inherit them. Final seccomp prevents setns, unshare, mount APIs and capability/credential recovery. Thus no accessible proc magic link reintroduces a parent's writable root/cwd/FD/executable authority under the selected kernel source premises. The genuine original outer owner can still perform its own required observations from outside. + +The filter kills alternate architectures and x32, returns ENOSYS for clone3, and admits only normalized low32 legacy tuples003d0f00 (thread),00004111 (ordinary spawn) and01200011 (glibc fork). It compares complete tuples, not an allowed-bit union. Linux-v6.12 legacy clone uses lower32 bits. Ordinary fork/vfork have no invented unused-register tests. The selected loader/memory/rseq/robust-list/futex/signal/pipe/wait/exec/thread-teardown vocabulary is explicit in the C array; compatibility of all reached source operations remains image-specific Q, not a guessed availability claim. + +Unlisted syscalls return EPERM. In particular postsetup namespace/mount/fsopen/move_mount/mount_setattr/open_tree, cgroup migration through filesystem writes, socket/socketpair and sendmsg/recvmsg/SCM_RIGHTS, ptrace/process_vm_*, pidfd_getfd, perf/BPF, key/request-key helpers, SystemV/POSIX-message IPC, AIO/io_uring/userfaultfd, handle-based opens and credential/capability changes are unavailable. pidfd_open/send_signal and ordinary signal calls are subject to the inherited Landlock signal scope; prlimit can target only pid0. Fcntl excludes ownership/notification/leases; ioctl permits only the six documented FD-local/observational request values in source. Session/process-group setup remains allowed because it changes neither cgroup membership nor namespace/policy and the original subprocess path requires it. No compiler is exempt from this policy. + +## Failed-resource and terminal map + +Each descriptor acquisition reserves a fixed registry slot before the native syscall. A negative acquisition records FAILED plus actual errno. A successful acquisition records its actual returned integer immediately. Before close, ownership transitions OPEN->RETIRED; there is exactly one close attempt. Success records CLOSED. Any close error records UNCERTAIN and forbids science; numeric FD reuse does not cause a retry. Fixed capacities are96 FD births,48 ordered error objects,4 bounded getdents reads per census,8192 bytes per census buffer and16KiB failure projection. Capacity exhaustion refuses rather than dropping a completion obligation. + +| Resource/effect | Actual owner and failure treatment | Completion evidence | +|---|---|---| +| stdin and two pipe writer endpoints | Runner creates/launches; entry reestablishes the same genuine devnull backing sink through the final view with tracked old0 close/new0 birth; two inherited pipe writers remain in G's domain | Real runner wait, relay EOF and guardian retirement; entry exit alone is insufficient | +| Entry/time image and proc/census descriptors | Entry pending->acquired->once-close; raw syscall errors ordered; no external library finalizer | Source-defined close states plus actual process exit; failure projection is non-success | +| Active LSM and two mount censuses | Fixed buffers, native attempt reserved before each call, raw errno retained immediately, strict completeness and field validation | Checked flags only after actual complete success; neither data nor a flag authenticates the installed kernel | +| Held association anchors and statx joins | Five added registered O_PATH descriptors, actual unique mount IDs and exact class/object checks | Once-close before final cwd/stdin setup; source-local immutable topology relation, not a blanket compiler proof | +| User/mount namespace and mapping writes | Entry creates no descendant; records each completed irreversible stage and every failed syscall | Kernel releases remaining namespace references on actual waited process exit; no self-issued release receipt | +| Detached clones | Entry owns actual open_tree FDs; partial attach remains recorded; all known FD closes attempted once | Actual process exit releases the private mount namespace; no unmount/rollback retry | +| Artifact and usage backing objects | Original runner/registry owns retained paths; entry exposes only exact pinned objects | Original retained-tree registry/oracle/archive custody; entry never unlinks or repairs them | +| Landlock ruleset/path FDs | Entry source-owned; mandatory restriction failure prevents exec; close error is uncertain | Once-close states and external exit; restrictions inherited only after successful restrict_self | +| Final filter/exec | Entry installs mandatory filter and execs exact original observer prefix | Actual outer child launch/wait/streams and complete receiver, never a pre-exit native success marker | +| Loader/setup/close/report/exit tails | Charged to enclosing actual attempt from entry launch; no cost is declared zero | Original enclosing interval/cost ledger; physical fit and final exit tails stay OPEN_NOT_ZERO until guarded evidence | + +On setup or exec failure, the entry writes only a bounded JSON failure object to the relay stderr pipe with schema `h25-native-view-setup-failure-v1`, actual first/ordered secondary errno sites, resource states and completed namespace/mount/restriction flags, then exits78. State numbers are UNUSED0,PENDING1,OPEN2,RETIRED3,CLOSED4,FAILED5,UNCERTAIN6. There is no success message or receipt before final exec. Interrupted native setup, failed stderr projection, lost writer/exit observations or an incomplete JSON projection cannot qualify success. The parent must preserve the raw retained bytes and actual wait disposition, register all pending/native/mount/usage/relay obligations in its existing attempt union and refuse sealing on uncertainty. This file does not create a replacement tracking framework. + +## Outside trust premises and unresolved finite association + +The following are outside this source's self-authentication and must be genuine original parent/profile facts: (a) the fresh trusted runner and this actual loaded native image/loader with a clean initial environment and no prior descendant; (b) the precise selected Linux v6.12 source/configuration/image, including `CONFIG_BINFMT_MISC=n`, `CONFIG_COREDUMP=n`, `CONFIG_MODULES=n`, and actual namespace/mount/Landlock/seccomp support; (c) a bounded stable mount topology with the concrete filesystem/delegation effect relation derived by the complete theorem; (d) the original applicable ownership/exclusion and native trust interval, without silently extending research EX to unrelated host actors; (e) original full native/interpreter/compiler/library/source association with each distinct compiler resolution/evidence contract; (f) actual G domain placement before birth, owner survival and retirement; (g) the complete proof's self-resource and original fault-consumer consequences under the same selected kernel on both routes; (h) enclosing budget/cost coverage for every reached setup, failure and terminal tail. An argv pin, JSON hash or native failure flag establishes none of these facts on its own. + +The closed predecessor implemented a private empty binfmt_misc instance for a kernel with that feature enabled. This successor proposal instead selects the same **misc-disabled kernel on both sides**. No ancestor misc handler or F/preopened interpreter exists in this selected implementation. The original and transformed paths must still preserve their real ordinary ELF/script/helper resolution, security, error and evidence semantics; removing an original required misc dependency on a different kernel is not claimed equivalent. The old private-dispatch source and its eight mocked groups remain exact closed predecessor evidence, not successor controls or whole-caller acceptance. + +The selected native interface profile requires the actual original native qualifier to associate the compiled kernel configuration and image. Neither profile DATA nor a supplied available/compatible flag creates that association. This is not a claim about the current workstation or authority to rebuild/replace its kernel. Module loading is compiled out on the selected original and transformed routes, so the exact source's disabled module-request behavior supplies that effect relation; no setup request_module route is introduced. `` still explicitly declares GNU `unshare`; obsolete fsopen/fsconfig build requirements and setup constants are absent. + +No successor dispatch-publication status fields or CORE-installation outcome are emitted because those operations are not executed. The failure schema retains actual ordered errno objects, FD states, namespace/view/restriction success flags and uncertainty. In particular `landlocked=true` is set only after the real restrict-self syscall succeeds, and final exec remains dominated by that success and all close/error barriers. All remaining setup failures stay paid setup failures before science and cannot count as the original optimized refusal. Actual current association, numerical fit and execution admission remain later, while the complete finite proof must be constructed and independently checked before this proposal is adopted. + +The exact successful-path FD bound is 31 lifetime registry slots, including initial FD0 adoption: the prior simplification's 26 plus five association anchors. Cap 96 is unchanged, leaving 65 slots. The groups are startup census/stdin/task/children 4; entry/self/time 3; ID-map writes 3; artifact/usage/cwd 3; detached clones 2; copied root/final cwd 2; final devnull/dup0 2; Landlock ruleset/root/artifact/usage/devnull 5; final census 1; final time image 1; association proc/devnull/entry/time/Python 5. Closing the five anchors before final cwd/stdin and Landlock keeps the peak at 13 tracked live FDs, or 15 actual including stdout/stderr. On failure no later acquisition is attempted. At most 12 cleanup closes plus one primary error remain covered by the 48-error cap. Known-once close, uncertainty refusal, FD0/pipe release and all namespace/kernel-retirement tails remain in the original enclosing attempt and are not declared free. + +The new non-FD acquisition registry has 288 attempt positions. Each position is reserved before its LSM/listmount/statmount/statx call; completion advances only after a nonnegative actual return, while semantic checks may still fail. A successful maximum-size path uses at most 268 positions: one LSM call, two list calls, at most 126 plus 128 per-mount stat calls, nine initial joins and two clone joins. Malformed earlier or oversized census branches stop earlier. This count covers the new acquisitions, not all native syscalls or physical work. Both 128-row censuses and their fixed type strings have static storage; each list has 129 slots and each statmount has a 576-byte bounded buffer. Query/FD/error capacity exhaustion is a paid setup refusal. Failure JSON retains checked LSM/topology flags, actual census counts and attempted/completed acquisition counts; it never emits a new success receipt. Physical costs remain OPEN_NOT_ZERO. + +The joined Q_sigma proof must separately map copied source attributes, default ACL/creation ancestors, executable/library attributes, original negative fixtures and within-invocation custody metadata to actual consumers for every required case. It must preserve the original outer C2 retention listxattr refusal on every retained root/file/directory. Same backing inode or source bytes do not prove that an ACL copied by CPython in the one-ID namespace is unchanged; an omitted consequential ACL can erase an original retention refusal. Nonempty attributes require consequence analysis. Entry contains no synthetic refusal or absence-of-xattrs assertion. Current attributes, current kernel/native images, original negative-case preservation, complete source acceptance and execution GO remain unissued by this native component. + +## Exact inspected predecessor choices and source basis + +Parent coverage freshly pins main7c49fe32c55de02c2c873655c804b16e4c3fef0a; accepted retention PR6736 at0f2a86fa9ef0daf760b77c662a5b762e17848598 is adapted for the bounded once-close/error/SHA mechanics and retained for the genuine outer owner/registry/archive route. PR6744 at1ac58a84b725bd6f17eec66727edc877c49c7e66 supplies unchanged original full bodies/criteria; PR6715 atdc34598c22e2ef43ae7e11fc1d8c14de3915cf89 supplies accepted image adoption. PR6780 ata7903f7ee16c85015f3f9a87fd6f3ae5c9053349 is review-only for the Landlock metadata failure. Parent's bounded overlap coverage reports no direct native copied-view repair; that is not a global novelty claim. The existing `native/retention_guardian.c` is reference and is unchanged by this author. + +Primary source references are source semantics, not current-host observations: + +- [Linux v6.12 mount UAPI](https://github.com/torvalds/linux/blob/v6.12/include/uapi/linux/mount.h) and [namespace implementation](https://github.com/torvalds/linux/blob/v6.12/fs/namespace.c): copy_mnt_ns, open_tree, move_mount and mount_setattr. +- [Linux v6.12 commoncap](https://github.com/torvalds/linux/blob/v6.12/security/commoncap.c): cap_capable and cap_ptrace_access_check; [proc base](https://github.com/torvalds/linux/blob/v6.12/fs/proc/base.c): proc_fd_access_allowed, proc_pid_get_link and map_files access. +- [Linux v6.12 Landlock UAPI](https://github.com/torvalds/linux/blob/v6.12/include/uapi/linux/landlock.h), [syscalls](https://github.com/torvalds/linux/blob/v6.12/security/landlock/syscalls.c) and [task scoping](https://github.com/torvalds/linux/blob/v6.12/security/landlock/task.c). +- [Linux v6.12 clone implementation](https://github.com/torvalds/linux/blob/v6.12/kernel/fork.c): SYSCALL_DEFINE0 fork/vfork and lower_32_bits in legacy clone. +- [Linux v6.12 coredump interface](https://github.com/torvalds/linux/blob/v6.12/include/linux/coredump.h), [signal exit](https://github.com/torvalds/linux/blob/v6.12/kernel/signal.c), [binary-format build selection](https://github.com/torvalds/linux/blob/v6.12/fs/Makefile), and [module-request interface](https://github.com/torvalds/linux/blob/v6.12/include/linux/kmod.h) supply the prospective compiled-out subject; the exact native configuration/image association and finite original fault/dispatch proof remain mandatory. +- [Linux v6.12 open metadata](https://github.com/torvalds/linux/blob/v6.12/fs/open.c), [utimes](https://github.com/torvalds/linux/blob/v6.12/fs/utimes.c), [xattr](https://github.com/torvalds/linux/blob/v6.12/fs/xattr.c) and [POSIX ACL](https://github.com/torvalds/linux/blob/v6.12/fs/posix_acl.c): mount-write and namespace representation dependencies. diff --git a/research/h25-native-view-facts/source/native-profile.json b/research/h25-native-view-facts/source/native-profile.json new file mode 100644 index 0000000000..61a7c07956 --- /dev/null +++ b/research/h25-native-view-facts/source/native-profile.json @@ -0,0 +1,31 @@ +{ + "binding": "Detached source manifest pins this exact profile and all exact source leaves; no reverse/future/self hash", + "execution_permission": false, + "required": [ + "Linux cgroup2 preexisting owned suitable delegated subtree; no privilege or host configuration change", + "clone3 CLONE_INTO_CGROUP and CLONE_PIDFD creates M insideD before birth; source-owned waitid P_PIDFD", + "SCM_CREDENTIALS + actual selfpidfd M/K/P/C2; distinct per-role SOCK_SEQPACKET peer and monotone sequence", + "Root/B/Fee no FD198 and no controlwrite; actual parent reports child nativepidfd and own waited/knownclosed state", + "G survives covered role deaths then wholeD retirement; killrequest/frozen/membership/populationempty/waits/FDclose are distinct conjunctions", + "G loss/unknown leaves persistent incomplete and no fresh selected operation/retention success", + "SourceSHA corroborates original external actualentry association; installed nativeimage/current runtime identity not proved by sourcehash", + "Science entry source, actual built image/source association, original time image, namespace/LL ABI6/seccomp semantics and finite observation Q require independently qualified current input; authoring grants no execution", + "Prospective semantic kernel subject on BOTH original and transformed routes: Linux v6.12 CONFIG_BINFMT_MISC=n, CONFIG_COREDUMP=n and CONFIG_MODULES=n; actual source/configuration/image association belongs to the genuine original native qualifier, not an available/compatible flag or a current-host assertion", + "Entry performs no binary-format filesystem context acquisition, registry publication or CORE alteration under this subject; ordinary selected ELF/script dispatch remains subject to the finite original executable/helper/security proof and actual native association", + "Inherited CORE values are preserved; self setrlimit and pid-zero prlimit64 queries/mutations retain all original resource and pointer arguments, including CORE; native kernel hard-limit enforcement remains and nonzero process targets are unavailable", + "Final inherited seccomp still denies filesystem-context/mount/namespace APIs and descriptor import; the copied tree and exact artifact/usage/devnull rules remain, with actual checked Landlock restrict-self success before final exec", + "GNU sched.h supplies unshare declaration; obsolete fsopen/fsconfig setup constants and build requirement are absent. Existing once-close/error/capability/NNP/relay/guardian custody remains; physical resource costs and full original consequence/fit proof remain separate", + "Actual native lsm_list_modules 461 must return exactly the two distinct IDs 100 and 110 with count 2 and returned bytes 16; the complete active stack is acquired rather than supplied in JSON", + "Original T1 selects a null initial Landlock domain. Active LSM IDs do not expose that per-task state; successful mount setup proves no applicable filesystem-handling domain but does not erase a possible REFER-only inherited layer", + "Original genuine T1 also selects initial seccomp mode 0 and no effective cgroup BPF attachment on the actual science ancestry. These are currently unissued native state premises, not conclusions of LSM enumeration or setup success, and no supplied flag is accepted as evidence. This proposal does not claim an actual host observation or an ancestor-policy query", + "Actual before/after mount census uses listmount 458 with 129 slots for a 128 bound and statmount 457 mask 0x63 with checked 512-byte header and bounded strings; pre-census reserves two clone slots, graph and unique namespace are checked, and unknown or idmapped classes refuse setup", + "Finite mount catalogue is ext4/tmpfs ordinary local, proc, devtmpfs/devpts device, and sysfs/cgroup2 auxiliary. Nine held actual object statx unique-mount-ID joins qualify root/cwd/artifact/usage/proc/devnull/entry/time/Python roles. This finite selection is not arbitrary-operation or complete compiler-helper harmlessness", + "Exact topology relation preserves all original rows and adds only the two owned clones, with base RDONLY|NOSUID and clone NOSUID additions. The single-task private interval and original no-interposition premise precede capability drop and descendants; final seccomp prevents later mount/namespace APIs", + "Registry bounds are 31 lifetime FD births in cap 96, peak 13 tracked and 15 actual including relay writers, 48 ordered errors and 288 new acquisition attempts. At most 268 new LSM/listmount/statmount/statx calls occur on a maximum successful path; all actual costs and teardown remain OPEN_NOT_ZERO" + ], + "runtime_admission": "UNISSUED", + "schema": "s03-source-operating-profile-v1", + "selected_design_sha256": "71acd51240bb6c7404bb8e1716de566159a3587d1d342c55f483c749df296407", + "source_only": true, + "subject": "G native lifetime/role/channel source profile" +} diff --git a/research/h25-native-view-facts/source/science_view_entry.c.txt b/research/h25-native-view-facts/source/science_view_entry.c.txt new file mode 100644 index 0000000000..5af0bc368c --- /dev/null +++ b/research/h25-native-view-facts/source/science_view_entry.c.txt @@ -0,0 +1,842 @@ +/* Joined complete-caller science entry. SOURCE ONLY; no execution admission. + * + * The authenticated runner execs this image, before GNU time, with precisely + * stdin=/dev/null and two relay pipe writers. This program creates no task. + * It keeps the caller's PID namespace, session, process group and wait owner. + * See VIEW-ENTRY-CONTRACT-v1.md for the fixed argv, external trust premises, + * Linux-v6.12 source basis and the still-unassociated Q_sigma environment. + * No metadata broker, supplied descriptor, compatible flag or ACL stripping. + * Both routes select CONFIG_BINFMT_MISC=n, CONFIG_COREDUMP=n and + * CONFIG_MODULES=n. Genuine native qualification must associate that exact + * semantic kernel subject; neither this entry nor JSON data detects it. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(__x86_64__) || defined(__ILP32__) +#error The entry is the reviewed native LP64 x86-64 ABI only +#endif +_Static_assert(sizeof(void *) == 8 && sizeof(long) == 8, "LP64 required"); + +/* Selected v6.12 UAPI shapes, intentionally independent of libc header age. */ +struct sv_mount_attr { uint64_t attr_set, attr_clr, propagation, userns_fd; }; +struct sv_ll_attr { uint64_t fs, net, scope; }; +struct sv_ll_path { uint64_t access; int32_t fd; } __attribute__((packed)); +#define SV_EMPTY_PATH 0x1000U +#define SV_RECURSIVE 0x8000U +#define SV_OPEN_TREE_CLONE 1U +#define SV_MOVE_FROM_EMPTY 4U +#define SV_MOVE_TO_EMPTY 0x40U +#define SV_MOUNT_RDONLY UINT64_C(1) +#define SV_MOUNT_NOSUID UINT64_C(2) +#define SV_FS_EXEC (UINT64_C(1)<<0) +#define SV_FS_WRITE (UINT64_C(1)<<1) +#define SV_FS_READ (UINT64_C(1)<<2) +#define SV_FS_READDIR (UINT64_C(1)<<3) +#define SV_FS_RMDIR (UINT64_C(1)<<4) +#define SV_FS_UNLINK (UINT64_C(1)<<5) +#define SV_FS_MKDIR (UINT64_C(1)<<7) +#define SV_FS_MKREG (UINT64_C(1)<<8) +#define SV_FS_MKFIFO (UINT64_C(1)<<10) +#define SV_FS_MKSYM (UINT64_C(1)<<12) +#define SV_FS_REFER (UINT64_C(1)<<13) +#define SV_FS_TRUNC (UINT64_C(1)<<14) +#define SV_FS_IOCTL (UINT64_C(1)<<15) +#define SV_FS_ALL UINT64_C(65535) +#define SV_READ (SV_FS_EXEC|SV_FS_READ|SV_FS_READDIR) +#define SV_ARTIFACT (SV_READ|SV_FS_WRITE|SV_FS_RMDIR|SV_FS_UNLINK|SV_FS_MKDIR|SV_FS_MKREG|SV_FS_MKFIFO|SV_FS_MKSYM|SV_FS_REFER|SV_FS_TRUNC) +#define SV_MAX_FDS 96 +#define SV_MAX_ERRORS 48 +#define SV_MAX_IMAGE UINT64_C(16777216) +#define SV_PROC_MAGIC 0x9fa0 +#define SV_REPORT_CAP 16384 +/* Native x86-64 Linux-v6.12 syscall table. This metadata operation is safe + * under the same final mount-write checks as chmod/fchmod/fchmodat. */ +#define SV_NR_FCHMODAT2 452 +#define SV_NR_STATMOUNT 457 +#define SV_NR_LISTMOUNT 458 +#define SV_NR_LSM_LIST_MODULES 461 +#define SV_MAX_MOUNTS 128U +#define SV_MAX_QUERIES 288U +#define SV_MOUNT_IDMAP UINT64_C(0x00100000) +#define SV_STATMOUNT_MASK UINT64_C(0x63) +#define SV_STATX_MASK 0x4103U +struct sv_mnt_request { uint32_t size, spare; uint64_t id, param, ns; }; +struct sv_statmount_head { + uint32_t size, opts; uint64_t mask; + uint32_t dev_major, dev_minor; uint64_t magic; + uint32_t sb_flags, fs_type; uint64_t id, parent; + uint32_t old_id, old_parent; uint64_t attr, propagation, peer, master, from; + uint32_t root, point; uint64_t ns, spare[49]; +}; +struct sv_statmount_buffer { struct sv_statmount_head h; char str[64]; }; +struct sv_statx_time { int64_t sec; uint32_t nsec; int32_t reserved; }; +struct sv_statx { + uint32_t mask, blocksize; uint64_t attr; + uint32_t links, uid, gid; uint16_t mode, spare; + uint64_t ino, size, blocks, attr_mask; struct sv_statx_time times[4]; + uint32_t rdev_major, rdev_minor, dev_major, dev_minor; + uint64_t mount_id, tail[13]; +}; +_Static_assert(sizeof(struct sv_mnt_request)==32,"v6.12 request ABI"); +_Static_assert(sizeof(struct sv_statmount_head)==512,"v6.12 statmount head"); +_Static_assert(offsetof(struct sv_statmount_buffer,str)==512,"statmount string base"); +_Static_assert(sizeof(struct sv_statx)==256&&offsetof(struct sv_statx,mount_id)==144,"v6.12 statx ABI"); +enum sv_fs_class { SV_FS_UNKNOWN, SV_FS_LOCAL, SV_FS_PROC, SV_FS_DEVICE, SV_FS_AUX }; +struct sv_mount_row { struct sv_statmount_head h; char type[16]; enum sv_fs_class class; }; +struct sv_census { size_t count; struct sv_mount_row row[SV_MAX_MOUNTS]; }; +static struct sv_census mounts_before, mounts_after; +static unsigned native_queries_started, native_queries_completed; +static bool lsm_checked, topology_checked; + +extern char **environ; +enum sv_fd_state { SV_UNUSED, SV_PENDING, SV_OPEN, SV_RETIRED, SV_CLOSED, SV_FAILED, SV_UNCERTAIN }; +struct sv_fd { int fd; enum sv_fd_state state; const char *site; }; +struct sv_error { const char *site; int number; }; +static struct sv_fd fds[SV_MAX_FDS]; +static struct sv_error errors[SV_MAX_ERRORS]; +static size_t fd_count, error_count; +static bool uncertain, error_overflow, user_entered, mount_entered; +static bool root_private, root_readonly, artifact_attached, usage_attached; +static bool landlocked, filtered; +static uid_t uid; +static gid_t gid; +static int stdin_status_flags; +static const char *artifact_path, *usage_path, *cwd_path; +static struct stat artifact_before, usage_before, cwd_before, root_before, stdin_before; + +static bool failed(const char *site) { + int saved = errno ? errno : EPROTO; + if (error_count < SV_MAX_ERRORS) errors[error_count++] = (struct sv_error){site,saved}; + else { error_overflow = true; uncertain = true; } + errno = saved; + return false; +} +static bool require(bool condition, const char *site) { + if (condition) return true; + errno = EPROTO; + return failed(site); +} +/* Non-FD acquisitions have a separate fixed attempt budget. Reserve before + * the syscall; a failed syscall's errno is recorded before cleanup. */ +static bool begin_query(void) { + if(native_queries_started==SV_MAX_QUERIES){errno=E2BIG;return failed("native-query-capacity");} + native_queries_started++;return true; +} +static bool query_result(long result,const char *site) { + if(result<0)return failed(site);native_queries_completed++;return true; +} +static bool valid_lsm_result(long count,uint32_t bytes,const uint64_t ids[2]) { + return count==2&&bytes==16&&((ids[0]==100&&ids[1]==110)||(ids[0]==110&&ids[1]==100)); +} +static bool read_lsm_stack(void) { + uint64_t ids[2]={0,0};uint32_t bytes=sizeof ids; + if(!begin_query())return false; + long result=syscall(SV_NR_LSM_LIST_MODULES,ids,&bytes,0U); + if(!query_result(result,"actual-lsm-list-modules"))return false; + if(!require(valid_lsm_result(result,bytes,ids),"exact-capability-landlock-active-stack"))return false; + lsm_checked=true;return true; +} +static int reserve(const char *site) { + if (fd_count == SV_MAX_FDS) { errno=EMFILE; failed("fd-registry-capacity"); return -1; } + size_t slot=fd_count++; + fds[slot]=(struct sv_fd){-1,SV_PENDING,site}; + return (int)slot; +} +static int acquired(int slot, long result) { + if (slot < 0) return -1; + if (result < 0) { fds[slot].state=SV_FAILED; failed(fds[slot].site); return -1; } + fds[slot].fd=(int)result; fds[slot].state=SV_OPEN; + return (int)result; +} +static bool close_once(int fd) { + for (size_t n=0;n2) close_once(fds[n].fd); +} +static int opened(const char *path, int flags, const char *site) { + int slot=reserve(site); if(slot<0)return -1; + return acquired(slot,open(path,flags|O_CLOEXEC,0)); +} +/* All role paths must be absolute canonical paths, with no symlink component. + * The one intentional proc magic-link open is separate below. */ +static bool canonical(const char *path) { + if (!path || path[0]!='/' || !path[1] || strlen(path)>=PATH_MAX || path[strlen(path)-1]=='/') return false; + const char *p=path+1; + while (*p) { + const char *end=strchr(p,'/'); size_t n=end?(size_t)(end-p):strlen(p); + if (!n || (n==1 && p[0]=='.') || (n==2 && p[0]=='.' && p[1]=='.')) return false; + if (!end) break; + p=end+1; + } + return true; +} +static bool beneath(const char *path, const char *parent) { + size_t n=strlen(parent); return !strncmp(path,parent,n) && (path[n]==0 || path[n]=='/'); +} +static int role_open(const char *path,int flags,const char *site) { + if(!require(canonical(path),"canonical-role-path"))return -1; + struct open_how how={.flags=(uint64_t)(flags|O_CLOEXEC|O_NOFOLLOW), + .resolve=RESOLVE_NO_SYMLINKS|RESOLVE_NO_MAGICLINKS}; + int slot=reserve(site);if(slot<0)return -1; + return acquired(slot,syscall(SYS_openat2,AT_FDCWD,path,&how,sizeof how)); +} +static bool same_object(const struct stat *a,const struct stat *b) { + return a->st_dev==b->st_dev && a->st_ino==b->st_ino && a->st_mode==b->st_mode && + a->st_uid==b->st_uid && a->st_gid==b->st_gid && a->st_nlink==b->st_nlink && + a->st_size==b->st_size && a->st_mtim.tv_sec==b->st_mtim.tv_sec && + a->st_mtim.tv_nsec==b->st_mtim.tv_nsec && a->st_ctim.tv_sec==b->st_ctim.tv_sec && + a->st_ctim.tv_nsec==b->st_ctim.tv_nsec; +} +/* uid/gid fields are namespace representations, not kernel inode ownership. + * This comparison is used ONLY across the one-ID namespace transition. Both + * image hashes separately retain stable owner fields in their own context; + * dev/ino, all other inventory fields and the complete byte pin still agree. + * Neither unshare nor mount operations change backing inode ownership. Original + * owner/native qualification is retained by the authenticated outer parent. */ +static bool same_backing_across_userns(const struct stat *a,const struct stat *b) { + struct stat represented=*a; + represented.st_uid=b->st_uid;represented.st_gid=b->st_gid; + return same_object(&represented,b); +} +static bool stat_fd(int fd,struct stat *out,const char *site) { + if(fstat(fd,out)<0)return failed(site);return true; +} +static bool decimal(const char *s,uint64_t *value) { + uint64_t n=0; + if(!s||!*s||(s[0]=='0'&&s[1]))return false; + for(;*s;s++){ if(*s<'0'||*s>'9'||n>(UINT64_MAX-(unsigned)(*s-'0'))/10)return false; n=n*10+(unsigned)(*s-'0'); } + *value=n;return true; +} + +/* SHA256 mechanics reused, with predecessor credit, from the accepted + * retention_guardian.c (PR6736 0f2a86fa9ef0daf760b77c662a5b762e17848598). + * The independent native-image/loader association is still an outside premise. */ +struct sha { uint32_t h[8]; uint64_t n; size_t used; unsigned char b[64]; }; +static uint32_t rr(uint32_t x,unsigned n){return (x>>n)|(x<<(32-n));} +static const uint32_t sk[64]={ +0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, +0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, +0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, +0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, +0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, +0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, +0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, +0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2}; +static void sha_block(struct sha*s,const unsigned char*b){uint32_t w[64]; + for(int i=0;i<16;i++)w[i]=(uint32_t)b[i*4]<<24|(uint32_t)b[i*4+1]<<16|(uint32_t)b[i*4+2]<<8|b[i*4+3]; + for(int i=16;i<64;i++){uint32_t x=w[i-15],y=w[i-2];w[i]=(rr(x,7)^rr(x,18)^(x>>3))+w[i-16]+w[i-7]+(rr(y,17)^rr(y,19)^(y>>10));} + uint32_t a=s->h[0],b0=s->h[1],c=s->h[2],d=s->h[3],e=s->h[4],f=s->h[5],g=s->h[6],h=s->h[7]; + for(int i=0;i<64;i++){uint32_t t=h+(rr(e,6)^rr(e,11)^rr(e,25))+((e&f)^(~e&g))+sk[i]+w[i]; + uint32_t t2=(rr(a,2)^rr(a,13)^rr(a,22))+((a&b0)^(a&c)^(b0&c));h=g;g=f;f=e;e=d+t;d=c;c=b0;b0=a;a=t+t2;} + s->h[0]+=a;s->h[1]+=b0;s->h[2]+=c;s->h[3]+=d;s->h[4]+=e;s->h[5]+=f;s->h[6]+=g;s->h[7]+=h; +} +static void sha_init(struct sha*s){*s=(struct sha){{0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19},0,0,{0}};} +static void sha_add(struct sha*s,const void*ptr,size_t n){const unsigned char*p=ptr;s->n+=n; + while(n){size_t a=64-s->used;if(a>n)a=n;memcpy(s->b+s->used,p,a);s->used+=a;p+=a;n-=a;if(s->used==64){sha_block(s,s->b);s->used=0;}}} +static void sha_done(struct sha*s,char out[65]){uint64_t bits=s->n*8;s->b[s->used++]=128; + if(s->used>56){memset(s->b+s->used,0,64-s->used);sha_block(s,s->b);s->used=0;} + memset(s->b+s->used,0,56-s->used);for(int i=0;i<8;i++)s->b[63-i]=(unsigned char)(bits>>(8*i));sha_block(s,s->b); + static const char x[]="0123456789abcdef";for(int i=0;i<32;i++){unsigned v=(s->h[i/4]>>(24-8*(i%4)))&255;out[i*2]=x[v>>4];out[i*2+1]=x[v&15];}out[64]=0;} +static bool hex64(const char*s){if(strlen(s)!=64)return false;for(int i=0;i<64;i++)if(!strchr("0123456789abcdef",s[i]))return false;return true;} + +static bool hash_image(int fd,const char *expected,uint64_t bytes,struct stat *stable) { + if(!require(hex64(expected)&&bytes>0&&bytes<=SV_MAX_IMAGE,"bounded-image-pin"))return false; + struct stat before,after; + if(!stat_fd(fd,&before,"image-before-fstat"))return false; + if(!require(S_ISREG(before.st_mode)&&before.st_size==(off_t)bytes&& + !(before.st_mode&(S_IWGRP|S_IWOTH|S_ISUID|S_ISGID))&&(before.st_mode&0111),"image-object-profile"))return false; + if(lseek(fd,0,SEEK_SET)<0)return failed("image-seek"); + struct sha h;sha_init(&h);unsigned char block[65536];uint64_t count=0; + while(countsizeof block?sizeof block:(size_t)(bytes-count); + ssize_t got=read(fd,block,ask); + if(got<0){if(errno==EINTR)continue;return failed("image-read");} + if(!require(got>0,"image-short-read"))return false; + sha_add(&h,block,(size_t)got);count+=(uint64_t)got; + } + ssize_t end; + do{end=read(fd,block,1);}while(end<0&&errno==EINTR); + if(end<0)return failed("image-end-read"); + if(!stat_fd(fd,&after,"image-after-fstat"))return false; + char actual[65];sha_done(&h,actual); + if(!require(end==0&&same_object(&before,&after)&&!strcmp(actual,expected),"image-stable-bytes-pin"))return false; + *stable=after;return true; +} + +struct sv_dirent { uint64_t ino; int64_t off; unsigned short reclen; unsigned char type; char name[]; }; +/* Bounded source-owned census. No opendir callback or hidden finalizer. */ +static bool enumerate(int fd,int census_kind) { + unsigned char block[8192] __attribute__((aligned(8))); + unsigned count=0;bool seen[3]={false,false,false},done=false; + pid_t self=getpid(); + for(unsigned reads=0;reads<4;reads++) { + long got=syscall(SYS_getdents64,fd,block,sizeof block); + if(got<0)return failed("census-getdents64"); + if(!got){done=true;break;} + size_t at=0; + while(at<(size_t)got) { + if(!require((size_t)got-at>=20,"census-record-header-bound"))return false; + struct sv_dirent *d=(struct sv_dirent *)(void *)(block+at); + if(!require(d->reclen>=20&&at+d->reclen<=(size_t)got&& + memchr(d->name,0,d->reclen-19),"census-record-shape"))return false; + if(strcmp(d->name,".")&&strcmp(d->name,"..")) { + uint64_t n; + if(!require(++count<=SV_MAX_FDS,"census-entry-bound"))return false; + if(census_kind==2) return require(false,"artifact-parent-must-be-empty"); + if(!require(decimal(d->name,&n)&&n<=INT_MAX,"census-native-numeric-name"))return false; + if(census_kind==1) {if(!require(n==(uint64_t)self,"entry-exactly-one-task"))return false;} + else { + bool owned=n<=2||n==(uint64_t)fd; + for(size_t i=0;ireclen; + } + } + if(!require(done,"complete-bounded-census"))return false; + if(census_kind==1)return require(count==1,"one-native-task"); + if(census_kind==2)return require(count==0,"empty-native-artifact-parent"); + return require(seen[0]&&seen[1]&&seen[2],"admitted-stdio-present"); +} +static bool fd_census(void) { + int fd=opened("/proc/self/fd",O_RDONLY|O_DIRECTORY|O_NOFOLLOW,"fd-census"); + if(fd<0)return false; + bool okay=enumerate(fd,0);bool closed=close_once(fd);return okay&&closed; +} +static bool native_start(void) { + uid=geteuid();gid=getegid();uid_t r,e,s;gid_t gr,ge,gs; + if(getresuid(&r,&e,&s)<0||getresgid(&gr,&ge,&gs)<0)return failed("entry-credentials"); + if(!require(uid!=0&&r==uid&&e==uid&&s==uid&&gr==gid&&ge==gid&&gs==gid,"same-unprivileged-real-effective-saved-IDs"))return false; + struct __user_cap_header_struct ch={.version=_LINUX_CAPABILITY_VERSION_3,.pid=0}; + struct __user_cap_data_struct cap[2]={{0},{0}}; + if(syscall(SYS_capget,&ch,cap)<0)return failed("initial-capget"); + if(!require(!(cap[0].effective|cap[0].permitted|cap[0].inheritable|cap[1].effective|cap[1].permitted|cap[1].inheritable),"no-initial-capabilities"))return false; + if(!fd_census())return false; + struct stat input,a,b;struct statfs procfs; + if(fstat(0,&input)<0||fstat(1,&a)<0||fstat(2,&b)<0||statfs("/proc",&procfs)<0)return failed("initial-native-stdio-proc"); + int fl1=fcntl(1,F_GETFL),fl2=fcntl(2,F_GETFL),fl0=fcntl(0,F_GETFL); + if(fl1<0||fl2<0||fl0<0)return failed("initial-stdio-flags"); + if(!require(S_ISCHR(input.st_mode)&&major(input.st_rdev)==1&&minor(input.st_rdev)==3&& + (fl0&O_ACCMODE)==O_RDONLY&&S_ISFIFO(a.st_mode)&&S_ISFIFO(b.st_mode)&& + (a.st_dev!=b.st_dev||a.st_ino!=b.st_ino)&&(fl1&O_ACCMODE)==O_WRONLY&& + (fl2&O_ACCMODE)==O_WRONLY&&!(fl1&O_NONBLOCK)&&!(fl2&O_NONBLOCK)&& + procfs.f_type==SV_PROC_MAGIC,"exact-devnull-and-distinct-blocking-pipe-writers"))return false; + stdin_before=input;stdin_status_flags=fl0; + int stdin_slot=reserve("inherited-devnull-stdin");if(stdin_slot<0)return false; + if(acquired(stdin_slot,0)!=0)return false; + for(int n=0;n<=2;n++) { + int flags=fcntl(n,F_GETFD);if(flags<0)return failed("stdio-fdflags"); + if(!require(!(flags&FD_CLOEXEC),"stdio-survives-final-exec"))return false; + } + int task=opened("/proc/self/task",O_RDONLY|O_DIRECTORY|O_NOFOLLOW,"task-census"); + if(task<0)return false; + bool okay=enumerate(task,1);bool closed=close_once(task); + if(!okay||!closed)return false; + char children[128];int n=snprintf(children,sizeof children,"/proc/self/task/%ld/children",(long)getpid()); + if(!require(n>0&&(size_t)n0&&(size_t)n0&&(size_t)ncount;i++)if(c->row[i].h.id==id)return &c->row[i];return NULL; +} +static bool decode_mount(const struct sv_statmount_buffer *b,uint64_t id,struct sv_mount_row *out) { + if(!require(b->h.size>512&&b->h.size<=sizeof *b&& + (b->h.mask&SV_STATMOUNT_MASK)==SV_STATMOUNT_MASK&&b->h.id==id&&id&&b->h.ns, + "statmount-complete-basic-type-namespace"))return false; + size_t strings=b->h.size-512; + if(!require(b->h.fs_typestr+b->h.fs_type; + const char *end=memchr(name,0,strings-b->h.fs_type); + if(!require(end&&end!=name&&(size_t)(end-name)type,"statmount-bounded-type"))return false; + memset(out,0,sizeof *out);out->h=b->h;memcpy(out->type,name,(size_t)(end-name));out->class=fs_class(out->type); + return require(out->class!=SV_FS_UNKNOWN&&!(out->h.attr&SV_MOUNT_IDMAP)&& + out->h.propagation==MS_PRIVATE&&!out->h.peer&&!out->h.master, + "selected-nonidmapped-private-mount-class"); +} +static bool census(struct sv_census *out) { + uint64_t ids[SV_MAX_MOUNTS+1]={0}; + struct sv_mnt_request req={.size=sizeof req,.id=UINT64_MAX}; + if(!begin_query())return false; + long n=syscall(SV_NR_LISTMOUNT,&req,ids,(size_t)SV_MAX_MOUNTS+1,0U); + if(!query_result(n,"complete-listmount"))return false; + if(!require(n>0&&(unsigned long)n<=SV_MAX_MOUNTS,"listmount-unsaturated-bound"))return false; + out->count=(size_t)n; + for(size_t i=0;icount;i++) { + if(!require(ids[i]&&(i==0||ids[i]>ids[i-1]),"listmount-distinct-ascending-ids"))return false; + req=(struct sv_mnt_request){.size=sizeof req,.id=ids[i],.param=SV_STATMOUNT_MASK}; + struct sv_statmount_buffer b={0}; + if(!begin_query())return false; + long result=syscall(SV_NR_STATMOUNT,&req,&b,sizeof b,0U); + if(!query_result(result,"actual-statmount-basic-type-namespace")|| + !require(result==0,"statmount-zero-success")||!decode_mount(&b,ids[i],&out->row[i]))return false; + if(i&&!require(out->row[i].h.ns==out->row[0].h.ns,"one-actual-private-mount-namespace"))return false; + } + return true; +} +static bool graph_rooted(const struct sv_census *c,uint64_t root) { + if(!require(mount_row(c,root)!=NULL,"actual-root-mount-in-census"))return false; + for(size_t i=0;icount;i++) { + uint64_t next=c->row[i].h.id;size_t steps=0; + while(next!=root&&stepscount) { + const struct sv_mount_row *r=mount_row(c,next); + if(!require(r&&r->h.parent!=next,"reachable-mount-parent"))return false; + next=r->h.parent;steps++; + } + if(!require(next==root,"mount-parent-chain-terminates-at-actual-root"))return false; + } + return true; +} +static bool join_object(int fd,const struct sv_census *c,enum sv_fs_class expected,uint64_t *id) { + /* statx invokes vfs_getattr: original T1 already qualifies these actual + * ordinary/proc/device objects. The safe census precedes this later join. */ + struct stat st;struct sv_statx sx={0}; + if(!stat_fd(fd,&st,"join-object-fstat")||!begin_query())return false; + long result=syscall(SYS_statx,fd,"",AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW,SV_STATX_MASK,&sx); + if(!query_result(result,"join-object-statx-unique-mount"))return false; + if(!require(result==0&&(sx.mask&SV_STATX_MASK)==SV_STATX_MASK&&sx.mount_id&& + sx.ino==(uint64_t)st.st_ino&&sx.mode==(uint16_t)st.st_mode&& + sx.dev_major==major(st.st_dev)&&sx.dev_minor==minor(st.st_dev),"statx-actual-object-and-unique-id"))return false; + const struct sv_mount_row *r=mount_row(c,sx.mount_id); + if(!require(r&&r->class==expected,"held-object-selected-mount-class"))return false; + if(expected==SV_FS_PROC&&!require(r->h.magic==SV_PROC_MAGIC,"joined-genuine-proc-superblock"))return false; + *id=sx.mount_id;return true; +} +static bool same_mount_backing(const struct sv_mount_row *a,const struct sv_mount_row *b) { + return a->h.dev_major==b->h.dev_major&&a->h.dev_minor==b->h.dev_minor&& + a->h.magic==b->h.magic&&a->h.sb_flags==b->h.sb_flags&&a->h.ns==b->h.ns&& + a->class==b->class&&!strcmp(a->type,b->type); +} +static bool exact_view_relation(uint64_t root,uint64_t art,uint64_t use,uint64_t ac,uint64_t uc) { + if(!require(mounts_before.count<=SV_MAX_MOUNTS-2&&mounts_after.count==mounts_before.count+2&& + ac!=uc&&!mount_row(&mounts_before,ac)&&!mount_row(&mounts_before,uc),"exactly-two-new-clone-ids"))return false; + for(size_t i=0;ih.id); + if(!require(b&&same_mount_backing(a,b)&&a->h.parent==b->h.parent&& + b->h.attr==(a->h.attr|SV_MOUNT_RDONLY|SV_MOUNT_NOSUID),"base-mount-only-readonly-nosuid-change"))return false; + } + const struct sv_mount_row *a=mount_row(&mounts_before,art),*u=mount_row(&mounts_before,use); + const struct sv_mount_row *ca=mount_row(&mounts_after,ac),*cu=mount_row(&mounts_after,uc); + if(!require(a&&u&&ca&&cu&&same_mount_backing(a,ca)&&same_mount_backing(u,cu)&& + ca->h.parent==art&&cu->h.parent==use&&ca->h.attr==(a->h.attr|SV_MOUNT_NOSUID)&& + cu->h.attr==(u->h.attr|SV_MOUNT_NOSUID),"exact-owned-clone-backing-parent-and-flags"))return false; + return graph_rooted(&mounts_after,root); +} +static bool make_view(char **argv) { + /* Open all writable-clone sources only AFTER copy_mnt_ns has remapped root + * and cwd, so no retained path points into the parent's writable mounts. */ + int art=-1,use=-1,cwd=-1; + if(!validate_owned_paths(argv,&art,&use,&cwd))return false; + int root=opened("/",O_PATH|O_DIRECTORY|O_NOFOLLOW,"copied-root-handle");if(root<0)return false; + int anchors[5];const char *paths[5]={"/proc","/dev/null",argv[2],argv[6],argv[28]}; + const char *sites[5]={"association-proc-root","association-devnull","association-entry","association-time","association-python"}; + for(size_t i=0;i<5;i++){anchors[i]=role_open(paths[i],O_PATH,sites[i]);if(anchors[i]<0)return false;} + if(!census(&mounts_before)||!require(mounts_before.count<=SV_MAX_MOUNTS-2,"reserve-two-mount-slots"))return false; + int handles[9]={root,cwd,art,use,anchors[0],anchors[1],anchors[2],anchors[3],anchors[4]}; + enum sv_fs_class classes[9]={SV_FS_LOCAL,SV_FS_LOCAL,SV_FS_LOCAL,SV_FS_LOCAL,SV_FS_PROC,SV_FS_DEVICE,SV_FS_LOCAL,SV_FS_LOCAL,SV_FS_LOCAL}; + uint64_t ids[9]; + for(size_t i=0;i<9;i++)if(!join_object(handles[i],&mounts_before,classes[i],&ids[i]))return false; + if(!graph_rooted(&mounts_before,ids[0]))return false; + int artclone=clone_mount(art,"detached-artifact-mount");if(artclone<0)return false; + int useclone=clone_mount(use,"detached-usage-mount");if(useclone<0)return false; + if(!mount_attributes(artclone,SV_MOUNT_NOSUID,0,"artifact-clone-nosuid")|| + !mount_attributes(useclone,SV_MOUNT_NOSUID,0,"usage-clone-nosuid"))return false; + if(!mount_attributes(root,SV_MOUNT_RDONLY|SV_MOUNT_NOSUID,SV_RECURSIVE,"recursive-readonly-nosuid-copied-tree"))return false; + root_readonly=true; + if(!attach_mount(artclone,art,"attach-exact-writable-artifact"))return false; + artifact_attached=true; + if(!attach_mount(useclone,use,"attach-exact-writable-usage"))return false; + usage_attached=true; + uint64_t ac,uc; + if(!census(&mounts_after)||!join_object(artclone,&mounts_after,SV_FS_LOCAL,&ac)|| + !join_object(useclone,&mounts_after,SV_FS_LOCAL,&uc)||!exact_view_relation(ids[0],ids[2],ids[3],ac,uc))return false; + topology_checked=true; + for(size_t i=0;i<5;i++)if(!close_once(anchors[i]))return false; + /* Re-resolve through final paths. Do not fchdir a pre-attachment handle. */ + int final_cwd=role_open(cwd_path,O_PATH|O_DIRECTORY,"final-view-cwd");if(final_cwd<0)return false; + struct stat a,u,c,r; + if(fstatat(AT_FDCWD,artifact_path,&a,AT_SYMLINK_NOFOLLOW)<0|| + fstatat(AT_FDCWD,usage_path,&u,AT_SYMLINK_NOFOLLOW)<0|| + fstat(final_cwd,&c)<0||stat("/",&r)<0)return failed("final-view-object-readback"); + if(!require(same_object(&artifact_before,&a)&&same_object(&usage_before,&u)&&same_object(&cwd_before,&c)&& + root_before.st_dev==r.st_dev&&root_before.st_ino==r.st_ino,"same-backing-inodes-root-and-cwd"))return false; + if(fchdir(final_cwd)<0)return failed("reestablish-original-cwd-through-final-view"); + char actual[PATH_MAX];if(!getcwd(actual,sizeof actual))return failed("final-cwd-getcwd"); + return require(!strcmp(actual,cwd_path),"exact-final-cwd-path")&&reestablish_stdin(); +} + +static bool drop_privilege(void) { + if(prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_CLEAR_ALL,0,0,0)<0)return failed("clear-ambient-capabilities"); + /* v6.12 has capabilities 0..40. A later incompatible capability vocabulary + * must be separately associated; this loop also clears recognized <64. */ + for(unsigned n=0;n<64;n++) { + int present=prctl(PR_CAPBSET_READ,n,0,0,0); + if(present<0){if(errno==EINVAL)break;return failed("bounding-set-read");} + if(present&&prctl(PR_CAPBSET_DROP,n,0,0,0)<0)return failed("drop-capability-bounding-set"); + } + unsigned bits=SECBIT_NOROOT|SECBIT_NOROOT_LOCKED|SECBIT_NO_SETUID_FIXUP| + SECBIT_NO_SETUID_FIXUP_LOCKED|SECBIT_KEEP_CAPS_LOCKED; + if(prctl(PR_SET_SECUREBITS,bits,0,0,0)<0)return failed("lock-securebits"); + struct __user_cap_header_struct h={.version=_LINUX_CAPABILITY_VERSION_3,.pid=0}; + struct __user_cap_data_struct zero[2]={{0},{0}},actual[2]={{0},{0}}; + if(syscall(SYS_capset,&h,zero)<0)return failed("drop-all-capability-sets"); + if(syscall(SYS_capget,&h,actual)<0)return failed("final-capability-readback"); + if(!require(!(actual[0].effective|actual[0].permitted|actual[0].inheritable| + actual[1].effective|actual[1].permitted|actual[1].inheritable),"empty-effective-permitted-inheritable"))return false; + if(prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0)<0)return failed("install-no-new-privileges"); + return require(prctl(PR_GET_NO_NEW_PRIVS,0,0,0,0)==1,"no-new-privileges-readback"); +} +static bool ll_rule(int rules,int fd,uint64_t access,const char *site) { + struct sv_ll_path path={.access=access,.fd=fd}; + if(syscall(SYS_landlock_add_rule,rules,1,&path,0)<0)return failed(site);return true; +} +static bool install_landlock(void) { + long abi=syscall(SYS_landlock_create_ruleset,NULL,0,1); + if(abi<0)return failed("required-landlock-ABI-query"); + if(!require(abi>=6,"landlock-ABI-six-or-associated-successor"))return false; + struct sv_ll_attr policy={.fs=SV_FS_ALL,.net=3,.scope=3}; + int slot=reserve("landlock-ruleset");if(slot<0)return false; + int rules=acquired(slot,syscall(SYS_landlock_create_ruleset,&policy,sizeof policy,0));if(rules<0)return false; + int root=opened("/",O_PATH|O_DIRECTORY|O_NOFOLLOW,"landlock-read-root");if(root<0)return false; + int art=role_open(artifact_path,O_PATH|O_DIRECTORY,"landlock-artifact-root");if(art<0)return false; + int use=role_open(usage_path,O_PATH,"landlock-exact-usage");if(use<0)return false; + int null=opened("/dev/null",O_PATH|O_NOFOLLOW,"landlock-devnull");if(null<0)return false; + struct stat sink;if(!stat_fd(null,&sink,"devnull-rule-fstat"))return false; + if(!require(S_ISCHR(sink.st_mode)&&major(sink.st_rdev)==1&&minor(sink.st_rdev)==3,"exact-devnull-rule-object"))return false; + if(!ll_rule(rules,root,SV_READ,"landlock-broad-read-execute")|| + !ll_rule(rules,art,SV_ARTIFACT,"landlock-artifact-write-only-tree")|| + !ll_rule(rules,use,SV_FS_READ|SV_FS_WRITE|SV_FS_TRUNC,"landlock-exact-usage-write")|| + /* IOCTL_DEV is confined to this exact sink and the final filter's six + * harmless requests, preserving isatty/TCGETS's native ENOTTY. */ + !ll_rule(rules,null,SV_FS_READ|SV_FS_WRITE|SV_FS_IOCTL,"landlock-devnull-sink-exception"))return false; + if(syscall(SYS_landlock_restrict_self,rules,0)<0)return failed("landlock-restrict-self"); + landlocked=true;return true; +} + +/* Fixed LP64 policy. All branches inspect native ABI-normalized scalar words; + * no pointer/string inspection, instruction-address authority or bit-union + * approximation for clone. Unlisted syscalls return EPERM. */ +static struct sock_filter program[768];static size_t program_count; +static bool stmt(unsigned short code,uint32_t k) { + if(program_count==sizeof program/sizeof program[0])return require(false,"seccomp-program-capacity"); + program[program_count++]=(struct sock_filter){.code=code,.k=k};return true; +} +static bool jump(unsigned short code,uint32_t k,unsigned char yes,unsigned char no) { + if(program_count==sizeof program/sizeof program[0])return require(false,"seccomp-program-capacity"); + program[program_count++]=(struct sock_filter){.code=code,.jt=yes,.jf=no,.k=k};return true; +} +#define SV_LOAD_NR() stmt(BPF_LD|BPF_W|BPF_ABS,offsetof(struct seccomp_data,nr)) +#define SV_LOAD_ARG(n) stmt(BPF_LD|BPF_W|BPF_ABS,offsetof(struct seccomp_data,args)+(n)*8) +#define SV_LOAD_ARG_HI(n) stmt(BPF_LD|BPF_W|BPF_ABS,offsetof(struct seccomp_data,args)+(n)*8+4) +#define SV_RET(value) stmt(BPF_RET|BPF_K,(value)) +#define SV_EQ(value,yes,no) jump(BPF_JMP|BPF_JEQ|BPF_K,(value),(yes),(no)) +#define SV_ALLOW SECCOMP_RET_ALLOW +#define SV_DENY (SECCOMP_RET_ERRNO|EPERM) +static bool allow_number(int nr) { return SV_EQ((uint32_t)nr,0,1)&&SV_RET(SV_ALLOW); } +static bool install_seccomp(void) { + if(!stmt(BPF_LD|BPF_W|BPF_ABS,offsetof(struct seccomp_data,arch))|| + !SV_EQ(AUDIT_ARCH_X86_64,1,0)||!SV_RET(SECCOMP_RET_KILL_PROCESS)||!SV_LOAD_NR()|| + !jump(BPF_JMP|BPF_JSET|BPF_K,0x40000000U,0,1)||!SV_RET(SECCOMP_RET_KILL_PROCESS))return false; + if(!SV_EQ(SYS_clone3,0,1)||!SV_RET(SECCOMP_RET_ERRNO|ENOSYS))return false; + /* False branch skips this complete clone body (load + 3 tests + 4 RETs). */ + if(!SV_EQ(SYS_clone,0,8)||!SV_LOAD_ARG(0)|| + !SV_EQ(0x003d0f00U,0,1)||!SV_RET(SV_ALLOW)|| + !SV_EQ(0x00004111U,0,1)||!SV_RET(SV_ALLOW)|| + !SV_EQ(0x01200011U,0,1)||!SV_RET(SV_ALLOW)||!SV_RET(SV_DENY)||!SV_LOAD_NR())return false; + /* Core dumping is compiled out on both routes. Preserve ordinary self + * setrlimit arguments, including CORE; kernel hard-limit checks apply. */ + if(!allow_number(SYS_setrlimit))return false; + /* The original selected resource wrappers use pid=0 (self). Preserve all + * query/mutation arguments. Nonzero process targets remain unavailable. */ + if(!SV_EQ(SYS_prlimit64,0,4)||!SV_LOAD_ARG(0)||!SV_EQ(0,1,0)||!SV_RET(SV_DENY)|| + !SV_RET(SV_ALLOW)||!SV_LOAD_NR())return false; + /* fcntl retains ordinary descriptor/lock/pipe commands, never ownership, + * signal delivery, leases or notification. */ + static const int fcntl_commands[]={F_DUPFD,F_GETFD,F_SETFD,F_GETFL,F_SETFL,F_GETLK,F_SETLK,F_SETLKW,F_DUPFD_CLOEXEC,F_GETPIPE_SZ,F_SETPIPE_SZ}; + if(!SV_EQ(SYS_fcntl,0,(unsigned char)(2+2*sizeof fcntl_commands/sizeof fcntl_commands[0]))||!SV_LOAD_ARG(1))return false; + for(size_t i=0;i=sizeof out-used){uncertain=true;goto emit;} used+=(size_t)amount; } while(0) + APPEND("{\"schema\":\"h25-native-view-setup-failure-v1\",\"exit\":78,\"science_started\":false,\"uncertain\":%s,\"error_overflow\":%s,\"user_entered\":%s,\"mount_entered\":%s,\"root_private\":%s,\"root_readonly\":%s,\"artifact_attached\":%s,\"usage_attached\":%s,\"landlocked\":%s,\"filtered\":%s,\"errors\":[", + uncertain?"true":"false",error_overflow?"true":"false",user_entered?"true":"false",mount_entered?"true":"false", + root_private?"true":"false",root_readonly?"true":"false",artifact_attached?"true":"false",usage_attached?"true":"false",landlocked?"true":"false",filtered?"true":"false"); + for(size_t i=0;i=29&&argc<=160,"fixed-native-argv-count"))return false; + if(!require(!strcmp(argv[1],"--entry-image")&&!strcmp(argv[5],"--time-image")&& + !strcmp(argv[9],"--read-root")&&!strcmp(argv[11],"--artifact-parent")&& + !strcmp(argv[15],"--science-leaf")&&!strcmp(argv[17],"--usage")&&!strcmp(argv[21],"--"),"fixed-native-argv-switches"))return false; + if(!require(!strcmp(argv[6],"/usr/bin/time")&&!strcmp(argv[22],argv[6])&& + !strcmp(argv[23],"-f")&&!strcmp(argv[24],format)&&!strcmp(argv[25],"-o")&& + !strcmp(argv[26],argv[18])&&!strcmp(argv[27],"--")&& + !strcmp(argv[28],"/usr/bin/python3.12"),"unchanged-original-GNU-time-command-prefix"))return false; + size_t total=0; + for(int i=0;i=0;} + if(okay){self=opened("/proc/self/exe",O_RDONLY|O_NONBLOCK,"actual-self-executable");okay=self>=0;} + if(okay)okay=hash_image(entry,argv[3],entry_bytes,&entry_image)&& + stat_fd(self,&self_image,"actual-self-executable-fstat")&& + require(same_object(&entry_image,&self_image),"actual-native-entry-not-supplied-path-authority"); + if(okay){timed=role_open(argv[6],O_RDONLY|O_NONBLOCK,"actual-time-image-path");okay=timed>=0;} + if(okay)okay=hash_image(timed,argv[7],time_bytes,&time_image); + /* No old-view image/setup FD survives namespace entry. The admitted old + * stdin is explicitly reestablished by make_view; pipes retain only the + * selected relay-writer authority. */ + close_all();if(uncertain||error_count)okay=false; + if(okay)okay=enter_namespaces()&&make_view(argv)&&drop_privilege()&&install_landlock(); + close_all();if(uncertain||error_count)okay=false; + if(okay)okay=fd_census(); + /* Re-open authenticated time in the FINAL view for a second stable hash; + * close it before path exec, leaving exactly admitted stdio. The remaining + * pathname race is excluded by the named external no-mutation premise, + * never by declaring that a compiler is trusted. */ + if(okay){timed=role_open(argv[6],O_RDONLY|O_NONBLOCK,"final-view-time-image");okay=timed>=0;} + if(okay){struct stat final_time;okay=hash_image(timed,argv[7],time_bytes,&final_time)&& + require(same_backing_across_userns(&time_image,&final_time),"same-authenticated-time-across-userns");} + close_all();if(uncertain||error_count)okay=false; + if(okay)okay=install_seccomp(); + if(okay){execve(argv[6],&argv[22],environ);failed("authenticated-final-GNU-time-exec");} + close_all();report_failure(); + /* Kernel namespace/mount references die with this process, and only an + * actual external wait can establish that final release. No blind retry. */ + _exit(78); +} diff --git a/research/h25-native-view-facts/verify_integrity.py b/research/h25-native-view-facts/verify_integrity.py new file mode 100644 index 0000000000..f3d423d633 --- /dev/null +++ b/research/h25-native-view-facts/verify_integrity.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Passive package membership and SHA-256 integrity only.""" +from pathlib import Path +import hashlib,json +def main(): + root=Path(__file__).resolve().parent + inventory=json.loads((root/'INVENTORY.json').read_text()) + rows=inventory['files'] + expected=set(rows)|{'INVENTORY.json'} + actual={str(p.relative_to(root)) for p in root.rglob('*') if p.is_file()} + if actual!=expected:raise RuntimeError('Package file membership differs') + for name,row in rows.items(): + parts=Path(name).parts + if Path(name).is_absolute() or '..' in parts:raise RuntimeError('Invalid member') + p=root + for part in parts: + p=p/part + if p.is_symlink():raise RuntimeError('Symlink member') + raw=p.read_bytes() + if len(raw)!=row['bytes'] or hashlib.sha256(raw).hexdigest()!=row['sha256']: + raise RuntimeError('Member bytes differ: '+name) + print(json.dumps({'status':'PASS','files':len(rows),'scope':'Passive package bytes only'},sort_keys=True)) +if __name__=='__main__':main() +