From 43c98c68be8bed7a2dfb817fe4b70d238496c733 Mon Sep 17 00:00:00 2001 From: rain1 Date: Thu, 14 Apr 2016 11:49:55 +0000 Subject: [PATCH 1/7] * src/main.cpp: Include header files for capabilities and attrs. * src/nethogs.cpp: Add code to read and parse file attrs, and check for the required capabilities in the non-root case. --- src/main.cpp | 16 ++++++++++++++-- src/nethogs.cpp | 3 +++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4fdab2e..ecf4fe8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -173,8 +173,20 @@ int main(int argc, char **argv) { init_ui(); } - if (NEEDROOT && (geteuid() != 0)) - forceExit(false, "You need to be root to run NetHogs!"); + if (NEEDROOT) { + if (geteuid() != 0) + forceExit(false, "You need to be root to run NetHogs!"); + } + else { + unsigned int caps[5] = {0}; + + getxattr(argv[0], "security.capability", (char *)caps, sizeof(caps)); + + if ((val[1] >> CAP_NET_ADMIN) & 1 != 1) + forceExit(false, "You need to enable cap_net_admin (and cap_net_raw) to run NetHogs!"); + if ((val[1] >> CAP_NET_RAW) & 1 != 1) + forceExit(false, "You need to enable cap_net_raw to run NetHogs!"); + } // use the Self-Pipe trick to interrupt the select() in the main loop self_pipe = create_self_pipe(); diff --git a/src/nethogs.cpp b/src/nethogs.cpp index 682c790..f2fba8a 100644 --- a/src/nethogs.cpp +++ b/src/nethogs.cpp @@ -37,6 +37,9 @@ #include #include #include +#include +#include +#include #include "cui.h" From c0dd0e2e0c03ce4e4f2b493b5794d409219f23f6 Mon Sep 17 00:00:00 2001 From: rain1 Date: Thu, 14 Apr 2016 12:02:04 +0000 Subject: [PATCH 2/7] * src/main.cpp: Bug fix, misnamed a variable. --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ecf4fe8..8d77726 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -182,9 +182,9 @@ int main(int argc, char **argv) { getxattr(argv[0], "security.capability", (char *)caps, sizeof(caps)); - if ((val[1] >> CAP_NET_ADMIN) & 1 != 1) + if ((caps[1] >> CAP_NET_ADMIN) & 1 != 1) forceExit(false, "You need to enable cap_net_admin (and cap_net_raw) to run NetHogs!"); - if ((val[1] >> CAP_NET_RAW) & 1 != 1) + if ((caps[1] >> CAP_NET_RAW) & 1 != 1) forceExit(false, "You need to enable cap_net_raw to run NetHogs!"); } From a5fbdc1910cd2393f0c500867dc1f58fab789c9a Mon Sep 17 00:00:00 2001 From: rain1 Date: Thu, 14 Apr 2016 12:15:48 +0000 Subject: [PATCH 3/7] * src/main.cpp: Make the capability imports conditional. * src/nethogs.cpp: Make the capability check conditional. Bug fix in the != test. --- src/main.cpp | 23 +++++++++++------------ src/nethogs.cpp | 3 +++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8d77726..b4bb3e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -173,20 +173,19 @@ int main(int argc, char **argv) { init_ui(); } - if (NEEDROOT) { - if (geteuid() != 0) - forceExit(false, "You need to be root to run NetHogs!"); - } - else { - unsigned int caps[5] = {0}; +#if NEEDROOT == 1 + if (geteuid() != 0) + forceExit(false, "You need to be root to run NetHogs!"); +#else + unsigned int caps[5] = {0}; - getxattr(argv[0], "security.capability", (char *)caps, sizeof(caps)); + getxattr(argv[0], "security.capability", (char *)caps, sizeof(caps)); - if ((caps[1] >> CAP_NET_ADMIN) & 1 != 1) - forceExit(false, "You need to enable cap_net_admin (and cap_net_raw) to run NetHogs!"); - if ((caps[1] >> CAP_NET_RAW) & 1 != 1) - forceExit(false, "You need to enable cap_net_raw to run NetHogs!"); - } + if (((caps[1] >> CAP_NET_ADMIN) & 1) != 1) + forceExit(false, "You need to enable cap_net_admin (and cap_net_raw) to run NetHogs!"); + if (((caps[1] >> CAP_NET_RAW) & 1) != 1) + forceExit(false, "You need to enable cap_net_raw to run NetHogs!"); +#endif // use the Self-Pipe trick to interrupt the select() in the main loop self_pipe = create_self_pipe(); diff --git a/src/nethogs.cpp b/src/nethogs.cpp index f2fba8a..855261c 100644 --- a/src/nethogs.cpp +++ b/src/nethogs.cpp @@ -37,9 +37,12 @@ #include #include #include + +#if NEEDROOT == 0 #include #include #include +#endif #include "cui.h" From 2ab130624688b8fc68fad65ece6df6ec8e923947 Mon Sep 17 00:00:00 2001 From: rain1 Date: Thu, 14 Apr 2016 12:31:13 +0000 Subject: [PATCH 4/7] * src/nethogs.h: Including files for PATH_MAX and readlink. * src/nethogs.cpp: Bug fix - make capability detection work correctly when invoking a program in PATH rather than only when invoked explicitly like ./src/nethogs. --- src/nethogs.cpp | 2 ++ src/nethogs.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nethogs.cpp b/src/nethogs.cpp index 855261c..d08c4e7 100644 --- a/src/nethogs.cpp +++ b/src/nethogs.cpp @@ -39,6 +39,8 @@ #include #if NEEDROOT == 0 +#include +#include #include #include #include diff --git a/src/nethogs.h b/src/nethogs.h index 08f1add..bae80f0 100644 --- a/src/nethogs.h +++ b/src/nethogs.h @@ -53,7 +53,7 @@ * like www.adamantix.org: in that case nethogs shouldn't check if it's * running as root. Take care to give it sufficient privileges though. */ #ifndef NEEDROOT -#define NEEDROOT 1 +#define NEEDROOT 0 #endif #define DEBUG 0 From b2f008c5682e1cc2214d70e22d4b5e4cb08fd515 Mon Sep 17 00:00:00 2001 From: rain1 Date: Thu, 14 Apr 2016 12:41:34 +0000 Subject: [PATCH 5/7] * src/nethogs.h: Undo accidental commit. * src/main.cpp: Properly commit this change. --- src/main.cpp | 4 +++- src/nethogs.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b4bb3e9..bc01334 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -177,9 +177,11 @@ int main(int argc, char **argv) { if (geteuid() != 0) forceExit(false, "You need to be root to run NetHogs!"); #else + char exe_path[PATH_MAX]; unsigned int caps[5] = {0}; - getxattr(argv[0], "security.capability", (char *)caps, sizeof(caps)); + readlink("/proc/self/exe", exe_path, PATH_MAX); + getxattr(exe_path, "security.capability", (char *)caps, sizeof(caps)); if (((caps[1] >> CAP_NET_ADMIN) & 1) != 1) forceExit(false, "You need to enable cap_net_admin (and cap_net_raw) to run NetHogs!"); diff --git a/src/nethogs.h b/src/nethogs.h index bae80f0..08f1add 100644 --- a/src/nethogs.h +++ b/src/nethogs.h @@ -53,7 +53,7 @@ * like www.adamantix.org: in that case nethogs shouldn't check if it's * running as root. Take care to give it sufficient privileges though. */ #ifndef NEEDROOT -#define NEEDROOT 0 +#define NEEDROOT 1 #endif #define DEBUG 0 From b6a595ae00d1ec60670af73a94e577634ee71c72 Mon Sep 17 00:00:00 2001 From: rain1 Date: Mon, 18 Apr 2016 18:04:37 +0100 Subject: [PATCH 6/7] * src/main.cpp: Made cap test conditional on __linux__. Improved the error message. * src/nethogs.cpp: Reduced the scope of the includes moving them out of this file. * src/nethogs.h: Removed NEEDROOT variable. --- src/main.cpp | 33 ++++++++++++++++++++------------- src/nethogs.cpp | 8 -------- src/nethogs.h | 7 ------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bc01334..3794cd4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,14 @@ #include #include +#ifdef __linux__ +#include +#include +#include +#include +#include +#endif + // The self_pipe is used to interrupt the select() in the main loop static std::pair self_pipe = std::make_pair(-1, -1); static time_t last_refresh_time = 0; @@ -173,21 +181,20 @@ int main(int argc, char **argv) { init_ui(); } -#if NEEDROOT == 1 - if (geteuid() != 0) - forceExit(false, "You need to be root to run NetHogs!"); + if (geteuid() != 0) { +#ifdef __linux__ + char exe_path[PATH_MAX]; + unsigned int caps[5] = {0}; + + readlink("/proc/self/exe", exe_path, PATH_MAX); + getxattr(exe_path, "security.capability", (char *)caps, sizeof(caps)); + + if ((((caps[1] >> CAP_NET_ADMIN) & 1) != 1) || (((caps[1] >> CAP_NET_RAW) & 1) != 1)) + forceExit(false, "To run nethogs without being root you need to enable capabilities on the program (cap_net_admin, cap_net_raw), see the documentation for details."); #else - char exe_path[PATH_MAX]; - unsigned int caps[5] = {0}; - - readlink("/proc/self/exe", exe_path, PATH_MAX); - getxattr(exe_path, "security.capability", (char *)caps, sizeof(caps)); - - if (((caps[1] >> CAP_NET_ADMIN) & 1) != 1) - forceExit(false, "You need to enable cap_net_admin (and cap_net_raw) to run NetHogs!"); - if (((caps[1] >> CAP_NET_RAW) & 1) != 1) - forceExit(false, "You need to enable cap_net_raw to run NetHogs!"); + forceExit(false, "You need to be root to run NetHogs!"); #endif + } // use the Self-Pipe trick to interrupt the select() in the main loop self_pipe = create_self_pipe(); diff --git a/src/nethogs.cpp b/src/nethogs.cpp index d08c4e7..682c790 100644 --- a/src/nethogs.cpp +++ b/src/nethogs.cpp @@ -38,14 +38,6 @@ #include #include -#if NEEDROOT == 0 -#include -#include -#include -#include -#include -#endif - #include "cui.h" extern "C" { diff --git a/src/nethogs.h b/src/nethogs.h index 08f1add..b4f5102 100644 --- a/src/nethogs.h +++ b/src/nethogs.h @@ -49,13 +49,6 @@ * after which a connection is removed */ #define CONNTIMEOUT 50 -/* Set to '0' when compiling for a system that uses Linux Capabilities, - * like www.adamantix.org: in that case nethogs shouldn't check if it's - * running as root. Take care to give it sufficient privileges though. */ -#ifndef NEEDROOT -#define NEEDROOT 1 -#endif - #define DEBUG 0 #define REVERSEHACK 0 From 30f10729462218fd8af9e08a664fe443fbe7f232 Mon Sep 17 00:00:00 2001 From: rain1 Date: Mon, 18 Apr 2016 18:34:08 +0100 Subject: [PATCH 7/7] * src/main.cpp: Bug fix - nul terminate the result of readlink after checking for failure. --- src/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3794cd4..5137a0f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -184,9 +184,13 @@ int main(int argc, char **argv) { if (geteuid() != 0) { #ifdef __linux__ char exe_path[PATH_MAX]; - unsigned int caps[5] = {0}; + ssize_t len; + unsigned int caps[5] = {0,0,0,0,0}; + + if ((len = readlink("/proc/self/exe", exe_path, PATH_MAX)) == -1) + forceExit(false, "Failed to locate nethogs binary."); + exe_path[len] = '\0'; - readlink("/proc/self/exe", exe_path, PATH_MAX); getxattr(exe_path, "security.capability", (char *)caps, sizeof(caps)); if ((((caps[1] >> CAP_NET_ADMIN) & 1) != 1) || (((caps[1] >> CAP_NET_RAW) & 1) != 1))