|
1 | 1 | diff --git a/Src/exec.c b/Src/exec.c |
2 | | -index 27bca11..baea760 100644 |
| 2 | +index 27bca110c..4e5000be3 100644 |
3 | 3 | --- a/Src/exec.c |
4 | 4 | +++ b/Src/exec.c |
5 | | -@@ -507,7 +507,9 @@ zexecve(char *pth, char **argv, char **newenvp) |
| 5 | +@@ -507,7 +507,12 @@ zexecve(char *pth, char **argv, char **newenvp) |
6 | 6 | { |
7 | 7 | int eno; |
8 | 8 | static char buf[PATH_MAX * 2+1]; |
9 | 9 | - char **eep; |
10 | | -+ char **eep, **exec_argv; |
| 10 | ++ char **eep, **exec_argv, **wrapper_envp; |
11 | 11 | + char *orig_pth = pth; |
12 | 12 | + char *exec_wrapper; |
| 13 | ++ char wrapper_origin_buf[64]; |
| 14 | ++ int wrapper_origin_len; |
| 15 | ++ int wrapper_envc, wrapper_origin_idx; |
13 | 16 |
|
14 | 17 | unmetafy(pth, NULL); |
15 | 18 | for (eep = argv; *eep; eep++) |
16 | | -@@ -526,8 +528,17 @@ zexecve(char *pth, char **argv, char **newenvp) |
| 19 | +@@ -526,8 +531,51 @@ zexecve(char *pth, char **argv, char **newenvp) |
17 | 20 |
|
18 | 21 | if (newenvp == NULL) |
19 | 22 | newenvp = environ; |
20 | 23 | + exec_argv = argv; |
| 24 | ++ /* Use the command env by default; wrapper mode may replace this with an |
| 25 | ++ * explicitly rebuilt envp so origin metadata is guaranteed to be present |
| 26 | ++ * even when execve does not use the process-global environ. */ |
| 27 | ++ wrapper_envp = newenvp; |
21 | 28 | + if ((exec_wrapper = getenv("EXEC_WRAPPER")) && |
22 | 29 | + *exec_wrapper && !inblank(*exec_wrapper)) { |
| 30 | ++ /* zexecve callers provide spare argv slots before argv[0] for |
| 31 | ++ * interpreter dispatch; reuse those slots to trampoline through the |
| 32 | ++ * wrapper binary while preserving the original target path. */ |
23 | 33 | + exec_argv = argv - 2; |
24 | 34 | + exec_argv[0] = exec_wrapper; |
25 | 35 | + exec_argv[1] = orig_pth; |
| 36 | ++ wrapper_origin_len = sprintf(wrapper_origin_buf, |
| 37 | ++ "CODEX_ZSH_EXEC_BRIDGE_WRAPPER_ORIGIN=%d", |
| 38 | ++ zsh_exec_wrapper_origin); |
| 39 | ++ if (wrapper_origin_len > 0 && |
| 40 | ++ wrapper_origin_len < (int)sizeof(wrapper_origin_buf)) { |
| 41 | ++ wrapper_envc = 0; |
| 42 | ++ wrapper_origin_idx = -1; |
| 43 | ++ for (eep = newenvp; *eep; eep++) { |
| 44 | ++ if (strncmp(*eep, "CODEX_ZSH_EXEC_BRIDGE_WRAPPER_ORIGIN=", |
| 45 | ++ sizeof("CODEX_ZSH_EXEC_BRIDGE_WRAPPER_ORIGIN=") - 1) == 0) |
| 46 | ++ wrapper_origin_idx = wrapper_envc; |
| 47 | ++ wrapper_envc++; |
| 48 | ++ } |
| 49 | ++ wrapper_envp = zalloc((wrapper_envc + 2) * sizeof(char *)); |
| 50 | ++ if (wrapper_origin_idx >= 0) { |
| 51 | ++ for (wrapper_envc = 0; newenvp[wrapper_envc]; wrapper_envc++) |
| 52 | ++ wrapper_envp[wrapper_envc] = |
| 53 | ++ wrapper_envc == wrapper_origin_idx ? |
| 54 | ++ wrapper_origin_buf : newenvp[wrapper_envc]; |
| 55 | ++ wrapper_envp[wrapper_envc] = NULL; |
| 56 | ++ } else { |
| 57 | ++ for (wrapper_envc = 0; newenvp[wrapper_envc]; wrapper_envc++) |
| 58 | ++ wrapper_envp[wrapper_envc] = newenvp[wrapper_envc]; |
| 59 | ++ wrapper_envp[wrapper_envc++] = wrapper_origin_buf; |
| 60 | ++ wrapper_envp[wrapper_envc] = NULL; |
| 61 | ++ } |
| 62 | ++ } |
26 | 63 | + pth = exec_wrapper; |
27 | 64 | + } |
28 | 65 | winch_unblock(); |
29 | 66 | - execve(pth, argv, newenvp); |
30 | | -+ execve(pth, exec_argv, newenvp); |
| 67 | ++ execve(pth, exec_argv, wrapper_envp); |
31 | 68 | + pth = orig_pth; |
32 | 69 |
|
33 | 70 | /* If the execve returns (which in general shouldn't happen), * |
34 | 71 | * then check for an errno equal to ENOEXEC. This errno is set * |
| 72 | +diff --git a/Src/init.c b/Src/init.c |
| 73 | +index 20b8cc7fd..b6d5c9c9a 100644 |
| 74 | +--- a/Src/init.c |
| 75 | ++++ b/Src/init.c |
| 76 | +@@ -59,6 +59,9 @@ int underscoreused; |
| 77 | + /**/ |
| 78 | + int sourcelevel; |
| 79 | + |
| 80 | ++/**/ |
| 81 | ++int zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_USER_COMMAND; |
| 82 | ++ |
| 83 | + /* the shell tty fd */ |
| 84 | + |
| 85 | + /**/ |
| 86 | +@@ -1450,14 +1453,25 @@ init_signals(void) |
| 87 | + void |
| 88 | + run_init_scripts(void) |
| 89 | + { |
| 90 | ++ int old_origin; |
| 91 | ++ |
| 92 | + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL; |
| 93 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_USER_COMMAND; |
| 94 | + |
| 95 | + if (EMULATION(EMULATE_KSH|EMULATE_SH)) { |
| 96 | +- if (islogin) |
| 97 | ++ if (islogin) { |
| 98 | ++ old_origin = zsh_exec_wrapper_origin; |
| 99 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP; |
| 100 | + source("/etc/profile"); |
| 101 | ++ zsh_exec_wrapper_origin = old_origin; |
| 102 | ++ } |
| 103 | + if (unset(PRIVILEGED)) { |
| 104 | +- if (islogin) |
| 105 | ++ if (islogin) { |
| 106 | ++ old_origin = zsh_exec_wrapper_origin; |
| 107 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP; |
| 108 | + sourcehome(".profile"); |
| 109 | ++ zsh_exec_wrapper_origin = old_origin; |
| 110 | ++ } |
| 111 | + |
| 112 | + if (interact) { |
| 113 | + noerrs = 2; |
| 114 | +@@ -1467,16 +1481,26 @@ run_init_scripts(void) |
| 115 | + if (!parsestr(&s)) { |
| 116 | + singsub(&s); |
| 117 | + noerrs = 0; |
| 118 | ++ old_origin = zsh_exec_wrapper_origin; |
| 119 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP; |
| 120 | + source(s); |
| 121 | ++ zsh_exec_wrapper_origin = old_origin; |
| 122 | + } |
| 123 | + } |
| 124 | + noerrs = 0; |
| 125 | + } |
| 126 | +- } else |
| 127 | ++ } else { |
| 128 | ++ old_origin = zsh_exec_wrapper_origin; |
| 129 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP; |
| 130 | + source("/etc/suid_profile"); |
| 131 | ++ zsh_exec_wrapper_origin = old_origin; |
| 132 | ++ } |
| 133 | + } else { |
| 134 | + #ifdef GLOBAL_ZSHENV |
| 135 | ++ old_origin = zsh_exec_wrapper_origin; |
| 136 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP; |
| 137 | + source(GLOBAL_ZSHENV); |
| 138 | ++ zsh_exec_wrapper_origin = old_origin; |
| 139 | + #endif |
| 140 | + |
| 141 | + if (isset(RCS) && unset(PRIVILEGED)) |
| 142 | +@@ -1492,33 +1516,61 @@ run_init_scripts(void) |
| 143 | + } |
| 144 | + } |
| 145 | + |
| 146 | ++ old_origin = zsh_exec_wrapper_origin; |
| 147 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP; |
| 148 | + sourcehome(".zshenv"); |
| 149 | ++ zsh_exec_wrapper_origin = old_origin; |
| 150 | + } |
| 151 | + if (islogin) { |
| 152 | + #ifdef GLOBAL_ZPROFILE |
| 153 | +- if (isset(RCS) && isset(GLOBALRCS)) |
| 154 | ++ if (isset(RCS) && isset(GLOBALRCS)) { |
| 155 | ++ old_origin = zsh_exec_wrapper_origin; |
| 156 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP; |
| 157 | + source(GLOBAL_ZPROFILE); |
| 158 | ++ zsh_exec_wrapper_origin = old_origin; |
| 159 | ++ } |
| 160 | + #endif |
| 161 | +- if (isset(RCS) && unset(PRIVILEGED)) |
| 162 | ++ if (isset(RCS) && unset(PRIVILEGED)) { |
| 163 | ++ old_origin = zsh_exec_wrapper_origin; |
| 164 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP; |
| 165 | + sourcehome(".zprofile"); |
| 166 | ++ zsh_exec_wrapper_origin = old_origin; |
| 167 | ++ } |
| 168 | + } |
| 169 | + if (interact) { |
| 170 | + #ifdef GLOBAL_ZSHRC |
| 171 | +- if (isset(RCS) && isset(GLOBALRCS)) |
| 172 | ++ if (isset(RCS) && isset(GLOBALRCS)) { |
| 173 | ++ old_origin = zsh_exec_wrapper_origin; |
| 174 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP; |
| 175 | + source(GLOBAL_ZSHRC); |
| 176 | ++ zsh_exec_wrapper_origin = old_origin; |
| 177 | ++ } |
| 178 | + #endif |
| 179 | +- if (isset(RCS) && unset(PRIVILEGED)) |
| 180 | ++ if (isset(RCS) && unset(PRIVILEGED)) { |
| 181 | ++ old_origin = zsh_exec_wrapper_origin; |
| 182 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_RC_STARTUP; |
| 183 | + sourcehome(".zshrc"); |
| 184 | ++ zsh_exec_wrapper_origin = old_origin; |
| 185 | ++ } |
| 186 | + } |
| 187 | + if (islogin) { |
| 188 | + #ifdef GLOBAL_ZLOGIN |
| 189 | +- if (isset(RCS) && isset(GLOBALRCS)) |
| 190 | ++ if (isset(RCS) && isset(GLOBALRCS)) { |
| 191 | ++ old_origin = zsh_exec_wrapper_origin; |
| 192 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP; |
| 193 | + source(GLOBAL_ZLOGIN); |
| 194 | ++ zsh_exec_wrapper_origin = old_origin; |
| 195 | ++ } |
| 196 | + #endif |
| 197 | +- if (isset(RCS) && unset(PRIVILEGED)) |
| 198 | ++ if (isset(RCS) && unset(PRIVILEGED)) { |
| 199 | ++ old_origin = zsh_exec_wrapper_origin; |
| 200 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP; |
| 201 | + sourcehome(".zlogin"); |
| 202 | ++ zsh_exec_wrapper_origin = old_origin; |
| 203 | ++ } |
| 204 | + } |
| 205 | + } |
| 206 | ++ zsh_exec_wrapper_origin = EXEC_WRAPPER_ORIGIN_USER_COMMAND; |
| 207 | + noerrexit = 0; |
| 208 | + nohistsave = 0; |
| 209 | + } |
| 210 | +diff --git a/Src/zsh.h b/Src/zsh.h |
| 211 | +index 5bda04e88..c0750cf45 100644 |
| 212 | +--- a/Src/zsh.h |
| 213 | ++++ b/Src/zsh.h |
| 214 | +@@ -2215,6 +2215,14 @@ enum source_return { |
| 215 | + SOURCE_ERROR = 2 |
| 216 | + }; |
| 217 | + |
| 218 | ++enum exec_wrapper_origin { |
| 219 | ++ EXEC_WRAPPER_ORIGIN_USER_COMMAND = 0, |
| 220 | ++ EXEC_WRAPPER_ORIGIN_LOGIN_STARTUP = 1, |
| 221 | ++ EXEC_WRAPPER_ORIGIN_RC_STARTUP = 2 |
| 222 | ++}; |
| 223 | ++ |
| 224 | ++extern int zsh_exec_wrapper_origin; |
| 225 | ++ |
| 226 | + enum noerrexit_bits { |
| 227 | + /* Suppress ERR_EXIT and traps: global */ |
| 228 | + NOERREXIT_EXIT = 1, |
0 commit comments