Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37044711
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-20210722-alt3.patch
Download


 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 <unistd.h>
 
 #ifdef HAVE_LIBCAP
-# include <sys/capability.h>
-# include <sys/prctl.h>
+#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 <unistd.h>
 
 #ifdef HAVE_LIBCAP
-# include <sys/capability.h>
+#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">
     <para>
     <citerefentry>
       <refentrytitle>ping</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>,
     <citerefentry>
       <refentrytitle>clockdiff</refentrytitle>
@@ -237,7 +237,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 9643bea..609e766 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 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">
     <para>
     <citerefentry>
       <refentrytitle>ping</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>.</para>
   </refsection>
 
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">
     <refentrytitle>
       <application>ping</application>
     </refentrytitle>
-    <manvolnum>8</manvolnum>
+    <manvolnum>1</manvolnum>
     <refmiscinfo class='manual'>iputils</refmiscinfo>
   </refmeta>
 
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">
     </citerefentry>,
     <citerefentry>
       <refentrytitle>ping</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>.</para>
   </refsection>
 
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/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">
     <refentrytitle>
       <application>traceroute6</application>
     </refentrytitle>
-    <manvolnum>8</manvolnum>
+    <manvolnum>1</manvolnum>
     <refmiscinfo class='manual'>iputils</refmiscinfo>
   </refmeta>
 
@@ -61,7 +61,7 @@ xml:id="man.traceroute6">
     <para>Description can be found in
     <citerefentry>
       <refentrytitle>traceroute</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>, all the references to IP replaced to IPv6.
     It is needless to copy the description from there.</para>
   </refsection>
@@ -71,15 +71,15 @@ xml:id="man.traceroute6">
     <para>
     <citerefentry>
       <refentrytitle>traceroute</refentrytitle>
-      <manvolnum>8</manvolnum>
+      <manvolnum>1</manvolnum>
     </citerefentry>,
     <citerefentry>
       <refentrytitle>tracepath</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 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 <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')
@@ -90,7 +90,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;')
@@ -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 <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/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 <sys/capability.h>
 #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 <sys/prctl.h>
-# include <sys/capability.h>
+#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 <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.
@@ -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 <sys/capability.h>
+#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)
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin