summary refs log tree commit diff stats
path: root/chardev/char-parallel.c
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2024-02-03 09:02:25 +0100
committerMarkus Armbruster <armbru@redhat.com>2024-02-14 07:44:38 +0100
commita58c439a2d2c07ec05429d8774d75faeef4eac1e (patch)
tree38398350bc3e1c28027f093d4879d91927754d40 /chardev/char-parallel.c
parent5d1fc614413b10dd94858b07a1b2e26b1aa0296c (diff)
downloadfocaccia-qemu-a58c439a2d2c07ec05429d8774d75faeef4eac1e.tar.gz
focaccia-qemu-a58c439a2d2c07ec05429d8774d75faeef4eac1e.zip
chardev/parallel: Don't close stdin on inappropriate device
The __linux__ version of qemu_chr_open_pp_fd() tries to claim the
parport device with a PPCLAIM ioctl().  On success, it stores the file
descriptor in the chardev object, and returns success.  On failure, it
closes the file descriptor, and returns failure.

chardev_new() then passes the Chardev to object_unref().  This duly
calls char_parallel_finalize(), which closes the file descriptor
stored in the chardev object.  Since qemu_chr_open_pp_fd() didn't
store it, it's still zero, so this closes standard input.  Ooopsie.

To demonstate, add a unit test.  With the bug above unfixed, running
this test closes standard input.  char_hotswap_test() happens to run
next.  It opens a socket, duly gets file descriptor 0, and since it
tests for success with > 0 instead of >= 0, it fails.

The new unit test needs to be conditional exactly like the chardev it
tests.  Since the condition is rather complicated, steal the solution
from the serial chardev: define HAVE_CHARDEV_PARALLEL in qemu/osdep.h.
This also permits simplifying chardev/meson.build a bit.

The bug fix is easy enough: store the file descriptor, and leave
closing it to char_parallel_finalize().

The next commit will fix char_hotswap_test()'s test for success.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-ID: <20240203080228.2766159-2-armbru@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[Test fixed up for BSDs, indentation fixed up, commit message improved]
Diffstat (limited to 'chardev/char-parallel.c')
-rw-r--r--chardev/char-parallel.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/chardev/char-parallel.c b/chardev/char-parallel.c
index a5164f975a..78697d7522 100644
--- a/chardev/char-parallel.c
+++ b/chardev/char-parallel.c
@@ -164,13 +164,13 @@ static void qemu_chr_open_pp_fd(Chardev *chr,
 {
     ParallelChardev *drv = PARALLEL_CHARDEV(chr);
 
+    drv->fd = fd;
+
     if (ioctl(fd, PPCLAIM) < 0) {
         error_setg_errno(errp, errno, "not a parallel port");
-        close(fd);
         return;
     }
 
-    drv->fd = fd;
     drv->mode = IEEE1284_MODE_COMPAT;
 }
 #endif /* __linux__ */
@@ -238,6 +238,7 @@ static void qemu_chr_open_pp_fd(Chardev *chr,
 }
 #endif
 
+#ifdef HAVE_CHARDEV_PARALLEL
 static void qmp_chardev_open_parallel(Chardev *chr,
                                       ChardevBackend *backend,
                                       bool *be_opened,
@@ -306,3 +307,5 @@ static void register_types(void)
 }
 
 type_init(register_types);
+
+#endif  /* HAVE_CHARDEV_PARALLEL */