diff options
| -rw-r--r-- | fs/binfmt_misc.c | 5 | ||||
| -rw-r--r-- | fs/binfmt_script.c | 4 | ||||
| -rw-r--r-- | fs/exec.c | 15 | ||||
| -rw-r--r-- | include/linux/binfmts.h | 1 |
4 files changed, 23 insertions, 2 deletions
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 9be335fb8a7c..0c8869fdd14e 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
| @@ -172,7 +172,10 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
| 172 | goto _error; | 172 | goto _error; |
| 173 | bprm->argc ++; | 173 | bprm->argc ++; |
| 174 | 174 | ||
| 175 | bprm->interp = iname; /* for binfmt_script */ | 175 | /* Update interp in case binfmt_script needs it. */ |
| 176 | retval = bprm_change_interp(iname, bprm); | ||
| 177 | if (retval < 0) | ||
| 178 | goto _error; | ||
| 176 | 179 | ||
| 177 | interp_file = open_exec (iname); | 180 | interp_file = open_exec (iname); |
| 178 | retval = PTR_ERR (interp_file); | 181 | retval = PTR_ERR (interp_file); |
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 1610a91637e5..5027a3e14922 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c | |||
| @@ -80,7 +80,9 @@ static int load_script(struct linux_binprm *bprm) | |||
| 80 | retval = copy_strings_kernel(1, &i_name, bprm); | 80 | retval = copy_strings_kernel(1, &i_name, bprm); |
| 81 | if (retval) return retval; | 81 | if (retval) return retval; |
| 82 | bprm->argc++; | 82 | bprm->argc++; |
| 83 | bprm->interp = interp; | 83 | retval = bprm_change_interp(interp, bprm); |
| 84 | if (retval < 0) | ||
| 85 | return retval; | ||
| 84 | 86 | ||
| 85 | /* | 87 | /* |
| 86 | * OK, now restart the process with the interpreter's dentry. | 88 | * OK, now restart the process with the interpreter's dentry. |
| @@ -1175,9 +1175,24 @@ void free_bprm(struct linux_binprm *bprm) | |||
| 1175 | mutex_unlock(¤t->signal->cred_guard_mutex); | 1175 | mutex_unlock(¤t->signal->cred_guard_mutex); |
| 1176 | abort_creds(bprm->cred); | 1176 | abort_creds(bprm->cred); |
| 1177 | } | 1177 | } |
| 1178 | /* If a binfmt changed the interp, free it. */ | ||
| 1179 | if (bprm->interp != bprm->filename) | ||
| 1180 | kfree(bprm->interp); | ||
| 1178 | kfree(bprm); | 1181 | kfree(bprm); |
| 1179 | } | 1182 | } |
| 1180 | 1183 | ||
| 1184 | int bprm_change_interp(char *interp, struct linux_binprm *bprm) | ||
| 1185 | { | ||
| 1186 | /* If a binfmt changed the interp, free it first. */ | ||
| 1187 | if (bprm->interp != bprm->filename) | ||
| 1188 | kfree(bprm->interp); | ||
| 1189 | bprm->interp = kstrdup(interp, GFP_KERNEL); | ||
| 1190 | if (!bprm->interp) | ||
| 1191 | return -ENOMEM; | ||
| 1192 | return 0; | ||
| 1193 | } | ||
| 1194 | EXPORT_SYMBOL(bprm_change_interp); | ||
| 1195 | |||
| 1181 | /* | 1196 | /* |
| 1182 | * install the new credentials for this executable | 1197 | * install the new credentials for this executable |
| 1183 | */ | 1198 | */ |
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index a4c2b565c835..bdf3965f0a29 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h | |||
| @@ -112,6 +112,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, | |||
| 112 | unsigned long stack_top, | 112 | unsigned long stack_top, |
| 113 | int executable_stack); | 113 | int executable_stack); |
| 114 | extern int bprm_mm_init(struct linux_binprm *bprm); | 114 | extern int bprm_mm_init(struct linux_binprm *bprm); |
| 115 | extern int bprm_change_interp(char *interp, struct linux_binprm *bprm); | ||
| 115 | extern int copy_strings_kernel(int argc, const char *const *argv, | 116 | extern int copy_strings_kernel(int argc, const char *const *argv, |
| 116 | struct linux_binprm *bprm); | 117 | struct linux_binprm *bprm); |
| 117 | extern int prepare_bprm_creds(struct linux_binprm *bprm); | 118 | extern int prepare_bprm_creds(struct linux_binprm *bprm); |
