]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Fix a TOCTOU in the Async regression tests 15380/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 31 Mar 2025 09:10:34 +0000 (11:10 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 31 Mar 2025 09:10:34 +0000 (11:10 +0200)
The existing code was catching all exceptions based on `OSError`
raised by a call to `os.unlink()` , and re-throwing if the file
actually existed, in an attempt to only ignore the case where
the file did not exist and still fail if the process did not
have enough rights to remove it, for example.
Unfortunately this construct introduced a TOCTOU issue, where the
initial exception might have been raised because the file did not
exist at the time of the call, resulting in a `FileNotFoundError`
exception being raised, but had been created before the existence
check, resulting in a puzzling message:
```
ready: 8/8 workersException in thread Asynchronous Responder:
Traceback (most recent call last):
  File "/usr/lib/python3.13/threading.py", line 992, in run
    self._target(*self._args, **self._kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/pdns/regression-tests.dnsdist/test_Async.py", line 17, in AsyncResponder
    os.unlink(listenPath)
    ~~~~~~~~~^^^^^^^^^^^^
8 workers [816 items]
```

The new code only catches `FileNotFoundError` instead, so that
other errors are still causing a failure without needing a second
check.

regression-tests.dnsdist/test_Async.py

index 474340bdf41583c44182ad34f55b667792dc6047..342ec680e6d0bba394db8c434d0704db09dd286a 100644 (file)
@@ -15,9 +15,8 @@ def AsyncResponder(listenPath, responsePath):
     # Make sure the socket does not already exist
     try:
         os.unlink(listenPath)
-    except OSError:
-        if os.path.exists(listenPath):
-            raise
+    except FileNotFoundError:
+        pass
 
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
     try: