Skip to content

[17.0-stable] pillar: fix decimal literals used as file modes - #6281

Merged
eriknordmark merged 1 commit into
lf-edge:17.0-stablefrom
christoph-zededa:17.0-backport_dec_perms
Aug 12, 2026
Merged

[17.0-stable] pillar: fix decimal literals used as file modes#6281
eriknordmark merged 1 commit into
lf-edge:17.0-stablefrom
christoph-zededa:17.0-backport_dec_perms

Conversation

@christoph-zededa

@christoph-zededa christoph-zededa commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Description

Backport of #6264

Six file-mode arguments in pillar are written as decimal literals, so the
permission bits they produce are not the ones they read as:

Literal Go value Resulting permission bits
755 0o1363 0o363-wxrw--wx
644 0o1204 0o204-w----r--

Measured, not inferred:

os.MkdirAll(dir, 755)  -> d-wxrw--wx (0363)
os.MkdirAll(dir, 0755) -> drwxr-xr-x (0755)

So the vault directories were created world-writable, and the attestation
integrity token file (/run/eve.integrity_token) was written world-readable
while not being readable by its owner. Affected call sites:

  • pkg/pillar/vault/key.go — key staging directory
  • pkg/pillar/vault/handler_ext4.go (x2) — default vault and vault path
  • pkg/pillar/vault/handler_unsupported.go — default vault
  • pkg/pillar/vault/handler_zfs.go — sealed dataset mount point
  • pkg/pillar/cmd/zedagent/attesttask.go — integrity token file

Each site is switched to an octal literal keeping the permissions it already
intended, so there is no change of intent anywhere — only the notation bug.

Cherry-picked with git cherry-pick -x, applies cleanly with no conflicts.

Only the fix commit of #6264 is backported. That PR's second commit,
semgrep: run the rules from make and in CI, is developer tooling (a make
target and a CI workflow) rather than a fix, and it modifies
tests/semgrep-rules/os-openfile-non-perm-mode.yaml, which is absent from
16.0-stable, 14.5-stable and 13.4-stable.

How to test and validate this PR

The mistake is checkable statically. This reports nothing after this PR, and
the six call sites above before it:

grep -rnE '\.(MkdirAll|Mkdir|WriteFile|OpenFile|Chmod)\(([^()]|\([^()]*\))*,\s*(os\.FileMode\()?[1-9][0-9]*\s*\)?\)' \
    --include='*.go' . | grep -v /vendor/

Also run:

make -C pkg/pillar fmt-check
make -C pkg/pillar vet
make -C pkg/pillar test

On a device, the permission change can be confirmed directly. Since MkdirAll
only applies its mode when creating the directory, the vault checks need a
device whose vault does not exist yet (fresh install, or an installation
without TPM where the vault is a plain folder):

  1. Boot a device with this build and confirm the vault directory is
    drwxr-xr-x rather than d-wxrw--wx:
    stat -c '%a %A %n' /persist/vault
  2. Confirm the vault still unlocks normally and app instances with encrypted
    volumes start. All the affected directories are used by root-owned
    processes only, so no functional change is expected.
  3. On a ZFS install, confirm the sealed dataset mount point is drwxr-xr-x:
    stat -c '%a %A %n' /persist/vault
  4. After a successful attestation, confirm the integrity token file is
    -rw-r--r-- rather than --w----r--:
    stat -c '%a %A %n' /run/eve.integrity_token

Suggested QA regression focus: vault creation and unlock on a fresh install,
both with and without TPM, on ext4 and zfs; plus one attestation cycle.

Changelog notes

Fixed file permissions on the vault directories, the vault key staging
directory and the attestation integrity token file, which were created with
different permission bits than intended.

PR Backports

Original: #6264

Checklist

  • I've provided a proper description
  • I've added the proper documentation
  • I've tested my PR on amd64 device
  • I've tested my PR on arm64 device
  • I've written the test verification instructions
  • I've set the proper labels to this PR

For backport PRs (remove it if it's not a backport):

  • I've added a reference link to the original PR
  • PR's title follows the template

And the last but not least:

  • I've checked the boxes above, or I've provided a good reason why I didn't
    check them

Reasons for the unchecked boxes:

  • Documentation: no user-facing or architectural behaviour changes, so there is
    nothing to document.
  • Device testing on amd64/arm64: not yet done, hence the draft status. The
    changes are architecture-independent, but the vault paths are device
    management code, so the on-device steps above still need to be run before
    this leaves draft.

os.MkdirAll(dir, 755) and os.WriteFile(file, data, 644) pass decimal,
not octal, values. Go reads 755 as 0o1363, leaving permission bits 0o363
(-wxrw--wx), and 644 as 0o1204, leaving 0o204 (-w----r--). The vault
directories were therefore created world-writable, and the attestation
integrity token was written world-readable while not being readable by
its owner.

Use octal literals, keeping the permissions each site already intended.

In vault/key.go that is not sufficient on its own: stageKey() mounts a
tmpfs onto the key staging directory right after creating it, and a
tmpfs root defaults to 01777, which masks the mode underneath for as
long as the unsealed vault key is staged there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Christoph Ostarek <christoph@zededa.com>
(cherry picked from commit 1204936)
@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 21.04%. Comparing base (7e025c1) to head (79c4144).

Files with missing lines Patch % Lines
pkg/pillar/vault/handler_ext4.go 0.00% 2 Missing ⚠️
pkg/pillar/cmd/zedagent/attesttask.go 0.00% 1 Missing ⚠️
pkg/pillar/vault/handler_unsupported.go 0.00% 1 Missing ⚠️
pkg/pillar/vault/handler_zfs.go 0.00% 1 Missing ⚠️
pkg/pillar/vault/key.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@               Coverage Diff               @@
##           17.0-stable    #6281      +/-   ##
===============================================
+ Coverage        20.62%   21.04%   +0.41%     
===============================================
  Files              506      516      +10     
  Lines            92973    94671    +1698     
===============================================
+ Hits             19179    19920     +741     
- Misses           72197    72973     +776     
- Partials          1597     1778     +181     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@eriknordmark
eriknordmark merged commit 362fa71 into lf-edge:17.0-stable Aug 12, 2026
50 of 52 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

security Provides a security fix stable Should be backported to stable release(s)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants