* [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno. @ 2015-07-22 13:07 Richard W.M. Jones 2015-07-22 13:07 ` Richard W.M. Jones 0 siblings, 1 reply; 8+ messages in thread From: Richard W.M. Jones @ 2015-07-22 13:07 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, jcody, qemu-block v2: I fixed several mistakes in the commit message. The code change is the same as before. Rich. ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno. 2015-07-22 13:07 [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno Richard W.M. Jones @ 2015-07-22 13:07 ` Richard W.M. Jones 2015-07-22 13:10 ` Daniel P. Berrange 2015-07-22 13:17 ` Jeff Cody 0 siblings, 2 replies; 8+ messages in thread From: Richard W.M. Jones @ 2015-07-22 13:07 UTC (permalink / raw) To: qemu-devel; +Cc: kwolf, jcody, qemu-block On some (but not all) systems: $ qemu-img create -f qcow2 overlay -b ssh://xen/ Segmentation fault It turns out this happens when inet_connect returns -1 in the following code, but errno == 0. s->sock = inet_connect(s->hostport, errp); if (s->sock < 0) { ret = -errno; goto err; } In the test case above, no host called "xen" exists, so getaddrinfo fails. On Fedora 22, getaddrinfo happens to set errno = ENOENT (although it is *not* documented to do that), so it doesn't segfault. On RHEL 7, errno is not set by the failing getaddrinfo, so ret = -errno = 0, so the caller doesn't know there was an error and continues with a half-initialized BDRVSSHState struct, and everything goes south from there, eventually resulting in a segfault. Fix this by setting ret to -EINVAL. The real error is saved in the Error** errp struct, so it is printed correctly: $ ./qemu-img create -f qcow2 overlay -b ssh://xen/ qemu-img: overlay: address resolution failed for xen:22: No address associated with hostname Signed-off-by: Richard W.M. Jones <rjones@redhat.com> Reported-by: Jun Li BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1147343 --- block/ssh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/ssh.c b/block/ssh.c index aebb18c..8d4dc2a 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -563,7 +563,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, /* Open the socket and connect. */ s->sock = inet_connect(s->hostport, errp); if (s->sock < 0) { - ret = -errno; + ret = -EINVAL; goto err; } -- 2.4.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno. 2015-07-22 13:07 ` Richard W.M. Jones @ 2015-07-22 13:10 ` Daniel P. Berrange 2015-07-22 13:17 ` Richard W.M. Jones 2015-07-22 13:24 ` Kevin Wolf 2015-07-22 13:17 ` Jeff Cody 1 sibling, 2 replies; 8+ messages in thread From: Daniel P. Berrange @ 2015-07-22 13:10 UTC (permalink / raw) To: Richard W.M. Jones; +Cc: kwolf, jcody, qemu-devel, qemu-block On Wed, Jul 22, 2015 at 02:07:22PM +0100, Richard W.M. Jones wrote: > On some (but not all) systems: > > $ qemu-img create -f qcow2 overlay -b ssh://xen/ > Segmentation fault > > It turns out this happens when inet_connect returns -1 in the > following code, but errno == 0. > > s->sock = inet_connect(s->hostport, errp); > if (s->sock < 0) { > ret = -errno; > goto err; > } > > In the test case above, no host called "xen" exists, so getaddrinfo fails. > > On Fedora 22, getaddrinfo happens to set errno = ENOENT (although it > is *not* documented to do that), so it doesn't segfault. > > On RHEL 7, errno is not set by the failing getaddrinfo, so ret = > -errno = 0, so the caller doesn't know there was an error and > continues with a half-initialized BDRVSSHState struct, and everything > goes south from there, eventually resulting in a segfault. > > Fix this by setting ret to -EINVAL. The real error is saved in the > Error** errp struct, so it is printed correctly: > > $ ./qemu-img create -f qcow2 overlay -b ssh://xen/ > qemu-img: overlay: address resolution failed for xen:22: No address associated with hostname > > Signed-off-by: Richard W.M. Jones <rjones@redhat.com> > Reported-by: Jun Li > BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1147343 > --- > block/ssh.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/block/ssh.c b/block/ssh.c > index aebb18c..8d4dc2a 100644 > --- a/block/ssh.c > +++ b/block/ssh.c > @@ -563,7 +563,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, > /* Open the socket and connect. */ > s->sock = inet_connect(s->hostport, errp); > if (s->sock < 0) { > - ret = -errno; > + ret = -EINVAL; > goto err; There are a reasonable number of other uses of inet_connect() in QEMU, so can't we fix inet_connect() itself to set EINVAL in the error case instead of just fixing one caller. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno. 2015-07-22 13:10 ` Daniel P. Berrange @ 2015-07-22 13:17 ` Richard W.M. Jones 2015-07-22 13:24 ` Kevin Wolf 1 sibling, 0 replies; 8+ messages in thread From: Richard W.M. Jones @ 2015-07-22 13:17 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: kwolf, jcody, qemu-devel, qemu-block On Wed, Jul 22, 2015 at 02:10:51PM +0100, Daniel P. Berrange wrote: > There are a reasonable number of other uses of inet_connect() in QEMU, > so can't we fix inet_connect() itself to set EINVAL in the error case > instead of just fixing one caller. The only users I can find are block/nbd.c and block/sheepdog.c, and neither of those is expecting errno to be set. So I think my use of errno in block/ssh.c was flat out wrong, although it happened to work most of the time. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno. 2015-07-22 13:10 ` Daniel P. Berrange 2015-07-22 13:17 ` Richard W.M. Jones @ 2015-07-22 13:24 ` Kevin Wolf 1 sibling, 0 replies; 8+ messages in thread From: Kevin Wolf @ 2015-07-22 13:24 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: jcody, Richard W.M. Jones, qemu-block, qemu-devel Am 22.07.2015 um 15:10 hat Daniel P. Berrange geschrieben: > On Wed, Jul 22, 2015 at 02:07:22PM +0100, Richard W.M. Jones wrote: > > On some (but not all) systems: > > > > $ qemu-img create -f qcow2 overlay -b ssh://xen/ > > Segmentation fault > > > > It turns out this happens when inet_connect returns -1 in the > > following code, but errno == 0. > > > > s->sock = inet_connect(s->hostport, errp); > > if (s->sock < 0) { > > ret = -errno; > > goto err; > > } > > > > In the test case above, no host called "xen" exists, so getaddrinfo fails. > > > > On Fedora 22, getaddrinfo happens to set errno = ENOENT (although it > > is *not* documented to do that), so it doesn't segfault. > > > > On RHEL 7, errno is not set by the failing getaddrinfo, so ret = > > -errno = 0, so the caller doesn't know there was an error and > > continues with a half-initialized BDRVSSHState struct, and everything > > goes south from there, eventually resulting in a segfault. > > > > Fix this by setting ret to -EINVAL. The real error is saved in the > > Error** errp struct, so it is printed correctly: > > > > $ ./qemu-img create -f qcow2 overlay -b ssh://xen/ > > qemu-img: overlay: address resolution failed for xen:22: No address associated with hostname > > > > Signed-off-by: Richard W.M. Jones <rjones@redhat.com> > > Reported-by: Jun Li > > BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1147343 > > --- > > block/ssh.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/block/ssh.c b/block/ssh.c > > index aebb18c..8d4dc2a 100644 > > --- a/block/ssh.c > > +++ b/block/ssh.c > > @@ -563,7 +563,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, > > /* Open the socket and connect. */ > > s->sock = inet_connect(s->hostport, errp); > > if (s->sock < 0) { > > - ret = -errno; > > + ret = -EINVAL; > > goto err; > > There are a reasonable number of other uses of inet_connect() in QEMU, > so can't we fix inet_connect() itself to set EINVAL in the error case > instead of just fixing one caller. None of the other callers try to use errno, which isn't even documented as part of the inet_connect() interface. So I think setting errno inside inet_connect() would be wrong. If we were to change anything, we might consider returning -EINVAL instead of -1, though I'm not sure how useful that change would be. We would still have to fix this call in the ssh block driver. Kevin ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno. 2015-07-22 13:07 ` Richard W.M. Jones 2015-07-22 13:10 ` Daniel P. Berrange @ 2015-07-22 13:17 ` Jeff Cody 2015-07-22 13:22 ` Richard W.M. Jones 1 sibling, 1 reply; 8+ messages in thread From: Jeff Cody @ 2015-07-22 13:17 UTC (permalink / raw) To: Richard W.M. Jones; +Cc: kwolf, qemu-devel, qemu-block On Wed, Jul 22, 2015 at 02:07:22PM +0100, Richard W.M. Jones wrote: > On some (but not all) systems: > > $ qemu-img create -f qcow2 overlay -b ssh://xen/ > Segmentation fault > > It turns out this happens when inet_connect returns -1 in the > following code, but errno == 0. > > s->sock = inet_connect(s->hostport, errp); > if (s->sock < 0) { > ret = -errno; > goto err; > } > > In the test case above, no host called "xen" exists, so getaddrinfo fails. > > On Fedora 22, getaddrinfo happens to set errno = ENOENT (although it > is *not* documented to do that), so it doesn't segfault. > > On RHEL 7, errno is not set by the failing getaddrinfo, so ret = > -errno = 0, so the caller doesn't know there was an error and > continues with a half-initialized BDRVSSHState struct, and everything > goes south from there, eventually resulting in a segfault. > > Fix this by setting ret to -EINVAL. The real error is saved in the > Error** errp struct, so it is printed correctly: > > $ ./qemu-img create -f qcow2 overlay -b ssh://xen/ > qemu-img: overlay: address resolution failed for xen:22: No address associated with hostname > > Signed-off-by: Richard W.M. Jones <rjones@redhat.com> > Reported-by: Jun Li > BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1147343 > --- > block/ssh.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/block/ssh.c b/block/ssh.c > index aebb18c..8d4dc2a 100644 > --- a/block/ssh.c > +++ b/block/ssh.c > @@ -563,7 +563,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, > /* Open the socket and connect. */ > s->sock = inet_connect(s->hostport, errp); > if (s->sock < 0) { > - ret = -errno; > + ret = -EINVAL; Both nbd and sheepdog handle it in a similar fashion (i.e. not relying on errno being set on inet_connect failure). However, both nbd and sheepdog use -EIO as the error return, and I think that makes more sense. What do you think? > goto err; > } > > -- > 2.4.3 > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno. 2015-07-22 13:17 ` Jeff Cody @ 2015-07-22 13:22 ` Richard W.M. Jones 2015-07-22 13:26 ` Jeff Cody 0 siblings, 1 reply; 8+ messages in thread From: Richard W.M. Jones @ 2015-07-22 13:22 UTC (permalink / raw) To: Jeff Cody; +Cc: kwolf, qemu-devel, qemu-block On Wed, Jul 22, 2015 at 09:17:49AM -0400, Jeff Cody wrote: > Both nbd and sheepdog handle it in a similar fashion (i.e. not relying > on errno being set on inet_connect failure). However, both nbd and > sheepdog use -EIO as the error return, and I think that makes more > sense. What do you think? If you prefer -- I don't mind as long as it doesn't segfault :-) Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno. 2015-07-22 13:22 ` Richard W.M. Jones @ 2015-07-22 13:26 ` Jeff Cody 0 siblings, 0 replies; 8+ messages in thread From: Jeff Cody @ 2015-07-22 13:26 UTC (permalink / raw) To: Richard W.M. Jones; +Cc: kwolf, qemu-devel, qemu-block On Wed, Jul 22, 2015 at 02:22:18PM +0100, Richard W.M. Jones wrote: > On Wed, Jul 22, 2015 at 09:17:49AM -0400, Jeff Cody wrote: > > Both nbd and sheepdog handle it in a similar fashion (i.e. not relying > > on errno being set on inet_connect failure). However, both nbd and > > sheepdog use -EIO as the error return, and I think that makes more > > sense. What do you think? > > If you prefer -- I don't mind as long as it doesn't segfault :-) > I think I would - mainly for consistency, but also because -EIO better describes all the various failures that may occur in inet_connect(). Thanks! Jeff ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-07-22 13:26 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-07-22 13:07 [Qemu-devel] [PATCH v2] block/ssh: Avoid segfault if inet_connect doesn't set errno Richard W.M. Jones 2015-07-22 13:07 ` Richard W.M. Jones 2015-07-22 13:10 ` Daniel P. Berrange 2015-07-22 13:17 ` Richard W.M. Jones 2015-07-22 13:24 ` Kevin Wolf 2015-07-22 13:17 ` Jeff Cody 2015-07-22 13:22 ` Richard W.M. Jones 2015-07-22 13:26 ` Jeff Cody
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).