Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ https://github.com/networkupstools/nut/milestone/13
not do so for single-driver runs -- addressed with this release. [#3302]

- common code:
* POSIX daemons now warn if their real or effective UID remains zero after
the common credential switch. [issue #3471, PR #3609]
* Refactored `common::background()` method used by numerous NUT daemons
to handle parent and child code paths by separately addressable methods.
This got used in the shared drivers `main` code file to preclude losing
Expand Down
12 changes: 11 additions & 1 deletion common/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,8 @@ void become_user(struct passwd *pw)
/* if we can't switch users, then don't even try */
intmax_t initial_uid = getuid();
intmax_t initial_euid = geteuid();
intmax_t final_uid;
intmax_t final_euid;

if (!pw) {
upsdebugx(1, "Can not become_user(<null>), skipped");
Expand Down Expand Up @@ -1019,8 +1021,16 @@ void become_user(struct passwd *pw)
if (setuid(pw->pw_uid) == -1)
fatal_with_errno(EXIT_FAILURE, "setuid");

final_uid = getuid();
final_euid = geteuid();
if ((final_uid == 0) || (final_euid == 0)) {
upslogx(LOG_WARNING, "Warning: running as root (UID=%jd EUID=%jd)",
final_uid, final_euid);
return;
}

upsdebugx(1, "Succeeded to become_user(%s): now UID=%jd GID=%jd",
pw->pw_name, (intmax_t)getuid(), (intmax_t)getgid());
pw->pw_name, final_uid, (intmax_t)getgid());
#else /* WIN32 */
/* NUT_WIN32_INCOMPLETE_MAYBE_NOT_APPLICABLE(); */
upsdebugx(1, "Can not become_user(%s): not implemented on this platform",
Expand Down
13 changes: 11 additions & 2 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ SUBDIRS = . NIT
# handle that properly
all: $(TESTS) $(check_PROGRAMS) $(check_SCRIPTS)

EXTRA_DIST = nut-driver-enumerator-test.sh nut-driver-enumerator-test--ups.conf
EXTRA_DIST = become-user-root-warning-test.sh nut-driver-enumerator-test.sh nut-driver-enumerator-test--ups.conf
EXTRA_DIST += cppunit-warnings.h cppunit-warnings-end.h

TESTS =
Expand Down Expand Up @@ -54,6 +54,9 @@ $(top_builddir)/clients/libnutclient.la \
$(top_builddir)/clients/libnutclientstub.la: dummy @dotMAKE@
+@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)

$(top_builddir)/clients/upslog$(EXEEXT): dummy @dotMAKE@
+@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) upslog$(EXEEXT)

# Builds from root dir arrange stuff decently. Make sure parallel builds
# started from scratch right in this dir get dependencies in proper order
# (sub-makes are independent as far as trying to write into same files):
Expand Down Expand Up @@ -310,10 +313,16 @@ memcheck:
@echo " SKIP $@ : valgrind was not detected on this system by configure script" >&2
endif !HAVE_VALGRIND

CHECK_LOCAL_TARGETS = become-user-root-warning-test
if WITH_VALGRIND
check-local: memcheck
CHECK_LOCAL_TARGETS += memcheck
endif WITH_VALGRIND

check-local: $(CHECK_LOCAL_TARGETS)

become-user-root-warning-test: $(top_builddir)/clients/upslog$(EXEEXT)
$(AM_V_at)UPSLOG='$(abs_top_builddir)/clients/upslog$(EXEEXT)' $(SHELL) $(srcdir)/become-user-root-warning-test.sh

dummy:

BUILT_SOURCES = $(LINKED_SOURCE_FILES)
Expand Down
24 changes: 24 additions & 0 deletions tests/become-user-root-warning-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh

if test "`id -u`" != 0; then
echo "SKIP: root privileges are required to test become_user()" >&2
exit 0
fi

testdir="`mktemp -d "${TMPDIR:-/tmp}/nut-become-user-root-warning.XXXXXX"`" || exit
trap 'rm -rf "$testdir"' EXIT HUP INT TERM

upslog=${UPSLOG-../clients/upslog}
root_user="`id -un`" || exit
warning='Warning: running as root (UID=0 EUID=0)'

if output="`"$upslog" -F -u "$root_user" -p "$testdir/upslog" -W 1 -d 1 -i 1 \
-s dummy@127.0.0.1:1 -l - 2>&1`"; then
count="`printf '%s\n' "$output" | grep -F "$warning" | wc -l`"
if test "$count" -eq 1; then
exit 0
fi
fi

printf '%s\n' "$output" >&2
exit 1
Loading