| Message ID | 20261021112532.3824701-2-clara.kowalsky@siemens.com |
|---|---|
| State | New |
| Headers | show |
| Series | [1/2] rootfs-add-files: correctly remove files in ROOTFSDIR | expand |
On Wed, 2026-10-21 at 13:25 +0200, 'Clara Kowalsky' via isar-users wrote: > rootfs_add_files uses host sudo to create directories and files. > In unshare mode, package installation runs as root in a user namespace, > where host-root ownership may not map to namespace root. Dpkg can then > fail to replace a rootfs file with: ... and in rootless mode we don't require to have sudo installed at all. > > Unable to create `<path>.dpkg-new`: Permission denied. > > Use RUN_PRIVILEGED_CMD for rootfs operations and disable ownership > preservation when copying files in unshare mode. The question is how to control ownership at all for these files. The whole rootfs_add_files logic seems to be broken. I even vote for just removing it. There can't be many users, given that nobody noticed that it breaks under rootless. > > Fixes: 4fedb1ae6f90 ("add support for fully rootless builds") > Signed-off-by: Clara Kowalsky <clara.kowalsky@siemens.com> > --- > meta/classes-recipe/rootfs-add-files.bbclass | 15 +++++++++++---- > 1 file changed, 11 insertions(+), 4 deletions(-) > > diff --git a/meta/classes-recipe/rootfs-add-files.bbclass b/meta/classes-recipe/rootfs-add-files.bbclass > index d33752f3..b21e282b 100644 > --- a/meta/classes-recipe/rootfs-add-files.bbclass > +++ b/meta/classes-recipe/rootfs-add-files.bbclass > @@ -16,6 +16,13 @@ ROOTFS_ADDITIONAL_FILES ??= "" > > > python rootfs_add_files() { > + import shlex > + > + cmd = shlex.split(d.getVar('RUN_PRIVILEGED_CMD')) bb.process.run executes the command in a shell if not passed as list. With that, we don't need to split it. Felix > + copy_args = ['-a'] > + if d.getVar('ISAR_CHROOT_MODE') == 'unshare': > + copy_args.append('--no-preserve=ownership') > + > postprocess_additional_files = d.getVar('ROOTFS_ADDITIONAL_FILES').split() > rootfsdir = d.getVar("ROOTFSDIR") > > @@ -24,18 +31,18 @@ python rootfs_add_files() { > destination = d.getVarFlag(additional_file_entry, "destination") or "" > source = d.getVarFlag(additional_file_entry, "source") or "" > if os.path.exists(f"{rootfsdir}/{destination}"): > - bb.process.run(["/usr/bin/rm", "-f", f"{rootfsdir}/{destination}"]) > + bb.process.run(cmd + ["/usr/bin/rm", "-f", f"{rootfsdir}/{destination}"]) > > dest_dir = os.path.dirname(destination) > - bb.process.run(["sudo", "-E", "/usr/bin/mkdir", "-p", f"{rootfsdir}/{dest_dir}" ]) > + bb.process.run(cmd + ["/usr/bin/mkdir", "-p", f"{rootfsdir}/{dest_dir}"]) > # empty source creates only an empty destination file > if not source: > - bb.process.run(["sudo", "-E", "/usr/bin/touch", f"{rootfsdir}/{destination}" ]) > + bb.process.run(cmd + ["/usr/bin/touch", f"{rootfsdir}/{destination}"]) > return > > if not os.path.exists(f"{source}"): > bb.error(f"{source} does not exists and cannot be copied to the rootfs!") > # no recursive copy only single files > - bb.process.run(["sudo", "-E", "/usr/bin/cp", "-a", f"{source}", f"{rootfsdir}/{destination}" ]) > + bb.process.run(cmd + ["/usr/bin/cp"] + copy_args + [source, f"{rootfsdir}/{destination}"]) > } > ROOTFS_INSTALL_COMMAND += "rootfs_add_files" > -- > 2.55.0 > > -- > You received this message because you are subscribed to the Google Groups "isar-users" group. > To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com. > To view this discussion visit https://groups.google.com/d/msgid/isar-users/20261021112532.3824701-2-clara.kowalsky%40siemens.com.
On 10/21/26 13:54, Moessbauer, Felix (FT RPD CPC OES-DE) wrote: > On Wed, 2026-10-21 at 13:25 +0200, 'Clara Kowalsky' via isar-users > wrote: >> rootfs_add_files uses host sudo to create directories and files. >> In unshare mode, package installation runs as root in a user namespace, >> where host-root ownership may not map to namespace root. Dpkg can then >> fail to replace a rootfs file with: > > ... and in rootless mode we don't require to have sudo installed at > all. > >> >> Unable to create `<path>.dpkg-new`: Permission denied. >> >> Use RUN_PRIVILEGED_CMD for rootfs operations and disable ownership >> preservation when copying files in unshare mode. > > The question is how to control ownership at all for these files. > The whole rootfs_add_files logic seems to be broken. > > I even vote for just removing it. There can't be many users, given that > nobody noticed that it breaks under rootless. > rootfs-add-files is used by installer-add-rootfs and therefore by isar-image-installer. So it is quite essential. Either we fix this or find a good replacement. BR, Clara >> >> Fixes: 4fedb1ae6f90 ("add support for fully rootless builds") >> Signed-off-by: Clara Kowalsky <clara.kowalsky@siemens.com> >> --- >> meta/classes-recipe/rootfs-add-files.bbclass | 15 +++++++++++---- >> 1 file changed, 11 insertions(+), 4 deletions(-) >> >> diff --git a/meta/classes-recipe/rootfs-add-files.bbclass b/meta/classes-recipe/rootfs-add-files.bbclass >> index d33752f3..b21e282b 100644 >> --- a/meta/classes-recipe/rootfs-add-files.bbclass >> +++ b/meta/classes-recipe/rootfs-add-files.bbclass >> @@ -16,6 +16,13 @@ ROOTFS_ADDITIONAL_FILES ??= "" >> >> >> python rootfs_add_files() { >> + import shlex >> + >> + cmd = shlex.split(d.getVar('RUN_PRIVILEGED_CMD')) > > bb.process.run executes the command in a shell if not passed as list. > With that, we don't need to split it. > > Felix > >> + copy_args = ['-a'] >> + if d.getVar('ISAR_CHROOT_MODE') == 'unshare': >> + copy_args.append('--no-preserve=ownership') >> + >> postprocess_additional_files = d.getVar('ROOTFS_ADDITIONAL_FILES').split() >> rootfsdir = d.getVar("ROOTFSDIR") >> >> @@ -24,18 +31,18 @@ python rootfs_add_files() { >> destination = d.getVarFlag(additional_file_entry, "destination") or "" >> source = d.getVarFlag(additional_file_entry, "source") or "" >> if os.path.exists(f"{rootfsdir}/{destination}"): >> - bb.process.run(["/usr/bin/rm", "-f", f"{rootfsdir}/{destination}"]) >> + bb.process.run(cmd + ["/usr/bin/rm", "-f", f"{rootfsdir}/{destination}"]) >> >> dest_dir = os.path.dirname(destination) >> - bb.process.run(["sudo", "-E", "/usr/bin/mkdir", "-p", f"{rootfsdir}/{dest_dir}" ]) >> + bb.process.run(cmd + ["/usr/bin/mkdir", "-p", f"{rootfsdir}/{dest_dir}"]) >> # empty source creates only an empty destination file >> if not source: >> - bb.process.run(["sudo", "-E", "/usr/bin/touch", f"{rootfsdir}/{destination}" ]) >> + bb.process.run(cmd + ["/usr/bin/touch", f"{rootfsdir}/{destination}"]) >> return >> >> if not os.path.exists(f"{source}"): >> bb.error(f"{source} does not exists and cannot be copied to the rootfs!") >> # no recursive copy only single files >> - bb.process.run(["sudo", "-E", "/usr/bin/cp", "-a", f"{source}", f"{rootfsdir}/{destination}" ]) >> + bb.process.run(cmd + ["/usr/bin/cp"] + copy_args + [source, f"{rootfsdir}/{destination}"]) >> } >> ROOTFS_INSTALL_COMMAND += "rootfs_add_files" >> -- >> 2.55.0 >> >> -- >> You received this message because you are subscribed to the Google Groups "isar-users" group. >> To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com. >> To view this discussion visit https://groups.google.com/d/msgid/isar-users/20261021112532.3824701-2-clara.kowalsky%40siemens.com. >
On Wed, 2026-10-21 at 14:21 +0200, Clara Kowalsky wrote: > On 10/21/26 13:54, Moessbauer, Felix (FT RPD CPC OES-DE) wrote: > > On Wed, 2026-10-21 at 13:25 +0200, 'Clara Kowalsky' via isar-users > > wrote: > > > rootfs_add_files uses host sudo to create directories and files. > > > In unshare mode, package installation runs as root in a user namespace, > > > where host-root ownership may not map to namespace root. Dpkg can then > > > fail to replace a rootfs file with: > > > > ... and in rootless mode we don't require to have sudo installed at > > all. > > > > > > > > Unable to create `<path>.dpkg-new`: Permission denied. > > > > > > Use RUN_PRIVILEGED_CMD for rootfs operations and disable ownership > > > preservation when copying files in unshare mode. > > > > The question is how to control ownership at all for these files. > > The whole rootfs_add_files logic seems to be broken. > > > > I even vote for just removing it. There can't be many users, given that > > nobody noticed that it breaks under rootless. > > > rootfs-add-files is used by installer-add-rootfs and therefore by > isar-image-installer. So it is quite essential. Either we fix this or > find a good replacement. I see... I'm just wondering why the installer tests did not catch this? They run perfectly fine with -p rootless=1. We probably really want to block sudo usage in kas-container when running in non-privileged mode. I'll try to inject a false sudo in the citest on -p rootless=1, but this will only be able to catch sudo usage without full path. Felix > > BR, > Clara > > > > > > > Fixes: 4fedb1ae6f90 ("add support for fully rootless builds") > > > Signed-off-by: Clara Kowalsky <clara.kowalsky@siemens.com> > > > --- > > > meta/classes-recipe/rootfs-add-files.bbclass | 15 +++++++++++---- > > > 1 file changed, 11 insertions(+), 4 deletions(-) > > > > > > diff --git a/meta/classes-recipe/rootfs-add-files.bbclass b/meta/classes-recipe/rootfs-add-files.bbclass > > > index d33752f3..b21e282b 100644 > > > --- a/meta/classes-recipe/rootfs-add-files.bbclass > > > +++ b/meta/classes-recipe/rootfs-add-files.bbclass > > > @@ -16,6 +16,13 @@ ROOTFS_ADDITIONAL_FILES ??= "" > > > > > > > > > python rootfs_add_files() { > > > + import shlex > > > + > > > + cmd = shlex.split(d.getVar('RUN_PRIVILEGED_CMD')) > > > > bb.process.run executes the command in a shell if not passed as list. > > With that, we don't need to split it. > > > > Felix > > > > > + copy_args = ['-a'] > > > + if d.getVar('ISAR_CHROOT_MODE') == 'unshare': > > > + copy_args.append('--no-preserve=ownership') > > > + > > > postprocess_additional_files = d.getVar('ROOTFS_ADDITIONAL_FILES').split() > > > rootfsdir = d.getVar("ROOTFSDIR") > > > > > > @@ -24,18 +31,18 @@ python rootfs_add_files() { > > > destination = d.getVarFlag(additional_file_entry, "destination") or "" > > > source = d.getVarFlag(additional_file_entry, "source") or "" > > > if os.path.exists(f"{rootfsdir}/{destination}"): > > > - bb.process.run(["/usr/bin/rm", "-f", f"{rootfsdir}/{destination}"]) > > > + bb.process.run(cmd + ["/usr/bin/rm", "-f", f"{rootfsdir}/{destination}"]) > > > > > > dest_dir = os.path.dirname(destination) > > > - bb.process.run(["sudo", "-E", "/usr/bin/mkdir", "-p", f"{rootfsdir}/{dest_dir}" ]) > > > + bb.process.run(cmd + ["/usr/bin/mkdir", "-p", f"{rootfsdir}/{dest_dir}"]) > > > # empty source creates only an empty destination file > > > if not source: > > > - bb.process.run(["sudo", "-E", "/usr/bin/touch", f"{rootfsdir}/{destination}" ]) > > > + bb.process.run(cmd + ["/usr/bin/touch", f"{rootfsdir}/{destination}"]) > > > return > > > > > > if not os.path.exists(f"{source}"): > > > bb.error(f"{source} does not exists and cannot be copied to the rootfs!") > > > # no recursive copy only single files > > > - bb.process.run(["sudo", "-E", "/usr/bin/cp", "-a", f"{source}", f"{rootfsdir}/{destination}" ]) > > > + bb.process.run(cmd + ["/usr/bin/cp"] + copy_args + [source, f"{rootfsdir}/{destination}"]) > > > } > > > ROOTFS_INSTALL_COMMAND += "rootfs_add_files" > > > -- > > > 2.55.0 > > > > > > -- > > > You received this message because you are subscribed to the Google Groups "isar-users" group. > > > To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com. > > > To view this discussion visit https://groups.google.com/d/msgid/isar-users/20261021112532.3824701-2-clara.kowalsky%40siemens.com. > >
diff --git a/meta/classes-recipe/rootfs-add-files.bbclass b/meta/classes-recipe/rootfs-add-files.bbclass index d33752f3..b21e282b 100644 --- a/meta/classes-recipe/rootfs-add-files.bbclass +++ b/meta/classes-recipe/rootfs-add-files.bbclass @@ -16,6 +16,13 @@ ROOTFS_ADDITIONAL_FILES ??= "" python rootfs_add_files() { + import shlex + + cmd = shlex.split(d.getVar('RUN_PRIVILEGED_CMD')) + copy_args = ['-a'] + if d.getVar('ISAR_CHROOT_MODE') == 'unshare': + copy_args.append('--no-preserve=ownership') + postprocess_additional_files = d.getVar('ROOTFS_ADDITIONAL_FILES').split() rootfsdir = d.getVar("ROOTFSDIR") @@ -24,18 +31,18 @@ python rootfs_add_files() { destination = d.getVarFlag(additional_file_entry, "destination") or "" source = d.getVarFlag(additional_file_entry, "source") or "" if os.path.exists(f"{rootfsdir}/{destination}"): - bb.process.run(["/usr/bin/rm", "-f", f"{rootfsdir}/{destination}"]) + bb.process.run(cmd + ["/usr/bin/rm", "-f", f"{rootfsdir}/{destination}"]) dest_dir = os.path.dirname(destination) - bb.process.run(["sudo", "-E", "/usr/bin/mkdir", "-p", f"{rootfsdir}/{dest_dir}" ]) + bb.process.run(cmd + ["/usr/bin/mkdir", "-p", f"{rootfsdir}/{dest_dir}"]) # empty source creates only an empty destination file if not source: - bb.process.run(["sudo", "-E", "/usr/bin/touch", f"{rootfsdir}/{destination}" ]) + bb.process.run(cmd + ["/usr/bin/touch", f"{rootfsdir}/{destination}"]) return if not os.path.exists(f"{source}"): bb.error(f"{source} does not exists and cannot be copied to the rootfs!") # no recursive copy only single files - bb.process.run(["sudo", "-E", "/usr/bin/cp", "-a", f"{source}", f"{rootfsdir}/{destination}" ]) + bb.process.run(cmd + ["/usr/bin/cp"] + copy_args + [source, f"{rootfsdir}/{destination}"]) } ROOTFS_INSTALL_COMMAND += "rootfs_add_files"
rootfs_add_files uses host sudo to create directories and files. In unshare mode, package installation runs as root in a user namespace, where host-root ownership may not map to namespace root. Dpkg can then fail to replace a rootfs file with: Unable to create `<path>.dpkg-new`: Permission denied. Use RUN_PRIVILEGED_CMD for rootfs operations and disable ownership preservation when copying files in unshare mode. Fixes: 4fedb1ae6f90 ("add support for fully rootless builds") Signed-off-by: Clara Kowalsky <clara.kowalsky@siemens.com> --- meta/classes-recipe/rootfs-add-files.bbclass | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)