diff options
Diffstat (limited to 'extra/openrc')
25 files changed, 1827 insertions, 0 deletions
| diff --git a/extra/openrc/0001-call-sbin-mkmntdirs-in-localmount-OpenRC-service.patch b/extra/openrc/0001-call-sbin-mkmntdirs-in-localmount-OpenRC-service.patch new file mode 100644 index 0000000..3d41060 --- /dev/null +++ b/extra/openrc/0001-call-sbin-mkmntdirs-in-localmount-OpenRC-service.patch @@ -0,0 +1,25 @@ +From 78245081fe109ed7777b79ba9c99890d56c21272 Mon Sep 17 00:00:00 2001 +From: Natanael Copa <ncopa@alpinelinux.org> +Date: Wed, 1 Feb 2017 04:04:52 +0000 +Subject: [PATCH] call /sbin/mkmntdirs in localmount OpenRC service + +--- + init.d/localmount.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/init.d/localmount.in b/init.d/localmount.in +index c571504a..14189396 100644 +--- a/init.d/localmount.in ++++ b/init.d/localmount.in +@@ -21,6 +21,8 @@ depend() +  + start() + { ++	[ -x /sbin/mkmntdirs ] && mkmntdirs ++ + 	# Mount local filesystems in /etc/fstab. + 	# The types variable must start with no, and must be a type + 	local critical= types="noproc" x= no_netdev= rc= +--  +2.33.1 + diff --git a/extra/openrc/0002-fsck-don-t-add-C0-to-busybox-fsck.patch b/extra/openrc/0002-fsck-don-t-add-C0-to-busybox-fsck.patch new file mode 100644 index 0000000..1d79818 --- /dev/null +++ b/extra/openrc/0002-fsck-don-t-add-C0-to-busybox-fsck.patch @@ -0,0 +1,35 @@ +From b143f35a45d59708365a52e329fd8caa6475a9bb Mon Sep 17 00:00:00 2001 +From: Natanael Copa <ncopa@alpinelinux.org> +Date: Tue, 28 Nov 2017 13:35:10 +0100 +Subject: [PATCH] fsck: don't add -C0 to busybox fsck + +--- + init.d/fsck.in | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/init.d/fsck.in b/init.d/fsck.in +index 7052d808..99a9ae4f 100644 +--- a/init.d/fsck.in ++++ b/init.d/fsck.in +@@ -82,7 +82,7 @@ start() + 		local skiptypes + 		skiptypes=$(printf 'no%s,' ${net_fs_list} ${extra_net_fs_list}) + 		[ "${skiptypes}" = "no," ] && skiptypes="" +-		fsck_opts="$fsck_opts -C0 -T -t ${skiptypes}noopts=_netdev" ++		fsck_opts="$fsck_opts -T -t ${skiptypes}noopts=_netdev" + 		if [ -z "$fsck_passno" -a -z "$fsck_mnt" ]; then + 			fsck_args=${fsck_args:--A -p} + 			if echo 2>/dev/null >/.test.$$; then +@@ -90,6 +90,9 @@ start() + 				fsck_opts="$fsck_opts -R" + 			fi + 		fi ++		if [ "$(readlink -f $(which fsck))" != "/bin/busybox" ]; then ++			fsck_opts="$fsck_opts -C0" ++		fi + 	fi +  + 	trap : INT QUIT +--  +2.33.1 + diff --git a/extra/openrc/0003-rc-pull-in-sysinit-and-boot-as-stacked-levels-when-n.patch b/extra/openrc/0003-rc-pull-in-sysinit-and-boot-as-stacked-levels-when-n.patch new file mode 100644 index 0000000..546ccb7 --- /dev/null +++ b/extra/openrc/0003-rc-pull-in-sysinit-and-boot-as-stacked-levels-when-n.patch @@ -0,0 +1,70 @@ +From 17f33c1968a51484eefdafbfb5b8fef5ac13d215 Mon Sep 17 00:00:00 2001 +From: Natanael Copa <ncopa@alpinelinux.org> +Date: Wed, 1 Feb 2017 04:17:14 +0000 +Subject: [PATCH] rc: pull in sysinit and boot as stacked levels when needed + +We need start services from sysinit and boot runlevel, even if the new +runlevel is empty. + +This fixes problem introduced with commit 7716bf31 (Fix stacked runlevel +support), at which the start_services list are no longer used to start +the services. + +This also make sure that all services in sysinit and boot runlevels are +started before switching to next. This was not guaranteed when switching +to a non-empty runlevel. + +Fixes issue #54. +--- + src/rc/rc.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/rc/rc.c b/src/rc/rc.c +index ef46925d..82786074 100644 +--- a/src/rc/rc.c ++++ b/src/rc/rc.c +@@ -729,6 +729,7 @@ int main(int argc, char **argv) + 	const char *bootlevel = NULL; + 	char *newlevel = NULL; + 	const char *systype = NULL; ++	RC_STRINGLIST *runlevel_chain; + 	RC_STRINGLIST *deporder = NULL; + 	RC_STRINGLIST *tmplist; + 	RC_STRING *service; +@@ -986,6 +987,7 @@ int main(int argc, char **argv) + 	main_hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); + 	main_start_services = rc_services_in_runlevel_stacked(newlevel ? + 	    newlevel : runlevel); ++	runlevel_chain = rc_runlevel_stacks(newlevel ? newlevel : runlevel); + 	if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && + 	    strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0) + 	{ +@@ -1003,6 +1005,7 @@ int main(int argc, char **argv) + 				tmplist = rc_services_in_runlevel(bootlevel); + 				TAILQ_CONCAT(main_start_services, tmplist, entries); + 				free(tmplist); ++				rc_stringlist_add(runlevel_chain, bootlevel); + 			} + 			if (main_hotplugged_services) { + 				TAILQ_FOREACH(service, main_hotplugged_services, +@@ -1011,6 +1014,7 @@ int main(int argc, char **argv) + 					service->value); + 			} + 		} ++		rc_stringlist_add(runlevel_chain, RC_LEVEL_SYSINIT); + 	} +  + 	parallel = rc_conf_yesno("rc_parallel"); +@@ -1067,9 +1071,6 @@ int main(int argc, char **argv) +  + 	/* If we have a list of services to start then... */ + 	if (main_start_services) { +-		/* Get a list of the chained runlevels which compose the target runlevel */ +-		RC_STRINGLIST *runlevel_chain = rc_runlevel_stacks(runlevel); +- + 		/* Loop through them in reverse order. */ + 		RC_STRING *rlevel; + 		TAILQ_FOREACH_REVERSE(rlevel, runlevel_chain, rc_stringlist, entries) +--  +2.33.1 + diff --git a/extra/openrc/0004-make-consolefont-service-compatible-with-busyboxs-se.patch b/extra/openrc/0004-make-consolefont-service-compatible-with-busyboxs-se.patch new file mode 100644 index 0000000..b92b5ac --- /dev/null +++ b/extra/openrc/0004-make-consolefont-service-compatible-with-busyboxs-se.patch @@ -0,0 +1,70 @@ +From 613fb7f437c42e0ed01b2366b597598235e64a2d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?S=C3=B6ren=20Tempel?= <soeren+git@soeren-tempel.net> +Date: Wed, 17 Aug 2016 17:52:58 +0200 +Subject: [PATCH] make consolefont service compatible with busyboxs setfont + applet + +Compared to kdbs setfont program it doesn't support -O and -m. +--- + conf.d/consolefont    | 11 ++--------- + init.d/consolefont.in |  7 ++----- + 2 files changed, 4 insertions(+), 14 deletions(-) + +diff --git a/conf.d/consolefont b/conf.d/consolefont +index e01ae842..75544b2f 100644 +--- a/conf.d/consolefont ++++ b/conf.d/consolefont +@@ -3,16 +3,9 @@ + # + # consolefont specifies the default font that you'd like Linux to use on the + # console.  You can find a good selection of fonts in /usr/share/consolefonts; +-# you shouldn't specify the trailing ".psf.gz", just the font name below. +-# To use the default console font, comment out the CONSOLEFONT setting below. +-consolefont="default8x16" ++consolefont="default8x16.psf.gz" +  + # consoletranslation is the charset map file to use.  Leave commented to use + # the default one.  Have a look in /usr/share/consoletrans for a selection of + # map files you can use. +-#consoletranslation="8859-1_to_uni" +- +-# unicodemap is the unicode map file to use. Leave commented to use the +-# default one. Have a look in /usr/share/unimaps for a selection of map files +-# you can use. +-#unicodemap="iso01" ++#consoletranslation="8859-1_to_uni.trans" +diff --git a/init.d/consolefont.in b/init.d/consolefont.in +index d65dd14c..ccb6ee87 100644 +--- a/init.d/consolefont.in ++++ b/init.d/consolefont.in +@@ -22,7 +22,6 @@ start() + { + 	ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}} + 	consolefont=${consolefont:-${CONSOLEFONT}} +-	unicodemap=${unicodemap:-${UNICODEMAP}} + 	consoletranslation=${consoletranslation:-${CONSOLETRANSLATION}} +  + 	if [ -z "$consolefont" ]; then +@@ -43,9 +42,6 @@ start() + 	if [ -n "$consoletranslation" ]; then + 		param="$param -m $consoletranslation" + 	fi +-	if [ -n "${unicodemap}" ]; then +-		param="$param -u $unicodemap" +-	fi +  + 	# Set the console font + 	ebegin "Setting console font [$consolefont]" +@@ -63,7 +59,8 @@ start() + 	# Store the font so we can use it ASAP on boot + 	if [ $retval -eq 0 ] && checkpath -W "$RC_LIBEXECDIR"; then + 		mkdir -p "$RC_LIBEXECDIR"/console +-		setfont -O "$RC_LIBEXECDIR"/console/font ++		zcat "/usr/share/consolefonts/$consolefont" \ ++			> "$RC_LIBEXECDIR"/console/font + 	fi +  + 	return $retval +--  +2.33.1 + diff --git a/extra/openrc/0005-Support-early-loading-of-keymap-if-kbd-is-installed.patch b/extra/openrc/0005-Support-early-loading-of-keymap-if-kbd-is-installed.patch new file mode 100644 index 0000000..f25d984 --- /dev/null +++ b/extra/openrc/0005-Support-early-loading-of-keymap-if-kbd-is-installed.patch @@ -0,0 +1,31 @@ +From a07970bf087c089f467eefa30c2476f17f6e9536 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?S=C3=B6ren=20Tempel?= <soeren+git@soeren-tempel.net> +Date: Thu, 7 Mar 2019 16:55:53 +0100 +Subject: [PATCH] Support early loading of keymap if kbd is installed + +Early loading of the keymap with busybox was never supported and would +require modifying the save-keymaps services as well. Since no one +complained that it doesn't work with busybox so far just make it work +with kbd for now. +--- + sh/init-early.sh.Linux.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sh/init-early.sh.Linux.in b/sh/init-early.sh.Linux.in +index f304e924..7571ff3d 100644 +--- a/sh/init-early.sh.Linux.in ++++ b/sh/init-early.sh.Linux.in +@@ -48,8 +48,8 @@ if service_present "$RC_DEFAULTLEVEL" consolefont || + fi +  + # Try and set a keyboard map as early as possible +-if service_present "$RC_DEFAULTLEVEL" keymaps || +-   service_present "$RC_BOOTLEVEL" keymaps; then ++if service_present "$RC_DEFAULTLEVEL" loadkeys || ++   service_present "$RC_BOOTLEVEL" loadkeys; then + 	kbd_mode $kmode -C "$CONSOLE" 2>/dev/null + 	if [ -r "$RC_LIBEXECDIR"/console/keymap ]; then + 		loadkeys -q "$RC_LIBEXECDIR"/console/keymap 2>/dev/null +--  +2.33.1 + diff --git a/extra/openrc/0006-Add-support-for-starting-services-in-a-specified-VRF.patch b/extra/openrc/0006-Add-support-for-starting-services-in-a-specified-VRF.patch new file mode 100644 index 0000000..6f7ed69 --- /dev/null +++ b/extra/openrc/0006-Add-support-for-starting-services-in-a-specified-VRF.patch @@ -0,0 +1,101 @@ +From c250503412b061e69a99cfe12514e47fc06b5885 Mon Sep 17 00:00:00 2001 +From: Ariadne Conill <ariadne@dereferenced.org> +Date: Fri, 14 Feb 2020 16:02:43 +0000 +Subject: [PATCH] Add support for starting services in a specified VRF. + +The venerable iproute2 utility has recently introduced support +for executing programs in specific VRFs which are virtualized +routing tables.  These are typically used to isolate different +networking planes from each other, for security or flexibility +reasons. + +Services which use the normal supervisor/start-stop-daemon +pattern can be configured by setting the vrf variable in the +/etc/conf.d tree for the service. + +This allows for things like configuring the sshd service to +run in a management VRF, which is useful for high assurance +environments where the management plane is intended to be +isolated. + +Signed-off-by: Ariadne Conill <ariadne@dereferenced.org> +--- + sh/openrc-run.sh.in     | 6 ++++++ + sh/runit.sh             | 2 +- + sh/s6.sh                | 2 +- + sh/start-stop-daemon.sh | 2 +- + sh/supervise-daemon.sh  | 2 +- + 5 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/sh/openrc-run.sh.in b/sh/openrc-run.sh.in +index 5c84af45..a1f374b0 100644 +--- a/sh/openrc-run.sh.in ++++ b/sh/openrc-run.sh.in +@@ -236,6 +236,12 @@ if ! sourcex -e "$_conf_d/$RC_SVCNAME.$RC_RUNLEVEL"; then + fi + unset _conf_d +  ++# If we are configured to run in a VRF, provide a hint for that ++RC_VRF_EXEC="" ++if [ -n "$vrf" ]; then ++	RC_VRF_EXEC="/sbin/ip vrf exec $vrf" ++fi ++ + # load service supervisor functions + sourcex "@LIBEXECDIR@/sh/runit.sh" + sourcex "@LIBEXECDIR@/sh/s6.sh" +diff --git a/sh/runit.sh b/sh/runit.sh +index 5d82c9f6..c0186a43 100644 +--- a/sh/runit.sh ++++ b/sh/runit.sh +@@ -23,7 +23,7 @@ runit_start() + 	local i=0 retval=1 + 	# it can take upto 5 seconds for runsv to start + 	while [ $i -lt 6 ] ; do +-		if sv start "${service_link}" > /dev/null 2>&1; then ++		if ${RC_VRF_EXEC} sv start "${service_link}" > /dev/null 2>&1; then + 			retval=0 + 			break + 		fi +diff --git a/sh/s6.sh b/sh/s6.sh +index acbe965b..1f339703 100644 +--- a/sh/s6.sh ++++ b/sh/s6.sh +@@ -37,7 +37,7 @@ s6_start() + 	ln -sf "${s6_service_path}" "${s6_service_link}" + 	s6-svscanctl -na "${RC_SVCDIR}"/s6-scan + 	sleep 1.5 +-	s6-svc -u "${s6_service_link}" ++	${RC_VRF_EXEC} s6-svc -u "${s6_service_link}" + 	if [ -n "$s6_svwait_options_start" ]; then + 		s6-svwait ${s6_svwait_options_start} "${s6_service_link}" + 	fi +diff --git a/sh/start-stop-daemon.sh b/sh/start-stop-daemon.sh +index 2e549ae1..5e7a1b88 100644 +--- a/sh/start-stop-daemon.sh ++++ b/sh/start-stop-daemon.sh +@@ -45,7 +45,7 @@ ssd_start() + 	#the eval call is necessary for cases like: + 	# command_args="this \"is a\" test" + 	# to work properly. +-	eval start-stop-daemon --start \ ++	eval ${RC_VRF_EXEC} start-stop-daemon --start \ + 		--exec $command \ + 		${chroot:+--chroot} $chroot \ + 		${directory:+--chdir} $directory \ +diff --git a/sh/supervise-daemon.sh b/sh/supervise-daemon.sh +index e403a789..259b8166 100644 +--- a/sh/supervise-daemon.sh ++++ b/sh/supervise-daemon.sh +@@ -24,7 +24,7 @@ supervise_start() + 	# The eval call is necessary for cases like: + 	# command_args="this \"is a\" test" + 	# to work properly. +-	eval supervise-daemon "${RC_SVCNAME}" --start \ ++	eval ${RC_VRF_EXEC} supervise-daemon "${RC_SVCNAME}" --start \ + 		${retry:+--retry} $retry \ + 		${directory:+--chdir} $directory  \ + 		${chroot:+--chroot} $chroot \ +--  +2.33.1 + diff --git a/extra/openrc/0007-Clean-up-staticroute-config-remove-irrelevant-parts-.patch b/extra/openrc/0007-Clean-up-staticroute-config-remove-irrelevant-parts-.patch new file mode 100644 index 0000000..34100ef --- /dev/null +++ b/extra/openrc/0007-Clean-up-staticroute-config-remove-irrelevant-parts-.patch @@ -0,0 +1,47 @@ +From f406231dc9a49b67ca558983de80513f95078309 Mon Sep 17 00:00:00 2001 +From: Ariadne Conill <ariadne@dereferenced.org> +Date: Wed, 8 Sep 2021 23:51:11 -0600 +Subject: [PATCH] Clean up staticroute config - remove irrelevant parts (for + BSD, Hurd) and suggest that route(8) is legacy. + +--- + conf.d/staticroute | 23 +++-------------------- + 1 file changed, 3 insertions(+), 20 deletions(-) + +diff --git a/conf.d/staticroute b/conf.d/staticroute +index 19d0961f..49d0e0bb 100644 +--- a/conf.d/staticroute ++++ b/conf.d/staticroute +@@ -1,26 +1,9 @@ +-# Static routes are defined differently depending on your operating +-# system, so please be sure to use the correct syntax. + # Do not use this file to define the default route. + # In all settings, multiple routes should be separated using ; or new lines. +  +-# Define static routes on Linux using route. See route(8) for syntax. +-#staticroute="net 192.168.0.0 netmask 255.255.255.0 gw 10.73.1.1 +-#net 192.168.1.0 netmask 255.255.255.0 gw 10.73.1.1" +- + # Define static routes on Linux using iproute2. See ip(8) for syntax. + #staticiproute="192.168.0.0/24 via 10.73.1.1; 192.168.1.0/24 via 10.73.1.1" +  +-# Define static routes on GNU/Hurd. See route(8) for syntax. +-# /etc/route.conf(5) takes precedence over this configuration. +-# FIXME: "net ..." not supported +-#staticroute="net 192.168.0.0 -netmask 255.255.255.0 --address 10.73.1.1 +-#net 192.168.1.0 -netmask 255.255.255.0 --address 10.73.1.1" +- +-# Define static routes on GNU/KFreeBSD. See route(8) for syntax. +-#staticroute="net 192.168.0.0 10.73.1.1 netmask 255.255.255.0 +-#net 192.168.1.0 10.73.1.1 netmask 255.255.255.0" +- +-# Define static routes on other BSD systems. See route(8) for syntax. +-# /etc/route.conf(5) takes precedence over this configuration. +-#staticroute="net 192.168.0.0 -netmask 255.255.255.0 10.73.1.1 +-#net 192.168.1.0 -netmask 255.255.255.0 10.73.1.1" ++# Or define static routes on Linux using route (legacy). See route(8) for syntax. ++#staticroute="net 192.168.0.0 netmask 255.255.255.0 gw 10.73.1.1 ++#net 192.168.1.0 netmask 255.255.255.0 gw 10.73.1.1" +--  +2.33.1 + diff --git a/extra/openrc/0008-bootmisc-switch-wipe_tmp-setting-to-no-by-default.patch b/extra/openrc/0008-bootmisc-switch-wipe_tmp-setting-to-no-by-default.patch new file mode 100644 index 0000000..f498d05 --- /dev/null +++ b/extra/openrc/0008-bootmisc-switch-wipe_tmp-setting-to-no-by-default.patch @@ -0,0 +1,44 @@ +From a756576ae62e4f24a2ea36e87053187cdfc1be63 Mon Sep 17 00:00:00 2001 +From: Ariadne Conill <ariadne@dereferenced.org> +Date: Wed, 13 Oct 2021 21:12:10 -0600 +Subject: [PATCH] bootmisc: switch wipe_tmp setting to no by default + +When wipe_tmp=yes, an insufficiently bounded rm -rf occurs that, +under specific unknown circumstances, can escape into other filesystems +resulting in data loss. + +See alpine/aports#13070. +--- + conf.d/bootmisc    | 2 +- + init.d/bootmisc.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/conf.d/bootmisc b/conf.d/bootmisc +index dd5b08e0..5cf18d33 100644 +--- a/conf.d/bootmisc ++++ b/conf.d/bootmisc +@@ -3,7 +3,7 @@ clean_tmp_dirs="/tmp" +  + # Should we wipe the tmp paths completely or just selectively remove known + # locks / files / etc... ? +-wipe_tmp="YES" ++wipe_tmp="NO" +  + # Write the initial dmesg log into /var/log/dmesg after boot + # This may be useful if you need the kernel boot log afterwards +diff --git a/init.d/bootmisc.in b/init.d/bootmisc.in +index b1a849a3..8485110a 100644 +--- a/init.d/bootmisc.in ++++ b/init.d/bootmisc.in +@@ -17,7 +17,7 @@ depend() + 	keyword -prefix -timeout + } +  +-: ${wipe_tmp:=${WIPE_TMP:-yes}} ++: ${wipe_tmp:=${WIPE_TMP:-no}} + : ${log_dmesg:=${LOG_DMESG:-yes}} +  + cleanup_tmp_dir() +--  +2.33.1 + diff --git a/extra/openrc/0009-fix-bootmisc-mv-error.patch b/extra/openrc/0009-fix-bootmisc-mv-error.patch new file mode 100644 index 0000000..e87f9bb --- /dev/null +++ b/extra/openrc/0009-fix-bootmisc-mv-error.patch @@ -0,0 +1,27 @@ +From: Dermot Bradley <dermot_bradley@yahoo.com> +Date: Sat, 29 Jan 2022 19:28 +0000 +Subject: prevent a bootmisc trying to move a nonexistant file + +During boot if the "previous_dmesg" setting is enabled in +/etc/conf.d/bootmisc then during the 1st boot of a machine the +bootmisc init.d script will attempt to move a nonexistant dmesg +file, so generating an error on the console. + +Modify the script to only move an existing file. + +Upstream has merged this as PR 496 so it will be in the next release. + +--- + +diff -aur a/init.d/bootmisc.in b/init.d/bootmisc.in +--- a/init.d/bootmisc.in ++++ b/init.d/bootmisc.in +@@ -226,7 +226,7 @@ + 			case "$RC_SYS" in + 				VSERVER|OPENVZ|LXC|SYSTEMD-NSPAWN) ;; + 				*) +-					if yesno ${previous_dmesg:-no}; then ++					if yesno ${previous_dmesg:-no} && [ -e /var/log/dmesg ]; then + 						mv /var/log/dmesg /var/log/dmesg.old + 					fi + 					dmesg > /var/log/dmesg diff --git a/extra/openrc/0010-noexec-devfs.patch b/extra/openrc/0010-noexec-devfs.patch new file mode 100644 index 0000000..9a8928c --- /dev/null +++ b/extra/openrc/0010-noexec-devfs.patch @@ -0,0 +1,14 @@ +--- a/init.d/devfs.in ++++ b/init.d/devfs.in +@@ -24,8 +24,9 @@ mount_dev() + 	action=--mount + 	conf_d_dir="${RC_SERVICE%/*/*}/conf.d" + 	msg=Mounting +-	# Some devices require exec, Bug #92921 +-	mountopts="exec,nosuid,mode=0755" ++	# Some devices require exec, https://bugs.gentoo.org/92921 ++	# Users with such requirements can use an fstab entry for /dev ++	mountopts="noexec,nosuid,mode=0755" + 	if yesno ${skip_mount_dev:-no} ; then + 		einfo "/dev will not be mounted due to user request" + 		return 0 diff --git a/extra/openrc/firstboot.initd b/extra/openrc/firstboot.initd new file mode 100644 index 0000000..eac4ef8 --- /dev/null +++ b/extra/openrc/firstboot.initd @@ -0,0 +1,34 @@ +#!/sbin/openrc-run + +# The first boot init service + +# read kernel options +init_KOPT() { +	eval "set -- $(cat /proc/cmdline 2>/dev/null)" +	for opt; do +		case "$opt" in +			ssh_*=*) +				eval "KOPT_${opt%%=*}='${opt#*=}'" ;; +		esac +	done +} + +start() { +	rm -f /etc/runlevels/*/$RC_SVCNAME +	init_KOPT +	local rc=0 +	ebegin "Starting ${RC_SVCNAME}" +	if [ -n "$KOPT_ssh_key" ] && [ ! -f "/root/.ssh/authorized_keys" ]; then +		einfo "Fetching ssh keys" +		mkdir -pm 700 /root/.ssh +		checkpath -fm 0600 /root/.ssh/authorized_keys +		case "$KOPT_ssh_key" in +			https://*|ftps://*|http://*) +				wget -q "$KOPT_ssh_key" -O /root/.ssh/authorized_keys +				rc=$?;; +			*) echo "$KOPT_ssh_key" > /root/.ssh/authorized_keys;; +		esac +	fi +	eend $rc +} + diff --git a/extra/openrc/hostname.initd b/extra/openrc/hostname.initd new file mode 100644 index 0000000..bd20874 --- /dev/null +++ b/extra/openrc/hostname.initd @@ -0,0 +1,18 @@ +#!/sbin/openrc-run + +description="Sets the hostname of the machine." + +depend() { +	keyword -prefix -lxc -docker +} + +start() { +	if [ -s /etc/hostname ] ; then +		opts="-F /etc/hostname" +	else +		opts="${hostname:-localhost}" +	fi +	ebegin "Setting hostname" +	hostname $opts +	eend $? +} diff --git a/extra/openrc/hwdrivers.initd b/extra/openrc/hwdrivers.initd new file mode 100644 index 0000000..80184c9 --- /dev/null +++ b/extra/openrc/hwdrivers.initd @@ -0,0 +1,32 @@ +#!/sbin/openrc-run + +depend() { +	need sysfs dev +	before checkfs fsck +	after modloop +	keyword -vserver -lxc +} + +# Load hardware drivers +start() { +	# check for boot option "nocoldplug" +	if get_bootparam noautodetect; then +		ewarn "Autodetection of hardware disabled from boot cmdline" +		return 0 +	fi + +	ebegin "Loading hardware drivers" +	find /sys -name modalias -type f -print0 | xargs -0 sort -u \ +		| xargs modprobe -b -a 2> /dev/null +	# we run it twice so we detect all devices +	find /sys -name modalias -type f -print0 | xargs -0 sort -u \ +		| xargs modprobe -b -a 2> /dev/null + +	# check if framebuffer drivers got pulled in +	if [ -e /dev/fb0 ] && ! [ -e /sys/module/fbcon ]; then +		modprobe -b -q fbcon +	fi + +	eend 0 +} + diff --git a/extra/openrc/machine-id.initd b/extra/openrc/machine-id.initd new file mode 100644 index 0000000..bdd0698 --- /dev/null +++ b/extra/openrc/machine-id.initd @@ -0,0 +1,17 @@ +#!/sbin/openrc-run + +description="Generate machine-id if needed" + +depend() { +	need root dev +} + +start() { +	if [ -s /etc/machine-id ] ; then +		return 0 +	fi +	ebegin "Generating machine-id" +	dd if=/dev/urandom status=none bs=16 count=1 \ +		| md5sum | cut -d' ' -f1 > /etc/machine-id +	eend $? +} diff --git a/extra/openrc/modloop.confd b/extra/openrc/modloop.confd new file mode 100644 index 0000000..6966429 --- /dev/null +++ b/extra/openrc/modloop.confd @@ -0,0 +1,6 @@ +# Enable loadable module support when running from RAM +# when OverlayFS support is available in the kernel. +# 0 means default tmpfs size (50% of physical RAM). +# for more information please see kernel documention at: +# https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt +overlay_size=0 diff --git a/extra/openrc/modloop.initd b/extra/openrc/modloop.initd new file mode 100755 index 0000000..fb7006c --- /dev/null +++ b/extra/openrc/modloop.initd @@ -0,0 +1,153 @@ +#!/sbin/openrc-run + +# script that will mount image with modules + +depend() { +	after dev-mount +	before checkfs fsck hwdrivers modules hwclock dev sysfs +	keyword -vserver -lxc +} + +# read kernel options +init_KOPT() { +	for opt in $(cat /proc/cmdline 2>/dev/null); do +	        case "$opt" in +			modloop=*|modloop_verify=*) +				eval "KOPT_${opt%%=*}='${opt#*=}'" ;; +		esac +	done +} + +mountdirs() { +	awk '$2 !~ /^\/(sys|proc|dev|run)/ && $2 != "/" {print $2}' /proc/mounts +} + +find_modloop() { +	local dir="$1" +	local kver=$(uname -r) +	local oifs="$IFS" +	IFS=$'\n' +	set -- $(blkid "$dir"/boot/* "$dir"/*) +	IFS="$oifs" +	for line; do +		img=${line%%:*} +		verify_modloop "$img" || eerror "Failed to verify signature of $img!" +		mount "$img" -o loop,ro /.modloop || continue +		if [ -d /.modloop/modules/$kver ]; then +			return 0 +		fi +		umount /.modloop +	done +	return 1 +} + +verify_modloop() { +	local modloop=$1 key= +	if ! yesno "${KOPT_modloop_verify:=yes}"; then +		return 0 +	fi +	for key in /etc/apk/keys/*.pub; do +		local sig=/var/cache/misc/${modloop##*/}.SIGN.RSA.${key##*/} +		if [ -f "$sig" ]; then +			if ! command -v openssl > /dev/null; then +				ewarn "Missing openssl. Modloop verification disabled!" +				return 0 +			fi +			einfo "Verifying modloop" +			openssl dgst -sha1 -verify "$key" -signature "$sig" "$modloop" \ +				>/dev/null 2>&1 || return 1 +		fi +	done +} + +find_backing_file() { +	local dir="$1" +	local dev=$(df -P "$dir" | tail -1 | awk '{print $1}') +	cat /sys/block/${dev#/dev/}/loop/backing_file 2>/dev/null +} + +start() { +	local modloop= mount_opts= modloop_dldir="/lib" +	init_KOPT + +	case "$KOPT_modloop" in +		none) return 0;; +		http://*|https://*|ftp://*) +			modloop=$modloop_dldir/${KOPT_modloop##*/} +			if [ ! -f "$modloop" ]; then +				mkdir -p "$modloop_dldir" +				wget -P "$modloop_dldir" "$KOPT_modloop" || eend 1 +			fi +			;; +		*) +			for dir in $(mountdirs); do +				if [ -f "$dir"/$KOPT_modloop ]; then +					modloop="$dir/${KOPT_modloop##/}" +					alpine_mnt="$dir" +					break +				fi +			done +			;; +	esac + +	ebegin "Mounting modloop $modloop" +	mkdir -p /.modloop +	if [ -n "$modloop" ]; then +		verify_modloop "$modloop" || eerror "Failed to verify signature of $img!" +		mount -o loop,ro $modloop /.modloop +		eend $? || return 1 +	else +		for dir in $(mountdirs); do +			if find_modloop "$dir"; then +				alpine_mnt="$dir" +				break +			fi +		done +		if [ -d /.modloop/modules/$(uname -r) ]; then +			eend 0 +		else +			eend 1 || return 1 +		fi +	fi + +	#use overlayfs if available and configured +	if grep -q -w "overlay$" /proc/filesystems && [ ! -z ${unionfs_size+x} ]; then +		ewarn "Use of unionfs_size is deprecated use overlay_size instead" +		overlay_size="$unionfs_size" +	fi +	if grep -q -w "overlay$" /proc/filesystems && [ -n "$overlay_size" ]; then +		ebegin "OverlayFS detected, mounting modloop rw" +		[ "$overlay_size" != 0 ] && mount_ops="-o size=$overlay_size" +		mkdir -p /.modoverlayfs /lib/modules +		mount -t tmpfs $mount_ops tmpfs /.modoverlayfs +		mkdir -p /.modoverlayfs/modules /.modoverlayfs/work +		mount -t overlay -o upperdir=/.modoverlayfs/modules,lowerdir=/lib/modules:/.modloop/modules,workdir=/.modoverlayfs/work overlay /lib/modules +		depmod -A +		eend $? || return 1 +	else +		rm -rf /lib/modules && ln -sf /.modloop/modules /lib/ +	fi + +	# copy firmware if there are any +	if [ -d $alpine_mnt/firmware ]; then +	        ebegin "Copying firmware from $alpine_mnt/firmware" +	        cp -R -a $alpine_mnt/firmware /lib/ +	        eend $? +	elif  [ -d /lib/modules/firmware ]; then +		rmdir /lib/firmware 2>/dev/null \ +			&& ln -s /lib/modules/firmware /lib/ +	fi +	return 0 +} + +stop() { +	local ret=0 +	local mnt; for mnt in /lib/modules /.modoverlayfs /.modloop; do +		if mountinfo --quiet "$mnt"; then +			ebegin "Unmounting $mnt" +			umount -d "$mnt" || ret=1 +		fi +	done +	eend $ret || return 1 +} + diff --git a/extra/openrc/modules.initd b/extra/openrc/modules.initd new file mode 100644 index 0000000..3cd141e --- /dev/null +++ b/extra/openrc/modules.initd @@ -0,0 +1,80 @@ +#!/sbin/openrc-run + +description="Loads a user defined list of kernel modules." + +depend() +{ +	before hwclock hwdrivers +	keyword -openvz -prefix -vserver -lxc +} + +start() { +	yesno $rc_verbose && verbose=yes + +	ebegin "Loading modules" +	eindent +	for f in /lib/modules-load.d/*.conf \ +		/usr/lib/modules-load.d/*.conf; do + +		if ! [ -f "$f" ]; then +			continue +		fi + +		if  [ -f /etc/modules-load.d/"${f##*/}" ]; then +			veinfo "Ignoring $f due to /etc/modules-load.d/${f##*/}" +			continue +		fi + +		if [ -f /run/modules-load.d/"${f##*/}" ]; then +			veinfo "Ignoring $f due to /run/modules-load.d/${f##*/}" +			continue +		fi + +		veinfo "Processing $f" +		sed -e 's/\#.*//g' -e '/^[[:space:]]*$/d' < "$f" \ +			| while read module args; do +			modprobe -q $module $args +		done +	done +	 +	if [ -f /etc/modules ]; then +		veinfo "Processing /etc/modules" +		sed -e 's/\#.*//g' -e '/^[[:space:]]*$/d' < /etc/modules \ +			| while read module args; do +			modprobe -q $module $args +		done +	fi + +	for f in /etc/modules-load.d/*.conf; do +		if [ ! -f "$f" ]; then +			continue +		fi + +		if [ -f /run/modules-load.d/"${f##*/}" ]; then +			veinfo "Ignoring $f due to /run/modules-load.d/${f##*/}" +			continue +		fi + +		veinfo "Processing $f" +		sed -e 's/\#.*//g' -e '/^[[:space:]]*$/d' < "$f" \ +			| while read module args; do +			modprobe -q $module $args +		done +	done + +	for f in /run/modules-load.d/*.conf; do +		if [ ! -f "$f" ]; then +			continue +		fi + +		veinfo "Processing $f" +		sed -e 's/\#.*//g' -e '/^[[:space:]]*$/d' < "$f" \ +			| while read module args; do +			modprobe -q $module $args +		done +	done +	eoutdent + +	eend $? +} + diff --git a/extra/openrc/networking.initd b/extra/openrc/networking.initd new file mode 100644 index 0000000..417f4a3 --- /dev/null +++ b/extra/openrc/networking.initd @@ -0,0 +1,88 @@ +#!/sbin/openrc-run + +# note that the spoofprotect, syncoockies and ip_forward options are set in  +# /etc/sysctl.conf + +: ${cfgfile:="/etc/network/interfaces"} +: ${ifquery:="ifquery"} +: ${ifstate:="/run/ifstate"} + +single_iface="${RC_SVCNAME#*.}" +if [ "$single_iface" = "$RC_SVCNAME" ]; then +	single_iface= +fi + +depend() { +	need localmount +	want dev-settle +	after bootmisc hwdrivers modules +	provide net +	keyword -jail -prefix -vserver -docker +} + +# find interfaces we want to start +find_ifaces() { +	if [ -n "$single_iface" ]; then +		echo $single_iface +		return 0 +	fi + +	if command -v "$ifquery" >/dev/null; then +		$ifquery -i "$cfgfile" --list --auto +		return +	fi + +	# fallback in case ifquery does not exist +	awk '$1 == "auto" {for (i = 2; i <= NF; i = i + 1) printf("%s ", $i)}' "$cfgfile" +} + +# return the list of interfaces we should try stop +find_running_ifaces() { +	if [ -n "$single_iface" ]; then +		echo $single_iface +		return 0 +	fi + +	if command -v "$ifquery" >/dev/null; then +		$ifquery --state-file $ifstate -i "$cfgfile" --running +		return +	fi + +	# fallback +	awk -F= '{print $2}' $ifstate +} + +start() { +	local iface= ret=1 +	ebegin "Starting networking" +	eindent +	for iface in $(find_ifaces); do +		local r=0 +		ebegin "$iface" +		if ! ifup -i "$cfgfile" $iface >/dev/null; then +			ifdown -i "$cfgfile" $iface >/dev/null 2>&1 +			r=1 +		fi +		# atleast one interface needs to be started for action +		# to be success +		eend $r && ret=0 +	done +	eoutdent +	return $ret +} + +stop() { +	local iface= +	# Don't stop the network at shutdown. +	yesno ${keep_network:-YES} && yesno $RC_GOINGDOWN && return 0 + +	ebegin "Stopping networking" +	eindent +	for iface in $(find_running_ifaces); do +		ebegin "$iface" +		ifdown -i "$cfgfile" -f $iface >/dev/null +		eend $? +	done +	eoutdent +	return 0 +} diff --git a/extra/openrc/openrc.logrotate b/extra/openrc/openrc.logrotate new file mode 100644 index 0000000..5e5e64b --- /dev/null +++ b/extra/openrc/openrc.logrotate @@ -0,0 +1,4 @@ +/var/log/rc.log { +	missingok +	notifempty +} diff --git a/extra/openrc/openrc.post-install b/extra/openrc/openrc.post-install new file mode 100644 index 0000000..1c27350 --- /dev/null +++ b/extra/openrc/openrc.post-install @@ -0,0 +1,38 @@ +#!/bin/sh + +rc_update() { +	local svc="$1" +	local level="$2" +	mkdir -p /etc/runlevels/$level +	ln -sf /etc/init.d/$svc /etc/runlevels/$level +} + +if [ ! -d etc/rcS.d ] && [ ! -d etc/rcL.d ]; then +	exit 0 +fi + +for i in etc/rc[SL].d/*; do +	[ -L "$i" ] || continue +	oldsvc=${i##*/S[0-9][0-9]} +	# some services are renamed +	case "$oldsvc" in +		modutils)	svc=modules;; +		procps)		svc=sysctl;; +		bootmisc.sh) 	svc=bootmisc;; +		keymap)		svc=keymaps;; +		rc.local)	svc=local;; +		*)		svc=$oldsvc;; +	esac +	 +	# add the service to correct "runlevel" +	case "$svc" in +		syslog|klogd) +			rc_update $svc sysinit;; +		hwclock|modules|sysctl|hostname|keymaps|bootmisc) +			rc_update $svc boot;; +		*)	rc_update $svc default;; +	esac + +	rm $i +done + diff --git a/extra/openrc/openrc.post-upgrade b/extra/openrc/openrc.post-upgrade new file mode 100644 index 0000000..8884202 --- /dev/null +++ b/extra/openrc/openrc.post-upgrade @@ -0,0 +1,35 @@ +#!/bin/sh + +# in 0.8.0-r1 the state dir moved from /libexec/rc/init.d to /lib/rc/init.d +# and with 0.10 it moved to /run/openrc + +mkdir -p /run/openrc +for dir in /libexec /lib; do +	[ -d $dir/rc/init.d ] || continue + +	for i in $dir/rc/init.d/* ; do +		[ -e "$i" ] || continue +		if [ -e /run/openrc/${i##*/} ]; then +			rm -r $i +		else +			mv $i /run/openrc/ +		fi +	done + +	rmdir $dir/rc/init.d $dir/rc /libexec 2>/dev/null +done + +# create rc.local compat +if [ -f /etc/rc.local ]; then +	cat >/etc/local.d/rc.local-compat.start<<__EOF__ +#!/bin/sh + +# this is only here for compatibility reasons +if [ -f /etc/rc.local ]; then +	. /etc/rc.local +fi +__EOF__ +	chmod +x /etc/local.d/rc.local-compat.start +fi + +exit 0 diff --git a/extra/openrc/seedrng.patch b/extra/openrc/seedrng.patch new file mode 100644 index 0000000..ff61d81 --- /dev/null +++ b/extra/openrc/seedrng.patch @@ -0,0 +1,640 @@ +From 076c2552aeff88a27fe275dfaae61dedf4bb4bd5 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" <Jason@zx2c4.com> +Date: Thu, 24 Mar 2022 22:07:16 -0600 +Subject: [PATCH] Use seedrng for seeding the random number generator + +The RNG can't actually be seeded from a shell script, due to the +reliance on ioctls. For this reason, the seedrng project provides a +basic script meant to be copy and pasted into projects like OpenRC and +tweaked as needed: https://git.zx2c4.com/seedrng/about/ + +This commit imports it into OpenRC and wires up /etc/init.d/urandom to +call it. It shouldn't be called by other things on the system, so it +lives in rc_sbindir. + +Closes #506. +Closes #507. + +Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> +--- + AUTHORS            |   1 + + conf.d/urandom     |   9 +- + init.d/urandom.in  |  41 ++-- + src/rc/Makefile    |   6 +- + src/rc/meson.build |  10 +- + src/rc/seedrng.c   | 453 +++++++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 499 insertions(+), 21 deletions(-) + create mode 100644 src/rc/seedrng.c + +diff --git a/AUTHORS b/AUTHORS +index 0616d5175..ede0f471b 100644 +--- a/AUTHORS ++++ b/AUTHORS +@@ -43,6 +43,7 @@ Ian Stakenvicius <axs@gentoo.org> + Jakob Drexel <jake42@rommel.stw.uni-erlangen.de> + James Le Cuirot <chewi@aura-online.co.uk> + Jan Psota <jasiu@belsznica.pl> ++Jason A. Donenfeld <Jason@zx2c4.com> + Jason Zaman <jason@perfinion.com> + Joe Harvell <jharvell@dogpad.net> + Joe M <joe9mail@gmail.com> +diff --git a/conf.d/urandom b/conf.d/urandom +index f721a2491..744e4f702 100644 +--- a/conf.d/urandom ++++ b/conf.d/urandom +@@ -2,4 +2,11 @@ + # (say for crypt swap), so you will need to customize this + # behavior.  If you have /var on a separate partition, then + # make sure this path lives on your root device somewhere. +-urandom_seed="/var/lib/misc/random-seed" ++seed_dir="/var/lib/seedrng" ++lock_file="/var/run/seedrng.lock" ++ ++# Set this to true if you do not want seed files to actually ++# credit the RNG. Set this if you plan to replicate this ++# file system image and do not have the wherewithal to first ++# delete the contents of /var/lib/seedrng. ++skip_credit="false" +diff --git a/init.d/urandom.in b/init.d/urandom.in +index 0d6ab66e0..cda431fdb 100644 +--- a/init.d/urandom.in ++++ b/init.d/urandom.in +@@ -1,5 +1,5 @@ + #!@SBINDIR@/openrc-run +-# Copyright (c) 2007-2015 The OpenRC Authors. ++# Copyright (c) 2007-2022 The OpenRC Authors. + # See the Authors file at the top-level directory of this distribution and + # https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS + # +@@ -9,7 +9,10 @@ + # This file may not be copied, modified, propagated, or distributed + # except according to the terms contained in the LICENSE file. +  +-: ${urandom_seed:=${URANDOM_SEED:-/var/lib/misc/random-seed}} ++export SEEDRNG_SEED_DIR="${seed_dir:-/var/lib/seedrng}" ++export SEEDRNG_LOCK_FILE="${lock_file:-/var/run/seedrng.lock}" ++export SEEDRNG_SKIP_CREDIT="${skip_credit:-false}" ++: ${urandom_seed:=${SEEDRNG_SEED_DIR}/../misc/random-seed} + description="Initializes the random number generator." +  + depend() +@@ -21,33 +24,35 @@ depend() +  + save_seed() + { +-	local psz=1 +- +-	if [ -e /proc/sys/kernel/random/poolsize ]; then +-		: $(( psz = $(cat /proc/sys/kernel/random/poolsize) / 4096 )) +-	fi +- + 	(	# sub shell to prevent umask pollution + 		umask 077 +-		dd if=/dev/urandom of="$urandom_seed" count=${psz} 2>/dev/null ++		dd if=/dev/urandom of="$urandom_seed" count=1 2>/dev/null + 	) + } +  + start() + { +-	[ -c /dev/urandom ] || return +-	if [ -f "$urandom_seed" ]; then +-		ebegin "Initializing random number generator" +-		cat "$urandom_seed" > /dev/urandom +-		eend $? "Error initializing random number generator" ++	if [ "$RC_UNAME" = Linux ]; then ++		seedrng ++	else ++		[ -c /dev/urandom ] || return ++		if [ -f "$urandom_seed" ]; then ++			ebegin "Initializing random number generator" ++			cat "$urandom_seed" > /dev/urandom ++			eend $? "Error initializing random number generator" ++		fi ++		rm -f "$urandom_seed" && save_seed + 	fi +-	rm -f "$urandom_seed" && save_seed + 	return 0 + } +  + stop() + { +-	ebegin "Saving random seed" +-	save_seed +-	eend $? "Failed to save random seed" ++	if [ "$RC_UNAME" = Linux ]; then ++		seedrng ++	else ++		ebegin "Saving random seed" ++		save_seed ++		eend $? "Failed to save random seed" ++	fi + } +diff --git a/src/rc/Makefile b/src/rc/Makefile +index fd796d920..62539f134 100644 +--- a/src/rc/Makefile ++++ b/src/rc/Makefile +@@ -15,7 +15,7 @@ endif +  + ifeq (${OS},Linux) + SRCS+=		kill_all.c openrc-init.c openrc-shutdown.c rc-sysvinit.c broadcast.c \ +-			rc-wtmp.c ++			rc-wtmp.c seedrng.c + endif +  + CLEANFILES=	version.h rc-selinux.o +@@ -47,6 +47,7 @@ RC_SBINPROGS=	mark_service_starting mark_service_started \ +  + ifeq (${OS},Linux) + RC_BINPROGS+= kill_all ++RC_SBINPROGS+= seedrng + SBINPROGS+= openrc-init openrc-shutdown + endif +  +@@ -180,3 +181,6 @@ shell_var: shell_var.o +  + swclock: swclock.o _usage.o rc-misc.o + 	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ++ ++seedrng: seedrng.o ++	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} +diff --git a/src/rc/meson.build b/src/rc/meson.build +index 8fdf3ac3b..b724c51f2 100644 +--- a/src/rc/meson.build ++++ b/src/rc/meson.build +@@ -268,7 +268,15 @@ if os == 'Linux' +     link_with: [libeinfo,librc], +     install: true, +     install_dir: rc_bindir) +-  endif ++ ++  executable('seedrng', ++    ['seedrng.c'], ++    c_args : cc_branding_flags, ++    include_directories: [incdir, einfo_incdir, rc_incdir], ++    link_with: [libeinfo, librc], ++    install: true, ++    install_dir: rc_sbindir) ++endif +  + executable('shell_var', +   ['shell_var.c'], +diff --git a/src/rc/seedrng.c b/src/rc/seedrng.c +new file mode 100644 +index 000000000..c1f941457 +--- /dev/null ++++ b/src/rc/seedrng.c +@@ -0,0 +1,453 @@ ++/* ++ * seedrng.c ++ * Seed kernel RNG from seed file, based on code from: ++ * https://git.zx2c4.com/seedrng/about/ ++ */ ++ ++/* ++ * Copyright (c) 2022 The OpenRC Authors. ++ * See the Authors file at the top-level directory of this distribution and ++ * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS ++ * ++ * This file is part of OpenRC. It is subject to the license terms in ++ * the LICENSE file found in the top-level directory of this ++ * distribution and at https://github.com/OpenRC/openrc/blob/HEAD/LICENSE ++ * This file may not be copied, modified, propagated, or distributed ++ *    except according to the terms contained in the LICENSE file. ++ */ ++ ++#include <linux/random.h> ++#include <sys/random.h> ++#include <sys/ioctl.h> ++#include <sys/file.h> ++#include <sys/stat.h> ++#include <sys/types.h> ++#include <fcntl.h> ++#include <poll.h> ++#include <unistd.h> ++#include <time.h> ++#include <errno.h> ++#include <endian.h> ++#include <stdbool.h> ++#include <stdint.h> ++#include <string.h> ++#include <stdio.h> ++#include <stdlib.h> ++ ++#include "rc.h" ++#include "einfo.h" ++#include "helpers.h" ++ ++#ifndef GRND_INSECURE ++#define GRND_INSECURE 0x0004 /* Apparently some headers don't ship with this yet. */ ++#endif ++ ++static const char *SEED_DIR; ++static const char *LOCK_FILE; ++static char *CREDITABLE_SEED; ++static char *NON_CREDITABLE_SEED; ++ ++enum blake2s_lengths { ++	BLAKE2S_BLOCK_LEN = 64, ++	BLAKE2S_HASH_LEN = 32, ++	BLAKE2S_KEY_LEN = 32 ++}; ++ ++enum seedrng_lengths { ++	MAX_SEED_LEN = 512, ++	MIN_SEED_LEN = BLAKE2S_HASH_LEN ++}; ++ ++struct blake2s_state { ++	uint32_t h[8]; ++	uint32_t t[2]; ++	uint32_t f[2]; ++	uint8_t buf[BLAKE2S_BLOCK_LEN]; ++	unsigned int buflen; ++	unsigned int outlen; ++}; ++ ++#define le32_to_cpup(a) le32toh(*(a)) ++#define cpu_to_le32(a) htole32(a) ++#ifndef ARRAY_SIZE ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++#endif ++#ifndef DIV_ROUND_UP ++#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) ++#endif ++ ++static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words) ++{ ++        while (words--) { ++		*buf = cpu_to_le32(*buf); ++		++buf; ++	} ++} ++ ++static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words) ++{ ++        while (words--) { ++		*buf = le32_to_cpup(buf); ++		++buf; ++        } ++} ++ ++static inline uint32_t ror32(uint32_t word, unsigned int shift) ++{ ++	return (word >> (shift & 31)) | (word << ((-shift) & 31)); ++} ++ ++static const uint32_t blake2s_iv[8] = { ++	0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, ++	0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL ++}; ++ ++static const uint8_t blake2s_sigma[10][16] = { ++	{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, ++	{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, ++	{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, ++	{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, ++	{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, ++	{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, ++	{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, ++	{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, ++	{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, ++	{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, ++}; ++ ++static void blake2s_set_lastblock(struct blake2s_state *state) ++{ ++	state->f[0] = -1; ++} ++ ++static void blake2s_increment_counter(struct blake2s_state *state, const uint32_t inc) ++{ ++	state->t[0] += inc; ++	state->t[1] += (state->t[0] < inc); ++} ++ ++static void blake2s_init_param(struct blake2s_state *state, const uint32_t param) ++{ ++	int i; ++ ++	memset(state, 0, sizeof(*state)); ++	for (i = 0; i < 8; ++i) ++		state->h[i] = blake2s_iv[i]; ++	state->h[0] ^= param; ++} ++ ++static void blake2s_init(struct blake2s_state *state, const size_t outlen) ++{ ++	blake2s_init_param(state, 0x01010000 | outlen); ++	state->outlen = outlen; ++} ++ ++static void blake2s_compress(struct blake2s_state *state, const uint8_t *block, size_t nblocks, const uint32_t inc) ++{ ++	uint32_t m[16]; ++	uint32_t v[16]; ++	int i; ++ ++	while (nblocks > 0) { ++		blake2s_increment_counter(state, inc); ++		memcpy(m, block, BLAKE2S_BLOCK_LEN); ++		le32_to_cpu_array(m, ARRAY_SIZE(m)); ++		memcpy(v, state->h, 32); ++		v[ 8] = blake2s_iv[0]; ++		v[ 9] = blake2s_iv[1]; ++		v[10] = blake2s_iv[2]; ++		v[11] = blake2s_iv[3]; ++		v[12] = blake2s_iv[4] ^ state->t[0]; ++		v[13] = blake2s_iv[5] ^ state->t[1]; ++		v[14] = blake2s_iv[6] ^ state->f[0]; ++		v[15] = blake2s_iv[7] ^ state->f[1]; ++ ++#define G(r, i, a, b, c, d) do { \ ++	a += b + m[blake2s_sigma[r][2 * i + 0]]; \ ++	d = ror32(d ^ a, 16); \ ++	c += d; \ ++	b = ror32(b ^ c, 12); \ ++	a += b + m[blake2s_sigma[r][2 * i + 1]]; \ ++	d = ror32(d ^ a, 8); \ ++	c += d; \ ++	b = ror32(b ^ c, 7); \ ++} while (0) ++ ++#define ROUND(r) do { \ ++	G(r, 0, v[0], v[ 4], v[ 8], v[12]); \ ++	G(r, 1, v[1], v[ 5], v[ 9], v[13]); \ ++	G(r, 2, v[2], v[ 6], v[10], v[14]); \ ++	G(r, 3, v[3], v[ 7], v[11], v[15]); \ ++	G(r, 4, v[0], v[ 5], v[10], v[15]); \ ++	G(r, 5, v[1], v[ 6], v[11], v[12]); \ ++	G(r, 6, v[2], v[ 7], v[ 8], v[13]); \ ++	G(r, 7, v[3], v[ 4], v[ 9], v[14]); \ ++} while (0) ++		ROUND(0); ++		ROUND(1); ++		ROUND(2); ++		ROUND(3); ++		ROUND(4); ++		ROUND(5); ++		ROUND(6); ++		ROUND(7); ++		ROUND(8); ++		ROUND(9); ++ ++#undef G ++#undef ROUND ++ ++		for (i = 0; i < 8; ++i) ++			state->h[i] ^= v[i] ^ v[i + 8]; ++ ++		block += BLAKE2S_BLOCK_LEN; ++		--nblocks; ++	} ++} ++ ++static void blake2s_update(struct blake2s_state *state, const void *inp, size_t inlen) ++{ ++	const size_t fill = BLAKE2S_BLOCK_LEN - state->buflen; ++	const uint8_t *in = inp; ++ ++	if (!inlen) ++		return; ++	if (inlen > fill) { ++		memcpy(state->buf + state->buflen, in, fill); ++		blake2s_compress(state, state->buf, 1, BLAKE2S_BLOCK_LEN); ++		state->buflen = 0; ++		in += fill; ++		inlen -= fill; ++	} ++	if (inlen > BLAKE2S_BLOCK_LEN) { ++		const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_LEN); ++		blake2s_compress(state, in, nblocks - 1, BLAKE2S_BLOCK_LEN); ++		in += BLAKE2S_BLOCK_LEN * (nblocks - 1); ++		inlen -= BLAKE2S_BLOCK_LEN * (nblocks - 1); ++	} ++	memcpy(state->buf + state->buflen, in, inlen); ++	state->buflen += inlen; ++} ++ ++static void blake2s_final(struct blake2s_state *state, uint8_t *out) ++{ ++	blake2s_set_lastblock(state); ++	memset(state->buf + state->buflen, 0, BLAKE2S_BLOCK_LEN - state->buflen); ++	blake2s_compress(state, state->buf, 1, state->buflen); ++	cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); ++	memcpy(out, state->h, state->outlen); ++} ++ ++static size_t determine_optimal_seed_len(void) ++{ ++	size_t ret = 0; ++	char poolsize_str[11] = { 0 }; ++	int fd = open("/proc/sys/kernel/random/poolsize", O_RDONLY); ++ ++	if (fd < 0 || read(fd, poolsize_str, sizeof(poolsize_str) - 1) < 0) { ++		ewarn("Unable to determine pool size, falling back to %u bits: %s", MIN_SEED_LEN * 8, strerror(errno)); ++		ret = MIN_SEED_LEN; ++	} else ++		ret = DIV_ROUND_UP(strtoul(poolsize_str, NULL, 10), 8); ++	if (fd >= 0) ++		close(fd); ++	if (ret < MIN_SEED_LEN) ++		ret = MIN_SEED_LEN; ++	else if (ret > MAX_SEED_LEN) ++		ret = MAX_SEED_LEN; ++	return ret; ++} ++ ++static int read_new_seed(uint8_t *seed, size_t len, bool *is_creditable) ++{ ++	ssize_t ret; ++	int urandom_fd; ++ ++	*is_creditable = false; ++	ret = getrandom(seed, len, GRND_NONBLOCK); ++	if (ret == (ssize_t)len) { ++		*is_creditable = true; ++		return 0; ++	} ++	if (ret == -1 && errno == ENOSYS) { ++		struct pollfd random_fd = { ++			.fd = open("/dev/random", O_RDONLY), ++			.events = POLLIN ++		}; ++		if (random_fd.fd < 0) ++			return -errno; ++		*is_creditable = poll(&random_fd, 1, 0) == 1; ++		close(random_fd.fd); ++	} else if (getrandom(seed, len, GRND_INSECURE) == (ssize_t)len) ++		return 0; ++	urandom_fd = open("/dev/urandom", O_RDONLY); ++	if (urandom_fd < 0) ++		return -errno; ++	ret = read(urandom_fd, seed, len); ++	if (ret == (ssize_t)len) ++		ret = 0; ++	else ++		ret = -errno ? -errno : -EIO; ++	close(urandom_fd); ++	return ret; ++} ++ ++static int seed_rng(uint8_t *seed, size_t len, bool credit) ++{ ++	struct { ++		int entropy_count; ++		int buf_size; ++		uint8_t buffer[MAX_SEED_LEN]; ++	} req = { ++		.entropy_count = credit ? len * 8 : 0, ++		.buf_size = len ++	}; ++	int random_fd, ret; ++ ++	if (len > sizeof(req.buffer)) ++		return -EFBIG; ++	memcpy(req.buffer, seed, len); ++ ++	random_fd = open("/dev/random", O_RDWR); ++	if (random_fd < 0) ++		return -errno; ++	ret = ioctl(random_fd, RNDADDENTROPY, &req); ++	if (ret) ++		ret = -errno ? -errno : -EIO; ++	close(random_fd); ++	return ret; ++} ++ ++static int seed_from_file_if_exists(const char *filename, bool credit, struct blake2s_state *hash) ++{ ++	uint8_t seed[MAX_SEED_LEN]; ++	ssize_t seed_len; ++	int fd, dfd, ret = 0; ++ ++	fd = open(filename, O_RDONLY); ++	if (fd < 0 && errno == ENOENT) ++		return 0; ++	else if (fd < 0) { ++		ret = -errno; ++		eerror("Unable to open seed file: %s", strerror(errno)); ++		return ret; ++	} ++	dfd = open(SEED_DIR, O_DIRECTORY | O_RDONLY); ++	if (dfd < 0) { ++		ret = -errno; ++		close(fd); ++		eerror("Unable to open seed directory: %s", strerror(errno)); ++		return ret; ++	} ++	seed_len = read(fd, seed, sizeof(seed)); ++	if (seed_len < 0) { ++		ret = -errno; ++		eerror("Unable to read seed file: %s", strerror(errno)); ++	} ++	close(fd); ++	if (ret) { ++		close(dfd); ++		return ret; ++	} ++	if ((unlink(filename) < 0 || fsync(dfd) < 0) && seed_len) { ++		ret = -errno; ++		eerror("Unable to remove seed after reading, so not seeding: %s", strerror(errno)); ++	} ++	close(dfd); ++	if (ret) ++		return ret; ++	if (!seed_len) ++		return 0; ++ ++	blake2s_update(hash, &seed_len, sizeof(seed_len)); ++	blake2s_update(hash, seed, seed_len); ++ ++	einfo("Seeding %zd bits %s crediting", seed_len * 8, credit ? "and" : "without"); ++	ret = seed_rng(seed, seed_len, credit); ++	if (ret < 0) ++		eerror("Unable to seed: %s", strerror(-ret)); ++	return ret; ++} ++ ++static void populate_global_paths(void) ++{ ++	SEED_DIR = getenv("SEEDRNG_SEED_DIR"); ++	if (!SEED_DIR || !*SEED_DIR) ++		SEED_DIR = "/var/lib/seedrng"; ++	LOCK_FILE = getenv("SEEDRNG_LOCK_FILE"); ++	if (!LOCK_FILE || !*LOCK_FILE) ++		LOCK_FILE = "/var/run/seedrng.lock"; ++	xasprintf(&CREDITABLE_SEED, "%s/seed.credit", SEED_DIR); ++	xasprintf(&NON_CREDITABLE_SEED, "%s/seed.no-credit", SEED_DIR); ++} ++ ++int main(int argc _unused, char *argv[] _unused) ++{ ++	static const char seedrng_prefix[] = "SeedRNG v1 Old+New Prefix"; ++	static const char seedrng_failure[] = "SeedRNG v1 No New Seed Failure"; ++	int ret, fd, lock, program_ret = 0; ++	uint8_t new_seed[MAX_SEED_LEN]; ++	size_t new_seed_len; ++	bool new_seed_creditable; ++	struct timespec realtime = { 0 }, boottime = { 0 }; ++	struct blake2s_state hash; ++ ++	umask(0077); ++	if (getuid()) ++		eerrorx("This rc helper program requires root"); ++ ++	populate_global_paths(); ++	blake2s_init(&hash, BLAKE2S_HASH_LEN); ++	blake2s_update(&hash, seedrng_prefix, strlen(seedrng_prefix)); ++	clock_gettime(CLOCK_REALTIME, &realtime); ++	clock_gettime(CLOCK_BOOTTIME, &boottime); ++	blake2s_update(&hash, &realtime, sizeof(realtime)); ++	blake2s_update(&hash, &boottime, sizeof(boottime)); ++ ++	if (mkdir(SEED_DIR, 0700) < 0 && errno != EEXIST) ++		eerrorx("Unable to create \"%s\" directory: %s", SEED_DIR, strerror(errno)); ++ ++	lock = open(LOCK_FILE, O_WRONLY | O_CREAT, 0000); ++	if (lock < 0 || flock(lock, LOCK_EX) < 0) ++		eerrorx("Unable to open lock file: %s", strerror(errno)); ++ ++	ret = seed_from_file_if_exists(NON_CREDITABLE_SEED, false, &hash); ++	if (ret < 0) ++		program_ret |= 1 << 1; ++	ret = seed_from_file_if_exists(CREDITABLE_SEED, !rc_yesno(getenv("SEEDRNG_SKIP_CREDIT")), &hash); ++	if (ret < 0) ++		program_ret |= 1 << 2; ++ ++	new_seed_len = determine_optimal_seed_len(); ++	ret = read_new_seed(new_seed, new_seed_len, &new_seed_creditable); ++	if (ret < 0) { ++		eerror("Unable to read new seed: %s", strerror(-ret)); ++		new_seed_len = BLAKE2S_HASH_LEN; ++		strncpy((char *)new_seed, seedrng_failure, new_seed_len); ++		program_ret |= 1 << 3; ++	} ++	blake2s_update(&hash, &new_seed_len, sizeof(new_seed_len)); ++	blake2s_update(&hash, new_seed, new_seed_len); ++	blake2s_final(&hash, new_seed + new_seed_len - BLAKE2S_HASH_LEN); ++ ++	einfo("Saving %zu bits of %s seed for next boot", new_seed_len * 8, new_seed_creditable ? "creditable" : "non-creditable"); ++	fd = open(NON_CREDITABLE_SEED, O_WRONLY | O_CREAT | O_TRUNC, 0400); ++	if (fd < 0) { ++		eerror("Unable to open seed file for writing: %s", strerror(errno)); ++		program_ret |= 1 << 4; ++		goto out; ++	} ++	if (write(fd, new_seed, new_seed_len) != (ssize_t)new_seed_len || fsync(fd) < 0) { ++		eerror("Unable to write seed file: %s", strerror(errno)); ++		program_ret |= 1 << 5; ++		goto out; ++	} ++	if (new_seed_creditable && rename(NON_CREDITABLE_SEED, CREDITABLE_SEED) < 0) { ++		ewarn("Unable to make new seed creditable: %s", strerror(errno)); ++		program_ret |= 1 << 6; ++	} ++out: ++	close(fd); ++	close(lock); ++	return program_ret; ++} diff --git a/extra/openrc/sysctl.initd b/extra/openrc/sysctl.initd new file mode 100644 index 0000000..befdb91 --- /dev/null +++ b/extra/openrc/sysctl.initd @@ -0,0 +1,87 @@ +#!/sbin/openrc-run + +depend() +{ +	after clock +	before bootmisc logger +	keyword -prefix -systemd-nspawn -vserver +} + +start() +{ +	local quiet retval=0 status +	ebegin "Configuring kernel parameters" + +	yesno $rc_verbose || quiet=-q + +	eindent + +	for f in /lib/sysctl.d/*.conf \ +		/usr/lib/sysctl.d/*.conf; do + +		if  [ -f /etc/sysctl.d/"${f##*/}" ]; then +			veinfo "Ignoring $f due to /etc/sysctl.d/${f##*/}" +			continue +		fi + +		if [ -f /run/sysctl.d/"${f##*/}" ]; then +			veinfo "Ignoring $f due to /run/sysctl.d/${f##*/}" +			continue +		fi +	 +		if [ -f "$f" ]; then +			vebegin "applying $f" +			sysctl $quiet -p "$f" +			status=$? +			if [ $status -gt 0 ]; then +				# Don't change retval= since we expect some package/distro provided +				# sysctl configurations to break, so just warn when the user wants +				# verbose messages +				vewarn "Unable to configure kernel parameters from $f" +			fi +		fi +	done + +	for f in /etc/sysctl.d/*.conf; do + +		if [ -f /run/sysctl.d/"${f##*/}" ]; then +			veinfo "Ignoring $f due to /run/sysctl.d/${f##*/}" +			continue +		fi + +		if [ -f "$f" ]; then +			vebegin "applying $f" +			sysctl $quiet -p "$f" +			status=$? +			if [ $status -gt 0 ]; then +				retval=$(( $retval + $status )) +				eerror "Unable to configure kernel parameters from $f" +			fi +		fi +	done + +	if [ -f /etc/sysctl.conf ]; then +		vebegin "applying /etc/sysctl.conf" +		sysctl $quiet -p /etc/sysctl.conf +		status=$? +		if [ $status -gt 0 ]; then +			retval=$(( $retval + $status )) +			eerror "Unable to configure kernel parameters from /etc/sysctl.conf" +		fi +	fi + +	for f in /run/sysctl.d/*.conf; do +		if [ -f "$f" ]; then +			vebegin "applying $f" +			sysctl $quiet -p "$f" +			status=$? +			if [ $status -gt 0 ]; then +				retval=$(( $retval + $status )) +				eerror "Unable to configure kernel parameters from $f" +			fi +		fi +	done +	eoutdent + +	eend $retval +} diff --git a/extra/openrc/sysfsconf.initd b/extra/openrc/sysfsconf.initd new file mode 100644 index 0000000..433e51d --- /dev/null +++ b/extra/openrc/sysfsconf.initd @@ -0,0 +1,66 @@ +#!/sbin/openrc-run + +description="Set sysfs variables from /etc/sysfs.conf and /etc/sysfs.d/*.conf" +conffile=/etc/sysfs.conf +confdir=/etc/sysfs.d + +depend() { +	need sysfs +} + +setval() { +	local value="$1" attrib="$2" +	# Some fields need a terminating newline, others +	# need the terminating newline to be absent :-( +	echo -n "$value" > "$attrib" 2>/dev/null \ +		|| echo "$value" > "$attrib" +} + +load_conffile() { +	local file="$1" +	while read line; do +		local line=${line%%#*} +		local cmd= attrib= value= +		set -- $line +		if [ $# -eq 0 ]; then +			continue +		fi +		case "$1$3" in +			mode=)	cmd=chmod +				attrib="$2" +				value="$4" +				;; +			owner=) cmd=chown +				attrib="$2" +				value="$4" +				;; +			*)	if [ "$2" = "=" ]; then +					cmd=setval +					attrib="$1" +					value="$3" +				fi +				;;  +		esac +		if ! [ -e "/sys/$attrib" ]; then +			eerror "$attrib: unknown attribute" +			continue +		fi +		if [ -z "$attrib" ] || [ -z "$value" ]; then +			eerror "syntax error in $file: '$line'" +			continue +		fi +		$cmd "$value" "/sys/$attrib" +	done < "$file" +} + +start() { +	[ -r "$conffile" -o -d "$confdir" ] || return 0 +	ebegin "Setting sysfs variables" +	for file in $confdir/*.conf $conffile; do +		[ -r "$file" ] || continue +		load_conffile "$file" || return 1 +	done +	eend 0 + +} + diff --git a/extra/openrc/test-networking.sh b/extra/openrc/test-networking.sh new file mode 100644 index 0000000..5e5f70b --- /dev/null +++ b/extra/openrc/test-networking.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# unit tests for find_ifaces and find_running_ifaces in networking.initd + +cfgfile=/tmp/openrc-test-network.$$ +sourcefile=$cfgfile.source +sourcedir=$cfgfile.d +ifstate=$cfgfile.state + +cat >$cfgfile<<EOF +auto eth0 +iface eth0 inet dhcp + +source $sourcefile + +source-directory $sourcedir +EOF + +cat >$sourcefile<<EOF +auto eth1 +iface eth1 inet dhcp +EOF + +mkdir -p $sourcedir +cat >$sourcedir/a<<EOF +auto eth2 +iface eth2 inet dhcp +EOF + +cat >$ifstate<<EOF +eth4=eth4 1 +EOF + +errors=0 +fail() { +	echo "$@" +	errors=$(( $errors + 1)) +} + +# test fallback, when ifquery does not exist +ifquery=does-not-exist +. ./networking.initd + +find_ifaces | grep -q -w eth0 || fail "Did not find eth0" +find_ifaces | grep -q -E '(eth1|eth2)' && fail "Unexpectedly found eth1 or eth2" + +# test that ifquery finds source and source-directory +unset ifquery +. ./networking.initd +for i in eth0 eth1 eth2; do +	find_ifaces | grep -q -w "$i" || fail "Did not find $i" +done + +# test that ifquery picks up the running state file +find_running_ifaces | grep -q -w "eth4" || fail "Did not detect eth4 running" + + +# test /etc/init.d/net.eth5 +RC_SVCNAME=net.eth5 +. ./networking.initd +find_ifaces | grep -q -w "eth5" || fail "Did not detect eth5" +find_running_ifaces | grep -q -w "eth5" || fail "Did not detect eth5 running" + +rm -rf $cfgfile $sourcefile $sourcedir $ifstate +exit $errors | 
