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.
This commit is contained in:
parent
321e12c82e
commit
eaad109973
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=182191
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user