arping.c | 74 ++++------------------- clockdiff.c | 12 ++-- doc/arping.xml | 4 +- doc/clockdiff.xml | 4 +- doc/meson.build | 39 +++++++++---- doc/ninfod.xml | 2 +- doc/ping.xml | 2 +- doc/rdisc.xml | 2 +- doc/tracepath.xml | 8 +-- doc/traceroute6.xml | 10 ++-- fixfds.c | 27 +++++++++ fixfds.h | 6 ++ meson.build | 30 +++++----- modcap.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++ modcap.h | 11 ++++ ninfod/meson.build | 2 + ninfod/ni_ifaddrs.c | 2 +- ninfod/ninfod.c | 3 + ping/meson.build | 2 + ping/ping.c | 23 +++++--- ping/ping.h | 6 +- ping/ping6_common.c | 2 +- ping/ping_common.c | 79 ++++--------------------- tracepath.c | 11 ++++ traceroute6.c | 15 +++-- 25 files changed, 341 insertions(+), 200 deletions(-) diff --git a/arping.c b/arping.c index 53fdbb4..d7e5555 100644 --- a/arping.c +++ b/arping.c @@ -31,10 +31,11 @@ #include #ifdef HAVE_LIBCAP -# include -# include +#include "modcap.h" #endif +#include "fixfds.h" + #include "iputils_common.h" #ifdef DEFAULT_DEVICE @@ -88,10 +89,6 @@ struct run_state { unsolicited:1; }; -#ifdef HAVE_LIBCAP -static const cap_value_t caps[] = { CAP_NET_RAW }; -#endif - /* * All includes, definitions, struct declarations, and global variables are * above. After this comment all you can find is functions. @@ -138,72 +135,19 @@ static void usage(void) } #ifdef HAVE_LIBCAP -static void limit_capabilities(struct run_state *ctl) +static void limit_capabilities(__attribute__((unused)) struct run_state *ctl) { - cap_t cap_p; - - cap_p = cap_get_proc(); - if (!cap_p) - error(-1, errno, "cap_get_proc"); - - cap_get_flag(cap_p, CAP_NET_RAW, CAP_PERMITTED, &ctl->cap_raw); - - if (ctl->cap_raw != CAP_CLEAR) { - if (cap_clear(cap_p) < 0) - error(-1, errno, "cap_clear"); - - cap_set_flag(cap_p, CAP_PERMITTED, 1, caps, CAP_SET); - - if (cap_set_proc(cap_p) < 0) { - error(0, errno, "cap_set_proc"); - if (errno != EPERM) - exit(-1); - } - } - - if (prctl(PR_SET_KEEPCAPS, 1) < 0) - error(-1, errno, "prctl"); - - if (setuid(getuid()) < 0) - error(-1, errno, "setuid"); - - if (prctl(PR_SET_KEEPCAPS, 0) < 0) - error(-1, errno, "prctl"); - - cap_free(cap_p); + limit_capabilities_common(1, 0); } -static int modify_capability_raw(struct run_state *ctl, int on) +static int modify_capability_raw(__attribute__((unused)) struct run_state *ctl, int on) { - cap_t cap_p; - - if (ctl->cap_raw != CAP_SET) - return on ? -1 : 0; - - cap_p = cap_get_proc(); - if (!cap_p) - error(-1, errno, "cap_get_proc"); - - cap_set_flag(cap_p, CAP_EFFECTIVE, 1, caps, on ? CAP_SET : CAP_CLEAR); - - if (cap_set_proc(cap_p) < 0) - error(-1, errno, "cap_set_proc"); - - cap_free(cap_p); - return 0; + return modify_capability_common(CAP_NET_RAW, on ? CAP_SET : CAP_CLEAR); } static void drop_capabilities(void) { - cap_t cap_p = cap_init(); - - if (!cap_p) - error(-1, errno, "cap_init"); - - if (cap_set_proc(cap_p) < 0) - error(-1, errno, "cap_set_proc"); - - cap_free(cap_p); + drop_capabilities_common(); } #else /* HAVE_LIBCAP */ static void limit_capabilities(struct run_state *ctl) @@ -840,6 +784,8 @@ int main(int argc, char **argv) }; int ch; + fix_fds(); + atexit(close_stdout); limit_capabilities(&ctl); #if defined(USE_IDN) || defined(ENABLE_NLS) diff --git a/clockdiff.c b/clockdiff.c index 538bf78..1f8023f 100644 --- a/clockdiff.c +++ b/clockdiff.c @@ -75,8 +75,9 @@ #include #ifdef HAVE_LIBCAP -# include +#include "modcap.h" #endif +#include "fixfds.h" #include "iputils_common.h" @@ -434,11 +435,8 @@ static int measure(struct run_state *ctl) static void drop_rights(void) { #ifdef HAVE_LIBCAP - cap_t caps = cap_init(); - - if (cap_set_proc(caps)) - error(-1, errno, "cap_set_proc"); - cap_free(caps); + limit_capabilities_common(0, 0); + drop_capabilities_common(); #endif if (setuid(getuid())) error(-1, errno, "setuid"); @@ -523,6 +521,8 @@ int main(int argc, char **argv) struct addrinfo *result; int status; + fix_fds(); + atexit(close_stdout); parse_opts(&ctl, argc, argv); diff --git a/doc/arping.xml b/doc/arping.xml index 711718f..0a67f51 100644 --- a/doc/arping.xml +++ b/doc/arping.xml @@ -229,7 +229,7 @@ xml:id="man.arping"> ping - 8 + 1 , clockdiff @@ -237,7 +237,7 @@ xml:id="man.arping"> , tracepath - 8 + 1 . diff --git a/doc/clockdiff.xml b/doc/clockdiff.xml index 9643bea..609e766 100644 --- a/doc/clockdiff.xml +++ b/doc/clockdiff.xml @@ -165,7 +165,7 @@ xml:id="man.clockdiff"> ping - 8 + 1 , arping @@ -173,7 +173,7 @@ xml:id="man.clockdiff"> , tracepath - 8 + 1 . diff --git a/doc/meson.build b/doc/meson.build index 30aca2d..4cc0fcc 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -1,43 +1,47 @@ manpages = [] +manpages1 = [] +manpages8 = [] custom_man_xsl = files('custom-man.xsl') custom_html_xsl = files('custom-html.xsl') if build_arping == true - manpages += ['arping'] + manpages8 += ['arping'] endif if build_clockdiff == true - manpages += ['clockdiff'] + manpages8 += ['clockdiff'] endif if build_ping == true - manpages += ['ping'] + manpages1 += ['ping'] endif if build_rarpd == true - manpages += ['rarpd'] + manpages8 += ['rarpd'] endif if build_rdisc == true - manpages += ['rdisc'] + manpages8 += ['rdisc'] endif if build_tftpd == true - manpages += ['tftpd'] + manpages8 += ['tftpd'] endif if build_tracepath == true - manpages += ['tracepath'] + manpages1 += ['tracepath'] endif if build_traceroute6 == true - manpages += ['traceroute6'] + manpages1 += ['traceroute6'] endif if build_ninfod == true - manpages += ['ninfod'] + manpages8 += ['ninfod'] endif +manpages = manpages1 + manpages8 + xsltproc = find_program('xsltproc', required : build_mans or build_html_mans) xsltproc_args = [ '--nonet', @@ -73,7 +77,7 @@ if xsltproc_works == false endif if build_mans - foreach man : manpages + foreach man : manpages8 custom_target(man + '.8', output : man + '.8', input : man + '.xml', @@ -88,6 +92,21 @@ if build_mans install_dir : join_paths(get_option('mandir'), 'man8'), ) endforeach + foreach man : manpages1 + custom_target(man + '.1', + output : man + '.1', + input : man + '.xml', + command : [ + xsltproc, + '-o', '@OUTPUT@', + xsltproc_args, + custom_man_xsl, + '@INPUT@', + ], + install : true, + install_dir : join_paths(get_option('mandir'), 'man1'), + ) + endforeach endif if build_html_mans diff --git a/doc/ninfod.xml b/doc/ninfod.xml index 081d470..ed88343 100644 --- a/doc/ninfod.xml +++ b/doc/ninfod.xml @@ -118,7 +118,7 @@ xml:id="man.ninfod"> ping - 8 + 1 . diff --git a/doc/ping.xml b/doc/ping.xml index 61b8a5e..a2bd90a 100644 --- a/doc/ping.xml +++ b/doc/ping.xml @@ -10,7 +10,7 @@ xml:id="man.ping"> ping - 8 + 1 iputils diff --git a/doc/rdisc.xml b/doc/rdisc.xml index 05a518c..daa339b 100644 --- a/doc/rdisc.xml +++ b/doc/rdisc.xml @@ -232,7 +232,7 @@ xml:id="man.rdisc"> , ping - 8 + 1 . diff --git a/doc/tracepath.xml b/doc/tracepath.xml index 6dbb637..ab06cba 100644 --- a/doc/tracepath.xml +++ b/doc/tracepath.xml @@ -8,7 +8,7 @@ xml:id="man.tracepath"> tracepath - 8 + 1 iputils @@ -192,15 +192,15 @@ root@mops:~ # tracepath -6 3ffe:2400:0:109::2 traceroute - 8 + 1 , traceroute6 - 8 + 1 , ping - 8 + 1 . diff --git a/doc/traceroute6.xml b/doc/traceroute6.xml index 5a72784..eb1da4b 100644 --- a/doc/traceroute6.xml +++ b/doc/traceroute6.xml @@ -10,7 +10,7 @@ xml:id="man.traceroute6"> traceroute6 - 8 + 1 iputils @@ -61,7 +61,7 @@ xml:id="man.traceroute6"> Description can be found in traceroute - 8 + 1 , all the references to IP replaced to IPv6. It is needless to copy the description from there. @@ -71,15 +71,15 @@ xml:id="man.traceroute6"> traceroute - 8 + 1 , tracepath - 8 + 1 , ping - 8 + 1 . diff --git a/fixfds.c b/fixfds.c new file mode 100644 index 0000000..e1298a0 --- /dev/null +++ b/fixfds.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "fixfds.h" + +void +fix_fds (void) +{ + struct stat stb; + + if ((fstat (STDIN_FILENO, &stb) < 0) + && (open (_PATH_DEVNULL, O_RDONLY) != STDIN_FILENO)) + error (EXIT_FAILURE, errno, "open: %s", _PATH_DEVNULL); + + if ((fstat (STDOUT_FILENO, &stb) < 0) + && (open (_PATH_DEVNULL, O_WRONLY) != STDOUT_FILENO)) + error (EXIT_FAILURE, errno, "open: %s", _PATH_DEVNULL); + + if ((fstat (STDERR_FILENO, &stb) < 0) + && (open (_PATH_DEVNULL, O_WRONLY) != STDERR_FILENO)) + error (EXIT_FAILURE, errno, "open: %s", _PATH_DEVNULL); +} diff --git a/fixfds.h b/fixfds.h new file mode 100644 index 0000000..419fe37 --- /dev/null +++ b/fixfds.h @@ -0,0 +1,6 @@ +#ifndef __FIXFDS_H__ +#define __FIXFDS_H__ + +extern void fix_fds (void); + +#endif /* __FIXFDS_H__ */ diff --git a/meson.build b/meson.build index cc88544..f3534d1 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('iputils', 'c', default_options : [ - 'c_std=c99', + 'c_std=gnu99', 'warning_level=3', 'localstatedir=var', ], @@ -77,7 +77,7 @@ if cc.compiles(''' #include #include int main(void) { - struct icmp6_nodeinfo nodeinfo; + struct icmp6_nodeinfo nodeinfo __attribute__((unused)); return 0; } ''', name : 'struct icmp6_nodeinfo') @@ -90,7 +90,7 @@ if cc.compiles(''' #include #include int main(void) { - struct tm time; + struct tm time __attribute__((unused)); return 0; } ''', name : 'struct tm time;') @@ -132,6 +132,8 @@ if gettext == true intl_dep += cc.find_library('intl', required : false) endif +add_project_link_arguments('-pie', language: 'c') + idn = get_option('USE_IDN') if idn == true idn_dep = dependency('libidn2', required : false) @@ -243,15 +245,15 @@ if build_ping == true endif if build_tracepath == true - executable('tracepath', ['tracepath.c', git_version_h], - dependencies : [idn_dep, intl_dep], + executable('tracepath', ['tracepath.c', 'modcap.c', 'fixfds.c', git_version_h], + dependencies : [cap_dep, idn_dep], link_with : [libcommon], install: true) endif if build_traceroute6 == true - executable('traceroute6', ['traceroute6.c', git_version_h], - dependencies : [cap_dep, intl_dep, idn_dep], + executable('traceroute6', ['traceroute6.c', 'modcap.c', 'fixfds.c', git_version_h], + dependencies : [cap_dep, idn_dep], link_with : [libcommon], install: true) if (setcap_traceroute6) @@ -265,13 +267,14 @@ if build_traceroute6 == true endif if build_clockdiff == true - executable('clockdiff', ['clockdiff.c', git_version_h], - dependencies : [cap_dep, intl_dep], + executable('clockdiff', ['clockdiff.c', 'modcap.c', 'fixfds.c', git_version_h], + dependencies : [cap_dep], + install_dir: 'sbin', link_with : [libcommon], install: true) if (setcap_clockdiff) meson.add_install_script('build-aux/setcap-setuid.sh', - bindir, + sbindir, 'clockdiff', perm_type, setcap_path @@ -305,13 +308,14 @@ if build_rdisc == true endif if build_arping == true - executable('arping', ['arping.c', git_version_h], - dependencies : [rt_dep, cap_dep, idn_dep, intl_dep], + executable('arping', ['arping.c', 'modcap.c', 'fixfds.c', git_version_h], + dependencies : [rt_dep, cap_dep, idn_dep], + install_dir: 'sbin', link_with : [libcommon], install: true) if (setcap_arping) meson.add_install_script('build-aux/setcap-setuid.sh', - bindir, + sbindir, 'arping', perm_type, setcap_path diff --git a/modcap.c b/modcap.c new file mode 100644 index 0000000..5ba082c --- /dev/null +++ b/modcap.c @@ -0,0 +1,165 @@ +#ifdef HAVE_LIBCAP +#include +#include +#include +#include +#include +#include +#include +#include + +#include "modcap.h" + +#define FAIL_EXIT(fstr, args...) error (EXIT_FAILURE, errno, fstr, ##args) + +int modify_capability_common(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) { + FAIL_EXIT("cap_get_proc"); + } + + cap_ok = CAP_CLEAR; + if (cap_get_flag(cap_p, cap, CAP_PERMITTED, &cap_ok) < 0) { + FAIL_EXIT("cap_get_flag"); + } + + if (cap_ok == CAP_CLEAR) { + rc = on ? -1 : 0; + goto out; + } + + if (cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on) < 0) { + FAIL_EXIT("cap_set_flag"); + } + + if (cap_set_proc(cap_p) < 0) { + FAIL_EXIT("cap_set_proc"); + } + + rc = 0; +out: + if (cap_p) + cap_free(cap_p); + return rc; +} + +void limit_capabilities_common(int perm_cap_raw, int perm_cap_admin) +{ + cap_t cap_cur_p; + cap_t cap_p; + cap_flag_value_t cap_ok; + const cap_value_t caps[] = {CAP_SETUID, CAP_SETGID}; + const cap_value_t cap_raw = CAP_NET_RAW; + const cap_value_t cap_admin = CAP_NET_ADMIN; + uid_t uid = getuid(); + + cap_p = cap_init(); + if (!cap_p) { + FAIL_EXIT("cap_init"); + } + + if (!uid) { + const char *user = "iputils"; + const char *dir = "/var/resolv"; + struct passwd *pw = getpwnam(user); + gid_t gid; + + if (!pw) + FAIL_EXIT("lookup of user \"%s\" failed", user); + + gid = pw->pw_gid; + uid = pw->pw_uid; + endpwent(); + + if (!uid) + FAIL_EXIT("user \"%s\" shouldn't be root", user); + + if (initgroups(user, gid) < 0) + FAIL_EXIT("initgroups"); + + if (chroot(dir) < 0) + FAIL_EXIT("chroot to \"%s\" failed", dir); + + if (chdir("/") < 0) + FAIL_EXIT("chdir to \"/\" failed"); + + if (cap_set_flag(cap_p, CAP_PERMITTED, 2, caps, CAP_SET) < 0 || + cap_set_flag(cap_p, CAP_EFFECTIVE, 2, caps, CAP_SET) < 0) { + FAIL_EXIT("cap_set_flag"); + } + + if (setregid (gid, gid) < 0) { + FAIL_EXIT("setregid"); + } + } + + cap_cur_p = cap_get_proc(); + if (!cap_cur_p) { + FAIL_EXIT("cap_get_proc"); + } + + if (perm_cap_admin) { + cap_ok = CAP_CLEAR; + if (cap_get_flag(cap_cur_p, CAP_NET_ADMIN, CAP_PERMITTED, &cap_ok) < 0) + FAIL_EXIT("cap_get_flag"); + + if (cap_ok != CAP_CLEAR) { + if (cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_admin, CAP_SET) < 0) + FAIL_EXIT("cap_set_flag"); + } + } + + if (perm_cap_raw) { + cap_ok = CAP_CLEAR; + if (cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok) < 0) + FAIL_EXIT("cap_get_flag"); + + if (cap_ok != CAP_CLEAR) { + if (cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_raw, CAP_SET) < 0) + FAIL_EXIT("cap_set_flag"); + } + } + + cap_free(cap_cur_p); + + if (cap_set_proc(cap_p) < 0) { + FAIL_EXIT("cap_set_proc"); + } + + if (prctl(PR_SET_KEEPCAPS, 1) < 0) { + FAIL_EXIT("prctl(PR_SET_KEEPCAPS, 1) failed"); + } + + if (setreuid (uid, uid) < 0) { + FAIL_EXIT("setreuid"); + } + + if (prctl(PR_SET_KEEPCAPS, 0) < 0) { + FAIL_EXIT("prctl"); + } + + if (cap_set_flag(cap_p, CAP_EFFECTIVE, 2, caps, CAP_CLEAR) < 0 || + cap_set_flag(cap_p, CAP_PERMITTED, 2, caps, CAP_CLEAR) < 0) { + FAIL_EXIT("cap_set_flag"); + } + + if (cap_set_proc(cap_p) < 0) { + FAIL_EXIT("cap_set_proc"); + } + + cap_free(cap_p); +} + +void drop_capabilities_common(void) +{ + cap_t cap = cap_init(); + if (cap_set_proc(cap) < 0) { + FAIL_EXIT("cap_set_proc"); + } + cap_free(cap); +} +#endif /* HAVE_LIBCAP */ diff --git a/modcap.h b/modcap.h new file mode 100644 index 0000000..5af31d7 --- /dev/null +++ b/modcap.h @@ -0,0 +1,11 @@ +#ifndef __MODCAP_H__ +#define __MODCAP_H__ +#ifdef HAVE_LIBCAP +#include + +extern int modify_capability_common(cap_value_t cap, cap_flag_value_t on); +extern void limit_capabilities_common(int perm_cap_raw, int perm_cap_admin); +extern void drop_capabilities_common(void); +#endif /* HAVE_LIBCAP */ + +#endif /* __MODCAP_H__ */ diff --git a/ninfod/meson.build b/ninfod/meson.build index 770169a..e6ee93c 100644 --- a/ninfod/meson.build +++ b/ninfod/meson.build @@ -1,5 +1,7 @@ inc = include_directories('..') ninfod_sources = files(''' + ../fixfds.h + ../fixfds.c icmp6_nodeinfo.h ni_ifaddrs.c ni_ifaddrs.h diff --git a/ninfod/ni_ifaddrs.c b/ninfod/ni_ifaddrs.c index 01ccaf5..5df0322 100644 --- a/ninfod/ni_ifaddrs.c +++ b/ninfod/ni_ifaddrs.c @@ -86,7 +86,7 @@ struct nlmsg_list { struct nlmsg_list *nlm_next; struct nlmsghdr *nlh; int size; - time_t seq; + uint32_t seq; }; #ifndef IFA_LOCAL diff --git a/ninfod/ninfod.c b/ninfod/ninfod.c index aa3cd79..9aa07f6 100644 --- a/ninfod/ninfod.c +++ b/ninfod/ninfod.c @@ -117,6 +117,8 @@ # include #endif +#include "../fixfds.h" + #include "iputils_common.h" #include "iputils_ni.h" #include "ninfod.h" @@ -634,6 +636,7 @@ int main (int argc, char **argv) atexit(close_stdout); appname = argv[0]; + fix_fds(); set_logfile(); limit_capabilities(); diff --git a/ping/meson.build b/ping/meson.build index 1e678ec..3ee7be6 100644 --- a/ping/meson.build +++ b/ping/meson.build @@ -5,6 +5,8 @@ ping = executable('ping', [ 'ping_common.c', 'ping6_common.c', 'node_info.c', + '../modcap.c', + '../fixfds.c', git_version_h ], include_directories : inc, diff --git a/ping/ping.c b/ping/ping.c index 6fcb44f..549c6b8 100644 --- a/ping/ping.c +++ b/ping/ping.c @@ -61,6 +61,8 @@ /* FIXME: global_rts will be removed in future */ struct ping_rts *global_rts; +#include "fixfds.h" + #ifndef ICMP_FILTER #define ICMP_FILTER 1 struct icmp_filter { @@ -174,20 +176,27 @@ static double ping_strtod(const char *str, const char *err_msg) { double num; char *end = NULL; + int strtod_errno; if (str == NULL || *str == '\0') goto err; - errno = 0; /* * Here we always want to use locale regardless USE_IDN or ENABLE_NLS, * because it handles decimal point of -i/-W input options. */ setlocale(LC_ALL, "C"); + errno = 0; num = strtod(str, &end); + strtod_errno = errno; setlocale(LC_ALL, ""); - if (errno || str == end || (end && *end)) { + if (strtod_errno) { + errno = strtod_errno; + goto err; + } + + if (str == end || (end && *end)) { error(0, 0, _("option argument contains garbage: %s"), end); error(0, 0, _("this will become fatal error in the future")); } @@ -276,10 +285,6 @@ main(int argc, char **argv) .pipesize = -1, .datalen = DEFDATALEN, .screen_width = INT_MAX, -#ifdef HAVE_LIBCAP - .cap_raw = CAP_NET_RAW, - .cap_admin = CAP_NET_ADMIN, -#endif .pmtudisc = -1, .source.sin_family = AF_INET, .source6.sin6_family = AF_INET6, @@ -289,6 +294,8 @@ main(int argc, char **argv) /* FIXME: global_rts will be removed in future */ global_rts = &rts; + fix_fds(); + atexit(close_stdout); limit_capabilities(&rts); @@ -740,7 +747,7 @@ int ping4_run(struct ping_rts *rts, int argc, char **argv, struct addrinfo *ai, if (!ifa->ifa_name || !ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET) continue; - if (!strcmp(ifa->ifa_name, rts->device) && + if (!strncmp(ifa->ifa_name, rts->device, IFNAMSIZ) && !memcmp(&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, &rts->source.sin_addr, sizeof(rts->source.sin_addr))) break; @@ -931,6 +938,8 @@ int ping4_run(struct ping_rts *rts, int argc, char **argv, struct addrinfo *ai, setup(rts, sock); + drop_capabilities(); + hold = main_loop(rts, &ping4_func_set, sock, packet, packlen); free(packet); return hold; diff --git a/ping/ping.h b/ping/ping.h index b81a2f1..cefaba8 100644 --- a/ping/ping.h +++ b/ping/ping.h @@ -35,7 +35,7 @@ #ifdef HAVE_LIBCAP # include -# include +#include "modcap.h" #endif #include "iputils_common.h" @@ -206,10 +206,6 @@ struct ping_rts { /* Used only in ping_common.c */ int screen_width; -#ifdef HAVE_LIBCAP - cap_value_t cap_raw; - cap_value_t cap_admin; -#endif /* Used only in ping6_common.c */ struct sockaddr_in6 firsthop; diff --git a/ping/ping6_common.c b/ping/ping6_common.c index 986210b..24a4644 100644 --- a/ping/ping6_common.c +++ b/ping/ping6_common.c @@ -206,7 +206,7 @@ int ping6_run(struct ping_rts *rts, int argc, char **argv, struct addrinfo *ai, if (!ifa->ifa_name || !ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET6) continue; - if (!strcmp(ifa->ifa_name, rts->device) && + if (!strncmp(ifa->ifa_name, rts->device, IFNAMSIZ) && IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, &rts->source6.sin6_addr)) break; diff --git a/ping/ping_common.c b/ping/ping_common.c index 357c39d..0147842 100644 --- a/ping/ping_common.c +++ b/ping/ping_common.c @@ -88,81 +88,25 @@ void usage(void) exit(2); } -void limit_capabilities(struct ping_rts *rts) -{ #ifdef HAVE_LIBCAP - cap_t cap_cur_p; - cap_t cap_p; - cap_flag_value_t cap_ok; - - cap_cur_p = cap_get_proc(); - if (!cap_cur_p) - error(-1, errno, "cap_get_proc"); - cap_p = cap_init(); - if (!cap_p) - error(-1, errno, "cap_init"); - cap_ok = CAP_CLEAR; - cap_get_flag(cap_cur_p, CAP_NET_ADMIN, CAP_PERMITTED, &cap_ok); - if (cap_ok != CAP_CLEAR) - cap_set_flag(cap_p, CAP_PERMITTED, 1, &rts->cap_admin, CAP_SET); - cap_ok = CAP_CLEAR; - cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok); - if (cap_ok != CAP_CLEAR) - cap_set_flag(cap_p, CAP_PERMITTED, 1, &rts->cap_raw, CAP_SET); - if (cap_set_proc(cap_p) < 0) - error(-1, errno, "cap_set_proc"); - if (prctl(PR_SET_KEEPCAPS, 1) < 0) - error(-1, errno, "prctl"); - if (setuid(getuid()) < 0) - error(-1, errno, "setuid"); - if (prctl(PR_SET_KEEPCAPS, 0) < 0) - error(-1, errno, "prctl"); - cap_free(cap_p); - cap_free(cap_cur_p); +void limit_capabilities(struct ping_rts *rts __attribute__((__unused__))) +{ + limit_capabilities_common(1, 1); +} #else - euid = geteuid(); -#endif +void limit_capabilities(struct ping_rts *rts) +{ rts->uid = getuid(); -#ifndef HAVE_LIBCAP + euid = geteuid(); if (seteuid(rts->uid)) error(-1, errno, "setuid"); -#endif } +#endif #ifdef HAVE_LIBCAP 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; + return modify_capability_common(cap, on); } #else int modify_capability(int on) @@ -179,10 +123,7 @@ int modify_capability(int on) void drop_capabilities(void) { #ifdef HAVE_LIBCAP - cap_t cap = cap_init(); - if (cap_set_proc(cap) < 0) - error(-1, errno, "cap_set_proc"); - cap_free(cap); + drop_capabilities_common(); #else if (setuid(getuid())) error(-1, errno, "setuid"); diff --git a/tracepath.c b/tracepath.c index fb4bdca..50ec509 100644 --- a/tracepath.c +++ b/tracepath.c @@ -23,6 +23,10 @@ #include #include #include +#ifdef HAVE_LIBCAP +#include "modcap.h" +#endif +#include "fixfds.h" /* * Keep linux/ includes after standard headers. @@ -435,6 +439,13 @@ int main(int argc, char **argv) char *p; char pbuf[NI_MAXSERV]; + fix_fds(); + +#ifdef HAVE_LIBCAP + limit_capabilities_common(0, 0); + drop_capabilities_common(); +#endif + atexit(close_stdout); #if defined(USE_IDN) || defined(ENABLE_NLS) setlocale(LC_ALL, ""); diff --git a/traceroute6.c b/traceroute6.c index c7cc242..1f85373 100644 --- a/traceroute6.c +++ b/traceroute6.c @@ -249,12 +249,14 @@ #endif #ifdef HAVE_LIBCAP -# include +#include "modcap.h" #endif #include "iputils_common.h" #include "ipv6.h" +#include "fixfds.h" + #ifdef USE_IDN # define ADDRINFO_IDN_FLAGS AI_IDN # define getnameinfo_flags NI_IDN @@ -656,6 +658,8 @@ int main(int argc, char **argv) uint32_t seq = 0; char *resolved_hostname = NULL; + fix_fds(); + atexit(close_stdout); ctl.datalen = sizeof(struct pkt_format); ctl.icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); @@ -665,13 +669,8 @@ int main(int argc, char **argv) if (setuid(getuid())) error(-1, errno, "setuid"); #ifdef HAVE_LIBCAP - { - cap_t caps = cap_init(); - - if (cap_set_proc(caps)) - error(-1, errno, "cap_set_proc"); - cap_free(caps); - } + limit_capabilities_common(0, 0); + drop_capabilities_common(); #endif #if defined(USE_IDN) || defined(ENABLE_NLS)