Repository: secdev/scapy

Issue:
Race condition in LinuxInterfaceProvider::load()
### Brief description

When loading scapy, it is possible that the initialization fails if interfaces are being deleted. This is because we're reading /proc/net/dev once and then iterating over all interfaces; however, if interfaces are disappearing during this operation, `ioctl()` will fail with errno 19.

### Scapy version

2.4.5rc1.dev108

### Python version

2.7.6

### Operating system

4.15.0-45

### Additional environment information

_No response_

### How to reproduce

1. Create 1000 tap interfaces
```bash
for i in $(seq 1 1000); do ip tuntap add tap$i mode tap; done
```
2. Open a python prompt and prepare yourself to initialize scapy (without hitting `return` yet)
```python
Python 2.7.6 (default, Nov 23 2017, 15:49:48) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from scapy.all import *
```
3. Open a bash prompt and prepare yourself to delete the 1000 interfaces (without hitting `return` yet)
```bash
for i in $(seq 1 1000); do ip link del tap$i; done
```
4. Hit `return` on the python prompt, and quickly after on the bash prompt
5. The following exception will occur
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "scapy/all.py", line 16, in <module>
    from scapy.arch import *
  File "scapy/arch/__init__.py", line 141, in <module>
    _set_conf_sockets()  # Apply config
  File "scapy/config.py", line 622, in _set_conf_sockets
    conf.ifaces.reload()
  File "scapy/interfaces.py", line 238, in reload
    self._reload_provs()
  File "scapy/interfaces.py", line 234, in _reload_provs
    self._load(prov.reload(), prov)
  File "scapy/interfaces.py", line 53, in reload
    return self.load()
  File "scapy/arch/linux.py", line 417, in load
    ifflags = struct.unpack("16xH14x", get_if(i, SIOCGIFFLAGS))[0]
  File "scapy/arch/common.py", line 65, in get_if
    return ioctl(sck, cmd, struct.pack("16s16x", iff.encode("utf8")))
IOError: [Errno 19] No such device
```

### Actual result

_No response_

### Expected result

The expected result is that scapy continues to load without failing.

### Related resources

_No response_


Discussion:

Resolving patch:
diff --git a/scapy/arch/linux.py b/scapy/arch/linux.py
--- a/scapy/arch/linux.py
+++ b/scapy/arch/linux.py
@@ -414,13 +414,17 @@ def load(self):
         data = {}
         ips = in6_getifaddr()
         for i in _get_if_list():
-            ifflags = struct.unpack("16xH14x", get_if(i, SIOCGIFFLAGS))[0]
-            index = get_if_index(i)
-            mac = scapy.utils.str2mac(
-                get_if_raw_hwaddr(i, siocgifhwaddr=SIOCGIFHWADDR)[1]
-            )
-            ip = None  # type: Optional[str]
-            ip = inet_ntop(socket.AF_INET, get_if_raw_addr(i))
+            try:
+                ifflags = struct.unpack("16xH14x", get_if(i, SIOCGIFFLAGS))[0]
+                index = get_if_index(i)
+                mac = scapy.utils.str2mac(
+                    get_if_raw_hwaddr(i, siocgifhwaddr=SIOCGIFHWADDR)[1]
+                )
+                ip = None  # type: Optional[str]
+                ip = inet_ntop(socket.AF_INET, get_if_raw_addr(i))
+            except IOError:
+                warning("Interface %s does not exist!", i)
+                continue
             if ip == "0.0.0.0":
                 ip = None
             ifflags = FlagValue(ifflags, _iff_flags)


Test patch: