diff options
author | Ron Yorston <rmy@pobox.com> | 2015-10-13 14:45:51 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2015-10-13 14:45:51 +0100 |
commit | 8e509f11bceeec419abc718300bef7422d1fee4c (patch) | |
tree | fdfbc752ad94102e3613a5d7254f14a93eaf7f56 /libbb/vfork_daemon_rexec.c | |
parent | 420f5edfe7676fe6e7cddbbf15c04649d096e422 (diff) | |
parent | 4d0c1ea4784c9844f8468d97ca5c26d3c70f9921 (diff) | |
download | busybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.tar.gz busybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.tar.bz2 busybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb/vfork_daemon_rexec.c')
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index de4d14fce..2d3204507 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -71,28 +71,44 @@ pid_t FAST_FUNC xspawn(char **argv) | |||
71 | } | 71 | } |
72 | 72 | ||
73 | #if ENABLE_FEATURE_PREFER_APPLETS | 73 | #if ENABLE_FEATURE_PREFER_APPLETS |
74 | static jmp_buf die_jmp; | ||
75 | static void jump(void) | ||
76 | { | ||
77 | /* Special case. We arrive here if NOFORK applet | ||
78 | * calls xfunc, which then decides to die. | ||
79 | * We don't die, but jump instead back to caller. | ||
80 | * NOFORK applets still cannot carelessly call xfuncs: | ||
81 | * p = xmalloc(10); | ||
82 | * q = xmalloc(10); // BUG! if this dies, we leak p! | ||
83 | */ | ||
84 | /* | 0x100 allows to pass zero exitcode (longjmp can't pass 0). | ||
85 | * This works because exitcodes are bytes, | ||
86 | * run_nofork_applet() ensures that by "& 0xff" */ | ||
87 | longjmp(die_jmp, xfunc_error_retval | 0x100); | ||
88 | } | ||
89 | |||
74 | struct nofork_save_area { | 90 | struct nofork_save_area { |
75 | jmp_buf die_jmp; | 91 | jmp_buf die_jmp; |
92 | void (*die_func)(void); | ||
76 | const char *applet_name; | 93 | const char *applet_name; |
77 | uint32_t option_mask32; | 94 | uint32_t option_mask32; |
78 | int die_sleep; | ||
79 | uint8_t xfunc_error_retval; | 95 | uint8_t xfunc_error_retval; |
80 | }; | 96 | }; |
81 | static void save_nofork_data(struct nofork_save_area *save) | 97 | static void save_nofork_data(struct nofork_save_area *save) |
82 | { | 98 | { |
83 | memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); | 99 | memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); |
100 | save->die_func = die_func; | ||
84 | save->applet_name = applet_name; | 101 | save->applet_name = applet_name; |
85 | save->xfunc_error_retval = xfunc_error_retval; | ||
86 | save->option_mask32 = option_mask32; | 102 | save->option_mask32 = option_mask32; |
87 | save->die_sleep = die_sleep; | 103 | save->xfunc_error_retval = xfunc_error_retval; |
88 | } | 104 | } |
89 | static void restore_nofork_data(struct nofork_save_area *save) | 105 | static void restore_nofork_data(struct nofork_save_area *save) |
90 | { | 106 | { |
91 | memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); | 107 | memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); |
108 | die_func = save->die_func; | ||
92 | applet_name = save->applet_name; | 109 | applet_name = save->applet_name; |
93 | xfunc_error_retval = save->xfunc_error_retval; | ||
94 | option_mask32 = save->option_mask32; | 110 | option_mask32 = save->option_mask32; |
95 | die_sleep = save->die_sleep; | 111 | xfunc_error_retval = save->xfunc_error_retval; |
96 | } | 112 | } |
97 | 113 | ||
98 | int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | 114 | int FAST_FUNC run_nofork_applet(int applet_no, char **argv) |
@@ -135,11 +151,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
135 | while (argv[argc]) | 151 | while (argv[argc]) |
136 | argc++; | 152 | argc++; |
137 | 153 | ||
138 | /* Special flag for xfunc_die(). If xfunc will "die" | 154 | /* If xfunc "dies" in NOFORK applet, die_func longjmp's here instead */ |
139 | * in NOFORK applet, xfunc_die() sees negative | 155 | die_func = jump; |
140 | * die_sleep and longjmp here instead. */ | ||
141 | die_sleep = -1; | ||
142 | |||
143 | rc = setjmp(die_jmp); | 156 | rc = setjmp(die_jmp); |
144 | if (!rc) { | 157 | if (!rc) { |
145 | /* Some callers (xargs) | 158 | /* Some callers (xargs) |
@@ -148,10 +161,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
148 | memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); | 161 | memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); |
149 | /* Finally we can call NOFORK applet's main() */ | 162 | /* Finally we can call NOFORK applet's main() */ |
150 | rc = applet_main[applet_no](argc, tmp_argv); | 163 | rc = applet_main[applet_no](argc, tmp_argv); |
151 | } else { /* xfunc died in NOFORK applet */ | 164 | } else { |
152 | /* in case they meant to return 0... */ | 165 | /* xfunc died in NOFORK applet */ |
153 | if (rc == -2222) | ||
154 | rc = 0; | ||
155 | } | 166 | } |
156 | 167 | ||
157 | /* Restoring some globals */ | 168 | /* Restoring some globals */ |