Skip to content

Commit

Permalink
usdt: daemon
Browse files Browse the repository at this point in the history
This commit adds a daemon, "dtprobed", which usually runs at boot
(monitored by systemd, if possible), providing /dev/dtrace/helper using
CUSE, accepting DOF from processes doing the usual DTrace ioctl()s to
that device, and using infrastructure in prior commits in this series to
pass the DOF to a child jailed with seccomp() for parsing, and accepting
structures containing parsed results back, then emitting uprobes from
these results before allowing the ioctl()ing.  The uprobes created have
stereotyped names and argument lists that include an encoded
representation of the name of the corresponding DTrace USDT probe.  (The
name also contains the address and a number of other things, so that
probes that appear in multiple places in a process still work.)

(The CUSE device is an "unrestricted ioctl" device, which restricts
dtprobed to running only as root, because the ioctl has to pull data --
the DOF -- out of arbitrary places in the client memory according to the
passed-in structure. Since you need to be root to create uprobes at all
this is not any kind of restriction.)

Extra complexity is provided by changes to libfuse.  Recent (> 2018)
libfuse has a nice logging interface, which if available means that
libfuse will log FUSE-side problems into syslog or anywhere else of your
choosing: we emit into syslog if -d or -F (debug, foreground) are not
specified and systemd is not in use (if systemd is in use, we never
daemonize at all).  But older libfuse does not provide this, and
unfortunately OL8 (but not OL7!) has such an older libfuse.  So we add a
compatibility wrapper providing a minimal reimplementation of the
logging interface if built against such an old libfuse.  The wrapper is
named like the header and source file implementing the real thing in
FUSE itself, but prepended with rpl_ to avoid the possibility of
dependencies on header file ordering when the new FUSE code is present.

Testing-wise, in installed mode the running dtprobed daemon is used, but
in in-source-tree mode runtest.sh kicks off a new dtprobed emitting to a
local device file named /dev/dtrace/test-$pid, and uses a new
testing-only environment variable to force drti.c to emit its ioctl()s
to that temporary device.  So in-tree testing always tests the actual
dtprobed in the tree (with any bugfixes), not the system copy.

Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
nickalcock authored and kvanhees committed Oct 25, 2022
1 parent 3fac45f commit 25cb727
Show file tree
Hide file tree
Showing 12 changed files with 815 additions and 4 deletions.
6 changes: 5 additions & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Build files in subdirectories are included by this file.
#
# Oracle Linux DTrace.
# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.

Expand Down Expand Up @@ -85,6 +85,10 @@ INCLUDEDIR := $(prefix)/include
INSTINCLUDEDIR := $(DESTDIR)$(INCLUDEDIR)
SBINDIR := $(prefix)/sbin
INSTSBINDIR := $(DESTDIR)$(SBINDIR)
UDEVDIR := $(prefix)/lib/udev/rules.d
INSTUDEVDIR := $(DESTDIR)$(UDEVDIR)
SYSTEMDUNITDIR := $(prefix)/lib/systemd/system
INSTSYSTEMDUNITDIR := $(DESTDIR)$(SYSTEMDUNITDIR)
DOCDIR := $(prefix)/share/doc/dtrace-$(VERSION)
INSTDOCDIR := $(DESTDIR)$(DOCDIR)
MANDIR := $(prefix)/share/man/man1
Expand Down
2 changes: 2 additions & 0 deletions Makeconfig
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,6 @@ $(eval $(call check-symbol-rule,ELF_GETSHDRSTRNDX,elf_getshdrstrndx,elf))
$(eval $(call check-symbol-rule,LIBCTF,ctf_open,ctf))
$(eval $(call check-symbol-rule,STRRSTR,strrstr,c))
$(eval $(call check-symbol-rule,WAITFD,waitfd,c))
$(eval $(call check-symbol-rule,LIBSYSTEMD,sd_notify,systemd))
$(eval $(call check-symbol-rule,FUSE_LOG,fuse_set_log_func,fuse3))
$(eval $(call check-header-symbol-rule,CLOSE_RANGE,close_range(3,~0U,0),c,unistd))
4 changes: 4 additions & 0 deletions dtprobed/60-dtprobed.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.

KERNEL=="dtrace/helper", MODE="0666"
41 changes: 41 additions & 0 deletions dtprobed/Build
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Oracle Linux DTrace.
# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.

CMDS += dtprobed

dtprobed_DIR := $(current-dir)
dtprobed_TARGET = dtprobed
dtprobed_CPPFLAGS := -I. -Idtprobed -Ilibproc -Ilibcommon -Ilibport
dtprobed_CFLAGS := $(shell pkg-config --cflags fuse3)
dtprobed_LIBS := -lcommon -lproc -lcommon -lport -lelf $(shell pkg-config --libs fuse3)
dtprobed_DEPS := libproc.a libcommon.a libport.a
dtprobed_SOURCES := dtprobed.c
dtprobed_LIBSOURCES := libproc libcommon

ifdef HAVE_LIBSYSTEMD
dtprobed_CFLAGS += $(shell pkg-config --cflags libsystemd)
dtprobed_LIBS += $(shell pkg-config --libs libsystemd)
endif

ifndef HAVE_FUSE_LOG
dtprobed_SOURCES += rpl_fuse_log.c
endif

dtprobed.c_CFLAGS := -Wno-pedantic

install::
mkdir -p $(INSTSBINDIR)
$(call describe-install-target,$(INSTSBINDIR),dtprobed)
install -m 755 $(objdir)/dtprobed $(INSTSBINDIR)
mkdir -p $(INSTUDEVDIR)
$(call describe-install-target,$(INSTUDEVDIR),60-dtprobed.rules)
install -m 644 $(dtprobed_DIR)60-dtprobed.rules $(INSTUDEVDIR)
ifdef HAVE_LIBSYSTEMD
mkdir -p $(INSTSYSTEMDUNITDIR)
$(call describe-install-target,$(INSTSYSTEMDUNITDIR),dtprobed.service)
install -m 644 $(dtprobed_DIR)dtprobed.service $(INSTSYSTEMDUNITDIR)
$(call describe-install-target,$(INSTSYSTEMDUNITDIR),dtrace-usdt.target)
install -m 644 $(dtprobed_DIR)dtrace-usdt.target $(INSTSYSTEMDUNITDIR)
endif
5 changes: 5 additions & 0 deletions dtprobed/GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
%:
$(MAKE) -C .. $@

all::
$(MAKE) -C .. all

0 comments on commit 25cb727

Please sign in to comment.