Bug 186490 - emulators/qemu-devel: Can't run scripts with shebang args.
Summary: emulators/qemu-devel: Can't run scripts with shebang args.
Status: Closed FIXED
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: Normal Affects Only Me
Assignee: Juergen Lock
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-02-05 17:30 UTC by Mathieu Arnold
Modified: 2014-02-06 17:50 UTC (History)
0 users

See Also:


Attachments
qemu-devel-shebangflags.patch (5.08 KB, patch)
2014-02-06 11:57 UTC, Juergen Lock
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mathieu Arnold freebsd_committer freebsd_triage 2014-02-05 17:30:02 UTC
When a script has a shebang with arguments, say "#!/usr/bin/perl -w" or
"#!/bin/sh -" qemu-xxx tries to exec the whole line, and fails, obviously.

e.g.:

root@pkg:~ # cat test.pl
#!/usr/bin/perl -w
print "ok\n";
root@pkg:~ # ./test.pl
Error loading /usr/bin/perl -w
root@pkg:~ # ln -s /usr/local/bin/perl5.16.3 /usr/bin/"perl -w"
root@pkg:~ # ./test.pl
ok

Generated with FreeBSD Port Tools 0.99_11 (mode: change, diff: SVN)
Comment 1 Edwin Groothuis freebsd_committer freebsd_triage 2014-02-05 17:30:10 UTC
Responsible Changed
From-To: freebsd-ports-bugs->nox

Over to maintainer (via the GNATS Auto Assign Tool)
Comment 2 Juergen Lock 2014-02-06 02:14:22 UTC
On Wed, Feb 05, 2014 at 05:30:10PM +0000, edwin@FreeBSD.org wrote:
> Synopsis: emulators/qemu-devel: Can't run scripts with shebang args.
> 
> Responsible-Changed-From-To: freebsd-ports-bugs->nox
> Responsible-Changed-By: edwin
> Responsible-Changed-When: Wed Feb 5 17:30:10 UTC 2014
> Responsible-Changed-Why: 
> Over to maintainer (via the GNATS Auto Assign Tool)
> 
> http://www.freebsd.org/cgi/query-pr.cgi?pr=186490

Hm you are right, looks like a bug in sson's patches.  Can you try
the patch below?  I'd like to commit it to the port if it works and
sson doesn't have a better version...

 Thanx! :)
	Juergen

--- a/bsd-user/freebsd/os-proc.c
--- b/bsd-user/freebsd/os-proc.c
@@ -83,7 +83,7 @@ out:
 }
 
 static int
-is_target_shell_script(int fd, char *interp, size_t size)
+is_target_shell_script(int fd, char *interp, size_t size, char **interp_args)
 {
     char buf[2], *p, *b;
     ssize_t n;
@@ -120,7 +120,21 @@ is_target_shell_script(int fd, char *int
             return 0;
         }
         if ((p = memchr(b, '\n', size)) != NULL) {
+            int hasargs = 0;
             *p = 0;
+
+            *interp_args = NULL;
+            p = interp;
+            while (*p) {
+                if ((*p == ' ') || (*p == '\t')) {
+                    hasargs = 1;
+                    *p = 0;
+                } else if (hasargs) {
+                    *interp_args = p;
+                    break;
+                }
+                ++p;
+            }
             return 1;
         }
         b += n;
@@ -136,7 +150,7 @@ is_target_shell_script(int fd, char *int
 abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
         abi_ulong guest_envp, int do_fexec)
 {
-    char **argp, **envp, **qargp, **qarg1, **qarg0;
+    char **argp, **envp, **qargp, **qarg1, **qarg0, **qargend;
     int argc, envc;
     abi_ulong gp;
     abi_ulong addr;
@@ -166,7 +180,7 @@ abi_long freebsd_exec_common(abi_ulong p
         envc++;
     }
 
-    qarg0 = argp =  alloca((argc + 4) * sizeof(void *));
+    qarg0 = argp =  alloca((argc + 5) * sizeof(void *));
     /* save the first agrument for the emulator */
     *argp++ = (char *)getprogname();
     qargp = argp;
@@ -188,7 +202,8 @@ abi_long freebsd_exec_common(abi_ulong p
         }
         total_size += strlen(*q) + 1;
     }
-    *q = NULL;
+    *q++ = NULL;
+    qargend = q;
 
     for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
         if (get_user_ual(addr, gp)) {
@@ -217,7 +232,7 @@ abi_long freebsd_exec_common(abi_ulong p
     }
 
     if (do_fexec) {
-        char execpath[PATH_MAX];
+        char execpath[PATH_MAX], *scriptargs;
 
         if (((int)path_or_fd > 0 &&
             is_target_elf_binary((int)path_or_fd)) == 1) {
@@ -238,7 +253,7 @@ abi_long freebsd_exec_common(abi_ulong p
                 goto execve_end;
             }
         } else if (is_target_shell_script((int)path_or_fd, execpath,
-                    sizeof(execpath)) != 0) {
+                    sizeof(execpath), &scriptargs) != 0) {
             char scriptpath[PATH_MAX];
 
             /* execve() as a target script using emulator. */
@@ -246,6 +261,10 @@ abi_long freebsd_exec_common(abi_ulong p
                         sizeof(scriptpath)) != NULL) {
                 *qargp = execpath;
                 *qarg1 = scriptpath;
+                if (scriptargs) {
+                    memmove(qarg1 + 1, qarg1, (qargend-qarg1) * sizeof(*qarg1));
+                    *qarg1 = scriptargs;
+                }
                 ret = get_errno(execve(qemu_proc_pathname, qarg0, envp));
             } else {
                 ret = -TARGET_EBADF;
@@ -256,7 +275,7 @@ abi_long freebsd_exec_common(abi_ulong p
         }
     } else {
         int fd;
-        char execpath[PATH_MAX];
+        char execpath[PATH_MAX], *scriptargs;
 
         p = lock_user_string(path_or_fd);
         if (p == NULL) {
@@ -275,11 +294,15 @@ abi_long freebsd_exec_common(abi_ulong p
             *qarg1 = (char *)p;
             ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
         } else if (is_target_shell_script(fd, execpath,
-                    sizeof(execpath)) != 0) {
+                    sizeof(execpath), &scriptargs) != 0) {
             close(fd);
             /* execve() as a target script using emulator. */
             *qargp = execpath;
             *qarg1 = (char *)p;
+            if (scriptargs) {
+                memmove(qarg1 + 1, qarg1, (qargend-qarg1) * sizeof(*qarg1));
+                *qarg1 = scriptargs;
+            }
             ret = get_errno(execve(qemu_proc_pathname, qarg0, envp));
         } else {
             close(fd);
Comment 3 Stacey Son freebsd_committer freebsd_triage 2014-02-06 03:43:29 UTC
Nice...  Thanks for fixing this.  I have been too busy working on pmap =
code for MIPS lately.  :)

I am going to try to refactor the patch set for qemu user-mode this =
weekend, maybe, so I can get all this code finally upstreamed to the =
qemu project.

-stacey.


On Feb 5, 2014, at 8:14 PM, Juergen Lock <nox@jelal.kn-bremen.de> wrote:

> On Wed, Feb 05, 2014 at 05:30:10PM +0000, edwin@FreeBSD.org wrote:
>> Synopsis: emulators/qemu-devel: Can't run scripts with shebang args.
>>=20
>> Responsible-Changed-From-To: freebsd-ports-bugs->nox
>> Responsible-Changed-By: edwin
>> Responsible-Changed-When: Wed Feb 5 17:30:10 UTC 2014
>> Responsible-Changed-Why:=20
>> Over to maintainer (via the GNATS Auto Assign Tool)
>>=20
>> http://www.freebsd.org/cgi/query-pr.cgi?pr=3D186490
>=20
> Hm you are right, looks like a bug in sson's patches.  Can you try
> the patch below?  I'd like to commit it to the port if it works and
> sson doesn't have a better version...
>=20
> Thanx! :)
> 	Juergen
>=20
> --- a/bsd-user/freebsd/os-proc.c
> --- b/bsd-user/freebsd/os-proc.c
> @@ -83,7 +83,7 @@ out:
> }
>=20
> static int
> -is_target_shell_script(int fd, char *interp, size_t size)
> +is_target_shell_script(int fd, char *interp, size_t size, char =
**interp_args)
> {
>     char buf[2], *p, *b;
>     ssize_t n;
> @@ -120,7 +120,21 @@ is_target_shell_script(int fd, char *int
>             return 0;
>         }
>         if ((p =3D memchr(b, '\n', size)) !=3D NULL) {
> +            int hasargs =3D 0;
>             *p =3D 0;
> +
> +            *interp_args =3D NULL;
> +            p =3D interp;
> +            while (*p) {
> +                if ((*p =3D=3D ' ') || (*p =3D=3D '\t')) {
> +                    hasargs =3D 1;
> +                    *p =3D 0;
> +                } else if (hasargs) {
> +                    *interp_args =3D p;
> +                    break;
> +                }
> +                ++p;
> +            }
>             return 1;
>         }
>         b +=3D n;
> @@ -136,7 +150,7 @@ is_target_shell_script(int fd, char *int
> abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong =
guest_argp,
>         abi_ulong guest_envp, int do_fexec)
> {
> -    char **argp, **envp, **qargp, **qarg1, **qarg0;
> +    char **argp, **envp, **qargp, **qarg1, **qarg0, **qargend;
>     int argc, envc;
>     abi_ulong gp;
>     abi_ulong addr;
> @@ -166,7 +180,7 @@ abi_long freebsd_exec_common(abi_ulong p
>         envc++;
>     }
>=20
> -    qarg0 =3D argp =3D  alloca((argc + 4) * sizeof(void *));
> +    qarg0 =3D argp =3D  alloca((argc + 5) * sizeof(void *));
>     /* save the first agrument for the emulator */
>     *argp++ =3D (char *)getprogname();
>     qargp =3D argp;
> @@ -188,7 +202,8 @@ abi_long freebsd_exec_common(abi_ulong p
>         }
>         total_size +=3D strlen(*q) + 1;
>     }
> -    *q =3D NULL;
> +    *q++ =3D NULL;
> +    qargend =3D q;
>=20
>     for (gp =3D guest_envp, q =3D envp; gp; gp +=3D sizeof(abi_ulong), =
q++) {
>         if (get_user_ual(addr, gp)) {
> @@ -217,7 +232,7 @@ abi_long freebsd_exec_common(abi_ulong p
>     }
>=20
>     if (do_fexec) {
> -        char execpath[PATH_MAX];
> +        char execpath[PATH_MAX], *scriptargs;
>=20
>         if (((int)path_or_fd > 0 &&
>             is_target_elf_binary((int)path_or_fd)) =3D=3D 1) {
> @@ -238,7 +253,7 @@ abi_long freebsd_exec_common(abi_ulong p
>                 goto execve_end;
>             }
>         } else if (is_target_shell_script((int)path_or_fd, execpath,
> -                    sizeof(execpath)) !=3D 0) {
> +                    sizeof(execpath), &scriptargs) !=3D 0) {
>             char scriptpath[PATH_MAX];
>=20
>             /* execve() as a target script using emulator. */
> @@ -246,6 +261,10 @@ abi_long freebsd_exec_common(abi_ulong p
>                         sizeof(scriptpath)) !=3D NULL) {
>                 *qargp =3D execpath;
>                 *qarg1 =3D scriptpath;
> +                if (scriptargs) {
> +                    memmove(qarg1 + 1, qarg1, (qargend-qarg1) * =
sizeof(*qarg1));
> +                    *qarg1 =3D scriptargs;
> +                }
>                 ret =3D get_errno(execve(qemu_proc_pathname, qarg0, =
envp));
>             } else {
>                 ret =3D -TARGET_EBADF;
> @@ -256,7 +275,7 @@ abi_long freebsd_exec_common(abi_ulong p
>         }
>     } else {
>         int fd;
> -        char execpath[PATH_MAX];
> +        char execpath[PATH_MAX], *scriptargs;
>=20
>         p =3D lock_user_string(path_or_fd);
>         if (p =3D=3D NULL) {
> @@ -275,11 +294,15 @@ abi_long freebsd_exec_common(abi_ulong p
>             *qarg1 =3D (char *)p;
>             ret =3D get_errno(execve(qemu_proc_pathname, qargp, =
envp));
>         } else if (is_target_shell_script(fd, execpath,
> -                    sizeof(execpath)) !=3D 0) {
> +                    sizeof(execpath), &scriptargs) !=3D 0) {
>             close(fd);
>             /* execve() as a target script using emulator. */
>             *qargp =3D execpath;
>             *qarg1 =3D (char *)p;
> +            if (scriptargs) {
> +                memmove(qarg1 + 1, qarg1, (qargend-qarg1) * =
sizeof(*qarg1));
> +                *qarg1 =3D scriptargs;
> +            }
>             ret =3D get_errno(execve(qemu_proc_pathname, qarg0, =
envp));
>         } else {
>             close(fd);
Comment 4 Juergen Lock 2014-02-06 11:57:56 UTC
Patch against the port for easier testing.
Comment 5 Mathieu Arnold freebsd_committer freebsd_triage 2014-02-06 12:38:22 UTC
+--On 6 f=C3=A9vrier 2014 12:57:56 +0100 Juergen Lock =
<nox@jelal.kn-bremen.de>
wrote:
| Patch against the port for easier testing.

That fixes the bug many thanks \o/

this time devel/autoconf will build, and I'll have *more* packages for both
mips64 and armv6 0:-)

--=20
Mathieu Arnold
Comment 6 dfilter service freebsd_committer freebsd_triage 2014-02-06 17:48:33 UTC
Author: nox
Date: Thu Feb  6 17:48:25 2014
New Revision: 343128
URL: http://svnweb.freebsd.org/changeset/ports/343128
QAT: https://qat.redports.org/buildarchive/r343128/

Log:
  - Fix bsd-user targets running scripts with shebang args. [1]
  - Bump PORTREVISION as per the new ruling. (fix only affecting
    non-default option BSD_USER)
  
  PR:		ports/186490 [1]
  Submitted by:	mat [1]

Added:
  head/emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c   (contents, props changed)
Modified:
  head/emulators/qemu-devel/Makefile

Modified: head/emulators/qemu-devel/Makefile
==============================================================================
--- head/emulators/qemu-devel/Makefile	Thu Feb  6 17:36:38 2014	(r343127)
+++ head/emulators/qemu-devel/Makefile	Thu Feb  6 17:48:25 2014	(r343128)
@@ -3,7 +3,7 @@
 
 PORTNAME=	qemu
 PORTVERSION=	1.7.0
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	emulators
 MASTER_SITES=	http://wiki.qemu.org/download/:release \
 		LOCAL/nox:snapshot
@@ -67,6 +67,7 @@ PATCHFILES= \
 	0017-bsd-user-add-support-for-miscellaneous-system-calls.patch \
 	0018-bsd-user-add-arm-mips-and-mips64-options-to-configur.patch
 PATCH_DIST_STRIP=	-p1
+EXTRA_PATCHES+=	${FILESDIR}/extra-patch-bsd-user-freebsd-os-proc.c
 .endif
 
 CONFIGURE_ARGS+=	--extra-ldflags=-L${LOCALBASE}/lib

Added: head/emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c	Thu Feb  6 17:48:25 2014	(r343128)
@@ -0,0 +1,116 @@
+--- a/bsd-user/freebsd/os-proc.c
+--- b/bsd-user/freebsd/os-proc.c
+@@ -83,7 +83,7 @@ out:
+ }
+ 
+ static int
+-is_target_shell_script(int fd, char *interp, size_t size)
++is_target_shell_script(int fd, char *interp, size_t size, char **interp_args)
+ {
+     char buf[2], *p, *b;
+     ssize_t n;
+@@ -120,7 +120,21 @@ is_target_shell_script(int fd, char *int
+             return 0;
+         }
+         if ((p = memchr(b, '\n', size)) != NULL) {
++            int hasargs = 0;
+             *p = 0;
++
++            *interp_args = NULL;
++            p = interp;
++            while (*p) {
++                if ((*p == ' ') || (*p == '\t')) {
++                    hasargs = 1;
++                    *p = 0;
++                } else if (hasargs) {
++                    *interp_args = p;
++                    break;
++                }
++                ++p;
++            }
+             return 1;
+         }
+         b += n;
+@@ -136,7 +150,7 @@ is_target_shell_script(int fd, char *int
+ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
+         abi_ulong guest_envp, int do_fexec)
+ {
+-    char **argp, **envp, **qargp, **qarg1, **qarg0;
++    char **argp, **envp, **qargp, **qarg1, **qarg0, **qargend;
+     int argc, envc;
+     abi_ulong gp;
+     abi_ulong addr;
+@@ -166,7 +180,7 @@ abi_long freebsd_exec_common(abi_ulong p
+         envc++;
+     }
+ 
+-    qarg0 = argp =  alloca((argc + 4) * sizeof(void *));
++    qarg0 = argp =  alloca((argc + 5) * sizeof(void *));
+     /* save the first agrument for the emulator */
+     *argp++ = (char *)getprogname();
+     qargp = argp;
+@@ -188,7 +202,8 @@ abi_long freebsd_exec_common(abi_ulong p
+         }
+         total_size += strlen(*q) + 1;
+     }
+-    *q = NULL;
++    *q++ = NULL;
++    qargend = q;
+ 
+     for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
+         if (get_user_ual(addr, gp)) {
+@@ -217,7 +232,7 @@ abi_long freebsd_exec_common(abi_ulong p
+     }
+ 
+     if (do_fexec) {
+-        char execpath[PATH_MAX];
++        char execpath[PATH_MAX], *scriptargs;
+ 
+         if (((int)path_or_fd > 0 &&
+             is_target_elf_binary((int)path_or_fd)) == 1) {
+@@ -238,7 +253,7 @@ abi_long freebsd_exec_common(abi_ulong p
+                 goto execve_end;
+             }
+         } else if (is_target_shell_script((int)path_or_fd, execpath,
+-                    sizeof(execpath)) != 0) {
++                    sizeof(execpath), &scriptargs) != 0) {
+             char scriptpath[PATH_MAX];
+ 
+             /* execve() as a target script using emulator. */
+@@ -246,6 +261,10 @@ abi_long freebsd_exec_common(abi_ulong p
+                         sizeof(scriptpath)) != NULL) {
+                 *qargp = execpath;
+                 *qarg1 = scriptpath;
++                if (scriptargs) {
++                    memmove(qarg1 + 1, qarg1, (qargend-qarg1) * sizeof(*qarg1));
++                    *qarg1 = scriptargs;
++                }
+                 ret = get_errno(execve(qemu_proc_pathname, qarg0, envp));
+             } else {
+                 ret = -TARGET_EBADF;
+@@ -256,7 +275,7 @@ abi_long freebsd_exec_common(abi_ulong p
+         }
+     } else {
+         int fd;
+-        char execpath[PATH_MAX];
++        char execpath[PATH_MAX], *scriptargs;
+ 
+         p = lock_user_string(path_or_fd);
+         if (p == NULL) {
+@@ -275,11 +294,15 @@ abi_long freebsd_exec_common(abi_ulong p
+             *qarg1 = (char *)p;
+             ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
+         } else if (is_target_shell_script(fd, execpath,
+-                    sizeof(execpath)) != 0) {
++                    sizeof(execpath), &scriptargs) != 0) {
+             close(fd);
+             /* execve() as a target script using emulator. */
+             *qargp = execpath;
+             *qarg1 = (char *)p;
++            if (scriptargs) {
++                memmove(qarg1 + 1, qarg1, (qargend-qarg1) * sizeof(*qarg1));
++                *qarg1 = scriptargs;
++            }
+             ret = get_errno(execve(qemu_proc_pathname, qarg0, envp));
+         } else {
+             close(fd);
_______________________________________________
svn-ports-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-ports-all
To unsubscribe, send any mail to "svn-ports-all-unsubscribe@freebsd.org"
Comment 7 Juergen Lock freebsd_committer freebsd_triage 2014-02-06 17:49:23 UTC
State Changed
From-To: open->closed

Fix committed.  Thanks!