mbox series

[RFC,00/12] add support to build isar unprivileged

Message ID 20260218115827.3947145-1-felix.moessbauer@siemens.com
Headers show
Series add support to build isar unprivileged | expand

Message

MOESSBAUER, Felix Feb. 18, 2026, 11:58 a.m. UTC
Dear isar-users,

currently isar requires password-less sudo and an environment
where mounting file systems is possible. This has proven problematic
for security reasons, both when running in a privileged container or
locally.

To solve this, we implement fully rootless builds that rely on the
unshare syscall which allows us to avoid sudo and instead operate in
temporary kernel namespaces as a user that is just privileged within
that namespace. This comes with some challenges regarding the handling
of mounts (they are cleared when leaving the namespace), as well as
cross namespace deployments (the outer user might not be able to access
the inner data). For that, we rework the handling of mounts and artifact
passing to make it compatible with both chroot modes (schroot and
unshare).

The patches 1-10 align the file permissions of deployments and artifacts
to avoid the use of chown (which will not work anymore across uid
boundaries). In addition, helpers are introduced to perform privileged
operations, which simplifies the migration of existing layers.

The patches 11 and 12 introduce the unshare mode, which can be executed
as a normal user and does not require root. To enable this mode, set
ISAR_ROOTLESS = "1".

While the series is by far not complete yet, it already passes the DevTest
CI. Know issues are currently:

- no support for VM and container images
- unprivileged cleanup of the build/tmp dir is non trivial
- sporadic issues on partial rebuilds on rootfs_install_sstate_finalize
- interfaces between kas and isar need to be defined

Note, that this series can be tested on a custom kas-container build
provided in [1]. Hints how to migrate downstream layers are provided
in the API changelog.

[1] https://groups.google.com/g/kas-devel/c/NWQFCU2aUHg

Best regards,
Felix Moessbauer
Siemens AG

Felix Moessbauer (12):
  refactor bootstrap: store rootfs tar with user permissions
  deb-dl-dir: export without root privileges
  download debs without locking
  introduce wrappers for privileged execution
  bootstrap: move cleanup trap to function
  rootfs: rework sstate caching of rootfs artifact
  rootfs_generate_initramfs: rework deployment to avoid chowning
  wic: rework image deploy logic to deploy under correct user
  use bitbake function to generate mounting scripts
  apt-fetcher: prepare for chroot specific fetching
  add support for fully rootless builds
  apt-fetcher: implement support for unshare backend

 Kconfig                                       |   2 +-
 RECIPE-API-CHANGELOG.md                       |  57 +++++
 doc/user_manual.md                            |   2 +
 meta/classes-global/base.bbclass              |  93 ++++++++
 meta/classes-recipe/deb-dl-dir.bbclass        |  20 +-
 meta/classes-recipe/dpkg-base.bbclass         |  20 +-
 meta/classes-recipe/dpkg-source.bbclass       |   2 +-
 meta/classes-recipe/dpkg.bbclass              |  16 +-
 .../image-account-extension.bbclass           |   4 +-
 .../image-locales-extension.bbclass           |  13 +-
 .../image-postproc-extension.bbclass          |  30 +--
 .../image-tools-extension.bbclass             |  96 +++++++-
 meta/classes-recipe/image.bbclass             |  24 +-
 meta/classes-recipe/imagetypes.bbclass        |  47 ++--
 .../imagetypes_container.bbclass              |  26 +--
 meta/classes-recipe/imagetypes_wic.bbclass    |  12 +-
 meta/classes-recipe/rootfs.bbclass            | 221 ++++++++++--------
 meta/classes-recipe/sbuild.bbclass            |  37 ++-
 meta/classes-recipe/sdk.bbclass               |  23 +-
 meta/classes-recipe/squashfs.bbclass          |   2 +-
 meta/classes/sbom.bbclass                     |   2 +-
 meta/conf/bitbake.conf                        |   7 +-
 meta/lib/aptsrc_fetcher.py                    |  90 ++++++-
 .../isar-mmdebstrap/isar-mmdebstrap.inc       |  47 ++--
 .../sbuild-chroot/sbuild-chroot.inc           |  24 +-
 .../unittests/test_image_account_extension.py |   9 +-
 26 files changed, 691 insertions(+), 235 deletions(-)

Comments

Jan Kiszka Feb. 18, 2026, 6:20 p.m. UTC | #1
On 18.02.26 12:58, 'Felix Moessbauer' via isar-users wrote:
> Dear isar-users,
> 
> currently isar requires password-less sudo and an environment
> where mounting file systems is possible. This has proven problematic
> for security reasons, both when running in a privileged container or
> locally.
> 
> To solve this, we implement fully rootless builds that rely on the
> unshare syscall which allows us to avoid sudo and instead operate in
> temporary kernel namespaces as a user that is just privileged within
> that namespace. This comes with some challenges regarding the handling
> of mounts (they are cleared when leaving the namespace), as well as
> cross namespace deployments (the outer user might not be able to access
> the inner data). For that, we rework the handling of mounts and artifact
> passing to make it compatible with both chroot modes (schroot and
> unshare).
> 
> The patches 1-10 align the file permissions of deployments and artifacts
> to avoid the use of chown (which will not work anymore across uid
> boundaries). In addition, helpers are introduced to perform privileged
> operations, which simplifies the migration of existing layers.
> 
> The patches 11 and 12 introduce the unshare mode, which can be executed
> as a normal user and does not require root. To enable this mode, set
> ISAR_ROOTLESS = "1".
> 
> While the series is by far not complete yet, it already passes the DevTest
> CI. Know issues are currently:
> 
> - no support for VM and container images
> - unprivileged cleanup of the build/tmp dir is non trivial
> - sporadic issues on partial rebuilds on rootfs_install_sstate_finalize
> - interfaces between kas and isar need to be defined
> 
> Note, that this series can be tested on a custom kas-container build
> provided in [1]. Hints how to migrate downstream layers are provided
> in the API changelog.
> 
> [1] https://groups.google.com/g/kas-devel/c/NWQFCU2aUHg
> 
> Best regards,
> Felix Moessbauer
> Siemens AG
> 
> Felix Moessbauer (12):
>   refactor bootstrap: store rootfs tar with user permissions
>   deb-dl-dir: export without root privileges
>   download debs without locking
>   introduce wrappers for privileged execution
>   bootstrap: move cleanup trap to function
>   rootfs: rework sstate caching of rootfs artifact
>   rootfs_generate_initramfs: rework deployment to avoid chowning
>   wic: rework image deploy logic to deploy under correct user
>   use bitbake function to generate mounting scripts
>   apt-fetcher: prepare for chroot specific fetching
>   add support for fully rootless builds
>   apt-fetcher: implement support for unshare backend
> 
>  Kconfig                                       |   2 +-
>  RECIPE-API-CHANGELOG.md                       |  57 +++++
>  doc/user_manual.md                            |   2 +
>  meta/classes-global/base.bbclass              |  93 ++++++++
>  meta/classes-recipe/deb-dl-dir.bbclass        |  20 +-
>  meta/classes-recipe/dpkg-base.bbclass         |  20 +-
>  meta/classes-recipe/dpkg-source.bbclass       |   2 +-
>  meta/classes-recipe/dpkg.bbclass              |  16 +-
>  .../image-account-extension.bbclass           |   4 +-
>  .../image-locales-extension.bbclass           |  13 +-
>  .../image-postproc-extension.bbclass          |  30 +--
>  .../image-tools-extension.bbclass             |  96 +++++++-
>  meta/classes-recipe/image.bbclass             |  24 +-
>  meta/classes-recipe/imagetypes.bbclass        |  47 ++--
>  .../imagetypes_container.bbclass              |  26 +--
>  meta/classes-recipe/imagetypes_wic.bbclass    |  12 +-
>  meta/classes-recipe/rootfs.bbclass            | 221 ++++++++++--------
>  meta/classes-recipe/sbuild.bbclass            |  37 ++-
>  meta/classes-recipe/sdk.bbclass               |  23 +-
>  meta/classes-recipe/squashfs.bbclass          |   2 +-
>  meta/classes/sbom.bbclass                     |   2 +-
>  meta/conf/bitbake.conf                        |   7 +-
>  meta/lib/aptsrc_fetcher.py                    |  90 ++++++-
>  .../isar-mmdebstrap/isar-mmdebstrap.inc       |  47 ++--
>  .../sbuild-chroot/sbuild-chroot.inc           |  24 +-
>  .../unittests/test_image_account_extension.py |   9 +-
>  26 files changed, 691 insertions(+), 235 deletions(-)
> 

Hmm, just testing xenomai-images with this and minimal changes for 
itself (buildsystem update). It seems to build the kernel - put only on 
a single core. This part looks still fine:

# $PARALLEL_MAKE
#   set? /work/build/../isar/meta/conf/bitbake.conf:135
#     "-j ${@bb.utils.cpu_count()}"
PARALLEL_MAKE="-j 16"

But the "-j 16" does not end up in the actually make call of the kernel 
build. How could we possibly lose this?


I wanted to test if rootfull mode with your patches applied may answer 
this, but:

...
ERROR: Unable to parse Var <UNSHARE_SUBUID_BASE[:=]>
Traceback (most recent call last):
  File "Var <UNSHARE_SUBUID_BASE[:=]>", line 1, in <module>
  File "/work/build/../isar/meta/classes-global/base.bbclass", line 396, in get_subid_range(idmap='/etc/subuid', d=<bb.data_smart.DataSmart object at 0x7f73357b7110>):
             user, base, cnt = e.split(':')
    >        if user == os.getuid() or user == os.getlogin():
                 return base, cnt
bb.data_smart.ExpansionError: Failure expanding variable UNSHARE_SUBUID_BASE[:=], expression was ${@get_subid_range('/etc/subuid', d)[0]} which triggered exception OSError: [Errno -25] Unknown error -25
The variable dependency chain for the failure is: UNSHARE_SUBUID_BASE[:=]

2026-02-18 19:18:28 - ERROR    - Command "/work/isar/bitbake/bin/bitbake -c build linux-xenomai-3" failed with error 1

I bet you can reproduce with plane Isar and a linux-mailine build as 
well.

Jan
Jan Kiszka Feb. 18, 2026, 6:31 p.m. UTC | #2
On 18.02.26 19:20, Jan Kiszka wrote:
> On 18.02.26 12:58, 'Felix Moessbauer' via isar-users wrote:
>> Dear isar-users,
>>
>> currently isar requires password-less sudo and an environment
>> where mounting file systems is possible. This has proven problematic
>> for security reasons, both when running in a privileged container or
>> locally.
>>
>> To solve this, we implement fully rootless builds that rely on the
>> unshare syscall which allows us to avoid sudo and instead operate in
>> temporary kernel namespaces as a user that is just privileged within
>> that namespace. This comes with some challenges regarding the handling
>> of mounts (they are cleared when leaving the namespace), as well as
>> cross namespace deployments (the outer user might not be able to access
>> the inner data). For that, we rework the handling of mounts and artifact
>> passing to make it compatible with both chroot modes (schroot and
>> unshare).
>>
>> The patches 1-10 align the file permissions of deployments and artifacts
>> to avoid the use of chown (which will not work anymore across uid
>> boundaries). In addition, helpers are introduced to perform privileged
>> operations, which simplifies the migration of existing layers.
>>
>> The patches 11 and 12 introduce the unshare mode, which can be executed
>> as a normal user and does not require root. To enable this mode, set
>> ISAR_ROOTLESS = "1".
>>
>> While the series is by far not complete yet, it already passes the DevTest
>> CI. Know issues are currently:
>>
>> - no support for VM and container images
>> - unprivileged cleanup of the build/tmp dir is non trivial
>> - sporadic issues on partial rebuilds on rootfs_install_sstate_finalize
>> - interfaces between kas and isar need to be defined
>>
>> Note, that this series can be tested on a custom kas-container build
>> provided in [1]. Hints how to migrate downstream layers are provided
>> in the API changelog.
>>
>> [1] https://groups.google.com/g/kas-devel/c/NWQFCU2aUHg
>>
>> Best regards,
>> Felix Moessbauer
>> Siemens AG
>>
>> Felix Moessbauer (12):
>>   refactor bootstrap: store rootfs tar with user permissions
>>   deb-dl-dir: export without root privileges
>>   download debs without locking
>>   introduce wrappers for privileged execution
>>   bootstrap: move cleanup trap to function
>>   rootfs: rework sstate caching of rootfs artifact
>>   rootfs_generate_initramfs: rework deployment to avoid chowning
>>   wic: rework image deploy logic to deploy under correct user
>>   use bitbake function to generate mounting scripts
>>   apt-fetcher: prepare for chroot specific fetching
>>   add support for fully rootless builds
>>   apt-fetcher: implement support for unshare backend
>>
>>  Kconfig                                       |   2 +-
>>  RECIPE-API-CHANGELOG.md                       |  57 +++++
>>  doc/user_manual.md                            |   2 +
>>  meta/classes-global/base.bbclass              |  93 ++++++++
>>  meta/classes-recipe/deb-dl-dir.bbclass        |  20 +-
>>  meta/classes-recipe/dpkg-base.bbclass         |  20 +-
>>  meta/classes-recipe/dpkg-source.bbclass       |   2 +-
>>  meta/classes-recipe/dpkg.bbclass              |  16 +-
>>  .../image-account-extension.bbclass           |   4 +-
>>  .../image-locales-extension.bbclass           |  13 +-
>>  .../image-postproc-extension.bbclass          |  30 +--
>>  .../image-tools-extension.bbclass             |  96 +++++++-
>>  meta/classes-recipe/image.bbclass             |  24 +-
>>  meta/classes-recipe/imagetypes.bbclass        |  47 ++--
>>  .../imagetypes_container.bbclass              |  26 +--
>>  meta/classes-recipe/imagetypes_wic.bbclass    |  12 +-
>>  meta/classes-recipe/rootfs.bbclass            | 221 ++++++++++--------
>>  meta/classes-recipe/sbuild.bbclass            |  37 ++-
>>  meta/classes-recipe/sdk.bbclass               |  23 +-
>>  meta/classes-recipe/squashfs.bbclass          |   2 +-
>>  meta/classes/sbom.bbclass                     |   2 +-
>>  meta/conf/bitbake.conf                        |   7 +-
>>  meta/lib/aptsrc_fetcher.py                    |  90 ++++++-
>>  .../isar-mmdebstrap/isar-mmdebstrap.inc       |  47 ++--
>>  .../sbuild-chroot/sbuild-chroot.inc           |  24 +-
>>  .../unittests/test_image_account_extension.py |   9 +-
>>  26 files changed, 691 insertions(+), 235 deletions(-)
>>
> 
> Hmm, just testing xenomai-images with this and minimal changes for 
> itself (buildsystem update). It seems to build the kernel - put only on 
> a single core. This part looks still fine:
> 
> # $PARALLEL_MAKE
> #   set? /work/build/../isar/meta/conf/bitbake.conf:135
> #     "-j ${@bb.utils.cpu_count()}"
> PARALLEL_MAKE="-j 16"
> 
> But the "-j 16" does not end up in the actually make call of the kernel 
> build. How could we possibly lose this?
> 

FWIW, I'm no longer seeing that PARALLEL_MAKE is even defined inside
sbuild (this is normally logged). Maybe the different sbuild mode needs
a different way of passing env vars in?

Jan

> 
> I wanted to test if rootfull mode with your patches applied may answer 
> this, but:
> 
> ...
> ERROR: Unable to parse Var <UNSHARE_SUBUID_BASE[:=]>
> Traceback (most recent call last):
>   File "Var <UNSHARE_SUBUID_BASE[:=]>", line 1, in <module>
>   File "/work/build/../isar/meta/classes-global/base.bbclass", line 396, in get_subid_range(idmap='/etc/subuid', d=<bb.data_smart.DataSmart object at 0x7f73357b7110>):
>              user, base, cnt = e.split(':')
>     >        if user == os.getuid() or user == os.getlogin():
>                  return base, cnt
> bb.data_smart.ExpansionError: Failure expanding variable UNSHARE_SUBUID_BASE[:=], expression was ${@get_subid_range('/etc/subuid', d)[0]} which triggered exception OSError: [Errno -25] Unknown error -25
> The variable dependency chain for the failure is: UNSHARE_SUBUID_BASE[:=]
> 
> 2026-02-18 19:18:28 - ERROR    - Command "/work/isar/bitbake/bin/bitbake -c build linux-xenomai-3" failed with error 1
> 
> I bet you can reproduce with plane Isar and a linux-mailine build as 
> well.
> 
> Jan
>