From 8edd5273ce090b31d6a819c6338ae87df225e978 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sat, 30 Aug 2025 21:15:38 +0200 Subject: [PATCH 1/6] openrc-run.sh: fix cgroup permission check --- sh/openrc-run.sh.in | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/sh/openrc-run.sh.in b/sh/openrc-run.sh.in index af64024cb..a3144b0d3 100644 --- a/sh/openrc-run.sh.in +++ b/sh/openrc-run.sh.in @@ -280,19 +280,11 @@ status|describe) ;; [ -n "${rc_ulimit:-$RC_ULIMIT}" ] && apply_ulimits ${rc_ulimit:-$RC_ULIMIT} # Apply cgroups settings if defined - if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]; then - if grep -qs /sys/fs/cgroup /proc/1/mountinfo - then - if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then - eerror "No permission to apply cgroup settings" - break - fi - fi - cgroup_add_service + if grep -qs /sys/fs/cgroup /proc/1/mountinfo && [ -d /sys/fs/cgroup ] && [ -w /sys/fs/cgroup ]; then + { cgroup_add_service && cgroup_set_limits && cgroup2_set_limits; } 2>/dev/null + else + eerror "No permission to apply cgroup settings" fi - - [ "$(command -v cgroup_set_limits)" = "cgroup_set_limits" ] && cgroup_set_limits - [ "$(command -v cgroup2_set_limits)" = "cgroup2_set_limits" ] && cgroup2_set_limits ;; esac From fed898dc6f04ef13729713eceb7b148bdd31f0b6 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sat, 12 Apr 2025 21:07:31 +0200 Subject: [PATCH 2/6] rc: don't run tests on pushed to non-master branches --- .github/workflows/ci-alpine-linux.yml | 6 +++++- .github/workflows/ci-ubuntu.yml | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-alpine-linux.yml b/.github/workflows/ci-alpine-linux.yml index e50c97653..485e21718 100644 --- a/.github/workflows/ci-alpine-linux.yml +++ b/.github/workflows/ci-alpine-linux.yml @@ -1,6 +1,10 @@ name: ci_alpine_linux -on: [push, pull_request] +on: + push: + branches: [master] + pull_request: + branches: [master] jobs: diff --git a/.github/workflows/ci-ubuntu.yml b/.github/workflows/ci-ubuntu.yml index 401b5f6b4..ab0110e3b 100644 --- a/.github/workflows/ci-ubuntu.yml +++ b/.github/workflows/ci-ubuntu.yml @@ -1,6 +1,10 @@ name: ci_ubuntu -on: [push, pull_request] +on: + push: + branches: [master] + pull_request: + branches: [master] jobs: From f1ae263090b2d531b8998fbc9447d698f5eea849 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sat, 30 Aug 2025 21:10:02 +0200 Subject: [PATCH 3/6] librc-depend: allow overriding gendepends.sh from rc_svcdir --- src/librc/librc-depend.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index c7ef4dcd8..ea3aa7f42 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -790,11 +790,18 @@ rc_deptree_update(void) size_t i, l; bool retval = true; const char *sys = rc_sys(); + char *gendep; int serrno; /* Phase 1 - source all init scripts and print dependencies */ setup_environment(); - if (!(fp = popen(GENDEP, "r"))) + xasprintf(&gendep, "%s/gendepends.sh", rc_svcdir()); + if (access(gendep, F_OK) == 0) + fp = popen(gendep, "r"); + else + fp = popen(GENDEP, "r"); + + if (!fp) return false; config = rc_stringlist_new(); From 59e686da02b4bbd7e7cd6abd0f0074179976ae00 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sat, 6 Dec 2025 19:56:29 +0100 Subject: [PATCH 4/6] shared/misc: allow RC_SVCDIR and RC_PATH in the env_allowlist --- src/shared/misc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/misc.c b/src/shared/misc.c index 50e436105..ab43c2149 100644 --- a/src/shared/misc.c +++ b/src/shared/misc.c @@ -60,6 +60,7 @@ static const char *const env_allowlist[] = { "EERROR_QUIET", "EINFO_QUIET", "IN_BACKGROUND", "IN_DRYRUN", "IN_HOTPLUG", "RC_DEBUG", "RC_NODEPS", "RC_USER_SERVICES", + "RC_SVCDIR", "RC_PATH", "LANG", "LC_MESSAGES", "TERM", "EINFO_COLOR", "EINFO_VERBOSE", NULL From b39a0127ab706d6d52b1291309df324e6b23fcad Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sun, 31 Aug 2025 01:39:52 +0200 Subject: [PATCH 5/6] openrc-run.sh: use RC_LIBEXECDIR from the environment --- sh/openrc-run.sh.in | 14 +++++++------- src/shared/misc.c | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/sh/openrc-run.sh.in b/sh/openrc-run.sh.in index a3144b0d3..2429ed1c7 100644 --- a/sh/openrc-run.sh.in +++ b/sh/openrc-run.sh.in @@ -53,11 +53,11 @@ apply_ulimits() done } -sourcex "@LIBEXECDIR@/sh/functions.sh" -sourcex "@LIBEXECDIR@/sh/rc-functions.sh" +sourcex "$RC_LIBEXECDIR/sh/functions.sh" +sourcex "$RC_LIBEXECDIR/sh/rc-functions.sh" case $RC_SYS in PREFIX|SYSTEMD-NSPAWN) ;; - *) yesno "$RC_USER_SERVICES" || sourcex -e "@LIBEXECDIR@/sh/rc-cgroup.sh";; + *) yesno "$RC_USER_SERVICES" || sourcex -e "$RC_LIBEXECDIR/sh/rc-cgroup.sh";; esac # Support LiveCD foo @@ -259,10 +259,10 @@ done unset _c _f _conf_d # load service supervisor functions -sourcex "@LIBEXECDIR@/sh/runit.sh" -sourcex "@LIBEXECDIR@/sh/s6.sh" -sourcex "@LIBEXECDIR@/sh/start-stop-daemon.sh" -sourcex "@LIBEXECDIR@/sh/supervise-daemon.sh" +sourcex "$RC_LIBEXECDIR/sh/runit.sh" +sourcex "$RC_LIBEXECDIR/sh/s6.sh" +sourcex "$RC_LIBEXECDIR/sh/start-stop-daemon.sh" +sourcex "$RC_LIBEXECDIR/sh/supervise-daemon.sh" # Load our script sourcex "$RC_SERVICE" diff --git a/src/shared/misc.c b/src/shared/misc.c index ab43c2149..c247f70dd 100644 --- a/src/shared/misc.c +++ b/src/shared/misc.c @@ -60,7 +60,7 @@ static const char *const env_allowlist[] = { "EERROR_QUIET", "EINFO_QUIET", "IN_BACKGROUND", "IN_DRYRUN", "IN_HOTPLUG", "RC_DEBUG", "RC_NODEPS", "RC_USER_SERVICES", - "RC_SVCDIR", "RC_PATH", + "RC_SVCDIR", "RC_PATH", "RC_LIBEXECDIR", "LANG", "LC_MESSAGES", "TERM", "EINFO_COLOR", "EINFO_VERBOSE", NULL @@ -218,11 +218,13 @@ env_config(void) free(cachedir); } + e = getenv("RC_LIBEXECDIR"); + setenv("RC_LIBEXECDIR", e ? e : RC_LIBEXECDIR, 1); + xasprintf(&tmpdir, "%s/tmp", svcdir); e = rc_runlevel_get(); setenv("RC_VERSION", VERSION, 1); - setenv("RC_LIBEXECDIR", RC_LIBEXECDIR, 1); setenv("RC_SVCDIR", svcdir, 1); setenv("RC_TMPDIR", tmpdir, 1); setenv("RC_BOOTLEVEL", RC_LEVEL_BOOT, 1); From 50e420d5f6c2e220428a2512b7f42c6a10650e79 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sat, 30 Aug 2025 21:14:24 +0200 Subject: [PATCH 6/6] tests: add basic rc-service tests --- sh/meson.build | 16 ++++---- src/openrc-run/meson.build | 2 +- src/rc-service/meson.build | 2 +- test/units/meson.build | 12 +++--- test/units/rc-service.sh | 72 +++++++++++++++++++++++++++++++++++ test/units/rc-update.sh | 77 ++++++++++++++++++++++++++++++++++++++ test/units/setup-root.sh | 28 ++++++++++++++ 7 files changed, 195 insertions(+), 14 deletions(-) create mode 100755 test/units/rc-service.sh create mode 100755 test/units/rc-update.sh create mode 100755 test/units/setup-root.sh diff --git a/sh/meson.build b/sh/meson.build index a229600fa..1b014420e 100644 --- a/sh/meson.build +++ b/sh/meson.build @@ -21,9 +21,9 @@ sh_config = [ ] scripts_config = [ - 'gendepends.sh.in', 'openrc-run.sh.in', 'openrc-user.sh.in', + 'gendepends.sh.in', 's6-svscanboot.sh.in' ] @@ -49,8 +49,12 @@ else ] endif -install_data(sh, - install_dir : rc_shdir) +fs = import('fs') +script_deps = [] +foreach file : sh + script_deps += fs.copyfile(file, install: true, install_dir: rc_shdir) +endforeach + foreach file : sh_config configure_file(input : file, output : '@BASENAME@', @@ -60,10 +64,8 @@ endforeach foreach file : scripts_config configure_file(input : file, - output : '@BASENAME@', - configuration : sh_conf_data, - install_dir : rc_shdir, - install_mode : 'rwxr-xr-x') + output : '@BASENAME@', configuration : sh_conf_data, + install_dir : rc_shdir, install_mode : 'rwxr-xr-x') endforeach foreach file : scripts_config_os diff --git a/src/openrc-run/meson.build b/src/openrc-run/meson.build index c2fac9d8a..412c5e9c7 100644 --- a/src/openrc-run/meson.build +++ b/src/openrc-run/meson.build @@ -1,4 +1,4 @@ -executable('openrc-run', 'openrc-run.c', +openrc_run = executable('openrc-run', 'openrc-run.c', dependencies: [rc, einfo, shared, audit_dep, dl_dep, pam_dep, pam_misc_dep, selinux_dep, util_dep, crypt_dep], include_directories: incdir, install: true, diff --git a/src/rc-service/meson.build b/src/rc-service/meson.build index 71c49fbef..211169ac6 100644 --- a/src/rc-service/meson.build +++ b/src/rc-service/meson.build @@ -1,4 +1,4 @@ -executable('rc-service', 'rc-service.c', +rc_service = executable('rc-service', 'rc-service.c', include_directories: incdir, dependencies: [rc, einfo, shared], install: true, diff --git a/test/units/meson.build b/test/units/meson.build index 23c2758a8..4d1cb8a39 100644 --- a/test/units/meson.build +++ b/test/units/meson.build @@ -1,5 +1,7 @@ -is_older_than = find_program('check-is-older-than.sh') -sh_yesno = find_program('check-sh-yesno.sh') - -test('is_older_than', is_older_than, env : test_env) -test('sh_yesno', sh_yesno, env : test_env) +test('is_older_than', find_program('check-is-older-than.sh'), env: test_env) +test('sh_yesno', find_program('check-sh-yesno.sh'), env: test_env) +test('rc-service', find_program('rc-service.sh'), + env: [test_env, 'SUBDIR=' + meson.current_source_dir()], + workdir: meson.project_source_root(), + args: [ rc_service, openrc_run ], + depends: script_deps) diff --git a/test/units/rc-service.sh b/test/units/rc-service.sh new file mode 100755 index 000000000..e0cd90a8e --- /dev/null +++ b/test/units/rc-service.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +set -e + +. "$SUBDIR/setup-root.sh" +rc_service=${1?} +openrc_run=${2?} +cp "$RC_LIBEXECDIR/sh/openrc-run.sh" "$root/run/openrc/openrc-run.sh" +cp "$RC_LIBEXECDIR/sh/gendepends.sh" "$root/run/openrc/gendepends.sh" +chmod +x "$root/run/openrc/openrc-run.sh" +chmod +x "$root/run/openrc/gendepends.sh" + +rc_service() { + $rc_service "$@" 2>&1 +} + +in_state() { + state=${1?} + shift + for svc; do + test "$(readlink "$RC_SVCDIR/$state/$svc")" = "$root/etc/init.d/$svc" + done +} + +mkservice() { + service="$root/etc/init.d/$1" + cat > "$service" <<-EOF + #!$SOURCE_ROOT/${openrc_run} + depend() { + ${2-:;} + } + start() { + ${3-sleep 0.1} + } + EOF + chmod +x "$service" +} + +mkservice nya +mkservice foo "need nya" +mkservice mew "want foo" + +addrunlevel() { + ln -s "$root/etc/init.d/${1?}" "$root/etc/runlevel/${2?}/$1" +} + +rc_service nya start +in_state started nya + +rc_service nya stop +( ! in_state started nya ) + +rc_service foo start +in_state started foo nya + +rc_service foo stop +in_state started nya +( ! in_state started foo ) + +rc_service foo start +in_state started foo nya + +rc_service nya stop +( ! in_state started foo nya ) + +rc_service mew start +in_state started foo nya mew + +rc_service nya stop +rc_service mew stop + +( ! in_state started foo nya mew ) diff --git a/test/units/rc-update.sh b/test/units/rc-update.sh new file mode 100755 index 000000000..d74373518 --- /dev/null +++ b/test/units/rc-update.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +set -ex + +. ${1?} +rc_update=${2?} + +rc_update() { + "$rc_update" --root "$root" "$@" 2>&1 +} + +in_runlevel() { + test "$(readlink "$root/etc/runlevels/${1?}/${2?}")" = "$root/etc/init.d/$2" +} + +stacked() { + test -d "$root/etc/runlevels/${1?}/${2?}" +} + +# non-existent +( ! rc_update add nya ) +( ! rc_update -s add nya ) +( ! rc_update del nya ) +( ! rc_update -s del nya ) + +cat > "$root/etc/init.d/nya" <<-EOF +#!/sbin/openrc-run +start() { + :; +} +EOF + +# non-executable +( ! rc_update add nya ) +( ! rc_update -s add nya ) + +chmod +x "$root/etc/init.d/nya" + +# implicit runlevel +rc_update add nya +in_runlevel default nya + +rc_update del nya +( ! in_runlevel default nya) +# not in the runlevel +( ! rc_update del nya ) + +# explicit runlevel +rc_update add nya default +in_runlevel default nya +# not in the specified runlevel +( ! rc_update del nya boop ) + +# stacking +rc_update -s add boop +stacked default boop + +rc_update -s del boop +( ! stacked boop nya ) + +rc_update -s add boop default +stacked default boop + +rc_update -s del boop +( ! stacked boop default ) +( ! rc_update -s del boop ) + +# show +rc_update add nya +rc_update | grep -qE "^\s*nya" +rc_update show | grep -qE "^\s*nya" +rc_update show default | grep -qE "^\s*nya" +rc_update del nya +( ! rc_update show | grep -qE "^\s*nya" ) +( ! rc_update show default | grep -qE "^\s*nya" ) + +exit 0 diff --git a/test/units/setup-root.sh b/test/units/setup-root.sh new file mode 100755 index 000000000..6545cb5dd --- /dev/null +++ b/test/units/setup-root.sh @@ -0,0 +1,28 @@ +root=$(mktemp -d --tmpdir rc.XXXXXX) +#trap "rm -r $root" EXIT + +sysdir="$root/etc" +export RC_LIBEXECDIR="$BUILD_ROOT" +export RC_PATH="$sysdir" +export RC_SVCDIR="$root/run/openrc" +mkdir -p "$RC_SVCDIR" +echo "default" > "$RC_SVCDIR/softlevel" + +for dir in init.d conf.d runlevels; do + mkdir -p "$sysdir/$dir" +done +for dir in sysinit boot default boop shutdown; do + mkdir -p "$sysdir/runlevels/$dir" +done + +for dir in daemons exclusive failed hotplugged inactive init.d \ + options scheduled started starting stopping tmp wasinactive; do + mkdir -p "$root/run/openrc/$dir" +done + +setup_path() { + local IFS=: + export PATH="$PATH:$*" +} + +setup_path "$BUILD_ROOT"/src/*