Commit 79caa560 authored by Rocky Automation's avatar Rocky Automation 📺
Browse files

import zsh-5.5.1-6.el8_1.2

parent e3d2dedc
From e6dea148252c9d8cb3de0965f2e558ac13e12f06 Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <danielsh@apache.org>
Date: Thu, 26 Dec 2019 11:49:45 +0000
Subject: [PATCH 1/7] internal: Allow %L in zerrmsg() in non-debug builds, too.
This will let error messages include long integers.
Upstream-commit: 81185f4c6106d7ea2f7beaabbec7360c08e400d2
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/utils.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/Src/utils.c b/Src/utils.c
index 32f6008..2ddc596 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -325,12 +325,10 @@ zerrmsg(FILE *file, const char *fmt, va_list ap)
nicezputs(s, file);
break;
}
-#ifdef DEBUG
case 'L':
lnum = va_arg(ap, long);
fprintf(file, "%ld", lnum);
break;
-#endif
case 'd':
num = va_arg(ap, int);
fprintf(file, "%d", num);
--
2.21.1
From 4907caaf15e5a054088e05534c5500679c15b105 Mon Sep 17 00:00:00 2001
From: dana <dana@dana.is>
Date: Thu, 26 Dec 2019 14:57:07 -0600
Subject: [PATCH 2/7] unposted: zerrmsg(): Fix macro guard missed in previous
commit
Upstream-commit: ed21a7b70068b4250a25dcdc5b7213a789b0d0ca
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/utils.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/Src/utils.c b/Src/utils.c
index 2ddc596..4a1dcc4 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -287,9 +287,7 @@ zerrmsg(FILE *file, const char *fmt, va_list ap)
{
const char *str;
int num;
-#ifdef DEBUG
long lnum;
-#endif
#ifdef HAVE_STRERROR_R
#define ERRBUFSIZE (80)
int olderrno;
--
2.21.1
From a6763e5de6eebc5994097fc4d778094e7254589c Mon Sep 17 00:00:00 2001
From: Sam Foxman <samfoxman320@gmail.com>
Date: Sun, 22 Dec 2019 17:30:28 -0500
Subject: [PATCH 3/7] Drop privileges securely
Upstream-commit: 24e993db62cf146fb76ebcf677a4a7aa3766fc74
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/options.c | 146 +++++++++++++++++++++++++++++++++++++++++---------
configure.ac | 4 +-
2 files changed, 125 insertions(+), 25 deletions(-)
diff --git a/Src/options.c b/Src/options.c
index 590652e..c9608af 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -576,6 +576,7 @@ int
bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
{
int action, optno, match = 0;
+ int retval = 0;
/* With no arguments or options, display options. */
if (!*args) {
@@ -603,18 +604,28 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
inittyptab();
return 1;
}
- if(!(optno = optlookup(*args)))
+ if(!(optno = optlookup(*args))) {
zwarnnam(nam, "no such option: %s", *args);
- else if(dosetopt(optno, action, 0, opts))
- zwarnnam(nam, "can't change option: %s", *args);
+ retval = 1;
+ } else {
+ retval = !!dosetopt(optno, action, 0, opts);
+ if (retval) {
+ zwarnnam(nam, "can't change option: %s", *args);
+ }
+ }
break;
} else if(**args == 'm') {
match = 1;
} else {
- if (!(optno = optlookupc(**args)))
+ if (!(optno = optlookupc(**args))) {
zwarnnam(nam, "bad option: -%c", **args);
- else if(dosetopt(optno, action, 0, opts))
- zwarnnam(nam, "can't change option: -%c", **args);
+ retval = 1;
+ } else {
+ retval = !!dosetopt(optno, action, 0, opts);
+ if (retval) {
+ zwarnnam(nam, "can't change option: -%c", **args);
+ }
+ }
}
}
args++;
@@ -624,10 +635,15 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
if (!match) {
/* Not globbing the arguments -- arguments are simply option names. */
while (*args) {
- if(!(optno = optlookup(*args++)))
+ if(!(optno = optlookup(*args++))) {
zwarnnam(nam, "no such option: %s", args[-1]);
- else if(dosetopt(optno, !isun, 0, opts))
- zwarnnam(nam, "can't change option: %s", args[-1]);
+ retval = 1;
+ } else {
+ retval = !!dosetopt(optno, !isun, 0, opts);
+ if (retval) {
+ zwarnnam(nam, "can't change option: %s", args[-1]);
+ }
+ }
}
} else {
/* Globbing option (-m) set. */
@@ -650,7 +666,8 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
tokenize(s);
if (!(pprog = patcompile(s, PAT_HEAPDUP, NULL))) {
zwarnnam(nam, "bad pattern: %s", *args);
- continue;
+ retval = 1;
+ break;
}
/* Loop over expansions. */
scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS,
@@ -659,7 +676,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
}
}
inittyptab();
- return 0;
+ return retval;
}
/* Identify an option name */
@@ -768,20 +785,101 @@ dosetopt(int optno, int value, int force, char *new_opts)
return -1;
} else if(optno == PRIVILEGED && !value) {
/* unsetting PRIVILEGED causes the shell to make itself unprivileged */
-#ifdef HAVE_SETUID
- setuid(getuid());
- setgid(getgid());
- if (setuid(getuid())) {
- zwarn("failed to change user ID: %e", errno);
- return -1;
- } else if (setgid(getgid())) {
- zwarn("failed to change group ID: %e", errno);
- return -1;
- }
+
+ int skip_setuid = 0;
+ int skip_setgid = 0;
+
+#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID)
+ int orig_egid = getegid();
+#endif
+
+#if defined(HAVE_GETEUID) && defined(HAVE_GETUID)
+ if (geteuid() == getuid()) {
+ skip_setuid = 1;
+ }
+#endif
+
+#if defined(HAVE_GETEGID) && defined(HAVE_GETGID)
+ if (getegid() == getgid()) {
+ skip_setgid = 1;
+ }
+#endif
+
+ if (!skip_setgid) {
+ int setgid_err;
+#ifdef HAVE_SETRESGID
+ setgid_err = setresgid(getgid(), getgid(), getgid());
+#elif defined(HAVE_SETREGID)
+#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID)
+ setgid_err = setregid(getgid(), getgid());
+#else
+ zwarnnam("unsetopt",
+ "PRIVILEGED: can't drop privileges; setregid available, but cannot check if saved gid changed");
+ return -1;
+#endif
+#else
+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid and setregid not available");
+ return -1;
+#endif
+ if (setgid_err) {
+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change group ID: %e", errno);
+ return -1;
+ }
+ }
+
+ if (!skip_setuid) {
+#if defined(HAVE_GETEUID) && defined(HAVE_SETUID)
+ int orig_euid = geteuid();
+#endif
+ int setuid_err;
+#if defined(HAVE_GETEUID) && defined(HAVE_INITGROUPS) && defined(HAVE_GETPWUID)
+ if (geteuid() == 0) {
+ struct passwd *pw = getpwuid(getuid());
+ if (pw == NULL) {
+ zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %d: %e",
+ getuid(), errno);
+ return -1;
+ }
+ if (initgroups(pw->pw_name, pw->pw_gid)) {
+ zwarnnam("unsetopt", "can't drop privileges; failed to set supplementary group list: %e", errno);
+ return -1;
+ }
+ }
+#endif
+
+#ifdef HAVE_SETRESUID
+ setuid_err = setresuid(getuid(), getuid(), getuid());
+#elif defined(HAVE_SETREUID)
+#if defined(HAVE_GETEUID) && defined(HAVE_SETUID) && defined(HAVE_GETUID)
+ setuid_err = setreuid(getuid(), getuid());
+#else
+ zwarnnam("unsetopt",
+ "PRIVILEGED: can't drop privileges; setreuid available, but cannot check if saved uid changed");
+ return -1;
+#endif
#else
- zwarn("setuid not available");
- return -1;
-#endif /* not HAVE_SETUID */
+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresuid and setreuid not available");
+ return -1;
+#endif
+ if (setuid_err) {
+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change user ID: %e", errno);
+ return -1;
+ }
+#if defined(HAVE_GETEUID) && defined(HAVE_SETUID) && defined(HAVE_GETUID)
+ if (getuid() != 0 && !setuid(orig_euid)) {
+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the euid");
+ return -1;
+ }
+#endif
+ }
+
+#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID)
+ if (getuid() != 0 && !skip_setgid && !setgid(orig_egid)) {
+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the egid");
+ return -1;
+ }
+#endif
+
#ifdef JOB_CONTROL
} else if (!force && optno == MONITOR && value) {
if (new_opts[optno] == value)
diff --git a/configure.ac b/configure.ac
index d15a6cd..51cdf89 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1300,7 +1300,9 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
inet_aton inet_pton inet_ntop \
getlogin getpwent getpwnam getpwuid getgrgid getgrnam \
initgroups nis_list \
- setuid seteuid setreuid setresuid setsid \
+ getuid setuid seteuid setreuid setresuid setsid \
+ getgid setgid setegid setregid setresgid \
+ geteuid getegid \
memcpy memmove strstr strerror strtoul \
getrlimit getrusage \
setlocale \
--
2.21.1
From 07ec3e46db743ff37fd2bfeafbb4a44ddc7b4aaa Mon Sep 17 00:00:00 2001
From: Daniel Shahaf <danielsh@apache.org>
Date: Thu, 26 Dec 2019 09:16:19 +0000
Subject: [PATCH 4/7] Improve PRIVILEGED fixes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Fix retval handling in bin_setopt()
- Don't skip_setuid / skip_setgid. It's not our place to optimize away noops
(that might not even _be_ noops; they might change the saved uid…).
- Remove HAVE_* guard checks around functions that are used unguarded elsewhere.
- Use bsd-setres_id.c from OpenSSH to provide setresuid() / setresgid()
everywhere, and thus simplify the ifdef soup. Fix some preëxisting
bugs in the macro definitions of setuid() (do we still need that one?).
- Fix zwarning() format codes for variadic arguments type safety
- Restored a comment from HEAD
- Fix failure modes around initgroups()
- Compared privilege restoration code with OpenSSH's permanently_drop_uid() and
updated as needed
- Add E01 PRIVILEGED sanity checks
Upstream-commit: 8250c5c168f07549ed646e6848e6dda118271e23
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
Src/openssh_bsd_setres_id.c | 129 +++++++++++++++++++++++++++++++
Src/options.c | 148 ++++++++++++++++--------------------
Src/zsh.mdd | 3 +-
Src/zsh_system.h | 94 ++++++++++++++++++-----
Test/E01options.ztst | 15 ++++
configure.ac | 5 +-
6 files changed, 292 insertions(+), 102 deletions(-)
create mode 100644 Src/openssh_bsd_setres_id.c
diff --git a/Src/openssh_bsd_setres_id.c b/Src/openssh_bsd_setres_id.c
new file mode 100644
index 0000000..65e91a4
--- /dev/null
+++ b/Src/openssh_bsd_setres_id.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012 Darren Tucker (dtucker at zip com au).
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * openssh_bsd_setres_id.c - setresuid() and setresgid() wrappers
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * It is based on the file openbsd-compat/bsd-setres_id.c in OpenSSH 7.9p1,
+ * which is subject to the copyright notice above. The zsh modifications are
+ * licensed as follows:
+ *
+ * Copyright (c) 2019 Daniel Shahaf
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Daniel Shahaf or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Daniel Shahaf and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Daniel Shahaf and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Daniel Shahaf and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "zsh.mdh"
+
+#if defined(ZSH_IMPLEMENT_SETRESGID) || defined(BROKEN_SETRESGID)
+int
+setresgid(gid_t rgid, gid_t egid, gid_t sgid)
+{
+ int ret = 0, saved_errno;
+
+ if (rgid != sgid) {
+ errno = ENOSYS;
+ return -1;
+ }
+#if defined(ZSH_HAVE_NATIVE_SETREGID) && !defined(BROKEN_SETREGID)
+ if (setregid(rgid, egid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setregid", "to gid %L: %e", (long)rgid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+#else
+ if (setegid(egid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setegid", "to gid %L: %e", (long)(unsigned int)egid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+ if (setgid(rgid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setgid", "to gid %L: %e", (long)rgid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+#endif
+ return ret;
+}
+#endif
+
+#if defined(ZSH_IMPLEMENT_SETRESUID) || defined(BROKEN_SETRESUID)
+int
+setresuid(uid_t ruid, uid_t euid, uid_t suid)
+{
+ int ret = 0, saved_errno;
+
+ if (ruid != suid) {
+ errno = ENOSYS;
+ return -1;
+ }
+#if defined(ZSH_HAVE_NATIVE_SETREUID) && !defined(BROKEN_SETREUID)
+ if (setreuid(ruid, euid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setreuid", "to uid %L: %e", (long)ruid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+#else
+
+# ifndef SETEUID_BREAKS_SETUID
+ if (seteuid(euid) < 0) {
+ saved_errno = errno;
+ zwarnnam("seteuid", "to uid %L: %e", (long)euid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+# endif
+ if (setuid(ruid) < 0) {
+ saved_errno = errno;
+ zwarnnam("setuid", "to uid %L: %e", (long)ruid, errno);
+ errno = saved_errno;
+ ret = -1;
+ }
+#endif
+ return ret;
+}
+#endif
diff --git a/Src/options.c b/Src/options.c
index c9608af..deec560 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -606,25 +606,21 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
}
if(!(optno = optlookup(*args))) {
zwarnnam(nam, "no such option: %s", *args);
- retval = 1;
- } else {
- retval = !!dosetopt(optno, action, 0, opts);
- if (retval) {
- zwarnnam(nam, "can't change option: %s", *args);
- }
+ retval |= 1;
+ } else if (dosetopt(optno, action, 0, opts)) {
+ zwarnnam(nam, "can't change option: %s", *args);
+ retval |= 1;
}
break;
} else if(**args == 'm') {
match = 1;
} else {
- if (!(optno = optlookupc(**args))) {
+ if (!(optno = optlookupc(**args))) {
zwarnnam(nam, "bad option: -%c", **args);
- retval = 1;
- } else {
- retval = !!dosetopt(optno, action, 0, opts);
- if (retval) {
- zwarnnam(nam, "can't change option: -%c", **args);
- }
+ retval |= 1;
+ } else if (dosetopt(optno, action, 0, opts)) {
+ zwarnnam(nam, "can't change option: -%c", **args);
+ retval |= 1;
}
}
}
@@ -637,12 +633,10 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
while (*args) {
if(!(optno = optlookup(*args++))) {
zwarnnam(nam, "no such option: %s", args[-1]);
- retval = 1;
- } else {
- retval = !!dosetopt(optno, !isun, 0, opts);
- if (retval) {
- zwarnnam(nam, "can't change option: %s", args[-1]);
- }
+ retval |= 1;
+ } else if (dosetopt(optno, !isun, 0, opts)) {
+ zwarnnam(nam, "can't change option: %s", args[-1]);
+ retval |= 1;
}
}
} else {
@@ -666,7 +660,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
tokenize(s);
if (!(pprog = patcompile(s, PAT_HEAPDUP, NULL))) {
zwarnnam(nam, "bad pattern: %s", *args);
- retval = 1;
+ retval |= 1;
break;
}
/* Loop over expansions. */
@@ -786,100 +780,92 @@ dosetopt(int optno, int value, int force, char *new_opts)
} else if(optno == PRIVILEGED && !value) {
/* unsetting PRIVILEGED causes the shell to make itself unprivileged */
- int skip_setuid = 0;
- int skip_setgid = 0;
-
-#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID)
- int orig_egid = getegid();
-#endif
+ /* If set, return -1 so lastval will be non-zero. */
+ int failed = 0;
-#if defined(HAVE_GETEUID) && defined(HAVE_GETUID)
- if (geteuid() == getuid()) {
- skip_setuid = 1;
- }
+#ifdef HAVE_SETUID
+ const int orig_euid = geteuid();
#endif
+ const int orig_egid = getegid();
-#if defined(HAVE_GETEGID) && defined(HAVE_GETGID)
- if (getegid() == getgid()) {
- skip_setgid = 1;
- }
-#endif
-
- if (!skip_setgid) {
- int setgid_err;
-#ifdef HAVE_SETRESGID
- setgid_err = setresgid(getgid(), getgid(), getgid());
-#elif defined(HAVE_SETREGID)
-#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID)
- setgid_err = setregid(getgid(), getgid());
-#else
- zwarnnam("unsetopt",
- "PRIVILEGED: can't drop privileges; setregid available, but cannot check if saved gid changed");
+ /*
+ * Set the GID first as if we set the UID to non-privileged it
+ * might be impossible to restore the GID.
+ */
+ {
+#ifndef HAVE_SETRESGID
+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid() and friends not available");
return -1;
-#endif
#else
- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid and setregid not available");
- return -1;
-#endif
+ int setgid_err;
+ setgid_err = setresgid(getgid(), getgid(), getgid());
if (setgid_err) {
zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change group ID: %e", errno);
return -1;
}
+#endif
}
- if (!skip_setuid) {
-#if defined(HAVE_GETEUID) && defined(HAVE_SETUID)
- int orig_euid = geteuid();
-#endif
+ /* Set the UID second. */
+ {
+#ifndef HAVE_SETRESUID
+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresuid() and friends not available");
+ return -1;
+#else
int setuid_err;
-#if defined(HAVE_GETEUID) && defined(HAVE_INITGROUPS) && defined(HAVE_GETPWUID)
+
+# ifdef HAVE_INITGROUPS
+ /* Set the supplementary groups list. */
if (geteuid() == 0) {
struct passwd *pw = getpwuid(getuid());
if (pw == NULL) {
- zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %d: %e",
- getuid(), errno);
- return -1;
- }
- if (initgroups(pw->pw_name, pw->pw_gid)) {
+ zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %L: %e",
+ (long)getuid(), errno);
+ failed = 1;
+ } else if (initgroups(pw->pw_name, pw->pw_gid)) {
zwarnnam("unsetopt", "can't drop privileges; failed to set supplementary group list: %e", errno);
return -1;
}
+ } else if (getuid() != 0 &&
+ (geteuid() != getuid() || orig_egid != getegid())) {
+ zwarnnam("unsetopt", "PRIVILEGED: supplementary group list not changed due to lack of permissions: EUID=%L",
+ (long)geteuid());
+ failed = 1;
}
-#endif