From c4e00dc7fc005078f123f218b91649ed36808f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=AA=20de=20Souza=20Pinto?= Date: Fri, 24 Jul 2026 12:16:35 +0200 Subject: [PATCH 1/3] pkg/dom0-ztools: Enable to kill rungetty.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rungetty.sh runs on an infinite loop so it can re-spawn a console shell when exited from getty. However, this makes impossible to disable a console during runtime if device property debug.enable.console is set to false. This script changes to rungetty.sh to trap signal USR1 and kill the current getty process, which will allow stop the console from pillar during runtime. Signed-off-by: Renê de Souza Pinto (cherry picked from commit 81424ce36459787addbf2c38e0fe7a7796ca08bc) --- pkg/dom0-ztools/rootfs/usr/bin/rungetty.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/dom0-ztools/rootfs/usr/bin/rungetty.sh b/pkg/dom0-ztools/rootfs/usr/bin/rungetty.sh index 0525b3cc239..042a8f81e09 100755 --- a/pkg/dom0-ztools/rootfs/usr/bin/rungetty.sh +++ b/pkg/dom0-ztools/rootfs/usr/bin/rungetty.sh @@ -1,8 +1,13 @@ #!/bin/sh infinite_loop() { - while true; do - $@ + stop=0 + child="" + trap 'stop=1; [ -n "$child" ] && kill $child 2> /dev/null' USR1 + while [ "$stop" -eq 0 ]; do + $@ & + child=$! + wait "$child" done } From c20e32edb1a1223b4e0702729d72781f7cbfd47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=AA=20de=20Souza=20Pinto?= Date: Wed, 22 Jul 2026 12:34:10 +0200 Subject: [PATCH 2/3] pillar: Implement console disabling during runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pillar starts on a fresh boot with USB, VGA and console enabled. This isn't an issue if no serial consoles are present in the cmdline because for video terminals, the TUI + VGA + usb inputs can be disabled during runtime. So as soon as pillar gets the global configuration from the controller, it can disabled all of them. However, if any serial console is present at the cmdline, like console=ttyAMA0, pillar will start getty on that console through the rungetty.sh script, which spawns a getty process on every console from /proc/cmdline. The script use to run a infinte loop, so even if pillar killed the getty process, it would be restarted again. The behavior of rungetty.sh was changed so it really stops getty if it receives a USR1 signal. This commit implements the stopGetty() to send the signal and really stop the console, allowing disabling serial consoles during runtime if "debug.enable.console" is set to false. Signed-off-by: Renê de Souza Pinto (cherry picked from commit 07f9fc59e2052ee8e5efce0b54d46944dc073cc7) --- pkg/pillar/cmd/domainmgr/domainmgr.go | 38 +++++++++++++++++++++++-- pkg/pillar/cmd/domainmgr/handlegetty.go | 32 +++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/pkg/pillar/cmd/domainmgr/domainmgr.go b/pkg/pillar/cmd/domainmgr/domainmgr.go index de81e034f9e..581489ef95e 100644 --- a/pkg/pillar/cmd/domainmgr/domainmgr.go +++ b/pkg/pillar/cmd/domainmgr/domainmgr.go @@ -495,8 +495,9 @@ func Run(ps *pubsub.PubSub, loggerArg *logrus.Logger, logArg *base.LogObject, ar if !domainCtx.setInitialConsoleAccess { log.Functionf("GCComplete but not setInitialConsoleAccess => first boot") - // Enable Console - domainCtx.consoleAccess = true + // Auto-enable the console only while the device is not yet + // onboarded to a controller. + domainCtx.consoleAccess = !isDeviceOnboarded(ps) updateConsoleAccess(&domainCtx) domainCtx.setInitialConsoleAccess = true } @@ -3671,10 +3672,41 @@ func updateVgaAccess(ctx *domainContext) { func updateConsoleAccess(ctx *domainContext) { log.Functionf("updateConsoleAccess(%t)", ctx.consoleAccess) - // FIXME: explore the way to stop getty/login if ctx.consoleAccess { startGetty(log) + } else { + stopGetty(log) + } +} + +// isDeviceOnboarded reports whether the device has already been onboarded to a +// controller. +func isDeviceOnboarded(ps *pubsub.PubSub) bool { + sub, err := ps.NewSubscription(pubsub.SubscriptionOptions{ + AgentName: "zedclient", + MyAgentName: agentName, + TopicImpl: types.OnboardingStatus{}, + Persistent: true, + Activate: false, + }) + if err != nil { + log.Errorf("isDeviceOnboarded: subscription failed: %v", err) + return false + } + defer sub.Close() + // Activate() populates a persistent subscription synchronously from the + // on-disk JSON, so GetAll() below observes the persisted status. + if err := sub.Activate(); err != nil { + log.Errorf("isDeviceOnboarded: activate failed: %v", err) + return false + } + for _, st := range sub.GetAll() { + if status, ok := st.(types.OnboardingStatus); ok && + status.DeviceUUID != nilUUID { + return true + } } + return false } // Track which ones of these are loaded diff --git a/pkg/pillar/cmd/domainmgr/handlegetty.go b/pkg/pillar/cmd/domainmgr/handlegetty.go index 71079396ad6..eb6ce200581 100644 --- a/pkg/pillar/cmd/domainmgr/handlegetty.go +++ b/pkg/pillar/cmd/domainmgr/handlegetty.go @@ -7,8 +7,10 @@ import ( "os" "os/exec" "strings" + "syscall" "github.com/lf-edge/eve/pkg/pillar/base" + "github.com/shirou/gopsutil/process" ) // cmdlineGettyFlag should be aligned with grub.cfg in grub and 001-getty in dom0-ztools @@ -51,3 +53,33 @@ func startGetty(log *base.LogObject) { log.Noticeln("getty started") gettyStarted = true } + +func stopGetty(log *base.LogObject) { + if !gettyStarted { + return + } + if hasInitGettyStarted(log) { + log.Noticeln("Not killing getty because it was started in init") + return + } + + // Find and send USR1 signal to all rungetty.sh processes + procs, err := process.Processes() + if err != nil { + log.Errorf("Cannot list processes: %v", err) + return + } + for _, p := range procs { + cmdline, _ := p.Cmdline() + if strings.Contains(cmdline, "rungetty.sh") { + proc, err := os.FindProcess(int(p.Pid)) + if err != nil { + continue + } + if err := proc.Signal(syscall.SIGUSR1); err != nil { + log.Errorf("Failed to signal pid %d: %v", p.Pid, err) + } + } + } + gettyStarted = false +} From a4452a17a75ec966d6fac5d7147f89982c3a8b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=AA=20de=20Souza=20Pinto?= Date: Mon, 3 Aug 2026 15:19:23 +0200 Subject: [PATCH 3/3] Update hash for dom0-ztools package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest version of dom0-ztools in the following packages: - pkg/pillar - pkg/vtpm Signed-off-by: Renê de Souza Pinto --- pkg/pillar/Dockerfile | 2 +- pkg/vtpm/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/pillar/Dockerfile b/pkg/pillar/Dockerfile index 69b256aa2b0..84e09a13ece 100644 --- a/pkg/pillar/Dockerfile +++ b/pkg/pillar/Dockerfile @@ -11,7 +11,7 @@ ARG BUILD_PKGS_BASE="git gcc linux-headers libc-dev make linux-pam-dev m4 findut ARG EVE_ALPINE_IMAGE=lfedge/eve-alpine:745ae9066273c73b0fd879c4ba4ff626a8392d04 FROM lfedge/eve-uefi:b3ef9ca37c99439c776673aeba83c52ea8b84626 AS uefi-build -FROM lfedge/eve-dom0-ztools:728e9ccb619ccc27368fa93c7121200d85a81f88 AS zfs +FROM lfedge/eve-dom0-ztools:5260091b794f9466d08cb33b8c613a6a8398c16a AS zfs RUN mkdir /out # copy zfs-related files from dom0-ztools using prepared list of files RUN while read -r x; do \ diff --git a/pkg/vtpm/Dockerfile b/pkg/vtpm/Dockerfile index f3eaaaa2e07..434ab884c34 100644 --- a/pkg/vtpm/Dockerfile +++ b/pkg/vtpm/Dockerfile @@ -3,7 +3,7 @@ # Copyright (c) 2023-2025 Zededa, Inc. # SPDX-License-Identifier: Apache-2.0 -FROM lfedge/eve-dom0-ztools:728e9ccb619ccc27368fa93c7121200d85a81f88 AS dom0 +FROM lfedge/eve-dom0-ztools:5260091b794f9466d08cb33b8c613a6a8398c16a AS dom0 FROM lfedge/eve-alpine:745ae9066273c73b0fd879c4ba4ff626a8392d04 AS build ENV BUILD_PKGS="gcc g++ autoconf automake libtool make openssl-dev libtasn1-dev \ json-glib-dev gnutls bash expect gawk socat libseccomp-dev gmp-dev \