-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DATA RACE]: github.com/cilium/dns.(*Conn).ReadMsgHeader() #33897
Comments
This is a concurrent read/write on The specific instance of write above indicates that the forwarded DNS request was a DNSSec one, as on current main branch the line vendor/github.com/cilium/dns/client.go:242 is:
In order to fix this we may have to assume as large as possible UDP buffer size (64k, or as large as ever needed, maybe 4k) for the shared client and change the setting of
|
I've taken a look and wrote down what I've understood. BackgroundA IssueOur shared client shares single Furthermore I don't know whether mixing message sizes is common (or even allowed), or how common usage of EDNS0 is. It seems to be used in DNSSec, however. On the other hand, I don't know of people using DNSSec inside k8s clusters, and I'm not sure CoreDNS would handle forwarding DNSSec requests either. SolutionsTo make the race detector happy, it would AFAICT be enough to change the UDPSize to be an
Since the buffer allocation and blocking read occurs before the second query is even sent, the atomicity of As mentioned above, one valid approach is to always allocate 65K buffers. This is pretty wasteful. An memory/CPU tradeoff can be made by having a single 65K buffer per conn and copying the actual data once the actual length is known. A second approach: As far as I understand the DNS RFC, as a proxy it would also be allowed to clamp the advertised max buffer size to what the proxy can handle. I don't like semantically changing the data we're proxying, though. A third solution: Large responses can only come from the server after we have sent a query which advertises large buffer. Hence, we can locally delay sending such a query, abort a potential pending read and restart it with a large enough buffer and only then send out the query. As long as we ensure that the buffer size only grows per conn, I believe this is sufficient. It's not possible to implement this using the existing interfaces of the DNS library, but given we have a fork already, we can adapt interfaces to fit. The DNSSec state remains an issue even after solving the buffer sizing. In the spirit of solving what is reported instead of going after theoretical issues, I'd argue for ignoring this issue until reports of breakage come in, with a description of how DNSSec is used. Ideally, though, we avoid race detector hits however, if possible. |
seen with 54796b0
The text was updated successfully, but these errors were encountered: