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

pppd: Check CAP_NET_RAW capability on Linux rather than requiring euid 0 #136

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
8 changes: 8 additions & 0 deletions pppd/Makefile.linux
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ PLUGIN=y
# Enable EAP SRP-SHA1 authentication (requires libsrp)
#USE_SRP=y

# Use libcap (requires libcap)
#USE_LIBCAP=y

# Use libutil; test if logwtmp is declared in <utmp.h> to detect
ifeq ($(shell echo '\#include <utmp.h>' | $(CC) -E - 2>/dev/null | grep -q logwtmp && echo yes),yes)
USE_LIBUTIL=y
Expand Down Expand Up @@ -148,6 +151,11 @@ CFLAGS += -DHAVE_CRYPT_H=1
LIBS += -lcrypt
endif

ifdef USE_LIBCAP
CFLAGS += -DUSE_CAP
LIBS += -lcap
endif

ifdef USE_LIBUTIL
CFLAGS += -DHAVE_LOGWTMP=1
LIBS += -lutil
Expand Down
11 changes: 7 additions & 4 deletions pppd/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,14 @@ main(int argc, char *argv[])
setlogmask(LOG_UPTO(LOG_DEBUG));

/*
* Check that we are running as root.
* Check that we are capable to admin the network.
*/
if (geteuid() != 0) {
option_error("must be root to run %s, since it is not setuid-root",
argv[0]);
if (!net_capable()) {
#ifdef USE_CAP
option_error("must have CAP_NET_RAW or root privilege to run %s", argv[0]);
a-andreyev marked this conversation as resolved.
Show resolved Hide resolved
#else
option_error("must be root to run %s, since it is not setuid-root", argv[0]);
#endif /* USE_CAP */
exit(EXIT_NOT_ROOT);
}

Expand Down
1 change: 1 addition & 0 deletions pppd/pppd.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,7 @@ void sys_init(void); /* Do system-dependent initialization */
void sys_cleanup(void); /* Restore system state before exiting */
int sys_check_options(void); /* Check options specified */
void sys_close(void); /* Clean up in a child before execing */
int net_capable(void); /* Test for any access to the net management */
int ppp_available(void); /* Test whether ppp kernel support exists */
int get_pty(int *, int *, char *, int); /* Get pty master/slave */
int open_ppp_loopback(void); /* Open loopback for demand-dialling */
Expand Down
41 changes: 41 additions & 0 deletions pppd/sys-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@
#include <sys/locks.h>
#endif

#ifdef USE_CAP
#include <sys/types.h>
#include <sys/capability.h>
#endif /* USE_CAP */

#ifdef INET6
#ifndef _LINUX_IN6_H
/*
Expand Down Expand Up @@ -2329,6 +2334,42 @@ ppp_registered(void)
return ret;
}

/***********************************************************
*
* net_capable - check for any access to the net management
*/

int net_capable(void)
{
int ok = 0;
#ifdef USE_CAP
/*
* Check that we are capable to admin the network.
*/
cap_t cap;
cap_flag_value_t cap_flag_value;
cap = cap_get_pid(getpid());
if (cap != 0) {
if (cap_get_flag(cap, CAP_NET_RAW, CAP_EFFECTIVE, &cap_flag_value) == 0) {
if (cap_flag_value == CAP_SET)
ok = 1;
}
if (cap_get_flag(cap, CAP_NET_RAW, CAP_PERMITTED, &cap_flag_value) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If already ok, why run the second check?

For that matter, why not simply return 1 immediately when things check out?

if (cap_flag_value == CAP_SET)
ok = 1;
}
}
#else /* USE_CAP */
/*
* Check that we are running as root.
*/
if (geteuid() == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps keep this check first, as it's going to be the most likely case anyway?

ok = 1;
}
#endif /* USE_CAP */
return ok;
}

/********************************************************************
*
* ppp_available - check whether the system has any ppp interfaces
Expand Down
14 changes: 14 additions & 0 deletions pppd/sys-solaris.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,20 @@ daemon(int nochdir, int noclose)
}
#endif

/***********************************************************
*
* net_capable - check for any access to the net management
*/

int net_capable(void)
{
int ok = 0;
if (geteuid() == 0) {
ok = 1;
}
return ok;
}

/*
* ppp_available - check whether the system has any ppp interfaces
*/
Expand Down