11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/fs/binfmt_script.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 496de0e252cedffad61b3cb5e05662c591898e69aJan Engelhardt * Copyright (C) 1996 Martin von Löwis 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * original #!-checking implemented by tytso. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stat.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/binfmts.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/file.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int load_script(struct linux_binprm *bprm,struct pt_regs *regs) 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19d7627467b7a8dd6944885290a03a07ceb28c10ebDavid Howells const char *i_arg, *i_name; 20d7627467b7a8dd6944885290a03a07ceb28c10ebDavid Howells char *cp; 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct file *file; 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char interp[BINPRM_BUF_SIZE]; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25bf2a9a39639b8b51377905397a5005f444e9a892Kirill A. Shutemov if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || 26bf2a9a39639b8b51377905397a5005f444e9a892Kirill A. Shutemov (bprm->recursion_depth > BINPRM_MAX_RECURSION)) 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOEXEC; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This section does the #! interpretation. 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sorta complicated, but hopefully it will work. -TYT 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33bf2a9a39639b8b51377905397a5005f444e9a892Kirill A. Shutemov bprm->recursion_depth++; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds allow_write_access(bprm->file); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fput(bprm->file); 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bprm->file = NULL; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bprm->buf[BINPRM_BUF_SIZE - 1] = '\0'; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cp = strchr(bprm->buf, '\n')) == NULL) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp = bprm->buf+BINPRM_BUF_SIZE-1; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp = '\0'; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (cp > bprm->buf) { 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp--; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*cp == ' ') || (*cp == '\t')) 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp = '\0'; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*cp == '\0') 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOEXEC; /* No interpreter name found */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i_name = cp; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i_arg = NULL; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* nothing */ ; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((*cp == ' ') || (*cp == '\t')) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = '\0'; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*cp) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i_arg = cp; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy (interp, i_name); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OK, we've parsed out the interpreter name and 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (optional) argument. 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Splice in (1) the interpreter's name for argv[0] 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (2) (optional) argument to interpreter 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (3) filename of shell script (replace argv[0]) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is done in reverse order, because of how the 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user environment and arguments are stored. 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 71b6a2fea39318e43fee84fa7b0b90d68bed92d2baOllie Wild retval = remove_arg_zero(bprm); 72b6a2fea39318e43fee84fa7b0b90d68bed92d2baOllie Wild if (retval) 73b6a2fea39318e43fee84fa7b0b90d68bed92d2baOllie Wild return retval; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = copy_strings_kernel(1, &bprm->interp, bprm); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) return retval; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bprm->argc++; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i_arg) { 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = copy_strings_kernel(1, &i_arg, bprm); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) return retval; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bprm->argc++; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = copy_strings_kernel(1, &i_name, bprm); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval) return retval; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bprm->argc++; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bprm->interp = interp; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OK, now restart the process with the interpreter's dentry. 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds file = open_exec(interp); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(file)) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(file); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bprm->file = file; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = prepare_binprm(bprm); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return search_binary_handler(bprm,regs); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct linux_binfmt script_format = { 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .module = THIS_MODULE, 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .load_binary = load_script, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_script_binfmt(void) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return register_binfmt(&script_format); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit exit_script_binfmt(void) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_binfmt(&script_format); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscore_initcall(init_script_binfmt); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(exit_script_binfmt); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 119