Message ID | 20221021181451.120630-1-JPEWhacker@gmail.com |
---|---|
State | Accepted, archived |
Commit | f698e98f2f09952b34488b8cf9e73e82bd7aea07 |
Headers | show |
Series | qemu-helper-native: Re-write bridge helper as C program | expand |
Steve, Please backport this to Langdale On Fri, Oct 21, 2022 at 1:14 PM Joshua Watt <jpewhacker@gmail.com> wrote: > > The bridge helper program is invoked directly from QEMU when it needs to > attach to a network bridge. As such, it is subject to the environment of > QEMU itself. Specifically, if bridging is enabled with direct rendering > acceleration, QEMU is run with an LD_PRELOAD that attempts to preload > several uninative libraries; however /bin/sh doesn't use the uninative > loader which means it can fail to start with an error like: > > /bin/sh: symbol lookup error: sysroots-uninative/x86_64-linux/lib/librt.so.1: undefined symbol: __libc_unwind_link_get, version GLIBC_PRIVATE > > Converting the helper program to a C program resolves this problem > because it will now use the uninative loader so the preload doesn't > cause errors. > > Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> > --- > .../qemu/qemu-helper-native_1.0.bb | 6 +-- > .../qemu/qemu-helper/qemu-oe-bridge-helper | 25 ----------- > .../qemu/qemu-helper/qemu-oe-bridge-helper.c | 41 +++++++++++++++++++ > 3 files changed, 44 insertions(+), 28 deletions(-) > delete mode 100755 meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper > create mode 100644 meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper.c > > diff --git a/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb b/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb > index aa9e499c77..e297586bbb 100644 > --- a/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb > +++ b/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb > @@ -7,7 +7,7 @@ LIC_FILES_CHKSUM = "file://${WORKDIR}/tunctl.c;endline=4;md5=ff3a09996bc5fff6bc5 > > SRC_URI = "\ > file://tunctl.c \ > - file://qemu-oe-bridge-helper \ > + file://qemu-oe-bridge-helper.c \ > " > > S = "${WORKDIR}" > @@ -16,13 +16,13 @@ inherit native > > do_compile() { > ${CC} ${CFLAGS} ${LDFLAGS} -Wall tunctl.c -o tunctl > + ${CC} ${CFLAGS} ${LDFLAGS} -Wall qemu-oe-bridge-helper.c -o qemu-oe-bridge-helper > } > > do_install() { > install -d ${D}${bindir} > install tunctl ${D}${bindir}/ > - > - install -m 755 ${WORKDIR}/qemu-oe-bridge-helper ${D}${bindir}/ > + install qemu-oe-bridge-helper ${D}${bindir}/ > } > > DEPENDS += "qemu-system-native" > diff --git a/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper b/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper > deleted file mode 100755 > index f057d4eef0..0000000000 > --- a/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper > +++ /dev/null > @@ -1,25 +0,0 @@ > -#! /bin/sh > -# Copyright 2020 Garmin Ltd. or its subsidiaries > -# > -# SPDX-License-Identifier: GPL-2.0 > -# > -# Attempts to find and exec the host qemu-bridge-helper program > - > -# If the QEMU_BRIDGE_HELPER variable is set by the user, exec it. > -if [ -n "$QEMU_BRIDGE_HELPER" ]; then > - exec "$QEMU_BRIDGE_HELPER" "$@" > -fi > - > -# Search common paths for the helper program > -BN="qemu-bridge-helper" > -PATHS="/usr/libexec/ /usr/lib/qemu/" > - > -for p in $PATHS; do > - if [ -e "$p/$BN" ]; then > - exec "$p/$BN" "$@" > - fi > -done > - > -echo "$BN not found!" > /dev/stderr > -exit 1 > - > diff --git a/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper.c b/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper.c > new file mode 100644 > index 0000000000..cadf2a012a > --- /dev/null > +++ b/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper.c > @@ -0,0 +1,41 @@ > +/* > + * Copyright 2022 Garmin Ltd. or its subsidiaries > + * > + * SPDX-License-Identifier: GPL-2.0 > + * > + * Attempts to find and exec the host qemu-bridge-helper program > + */ > + > +#include <stdio.h> > +#include <unistd.h> > + > +void try_program(char const* path, char** args) { > + if (access(path, X_OK) == 0) { > + execv(path, args); > + } > +} > + > +int main(int argc, char** argv) { > + char* var; > + > + /* Copy arguments so that they are a NULL terminated list, skipping argv[0] > + * since it is this program name */ > + char** args = malloc(argc * sizeof(char*)); > + for (int i = 0; i < argc - 1; i++) { > + args[i] = argv[i + 1]; > + } > + args[argc - 1] = NULL; > + > + var = getenv("QEMU_BRIDGE_HELPER"); > + if (var && var[0] != '\0') { > + execvp(var, args); > + return 1; > + } > + > + try_program("/usr/libexec/qemu-bridge-helper", args); > + try_program("/usr/lib/qemu/qemu-bridge-helper", args); > + > + fprintf(stderr, "No bridge helper found\n"); > + return 1; > +} > + > -- > 2.33.0 >
diff --git a/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb b/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb index aa9e499c77..e297586bbb 100644 --- a/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb +++ b/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb @@ -7,7 +7,7 @@ LIC_FILES_CHKSUM = "file://${WORKDIR}/tunctl.c;endline=4;md5=ff3a09996bc5fff6bc5 SRC_URI = "\ file://tunctl.c \ - file://qemu-oe-bridge-helper \ + file://qemu-oe-bridge-helper.c \ " S = "${WORKDIR}" @@ -16,13 +16,13 @@ inherit native do_compile() { ${CC} ${CFLAGS} ${LDFLAGS} -Wall tunctl.c -o tunctl + ${CC} ${CFLAGS} ${LDFLAGS} -Wall qemu-oe-bridge-helper.c -o qemu-oe-bridge-helper } do_install() { install -d ${D}${bindir} install tunctl ${D}${bindir}/ - - install -m 755 ${WORKDIR}/qemu-oe-bridge-helper ${D}${bindir}/ + install qemu-oe-bridge-helper ${D}${bindir}/ } DEPENDS += "qemu-system-native" diff --git a/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper b/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper deleted file mode 100755 index f057d4eef0..0000000000 --- a/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper +++ /dev/null @@ -1,25 +0,0 @@ -#! /bin/sh -# Copyright 2020 Garmin Ltd. or its subsidiaries -# -# SPDX-License-Identifier: GPL-2.0 -# -# Attempts to find and exec the host qemu-bridge-helper program - -# If the QEMU_BRIDGE_HELPER variable is set by the user, exec it. -if [ -n "$QEMU_BRIDGE_HELPER" ]; then - exec "$QEMU_BRIDGE_HELPER" "$@" -fi - -# Search common paths for the helper program -BN="qemu-bridge-helper" -PATHS="/usr/libexec/ /usr/lib/qemu/" - -for p in $PATHS; do - if [ -e "$p/$BN" ]; then - exec "$p/$BN" "$@" - fi -done - -echo "$BN not found!" > /dev/stderr -exit 1 - diff --git a/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper.c b/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper.c new file mode 100644 index 0000000000..cadf2a012a --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper.c @@ -0,0 +1,41 @@ +/* + * Copyright 2022 Garmin Ltd. or its subsidiaries + * + * SPDX-License-Identifier: GPL-2.0 + * + * Attempts to find and exec the host qemu-bridge-helper program + */ + +#include <stdio.h> +#include <unistd.h> + +void try_program(char const* path, char** args) { + if (access(path, X_OK) == 0) { + execv(path, args); + } +} + +int main(int argc, char** argv) { + char* var; + + /* Copy arguments so that they are a NULL terminated list, skipping argv[0] + * since it is this program name */ + char** args = malloc(argc * sizeof(char*)); + for (int i = 0; i < argc - 1; i++) { + args[i] = argv[i + 1]; + } + args[argc - 1] = NULL; + + var = getenv("QEMU_BRIDGE_HELPER"); + if (var && var[0] != '\0') { + execvp(var, args); + return 1; + } + + try_program("/usr/libexec/qemu-bridge-helper", args); + try_program("/usr/lib/qemu/qemu-bridge-helper", args); + + fprintf(stderr, "No bridge helper found\n"); + return 1; +} +
The bridge helper program is invoked directly from QEMU when it needs to attach to a network bridge. As such, it is subject to the environment of QEMU itself. Specifically, if bridging is enabled with direct rendering acceleration, QEMU is run with an LD_PRELOAD that attempts to preload several uninative libraries; however /bin/sh doesn't use the uninative loader which means it can fail to start with an error like: /bin/sh: symbol lookup error: sysroots-uninative/x86_64-linux/lib/librt.so.1: undefined symbol: __libc_unwind_link_get, version GLIBC_PRIVATE Converting the helper program to a C program resolves this problem because it will now use the uninative loader so the preload doesn't cause errors. Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> --- .../qemu/qemu-helper-native_1.0.bb | 6 +-- .../qemu/qemu-helper/qemu-oe-bridge-helper | 25 ----------- .../qemu/qemu-helper/qemu-oe-bridge-helper.c | 41 +++++++++++++++++++ 3 files changed, 44 insertions(+), 28 deletions(-) delete mode 100755 meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper create mode 100644 meta/recipes-devtools/qemu/qemu-helper/qemu-oe-bridge-helper.c