diff options
author | Ron Yorston <rmy@pobox.com> | 2018-04-04 19:55:09 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-04-04 19:55:09 +0100 |
commit | 33a914da6bba61e27aee82675276bf1dccc52966 (patch) | |
tree | 2242719bf4bb7705504967d54d137d6fe19cc8f3 | |
parent | 016ca978455df7257a92236bbfb0c67de4a4bcd8 (diff) | |
download | busybox-w32-33a914da6bba61e27aee82675276bf1dccc52966.tar.gz busybox-w32-33a914da6bba61e27aee82675276bf1dccc52966.tar.bz2 busybox-w32-33a914da6bba61e27aee82675276bf1dccc52966.zip |
ps: obtain applet names from other BusyBox processes
Remove the code which passed applet names to child processes using
environment variables. This only allowed ps to display names for
its ancestors.
Instead attempt to read applet names from the memory of unrelated
processes.
The Microsoft documentation alone wasn't enough to figure out how
to do this. Additional hints from:
https://stackoverflow.com/questions/4298331/exe-or-dll-image-base-address
https://stackoverflow.com/questions/14467229/get-base-address-of-process
-rw-r--r-- | Makefile.flags | 2 | ||||
-rw-r--r-- | applets/applet_tables.c | 9 | ||||
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | libbb/appletlib.c | 19 | ||||
-rw-r--r-- | shell/ash.c | 7 | ||||
-rw-r--r-- | win32/process.c | 107 |
6 files changed, 104 insertions, 42 deletions
diff --git a/Makefile.flags b/Makefile.flags index 6bb6a8fb1..86ab0a0ec 100644 --- a/Makefile.flags +++ b/Makefile.flags | |||
@@ -126,7 +126,7 @@ endif | |||
126 | ifeq ($(CONFIG_PLATFORM_MINGW32),y) | 126 | ifeq ($(CONFIG_PLATFORM_MINGW32),y) |
127 | CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy -fno-ident | 127 | CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy -fno-ident |
128 | EXEEXT = .exe | 128 | EXEEXT = .exe |
129 | LDLIBS += userenv ws2_32 | 129 | LDLIBS += userenv psapi ws2_32 |
130 | endif | 130 | endif |
131 | 131 | ||
132 | # Android has no separate crypt library | 132 | # Android has no separate crypt library |
diff --git a/applets/applet_tables.c b/applets/applet_tables.c index 9a2aa5329..858429ac2 100644 --- a/applets/applet_tables.c +++ b/applets/applet_tables.c | |||
@@ -61,6 +61,7 @@ static int str_isalnum_(const char *s) | |||
61 | int main(int argc, char **argv) | 61 | int main(int argc, char **argv) |
62 | { | 62 | { |
63 | int i, j; | 63 | int i, j; |
64 | unsigned MAX_APPLET_NAME_LEN = 1; | ||
64 | 65 | ||
65 | // In find_applet_by_name(), before linear search, narrow it down | 66 | // In find_applet_by_name(), before linear search, narrow it down |
66 | // by looking at N "equidistant" names. With ~350 applets: | 67 | // by looking at N "equidistant" names. With ~350 applets: |
@@ -124,8 +125,8 @@ int main(int argc, char **argv) | |||
124 | printf("const char applet_names[] ALIGN1 = \"\"\n"); | 125 | printf("const char applet_names[] ALIGN1 = \"\"\n"); |
125 | for (i = 0; i < NUM_APPLETS; i++) { | 126 | for (i = 0; i < NUM_APPLETS; i++) { |
126 | printf("\"%s\" \"\\0\"\n", applets[i].name); | 127 | printf("\"%s\" \"\\0\"\n", applets[i].name); |
127 | // if (MAX_APPLET_NAME_LEN < strlen(applets[i].name)) | 128 | if (MAX_APPLET_NAME_LEN < strlen(applets[i].name)) |
128 | // MAX_APPLET_NAME_LEN = strlen(applets[i].name); | 129 | MAX_APPLET_NAME_LEN = strlen(applets[i].name); |
129 | } | 130 | } |
130 | printf(";\n\n"); | 131 | printf(";\n\n"); |
131 | 132 | ||
@@ -193,8 +194,8 @@ int main(int argc, char **argv) | |||
193 | #endif | 194 | #endif |
194 | //printf("#endif /* SKIP_definitions */\n"); | 195 | //printf("#endif /* SKIP_definitions */\n"); |
195 | 196 | ||
196 | // printf("\n"); | 197 | printf("\n"); |
197 | // printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN); | 198 | printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN); |
198 | 199 | ||
199 | if (argv[2]) { | 200 | if (argv[2]) { |
200 | FILE *fp; | 201 | FILE *fp; |
diff --git a/include/libbb.h b/include/libbb.h index da3459224..d948f88f3 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -2075,7 +2075,7 @@ extern const char bb_path_wtmp_file[] ALIGN1; | |||
2075 | #define bb_dev_null "/dev/null" | 2075 | #define bb_dev_null "/dev/null" |
2076 | #if ENABLE_PLATFORM_MINGW32 | 2076 | #if ENABLE_PLATFORM_MINGW32 |
2077 | #define bb_busybox_exec_path get_busybox_exec_path() | 2077 | #define bb_busybox_exec_path get_busybox_exec_path() |
2078 | extern char *bb_applet_pid(void); | 2078 | extern char bb_applet_name[]; |
2079 | #else | 2079 | #else |
2080 | extern const char bb_busybox_exec_path[] ALIGN1; | 2080 | extern const char bb_busybox_exec_path[] ALIGN1; |
2081 | #endif | 2081 | #endif |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 1488d4bd6..3e740363a 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -796,13 +796,6 @@ static void install_links(const char *busybox UNUSED_PARAM, | |||
796 | 796 | ||
797 | static void run_applet_and_exit(const char *name, char **argv) NORETURN; | 797 | static void run_applet_and_exit(const char *name, char **argv) NORETURN; |
798 | 798 | ||
799 | #if ENABLE_PLATFORM_MINGW32 | ||
800 | char *bb_applet_pid(void) | ||
801 | { | ||
802 | return auto_string(xasprintf("BB_APPLET_%d=%s", getpid(), applet_name)); | ||
803 | } | ||
804 | #endif | ||
805 | |||
806 | # if ENABLE_BUSYBOX | 799 | # if ENABLE_BUSYBOX |
807 | # if ENABLE_FEATURE_SH_STANDALONE && ENABLE_FEATURE_TAB_COMPLETION | 800 | # if ENABLE_FEATURE_SH_STANDALONE && ENABLE_FEATURE_TAB_COMPLETION |
808 | /* | 801 | /* |
@@ -979,6 +972,11 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) | |||
979 | # endif | 972 | # endif |
980 | 973 | ||
981 | # if NUM_APPLETS > 0 | 974 | # if NUM_APPLETS > 0 |
975 | |||
976 | # if ENABLE_PLATFORM_MINGW32 | ||
977 | char bb_applet_name[MAX_APPLET_NAME_LEN+1]; | ||
978 | # endif | ||
979 | |||
982 | void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) | 980 | void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) |
983 | { | 981 | { |
984 | int argc = string_array_len(argv); | 982 | int argc = string_array_len(argv); |
@@ -988,6 +986,9 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar | |||
988 | * "-/sbin/halt" -> "halt", for example. | 986 | * "-/sbin/halt" -> "halt", for example. |
989 | */ | 987 | */ |
990 | applet_name = name; | 988 | applet_name = name; |
989 | #if ENABLE_PLATFORM_MINGW32 | ||
990 | strcpy(bb_applet_name, applet_name); | ||
991 | #endif | ||
991 | 992 | ||
992 | /* Special case. POSIX says "test --help" | 993 | /* Special case. POSIX says "test --help" |
993 | * should be no different from e.g. "test --foo". | 994 | * should be no different from e.g. "test --foo". |
@@ -1014,10 +1015,6 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar | |||
1014 | if (ENABLE_FEATURE_SUID) | 1015 | if (ENABLE_FEATURE_SUID) |
1015 | check_suid(applet_no); | 1016 | check_suid(applet_no); |
1016 | 1017 | ||
1017 | #if ENABLE_PLATFORM_MINGW32 | ||
1018 | putenv(bb_applet_pid()); | ||
1019 | #endif | ||
1020 | |||
1021 | xfunc_error_retval = applet_main[applet_no](argc, argv); | 1018 | xfunc_error_retval = applet_main[applet_no](argc, argv); |
1022 | /* Note: applet_main() may also not return (die on a xfunc or such) */ | 1019 | /* Note: applet_main() may also not return (die on a xfunc or such) */ |
1023 | xfunc_die(); | 1020 | xfunc_die(); |
diff --git a/shell/ash.c b/shell/ash.c index 2a1ddac39..6d24fb55a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -14975,13 +14975,6 @@ reinitvar(void) | |||
14975 | varinit[i].var_func = varinit_data[i].var_func; | 14975 | varinit[i].var_func = varinit_data[i].var_func; |
14976 | } | 14976 | } |
14977 | vlineno.var_text = linenovar; | 14977 | vlineno.var_text = linenovar; |
14978 | |||
14979 | /* | ||
14980 | * BB_APPLET_<pid> was correct when 'sh --forkshell' was started | ||
14981 | * but has now been overwritten by the environment from the forkshell | ||
14982 | * data block. Reinstate it. | ||
14983 | */ | ||
14984 | setvareq(bb_applet_pid(), VEXPORT); | ||
14985 | } | 14978 | } |
14986 | 14979 | ||
14987 | /* FIXME: should consider running forkparent() and forkchild() */ | 14980 | /* FIXME: should consider running forkparent() and forkchild() */ |
diff --git a/win32/process.c b/win32/process.c index d6176ca23..3219fcad4 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "libbb.h" | 1 | #include "libbb.h" |
2 | #include <tlhelp32.h> | 2 | #include <tlhelp32.h> |
3 | #include <psapi.h> | ||
3 | 4 | ||
4 | int waitpid(pid_t pid, int *status, int options) | 5 | int waitpid(pid_t pid, int *status, int options) |
5 | { | 6 | { |
@@ -406,6 +407,79 @@ static inline long long filetime_to_ticks(const FILETIME *ft) | |||
406 | HNSEC_PER_TICK; | 407 | HNSEC_PER_TICK; |
407 | } | 408 | } |
408 | 409 | ||
410 | /* | ||
411 | * Attempt to get the applet name from another instance of busybox.exe. | ||
412 | * This will only work if the other process is using the same binary | ||
413 | * as the current process. If anything goes wrong just give up. | ||
414 | */ | ||
415 | static char *get_applet_name(DWORD pid, char *exe) | ||
416 | { | ||
417 | HANDLE proc; | ||
418 | HMODULE mlist[32]; | ||
419 | DWORD needed; | ||
420 | void *address; | ||
421 | char *my_base; | ||
422 | char buffer[128]; | ||
423 | char *name = NULL; | ||
424 | int i; | ||
425 | |||
426 | if (!(proc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, | ||
427 | FALSE, pid))) { | ||
428 | return NULL; | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * Search for the module that matches the name of the executable. | ||
433 | * The values returned in mlist are actually the base address of | ||
434 | * the module in the other process (as noted in the documentation | ||
435 | * for the MODULEINFO structure). | ||
436 | */ | ||
437 | if (!EnumProcessModules(proc, mlist, sizeof(mlist), &needed)) { | ||
438 | goto finish; | ||
439 | } | ||
440 | |||
441 | for (i=0; i<needed/sizeof(HMODULE); ++i) { | ||
442 | char modname[MAX_PATH]; | ||
443 | if (GetModuleFileNameEx(proc, mlist[i], modname, sizeof(modname))) { | ||
444 | if (strcasecmp(bb_basename(modname), exe) == 0) { | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | } | ||
449 | |||
450 | if (i == needed/sizeof(HMODULE)) { | ||
451 | goto finish; | ||
452 | } | ||
453 | |||
454 | /* attempt to read the BusyBox version string */ | ||
455 | my_base = (char *)GetModuleHandle(NULL); | ||
456 | address = (char *)mlist[i] + ((char *)bb_banner - my_base); | ||
457 | if (!ReadProcessMemory(proc, address, buffer, 128, NULL)) { | ||
458 | goto finish; | ||
459 | } | ||
460 | |||
461 | if (memcmp(buffer, bb_banner, strlen(bb_banner)) != 0) { | ||
462 | /* version mismatch (or not BusyBox at all) */ | ||
463 | goto finish; | ||
464 | } | ||
465 | |||
466 | /* attempt to read the applet name */ | ||
467 | address = (char *)mlist[i] + ((char *)bb_applet_name - my_base); | ||
468 | if (!ReadProcessMemory(proc, address, buffer, 128, NULL)) { | ||
469 | goto finish; | ||
470 | } | ||
471 | |||
472 | /* check that the string really is an applet name */ | ||
473 | buffer[31] = '\0'; | ||
474 | if (find_applet_by_name(buffer) >= 0) { | ||
475 | name = auto_string(xstrdup(buffer)); | ||
476 | } | ||
477 | |||
478 | finish: | ||
479 | CloseHandle(proc); | ||
480 | return name; | ||
481 | } | ||
482 | |||
409 | /* POSIX version in libbb/procps.c */ | 483 | /* POSIX version in libbb/procps.c */ |
410 | procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags | 484 | procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags |
411 | #if !ENABLE_FEATURE_PS_TIME && !ENABLE_FEATURE_PS_LONG | 485 | #if !ENABLE_FEATURE_PS_TIME && !ENABLE_FEATURE_PS_LONG |
@@ -414,7 +488,8 @@ UNUSED_PARAM | |||
414 | ) | 488 | ) |
415 | { | 489 | { |
416 | PROCESSENTRY32 pe; | 490 | PROCESSENTRY32 pe; |
417 | const char *comm; | 491 | const char *comm, *name; |
492 | BOOL ret; | ||
418 | 493 | ||
419 | pe.dwSize = sizeof(pe); | 494 | pe.dwSize = sizeof(pe); |
420 | if (!sp) { | 495 | if (!sp) { |
@@ -424,18 +499,16 @@ UNUSED_PARAM | |||
424 | free(sp); | 499 | free(sp); |
425 | return NULL; | 500 | return NULL; |
426 | } | 501 | } |
427 | if (!Process32First(sp->snapshot, &pe)) { | 502 | ret = Process32First(sp->snapshot, &pe); |
428 | CloseHandle(sp->snapshot); | ||
429 | free(sp); | ||
430 | return NULL; | ||
431 | } | ||
432 | } | 503 | } |
433 | else { | 504 | else { |
434 | if (!Process32Next(sp->snapshot, &pe)) { | 505 | ret = Process32Next(sp->snapshot, &pe); |
435 | CloseHandle(sp->snapshot); | 506 | } |
436 | free(sp); | 507 | |
437 | return NULL; | 508 | if (!ret) { |
438 | } | 509 | CloseHandle(sp->snapshot); |
510 | free(sp); | ||
511 | return NULL; | ||
439 | } | 512 | } |
440 | 513 | ||
441 | memset(&sp->vsz, 0, sizeof(*sp) - offsetof(procps_status_t, vsz)); | 514 | memset(&sp->vsz, 0, sizeof(*sp) - offsetof(procps_status_t, vsz)); |
@@ -478,19 +551,17 @@ UNUSED_PARAM | |||
478 | sp->pid = pe.th32ProcessID; | 551 | sp->pid = pe.th32ProcessID; |
479 | sp->ppid = pe.th32ParentProcessID; | 552 | sp->ppid = pe.th32ParentProcessID; |
480 | 553 | ||
481 | comm = pe.szExeFile; | ||
482 | if (sp->pid == GetProcessId(GetCurrentProcess())) { | 554 | if (sp->pid == GetProcessId(GetCurrentProcess())) { |
483 | comm = applet_name; | 555 | comm = applet_name; |
484 | } | 556 | } |
557 | else if ((name=get_applet_name(pe.th32ProcessID, pe.szExeFile)) != NULL) { | ||
558 | comm = name; | ||
559 | } | ||
485 | else { | 560 | else { |
486 | char name[32], *value; | 561 | comm = pe.szExeFile; |
487 | |||
488 | sprintf(name, "BB_APPLET_%d", sp->pid); | ||
489 | if ((value=getenv(name)) != NULL) { | ||
490 | comm = value; | ||
491 | } | ||
492 | } | 562 | } |
493 | safe_strncpy(sp->comm, comm, COMM_LEN); | 563 | safe_strncpy(sp->comm, comm, COMM_LEN); |
564 | |||
494 | return sp; | 565 | return sp; |
495 | } | 566 | } |
496 | 567 | ||