Skip to content

Let any uid configure a project on ESP-IDF 5.5.6 - #58

Merged
hacker-cb merged 2 commits into
masterfrom
esp-idf-uid-writable-components
Oct 17, 2026
Merged

hacker-cb merged 2 commits into
masterfrom
esp-idf-uid-writable-components

Conversation

@hacker-cb

@hacker-cb hacker-cb commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Образы ESP-IDF v5.5.6 из #57 ломают сборку под задокументированным -u $(id -u):$(id -g): CMake configure любого проекта падает с PermissionError: '/opt/esp/root_managed_components'. Нашёл потребитель — батч jethome-iot/jetcontrol-cpp#2005: так у него ломалась каждая ESP32-сборка. Сборка от root, в том числе собственный слой проверки образа, продолжала проходить.

Почему так

В ESP-IDF 5.5.6 появился tools/idf_extra_components.yml (все строки закомментированы). Как только этот файл есть, менеджер компонентов (prepare_dep_dirs) при каждом configure пишет $IDF_TOOLS_PATH/root_managed_components/idf5.5/dependencies.lock и сначала создаёт этот каталог. /opt/esp принадлежит root. В 5.5.5 файла не было.

Обойти это переменной окружения нельзя. Каталог выводится только из IDF_TOOLS_PATH (idf_component_tools.config.config_dir(), запасной вариант — ~/.espressif), а по IDF_TOOLS_PATH образ находит тулчейны. Готовый lock, созданный при сборке от root, тоже не подходит: в нём записан target, и при каждой смене цели файл переписывается на месте (open(path, 'w')). Проверено: под чужим uid отказ случается на первом же set-target.

Что изменилось

  • images/esp-idf/Dockerfile:
    • новый слой — install -d -m 1777 "${IDF_TOOLS_PATH:?}/root_managed_components". Создаётся пустым и только верхний уровень: подкаталог idf<major.minor> заводит первый uid, выполнивший configure, и дальше он принадлежит этому uid. Один uid на контейнер — то, что даёт docker run -u, — проходит на любой цели. Второй uid в том же контейнере падает при смене цели. Комментарий и README об этом говорят прямо;
    • слой проверки настраивает hello_world под uid 54321, у которого нет записи в passwd, через entrypoint образа: сначала цель по умолчанию, затем set-target esp32c3. Если в SDK есть idf_extra_components.yml, слой требует, чтобы lock появился и принадлежал этому uid; в 5.4.1 этого файла нет. HOME и TMPDIR направлены во временный каталог проверки. Затем слой удаляет из root_managed_components всё, что записал этот uid, и проверяет режим 1777 и что в /tmp и /var/tmp от этого uid ничего не осталось. Если setpriv нет или он не может сбросить привилегии, слой так и сообщает, как это уже делает esp-matter.
  • images/esp-matter/Dockerfile — тот же install -d (идемпотентный) для баз, собранных до этого слоя: на них, в том числе на уже опубликованном idf-v5.5.6, локальная сборка esp-matter иначе снова сломалась бы под -u. Слой проверки требует, чтобы каталог оставался пустым и с режимом 1777 после install.sh, который выполняется от root.
  • images/esp-idf/README.md — раздел Building as Your Own User: пример с -u и -e HOME=/tmp, что образ подготовил для этого случая и чего не покрывает. Записываемый HOME по-прежнему за вызывающим: без него configure падает на кэше менеджера компонентов (~/.cache/Espressif/ComponentManager). Так было и на 5.5.5.
  • images/esp-matter/README.md — абзац о -u ссылается на этот раздел.

Файл SDK idf_extra_components.yml не меняется — так просил потребитель.

Как проверено

Локально, ./scripts/build.sh esp-idf (linux/arm64, IDF_BASE_TAG=v5.5.6):

проверка результат
сборка образа зелёная; configure as uid 54321, esp32 then esp32c3: ok
тот же Dockerfile без слоя 1777 слой проверки падает: PermissionError, configure as uid 54321 failed
root_managed_components в образе 1777 root, пустой; в /tmp от uid 54321 ничего нет (до исправления оставался /tmp/esp_idf_activate этого uid)
пример из README под -u $(id -u):$(id -g) -e HOME=/tmp hello_world собирается для esp32, затем set-target esp32c6 и снова собирается; build/ принадлежит вызывающему
образ v5.5.6 без исправления (локальная сборка master) под -u воспроизводит PermissionError; на опубликованном idf-v5.5.6-r39022168715.1 его воспроизвёл потребитель
check-versions.sh, check-pins.sh, lint.sh зелёные (у hadolint только прежние предупреждения)

esp-matter и вариант idf-v5.4.1 локально не собирались: для esp-matter нужно около 50 ГБ диска, а свободно меньше. Их проверяют сборки CI на этом PR, где esp-matter собирается поверх esp-idf этого же запуска.

Локальное ревью — раунд уровня high. У Claude полное покрытие, у Codex частичное: ему не хватило сети, чтобы прочитать Dockerfile базовых образов. Девять находок Minor. Шесть исправлены в 30d0476: различение отсутствующего setpriv, путь через entrypoint, смена цели, требование lock-файла, ${IDF_TOOLS_PATH:?}, кавычки вокруг $(pwd). Три отклонены:

  • убрать или обезвредить idf_extra_components.yml — потребитель просил файл SDK не трогать, а с первым же раскомментированным пакетом upstream это решение сломалось бы;
  • не создавать каталог в esp-matter — сделано намеренно, ради баз без этого слоя;
  • вынести кэш менеджера компонентов из HOME — требование существовало и до 5.5.6, это отдельное решение об окружении образа.

Исправление с TMPDIR и проверку остатков в /tmp после этого ещё раз прочитал Codex: полное покрытие, находок нет.

После слияния воркфлоу ESP-IDF опубликует новые idf-v5.5.6-r<run>.<attempt> и idf-v5.5.6-matter-v1.6-r<run>.<attempt> — их передадут в jethome-iot/jetcontrol-cpp#2005.

ESP-IDF 5.5.6 ships tools/idf_extra_components.yml, and its presence makes
the component manager write
$IDF_TOOLS_PATH/root_managed_components/idf5.5/dependencies.lock on every
configure. /opt/esp belongs to root, so under the documented
`-u $(id -u):$(id -g)` every project failed at configure with a
PermissionError, while every check, run as root, stayed green.

Both ESP images now ship that directory empty at mode 1777. The esp-idf
verification layer configures hello_world as an arbitrary uid and returns
the directory empty; esp-matter creates it too, for bases that predate the
layer, and asserts install.sh left it empty.
Review findings on the previous commit:
- tell a missing setpriv from one that cannot drop privileges;
- go through the image's entrypoint, as `docker run` does;
- switch targets after the first configure, the path that rewrites the lock;
- require the lock to exist and belong to the probe's uid where the SDK
  ships idf_extra_components.yml, so the probe cannot pass untouched;
- refuse an unset IDF_TOOLS_PATH in both images instead of creating
  /root_managed_components;
- quote $(pwd) in the new README example.

Also point the probe's TMPDIR at its scratch directory and assert nothing
of its uid is left in /tmp or /var/tmp: export.sh otherwise left
/tmp/esp_idf_activate owned by that uid, the directory it uses under every
uid without a passwd entry.
Copilot AI lite review requested due to automatic review settings October 17, 2026 11:40
@hacker-cb hacker-cb added the bug Something isn't working label Oct 17, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

No unresolved blocking issues remain.

No open issues 🎉

What changed in this PR

Fixes ESP-IDF 5.5.6 configuration for non-root container users.

Changes:

  • Adds writable component-manager storage and validation.
  • Applies compatibility setup to ESP-Matter images.
  • Documents non-root usage and HOME requirements.
File Description
images/​esp-matter/​README.md Links to ESP-IDF non-root build guidance.
images/​esp-matter/​Dockerfile Adds compatibility setup for inherited base images.
images/​esp-idf/​README.md Documents non-root builds and limitations.
images/​esp-idf/​Dockerfile Creates and validates writable component-manager storage.

Review effort: Lite

@hacker-cb
hacker-cb merged commit ceb19b6 into master Oct 17, 2026
15 checks passed
@hacker-cb
hacker-cb deleted the esp-idf-uid-writable-components branch October 17, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants