From 12ebd46e4ba3e87df2146ded91995561d2d7fdd0 Mon Sep 17 00:00:00 2001 From: "Jordan K. Hubbard" Date: Mon, 6 Jan 2003 07:39:02 +0000 Subject: [PATCH] Prevent buffer overflow in format_cmd() by properly tracking maximum buffer size. Reported by: Lionnel CHAPTAL MFC after: 1 week --- usr.sbin/pkg_install/add/extract.c | 2 +- usr.sbin/pkg_install/lib/file.c | 34 ++++++++++++++++++------------ usr.sbin/pkg_install/lib/lib.h | 2 +- usr.sbin/pkg_install/lib/plist.c | 2 +- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/usr.sbin/pkg_install/add/extract.c b/usr.sbin/pkg_install/add/extract.c index 83f46e312c9..f35cce2663a 100644 --- a/usr.sbin/pkg_install/add/extract.c +++ b/usr.sbin/pkg_install/add/extract.c @@ -223,7 +223,7 @@ extract_plist(const char *home, Package *pkg) errx(2, "%s: no directory specified for '%s' command", __func__, p->name); } - format_cmd(cmd, p->name, Directory, last_file); + format_cmd(cmd, FILENAME_MAX, p->name, Directory, last_file); PUSHOUT(Directory); if (Verbose) printf("extract: execute '%s'\n", cmd); diff --git a/usr.sbin/pkg_install/lib/file.c b/usr.sbin/pkg_install/lib/file.c index 2ad1bc20e44..5cb0d49c9c8 100644 --- a/usr.sbin/pkg_install/lib/file.c +++ b/usr.sbin/pkg_install/lib/file.c @@ -370,50 +370,58 @@ unpack(const char *pkg, const char *flist) * */ void -format_cmd(char *buf, const char *fmt, const char *dir, const char *name) +format_cmd(char *buf, int max, const char *fmt, const char *dir, const char *name) { char *cp, scratch[FILENAME_MAX * 2]; + int l; - while (*fmt) { + while (*fmt && max > 0) { if (*fmt == '%') { switch (*++fmt) { case 'F': - strcpy(buf, name); - buf += strlen(name); + strncpy(buf, name, max); + l = strlen(name); + buf += l, max -= l; break; case 'D': - strcpy(buf, dir); - buf += strlen(dir); + strncpy(buf, dir, max); + l = strlen(dir); + buf += l, max -= l; break; case 'B': - sprintf(scratch, "%s/%s", dir, name); + snprintf(scratch, FILENAME_MAX * 2, "%s/%s", dir, name); cp = &scratch[strlen(scratch) - 1]; while (cp != scratch && *cp != '/') --cp; *cp = '\0'; - strcpy(buf, scratch); - buf += strlen(scratch); + strncpy(buf, scratch, max); + l = strlen(scratch); + buf += l, max -= l; break; case 'f': - sprintf(scratch, "%s/%s", dir, name); + snprintf(scratch, FILENAME_MAX * 2, "%s/%s", dir, name); cp = &scratch[strlen(scratch) - 1]; while (cp != scratch && *(cp - 1) != '/') --cp; - strcpy(buf, cp); - buf += strlen(cp); + strncpy(buf, cp, max); + l = strlen(cp); + buf += l, max -= l; break; default: *buf++ = *fmt; + --max; break; } ++fmt; } - else + else { *buf++ = *fmt++; + --max; + } } *buf = '\0'; } diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h index 00b735ee1b9..ffb0e737427 100644 --- a/usr.sbin/pkg_install/lib/lib.h +++ b/usr.sbin/pkg_install/lib/lib.h @@ -171,7 +171,7 @@ void move_file(const char *, const char *, const char *); void copy_hierarchy(const char *, const char *, Boolean); int delete_hierarchy(const char *, Boolean, Boolean); int unpack(const char *, const char *); -void format_cmd(char *, const char *, const char *, const char *); +void format_cmd(char *, int, const char *, const char *, const char *); /* Msg */ void upchuck(const char *); diff --git a/usr.sbin/pkg_install/lib/plist.c b/usr.sbin/pkg_install/lib/plist.c index 4a640c42728..696e0f56893 100644 --- a/usr.sbin/pkg_install/lib/plist.c +++ b/usr.sbin/pkg_install/lib/plist.c @@ -427,7 +427,7 @@ delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg) break; case PLIST_UNEXEC: - format_cmd(tmp, p->name, Where, last_file); + format_cmd(tmp, FILENAME_MAX, p->name, Where, last_file); if (Verbose) printf("Execute '%s'\n", tmp); if (!Fake && system(tmp)) {