We need to ensure that the init script started is correct, translating symlinks. This has a new rule - multiplexed services must exist in the same dir as the master sript. So we need to ensuret that net.lo(0) is the real script and not a symlink itself. This fixes Gentoo #219526.
This commit is contained in:
		
							
								
								
									
										4
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -26,3 +26,7 @@ mixer
 | 
			
		||||
nscd
 | 
			
		||||
powerd
 | 
			
		||||
syscons
 | 
			
		||||
net.lo
 | 
			
		||||
ttys
 | 
			
		||||
swap-blk
 | 
			
		||||
wscons
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,14 @@ SRCS=	bootmisc.in fsck.in halt.sh.in hostname.in local.in localmount.in \
 | 
			
		||||
	netmount.in root.in swap.in sysctl.in urandom.in
 | 
			
		||||
BIN=	${OBJS}
 | 
			
		||||
 | 
			
		||||
INSTALLAFTER=	_installafter
 | 
			
		||||
CLEANFILES+=	net.lo
 | 
			
		||||
TARGETS+=	net.lo
 | 
			
		||||
 | 
			
		||||
MK=	../mk
 | 
			
		||||
include ${MK}/os.mk
 | 
			
		||||
include Makefile.${OS}
 | 
			
		||||
include ${MK}/scripts.mk
 | 
			
		||||
 | 
			
		||||
_installafter: net.lo
 | 
			
		||||
	${INSTALL} -m ${BINMODE} net.lo ${DESTDIR}/${INITDIR}/${NET_LO}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
NET_LO=	net.lo0
 | 
			
		||||
 | 
			
		||||
# Generic BSD scripts
 | 
			
		||||
SRCS+=	hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
 | 
			
		||||
	rpcbind.in savecore.in syslogd.in
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
NET_LO=	net.lo
 | 
			
		||||
 | 
			
		||||
SRCS+=	hwclock.in consolefont.in keymaps.in modules.in mtab.in numlock.in \
 | 
			
		||||
	procfs.in termencoding.in
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
NET_LO=	net.lo0
 | 
			
		||||
 | 
			
		||||
# Generic BSD scripts
 | 
			
		||||
SRCS+=	hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
 | 
			
		||||
	rpcbind.in savecore.in syslogd.in
 | 
			
		||||
 
 | 
			
		||||
@@ -22,9 +22,9 @@ SED_REPLACE=		-e 's:@SHELL@:${SH}:g' -e 's:@LIB@:${LIBNAME}:g' -e 's:@SYSCONFDIR
 | 
			
		||||
.in:
 | 
			
		||||
	${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@
 | 
			
		||||
 | 
			
		||||
all: ${OBJS}
 | 
			
		||||
all: ${OBJS} ${TARGETS}
 | 
			
		||||
 | 
			
		||||
realinstall: ${BIN} ${CONF} ${CONF_APPEND}
 | 
			
		||||
realinstall: ${BIN} ${CONF} ${INC}
 | 
			
		||||
	@if test -n "${DIR}"; then \
 | 
			
		||||
		${ECHO} ${INSTALL} -d ${DESTDIR}/${DIR}; \
 | 
			
		||||
		${INSTALL} -d ${DESTDIR}/${DIR} || exit $$?; \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								sh/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								sh/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -4,3 +4,5 @@ net.sh
 | 
			
		||||
rc-functions.sh
 | 
			
		||||
runscript.sh
 | 
			
		||||
init.sh
 | 
			
		||||
ifwatchd-carrier.sh
 | 
			
		||||
ifwatchd-nocarrier.sh
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
DIR=	${PREFIX}/${RC_LIB}/sh
 | 
			
		||||
SRCS=	functions.sh.in gendepends.sh.in net.sh.in \
 | 
			
		||||
SRCS=	functions.sh.in gendepends.sh.in \
 | 
			
		||||
	rc-functions.sh.in runscript.sh.in
 | 
			
		||||
INC=	init-common-post.sh rc-mount.sh functions.sh rc-functions.sh
 | 
			
		||||
BIN=	gendepends.sh init.sh net.sh runscript.sh
 | 
			
		||||
BIN=	gendepends.sh init.sh runscript.sh
 | 
			
		||||
 | 
			
		||||
INSTALLAFTER=	_installafter
 | 
			
		||||
 | 
			
		||||
@@ -13,8 +13,6 @@ include ${MK}/scripts.mk
 | 
			
		||||
 | 
			
		||||
_installafter:
 | 
			
		||||
	${INSTALL} -d ${DESTDIR}/${INITDIR}
 | 
			
		||||
	@# Provide an init script for the loopback interface
 | 
			
		||||
	ln -snf ${PREFIX}/${RC_LIB}/sh/net.sh ${DESTDIR}/${INITDIR}/${NET_LO} || exit $$?
 | 
			
		||||
	@# Put functions.sh into the init.d dir so 3rd party apps don't have to
 | 
			
		||||
	@# be multilib aware
 | 
			
		||||
	ln -snf ${PREFIX}/${RC_LIB}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$?
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,5 @@
 | 
			
		||||
SRCS+=		init.sh.in
 | 
			
		||||
 | 
			
		||||
NET_LO=		net.lo0
 | 
			
		||||
 | 
			
		||||
.SUFFIXES:	.sh.BSD.in
 | 
			
		||||
.sh.BSD.in.sh:
 | 
			
		||||
	${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
NET_LO=		net.lo
 | 
			
		||||
SRCS+=		init.sh.in init-early.sh.in
 | 
			
		||||
BIN+=		init-early.sh
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
SRCS+=		init.sh.in
 | 
			
		||||
 | 
			
		||||
NET_LO=		net.lo0
 | 
			
		||||
SRCS+=		ifwatchd-carrier.sh.in ifwatchd-nocarrier.sh.in
 | 
			
		||||
BIN+=		ifwatchd-carrier.sh ifwatchd-nocarrier.sh
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <libgen.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
@@ -707,7 +708,8 @@ static void svc_start(bool deps)
 | 
			
		||||
	hook_out = RC_HOOK_SERVICE_START_OUT;
 | 
			
		||||
	rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet);
 | 
			
		||||
 | 
			
		||||
	if (rc_conf_yesno("rc_depend_strict"))
 | 
			
		||||
	errno = 0;
 | 
			
		||||
	if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT)
 | 
			
		||||
		depoptions |= RC_DEP_STRICT;
 | 
			
		||||
 | 
			
		||||
	if (deps) {
 | 
			
		||||
@@ -933,8 +935,8 @@ static void svc_stop(bool deps)
 | 
			
		||||
		ewarn ("WARNING: you are stopping a boot service");
 | 
			
		||||
 | 
			
		||||
	if (deps && ! (state & RC_SERVICE_WASINACTIVE)) {
 | 
			
		||||
 | 
			
		||||
		if (rc_conf_yesno("rc_depend_strict"))
 | 
			
		||||
		errno = 0;
 | 
			
		||||
		if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT)
 | 
			
		||||
			depoptions |= RC_DEP_STRICT;
 | 
			
		||||
 | 
			
		||||
		if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
 | 
			
		||||
@@ -1102,39 +1104,73 @@ int runscript(int argc, char **argv)
 | 
			
		||||
	int retval;
 | 
			
		||||
	int opt;
 | 
			
		||||
	RC_STRING *svc;
 | 
			
		||||
	char dir[PATH_MAX];
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	char lnk[PATH_MAX];
 | 
			
		||||
	size_t l = 0;
 | 
			
		||||
	size_t ll;
 | 
			
		||||
	char *save;
 | 
			
		||||
	char *dir, *save;
 | 
			
		||||
	const char *file;
 | 
			
		||||
	int depoptions = RC_DEP_TRACE;
 | 
			
		||||
	struct stat stbuf;
 | 
			
		||||
 | 
			
		||||
	/* Show help if insufficient args */
 | 
			
		||||
	if (argc < 2 || ! exists(argv[1])) {
 | 
			
		||||
		fprintf(stderr, "runscript is not meant to be to run directly\n");
 | 
			
		||||
		fprintf(stderr, "runscript should not be run directly\n");
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[1]);
 | 
			
		||||
	if (argc < 3)
 | 
			
		||||
		usage(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
	if (*argv[1] == '/')
 | 
			
		||||
		service = xstrdup(argv[1]);
 | 
			
		||||
	else {
 | 
			
		||||
		getcwd(dir, sizeof(dir));
 | 
			
		||||
		l = strlen(dir) + strlen(argv[1]) + 2;
 | 
			
		||||
		service = xmalloc(sizeof (char) * l);
 | 
			
		||||
		snprintf(service, l, "%s/%s", dir, argv[1]);
 | 
			
		||||
	if (stat(argv[1], &stbuf) != 0) {
 | 
			
		||||
		fprintf(stderr, "runscript `%s': %s\n",
 | 
			
		||||
			argv[1], strerror(errno));
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	atexit(cleanup);
 | 
			
		||||
 | 
			
		||||
	/* We need to work out the real full path to our service.
 | 
			
		||||
	 * This works fine, provided that we ONLY allow mulitplexed services
 | 
			
		||||
	 * to exist in the same directory as the master link.
 | 
			
		||||
	 * Also, the master link as to be a real file in the init dir. */
 | 
			
		||||
	if (!realpath(argv[1], path)) {
 | 
			
		||||
		fprintf(stderr, "realpath: %s\n", strerror(errno));
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
	memset(lnk, 0, sizeof(lnk));
 | 
			
		||||
	if (readlink(argv[1], lnk, sizeof(lnk)-1)) {
 | 
			
		||||
		dir = dirname(path);
 | 
			
		||||
		if (strchr(lnk, '/')) {
 | 
			
		||||
			save = xstrdup(dir);
 | 
			
		||||
			dir = dirname(lnk);
 | 
			
		||||
			if (strcmp(dir, save) == 0)
 | 
			
		||||
				file = basename_c(argv[1]);
 | 
			
		||||
			else
 | 
			
		||||
				file = basename_c(lnk);
 | 
			
		||||
			free(save);
 | 
			
		||||
			dir = dirname(path);
 | 
			
		||||
		} else
 | 
			
		||||
			file = basename_c(argv[1]);
 | 
			
		||||
		ll = strlen(dir) + strlen(file) + 2;
 | 
			
		||||
		service = xmalloc(ll);
 | 
			
		||||
		snprintf(service, ll, "%s/%s", dir, file);
 | 
			
		||||
		if (stat(service, &stbuf) != 0) {
 | 
			
		||||
			free(service);
 | 
			
		||||
			service = xstrdup(lnk);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (!service)
 | 
			
		||||
		service = xstrdup(path);
 | 
			
		||||
	applet = basename_c(service);
 | 
			
		||||
 | 
			
		||||
	if (argc < 3)
 | 
			
		||||
		usage(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
	/* Change dir to / to ensure all init scripts don't use stuff in pwd */
 | 
			
		||||
	chdir("/");
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
	/* coldplug events can trigger init scripts, but we don't want to run them
 | 
			
		||||
	   until after rc sysinit has completed so we punt them to the boot runlevel */
 | 
			
		||||
	/* coldplug events can trigger init scripts, but we don't want to run
 | 
			
		||||
	 * them until after rc sysinit has completed so we punt them to the
 | 
			
		||||
	 * boot runlevel */
 | 
			
		||||
	if (exists("/dev/.rcsysinit")) {
 | 
			
		||||
		eerror("%s: cannot run until sysvinit completes", applet);
 | 
			
		||||
		if (mkdir("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
 | 
			
		||||
@@ -1264,7 +1300,8 @@ int runscript(int argc, char **argv)
 | 
			
		||||
			   strcmp(optarg, "ibefore") == 0 ||
 | 
			
		||||
			   strcmp(optarg, "iprovide") == 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (rc_conf_yesno("rc_depend_strict"))
 | 
			
		||||
			errno = 0;
 | 
			
		||||
			if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT)
 | 
			
		||||
				depoptions |= RC_DEP_STRICT;
 | 
			
		||||
 | 
			
		||||
			if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user