diff mbox series

[2/6,v3] package/skeleton-systemd: systemd-ify mounting /var tmpfs with ro rootfs

Message ID 27491_1666122194_634F01D2_27491_495_1_cf89a104edc507c063e6f4716cc859891b489d27.1666122184.git.yann.morin@orange.com
State Accepted
Headers show
Series [1/6,v3] package/skeleton-systemd: move /var factory tmpfiles out of /etc | expand

Commit Message

Yann E. MORIN Oct. 18, 2022, 7:43 p.m. UTC
To mount our /var tmpfs when the rootfs is mounted read-only (really,
not remounted reqd-write), we use an entry in fstab.

However, /etc could also be a tmpfs (for full state-less systems, or
easy factory-reset, see [0]). It also prevents easily ordeting other
systemd units until after /var is mounted 5not impossible, but less
easy).

So, we register /var as a systemd mount unit, so that we can also have
the /var factory populated and functional even when /etc is empty. The
var.mount unit is heavily modelled after systemd's own tmp.mount one, so
we carry the same license for that file (in case that may apply). We add
an explicit reverse dependency to systemd-tmpfiles-setup.service, to
ensure /var is mounted before we try to populate it.

This has two side effects:
  - as hinted previously, it simplifies writing other systemd units to
    order them after /var is mounted
  - replace it with their own, which mounts an actual filesystem

[0] http://0pointer.de/blog/projects/stateless.html

Signed-off-by: Yann E. MORIN <yann.morin@orange.com>
Cc: Norbert Lange <nolange79@gmail.com>
Cc: Romain Naour <romain.naour@smile.fr>
Cc: Jérémy Rosen <jeremy.rosen@smile.fr>
[yann.morin.1998@free.fr:
  - split original patch in two
  - this one only handles converting /var mounting into a systemd unit
  - adapt commit log accordingly
]
Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
---
 .../skeleton-init-systemd.mk                   |  3 ++-
 package/skeleton-init-systemd/var.mount        | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 package/skeleton-init-systemd/var.mount

Comments

Norbert Lange Nov. 6, 2022, 3:56 p.m. UTC | #1
Am Di., 18. Okt. 2022 um 21:43 Uhr schrieb <yann.morin@orange.com>:
>
> To mount our /var tmpfs when the rootfs is mounted read-only (really,
> not remounted reqd-write), we use an entry in fstab.
>
> However, /etc could also be a tmpfs (for full state-less systems, or
> easy factory-reset, see [0]). It also prevents easily ordeting other
> systemd units until after /var is mounted 5not impossible, but less
> easy).
>
> So, we register /var as a systemd mount unit, so that we can also have
> the /var factory populated and functional even when /etc is empty. The
> var.mount unit is heavily modelled after systemd's own tmp.mount one, so
> we carry the same license for that file (in case that may apply). We add
> an explicit reverse dependency to systemd-tmpfiles-setup.service, to
> ensure /var is mounted before we try to populate it.
>
> This has two side effects:
>   - as hinted previously, it simplifies writing other systemd units to
>     order them after /var is mounted
>   - replace it with their own, which mounts an actual filesystem
>
> [0] http://0pointer.de/blog/projects/stateless.html
>
> Signed-off-by: Yann E. MORIN <yann.morin@orange.com>
> Cc: Norbert Lange <nolange79@gmail.com>
> Cc: Romain Naour <romain.naour@smile.fr>
> Cc: Jérémy Rosen <jeremy.rosen@smile.fr>
> [yann.morin.1998@free.fr:
>   - split original patch in two
>   - this one only handles converting /var mounting into a systemd unit
>   - adapt commit log accordingly
> ]
> Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
> ---
>  .../skeleton-init-systemd.mk                   |  3 ++-
>  package/skeleton-init-systemd/var.mount        | 18 ++++++++++++++++++
>  2 files changed, 20 insertions(+), 1 deletion(-)
>  create mode 100644 package/skeleton-init-systemd/var.mount
>
> diff --git a/package/skeleton-init-systemd/skeleton-init-systemd.mk b/package/skeleton-init-systemd/skeleton-init-systemd.mk
> index 7b66732ef4..970951d553 100644
> --- a/package/skeleton-init-systemd/skeleton-init-systemd.mk
> +++ b/package/skeleton-init-systemd/skeleton-init-systemd.mk
> @@ -30,7 +30,6 @@ else
>  # back there by the tmpfiles.d mechanism.
>  define SKELETON_INIT_SYSTEMD_ROOT_RO_OR_RW
>         echo "/dev/root / auto ro 0 1" >$(TARGET_DIR)/etc/fstab
> -       echo "tmpfs /var tmpfs mode=1777 0 0" >>$(TARGET_DIR)/etc/fstab
>  endef
>
>  define SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
> @@ -52,6 +51,8 @@ define SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
>                         || exit 1; \
>                 fi; \
>         done >$(TARGET_DIR)/usr/lib/tmpfiles.d/buildroot-factory.conf
> +       $(INSTALL) -D -m 0644 $(SKELETON_INIT_SYSTEMD_PKGDIR)/var.mount \
> +               $(TARGET_DIR)/usr/lib/systemd/system/var.mount
>  endef
>  SKELETON_INIT_SYSTEMD_ROOTFS_PRE_CMD_HOOKS += SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
>
> diff --git a/package/skeleton-init-systemd/var.mount b/package/skeleton-init-systemd/var.mount
> new file mode 100644
> index 0000000000..6b165dff6d
> --- /dev/null
> +++ b/package/skeleton-init-systemd/var.mount
> @@ -0,0 +1,18 @@
> +# SPDX-License-Identifier: LGPL-2.1-or-later
> +# Modelled after systemd's tmp.mount
> +
> +[Unit]
> +Description=Buildroot /var tmpfs
> +DefaultDependencies=no
> +Conflicts=umount.target
> +Before=basic.target local-fs.target umount.target systemd-tmpfiles-setup.service

Change it to
Before=local-fs.target umount.target

All other dependencies are implicit

> +After=swap.target
> +
> +[Mount]
> +What=tmpfs
> +Where=/var
> +Type=tmpfs
> +Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
> +
> +[Install]
> +WantedBy=basic.target

Drop the install section.

While testing some other overlay solutions I found out that
a /var mount cant be reasonably disabled.
What happens is that basic.target will pull in var.mount,
the only option to disable it would be masking var.mount


> --
> 2.25.1
>
>
> _________________________________________________________________________________________________________________________
>
> Ce message et ses pieces jointes peuvent contenir des informations confidentielles ou privilegiees et ne doivent donc
> pas etre diffuses, exploites ou copies sans autorisation. Si vous avez recu ce message par erreur, veuillez le signaler
> a l'expediteur et le detruire ainsi que les pieces jointes. Les messages electroniques etant susceptibles d'alteration,
> Orange decline toute responsabilite si ce message a ete altere, deforme ou falsifie. Merci.
>
> This message and its attachments may contain confidential or privileged information that may be protected by law;
> they should not be distributed, used or copied without authorisation.
> If you have received this email in error, please notify the sender and delete this message and its attachments.
> As emails may be altered, Orange is not liable for messages that have been modified, changed or falsified.
> Thank you.
>

Guess i cant ack it conditionally, so far:

Reviewed-by: Norbert Lange <nolange79@gmail.com>
Yann E. MORIN Nov. 6, 2022, 4:26 p.m. UTC | #2
Norbert, All,

Thanks for the feedback!

On 2022-11-06 16:56 +0100, Norbert Lange spake thusly:
> Am Di., 18. Okt. 2022 um 21:43 Uhr schrieb <yann.morin@orange.com>:
[--SNIP--]
> > diff --git a/package/skeleton-init-systemd/var.mount b/package/skeleton-init-systemd/var.mount
> > new file mode 100644
> > index 0000000000..6b165dff6d
> > --- /dev/null
> > +++ b/package/skeleton-init-systemd/var.mount
> > @@ -0,0 +1,18 @@
> > +# SPDX-License-Identifier: LGPL-2.1-or-later
> > +# Modelled after systemd's tmp.mount
> > +
> > +[Unit]
> > +Description=Buildroot /var tmpfs
> > +DefaultDependencies=no
> > +Conflicts=umount.target
> > +Before=basic.target local-fs.target umount.target systemd-tmpfiles-setup.service
> 
> Change it to
> Before=local-fs.target umount.target
> 
> All other dependencies are implicit

I looked at bootup(7) (thanks for the pointer!), and it seems that
tmpfiles is on a different synchronisation path (elided for brevity):

            (various low-level  (various mounts and
             services: udevd,    fsck services...)
             tmpfiles, random            |
    .    .   seed, sysctl, ...)          v           .
    .    .      |                 local-fs.target    .
    |    |      |                        |           |
    \____|______|_______________   ______|___________/
                                \ /
                                 v
                          sysinit.target

So, if we want tmpfiles to populate /var, we need to mount /var before
tmpfiles are run, so we need it in the Before section.

I suspect that this should also consistent with the other unit about the
overlayfs; we probably want the same Before for both, no?

> > +After=swap.target
> > +
> > +[Mount]
> > +What=tmpfs
> > +Where=/var
> > +Type=tmpfs
> > +Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
> > +
> > +[Install]
> > +WantedBy=basic.target
> 
> Drop the install section.

Then, how do we ensure the unit is enabled and active?

I guess however that this should be consistent between this unit and the
one about the overlayfs.

> While testing some other overlay solutions I found out that
> a /var mount cant be reasonably disabled.

Do you meant that the following preset:

    disable var.mount

would not be enough to prevent our unit from being acted on?

Also, see below...

> What happens is that basic.target will pull in var.mount,

Ah, so it is implicit that basic.target pulls in mount units? Or is
var.mount somehow special?

Also, why "basic.target", when bootup(7) shows that the first sync point
by which filesystems are supposed to be mounted, is sysinit.target?

> the only option to disable it would be masking var.mount

In this case, people who would mask var.mount would rather need to
override it to mount an actual device arther than a tmpfs, no?

Also, since mount units must be named after their mount point, users who
want to mount their own device would have to provide a unit named
var.mount, so they can't disable it.

Finally, usetrs who have custom dispositions (like an initramfs that
mounts /var) can just remove the unit with a post-build script.

> Guess i cant ack it conditionally, so far:
> 
> Reviewed-by: Norbert Lange <nolange79@gmail.com>

Thanks! I'll add it when I respin with your suggestions.

Regards,
Yann E. MORIN.
Norbert Lange Nov. 6, 2022, 4:41 p.m. UTC | #3
Am So., 6. Nov. 2022 um 17:26 Uhr schrieb Yann E. MORIN
<yann.morin.1998@free.fr>:
>
> Norbert, All,
>
> Thanks for the feedback!
>
> On 2022-11-06 16:56 +0100, Norbert Lange spake thusly:
> > Am Di., 18. Okt. 2022 um 21:43 Uhr schrieb <yann.morin@orange.com>:
> [--SNIP--]
> > > diff --git a/package/skeleton-init-systemd/var.mount b/package/skeleton-init-systemd/var.mount
> > > new file mode 100644
> > > index 0000000000..6b165dff6d
> > > --- /dev/null
> > > +++ b/package/skeleton-init-systemd/var.mount
> > > @@ -0,0 +1,18 @@
> > > +# SPDX-License-Identifier: LGPL-2.1-or-later
> > > +# Modelled after systemd's tmp.mount
> > > +
> > > +[Unit]
> > > +Description=Buildroot /var tmpfs
> > > +DefaultDependencies=no
> > > +Conflicts=umount.target
> > > +Before=basic.target local-fs.target umount.target systemd-tmpfiles-setup.service
> >
> > Change it to
> > Before=local-fs.target umount.target
> >
> > All other dependencies are implicit
>
> I looked at bootup(7) (thanks for the pointer!), and it seems that
> tmpfiles is on a different synchronisation path (elided for brevity):
>
>             (various low-level  (various mounts and
>              services: udevd,    fsck services...)
>              tmpfiles, random            |
>     .    .   seed, sysctl, ...)          v           .
>     .    .      |                 local-fs.target    .
>     |    |      |                        |           |
>     \____|______|_______________   ______|___________/
>                                 \ /
>                                  v
>                           sysinit.target
>
> So, if we want tmpfiles to populate /var, we need to mount /var before
> tmpfiles are run, so we need it in the Before section.

you should keep the dependency lists as short as possible

var.mount is ordered before local-fs.target which is ordered before
systemd-tmpfiles-setup.service.
(that makes it transitive, not implicit, by bad)

(its also sorted before basic.target, see below)

>
> I suspect that this should also consistent with the other unit about the
> overlayfs; we probably want the same Before for both, no?
>
> > > +After=swap.target
> > > +
> > > +[Mount]
> > > +What=tmpfs
> > > +Where=/var
> > > +Type=tmpfs
> > > +Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
> > > +
> > > +[Install]
> > > +WantedBy=basic.target
> >
> > Drop the install section.
>
> Then, how do we ensure the unit is enabled and active?
>
> I guess however that this should be consistent between this unit and the
> one about the overlayfs.
>
> > While testing some other overlay solutions I found out that
> > a /var mount cant be reasonably disabled.
>
> Do you meant that the following preset:
>
>     disable var.mount
>
> would not be enough to prevent our unit from being acted on?

Yes

>
> Also, see below...
>
> > What happens is that basic.target will pull in var.mount,
>
> Ah, so it is implicit that basic.target pulls in mount units? Or is
> var.mount somehow special?

basic.target is special, enabled and orders var.mount before itself with:

RequiresMountsFor=/var /var/tmp

>
> Also, why "basic.target", when bootup(7) shows that the first sync point
> by which filesystems are supposed to be mounted, is sysinit.target?

there is order and there is enablement. basic.target enables var.mount,
but if enabled earlier services might be ordered around var.mount.

>
> > the only option to disable it would be masking var.mount
>
> In this case, people who would mask var.mount would rather need to
> override it to mount an actual device arther than a tmpfs, no?

Depends on what they want to do with it, hope they know.
(there are valid reasons for it)

>
> Also, since mount units must be named after their mount point, users who
> want to mount their own device would have to provide a unit named
> var.mount, so they can't disable it.

yes, or add an override. But are we still here in the
"buildroot should care about that" category?

As you might know, I do that kinda stuff within an initramfs.

>
> Finally, usetrs who have custom dispositions (like an initramfs that
> mounts /var) can just remove the unit with a post-build script.

then why enable it in buildroot in the first place?

>
> > Guess i cant ack it conditionally, so far:
> >
> > Reviewed-by: Norbert Lange <nolange79@gmail.com>
>
> Thanks! I'll add it when I respin with your suggestions.
>
> Regards,
> Yann E. MORIN.
>
> --
> .-----------------.--------------------.------------------.--------------------.
> |  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
> | +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
> | +33 561 099 427 `------------.-------:  X  AGAINST      |  \e/  There is no  |
> | http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |
> '------------------------------^-------^------------------^--------------------'

Regards, Norbert
Yann E. MORIN Dec. 21, 2022, 9:17 p.m. UTC | #4
Yann, All,

On 2022-10-18 21:43 +0200, yann.morin@orange.com spake thusly:
> To mount our /var tmpfs when the rootfs is mounted read-only (really,
> not remounted reqd-write), we use an entry in fstab.
> 
> However, /etc could also be a tmpfs (for full state-less systems, or
> easy factory-reset, see [0]). It also prevents easily ordeting other
> systemd units until after /var is mounted 5not impossible, but less
> easy).
> 
> So, we register /var as a systemd mount unit, so that we can also have
> the /var factory populated and functional even when /etc is empty. The
> var.mount unit is heavily modelled after systemd's own tmp.mount one, so
> we carry the same license for that file (in case that may apply). We add
> an explicit reverse dependency to systemd-tmpfiles-setup.service, to
> ensure /var is mounted before we try to populate it.
> 
> This has two side effects:
>   - as hinted previously, it simplifies writing other systemd units to
>     order them after /var is mounted
>   - replace it with their own, which mounts an actual filesystem
> 
> [0] http://0pointer.de/blog/projects/stateless.html
> 
> Signed-off-by: Yann E. MORIN <yann.morin@orange.com>
> Cc: Norbert Lange <nolange79@gmail.com>
> Cc: Romain Naour <romain.naour@smile.fr>
> Cc: Jérémy Rosen <jeremy.rosen@smile.fr>
> [yann.morin.1998@free.fr:
>   - split original patch in two
>   - this one only handles converting /var mounting into a systemd unit
>   - adapt commit log accordingly
> ]
> Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>

Applied to master with the tweaks suggested by Norbert, thanks.

Regards,
Yann E. MORIN.

> ---
>  .../skeleton-init-systemd.mk                   |  3 ++-
>  package/skeleton-init-systemd/var.mount        | 18 ++++++++++++++++++
>  2 files changed, 20 insertions(+), 1 deletion(-)
>  create mode 100644 package/skeleton-init-systemd/var.mount
> 
> diff --git a/package/skeleton-init-systemd/skeleton-init-systemd.mk b/package/skeleton-init-systemd/skeleton-init-systemd.mk
> index 7b66732ef4..970951d553 100644
> --- a/package/skeleton-init-systemd/skeleton-init-systemd.mk
> +++ b/package/skeleton-init-systemd/skeleton-init-systemd.mk
> @@ -30,7 +30,6 @@ else
>  # back there by the tmpfiles.d mechanism.
>  define SKELETON_INIT_SYSTEMD_ROOT_RO_OR_RW
>  	echo "/dev/root / auto ro 0 1" >$(TARGET_DIR)/etc/fstab
> -	echo "tmpfs /var tmpfs mode=1777 0 0" >>$(TARGET_DIR)/etc/fstab
>  endef
>  
>  define SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
> @@ -52,6 +51,8 @@ define SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
>  			|| exit 1; \
>  		fi; \
>  	done >$(TARGET_DIR)/usr/lib/tmpfiles.d/buildroot-factory.conf
> +	$(INSTALL) -D -m 0644 $(SKELETON_INIT_SYSTEMD_PKGDIR)/var.mount \
> +		$(TARGET_DIR)/usr/lib/systemd/system/var.mount
>  endef
>  SKELETON_INIT_SYSTEMD_ROOTFS_PRE_CMD_HOOKS += SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
>  
> diff --git a/package/skeleton-init-systemd/var.mount b/package/skeleton-init-systemd/var.mount
> new file mode 100644
> index 0000000000..6b165dff6d
> --- /dev/null
> +++ b/package/skeleton-init-systemd/var.mount
> @@ -0,0 +1,18 @@
> +# SPDX-License-Identifier: LGPL-2.1-or-later
> +# Modelled after systemd's tmp.mount
> +
> +[Unit]
> +Description=Buildroot /var tmpfs
> +DefaultDependencies=no
> +Conflicts=umount.target
> +Before=basic.target local-fs.target umount.target systemd-tmpfiles-setup.service
> +After=swap.target
> +
> +[Mount]
> +What=tmpfs
> +Where=/var
> +Type=tmpfs
> +Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
> +
> +[Install]
> +WantedBy=basic.target
> -- 
> 2.25.1
> 
> 
> _________________________________________________________________________________________________________________________
> 
> Ce message et ses pieces jointes peuvent contenir des informations confidentielles ou privilegiees et ne doivent donc
> pas etre diffuses, exploites ou copies sans autorisation. Si vous avez recu ce message par erreur, veuillez le signaler
> a l'expediteur et le detruire ainsi que les pieces jointes. Les messages electroniques etant susceptibles d'alteration,
> Orange decline toute responsabilite si ce message a ete altere, deforme ou falsifie. Merci.
> 
> This message and its attachments may contain confidential or privileged information that may be protected by law;
> they should not be distributed, used or copied without authorisation.
> If you have received this email in error, please notify the sender and delete this message and its attachments.
> As emails may be altered, Orange is not liable for messages that have been modified, changed or falsified.
> Thank you.
> 
> _______________________________________________
> buildroot mailing list
> buildroot@buildroot.org
> https://lists.buildroot.org/mailman/listinfo/buildroot
diff mbox series

Patch

diff --git a/package/skeleton-init-systemd/skeleton-init-systemd.mk b/package/skeleton-init-systemd/skeleton-init-systemd.mk
index 7b66732ef4..970951d553 100644
--- a/package/skeleton-init-systemd/skeleton-init-systemd.mk
+++ b/package/skeleton-init-systemd/skeleton-init-systemd.mk
@@ -30,7 +30,6 @@  else
 # back there by the tmpfiles.d mechanism.
 define SKELETON_INIT_SYSTEMD_ROOT_RO_OR_RW
 	echo "/dev/root / auto ro 0 1" >$(TARGET_DIR)/etc/fstab
-	echo "tmpfs /var tmpfs mode=1777 0 0" >>$(TARGET_DIR)/etc/fstab
 endef
 
 define SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
@@ -52,6 +51,8 @@  define SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
 			|| exit 1; \
 		fi; \
 	done >$(TARGET_DIR)/usr/lib/tmpfiles.d/buildroot-factory.conf
+	$(INSTALL) -D -m 0644 $(SKELETON_INIT_SYSTEMD_PKGDIR)/var.mount \
+		$(TARGET_DIR)/usr/lib/systemd/system/var.mount
 endef
 SKELETON_INIT_SYSTEMD_ROOTFS_PRE_CMD_HOOKS += SKELETON_INIT_SYSTEMD_PRE_ROOTFS_VAR
 
diff --git a/package/skeleton-init-systemd/var.mount b/package/skeleton-init-systemd/var.mount
new file mode 100644
index 0000000000..6b165dff6d
--- /dev/null
+++ b/package/skeleton-init-systemd/var.mount
@@ -0,0 +1,18 @@ 
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# Modelled after systemd's tmp.mount
+
+[Unit]
+Description=Buildroot /var tmpfs
+DefaultDependencies=no
+Conflicts=umount.target
+Before=basic.target local-fs.target umount.target systemd-tmpfiles-setup.service
+After=swap.target
+
+[Mount]
+What=tmpfs
+Where=/var
+Type=tmpfs
+Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
+
+[Install]
+WantedBy=basic.target