Skip to content

Ping.Send buffer is not really sent on linux running as non-root #62458

@svc-user

Description

@svc-user

Description

When creating a new instance of the Ping class and calling the Send method providing a buffer, the buffer is not put into the ICMP message that's sent over the network unless the program is run as root.

Instead the runtime simply forwards the call to the ping binary on the system, applying the -s parameter that tells ping how large a payload should be sent. From here it's the systems ping command actually generating the payload and not the payload defined in the C# code.

Reproduction Steps

Create a new console application with dotnet new console -n fancy-project-name and cd into the directory. Use the following code in Program.cs

using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;

if (args[0] == "/Client")
{
    Client();
}
else if (args[0] == "/Server")
{
    Server();
}

static void Client()
{
    Ping pinger = new();

    byte[] buff = new byte[123];
    for (int i = 0; i < buff.Length; i++)
    {
        buff[i] = (byte)'A'; // fill buff with something easily recognizable
    }

    pinger.Send(IPAddress.Parse("127.0.0.1"), 10, buff);
}

static void Server()
{
    Socket s = new(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
    s.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 0));

    Console.WriteLine("Listening for ICMP message.");

    byte[] buff = new byte[1024];
    var r = s.Receive(buff);

    Console.WriteLine($"Received {r}bytes.");
    for (int i = 0; i < r; i++)
    {
        Console.Write(buff[i].ToString("x02") + " ");
        if (i != 0 && i % 16 == 0)
        {
            Console.WriteLine();
        }
    }
    Console.WriteLine();
}

Build the executable with dotnet build and cd into the build output folder. Open a second terminal in the same folder.
In terminal window A run the server-part as root sudo ./fancy-project-name /Server.
In terminal window B run the client-part as non-root ./fancy-project-name /Client. Notice how the output is not the hex-code for 'A'.
Rerun the server as root in terminal window A and now rerun the client as root in terminal window B. This time the server prints the expected bytes.

Expected behavior

The supplied buffer is sent along with the ICMP echo message.

Actual behavior

The wrong payload is sent along with the ICMP echo message.

Regression?

No response

Known Workarounds

Running any "Client" program as root sends along the correct buffer.

Configuration

Output of dotnet --info

.NET SDK (reflecting any global.json):
 Version:   6.0.100
 Commit:    9e8b04bbff

Runtime Environment:
 OS Name:     debian
 OS Version:  
 OS Platform: Linux
 RID:         debian-x64
 Base Path:   /usr/share/dotnet/sdk/6.0.100/

Host (useful for support):
  Version: 6.0.0
  Commit:  4822e3c3aa

.NET SDKs installed:
  2.2.402 [/usr/share/dotnet/sdk]
  5.0.403 [/usr/share/dotnet/sdk]
  6.0.100 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.2.8 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.2.8 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.12 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.2.8 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.12 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-System.Netbughelp wanted[up-for-grabs] Good issue for external contributorsos-linuxLinux OS (any supported distro)

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions