summaryrefslogtreecommitdiffstats
path: root/sys/kern/imgact_shell.c
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2010-09-21 16:24:51 +0000
committeralc <alc@FreeBSD.org>2010-09-21 16:24:51 +0000
commit524cb00f17e42971cf96e8296f984f02cb0fa592 (patch)
tree678f632332f49df72469a35d01eac0912c8bef7b /sys/kern/imgact_shell.c
parentfe208ba09513af099f5dc6f4602814ccba69a10e (diff)
downloadFreeBSD-src-524cb00f17e42971cf96e8296f984f02cb0fa592.zip
FreeBSD-src-524cb00f17e42971cf96e8296f984f02cb0fa592.tar.gz
Fix exec_imgact_shell()'s handling of two error cases: (1) Previously, if
the first line of a script exceeded MAXSHELLCMDLEN characters, then exec_imgact_shell() silently truncated the line and passed on the truncated interpreter name or argument. Now, exec_imgact_shell() will fail and return ENOEXEC, which is the commonly used errno among Unix variants for this type of error. (2) Previously, exec_imgact_shell()'s check on the length of the interpreter's name was ineffective. In other words, exec_imgact_shell() could not possibly fail and return ENAMETOOLONG. The reason being that the length of the interpreter name had to exceed MAXSHELLCMDLEN characters in order that ENAMETOOLONG be returned. But, the search for the end of the interpreter name stops after at most MAXSHELLCMDLEN - 2 characters are scanned. (In the end, this particular error is eventually discovered outside of exec_imgact_shell() and ENAMETOOLONG is returned. So, the real effect of this second change is that the error is detected earlier, in exec_imgact_shell().) Update the definition of MAXINTERP to the actual limit on the size of the interpreter name that has been in effect since r142453 (from 2005). In collaboration with: kib
Diffstat (limited to 'sys/kern/imgact_shell.c')
-rw-r--r--sys/kern/imgact_shell.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/sys/kern/imgact_shell.c b/sys/kern/imgact_shell.c
index d0ef87c..0dc9299 100644
--- a/sys/kern/imgact_shell.c
+++ b/sys/kern/imgact_shell.c
@@ -46,13 +46,18 @@ __FBSDID("$FreeBSD$");
/*
* At the time of this writing, MAXSHELLCMDLEN == PAGE_SIZE. This is
* significant because the caller has only mapped in one page of the
- * file we're reading. This code should be changed to know how to
- * read in the second page, but I'm not doing that just yet...
+ * file we're reading.
*/
#if MAXSHELLCMDLEN > PAGE_SIZE
#error "MAXSHELLCMDLEN is larger than a single page!"
#endif
+/*
+ * MAXSHELLCMDLEN must be at least MAXINTERP plus the size of the `#!'
+ * prefix and terminating newline.
+ */
+CTASSERT(MAXSHELLCMDLEN >= MAXINTERP + 3);
+
/**
* Shell interpreter image activator. An interpreter name beginning at
* imgp->args->begin_argv is the minimal successful exit requirement.
@@ -98,20 +103,20 @@ exec_shell_imgact(imgp)
const char *image_header = imgp->image_header;
const char *ihp, *interpb, *interpe, *maxp, *optb, *opte, *fname;
int error, offset;
- size_t length, clength;
+ size_t length;
struct vattr vattr;
struct sbuf *sname;
/* a shell script? */
- if (((const short *) image_header)[0] != SHELLMAGIC)
- return(-1);
+ if (((const short *)image_header)[0] != SHELLMAGIC)
+ return (-1);
/*
* Don't allow a shell script to be the shell for a shell
* script. :-)
*/
if (imgp->interpreted)
- return(ENOEXEC);
+ return (ENOEXEC);
imgp->interpreted = 1;
@@ -127,12 +132,9 @@ exec_shell_imgact(imgp)
/*
* Copy shell name and arguments from image_header into a string
- * buffer. Remember that the caller has mapped only the
- * first page of the file into memory.
+ * buffer.
*/
- clength = (vattr.va_size > PAGE_SIZE) ? PAGE_SIZE : vattr.va_size;
-
- maxp = &image_header[clength];
+ maxp = &image_header[MIN(vattr.va_size, MAXSHELLCMDLEN)];
ihp = &image_header[2];
/*
@@ -149,7 +151,7 @@ exec_shell_imgact(imgp)
interpe = ihp;
if (interpb == interpe)
return (ENOEXEC);
- if ((interpe - interpb) >= MAXSHELLCMDLEN)
+ if (interpe - interpb >= MAXINTERP)
return (ENAMETOOLONG);
/*
@@ -163,6 +165,8 @@ exec_shell_imgact(imgp)
while (ihp < maxp && ((*ihp != '\n') && (*ihp != '\0')))
ihp++;
opte = ihp;
+ if (opte == maxp)
+ return (ENOEXEC);
while (--ihp > optb && ((*ihp == ' ') || (*ihp == '\t')))
opte = ihp;
OpenPOWER on IntegriCloud