diff options
author | kib <kib@FreeBSD.org> | 2008-08-26 10:53:32 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2008-08-26 10:53:32 +0000 |
commit | 2d990eae0580f74b2aee49da3c6434c6224e084c (patch) | |
tree | 47bfdf1c555705341fbc8c52a90b0103dae4c384 | |
parent | 166aba1cac7a69c4dd3b699509db81eab23ac6f2 (diff) | |
download | FreeBSD-src-2d990eae0580f74b2aee49da3c6434c6224e084c.zip FreeBSD-src-2d990eae0580f74b2aee49da3c6434c6224e084c.tar.gz |
When calculating arguments to the interpreter for the shebang script
executed by fexecve(2), imgp->args->fname is NULL. Moreover, there is
no way to recover the path to the script being executed.
Do what some other U*ixes do unconditionally, namely supply /dev/fd/n
as the script path when called from fexecve(). Document requirement of
having fdescfs mounted as caveat.
-rw-r--r-- | lib/libc/sys/execve.2 | 19 | ||||
-rw-r--r-- | sys/kern/imgact_shell.c | 27 |
2 files changed, 40 insertions, 6 deletions
diff --git a/lib/libc/sys/execve.2 b/lib/libc/sys/execve.2 index c077008..8cb25bc 100644 --- a/lib/libc/sys/execve.2 +++ b/lib/libc/sys/execve.2 @@ -314,7 +314,7 @@ The .Fa fd argument is not a valid file descriptor open for executing. .El -.Sh CAVEAT +.Sh CAVEATS If a program is .Em setuid to a non-super-user, but is executed when @@ -322,6 +322,22 @@ the real .Em uid is ``root'', then the program has some of the powers of a super-user as well. +.Pp +When executing an interpreted program through +.Fn fexecve , +kernel supplies +.Pa /dev/fd/n +as a second argument to the interpreter, +where +.Ar n +is the file descriptor passed in the +.Fa fd +argument to +.Fn fexecve . +For this construction to work correctly, the +.Xr fdescfs 5 +filesystem shall be mounted on +.Pa /dev/fd . .Sh SEE ALSO .Xr ktrace 1 , .Xr _exit 2 , @@ -332,6 +348,7 @@ of a super-user as well. .Xr sysctl 3 , .Xr a.out 5 , .Xr elf 5 , +.Xr fdescfs 5 , .Xr environ 7 , .Xr mount 8 .Sh STANDARDS diff --git a/sys/kern/imgact_shell.c b/sys/kern/imgact_shell.c index 2f8b133..99b4c27 100644 --- a/sys/kern/imgact_shell.c +++ b/sys/kern/imgact_shell.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/vnode.h> #include <sys/proc.h> +#include <sys/sbuf.h> #include <sys/systm.h> #include <sys/sysproto.h> #include <sys/exec.h> @@ -95,10 +96,11 @@ exec_shell_imgact(imgp) struct image_params *imgp; { const char *image_header = imgp->image_header; - const char *ihp, *interpb, *interpe, *maxp, *optb, *opte; + const char *ihp, *interpb, *interpe, *maxp, *optb, *opte, *fname; int error, offset; size_t length, clength; struct vattr vattr; + struct sbuf *sname; /* a shell script? */ if (((const short *) image_header)[0] != SHELLMAGIC) @@ -164,6 +166,16 @@ exec_shell_imgact(imgp) while (--ihp > optb && ((*ihp == ' ') || (*ihp == '\t'))) opte = ihp; + if (imgp->args->fname != NULL) { + fname = imgp->args->fname; + sname = NULL; + } else { + sname = sbuf_new_auto(); + sbuf_printf(sname, "/dev/fd/%d", imgp->args->fd); + sbuf_finish(sname); + fname = sbuf_data(sname); + } + /* * We need to "pop" (remove) the present value of arg[0], and "push" * either two or three new values in the arg[] list. To do this, @@ -175,12 +187,15 @@ exec_shell_imgact(imgp) offset = interpe - interpb + 1; /* interpreter */ if (opte > optb) /* options (if any) */ offset += opte - optb + 1; - offset += strlen(imgp->args->fname) + 1; /* fname of script */ + offset += strlen(fname) + 1; /* fname of script */ length = (imgp->args->argc == 0) ? 0 : strlen(imgp->args->begin_argv) + 1; /* bytes to delete */ - if (offset - length > imgp->args->stringspace) + if (offset - length > imgp->args->stringspace) { + if (sname != NULL) + sbuf_delete(sname); return (E2BIG); + } bcopy(imgp->args->begin_argv + length, imgp->args->begin_argv + offset, imgp->args->endp - (imgp->args->begin_argv + length)); @@ -221,13 +236,15 @@ exec_shell_imgact(imgp) * use and copy the interpreter's name to imgp->interpreter_name * for exec to use. */ - error = copystr(imgp->args->fname, imgp->args->buf + offset, - imgp->args->stringspace, &length); + error = copystr(fname, imgp->args->buf + offset, imgp->args->stringspace, + &length); if (error == 0) error = copystr(imgp->args->begin_argv, imgp->interpreter_name, MAXSHELLCMDLEN, &length); + if (sname != NULL) + sbuf_delete(sname); return (error); } |