Compare commits

...

20 Commits
0.45 ... 0.46

Author SHA1 Message Date
William Hubbs
9ef74594df version 0.46 2023-01-05 00:31:37 -06:00
William Hubbs
59e9637647 update news 2023-01-05 00:22:41 -06:00
Nikolaos Chatzikonstantinou
35077afb68 build: fix run_command warning
The default behavior of check: false is going to change to true in the
future, see <https://github.com/mesonbuild/meson/issues/9300>.

Thus we are explicit about the desired behavior. The error in uname is
important but with test we check ourselves using returncode().

This fixes #556.
2022-12-08 11:06:09 -06:00
William Hubbs
02b064a591 src/swclock: make the reference file a required argument 2022-12-08 09:56:50 -06:00
William Hubbs
839083bb52 make the location of the swclock reference file configurable
This fixes #565.
2022-12-08 09:56:40 -06:00
Mike Gilbert
1364e6631c start-stop-daemon: use a pipe to sync parent/child processes
This fixes #557.
2022-12-07 17:12:24 -06:00
Jakub Jirutka
953172c6c6 supervise-daemon: don't overwrite empty supervise_daemon_args
If supervise_daemon_args is not set *or empty*, it defaults to
`start_stop_daemon_args`. This is bad because supervise-daemon doesn't
accept the same options as `start-stop-daemon`. So if we set e.g.
`start_stop_daemon_args="--wait 50"`, but not `supervise_daemon_args`,
and the user adds `supervisor=supervise-daemon` to the corresponding
/etc/conf.d/<service> file, the service will fail to start due to
unrecognized option "wait".

It would be best to remove this fallback, but that might break some
existing scripts that depend on it. So this commit just changes it to
use `start_stop_daemon_args` as the default for `supervise_daemon_args`
only if `supervise_daemon_args` is not set at all, but not if it's
empty.

This at least simplifies workarounds; we can just add
`supervise_daemon_args="$supervise_daemon_args"` to init scripts.

This fixes #558.
2022-12-07 16:42:14 -06:00
Sam James
0525de4f18 librc-depend: fix -Wmismatched-dealloc
Despite this being a 'deptree', it's actually
xmalloc'd in the same function (rc_deptree_update),
and so should be free'd, not rc_deptree_free'd,
as rc_deptree_load* wasn't used to allocate it.

```
[71/213] Compiling C object src/librc/librc.so.1.p/librc-depend.c.o
../src/librc/librc-depend.c: In function ‘rc_deptree_update’:
../src/librc/librc-depend.c:1077:9: warning: ‘rc_deptree_free’ called on pointer returned from a mismatched allocation function [-Wmismatched-dealloc]
 1077 |         rc_deptree_free(deptree);
      |         ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../src/shared/misc.h:29,
                 from ../src/librc/librc.h:57,
                 from ../src/librc/librc-depend.c:21:
In function ‘xmalloc’,
    inlined from ‘rc_deptree_update’ at ../src/librc/librc-depend.c:775:12:
../src/shared/helpers.h:64:23: note: returned from ‘malloc’
   64 |         void *value = malloc(size);
      |                       ^~~~~~~~~~~~
```

This fixes #563.
2022-12-07 11:35:16 -06:00
Stefan Linke
9380347f04 Avoid warning on grep 3.8 in hwclock
Starting with grep version 3.8, the hwclock init script logs warnings
about stray backslashes:

> hwclock | * Setting system clock using the hardware clock [UTC] ...
> hwclock |grep: warning: stray \ before -
> hwclock |grep: warning: stray \ before -

This is caused by the check for existence of the `--noadjfile` argument
in function `get_noadjfile()`.

Replacing the affected logic with an explicit argument denoting the
pattern as such resolves the issue.

Fixes #548
2022-09-07 11:59:30 -04:00
Matt Whitlock
112b69860f start-stop-daemon, supervise-daemon: set autogroup nicelevel
As described in "Why nice levels are a placebo and have been for a very
long time, and no one seems to have noticed"[1], the Linux kernel in its
default configuration on many Linux distributions autogroups tasks by
session ID and "fairly" allocates CPU time among such autogroups. The
nice levels of tasks within each autogroup are only relative to
other tasks within the same autogroup. Effectively, this means that the
traditional nice level is rendered moot for tools like start-stop-daemon
and supervise-daemon, which start each daemon in its own session and
thus in its own autogroup. Linux does provide a means to change the
niceness of autogroups relative to each other, so let's have start-stop-
daemon and supervise-daemon make use of this feature where available so
that -N,--nicelevel/SSD_NICELEVEL will actually do what the user
intends. On systems where autogroups are not supported or are disabled,
this commit introduces no change in behavior.

Note that the setsid() call in the child process of start-stop-daemon is
moved to much earlier. This is necessary so that the new process will be
assigned to a new autogroup before the autogroup nicelevel is set. To
avoid inadvertently acquiring /dev/tty as the controlling terminal of
the new session after setsid() has given up the controlling terminal
inherited from the parent process, tty_fd is opened before the call to
setsid().

[1] https://www.reddit.com/r/linux/comments/d7hx2c/why_nice_levels_are_a_placebo_and_have_been_for_a/
This fixes #542.
2022-09-06 17:26:22 -05:00
Sören Tempel
d21dde73ba init.d/root: don't remount swap
While refactoring the changes proposed in #533 a minor error was
introduced were the root service will now attempt to remount swap.
This will fail with the error message `mountinfo: 'swap' is not a
mountpoint`.

This fixes #546
2022-09-04 18:44:47 -05:00
William Hubbs
9b08de926b Revert "start-stop-daemon: use vfork to avoid races"
This is broken, so revert it and reopen #532.

This reverts commit 9e5ce59a21.
2022-09-02 17:27:39 -05:00
Sören Tempel
f60d42e901 init.d/root: also remount / with options provided in /etc/fstab
Without this commit, the root OpenRC service remounts all mounted
filesystems (except /) with the options defined in /etc/fstab via
fstabinfo. It is presently unclear to me why / was excluded from
remounting in 497ff7ee41 and unfortunately
neither the commit nor the associated Bugzilla issue [1] provides
further information on this.

At Alpine, our initramfs does currently not remount / with all options
defined in /etc/fstab [2]. As part of the discussion on the Alpine side
of things we wondered why OpenRC does not remount / since this would be
the easier solution for us. For this reason, this commit changes the
behavior of the OpenRC root services accordingly to also remount / with
the options defined in /etc/fstab.

[1]: https://bugs.gentoo.org/401573
[2]: https://gitlab.alpinelinux.org/alpine/mkinitfs/-/merge_requests/103
This fixes #533.
2022-09-02 13:41:44 -05:00
Arusekk
9e5ce59a21 start-stop-daemon: use vfork to avoid races
While running `rc-service start docker` on Gentoo,
I found that the command does not start the service 90% of the time,
with an enigmatic 'service crashed' message.

The root cause of this is apparently rc-service spawning a pty,
running start-stop-daemon inside that pty, and exitting,
before start-stop-daemon child process calls setsid(),
which results in the child process being killed with SIGHUP (SI_KERNEL).

Theoretically this bug was present ever since the file was created in
5af58b4514 ("Rewrite the core parts in C. We now provide...")
(or even before that), but it should have been only a minor issue before
45bd125dcc ("Use a pty for prefixed output instead of pipes for...").
Not sure why nobody has had the issue so far (it has been present for
almost 15 years).

As here setsid() is the last call before execve(), the most natural
locking mechanism is vfork(), as it gives back control to parent
process only after execve() or process termination.
So this way the bug can be fixed by adding a single letter. :-)

Another way to ensure this would be using an O_CLOEXEC file descriptor
or some custom lock, which would need to be released not before setsid().

Fixes: 5af58b4514 ("Rewrite the core parts in C. We now provide...")
Fixes #532.
2022-09-02 12:41:09 -05:00
xdavidwu
95dc83bfbc openrc: fix help messages
The two lines seem to both belong to --override, but made into seperate
array elements accidentally, making options after --override and their
help mismatch. This fixes it.
2022-07-21 03:53:42 -04:00
psykose
14b153c1a4 fix quoting of loggers in start-stop-daemon
previously broken in 6034866d1c
caused *_logger options to be passed unquoted, so
`error_logger="logger -t .."` would pass -t to s-s-d and fail to start
the service.

Fixes: #531
2022-07-03 12:40:34 -05:00
William Hubbs
3cc4c01485 remove trailing space 2022-06-28 17:21:54 -05:00
William Hubbs
414f398498 modules.in: always return 0, make loading more verbose 2022-06-27 17:32:42 -05:00
William Hubbs
107b23819d restore the init symlink for sysvinit mode
This symlink got lost in the transition to meson.

X-Gentoo-Bug: 850754
X-Gentoo-Bug-URL: https://bugs.gentoo.org/850754
2022-06-10 10:28:57 -05:00
William Hubbs
d2b3144070 clean up hostname service script
- use _ throw-away variable to get rid of a shellcheck warning
- remove tests for /etc/hostname and just try to read it
- drop reference to bash HOSTNAME variable.
- make source of host name more accurate

X-Gentoo-Bug: 850577
X-Gentoo-Bug-URL: https://bugs.gentoo.org/850577
2022-06-08 13:40:29 -05:00
17 changed files with 108 additions and 34 deletions

21
NEWS.md
View File

@@ -4,6 +4,27 @@ OpenRC NEWS
This file will contain a list of notable changes for each release. Note
the information in this file is in reverse order.
## OpenRC 0.46
The path for the reference file for the swclock service is now
configurable in conf.d/swclock.
In the past, if supervise_daemon_args was not set *or empty*, it defaulted to
`start_stop_daemon_args`. This was bad because supervise-daemon doesn't
accept the same options as `start-stop-daemon`. So if we set e.g.
`start_stop_daemon_args="--wait 50"`, but not `supervise_daemon_args`,
and the user adds `supervisor=supervise-daemon` to the corresponding
conf.d/<service> file, the service will fail to start due to
unrecognized option "wait".
It would be best to remove this fallback, but that might break some
existing scripts that depend on it. So we are changing it to
use `start_stop_daemon_args` as the default for `supervise_daemon_args`
only if `supervise_daemon_args` is not set at all, but not if it's
empty.
This fallback will be dropped in a future release.
## OpenRC 0.45
The old make-based build system is removed in this release.

View File

@@ -7,6 +7,7 @@ conf_common = [
'localmount',
'netmount',
'swap',
'swclock',
]
conf_net = [

6
conf.d/swclock Normal file
View File

@@ -0,0 +1,6 @@
# This is the location of the reference file swclock uses to set the
# system date and time.
# This is the default path. If you are using it, you do not need to
# uncomment it. If you are using the default and have /var on its own
# file system, you need to add the appropriate rc_after setting.
# swclock_file=/var/lib/misc/openrc-shutdowntime

View File

@@ -19,20 +19,18 @@ depend()
start()
{
local h source x
if [ -s /etc/hostname ] && [ -r /etc/hostname ]; then
read h x </etc/hostname
source="from /etc/hostname"
else
# HOSTNAME variable used to be defined in caps in conf.d/hostname.
# It is also a magic variable in bash.
h=${hostname:-${HOSTNAME}} # checkbashisms: false positive (HOSTNAME var)
local h source
if read -r h _ 2> /dev/null < @SYSCONFDIR@/hostname; then
source="@SYSCONFDIR@/hostname"
elif [ -n "${hostname}" ]; then
h=${hostname}
source="@SYSCONFDIR@/conf.d/${RC_SVCNAME}"
fi
if [ -z "$h" ]; then
einfo "Using default system hostname"
return 0
fi
ebegin "Setting hostname to $h $source"
ebegin "Setting hostname to $h from $source"
hostname "$h"
eend $? "Failed to set the hostname"
}

View File

@@ -72,7 +72,7 @@ get_noadjfile()
{
if ! yesno $clock_adjfile; then
# Some implementations don't handle adjustments
if LC_ALL=C hwclock --help 2>&1 | grep -q "\-\-noadjfile"; then
if LC_ALL=C hwclock --help 2>&1 | grep -q -e "--noadjfile"; then
echo --noadjfile
fi
fi

View File

@@ -56,10 +56,10 @@ load_modules()
ebegin "Loading module $x"
case "$RC_UNAME" in
FreeBSD) kldload "$x"; rc=$? ;;
Linux) modprobe --first-time -q --use-blacklist "$x"; rc=$? ;;
Linux) modprobe --first-time --use-blacklist --verbose "$x"; rc=$? ;;
*) ;;
esac
eend $rc "Failed to load $x"
eend
done
return 0
}
@@ -80,9 +80,10 @@ FreeBSD_modules()
for x in $modules; do
ebegin "Loading module $x"
kldload "$x"
eend $? "Failed to load $x" && : $(( cnt += 1 ))
eend && : $(( cnt += 1 ))
done
einfo "Autoloaded $cnt module(s)"
return 0
}
Linux_modules()
@@ -122,6 +123,7 @@ Linux_modules()
eval modprobe --first-time --use-blacklist --verbose "$x" "$args"
done
[ -n "$list" ] && eend
return 0
}
start()

View File

@@ -49,9 +49,7 @@ start()
local mountpoint
for mountpoint in $(fstabinfo); do
case "${mountpoint}" in
/)
;;
/*)
/*) # Don't remount swap etc.
mountinfo -q "${mountpoint}" && \
fstabinfo --remount "${mountpoint}"
;;

View File

@@ -10,6 +10,7 @@
# except according to the terms contained in the LICENSE file.
description="Sets the local clock to the mtime of a given file."
swclock_file="${swclock_file:-/var/lib/misc/openrc-shutdowntime}"
depend()
{
@@ -22,7 +23,7 @@ depend()
start()
{
ebegin "Setting the local clock based on last shutdown time"
if ! swclock 2> /dev/null; then
if ! swclock "${swclock_file}" 2> /dev/null; then
swclock --warn @SBINDIR@/openrc-run
fi
eend $?
@@ -31,6 +32,6 @@ start()
stop()
{
ebegin "Saving the shutdown time"
swclock --save
swclock --save "${swclock_file}"
eend $?
}

View File

@@ -1,5 +1,5 @@
project('OpenRC', 'c',
version : '0.45',
version : '0.46',
license: 'BSD-2',
default_options : [
'c_std=c99',
@@ -36,7 +36,7 @@ endif
option_os = get_option('os')
if option_os == ''
uname = find_program('uname')
r = run_command(uname, '-s')
r = run_command(uname, '-s', check: true)
os = r.stdout().strip()
os = '-'.join(os.split('/'))
else
@@ -84,7 +84,7 @@ else
endif
if get_option('split-usr') == 'auto'
split_usr = run_command('test', '-L', '/bin').returncode() != 0
split_usr = run_command('test', '-L', '/bin', check: false).returncode() != 0
else
split_usr = get_option('split-usr') == 'true'
endif
@@ -226,4 +226,6 @@ meson.add_install_script('tools/meson_runlevels.sh',
get_option('sysvinit') ? 'yes' : 'no')
meson.add_install_script('tools/meson_final.sh',
rc_libexecdir,
os)
sbindir,
os,
get_option('sysvinit') ? 'yes' : 'no')

View File

@@ -47,8 +47,8 @@ ssd_start()
${directory:+--chdir} $directory \
${output_log+--stdout} $output_log \
${error_log+--stderr} $error_log \
${output_logger:+--stdout-logger} "$output_logger" \
${error_logger:+--stderr-logger} "$error_logger" \
${output_logger:+--stdout-logger \"$output_logger\"} \
${error_logger:+--stderr-logger \"$error_logger\"} \
${capabilities+--capabilities} "$capabilities" \
${secbits:+--secbits} "$secbits" \
${no_new_privs:+--no-new-privs} \

View File

@@ -41,7 +41,7 @@ supervise_start()
${no_new_privs:+--no_new_privs} \
${command_user+--user} $command_user \
${umask+--umask} $umask \
${supervise_daemon_args:-${start_stop_daemon_args}} \
${supervise_daemon_args-${start_stop_daemon_args}} \
$command \
-- $command_args $command_args_foreground
rc=$?

View File

@@ -1074,6 +1074,6 @@ rc_deptree_update(void)
}
rc_stringlist_free(config);
rc_deptree_free(deptree);
free(deptree);
return retval;
}

View File

@@ -64,8 +64,7 @@ const struct option longopts[] = {
};
const char * const longopts_help[] = {
"do not stop any services",
"override the next runlevel to change into\n",
"when leaving single user or boot runlevels",
"override the next runlevel to change into\nwhen leaving single user or boot runlevels",
"runs the service specified with the rest\nof the arguments",
"output the RC system type, if any",
longopts_help_COMMON

View File

@@ -354,6 +354,9 @@ int main(int argc, char **argv)
#ifdef PR_SET_NO_NEW_PRIVS
bool no_new_privs = false;
#endif
int pipefd[2];
char readbuf[1];
ssize_t ss;
applet = basename_c(argv[0]);
atexit(cleanup);
@@ -864,12 +867,17 @@ int main(int argc, char **argv)
if (background)
signal_setup(SIGCHLD, handle_signal);
/* Use a pipe to sync the parent/child processes. */
if (pipe2(pipefd, O_CLOEXEC) == -1)
eerrorx("%s: pipe2: %s", applet, strerror(errno));
if ((pid = fork()) == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
/* Child process - lets go! */
if (pid == 0) {
pid_t mypid = getpid();
close(pipefd[0]); /* Close the read end of the pipe. */
umask(numask);
#ifdef TIOCNOTTY
@@ -878,11 +886,23 @@ int main(int argc, char **argv)
devnull_fd = open("/dev/null", O_RDWR);
/* Must call setsid() before setting autogroup nicelevel
* but after opening tty_fd. */
setsid();
if (nicelevel != INT_MIN) {
if (setpriority(PRIO_PROCESS, mypid, nicelevel) == -1)
eerrorx("%s: setpriority %d: %s",
applet, nicelevel,
strerror(errno));
/* Open in "r+" mode to avoid creating if non-existent. */
fp = fopen("/proc/self/autogroup", "r+");
if (fp) {
fprintf(fp, "%d\n", nicelevel);
fclose(fp);
} else if (errno != ENOENT)
eerrorx("%s: autogroup nice %d: %s", applet,
nicelevel, strerror(errno));
}
if (ionicec != -1 &&
@@ -1085,7 +1105,8 @@ int main(int argc, char **argv)
dup2(stderr_fd, STDERR_FILENO);
for (i = getdtablesize() - 1; i >= 3; --i)
close(i);
if (i != pipefd[1])
close(i);
if (scheduler != NULL) {
int scheduler_index;
@@ -1118,7 +1139,6 @@ int main(int argc, char **argv)
eerrorx("Failed to set scheduler parameters: %s", strerror(errno));
}
setsid();
execvp(exec, argv);
#ifdef HAVE_PAM
if (changeuser != NULL && pamr == PAM_SUCCESS)
@@ -1129,6 +1149,18 @@ int main(int argc, char **argv)
}
/* Parent process */
close(pipefd[1]); /* Close the write end of the pipe. */
/* The child never writes to the pipe, so this read will block until
* the child calls exec or exits. */
while ((ss = read(pipefd[0], readbuf, 1)) == -1 && errno == EINTR);
if (ss == -1)
eerrorx("%s: failed to read from pipe: %s",
applet, strerror(errno));
close(pipefd[0]);
if (!background) {
/* As we're not backgrounding the process, wait for our pid
* to return */

View File

@@ -391,6 +391,14 @@ static void child_process(char *exec, char **argv)
if (setpriority(PRIO_PROCESS, getpid(), nicelevel) == -1)
eerrorx("%s: setpriority %d: %s", applet, nicelevel,
strerror(errno));
/* Open in "r+" mode to avoid creating if non-existent. */
fp = fopen("/proc/self/autogroup", "r+");
if (fp) {
fprintf(fp, "%d\n", nicelevel);
fclose(fp);
} else if (errno != ENOENT)
eerrorx("%s: autogroup nice %d: %s", applet,
nicelevel, strerror(errno));
}
if (ionicec != -1 && ioprio_set(1, getpid(), ionicec | ioniced) == -1)

View File

@@ -34,7 +34,6 @@
#include "misc.h"
#include "_usage.h"
#define RC_SHUTDOWNTIME RC_SVCDIR "/shutdowntime"
const char *applet = NULL;
const char *extraopts = "file";
@@ -54,7 +53,7 @@ const char *usagestring = NULL;
int main(int argc, char **argv)
{
int opt, sflag = 0, wflag = 0;
const char *file = RC_SHUTDOWNTIME;
const char *file = NULL;
struct stat sb;
struct timeval tv;
@@ -75,6 +74,8 @@ int main(int argc, char **argv)
if (optind < argc)
file = argv[optind++];
else
eerrorx("swclock: Reference file was not specified");
if (sflag) {
if (stat(file, &sb) == -1) {

View File

@@ -4,10 +4,15 @@ set -e
set -u
rc_libexecdir="$1"
os="$2"
sbindir="$2"
os="$3"
sysvinit="$4"
if [ ${os} != Linux ]; then
if [ "${os}" != Linux ]; then
install -d "${DESTDIR}/${rc_libexecdir}"/init.d
fi
install -d "${DESTDIR}/${rc_libexecdir}"/tmp
install -m 644 "${MESON_BUILD_ROOT}/src/shared/version" "${DESTDIR}/${rc_libexecdir}"
if [ "${os}" = Linux ] && [ "${sysvinit}" = yes ]; then
ln -s openrc-init "${DESTDIR}/${sbindir}"/init
fi