Re: [PATCH 2/2] net/tap: fix error reporting when bridge helper forgets to send an FD

2021-05-12 Thread Daniel P . Berrangé
On Wed, May 05, 2021 at 02:32:04PM +0200, Philippe Mathieu-Daudé wrote:
> On 5/5/21 2:12 PM, Daniel P. Berrangé wrote:
> > The recv_fd() method returns -1 on error, 0 on end of file, or an FD
> > number on success.
> > 
> > Technically 0 is also a valid FD number, so the return value is
> > ambiguous.
> > 
> > The caller doesn't even consider the possibility of 0 meaning end
> > of file, so just blindly assume it is a valid FD.
> > 
> > IOW if the bridge helper exits with 0 status code and forgets to
> > send an FD, QEMU will accidentally try to use STDIN as a TAP FD.
> > 
> > Fortunately we get an error shortly thereafter
> > 
> >  $ qemu-system-x86_64 -netdev bridge,br=br99,helper=/bin/true,id=ns0
> >  qemu-system-x86_64: -netdev bridge,br=br99,helper=/bin/true,id=ns0:
> >Unable to query TUNGETIFF on FD 0: Inappropriate ioctl for device
> > 
> > It is better if we correctly diagnose this broken bridge helper
> > though. To do this we need to return the FD in an output parameter
> > to remove the ambiguity and then fix the caller to check for the
> > end of file condition. With this done we now get
> > 
> >   $ qemu-system-x86_64 -netdev bridge,br=br99,helper=/bin/true,id=ns0
> >   qemu-system-x86_64: -netdev bridge,br=br99,helper=/bin/true,id=ns0:
> > bridge helper did not send a file descriptor
> > 
> > Fixes: https://gitlab.com/qemu-project/qemu/-/issues/166
> > Signed-off-by: Daniel P. Berrangé 
> > ---
> >  net/tap.c | 32 ++--
> >  1 file changed, 22 insertions(+), 10 deletions(-)
> 
> > +/*
> > + * ret == 0 means EOF, and if status == 0 then helper
> > + * exited cleanly but forgot to send us an FD. Opps...
> 
> Opps or Oops?

Oops, it should be Oops :-)

> 
> Otherwise:
> Reviewed-by: Philippe Mathieu-Daudé 
> 

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 2/2] net/tap: fix error reporting when bridge helper forgets to send an FD

2021-05-12 Thread Daniel P . Berrangé
On Tue, May 11, 2021 at 01:53:39PM -0500, Connor Kuehl wrote:
> On 5/5/21 7:12 AM, Daniel P. Berrangé wrote:
> > [..]
> > The recv_fd() method returns -1 on error, 0 on end of file, or an FD
> >   $ qemu-system-x86_64 -netdev bridge,br=br99,helper=/bin/true,id=ns0
> >   qemu-system-x86_64: -netdev bridge,br=br99,helper=/bin/true,id=ns0:
> > bridge helper did not send a file descriptor
> > [..]
> >  }
> > +
> > +/*
> > + * ret == 0 means EOF, and if status == 0 then helper
> > + * exited cleanly but forgot to send us an FD. Opps...
> > + */
> > +if (ret == 0) {
> > +error_setg(errp, "bridge helper did not send a file
> > descriptor");
> 
> Is it possible to include the name of the helper that's at fault here?
> Could be helpful for debugging if the command line includes multiple
> netdev opts with a helper parameter (unless that's literally impossible).

Yes, easy change.

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 2/2] net/tap: fix error reporting when bridge helper forgets to send an FD

2021-05-11 Thread Connor Kuehl
On 5/5/21 7:12 AM, Daniel P. Berrangé wrote:
> [..]
> The recv_fd() method returns -1 on error, 0 on end of file, or an FD
>   $ qemu-system-x86_64 -netdev bridge,br=br99,helper=/bin/true,id=ns0
>   qemu-system-x86_64: -netdev bridge,br=br99,helper=/bin/true,id=ns0:
> bridge helper did not send a file descriptor
> [..]
>  }
> +
> +/*
> + * ret == 0 means EOF, and if status == 0 then helper
> + * exited cleanly but forgot to send us an FD. Opps...
> + */
> +if (ret == 0) {
> +error_setg(errp, "bridge helper did not send a file
> descriptor");

Is it possible to include the name of the helper that's at fault here?
Could be helpful for debugging if the command line includes multiple
netdev opts with a helper parameter (unless that's literally impossible).

Connor




Re: [PATCH 2/2] net/tap: fix error reporting when bridge helper forgets to send an FD

2021-05-05 Thread Philippe Mathieu-Daudé
On 5/5/21 2:12 PM, Daniel P. Berrangé wrote:
> The recv_fd() method returns -1 on error, 0 on end of file, or an FD
> number on success.
> 
> Technically 0 is also a valid FD number, so the return value is
> ambiguous.
> 
> The caller doesn't even consider the possibility of 0 meaning end
> of file, so just blindly assume it is a valid FD.
> 
> IOW if the bridge helper exits with 0 status code and forgets to
> send an FD, QEMU will accidentally try to use STDIN as a TAP FD.
> 
> Fortunately we get an error shortly thereafter
> 
>  $ qemu-system-x86_64 -netdev bridge,br=br99,helper=/bin/true,id=ns0
>  qemu-system-x86_64: -netdev bridge,br=br99,helper=/bin/true,id=ns0:
>Unable to query TUNGETIFF on FD 0: Inappropriate ioctl for device
> 
> It is better if we correctly diagnose this broken bridge helper
> though. To do this we need to return the FD in an output parameter
> to remove the ambiguity and then fix the caller to check for the
> end of file condition. With this done we now get
> 
>   $ qemu-system-x86_64 -netdev bridge,br=br99,helper=/bin/true,id=ns0
>   qemu-system-x86_64: -netdev bridge,br=br99,helper=/bin/true,id=ns0:
> bridge helper did not send a file descriptor
> 
> Fixes: https://gitlab.com/qemu-project/qemu/-/issues/166
> Signed-off-by: Daniel P. Berrangé 
> ---
>  net/tap.c | 32 ++--
>  1 file changed, 22 insertions(+), 10 deletions(-)

> +/*
> + * ret == 0 means EOF, and if status == 0 then helper
> + * exited cleanly but forgot to send us an FD. Opps...

Opps or Oops?

Otherwise:
Reviewed-by: Philippe Mathieu-Daudé 




[PATCH 2/2] net/tap: fix error reporting when bridge helper forgets to send an FD

2021-05-05 Thread Daniel P . Berrangé
The recv_fd() method returns -1 on error, 0 on end of file, or an FD
number on success.

Technically 0 is also a valid FD number, so the return value is
ambiguous.

The caller doesn't even consider the possibility of 0 meaning end
of file, so just blindly assume it is a valid FD.

IOW if the bridge helper exits with 0 status code and forgets to
send an FD, QEMU will accidentally try to use STDIN as a TAP FD.

Fortunately we get an error shortly thereafter

 $ qemu-system-x86_64 -netdev bridge,br=br99,helper=/bin/true,id=ns0
 qemu-system-x86_64: -netdev bridge,br=br99,helper=/bin/true,id=ns0:
   Unable to query TUNGETIFF on FD 0: Inappropriate ioctl for device

It is better if we correctly diagnose this broken bridge helper
though. To do this we need to return the FD in an output parameter
to remove the ambiguity and then fix the caller to check for the
end of file condition. With this done we now get

  $ qemu-system-x86_64 -netdev bridge,br=br99,helper=/bin/true,id=ns0
  qemu-system-x86_64: -netdev bridge,br=br99,helper=/bin/true,id=ns0:
bridge helper did not send a file descriptor

Fixes: https://gitlab.com/qemu-project/qemu/-/issues/166
Signed-off-by: Daniel P. Berrangé 
---
 net/tap.c | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/net/tap.c b/net/tap.c
index 276a9077fc..02046c9fd2 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -450,9 +450,11 @@ static void launch_script(const char *setup_script, const 
char *ifname,
 }
 }
 
-static int recv_fd(int c)
+/*
+ * Returns: -1 on error, 0 on end of file, 1 if an FD was received
+ */
+static int recv_fd(int c, int *fd)
 {
-int fd;
 uint8_t msgbuf[CMSG_SPACE(sizeof(fd))];
 struct msghdr msg = {
 .msg_control = msgbuf,
@@ -476,12 +478,12 @@ static int recv_fd(int c)
 msg.msg_iovlen = 1;
 
 len = recvmsg(c, , 0);
-if (len > 0) {
-memcpy(, CMSG_DATA(cmsg), sizeof(fd));
-return fd;
+if (len <= 0) {
+return len;
 }
 
-return len;
+memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
+return 1;
 }
 
 static int net_bridge_run_helper(const char *helper, const char *bridge,
@@ -564,14 +566,15 @@ static int net_bridge_run_helper(const char *helper, 
const char *bridge,
 _exit(1);
 
 } else {
-int fd;
+int ret;
+int fd = -1;
 int saved_errno;
 
 close(sv[1]);
 
 do {
-fd = recv_fd(sv[0]);
-} while (fd == -1 && errno == EINTR);
+ret = recv_fd(sv[0], );
+} while (ret == -1 && errno == EINTR);
 saved_errno = errno;
 
 close(sv[0]);
@@ -580,7 +583,7 @@ static int net_bridge_run_helper(const char *helper, const 
char *bridge,
 /* loop */
 }
 sigprocmask(SIG_SETMASK, , NULL);
-if (fd < 0) {
+if (ret < 0) {
 error_setg_errno(errp, saved_errno,
  "failed to recv file descriptor");
 return -1;
@@ -589,6 +592,15 @@ static int net_bridge_run_helper(const char *helper, const 
char *bridge,
 error_setg(errp, "bridge helper failed");
 return -1;
 }
+
+/*
+ * ret == 0 means EOF, and if status == 0 then helper
+ * exited cleanly but forgot to send us an FD. Opps...
+ */
+if (ret == 0) {
+error_setg(errp, "bridge helper did not send a file descriptor");
+return -1;
+}
 return fd;
 }
 }
-- 
2.31.1