]> git.gsnw.org Git - fping.git/commitdiff
fix -k, --fwmark with setuid fping executable
authorErik Auerswald <auerswal@unix-ag.uni-kl.de>
Mon, 29 Jul 2024 17:38:16 +0000 (19:38 +0200)
committerErik Auerswald <auerswal@unix-ag.uni-kl.de>
Sat, 17 Aug 2024 15:10:59 +0000 (17:10 +0200)
* Setting the SO_MARK socket option requires root privileges (or
  CAP_NET_ADMIN), thus temporarily elevate privileges for this
  operation, if possible, by using the p_setsockopt() function.
  This allows to use -k, --fwmark with setuid fping.
* Adjust README.md since setuid now works for -k, --fwmark.
* Remove "sudo" from testing -k since it is no longer needed.
* Test failure of setting firewall mark without privileges or
  capabilities for both IPv4 and IPv6.

README.md
ci/test-07-options-i-m.pl
ci/test-11-unpriv.pl
src/fping.c

index 43925b67c931b0c3f54ae3ed01d1e74efac601ac..8cf4f88ab52ea0b0bc30f30cd70880080f807ccd 100644 (file)
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ also run fping in unprivileged mode. This works on MacOS and also on Linux,
 provided that your GID is included in the range defined in
 `/proc/sys/net/ipv4/ping_group_range`. This is particularly useful for running
 fping in rootless / unprivileged containers. The --fwmark option needs root or
-cap_net_admin. setuid will not work for --fwmark.
+cap_net_admin.
 
 ## Usage
 
index 4a29970d35000cd9012efbdc9b8809bae0f2af60..185d015620dd530b4a4c67615276c0aad8ad3f7e 100755 (executable)
@@ -30,7 +30,7 @@ SKIP: {
 if($^O ne 'linux') {
     skip '-k option is only supported on Linux', 3;
 }
-my $cmd = Test::Command->new(cmd => 'sudo env "PATH=$PATH" fping -k 256 127.0.0.1');
+my $cmd = Test::Command->new(cmd => 'fping -k 256 127.0.0.1');
 $cmd->exit_is_num(0);
 $cmd->stdout_is_eq("127.0.0.1 is alive\n");
 $cmd->stderr_is_eq("");
index 0f10a1a370f708417fa3d35a259beba85aba72f6..9a15bc0d1af6c9bea7804c82a2fa6d925fc6e731 100755 (executable)
@@ -35,7 +35,7 @@ else {
 }
 
 sub test_unprivileged_works {
-    plan tests => 6;
+    plan tests => 12;
 
     {
         my $cmd = Test::Command->new(cmd => "/tmp/fping.copy 127.0.0.1");
@@ -49,6 +49,27 @@ sub test_unprivileged_works {
         $cmd->stdout_is_eq("127.0.0.1 is alive (TOS unknown)\n");
         $cmd->stderr_is_eq("");
     }
+    SKIP: {
+        if($^O ne 'linux') {
+            skip '-k option is only supported on Linux', 3;
+        }
+        my $cmd = Test::Command->new(cmd => "/tmp/fping.copy -4 -k 256 127.0.0.1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("127.0.0.1 is alive\n");
+        $cmd->stderr_like(qr{fwmark ipv4: .+\n});
+    }
+    SKIP: {
+        if($^O ne 'linux') {
+            skip '-k option is only supported on Linux', 3;
+        }
+        if($ENV{SKIP_IPV6}) {
+            skip 'Skip IPv6 tests', 3;
+        }
+        my $cmd = Test::Command->new(cmd => "/tmp/fping.copy -6 -k 256 ::1");
+        $cmd->exit_is_num(0);
+        $cmd->stdout_is_eq("::1 is alive\n");
+        $cmd->stderr_like(qr{fwmark ipv6: .+\n});
+    }
 }
 
 sub test_privileged_fails {
index b74895ff96423a7871ad9f1c88e151ab899b37f6..696a017bcaec4772a26ac00cfeefaf052a019146 100644 (file)
@@ -816,12 +816,12 @@ int main(int argc, char **argv)
                 usage(1);
 
             if (socket4 >= 0)
-                if(-1 == setsockopt(socket4, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
+                if(-1 == p_setsockopt(suid, socket4, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
                     perror("fwmark ipv4");
 
 #ifdef IPV6
             if (socket6 >= 0)
-                if(-1 == setsockopt(socket6, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
+                if(-1 == p_setsockopt(suid, socket6, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
                     perror("fwmark ipv6");
 #endif