Skip to content

Commit

Permalink
fix -k, --fwmark with setuid fping executable
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
auerswal committed Aug 17, 2024
1 parent fc2fcb3 commit 096a75f
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion ci/test-07-options-i-m.pl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
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("");
Expand Down
23 changes: 22 additions & 1 deletion ci/test-11-unpriv.pl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ sub get_ping_gid_range {
}

sub test_unprivileged_works {
plan tests => 6;
plan tests => 12;

{
my $cmd = Test::Command->new(cmd => "/tmp/fping.copy 127.0.0.1");
Expand All @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions src/fping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 096a75f

Please sign in to comment.