Skip to content

Conversation

afshin-deriv
Copy link

@afshin-deriv afshin-deriv commented Sep 23, 2025

Fix interface existence check on Linux before privileged operations

When attempting to open a non-existent network interface on Linux,
libpcap would return PCAP_ERROR_PERM_DENIED instead of the correct
PCAP_ERROR_NO_SUCH_DEVICE. This occurred because the privileged
socket(PF_PACKET, SOCK_RAW, 0) call in setup_socket() would fail
with permission errors before interface validation could occur.

This fix adds an interface existence check using an unprivileged
AF_INET socket and SIOCGIFINDEX ioctl before attempting to create
the privileged packet socket. Non-existent interfaces now correctly
return PCAP_ERROR_NO_SUCH_DEVICE.

This resolves the issue where applications like tcpdump would report
"Permission denied" instead of "No such device exists" for non-existent
interfaces, breaking their fallback logic from interface names to indices.

Note: BSD/macOS platforms have the same underlying issue where BPF device
access fails with permission errors before interface validation. This
should be addressed in a separate commit.

Fixes: libpcap issue #1538
Related: tcpdump issue #1334

./tcpdump -i nonexistent
tcpdump: nonexistent: No such device exists
(No such device exists)

./tcpdump -i eth999
tcpdump: eth999: No such device exists
(No such device exists)

// The zero-padded interface numbers like 000000000000008 are being interpreted as interface index 8, which actually exists, so the permission error is correct behavior

./tcpdump -i 000000000000008
tcpdump: vethad16f6a: You don't have permission to perform this capture on that device
(Attempt to create packet socket failed - CAP_NET_RAW may be required)

./tcpdump -i 00000000000000073
tcpdump: Invalid adapter index 73: only 72 interfaces found

@infrastation
Copy link
Member

Thank you for preparing this change. The comments that clarify the problem and the solution should be in the commit message.

* There's nothing more to say, so clear the
* error message.
*/
handle->tstamp_type_list = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why tstamp_type_list no longer needs to be set here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for reviewing these changes
because current code ignoring the ENODEV error and treating it as a success case, assumes the user will discover the real problem later during activation

  case ENODEV:
      ..
      handle->tstamp_type_list = NULL;
      return 0;  // SUCCESS, continue execution

This is problematic because it allows execution to continue with a non existent interface, leading to confusing error messages later

The new code immediately fails when it detects ENODEV:

  case ENODEV:
      ...
      ebuf[0] = '\0';
      return PCAP_ERROR_NO_SUCH_DEVICE;  // MMEDIATE FAILURE

after returning PCAP_ERROR_NO_SUCH_DEVICE, the calling function (pcapint_create_interface) do:

  if (iface_get_ts_types(device, handle, ebuf) == -1) {
      pcap_close(handle);  // Cleans up the handle
      return NULL;         // Function exits immediately
  }

Since the function exits immediately and calls pcap_close(handle), there's no point in setting tstamp_type_list

@infrastation
Copy link
Member

On Linux the only proposed change is to iface_get_ts_types(), thus the "check for existence before trying a privileged operation" logic does not apply to Linux:

$ ./testprogs/activatetest 
Trying to use capture device "nosuchdevice"...
FAIL: Permission denied from pcap_activate(), retry with higher privileges.

It looks like the two proposed changes are not related and should be two different commits, each stating and solving a separate problem. Also, since pcap-linux.c already implements helper functions such as iface_get_id(), it would be easy to implement the same logic for Linux. That said, the logic increases the race condition window, which would require some attention.

This requires a bit more work before it is ready.

@afshin-deriv afshin-deriv force-pushed the non-existent-interface branch 2 times, most recently from d5797aa to 8b097c7 Compare September 24, 2025 02:01
@afshin-deriv afshin-deriv marked this pull request as draft September 24, 2025 03:25
  When attempting to open a non-existent network interface on Linux,
  libpcap would return PCAP_ERROR_PERM_DENIED instead of the correct
  PCAP_ERROR_NO_SUCH_DEVICE. This occurred because the privileged
  socket(PF_PACKET, SOCK_RAW, 0) call in setup_socket() would fail
  with permission errors before interface validation could occur.

  This fix adds an interface existence check using an unprivileged
  AF_INET socket and SIOCGIFINDEX ioctl before attempting to create
  the privileged packet socket. Non-existent interfaces now correctly
  return PCAP_ERROR_NO_SUCH_DEVICE.

  This resolves the issue where applications like tcpdump would report
  "Permission denied" instead of "No such device exists" for non-existent
  interfaces, breaking their fallback logic from interface names to indices.

  Note: BSD/macOS platforms have the same underlying issue where BPF device
  access fails with permission errors before interface validation. This
  should be addressed in a separate commit.

  Fixes: libpcap issue the-tcpdump-group#1538
  Related: tcpdump issue the-tcpdump-group#1334

Signed-off-by: Afshin Paydar <afshin.paydar@deriv.com>
@afshin-deriv afshin-deriv marked this pull request as ready for review September 24, 2025 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants