Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mtr-packet cap_net_raw turn on and off #311

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ dist_man_MANS = mtr.8 mtr-packet.8
PATHFILES += man/mtr.8 man/mtr-packet.8

install-exec-hook:
`setcap cap_net_raw+ep $(DESTDIR)$(sbindir)/mtr-packet` \
`setcap cap_net_raw+p $(DESTDIR)$(sbindir)/mtr-packet` \
|| chmod u+s $(DESTDIR)$(sbindir)/mtr-packet

mtr_SOURCES = ui/mtr.c ui/mtr.h \
Expand Down
2 changes: 1 addition & 1 deletion SECURITY
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ On Linux, privileges are known as capabilities. The only additional
capability that mtr-packet needs is cap_net_raw. To give this
capability to the mtr-packet binary, run the following command as root:

# setcap cap_net_raw+ep mtr-packet
# setcap cap_net_raw+p mtr-packet


2. Run mtr as the root user.
Expand Down
6 changes: 6 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ AC_CHECK_HEADERS([ \
AC_CHECK_FUNCS([ \
__fpending \
fcntl \
prctl \
])

AC_CHECK_FUNC([error], [with_error=no],
Expand Down Expand Up @@ -113,6 +114,11 @@ AM_CONDITIONAL([WITH_CURSES], [test "x$with_ncurses" = xyes])
AC_CHECK_LIB([cap], [cap_set_proc], [have_cap="yes"],
AS_IF([test "$host_os" = linux-gnu],
AC_MSG_WARN([Capabilities support is strongly recommended for increased security. See SECURITY for more information.])))
AS_IF([test "x$have_cap" = "xyes"], [
AC_DEFINE([HAVE_LIBCAP], [1], [Define when libcap is in use])
AC_SUBST([CAP_LIBS], [-lcap])
])


# Enable ipinfo
AC_ARG_WITH([ipinfo],
Expand Down
12 changes: 12 additions & 0 deletions packet/packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
#include <sys/capability.h>
#endif

#ifdef HAVE_PRCTL
# include <sys/prctl.h>
# ifndef PR_SET_NO_NEW_PRIVS
# define PR_SET_NO_NEW_PRIVS 38
# endif
#endif

#include "wait.h"

/* Drop SUID privileges. To be used after accquiring raw sockets. */
Expand Down Expand Up @@ -69,6 +76,11 @@ int drop_elevated_permissions(
return -1;
}
#endif
#ifdef HAVE_PRCTL
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
return -1;
}
#endif

return 0;
}
Expand Down
48 changes: 47 additions & 1 deletion packet/probe_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
#include <sys/socket.h>
#include <unistd.h>

#ifdef HAVE_LIBCAP
# include <sys/capability.h>
#endif

#include "platform.h"
#include "protocols.h"
#include "sockaddr.h"
Expand Down Expand Up @@ -402,6 +406,43 @@ int open_ip6_sockets_dgram(
}
#endif

#ifdef HAVE_LIBCAP
static int modify_capability(cap_value_t cap, cap_flag_value_t on)
{
cap_t cap_p = cap_get_proc();
cap_flag_value_t cap_ok;
int rc = -1;

if (!cap_p) {
error(0, errno, "cap_get_proc");
goto out;
}

cap_ok = CAP_CLEAR;
cap_get_flag(cap_p, cap, CAP_PERMITTED, &cap_ok);
if (cap_ok == CAP_CLEAR) {
rc = on ? -1 : 0;
goto out;
}

cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on);

if (cap_set_proc(cap_p) < 0) {
error(0, errno, "cap_set_proc");
goto out;
}

cap_free(cap_p);
cap_p = NULL;

rc = 0;
out:
if (cap_p)
cap_free(cap_p);
return rc;
}
#endif

/*
The first half of the net state initialization. Since this
happens with elevated privileges, this is kept as minimal
Expand All @@ -417,6 +458,9 @@ void init_net_state_privileged(

net_state->platform.next_sequence = MIN_PORT;

#ifdef HAVE_LIBCAP
modify_capability(CAP_NET_RAW, CAP_SET);
#endif
if (open_ip4_sockets_raw(net_state)) {
#ifdef HAVE_LINUX_ERRQUEUE_H
/* fall back to using unprivileged sockets */
Expand All @@ -433,7 +477,9 @@ void init_net_state_privileged(
}
#endif
}

#ifdef HAVE_LIBCAP
modify_capability(CAP_NET_RAW, CAP_CLEAR);
#endif
/*
If we couldn't open either IPv4 or IPv6 sockets, we can't do
much, so print errors and exit.
Expand Down