-
-
Notifications
You must be signed in to change notification settings - Fork 105
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
When piped into, nsd-checkzone cannot open /dev/stdin #380
Comments
Hi @dcepelik. Thanks for reporting! (And sorry for taking so long to respond.) With 4.10.0 we started using simdzone to improve zone loading performance. We use the There's nothing really "fishy" going on if you ask me(?) We simply prepended the basedir of the includer if the path was relative and then resolved it. Since 4.10.1 we prepend the current working directory. We can probably catch this case by testing if the file is a device, possibly even detecting if the resolved path starts with a |
Hi @k0ekk0ek, no problem!
Ah, right; I'm on 4.10.0. I'll update then :)
"Fishy" certainly was a poor choice of words, sorry. I was surprised by the amount of ad-hoc string manipulation. In my experience, that's where the nasty bugs happen, so I tend to avoid it if possible.
I looked at the code a bit more. The resolve_path function is static and only used in one place in open_file. There, it's always resolved relative to the current working directory (if relative). Unless I'm mistaken, you paste includer (which is always the current working directory) and include; then hand this over to realpath to resolve? In that case, the whole thing simplifies to char *abs = realpath(include, NULL);
if (!abs)
return ...; // errno contains the error (And that's probably just as portable as the current solution, without having to special-case for Win32.)
Right! So perhaps the original logic was necessary, but not anymore? This could make for a very nice clean-up. Also, nitpick: int length = snprintf(
buffer, sizeof(buffer), "%s/%s", includer, include);
if (length < 0)
return ZONE_OUT_OF_MEMORY; This doesn't seem right to me: how do we know the cause is insufficient memory? Also, there's no check for |
To resolve the original issue:
Would you please point me to the cycle-detection logic? I wanted to check so that I don't suggest nonsense but couldn't find it.
From proc(5):
In other words, what realpath returns is a special-format entry and not an absolute file path; the original name (/dev/stdin) refers to something (an anonymous pipe) that has no file name to begin with.
So, it's not a device file, it's a symlink with special content. |
The include checks are done here. It does both, cyclic check and include depth. I prefer to leave that detection as-is. I think we indeed just use the name in the the include directive for We don't need to worry about the race. I mean yes, theoretically one can update the link etc, but at that point updating the contents of an actual file is an attack vector too(?)
Do you want to make the changes and issue a PR or do you prefer I do so? |
Ah! Of course. I forgot to look into the submodule. Thank you :)
OK
I'm happy to fix both as long as somebody else is able to test the changes on Windows.
I assumed the race might happen if another program is re-generating zones and the reload of nsd happens at an unfortunate moment. Then it could fool the cycle detection code, leading to a false positive or a false negative. I think I understand now: there's a depth limit to make sure you don't get stuck in an infinite loop, which is simple and foolproof but probably not too user-friendly (what caused the loop?) and this realpath-based mechanism which is able to produce meaningful diagnostics, correct? If that's the case, false negatives are not possible. I think that's good enough.
I would be happy to provide a fix. |
We have Windows tests in place and I can do some manual testing in a VM. |
When piped into, nsd-checkzone cannot open /dev/stdin:
But invocation with /dev/stdin works when executed without being piped into. The difference in the invocations is:
This used to work, so something must have changed recently. I tracked this down to
simdzone/src/zone.c
(in the Git submodule) inresolve_path
(probably).https://github.com/NLnetLabs/simdzone/blob/7efedd672462d1062d5a73fb9c033ce75e8b2c14/src/zone.c#L149-L174
The code seems a bit fishy to me; at the very least the following is bound to produce confusing diagnostics:
https://github.com/NLnetLabs/simdzone/blob/7efedd672462d1062d5a73fb9c033ce75e8b2c14/src/zone.c#L173
Overall, the whole file-reading logic seems overly complex. Couldn't we just
fopen
the argument (and check errno) and be done with it? I may be wrong, I only read the code superficially and of course don't know the whole story. But this shouldn't be too hard I think?I'm running nsd-checkzone 4.10.0. Please let me know if I can provide further info or help with debugging and/or testing. :)
Debugged with @trueMiskin while investigating a failing DNSSEC integration.
The text was updated successfully, but these errors were encountered: