linux-user: added fake open() for /proc/self/cmdline
PATCH 1/1 linux-user: added fake open() for /proc/self/cmdline
A piece of software I use depends on /proc/self/cmdline to determine the command with which it was invoked. When using linux-user, that file would read:
$ hd /proc/self/cmdline 00000000 2f 75 73 72 2f 62 69 6e 2f 71 65 6d 75 2d 61 72 |/usr/bin/qemu-ar| 00000010 6d 2d 73 74 61 74 69 63 00 2f 75 73 72 2f 62 69 |m-static./usr/bi| 00000020 6e 2f 68 64 00 2f 70 72 6f 63 2f 73 65 6c 66 2f |n/hd./proc/self/| 00000030 63 6d 64 6c 69 6e 65 00 |cmdline.|
With this patch, the first word is omitted from the process's own cmdline entry, removing the emulator path from the file:
$ hd /proc/self/cmdline 00000000 2f 75 73 72 2f 62 69 6e 2f 68 64 00 2f 70 72 6f |/usr/bin/hd./pro| 00000010 63 2f 73 65 6c 66 2f 63 6d 64 6c 69 6e 65 00 |c/self/cmdline.| 0000001f
Kind regards,
Wim
PATCH 1/1 linux-user: added fake open() for /proc/self/cmdline
From: Wim Vander Schelden <[email protected]>
--- linux-user/syscall.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
linux-user/syscall.c +49 -0
@@ -4947,6 +4947,54 @@ int host_to_target_waitstatus(int status)return status; } +static int open_self_cmdline (void *cpu_env,int fd) +{ +int fd_orig =-1 ; +bool word_skipped = false; + + fd_orig =open ("/proc/self/cmdline" ,O_RDONLY ); +if (fd_orig <0 ) { +return fd_orig; + } + +while (true) { +ssize_t nb_read; +char buf[128 ]; +char * cp_buf = buf; + + nb_read =read (fd_orig, buf,sizeof (buf)); +if (nb_read <0 ) + { + fd_orig =close (fd_orig); +return -1 ; + }else if (nb_read ==0 ) { +break ; + } + +if (nb_read ==0 ) +break ; + +if (! word_skipped) { +// Skip the first string, which is the path to qemu-*-static instead of the actual command. +size_t command_length =strnlen (buf,sizeof (buf)); +if (command_length !=sizeof (buf)) { +// Null byte found, skip one string + nb_read -= command_length +1 ; + cp_buf += command_length +1 ; + word_skipped = true; + } + } + +if (word_skipped) { +if (write (fd, cp_buf, nb_read) != nb_read) { +return -1 ; + } + } + } + +return close (fd_orig); +} +static int open_self_maps (void *cpu_env,int fd) {#if defined(TARGET_ARM ) || defined(TARGET_M68K ) || defined(TARGET_UNICORE32 )
@@ -5148,6 +5196,7 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) { "maps", open_self_maps, is_proc_myself }, { "stat", open_self_stat, is_proc_myself }, { "auxv", open_self_auxv, is_proc_myself }, + { "cmdline", open_self_cmdline, is_proc_myself}, #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) { "/proc/net/route", open_net_route, is_proc }, #endif
Signature · 1 line
1.9.1
Quoted 3 lines · On 06/16/2014 09:16 PM, [email protected] wrote:
From: Wim Vander Schelden <[email protected]>
---
Missing a Signed-off-by declaration; without that legal hurdle, we are unwilling to take the patch.
For more details: http://wiki.qemu.org/Contribute/SubmitAPatch
Quoted 2 lines
linux-user/syscall.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
Run your patch through scripts/checkpatch.pl to flag many of the complaints below.
Quoted 6 lines
linux-user/syscall.c +0
-0
linux-user/syscall.c int host_to_target_waitstatus(int status) · line 4955
Quoted 9 lines
linux-user/syscall.c +6
-0@@ -4947,6 +4947,54 @@ int host_to_target_waitstatus(int status)return status; } +static int open_self_cmdline (void *cpu_env,int fd) +{ +int fd_orig =-1 ; +bool word_skipped = false; + + fd_orig =open ("/proc/self/cmdline" ,O_RDONLY );
Why a double space?
linux-user/syscall.c int host_to_target_waitstatus(int status) · line 4956
Quoted 1 line
linux-user/syscall.c +1
-0+if (fd_orig <0 ) {
Wrong style - we use space after 'if'
linux-user/syscall.c int host_to_target_waitstatus(int status) · line 4960
Quoted 4 lines
linux-user/syscall.c +4
-0+return fd_orig; + } + +while (true) {
and space after 'while'
linux-user/syscall.c int host_to_target_waitstatus(int status) · line 4978
Quoted 2 lines
linux-user/syscall.c +2
-0+if (! word_skipped) { +// Skip the first string, which is the path to qemu-*-static instead of the actual command.
/* */ comments instead of //; fit 80 columns.
linux-user/syscall.c int host_to_target_waitstatus(int status) · line 4984
Quoted 6 lines
linux-user/syscall.c +6
-0+size_t command_length =strnlen (buf,sizeof (buf)); +if (command_length !=sizeof (buf)) { +// Null byte found, skip one string + nb_read -= command_length +1 ; + cp_buf += command_length +1 ; + word_skipped = true;
This feels a bit complicated. Why not just use memchr() to locate the first NUL byte, rather than messing with strnlen()?
linux-user/syscall.c static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) · line 5199
Quoted 5 lines
linux-user/syscall.c +1
-0@@ -5148,6 +5196,7 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) { "maps", open_self_maps, is_proc_myself }, { "stat", open_self_stat, is_proc_myself }, { "auxv", open_self_auxv, is_proc_myself }, + { "cmdline", open_self_cmdline, is_proc_myself},
Match the style of the lines nearby (space before '}')
Signature · 2 lines
Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Hi Eric,
Thanks for your feedback.
I've addressed the issues you mentioned and verified the patch with checkpatch.pl.
The updated patch follows.
Kind regards,
Wim
PATCH 1/1 linux-user: added fake open() for /proc/self/cmdline
From: Wim Vander Schelden <[email protected]>
--- linux-user/syscall.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
linux-user/syscall.c +46 -0
@@ -4947,6 +4947,51 @@ int host_to_target_waitstatus(int status)return status; } +static int open_self_cmdline (void *cpu_env,int fd) +{ +int fd_orig =-1 ; +bool word_skipped = false; + + fd_orig =open ("/proc/self/cmdline" ,O_RDONLY ); +if (fd_orig <0 ) { +return fd_orig; + } + +while (true) { +ssize_t nb_read; +char buf[128 ]; +char *cp_buf = buf; + + nb_read =read (fd_orig, buf,sizeof (buf)); +if (nb_read <0 ) { + fd_orig =close (fd_orig); +return -1 ; + }else if (nb_read ==0 ) { +break ; + } + +if (!word_skipped) { +/* Skip the first string, which is the path to qemu-*-static +instead of the actual command. */ + cp_buf =memchr (buf,0 ,sizeof (buf)); +if (cp_buf) { +/* Null byte found, skip one string */ + cp_buf++; + nb_read -= cp_buf - buf; + word_skipped = true; + } + } + +if (word_skipped) { +if (write (fd, cp_buf, nb_read) != nb_read) { +return -1 ; + } + } + } + +return close (fd_orig); +} +static int open_self_maps (void *cpu_env,int fd) {#if defined(TARGET_ARM ) || defined(TARGET_M68K ) || defined(TARGET_UNICORE32 )
@@ -5148,6 +5193,7 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) { "maps", open_self_maps, is_proc_myself }, { "stat", open_self_stat, is_proc_myself }, { "auxv", open_self_auxv, is_proc_myself }, + { "cmdline", open_self_cmdline, is_proc_myself }, #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) { "/proc/net/route", open_net_route, is_proc }, #endif
Signature · 1 line
1.9.1
Quoted 1 line · On Wed, Jun 18, 2014 at 11:02:39AM +0200, [email protected] wrote:
From: Wim Vander Schelden <[email protected]>
Seems to work,
applied to linux-user updates
Quoted 72 lines
Signed-off-by Wim Vander Schelden <[email protected]>--- linux-user/syscall.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)linux-user/syscall.c +46
-0@@ -4947,6 +4947,51 @@ int host_to_target_waitstatus(int status)return status; } +static int open_self_cmdline (void *cpu_env,int fd) +{ +int fd_orig =-1 ; +bool word_skipped = false; + + fd_orig =open ("/proc/self/cmdline" ,O_RDONLY ); +if (fd_orig <0 ) { +return fd_orig; + } + +while (true) { +ssize_t nb_read; +char buf[128 ]; +char *cp_buf = buf; + + nb_read =read (fd_orig, buf,sizeof (buf)); +if (nb_read <0 ) { + fd_orig =close (fd_orig); +return -1 ; + }else if (nb_read ==0 ) { +break ; + } + +if (!word_skipped) { +/* Skip the first string, which is the path to qemu-*-static +instead of the actual command. */ + cp_buf =memchr (buf,0 ,sizeof (buf)); +if (cp_buf) { +/* Null byte found, skip one string */ + cp_buf++; + nb_read -= cp_buf - buf; + word_skipped = true; + } + } + +if (word_skipped) { +if (write (fd, cp_buf, nb_read) != nb_read) { +return -1 ; + } + } + } + +return close (fd_orig); +} +static int open_self_maps (void *cpu_env,int fd) {#if defined(TARGET_ARM ) || defined(TARGET_M68K ) || defined(TARGET_UNICORE32 )@@ -5148,6 +5193,7 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) { "maps", open_self_maps, is_proc_myself }, { "stat", open_self_stat, is_proc_myself }, { "auxv", open_self_auxv, is_proc_myself }, + { "cmdline", open_self_cmdline, is_proc_myself }, #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) { "/proc/net/route", open_net_route, is_proc }, #endifSignature · 1 line
1.9.1