Skip to content
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

dns: fix crash while using dns.setServers after dns.resolve4 #13050

Closed

Conversation

XadillaX
Copy link
Contributor

@XadillaX XadillaX commented May 16, 2017

The callback function in cares_query is synchronous and called before closed. So dns.setServers in the synchronous callback before closed will occur crashing.

This PR makes the real callback of dns.resolve4 or some other functions in dns asynchronous to resolve this problem.

Solution

I use uv_async_t to send the callback task to next loop. And the task data is created from CaresAsyncData.

Because Callback has two functions with parameters hostent* or unsigned char*, int, CaresAsyncData has a flag is_host to distinguish them.

In the Callback function, whether hostent* or unsigned char* will be destroyed after this function is done. So I make a copy for those buffers for asynchronous use. In the asynchronous function and asynchronous done callback, I delete some related pointers.

Related Issue: #894 #1071

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

dns

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. cares Issues and PRs related to the c-ares dependency or the cares_wrap binding. v6.x labels May 16, 2017
@XadillaX
Copy link
Contributor Author

XadillaX commented May 16, 2017

The related cares code is under ares_process.c.

query->callback(query->arg, status, query->timeouts, abuf, alen);
ares__free_query(query);

If real callback is synchronous and we do dns.setServers in the callback, the program will crash because ares_set_servers will destroy current servers first.

@XadillaX XadillaX changed the title dns: fix crash while using dns.setServers after dns.resolve4 [WIP] dns: fix crash while using dns.setServers after dns.resolve4 May 16, 2017
@XadillaX XadillaX force-pushed the fix/crash_when_setServers_after_resolve branch from 79cd9b4 to 279c383 Compare May 16, 2017 15:17
@XadillaX XadillaX changed the title [WIP] dns: fix crash while using dns.setServers after dns.resolve4 dns: fix crash while using dns.setServers after dns.resolve4 May 16, 2017
@XadillaX XadillaX force-pushed the fix/crash_when_setServers_after_resolve branch from 279c383 to 9806008 Compare May 16, 2017 17:00
@Trott
Copy link
Member

Trott commented May 16, 2017

Awesome!

Someone else will have to comment on the C++ code. /cc @trevnorris @indutny @addaleax @danbev

But I can comment on the test. The test itself looks good. Some small comments:

  • I'm pretty sure the test file needs to go in test/internet because it attempts to do a DNS resolution.
  • In the comment, it's probably a good idea to use the full URL for the GitHub issues rather than the #1234 shortcut. We have a lot of old tests where it is ambiguous if #1234 means issue 1234 in this repo or if it is referring to github.com/nodejs/node-v0.x-archive/. Using the full URL will (hopefully) eliminate that ambiguity.

/cc @nodejs/testing

@XadillaX
Copy link
Contributor Author

XadillaX commented May 17, 2017

@Trott

  • I wrote test refer to test-dns-regress-6244, it resolve4 with 127.0.0.1 and actually has no internet request. And then I setServers with 127.0.0.1 too. And I think we can discuss more about it.
  • I've updated the comment.

Thanks for your suggestions.

@Trott
Copy link
Member

Trott commented May 17, 2017

I wrote test refer to test-dns-regress-6244, it resolve4 with 127.0.0.1 and actually has no internet request.

Are you sure about that? If I change your test code to this:

'use strict';

const common = require('../common');
const dns = require('dns');

dns.resolve4('nodejs.org', common.mustCall(function(err, nameServers) {
  if (err)
    throw err;
}));

...running it with a network connection results in no error. If I run it without a network connection enabled, I get ECONNREFUSED. I haven't fired up Wireshark or anything, but that sure seems to suggest it's sending a DNS request...

@XadillaX
Copy link
Contributor Author

XadillaX commented May 17, 2017

I see. Actually I don't care about whether it will throw an error or not. My test destination is to test whether the case will crash or not.

Anyway, I moved the test case under internet now.

Before this fixture PR, that test case will fail because of crash.

@silverwind
Copy link
Contributor

Shouldn't this target master instead of v6.x? Because as far as I know, the bug is still present there.

@XadillaX
Copy link
Contributor Author

@silverwind hmmmm, I think if this PR is merged, we can port it to master.

But if reviewers consider that this PR must target to master, then I will change the target.

@silverwind
Copy link
Contributor

We generally land on master first and then backport it after a few weeks/months, so I'd appreciate if you target master now.

@XadillaX XadillaX changed the base branch from v6.x to master May 17, 2017 05:23
@XadillaX XadillaX changed the base branch from master to v6.x May 17, 2017 05:24
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: nodejs#894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
@XadillaX XadillaX force-pushed the fix/crash_when_setServers_after_resolve branch from eeb7813 to 0c51d0a Compare May 17, 2017 06:08
@XadillaX XadillaX changed the base branch from v6.x to master May 17, 2017 06:08
@XadillaX
Copy link
Contributor Author

XadillaX commented May 17, 2017

@silverwind I've updated the PR to make master as base. And who help to update the label 6.x?

@silverwind
Copy link
Contributor

I can confirm it fixes the test case in #894.

@pmq20
Copy link
Contributor

pmq20 commented May 17, 2017

Excellent work! Thanks for the patch. To my understanding this PR simply postponed the execution of the callback of dns.resolve4 to the next tick, yet achieved this in a lot of code. I would prefer a simpler approach (or even only patch the JS level if possible), e.g. wrapping the callback function into a process.nextTick(). It would be easier to land if the diff was smaller. Do you think it's possible? @XadillaX

@XadillaX
Copy link
Contributor Author

XadillaX commented May 17, 2017

My consideration is that:

If we solve this bug in JavaScript level, the bug will still exist if developers use DNS binding directly. @pmq20

Or if someone add some new features for dns in dns.js, he / she may forget this bug and then uses sync code.

@@ -296,6 +300,121 @@ Local<Array> HostentToNames(Environment* env, struct hostent* host) {
return scope.Escape(names);
}

/* copies a hostent structure*, returns 0 on success, -1 on error */
/* this function refers to OpenSIPS */
Copy link
Member

Choose a reason for hiding this comment

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

This is code that was licensed under the GPL, we can’t use it – sorry.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I'll rewrite this function then.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thx. I've rewritten those two functions by myself now.

@addaleax
Copy link
Member

Landed in 5a948f6, thanks for the PR!

@addaleax addaleax closed this May 18, 2017
addaleax pushed a commit that referenced this pull request May 18, 2017
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: #894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
PR-URL: #13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@refack
Copy link
Contributor

refack commented May 18, 2017

@XadillaX congrats 🎉 is this your first code contribution?

@silverwind
Copy link
Contributor

It is. Pretty awesome first contribution!

@XadillaX
Copy link
Contributor Author

Yes, it is my first contribution. Thank you all for helping with my first contribution!

anchnk pushed a commit to anchnk/node that referenced this pull request May 19, 2017
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: nodejs#894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
PR-URL: nodejs#13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@sam-github
Copy link
Contributor

2 new defect(s) introduced to Node.js found with Coverity Scan.


New defect(s) Reported-by: Coverity Scan
Showing 2 of 2 defect(s)


** CID 169571:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 467 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, unsigned char *, int)()


________________________________________________________________________________________________________
*** CID 169571:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 467 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, unsigned char *, int)()
461         data->wrap = wrap;
462         data->is_host = false;
463         data->data.buf = buf_copy;
464         data->len = answer_len;
465
466         uv_async_t* async_handle = &data->async_handle;
>>>     CID 169571:  Error handling issues  (CHECKED_RETURN)
>>>     Calling "uv_async_init" without checking return value (as is done elsewhere 9 out of 11 times).
467         uv_async_init(wrap->env()->event_loop(), async_handle, CaresAsyncCb);
468
469         async_handle->data = data;
470         uv_async_send(async_handle);
471       }
472

** CID 169570:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 490 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, hostent *)()


________________________________________________________________________________________________________
*** CID 169570:  Error handling issues  (CHECKED_RETURN)
/src/cares_wrap.cc: 490 in node::cares_wrap::<unnamed>::QueryWrap::Callback(void *, int, int, hostent *)()
484         data->status = status;
485         data->data.host = host_copy;
486         data->wrap = wrap;
487         data->is_host = true;
488
489         uv_async_t* async_handle = &data->async_handle;
>>>     CID 169570:  Error handling issues  (CHECKED_RETURN)
>>>     Calling "uv_async_init" without checking return value (as is done elsewhere 9 out of 11 times).
490         uv_async_init(wrap->env()->event_loop(), async_handle, CaresAsyncCb);
491
492         async_handle->data = data;
493         uv_async_send(async_handle);
494       }
495

@cjihrig
Copy link
Contributor

cjihrig commented May 19, 2017

@sam-github #13116

@gibfahn gibfahn mentioned this pull request May 19, 2017
cjihrig added a commit to cjihrig/node that referenced this pull request May 22, 2017
This commit fixes two coverity warnings for unchecked
return values.

Refs: nodejs#13050
PR-URL: nodejs#13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
jasnell pushed a commit that referenced this pull request May 23, 2017
This commit fixes two coverity warnings for unchecked
return values.

Refs: #13050
PR-URL: #13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
jasnell pushed a commit that referenced this pull request May 23, 2017
This commit fixes two coverity warnings for unchecked
return values.

Refs: #13050
PR-URL: #13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
@jasnell jasnell mentioned this pull request May 28, 2017
@gibfahn gibfahn mentioned this pull request Jun 15, 2017
3 tasks
XadillaX added a commit to XadillaX/node that referenced this pull request Jun 16, 2017
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: nodejs#894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
PR-URL: nodejs#13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@MylesBorins
Copy link
Contributor

MylesBorins commented Jun 23, 2017

It would appear that this is causing build errors on v6.x. I have labelled it as dont-land

If it does land it needs to come with 06f62eb

edit: I left dont land off for now until we hear that someone can say if this needs to land

MylesBorins pushed a commit that referenced this pull request Jul 10, 2017
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: #894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
Backport-PR-URL: #13724
PR-URL: #13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>
MylesBorins pushed a commit that referenced this pull request Jul 10, 2017
This commit fixes two coverity warnings for unchecked
return values.

Refs: #13050
PR-URL: #13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
MylesBorins pushed a commit that referenced this pull request Jul 11, 2017
The callback function in cares_query is synchronous and called before
closed. So dns.setServers in the synchronous callback before closed will
occur crashing.

Fixes: #894
Refs: https://github.com/nodejs/node/blob/v6.9.4/deps/cares/src/ares_process.c#L1332-L1333
Refs: https://github.com/OpenSIPS/opensips/blob/2.3.0/proxy.c
Backport-PR-URL: #13724
PR-URL: #13050
Reviewed-By: Anna Henningsen <anna@addaleax.net>
MylesBorins pushed a commit that referenced this pull request Jul 11, 2017
This commit fixes two coverity warnings for unchecked
return values.

Refs: #13050
PR-URL: #13116
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
@MylesBorins MylesBorins mentioned this pull request Jul 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. cares Issues and PRs related to the c-ares dependency or the cares_wrap binding.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants