From: AdrianF <adrian.freihofer@siemens.com>
To: openembedded-core@lists.openembedded.org
Cc: Adrian Freihofer <adrian.freihofer@siemens.com>
Subject: [PATCH v2 4/9] oe-selftest/cpp-example: fix conf file ownership with static UIDs/GIDs
Date: Sun, 22 Mar 2026 16:12:55 +0100 [thread overview]
Message-ID: <20260322151320.661246-5-adrian.freihofer@siemens.com> (raw)
In-Reply-To: <20260322151320.661246-1-adrian.freihofer@siemens.com>
From: Adrian Freihofer <adrian.freihofer@siemens.com>
test_devtool_ide_sdk_none_qemu builds an image containing both
cmake-example and meson-example, starts a QEMU instance, then uses
devtool ide-sdk + devtool deploy-target to rebuild and redeploy each
recipe in turn. The test verifies that /etc/<recipe>.conf is owned by
the matching user both before and after each deploy cycle.
The test was failing with:
/etc/meson-example.conf not owned by user meson-example: got cmake-example
Root cause: both recipes call
install -m 0644 -o ${BPN} -g ${BPN} ... ${D}${sysconfdir}/${BPN}.conf
During do_install, pseudo resolves ${BPN} to a UID by looking up
/etc/passwd in the recipe's own isolated RECIPE_SYSROOT. Since the
sysroots are independent, both cmake-example and meson-example each
see themselves as the first --system user and get the same UID (e.g.
100). Both ${D} trees therefore contain files with UID 100. In the
final rootfs cmake-example is allocated UID 100 and meson-example UID
101. Files packaged for meson-example still carry UID 100, so stat
reports them as owned by cmake-example.
A pkg_postinst chown would fix the rootfs, but devtool deploy-target
is a plain tar pipe over SSH with no package-manager involvement - it
never runs pkg_postinst. Whatever UID is embedded in ${D} is what
lands on the target. Not sure how this could be fixed with dynamic UIDs.
A clean solution is to make every recipe sysroot and the final image
agree on the same UIDs from the start, i.e. static IDs.
Fix:
- Enable USERADDEXTENSION = "useradd-staticids" in _write_bb_config so
the test builds with static IDs for the duration of the test.
- Add cmake-example (UID/GID 533) and meson-example (UID/GID 534) to
meta-selftest/files/static-passwd and static-group.
- Expand the comment in cpp-example.inc's do_install to document the
static-ID requirement so future readers understand why the -o/-g
flags work correctly only under useradd-staticids.
- Fix a copy-paste error in the in-test comment (said
"meson-example.conf ... cmake-example user" for the cmake block).
Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
meta-selftest/files/static-group | 2 ++
meta-selftest/files/static-passwd | 2 ++
meta-selftest/recipes-test/cpp/cpp-example.inc | 6 +++++-
meta/lib/oeqa/selftest/cases/devtool.py | 14 ++++++++++++--
4 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/meta-selftest/files/static-group b/meta-selftest/files/static-group
index 3fca4aa5c9..adf436f310 100644
--- a/meta-selftest/files/static-group
+++ b/meta-selftest/files/static-group
@@ -28,4 +28,6 @@ ptest:x:529:
xuser:x:530:
seat:x:531:
audio:x:532:
+cmake-example:x:533:
+meson-example:x:534:
nogroup:x:65534:
diff --git a/meta-selftest/files/static-passwd b/meta-selftest/files/static-passwd
index cc6c5acd5c..8d9f149b9f 100644
--- a/meta-selftest/files/static-passwd
+++ b/meta-selftest/files/static-passwd
@@ -19,3 +19,5 @@ _apt:x:523:523::/:/bin/nologin
weston:x:525:525::/:/bin/nologin
ptest:x:529:529::/:/bin/nologin
xuser:x:530:530::/:/bin/nologin
+cmake-example:x:533:533::/var/lib/cmake-example:/bin/false
+meson-example:x:534:534::/var/lib/meson-example:/bin/false
diff --git a/meta-selftest/recipes-test/cpp/cpp-example.inc b/meta-selftest/recipes-test/cpp/cpp-example.inc
index 2653f45e90..0671824d1c 100644
--- a/meta-selftest/recipes-test/cpp/cpp-example.inc
+++ b/meta-selftest/recipes-test/cpp/cpp-example.inc
@@ -41,7 +41,11 @@ USERADD_PARAM:${PN} = "--system --home /var/lib/${BPN} --no-create-home --shell
EX_BINARY_NAME ?= "${BPN}"
do_install:append() {
- # Install configuration file owned by unprivileged user
+ # Install configuration file owned by the recipe's unprivileged user.
+ # Note: this requires static UIDs/GIDs (USERADDEXTENSION = "useradd-staticids")
+ # so that the UID embedded by pseudo during do_install matches the UID assigned
+ # in the final image. devtool deploy-target is a raw file copy and does not run
+ # pkg_postinst, so the UID in ${D} must already be correct.
install -d ${D}${sysconfdir}
install -m 0644 -g ${BPN} -o ${BPN} ${S}/cpp-example.conf ${D}${sysconfdir}/${BPN}.conf
sed -i -e 's|@BINARY_NAME@|${BPN}|g' ${D}${sysconfdir}/${BPN}.conf
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index dc83d406fd..bccbae912f 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -2597,7 +2597,17 @@ class DevtoolIdeSdkTests(DevtoolBase):
'IMAGE_GEN_DEBUGFS = "1"',
'IMAGE_INSTALL:append = " gdbserver %s"' % ' '.join(
[r + '-ptest' for r in recipe_names]),
- 'DISTRO_FEATURES:append = " ptest"'
+ 'DISTRO_FEATURES:append = " ptest"',
+ # Static UIDs/GIDs are required so that files installed via
+ # "install -o ${BPN}" in do_install embed the same UID that gets
+ # assigned in the final image. Without this, each recipe's isolated
+ # sysroot allocates UIDs independently (both start at the first free
+ # system UID), so files end up with colliding UIDs in the image.
+ # devtool deploy-target is a raw file copy and does not run
+ # pkg_postinst, so ownership must be correct already in ${D}.
+ 'USERADDEXTENSION = "useradd-staticids"',
+ 'USERADD_UID_TABLES += "files/static-passwd"',
+ 'USERADD_GID_TABLES += "files/static-group"',
]
self.write_config("\n".join(conf_lines))
@@ -2985,7 +2995,7 @@ class DevtoolIdeSdkTests(DevtoolBase):
self.assertEqual(self._workspace_scripts_dir(
recipe_name), self._sources_scripts_dir(tempdir))
- # Verify /etc/meson-example.conf is still owned by the cmake-example user
+ # Verify /etc/cmake-example.conf is still owned by the cmake-example user
# after the install and deploy scripts updated the file
self._verify_conf_file(qemu, conf_file, example_exe, example_exe)
--
2.53.0
next prev parent reply other threads:[~2026-03-22 15:13 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-22 15:12 [PATCH v2 0/9] devtool: ide-sdk clang/LLDB support and minor fixes AdrianF
2026-03-22 15:12 ` [PATCH v2 1/9] oe-selftest: devtool: use stat for reading user/group names in ide-sdk tests AdrianF
2026-03-22 15:12 ` [PATCH v2 2/9] oe-selftest: devtool: GDB breakpoint after std::vector is constructed AdrianF
2026-03-22 15:12 ` [PATCH v2 3/9] oe-selftest: devtool: use assertRegex to match test output for meson AdrianF
2026-03-22 15:12 ` AdrianF [this message]
2026-03-22 15:12 ` [PATCH v2 5/9] devtool: ide-sdk: use TOOLCHAIN not TCOVERRIDE AdrianF
2026-03-22 15:12 ` [PATCH v2 6/9] devtool: ide-sdk debugger back-end abstraction AdrianF
2026-03-22 15:12 ` [PATCH v2 7/9] devtool: ide-sdk add LLDB support for clang toolchain AdrianF
2026-03-22 15:12 ` [PATCH v2 8/9] meta-selftest: refactor cpp examples into .inc files and add clang variants AdrianF
2026-03-22 15:13 ` [PATCH v2 9/9] oe-selftest: devtool ide-sdk: add clang/LLDB test AdrianF
2026-03-24 17:22 ` [OE-core] " Mathieu Dubois-Briand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260322151320.661246-5-adrian.freihofer@siemens.com \
--to=adrian.freihofer@siemens.com \
--cc=openembedded-core@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox