Compare commits

...
Sign in to create a new pull request.

6 commits

7 changed files with 364 additions and 1 deletions

View file

@ -0,0 +1,134 @@
From ddb6c5b4c0ab9c6a7404112d367f0c7cc400ceec Mon Sep 17 00:00:00 2001
From: Anthony Sottile <asottile@umich.edu>
Date: Mon, 3 Sep 2018 14:39:25 +0000
Subject: [PATCH] CVE-2018-0502, CVE-2018-13259: Fix two security issues in
shebang line parsing.
See NEWS for more information.
Patch by Anthony Sottile and Buck Evan.
Upstream-commit: 1c4c7b6a4d17294df028322b70c53803a402233d
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/exec.c | 36 ++++++++++++++++++++----------------
Test/A05execution.ztst | 22 ++++++++++++++++++++++
3 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/Src/exec.c b/Src/exec.c
index 216057a..0908a1a 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -453,7 +453,7 @@ execcursh(Estate state, int do_exec)
/* execve after handling $_ and #! */
-#define POUNDBANGLIMIT 64
+#define POUNDBANGLIMIT 128
/**/
static int
@@ -494,18 +494,20 @@ zexecve(char *pth, char **argv, char **newenvp)
if ((fd = open(pth, O_RDONLY|O_NOCTTY)) >= 0) {
argv0 = *argv;
*argv = pth;
- execvebuf[0] = '\0';
+ memset(execvebuf, '\0', POUNDBANGLIMIT + 1);
ct = read(fd, execvebuf, POUNDBANGLIMIT);
close(fd);
if (ct >= 0) {
- if (execvebuf[0] == '#') {
- if (execvebuf[1] == '!') {
- for (t0 = 0; t0 != ct; t0++)
- if (execvebuf[t0] == '\n')
- break;
+ if (ct >= 2 && execvebuf[0] == '#' && execvebuf[1] == '!') {
+ for (t0 = 0; t0 != ct; t0++)
+ if (execvebuf[t0] == '\n')
+ break;
+ if (t0 == ct)
+ zerr("%s: bad interpreter: %s: %e", pth,
+ execvebuf + 2, eno);
+ else {
while (inblank(execvebuf[t0]))
execvebuf[t0--] = '\0';
- execvebuf[POUNDBANGLIMIT] = '\0';
for (ptr = execvebuf + 2; *ptr && *ptr == ' '; ptr++);
for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++);
if (eno == ENOENT) {
@@ -514,10 +516,16 @@ zexecve(char *pth, char **argv, char **newenvp)
*ptr = '\0';
if (*ptr2 != '/' &&
(pprog = pathprog(ptr2, NULL))) {
- argv[-2] = ptr2;
- argv[-1] = ptr + 1;
- winch_unblock();
- execve(pprog, argv - 2, newenvp);
+ if (ptr == execvebuf + t0 + 1) {
+ argv[-1] = ptr2;
+ winch_unblock();
+ execve(pprog, argv - 1, newenvp);
+ } else {
+ argv[-2] = ptr2;
+ argv[-1] = ptr + 1;
+ winch_unblock();
+ execve(pprog, argv - 2, newenvp);
+ }
}
zerr("%s: bad interpreter: %s: %e", pth, ptr2,
eno);
@@ -532,10 +540,6 @@ zexecve(char *pth, char **argv, char **newenvp)
winch_unblock();
execve(ptr2, argv - 1, newenvp);
}
- } else if (eno == ENOEXEC) {
- argv[-1] = "sh";
- winch_unblock();
- execve("/bin/sh", argv - 1, newenvp);
}
} else if (eno == ENOEXEC) {
for (t0 = 0; t0 != ct; t0++)
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
index 0804691..fb39d05 100644
--- a/Test/A05execution.ztst
+++ b/Test/A05execution.ztst
@@ -12,7 +12,14 @@
print '#!/bin/sh\necho This is dir2' >dir2/tstcmd
+ print -n '#!sh\necho This is slashless' >tstcmd-slashless
+ print -n '#!echo foo\necho This is arg' >tstcmd-arg
+ print '#!xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxnyyy' >tstcmd-interp-too-long
+ print '#!/bin/sh\necho should not execute; exit 1' >xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxn
+
chmod 755 tstcmd dir1/tstcmd dir2/tstcmd
+ chmod 755 tstcmd-slashless tstcmd-arg tstcmd-interp-too-long
+ chmod 755 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxn
%test
./tstcmd
@@ -33,6 +40,21 @@
0:path (2)
>This is top
+ PATH=/bin:${ZTST_testdir}/command.tmp/ tstcmd-slashless
+0:path (3)
+>This is slashless
+
+ PATH=/bin:${ZTST_testdir}/command.tmp tstcmd-arg
+0:path (4)
+*>foo */command.tmp/tstcmd-arg
+
+ path=(/bin ${ZTST_testdir}/command.tmp/)
+ tstcmd-interp-too-long 2>&1; echo "status $?"
+ path=($storepath)
+0:path (5)
+*>*tstcmd-interp-too-long: bad interpreter: x*xn: no such file or directory
+>status 127
+
functst() { print $# arguments:; print -l $*; }
functst "Eines Morgens" "als Gregor Samsa"
functst ""
--
2.17.1

View file

@ -0,0 +1,28 @@
From fc22af40437f4de42f7505ca93361391eab788e3 Mon Sep 17 00:00:00 2001
From: Joey Pabalinas <joeypabalinas@gmail.com>
Date: Tue, 23 Jan 2018 22:28:08 -0800
Subject: [PATCH 1/2] 42313: avoid null-pointer deref when using ${(PA)...} on
an empty array result
Upstream-commit: 110b13e1090bc31ac1352b28adc2d02b6d25a102
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/subst.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Src/subst.c b/Src/subst.c
index 5b1bf89..94b0207 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2340,7 +2340,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
val = aval[0];
isarr = 0;
}
- s = dyncat(val, s);
+ s = val ? dyncat(val, s) : dupstring(s);
/* Now behave po-faced as if it was always like that... */
subexp = 0;
/*
--
2.14.3

View file

@ -0,0 +1,38 @@
From 016b8889a6c30279f6ee362e34262c204ef834c2 Mon Sep 17 00:00:00 2001
From: Stephane Chazelas <stephane.chazelas@gmail.com>
Date: Fri, 22 Dec 2017 22:17:09 +0000
Subject: [PATCH 2/2] Avoid crash copying empty hash table.
Visible with typeset -p.
Upstream-commit: c2cc8b0fbefc9868fa83537f5b6d90fc1ec438dd
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/params.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/Src/params.c b/Src/params.c
index 9c7833f..d9da7f6 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -549,10 +549,13 @@ scancopyparams(HashNode hn, UNUSED(int flags))
HashTable
copyparamtable(HashTable ht, char *name)
{
- HashTable nht = newparamtable(ht->hsize, name);
- outtable = nht;
- scanhashtable(ht, 0, 0, 0, scancopyparams, 0);
- outtable = NULL;
+ HashTable nht = 0;
+ if (ht) {
+ nht = newparamtable(ht->hsize, name);
+ outtable = nht;
+ scanhashtable(ht, 0, 0, 0, scancopyparams, 0);
+ outtable = NULL;
+ }
return nht;
}
--
2.14.3

View file

@ -0,0 +1,46 @@
From 3f930a5b3c4e3d34724db6a985393f6a8408703d Mon Sep 17 00:00:00 2001
From: Oliver Kiddle <okiddle@yahoo.co.uk>
Date: Sat, 24 Mar 2018 15:02:41 +0100
Subject: [PATCH] 42518, CVE-2018-1071: check bounds when copying path in hashcmd()
Upstream-commit: 679b71ec4d852037fe5f73d35bf557b0f406c8d4
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/exec.c | 2 +-
Src/utils.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Src/exec.c b/Src/exec.c
index f339dd6..1e82575 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -917,7 +917,7 @@ hashcmd(char *arg0, char **pp)
for (; *pp; pp++)
if (**pp == '/') {
s = buf;
- strucpy(&s, *pp);
+ struncpy(&s, *pp, PATH_MAX);
*s++ = '/';
if ((s - buf) + strlen(arg0) >= PATH_MAX)
continue;
diff --git a/Src/utils.c b/Src/utils.c
index 5055d69..271f55f 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2283,10 +2283,10 @@ struncpy(char **s, char *t, int n)
{
char *u = *s;
- while (n--)
- *u++ = *t++;
+ while (n-- && (*u++ = *t++));
*s = u;
- *u = '\0';
+ if (n > 0) /* just one null-byte will do, unlike strncpy(3) */
+ *u = '\0';
}
/* Return the number of elements in an array of pointers. *
--
2.14.3

View file

@ -0,0 +1,46 @@
From ca7c69f009bf0e13b2c7cbb02310f7c322ee12a0 Mon Sep 17 00:00:00 2001
From: Oliver Kiddle <okiddle@yahoo.co.uk>
Date: Sat, 24 Mar 2018 15:04:39 +0100
Subject: [PATCH] 42519, CVE-2018-1083: check bounds on PATH_MAX-sized
buffer used for file completion candidates
Upstream-commit: 259ac472eac291c8c103c7a0d8a4eaf3c2942ed7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/Zle/compctl.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index 5414b8f..29649ac 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -2176,6 +2176,8 @@ gen_matches_files(int dirs, int execs, int all)
if (prpre && *prpre) {
pathpref = dupstring(prpre);
unmetafy(pathpref, &pathpreflen);
+ if (pathpreflen > PATH_MAX)
+ return;
/* system needs NULL termination, not provided by unmetafy */
pathpref[pathpreflen] = '\0';
} else {
@@ -2218,6 +2220,8 @@ gen_matches_files(int dirs, int execs, int all)
* the path buffer by appending the filename. */
ums = dupstring(n);
unmetafy(ums, &umlen);
+ if (umlen + pathpreflen + 1 > PATH_MAX)
+ continue;
memcpy(q, ums, umlen);
q[umlen] = '\0';
/* And do the stat. */
@@ -2232,6 +2236,8 @@ gen_matches_files(int dirs, int execs, int all)
/* We have to test for a path suffix. */
int o = strlen(p), tt;
+ if (o + strlen(psuf) > PATH_MAX)
+ continue;
/* Append it to the path buffer. */
strcpy(p + o, psuf);
--
2.14.3

View file

@ -0,0 +1,41 @@
From 33be20229d5be359c04b56e5548dd2c17b3aa0b5 Mon Sep 17 00:00:00 2001
From: Oliver Kiddle <okiddle@yahoo.co.uk>
Date: Sat, 7 Apr 2018 18:28:38 +0200
Subject: [PATCH] 42607, CVE-2018-1100: check bounds on buffer in mail checking
Upstream-commit: 31f72205630687c1cef89347863aab355296a27f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/utils.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Src/utils.c b/Src/utils.c
index 271f55f..fa1b5ed 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1653,7 +1653,7 @@ checkmailpath(char **s)
LinkList l;
DIR *lock = opendir(unmeta(*s));
char buf[PATH_MAX * 2 + 1], **arr, **ap;
- int ct = 1;
+ int buflen, ct = 1;
if (lock) {
char *fn;
@@ -1662,9 +1662,11 @@ checkmailpath(char **s)
l = newlinklist();
while ((fn = zreaddir(lock, 1)) && !errflag) {
if (u)
- sprintf(buf, "%s/%s?%s", *s, fn, u);
+ buflen = snprintf(buf, sizeof(buf), "%s/%s?%s", *s, fn, u);
else
- sprintf(buf, "%s/%s", *s, fn);
+ buflen = snprintf(buf, sizeof(buf), "%s/%s", *s, fn);
+ if (buflen < 0 || buflen >= (int)sizeof(buf))
+ continue;
addlinknode(l, dupstring(buf));
ct++;
}
--
2.14.3

View file

@ -1,7 +1,7 @@
Summary: Powerful interactive shell
Name: zsh
Version: 5.4.1
Release: 1%{?dist}
Release: 4%{?dist}
License: MIT
URL: http://zsh.sourceforge.net/
Source0: https://www.zsh.org/pub/%{name}-%{version}.tar.xz
@ -12,6 +12,24 @@ Source4: zshrc.rhs
Source5: zshenv.rhs
Source6: dotzshrc
# fix two security issues in shebang line parsing (CVE-2018-0502 CVE-2018-13259)
Patch1: 0001-zsh-5.5.1-CVE-2018-0502-CVE-2018-13259.patch
# avoid NULL dereference when using ${(PA)...} on an empty array (CVE-2018-7548)
Patch4: 0004-zsh-5.4.2-CVE-2018-7548.patch
# avoid crash when copying empty hash table (CVE-2018-7549)
Patch5: 0005-zsh-5.4.2-CVE-2018-7549.patch
# fix stack-based buffer overflow in exec.c:hashcmd() (CVE-2018-1071)
Patch6: 0006-zsh-5.4.2-CVE-2018-1071.patch
# fix stack-based buffer overflow in gen_matches_files() (CVE-2018-1083)
Patch7: 0007-zsh-5.4.2-CVE-2018-1083.patch
# fix stack-based buffer overflow in utils.c:checkmailpath() (CVE-2018-1100)
Patch8: 0008-zsh-5.4.2-CVE-2018-1100.patch
BuildRequires: coreutils
BuildRequires: gawk
BuildRequires: gdbm-devel
@ -168,6 +186,18 @@ fi
%doc Doc/*.html
%changelog
* Tue Sep 04 2018 Kamil Dudka <kdudka@redhat.com> - 5.4.1-4
- fix two security issues in shebang line parsing (CVE-2018-0502 CVE-2018-13259)
* Wed Apr 18 2018 Kamil Dudka <kdudka@redhat.com> - 5.4.1-3
- fix stack-based buffer overflow in utils.c:checkmailpath() (CVE-2018-1100)
- fix stack-based buffer overflow in gen_matches_files() (CVE-2018-1083)
- fix stack-based buffer overflow in exec.c:hashcmd() (CVE-2018-1071)
* Tue Mar 06 2018 Kamil Dudka <kdudka@redhat.com> - 5.4.1-2
- avoid crash when copying empty hash table (CVE-2018-7549)
- avoid NULL dereference when using ${(PA)...} on an empty array (CVE-2018-7548)
* Wed Aug 09 2017 Kamil Dudka <kdudka@redhat.com> - 5.4.1-1
- update to latest upstream release