Summary: | sys-apps/openrc: symlinked init scripts must be in the same directory as their symlink | ||
---|---|---|---|
Product: | Gentoo Hosted Projects | Reporter: | Manuel Danisch <oeffentlicheszeug> |
Component: | OpenRC | Assignee: | OpenRC Team <openrc> |
Status: | CONFIRMED --- | ||
Severity: | normal | CC: | bialut, bts, dmitry_b, jlec, jmbsvicetto, kirin.yuri, petr.bahula, roy, Sergiy.Borodych, vm |
Priority: | High | ||
Version: | unspecified | ||
Hardware: | AMD64 | ||
OS: | Linux | ||
See Also: | https://bugs.gentoo.org/show_bug.cgi?id=424589 | ||
Whiteboard: | |||
Package list: | Runtime testing required: | --- | |
Bug Depends on: | |||
Bug Blocks: | 374183 | ||
Attachments: |
My dynamic rule generation script
Patch to fix dirname() call in runscript.c 0001-do-not-treat-symbolic-links-specially-in-init.d.patch 0001-Improve-processing-of-conf.d-files.patch |
Description
Manuel Danisch
2011-01-07 00:06:35 UTC
post an actual file that can be downloaded, and then post the actual commands you're using to link in things and then execute (and show the actual output) moving a random init.d file out of /etc/init.d/ and symlinking it back seems to work fine for me. OK, here wo go. First some more information on my directory structure: my scripts are in /usr/local/svn-repo/scripts/sbin/, the filename is firewall.init. So the full path of the particular script is /usr/local/svn-repo/scripts/sbin/firewall.init. Additionally, /usr/local/sbin is a symlink to svn-repo/scripts/sbin, so I can run scripts in this directory also as root from command line. cd /usr/local ls -lh [...] sbin -> svn-repo/scripts/sbin [...] When I first installed this init-script, I made the following link: cd /etc/init.d ln -s /usr/local/sbin/firewall.init firewall With baselayout-1, I could now use /etc/init.d/firewall just like any other init-script. With baselayout-2, I did some more tests. This is what does work: cd /etc/init.d/ rm firewall cp -a /usr/local/sbin/firewall.init firewall => works rm firewall ln -s /usr/local/svn-repo/scripts/sbin/firewall.init . => works (as firewall.init) This does NOT work: cd /etc/init.d/ rm firewall ln -s /usr/local/sbin/firewall.init firewall => does not work rm firewall ln -s /usr/local/sbin/firewall.init . => going over the /usr/local/sbin/ symlink does not work at all rm firewall ln -s /usr/local/svn-repo/scripts/sbin/firewall.init firewall => changing the filename does not work either I'll attach a simplified version of firewall.init, so you could also test it. Created attachment 259462 [details]
My dynamic rule generation script
This script generates three files in /tmp, and generates from these files iptables-rules. When the script is stopped, nothing gets in and out over the net. If the script is started, but the three files are empty, traffic can go out and replies can get in. If subnets and ports are added to the files, a /etc/init.d/firewall reload automatically generates rules to allow incoming traffic for this port for this subnet.
Small update: today I tested openrc-0.7.0 which gave me the same error messages and the same behaviour like openrc-0.6.8. I reproduced this as well. The problem happens when the basename of the init script itself and the basename of the symlink linking to it are not the same. (In reply to comment #5) > The problem happens when the basename of the init script itself and the > basename of the symlink linking to it are not the same. > As you can see from my tests in comment #2, the problem also occurs when the path "goes over" a symlink. ln -s /usr/local/svn-repo/scripts/sbin/firewall.init . works, while ln -s /usr/local/sbin/firewall.init . does not work. As already mentioned, /usr/local/sbin is a symlink on my systems to /usr/local/svn-repo/scripts/sbin I just found the following text in the bugs section of the runscript man page: " Because of the way we load our configuration files and the need to handle more than one service directory, you can only use symlinks in service directories to other services in the same directory. You cannot symlink to a service in a different directory even if it is another service directory." This appears to be a known issue. What does everyone else think? if we're going to ban it, we should ban it. i.e. have runscript detect that the symlink contains path components and abort immediately. *** Bug 366617 has been marked as a duplicate of this bug. *** After the recent baselayout2/openrc stabilization I ran into this problem, too. If this behaviour is intended, it needs a better output than it currently has and which looks like a bug. Either way at least for me this is a major regression over the old versions. Managing/Versioning your custom scripts outside of /etc/init.d/ isn't an exotic requirement, I think. I have the same issue and really want to someone fix this regression or suggest alternative way *** Bug 366819 has been marked as a duplicate of this bug. *** *** Bug 365955 has been marked as a duplicate of this bug. *** I just ran into this yesterday. My company uses some custom init scripts where multiple different links in /etc/init.d symlink to the one script in an external directory (and perform different actions based on the SVCNAME). To work around this I have to temporarily make actual copies of the script in /etc/init.d. I could really use a solution to this one. Created attachment 273833 [details, diff]
Patch to fix dirname() call in runscript.c
The dirname() call at runscript.c:1136 modifies lnk, so an
incorrect name is returned by the basename() call at runscript.c:1140. The patch saves lnk before the call.
(In reply to comment #7) > I just found the following text in the bugs section of the runscript man page: > > " Because of the way we load our configuration files and the need to handle > more than one service directory, you can only use symlinks in service > directories to other services in the same directory. You cannot symlink > to a service in a different directory even if it is another service > directory." > > This appears to be a known issue. What does everyone else think? The issue is this /etc/init.d net.lo net.eth0 -> net.lo /etc/conf.d net /usr/local/etc/init.d net.lo net.eth1 -> net.lo /usr/local/conf.d net A perfectly valid setup, which works 100%. Now add net.eth2 in /etc/init.d which links to /usr/local/etc/init.d/net.lo Which config file is it supposed to use? The last I looked at this there may have been other complications, but that is the meaning behind that man page entry. (In reply to comment #16) > The issue is this > /etc/init.d > net.lo > net.eth0 -> net.lo > /etc/conf.d > net > /usr/local/etc/init.d > net.lo > net.eth1 -> net.lo > /usr/local/conf.d You mean /usr/local/etc/conf.d here right? Then perhaps 366819 and 365955 are not duplicates. (In reply to comment #17) > (In reply to comment #16) > > The issue is this > > /etc/init.d > > net.lo > > net.eth0 -> net.lo > > /etc/conf.d > > net > > /usr/local/etc/init.d > > net.lo > > net.eth1 -> net.lo > > /usr/local/conf.d > > You mean /usr/local/etc/conf.d here right? Right (In reply to comment #18) > Then perhaps 366819 and 365955 are not duplicates. I think that they are, but different entry points to the same problem. The easiest fix for those to is to remove ./ if it starts with ./ The bug report here though is more complex and sadly fits into my above scenario. I didn't come up with a reasonable fix, but I don't recall it erroring like it does now either. Now, you may ask *why* it's needed. And the reason is thus - to separate base system scripts from package scripts entirely which is how BSD portage equivalents work. package system borked? Want to change from pkgsrc to ports or portage? Just rm -rf /usr/pkg or /usr/local depending on setup and you're good to go. I see your point about the bug in this report and you're right that the fix for the others is trivial, so I don't want to belabor the point. Still, the dirname(3) manage says: Both dirname() and basename() may modify the contents of path, so copies should be passed to these functions. It would seem that these lines are a bug because, at the very least, they depend on undocumented behavior. 1136 dir = dirname(lnk); 1137 if (strcmp(dir, save) == 0) 1138 file = basename_c(argv[1]); 1139 else 1140 file = basename_c(lnk); *** Bug 365955 has been marked as a duplicate of this bug. *** *** Bug 365955 has been marked as a duplicate of this bug. *** Created attachment 281179 [details]
0001-do-not-treat-symbolic-links-specially-in-init.d.patch
All,
in my testing, this patch seems to fix the issue. It allows links in
init.d directories to point anywhere, but it requires that for an init.d
directory there is a conf.d directory at the same level in the tree to
hold configuration files that match the services in the init.d
directory.
I need comments and testing for this fix.
In particular, does it still allow BSDs to work properly?
Created attachment 281201 [details]
0001-Improve-processing-of-conf.d-files.patch
All,
after discussion with robbat2, I came up with this patch. Now besides
checking in the relative ../conf.d directory for configuration files, we
also check @sysconfdir@/conf.d.
I have tested this patch and it works here, so if there are no
objections I will commit it to the tree.
Can anyone say if this patch is OK for BSDs as well?
This patch, including an update to the man page, has been implemented in commit 0c8bea2. All, we need to re-visit this bug. The commit I mentioned that seemed to fix the issue causes the regression in bug #392457. Also, the RC_SERVICE environment variable is now set incorrectly, so I don't know of what other possible regressions it might be causing. I would like to revert this commit asap and work out another fix. *** Bug 411583 has been marked as a duplicate of this bug. *** It seems to me that you could just use: service = realpath(argv[1], NULL); // from #392457 comment 3 applet = basename_c(argv[1]); ..as the applet name is always present in the argument, even if run from within /etc/init.d, eg as ./net.eth0 Sorry if I'm missing something obvious. WRT to the shell patch, wouldn't: if [ -f "${RC_SERVICE%/*}/../conf.d" ]; then loadconfig "${RC_SERVICE%/*}/../conf.d" else loadconfig "@SYSCONFDIR@/conf.d" fi ..be more what the user is after? > if [ -f "${RC_SERVICE%/*}/../conf.d" ]; then
Doh, that should be -d not -f ofc. (I just think it's a bit safer, but might not be what you want.)
Sorry for noise.
*** Bug 425656 has been marked as a duplicate of this bug. *** *** Bug 470854 has been marked as a duplicate of this bug. *** |