Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37037342
en ru br
ALT Linux repos
S:20221126-alt1
5.0: 20071127-alt4
4.1: 20071127-alt0.M41.1
4.0: 20020927-alt4.2
3.0: 20020927-alt2

Group :: Networking/Other
RPM: iputils

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: iputils-20221126-alt1.patch
Download


 arping.c            |  74 ++++-------------------
 clockdiff.c         |  12 ++--
 doc/arping.xml      |   4 +-
 doc/clockdiff.xml   |   4 +-
 doc/meson.build     |  29 +++++++--
 doc/ping.xml        |   2 +-
 doc/tracepath.xml   |   8 +--
 fixfds.c            |  27 +++++++++
 fixfds.h            |   6 ++
 meson.build         |  22 ++++---
 modcap.c            | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 modcap.h            |  11 ++++
 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 ++++
 18 files changed, 312 insertions(+), 175 deletions(-)
diff --git a/arping.c b/arping.c
index 8c97f63..6e3b6a8 100644
--- a/arping.c
+++ b/arping.c
@@ -33,10 +33,11 @@
 #include <unistd.h>
 
 #ifdef HAVE_LIBCAP
-# include <sys/capability.h>
-# include <sys/prctl.h>
+#include "modcap.h"
 #endif
 
+#include "fixfds.h"
+
 #include "iputils_common.h"
 
 /*
@@ -98,10 +99,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.
@@ -148,72 +145,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)
@@ -870,6 +814,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 5e639ab..80192fe 100644
--- a/clockdiff.c
+++ b/clockdiff.c
@@ -77,8 +77,9 @@
 #include <unistd.h>
 
 #ifdef HAVE_LIBCAP
-# include <sys/capability.h>
+#include "modcap.h"
 #endif
+#include "fixfds.h"
 
 #include "iputils_common.h"
 
@@ -436,11 +437,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");
@@ -526,6 +524,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 58123a4..cac9b51 100644
--- a/doc/arping.xml
+++ b/doc/arping.xml
@@ -237,7 +237,7 @@ xml:id="man.arping">
     </citerefentry>,
     <citerefentry>
       <refentrytitle>ping</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>,
     <citerefentry>
       <refentrytitle>clockdiff</refentrytitle>
@@ -245,7 +245,7 @@ xml:id="man.arping">
     </citerefentry>,
     <citerefentry>
       <refentrytitle>tracepath</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>.</para>
   </refsect1>
 
diff --git a/doc/clockdiff.xml b/doc/clockdiff.xml
index 580d701..f0b4bfa 100644
--- a/doc/clockdiff.xml
+++ b/doc/clockdiff.xml
@@ -165,7 +165,7 @@ xml:id="man.clockdiff">
     <para>
     <citerefentry>
       <refentrytitle>ping</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>,
     <citerefentry>
       <refentrytitle>arping</refentrytitle>
@@ -173,7 +173,7 @@ xml:id="man.clockdiff">
     </citerefentry>,
     <citerefentry>
       <refentrytitle>tracepath</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>.</para>
   </refsect1>
 
diff --git a/doc/meson.build b/doc/meson.build
index 8ae754d..90d75e6 100644
--- a/doc/meson.build
+++ b/doc/meson.build
@@ -1,25 +1,29 @@
 # Copyright (c) Iputils Project, 2017-2019
 
 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_tracepath == true
-	manpages += ['tracepath']
+	manpages1 += ['tracepath']
 endif
 
+manpages = manpages1 + manpages8
+
 xsltproc = find_program('xsltproc', required : build_mans or build_html_mans)
 xsltproc_args = [
 	'--nonet',
@@ -55,7 +59,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',
@@ -70,6 +74,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/ping.xml b/doc/ping.xml
index 6b5c3c2..e17c60d 100644
--- a/doc/ping.xml
+++ b/doc/ping.xml
@@ -10,7 +10,7 @@ xml:id="man.ping">
     <refentrytitle>
       <application>ping</application>
     </refentrytitle>
-    <manvolnum>8</manvolnum>
+    <manvolnum>1</manvolnum>
     <refmiscinfo class='manual'>iputils</refmiscinfo>
   </refmeta>
 
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">
 
   <refmeta>
     <refentrytitle><application>tracepath</application></refentrytitle>
-    <manvolnum>8</manvolnum>
+    <manvolnum>1</manvolnum>
     <refmiscinfo class='manual'>iputils</refmiscinfo>
   </refmeta>
 
@@ -192,15 +192,15 @@ root@mops:~ # tracepath -6 3ffe:2400:0:109::2
     <para>
     <citerefentry>
       <refentrytitle>traceroute</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>,
     <citerefentry>
       <refentrytitle>traceroute6</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>,
     <citerefentry>
       <refentrytitle>ping</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>.</para>
   </refsect1>
 
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 <stdlib.h>
+#include <error.h>
+#include <errno.h>
+#include <unistd.h>
+#include <paths.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#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 2c6ff8d..04e70e6 100644
--- a/meson.build
+++ b/meson.build
@@ -2,7 +2,7 @@
 
 project('iputils', 'c',
 	default_options : [
-		'c_std=c99',
+		'c_std=gnu99',
 		'warning_level=3',
 		'localstatedir=var',
 	],
@@ -68,7 +68,7 @@ if cc.compiles('''
 	#include <netinet/in.h>
 	#include <netinet/icmp6.h>
 	int main(void) {
-		struct icmp6_nodeinfo nodeinfo;
+		struct icmp6_nodeinfo nodeinfo __attribute__((unused));
 		return 0;
 	}
 ''', name : 'struct icmp6_nodeinfo')
@@ -81,7 +81,7 @@ if cc.compiles('''
 	#include <sys/time.h>
 	#include <time.h>
 	int main(void) {
-		struct tm time;
+		struct tm time __attribute__((unused));
 		return 0;
 	}
 ''', name : 'struct tm time;')
@@ -123,6 +123,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)
@@ -182,20 +184,21 @@ if build_ping == true
 endif
 
 if build_tracepath == true
-	tracepath = executable('tracepath', ['tracepath.c', git_version_h],
-		dependencies : [idn_dep, intl_dep],
+	tracepath = executable('tracepath', ['tracepath.c', 'modcap.c', 'fixfds.c', git_version_h],
+		dependencies : [cap_dep, idn_dep, intl_dep],
 		link_with : [libcommon],
 		install: true)
 endif
 
 if build_clockdiff == true
-	clockdiff = executable('clockdiff', ['clockdiff.c', git_version_h],
+	clockdiff = executable('clockdiff', ['clockdiff.c', 'modcap.c', 'fixfds.c', git_version_h],
 		dependencies : [cap_dep, intl_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
@@ -204,13 +207,14 @@ if build_clockdiff == true
 endif
 
 if build_arping == true
-	arping = executable('arping', ['arping.c', git_version_h],
+	arping = executable('arping', ['arping.c', 'modcap.c', 'fixfds.c', git_version_h],
 		dependencies : [rt_dep, cap_dep, idn_dep, intl_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 <stdlib.h>
+#include <error.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <linux/types.h>
+#include <sys/prctl.h>
+
+#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 <sys/capability.h>
+
+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/ping/meson.build b/ping/meson.build
index 522ac19..5d3e08c 100644
--- a/ping/meson.build
+++ b/ping/meson.build
@@ -7,6 +7,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 02d358e..d79d6b2 100644
--- a/ping/ping.c
+++ b/ping/ping.c
@@ -63,6 +63,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 {
@@ -214,20 +216,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"));
 	}
@@ -322,10 +331,6 @@ main(int argc, char **argv)
 		.datalen = DEFDATALEN,
 		.ident = -1,
 		.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,
@@ -335,6 +340,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);
 
@@ -848,7 +855,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;
@@ -1007,6 +1014,8 @@ int ping4_run(struct ping_rts *rts, int argc, char **argv, struct addrinfo *ai,
 
 	drop_capabilities();
 
+	drop_capabilities();
+
 	hold = main_loop(rts, &ping4_func_set, sock, packet, packlen);
 	free(packet);
 
diff --git a/ping/ping.h b/ping/ping.h
index 46cfbe7..77b33f6 100644
--- a/ping/ping.h
+++ b/ping/ping.h
@@ -36,7 +36,7 @@
 
 #ifdef HAVE_LIBCAP
 # include <sys/prctl.h>
-# include <sys/capability.h>
+#include "modcap.h"
 #endif
 
 #include "iputils_common.h"
@@ -207,10 +207,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 */
 	int subnet_router_anycast; /* Subnet-Router anycast (RFC 4291) */
diff --git a/ping/ping6_common.c b/ping/ping6_common.c
index 4b3706f..589ec24 100644
--- a/ping/ping6_common.c
+++ b/ping/ping6_common.c
@@ -213,7 +213,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 d188fb8..df7e5c2 100644
--- a/ping/ping_common.c
+++ b/ping/ping_common.c
@@ -95,81 +95,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)
@@ -186,10 +130,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 4d2a9ac..9c1e905 100644
--- a/tracepath.c
+++ b/tracepath.c
@@ -25,6 +25,10 @@
 #include <sys/uio.h>
 #include <time.h>
 #include <unistd.h>
+#ifdef HAVE_LIBCAP
+#include "modcap.h"
+#endif
+#include "fixfds.h"
 
 /*
  * Keep linux/ includes after standard headers.
@@ -437,6 +441,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, "");
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin