| Summary: | the kernel config utility crashes with large path | ||
|---|---|---|---|
| Product: | Base System | Reporter: | patrick <patrick> |
| Component: | kern | Assignee: | Warner Losh <imp> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 4.1.1-STABLE | ||
| Hardware: | Any | ||
| OS: | Any | ||
State Changed From-To: open->closed Aren't those exactly the patches that Warner Losch committed on Nov 21, around 20:00 UTC? Look at the following revisions of the files: Filename HEAD RELENG_4 main.c 1.41 1.37.2.2 mkheaders.c 1.17 1.14.2.1 mkmakefile.c 1.56 1.51.2.2 mkoptions.c 1.21 1.17.2.2 Responsible Changed From-To: freebsd-bugs->imp Warner Losch committed this. |
The config utility used to configure a customized kernel can not accept long path names as arguments. Many internal variables are not sized properly (usually 80 characters !!!), and unsafe string copies are performed all over the place. Fix: The following set of patches for /usr/sbin/config fix a bunch of unsafe string manipulations and size the variables containing path to be MAXPATHLEN long. --- main.c.orig +++ main.c @@ -98,7 +98,7 @@ switch (ch) { case 'd': if (*destdir == '\0') - strcpy(destdir, optarg); + strncpy(destdir, optarg, sizeof(destdir)); else errx(2, "directory already set"); break; @@ -135,8 +135,8 @@ destdir[--len] = '\0'; get_srcdir(); } else { - strcpy(destdir, CDIR); - strcat(destdir, PREFIX); + strncpy(destdir, CDIR, sizeof(destdir)); + strncat(destdir, PREFIX, sizeof(destdir)-strlen(destdir)); } p = path((char *)NULL); @@ -183,7 +183,7 @@ * and similarly for "machine". */ { - char xxx[80]; + char xxx[MAXPATHLEN]; if (*srcdir == '\0') (void)snprintf(xxx, sizeof(xxx), "../../%s/include", machinename); --- mkheaders.c.orig +++ mkheaders.c @@ -43,6 +43,7 @@ * Make all the .h files for the optional entries */ +#include <sys/param.h> #include <ctype.h> #include <err.h> #include <stdio.h> @@ -220,10 +221,10 @@ toheader(dev) char *dev; { - static char hbuf[80]; + static char hbuf[MAXPATHLEN]; - (void) strcpy(hbuf, path(dev)); - (void) strcat(hbuf, ".h"); + (void) strncpy(hbuf, path(dev), sizeof(hbuf)); + (void) strncat(hbuf, ".h", sizeof(hbuf)-strlen(hbuf)); return (hbuf); } --- mkmakefile.c.orig +++ mkmakefile.c @@ -45,6 +45,7 @@ * additional files for the machine being compiled to. */ +#include <sys/param.h> #include <ctype.h> #include <err.h> #include <stdio.h> @@ -232,7 +233,7 @@ struct device *save_dp; register struct opt *op; char *wd, *this, *needs, *special, *depends, *clean, *warn; - char fname[80]; + char fname[MAXPATHLEN]; int ddwarned = 0; int nreqs, first = 1, configdep, isdup, std, filetype, imp_rule, no_obj, before_depend, mandatory; --- mkoptions.c.orig +++ mkoptions.c @@ -44,6 +44,7 @@ * Make all the .h files for the optional entries */ +#include <sys/param.h> #include <ctype.h> #include <err.h> #include <stdio.h> @@ -275,21 +276,21 @@ tooption(name) char *name; { - static char hbuf[80]; - char nbuf[80]; + static char hbuf[MAXPATHLEN]; + char nbuf[MAXPATHLEN]; struct opt_list *po; /* "cannot happen"? the otab list should be complete.. */ - (void) strcpy(nbuf, "options.h"); + (void) strncpy(nbuf, "options.h", sizeof(nbuf)); for (po = otab ; po != 0; po = po->o_next) { if (eq(po->o_name, name)) { - strcpy(nbuf, po->o_file); + strncpy(nbuf, po->o_file, sizeof(nbuf)); break; } } - (void) strcpy(hbuf, path(nbuf)); + (void) strncpy(hbuf, path(nbuf), sizeof(nbuf)); return (hbuf); } @@ -300,7 +301,7 @@ read_options() { FILE *fp; - char fname[80]; + char fname[MAXPATHLEN]; char *wd, *this, *val; struct opt_list *po; int first = 1; How-To-Repeat: config -d /a/path/obviously/longer/than/80/characters/which/can/happen/easily/if/you/keep/your/source/in/a/non/standard/directory/src/sys/KERNELNAME KERNELNAME will provoke the appropriate crash.