o Replace two while {} do loops with more appropriate do {} while loops. This

doesn't change functionality, but makes code more logical.

Obtained from:	DrafonFlyBSD

o Use VOP_GETATTR() to obtain actual size of file and parse no more than that.
  Previously, we parsed MAXSHELLCMDLEN characters regardless of the actual file
  size. This makes the following working:

$ printf '#!/bin/echo' > /tmp/test.sh
$ chmod 755 /tmp/test.sh
$ /tmp/test.sh

Previously, attempts to execve() that shell script has been failing with bogus
ENAMETOOLONG.

PR:		kern/64196
Submitted by:	Magnus B.ckstr.m <b@etek.chalmers.se>
This commit is contained in:
Maxim Sobolev 2005-02-25 10:17:53 +00:00
parent 39aeaa0eb5
commit 6916a1da50
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=142448

View File

@ -28,6 +28,8 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/vnode.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/exec.h>
@ -51,7 +53,8 @@ exec_shell_imgact(imgp)
const char *image_header = imgp->image_header;
const char *ihp;
int error, offset;
size_t length;
size_t length, clength;
struct vattr vattr;
/* a shell script? */
if (((const short *) image_header)[0] != SHELLMAGIC)
@ -66,6 +69,18 @@ exec_shell_imgact(imgp)
imgp->interpreted = 1;
/*
* At this point we have the first page of the file mapped.
* However, we don't know how far into the page the contents are
* valid -- the actual file might be much shorter than the page.
* So find out the file size.
*/
error = VOP_GETATTR(imgp->vp, &vattr, imgp->proc->p_ucred, curthread);
if (error)
return (error);
clength = (vattr.va_size > MAXSHELLCMDLEN) ?
MAXSHELLCMDLEN : vattr.va_size;
/*
* Figure out the number of bytes that need to be reserved in the
* argument string to copy the contents of the interpreter's command
@ -73,7 +88,7 @@ exec_shell_imgact(imgp)
*/
ihp = &image_header[2];
offset = 0;
while (ihp < &image_header[MAXSHELLCMDLEN]) {
while (ihp < &image_header[clength]) {
/* Skip any whitespace */
if ((*ihp == ' ') || (*ihp == '\t')) {
ihp++;
@ -85,12 +100,12 @@ exec_shell_imgact(imgp)
break;
/* Found a token */
while ((*ihp != ' ') && (*ihp != '\t') && (*ihp != '\n') &&
(*ihp != '#') && (*ihp != '\0') &&
(ihp < &image_header[MAXSHELLCMDLEN])) {
do {
offset++;
ihp++;
}
} while ((*ihp != ' ') && (*ihp != '\t') && (*ihp != '\n') &&
(*ihp != '#') && (*ihp != '\0') &&
(ihp < &image_header[clength]));
/* Include terminating nulls in the offset */
offset++;
}
@ -100,7 +115,7 @@ exec_shell_imgact(imgp)
return (ENOEXEC);
/* Check that we aren't too big */
if (offset > MAXSHELLCMDLEN)
if (ihp == &image_header[MAXSHELLCMDLEN])
return (ENAMETOOLONG);
/*
@ -139,7 +154,7 @@ exec_shell_imgact(imgp)
*/
ihp = &image_header[2];
offset = 0;
while (ihp < &image_header[MAXSHELLCMDLEN]) {
while (ihp < &image_header[clength]) {
/* Skip whitespace */
if ((*ihp == ' ') || (*ihp == '\t')) {
ihp++;
@ -151,11 +166,11 @@ exec_shell_imgact(imgp)
break;
/* Found a token, copy it */
while ((*ihp != ' ') && (*ihp != '\t') && (*ihp != '\n') &&
(*ihp != '#') && (*ihp != '\0') &&
(ihp < &image_header[MAXSHELLCMDLEN])) {
do {
imgp->args->begin_argv[offset++] = *ihp++;
}
} while ((*ihp != ' ') && (*ihp != '\t') && (*ihp != '\n') &&
(*ihp != '#') && (*ihp != '\0') &&
(ihp < &image_header[MAXSHELLCMDLEN]));
imgp->args->begin_argv[offset++] = '\0';
imgp->args->argc++;
}