Compare commits

...

4 Commits

Author SHA1 Message Date
David Tardon 02baf239d8 add test for ExecStopPost
This is a follow-up to #4843.
2019-10-18 16:13:47 +02:00
Benjamin Bouvier e4fc745547 systemd-fsck: fix systemd-fsck/fsck pipe bad closure
Currently, when console is disabled but progress is tracked, pipe opened
for communication between systemd-fsck and fsck may be closed
inadvertently (when opening of /dev/console return in error). That lead
to finish fsck prematurely (because it receives a SIGPIPE) and so fsck
may not check correctly filesystems and do not have time to fix memory
corruptions.

This commit changes the opening of /dev/console to be done previously to
pipe creation and so fix the bug described just above.
2019-10-18 16:07:00 +02:00
Aaron Plattner ab84cf9191 coredump: Include module offsets in stack traces
These offsets can be useful to decode stack traces through modules that don't
have symbol names. For example, with a simple test that crashes after calling
through several static functions, systemd-coredump reports this:

 Oct 17 : Process 640333 (a.out) of user 1000 dumped core.

          Stack trace of thread 640333:
          #0  0x00005562c2b9f11d n/a (/tmp/a.out)
          #1  0x00005562c2b9f12d n/a (/tmp/a.out)
          #2  0x00005562c2b9f139 n/a (/tmp/a.out)
          #3  0x00005562c2b9f145 n/a (/tmp/a.out)
          #4  0x00007fc768b39153 __libc_start_main (libc.so.6)
          #5  0x00005562c2b9f04e n/a (/tmp/a.out)

With this change:

          Stack trace of thread 666897:
          #0  0x0000555668fbe11d n/a (/tmp/a.out + 0x111d)
          #1  0x0000555668fbe12d n/a (/tmp/a.out + 0x112d)
          #2  0x0000555668fbe139 n/a (/tmp/a.out + 0x1139)
          #3  0x0000555668fbe145 n/a (/tmp/a.out + 0x1145)
          #4  0x00007f7b5c828153 __libc_start_main (libc.so.6 + 0x27153)
          #5  0x0000555668fbe04e n/a (/tmp/a.out + 0x104e)

Disassembling the test binary shows that these offsets line up:

 0000000000001119 <crash>:
     1119:      55                      push   %rbp
     111a:      48 89 e5                mov    %rsp,%rbp
     111d:      0f 0b                   ud2                 <---- #0

 000000000000111f <b>:
     111f:      55                      push   %rbp
     1120:      48 89 e5                mov    %rsp,%rbp
     1123:      b8 00 00 00 00          mov    $0x0,%eax
     1128:      e8 ec ff ff ff          callq  1119 <crash>
     112d:      90                      nop                 <---- #1
     112e:      5d                      pop    %rbp
     112f:      c3                      retq

 0000000000001130 <a>:
     1130:      55                      push   %rbp
     1131:      48 89 e5                mov    %rsp,%rbp
     1134:      e8 e6 ff ff ff          callq  111f <b>
     1139:      90                      nop                 <---- #2
     113a:      5d                      pop    %rbp
     113b:      c3                      retq

 000000000000113c <main>:
     113c:      55                      push   %rbp
     113d:      48 89 e5                mov    %rsp,%rbp
     1140:      e8 eb ff ff ff          callq  1130 <a>
     1145:      b8 00 00 00 00          mov    $0x0,%eax    <---- #3
     114a:      5d                      pop    %rbp
     114b:      c3                      retq
     114c:      0f 1f 40 00             nopl   0x0(%rax)

 (from libc.so.6)
 0000000000027060 <__libc_start_main>:
   27060:	f3 0f 1e fa          	endbr64
   27064:	41 56                	push   %r14
   27066:	31 c0                	xor    %eax,%eax
   [...]
   2714c:	48 8b 44 24 18       	mov    0x18(%rsp),%rax
   27151:	ff d0                	callq  *%rax
   27153:	89 c7                	mov    %eax,%edi    <---- #4
   27155:	e8 e6 76 01 00       	callq  3e840 <exit>
2019-10-18 15:26:47 +02:00
Dan Streetman 626fbf7f70 test: blacklist TEST-41 on Ubuntu CI
This test has been failing on Ubuntu CI since introduced, let's
blacklist it until we can debug what's causing it to fail.
2019-10-18 15:21:32 +02:00
6 changed files with 164 additions and 11 deletions

View File

@ -32,6 +32,7 @@ static int frame_callback(Dwfl_Frame *frame, void *userdata) {
const char *fname = NULL, *symbol = NULL; const char *fname = NULL, *symbol = NULL;
Dwfl_Module *module; Dwfl_Module *module;
bool is_activation; bool is_activation;
uint64_t module_offset = 0;
assert(frame); assert(frame);
assert(c); assert(c);
@ -48,6 +49,7 @@ static int frame_callback(Dwfl_Frame *frame, void *userdata) {
if (module) { if (module) {
Dwarf_Die *s, *cudie; Dwarf_Die *s, *cudie;
int n; int n;
Dwarf_Addr start;
cudie = dwfl_module_addrdie(module, pc_adjusted, &bias); cudie = dwfl_module_addrdie(module, pc_adjusted, &bias);
if (cudie) { if (cudie) {
@ -73,10 +75,11 @@ static int frame_callback(Dwfl_Frame *frame, void *userdata) {
if (!symbol) if (!symbol)
symbol = dwfl_module_addrname(module, pc_adjusted); symbol = dwfl_module_addrname(module, pc_adjusted);
fname = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL); fname = dwfl_module_info(module, NULL, &start, NULL, NULL, NULL, NULL, NULL);
module_offset = pc - start;
} }
fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s)\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname)); fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s + 0x%" PRIx64 ")\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname), module_offset);
c->n_frame++; c->n_frame++;
return DWARF_CB_OK; return DWARF_CB_OK;

View File

@ -156,8 +156,8 @@ static double percent(int pass, unsigned long cur, unsigned long max) {
(double) cur / (double) max; (double) cur / (double) max;
} }
static int process_progress(int fd) { static int process_progress(int fd, FILE* console) {
_cleanup_fclose_ FILE *console = NULL, *f = NULL; _cleanup_fclose_ FILE *f = NULL;
usec_t last = 0; usec_t last = 0;
bool locked = false; bool locked = false;
int clear = 0, r; int clear = 0, r;
@ -172,10 +172,6 @@ static int process_progress(int fd) {
return log_debug_errno(errno, "Failed to use pipe: %m"); return log_debug_errno(errno, "Failed to use pipe: %m");
} }
console = fopen("/dev/console", "we");
if (!console)
return log_debug_errno(errno, "Failed to open /dev/console, can't print progress output: %m");
for (;;) { for (;;) {
int pass, m; int pass, m;
unsigned long cur, max; unsigned long cur, max;
@ -254,6 +250,7 @@ static int run(int argc, char *argv[]) {
_cleanup_close_pair_ int progress_pipe[2] = { -1, -1 }; _cleanup_close_pair_ int progress_pipe[2] = { -1, -1 };
_cleanup_(sd_device_unrefp) sd_device *dev = NULL; _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
_cleanup_free_ char *dpath = NULL; _cleanup_free_ char *dpath = NULL;
_cleanup_fclose_ FILE *console = NULL;
const char *device, *type; const char *device, *type;
bool root_directory; bool root_directory;
struct stat st; struct stat st;
@ -342,7 +339,9 @@ static int run(int argc, char *argv[]) {
} }
} }
if (arg_show_progress && console = fopen("/dev/console", "we");
if (console &&
arg_show_progress &&
pipe(progress_pipe) < 0) pipe(progress_pipe) < 0)
return log_error_errno(errno, "pipe(): %m"); return log_error_errno(errno, "pipe(): %m");
@ -401,8 +400,10 @@ static int run(int argc, char *argv[]) {
_exit(FSCK_OPERATIONAL_ERROR); _exit(FSCK_OPERATIONAL_ERROR);
} }
if (console) {
progress_pipe[1] = safe_close(progress_pipe[1]); progress_pipe[1] = safe_close(progress_pipe[1]);
(void) process_progress(TAKE_FD(progress_pipe[0])); (void) process_progress(TAKE_FD(progress_pipe[0]), console);
}
exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL); exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL);
if (exit_status < 0) if (exit_status < 0)

View File

@ -0,0 +1,4 @@
This appears to be failing on Ubuntu CI due to short sleep duration
waiting for the service-restarts to complete, but doubling the
sleep from 5 to 10 seconds didn't appear to help, so let's blacklist
this on Ubuntu CI while debugging the test failure.

View File

@ -0,0 +1,9 @@
BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
all setup run:
@basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
clean clean-again:
@basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --clean
.PHONY: all setup run clean clean-again

View File

@ -0,0 +1,47 @@
#!/bin/bash
set -e
TEST_DESCRIPTION="test that ExecStopPost= is always run"
. $TEST_BASE_DIR/test-functions
test_setup() {
create_empty_image_rootdir
(
LOG_LEVEL=5
eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
setup_basic_environment
mask_supporting_services
# setup policy for Type=dbus test
mkdir -p $initdir/etc/dbus-1/system.d
cat > $initdir/etc/dbus-1/system.d/systemd.test.ExecStopPost.conf <<EOF
<?xml version="1.0"?>
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="systemd.test.ExecStopPost"/>
</policy>
</busconfig>
EOF
# setup the testsuite service
cat >$initdir/etc/systemd/system/testsuite.service <<EOF
[Unit]
Description=Testsuite service
[Service]
ExecStart=/testsuite.sh
Type=oneshot
EOF
cp testsuite.sh $initdir/
setup_testsuite
)
setup_nspawn_root
}
do_test "$@"

View File

@ -0,0 +1,89 @@
#!/bin/bash
set -ex
systemd-analyze log-level debug
systemd-run --unit=simple1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=simple -p ExecStopPost='/bin/touch /run/simple1' true
test -f /run/simple1
! systemd-run --unit=simple2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=simple -p ExecStopPost='/bin/touch /run/simple2' false
test -f /run/simple2
systemd-run --unit=exec1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=exec -p ExecStopPost='/bin/touch /run/exec1' sleep 1
test -f /run/exec1
! systemd-run --unit=exec2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=exec -p ExecStopPost='/bin/touch /run/exec2' sh -c 'sleep 1; false'
test -f /run/exec2
cat > /tmp/forking1.sh <<EOF
#!/bin/bash
set -eux
sleep 4 &
MAINPID=\$!
disown
systemd-notify MAINPID=\$MAINPID
EOF
chmod +x /tmp/forking1.sh
systemd-run --unit=forking1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=forking -p NotifyAccess=exec -p ExecStopPost='/bin/touch /run/forking1' /tmp/forking1.sh
test -f /run/forking1
cat > /tmp/forking2.sh <<EOF
#!/bin/bash
set -eux
( sleep 4; exit 1 ) &
MAINPID=\$!
disown
systemd-notify MAINPID=\$MAINPID
EOF
chmod +x /tmp/forking2.sh
! systemd-run --unit=forking2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=forking -p NotifyAccess=exec -p ExecStopPost='/bin/touch /run/forking2' /tmp/forking2.sh
test -f /run/forking2
systemd-run --unit=oneshot1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=oneshot -p ExecStopPost='/bin/touch /run/oneshot1' true
test -f /run/oneshot1
! systemd-run --unit=oneshot2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=oneshot -p ExecStopPost='/bin/touch /run/oneshot2' false
test -f /run/oneshot2
systemd-run --unit=dbus1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=dbus -p BusName=systemd.test.ExecStopPost -p ExecStopPost='/bin/touch /run/dbus1' \
busctl call org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus RequestName su systemd.test.ExecStopPost 4 \
|| :
test -f /run/dbus1
! systemd-run --unit=dbus2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=dbus -p BusName=systemd.test.ExecStopPost -p ExecStopPost='/bin/touch /run/dbus2' true
test -f /run/dbus2
cat > /tmp/notify1.sh <<EOF
#!/bin/bash
set -eux
systemd-notify --ready
EOF
chmod +x /tmp/notify1.sh
systemd-run --unit=notify1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=notify -p ExecStopPost='/bin/touch /run/notify1' /tmp/notify1.sh
test -f /run/notify1
! systemd-run --unit=notify2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=notify -p ExecStopPost='/bin/touch /run/notify2' true
test -f /run/notify2
systemd-run --unit=idle1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=idle -p ExecStopPost='/bin/touch /run/idle1' true
test -f /run/idle1
! systemd-run --unit=idle2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=idle -p ExecStopPost='/bin/touch /run/idle2' false
test -f /run/idle2
systemd-analyze log-level info
echo OK > /testok
exit 0