Compare commits

...

11 Commits

Author SHA1 Message Date
openeuler-ci-bot
6b349b67ea
!44 [sync] PR-43: cifs-utils: backport some patches
From: @openeuler-sync-bot 
Reviewed-by: @swf504 
Signed-off-by: @swf504
2023-03-31 06:26:00 +00:00
Zhiqiang Liu
b9a4d50032 cifs-utils: backport some patches
Fix issue: https://gitee.com/src-openeuler/cifs-utils/issues/I6RRNJ

Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
(cherry picked from commit 9305c08964d0f21e12f29fed187e53e5231770a2)
2023-03-31 11:18:24 +08:00
openeuler-ci-bot
2fb1871e5e
!39 [sync] PR-33: Fix CVE-2022-27239 and CVE-2022-29869
From: @openeuler-sync-bot 
Reviewed-by: @liuzhiqiang26 
Signed-off-by: @liuzhiqiang26
2022-05-05 13:13:39 +00:00
markeryang
45878d64d8 Fix CVE-2022-27239 and CVE-2022-29869
(cherry picked from commit 7eea3d2a39f9a4b662c6fd87bfc7729a717222cd)
2022-05-05 20:37:04 +08:00
openeuler-ci-bot
c87206bc5a !30 [sync] PR-25: bug fix :cifs-utils-6.10_fix_capng_apply_for_libcap-ng-0.8.1
From: @openeuler-sync-bot
Reviewed-by: @liuzhiqiang26
Signed-off-by: @liuzhiqiang26
2021-11-30 02:54:24 +00:00
konglidong
b96453fd95 fix_capng_apply_for_libcap-ng-0.8.1
(cherry picked from commit 4f1a54450022f0b9a03d4abe477a164c122055a1)
2021-11-30 10:29:34 +08:00
openeuler-ci-bot
40a8127454 !23 [sync] PR-19: Sync each branch submit
From: @openeuler-sync-bot
Reviewed-by: @liuzhiqiang26
Signed-off-by: @liuzhiqiang26
2021-08-17 12:03:28 +00:00
openeuler-ci-bot
caba941b07 !23 [sync] PR-19: Sync each branch submit
From: @openeuler-sync-bot
Reviewed-by: @liuzhiqiang26
Signed-off-by: @liuzhiqiang26
2021-08-17 12:03:27 +00:00
Wenchao Hao
df1d03ec28 delete -Sgit from %autosetup, and delete BuildRequires git
Signed-off-by: Wenchao Hao <haowenchao@huawei.com>
(cherry picked from commit 1bde74c1a80d63f4668d313630126310ade5c2c4)
2021-08-17 19:41:58 +08:00
openeuler-ci-bot
613a935956 !14 Fix CVE-2021-20208
From: @markeryang
Reviewed-by: @liuzhiqiang26,@wubo009
Signed-off-by: @wubo009
2021-05-13 10:06:43 +08:00
markeryang
c5046a7d89 Fix CVE-2021-20208 2021-05-08 15:45:03 +08:00
11 changed files with 1147 additions and 4 deletions

View File

@ -0,0 +1,51 @@
From 8f46aaadffde42ef0c89e97c0443ee7944708d94 Mon Sep 17 00:00:00 2001
From: Simon Arlott <simon@octiron.net>
Date: Thu, 26 Nov 2020 00:28:08 +0000
Subject: [PATCH] Add missing position handling to mount parameters
gid/backup_gid/snapshot
The code tries to optimise for the last parameter not needing to update
the position which means that every time a new one is added to the end
by copying and pasting, the string position is not updated.
That makes it impossible to use backup_uid=/backup_gid=/snapshot= after
gid= or snapshot= after backup_gid= because part of the string is
overwritten and contains invalid keys like "gbackup_uid".
Prepare for the next parameter to be added on the end by updating the
position for snapshot= even though it will be unused.
---
mount.cifs.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/mount.cifs.c b/mount.cifs.c
index 2474e98..ff07232 100644
--- a/mount.cifs.c
+++ b/mount.cifs.c
@@ -1245,6 +1245,7 @@ nocopy:
out_len++;
}
snprintf(out + out_len, word_len + 5, "gid=%s", txtbuf);
+ out_len = strlen(out);
}
if (got_bkupuid) {
word_len = snprintf(txtbuf, sizeof(txtbuf), "%u", bkupuid);
@@ -1276,6 +1277,7 @@ nocopy:
out_len++;
}
snprintf(out + out_len, word_len + 11, "backupgid=%s", txtbuf);
+ out_len = strlen(out);
}
if (got_snapshot) {
word_len = snprintf(txtbuf, sizeof(txtbuf), "%llu", snapshot);
@@ -1291,6 +1293,7 @@ nocopy:
out_len++;
}
snprintf(out + out_len, word_len + 11, "snapshot=%s", txtbuf);
+ out_len = strlen(out);
}
return 0;
--
2.33.0

262
0002-CVE-2021-20208.patch Normal file
View File

@ -0,0 +1,262 @@
From cb8b6a8b8ea983844584d8ada4d9aa4c88c997fb Mon Sep 17 00:00:00 2001
From: Alastair Houghton <alastair@alastairs-place.net>
Date: Tue, 29 Dec 2020 14:02:39 +0000
Subject: [PATCH] cifs.upcall: try to use container ipc/uts/net/pid/mnt/user
namespaces
In certain scenarios (e.g. kerberos multimount), when a process does
syscalls, the kernel sometimes has to query information or trigger
some actions in userspace. To do so it calls the cifs.upcall binary
with information on the process that triggered the syscall in the
first place.
ls(pid=10) ====> open("foo") ====> kernel
that user doesn't have an SMB
session, lets create one using his
kerberos credential cache
call cifs.upcall and ask for krb info
for whoever owns pid=10
|
cifs.upcall --pid 10 <=================+
...gather info...
return binary blob used
when establishing SMB session
===================> kernel
open SMB session, handle
open() syscall
ls <=================================== return open() result to ls
On a system using containers, the kernel is still calling the host
cifs.upcall and using the host configuration (for network, pid, etc).
This patch changes the behaviour of cifs.upcall so that it uses the
calling process namespaces (ls in the example) when doing its
job.
Note that the kernel still calls the binary in the host, but the
binary will place itself the contexts of the calling process
namespaces.
This code makes use of (but shouldn't require) the following kernel
config options and syscall flags:
approx. year |
introduced | config/flags
---------------+----------------
2008 | CONFIG_NAMESPACES=y
2007 | CONFIG_UTS_NS=y
2020 | CONFIG_TIME_NS=y
2006 | CONFIG_IPC_NS=y
2007 | CONFIG_USER_NS
2008 | CONFIG_PID_NS=y
2007 | CONFIG_NET_NS=y
2007 | CONFIG_CGROUPS
2016 | CLONE_NEWCGROUP setns() flag
Signed-off-by: Aurelien Aptel <aaptel@suse.com>
Signed-off-by: Alastair Houghton <alastair@alastairs-place.net>
---
cifs.upcall.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 171 insertions(+)
diff --git a/cifs.upcall.c b/cifs.upcall.c
index 1559434..141dc66 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -51,6 +51,7 @@
#include <grp.h>
#include <stdbool.h>
#include <errno.h>
+#include <sched.h>
#include "data_blob.h"
#include "spnego.h"
@@ -230,6 +231,164 @@ err_cache:
return credtime;
}
+static struct namespace_file {
+ int nstype;
+ const char *name;
+ int fd;
+} namespace_files[] = {
+
+#ifdef CLONE_NEWCGROUP
+ { CLONE_NEWCGROUP, "cgroup", -1 },
+#endif
+
+#ifdef CLONE_NEWIPC
+ { CLONE_NEWIPC, "ipc", -1 },
+#endif
+
+#ifdef CLONE_NEWUTS
+ { CLONE_NEWUTS, "uts", -1 },
+#endif
+
+#ifdef CLONE_NEWNET
+ { CLONE_NEWNET, "net", -1 },
+#endif
+
+#ifdef CLONE_NEWPID
+ { CLONE_NEWPID, "pid", -1 },
+#endif
+
+#ifdef CLONE_NEWTIME
+ { CLONE_NEWTIME, "time", -1 },
+#endif
+
+#ifdef CLONE_NEWNS
+ { CLONE_NEWNS, "mnt", -1 },
+#endif
+
+#ifdef CLONE_NEWUSER
+ { CLONE_NEWUSER, "user", -1 },
+#endif
+};
+
+#define NS_PATH_FMT "/proc/%d/ns/%s"
+#define NS_PATH_MAXLEN (6 + 10 + 4 + 6 + 1)
+
+/**
+ * in_same_user_ns - return true if two processes are in the same user
+ * namespace.
+ * @pid_a: the pid of the first process
+ * @pid_b: the pid of the second process
+ *
+ * Works by comparing the inode numbers for /proc/<pid>/user.
+ */
+static int
+in_same_user_ns(pid_t pid_a, pid_t pid_b)
+{
+ char path[NS_PATH_MAXLEN];
+ ino_t a_ino, b_ino;
+ struct stat st;
+
+ snprintf(path, sizeof(path), NS_PATH_FMT, pid_a, "user");
+ if (stat(path, &st) != 0)
+ return 0;
+ a_ino = st.st_ino;
+
+ snprintf(path, sizeof(path), NS_PATH_FMT, pid_b, "user");
+ if (stat(path, &st) != 0)
+ return 0;
+ b_ino = st.st_ino;
+
+ return a_ino == b_ino;
+}
+
+/**
+ * switch_to_process_ns - change the namespace to the one for the specified
+ * process.
+ * @pid: initiating pid value from the upcall string
+ *
+ * Uses setns() to switch process namespace.
+ * This ensures that we have the same access and configuration as the
+ * process that triggered the lookup.
+ */
+static int
+switch_to_process_ns(pid_t pid)
+{
+ int count = sizeof(namespace_files) / sizeof(struct namespace_file);
+ int n, err = 0;
+ int rc = 0;
+
+ /* First, open all the namespace fds. We do this first because
+ the namespace changes might prohibit us from opening them. */
+ for (n = 0; n < count; ++n) {
+ char nspath[NS_PATH_MAXLEN];
+ int ret, fd;
+
+#ifdef CLONE_NEWUSER
+ if (namespace_files[n].nstype == CLONE_NEWUSER
+ && in_same_user_ns(getpid(), pid)) {
+ /* Switching to the same user namespace is forbidden,
+ because switching to a user namespace grants all
+ capabilities in that namespace regardless of uid. */
+ namespace_files[n].fd = -1;
+ continue;
+ }
+#endif
+
+ ret = snprintf(nspath, NS_PATH_MAXLEN, NS_PATH_FMT,
+ pid, namespace_files[n].name);
+ if (ret >= NS_PATH_MAXLEN) {
+ syslog(LOG_DEBUG, "%s: unterminated path!\n", __func__);
+ err = ENAMETOOLONG;
+ rc = -1;
+ goto out;
+ }
+
+ fd = open(nspath, O_RDONLY);
+ if (fd < 0 && errno != ENOENT) {
+ /*
+ * don't stop on non-existing ns
+ * but stop for other errors
+ */
+ err = errno;
+ rc = -1;
+ goto out;
+ }
+
+ namespace_files[n].fd = fd;
+ }
+
+ /* Next, call setns for each of them */
+ for (n = 0; n < count; ++n) {
+ /* skip non-existing ns */
+ if (namespace_files[n].fd < 0)
+ continue;
+
+ rc = setns(namespace_files[n].fd, namespace_files[n].nstype);
+
+ if (rc < 0) {
+ syslog(LOG_DEBUG, "%s: setns() failed for %s\n",
+ __func__, namespace_files[n].name);
+ err = errno;
+ goto out;
+ }
+ }
+
+out:
+ /* Finally, close all the fds */
+ for (n = 0; n < count; ++n) {
+ if (namespace_files[n].fd != -1) {
+ close(namespace_files[n].fd);
+ namespace_files[n].fd = -1;
+ }
+ }
+
+ if (rc != 0) {
+ errno = err;
+ }
+
+ return rc;
+}
+
#define ENV_PATH_FMT "/proc/%d/environ"
#define ENV_PATH_MAXLEN (6 + 10 + 8 + 1)
@@ -1099,6 +1258,19 @@ int main(const int argc, char *const argv[])
env_cachename =
get_cachename_from_process_env(env_probe ? arg.pid : 0);
+ /*
+ * Change to the process's namespace. This means that things will work
+ * acceptably in containers, because we'll be looking at the correct
+ * filesystem and have the correct network configuration.
+ */
+ rc = switch_to_process_ns(arg.pid);
+ if (rc == -1) {
+ syslog(LOG_ERR, "unable to switch to process namespace: %s",
+ strerror(errno));
+ rc = 1;
+ goto out;
+ }
+
rc = setuid(uid);
if (rc == -1) {
syslog(LOG_ERR, "setuid: %s", strerror(errno));
--

View File

@ -0,0 +1,44 @@
From aeaa786aceb0ea781ded2c151fb68f6b34880ad4 Mon Sep 17 00:00:00 2001
From: lizhe <lizhe67@huawei.com>
Date: Tue, 26 May 2020 11:54:11 +0800
Subject: [PATCH] cifs-utils: fix probabilistic compiling error
When we compile cifs-utils, we may probabilistic
encounter install error like:
cd ***/sbin && ln -sf mount.cifs mount.smb3
***/sbin: No such file or directory
The reason of this problem is that if we compile
cifs-utils using multithreading, target
'install-sbinPROGRAMS' may be built after
target 'install-exec-hook' of the main Makefile.
Target 'install-sbinPROGRAMS' will copy the
executable file 'mount.cifs' to the $(ROOTSBINDIR),
which target 'install-exec-hook' will do the
'ln' command on.
This patch add the dependency of target
'install-exec-hook' to ensure the correct order
of the compiling.
Signed-off-by: lizhe <lizhe67@huawei.com>
---
Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index a95782d..8a17e73 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -117,7 +117,7 @@ endif
SUBDIRS = contrib
-install-exec-hook:
+install-exec-hook: install-sbinPROGRAMS
(cd $(ROOTSBINDIR) && ln -sf mount.cifs mount.smb3)
install-data-hook:
--
2.33.0

View File

@ -0,0 +1,26 @@
From 7156c6eca0fcf3d4a2fd2f8677b2622475c5c46e Mon Sep 17 00:00:00 2001
From: Pavel Shilovsky <pshilov@microsoft.com>
Date: Wed, 9 Dec 2020 11:29:40 -0800
Subject: [PATCH] mount.cifs: fix max buffer size when parsing snapshot option
Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
---
mount.cifs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mount.cifs.c b/mount.cifs.c
index ff07232..7c949cf 100644
--- a/mount.cifs.c
+++ b/mount.cifs.c
@@ -1292,7 +1292,7 @@ nocopy:
strlcat(out, ",", MAX_OPTIONS_LEN);
out_len++;
}
- snprintf(out + out_len, word_len + 11, "snapshot=%s", txtbuf);
+ snprintf(out + out_len, word_len + 10, "snapshot=%s", txtbuf);
out_len = strlen(out);
}
--
2.33.0

View File

@ -0,0 +1,50 @@
From 4205fdc411701ffc323769d41508e0875b9d63d4 Mon Sep 17 00:00:00 2001
From: Jonas Witschel <diabonas@archlinux.org>
Date: Sat, 21 Nov 2020 12:11:45 +0100
Subject: [PATCH] cifs.upcall: update the cap bounding set only when
CAP_SETPCAP is given
libcap-ng 0.8.1 tightened the error checking on capng_apply, returning an error
of -4 when trying to update the capability bounding set without having the
CAP_SETPCAP capability to be able to do so. Previous versions of libcap-ng
silently skipped updating the bounding set and only updated the normal
CAPNG_SELECT_CAPS capabilities instead.
Check beforehand whether we have CAP_SETPCAP, in which case we can use
CAPNG_SELECT_BOTH to update both the normal capabilities and the bounding set.
Otherwise, we can at least update the normal capabilities, but refrain from
trying to update the bounding set to avoid getting an error.
Signed-off-by: Jonas Witschel <diabonas@archlinux.org>
---
cifs.upcall.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/cifs.upcall.c b/cifs.upcall.c
index 1559434..af1a0b0 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -88,6 +88,8 @@ typedef enum _sectype {
static int
trim_capabilities(bool need_environ)
{
+ capng_select_t set = CAPNG_SELECT_CAPS;
+
capng_clear(CAPNG_SELECT_BOTH);
/* SETUID and SETGID to change uid, gid, and grouplist */
@@ -105,7 +107,10 @@ trim_capabilities(bool need_environ)
return 1;
}
- if (capng_apply(CAPNG_SELECT_BOTH)) {
+ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
+ set = CAPNG_SELECT_BOTH;
+ }
+ if (capng_apply(set)) {
syslog(LOG_ERR, "%s: Unable to apply capability set: %m\n", __func__);
return 1;
}
--
2.27.0

View File

@ -0,0 +1,50 @@
From e406fb13e5b08b440100ec6215973060b7fdcff3 Mon Sep 17 00:00:00 2001
From: Jonas Witschel <diabonas@archlinux.org>
Date: Sat, 21 Nov 2020 12:11:44 +0100
Subject: [PATCH] mount.cifs: update the cap bounding set only when CAP_SETPCAP
is given
libcap-ng 0.8.1 tightened the error checking on capng_apply, returning an error
of -4 when trying to update the capability bounding set without having the
CAP_SETPCAP capability to be able to do so. Previous versions of libcap-ng
silently skipped updating the bounding set and only updated the normal
CAPNG_SELECT_CAPS capabilities instead.
Check beforehand whether we have CAP_SETPCAP, in which case we can use
CAPNG_SELECT_BOTH to update both the normal capabilities and the bounding set.
Otherwise, we can at least update the normal capabilities, but refrain from
trying to update the bounding set to avoid getting an error.
Signed-off-by: Jonas Witschel <diabonas@archlinux.org>
---
mount.cifs.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/mount.cifs.c b/mount.cifs.c
index 81bdbc8..2474e98 100644
--- a/mount.cifs.c
+++ b/mount.cifs.c
@@ -347,6 +347,8 @@ static int set_password(struct parsed_mount_info *parsed_info, const char *src)
static int
drop_capabilities(int parent)
{
+ capng_select_t set = CAPNG_SELECT_CAPS;
+
capng_setpid(getpid());
capng_clear(CAPNG_SELECT_BOTH);
if (parent) {
@@ -364,7 +366,10 @@ drop_capabilities(int parent)
return EX_SYSERR;
}
}
- if (capng_apply(CAPNG_SELECT_BOTH)) {
+ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
+ set = CAPNG_SELECT_BOTH;
+ }
+ if (capng_apply(set)) {
fprintf(stderr, "Unable to apply new capability set.\n");
return EX_SYSERR;
}
--
2.27.0

35
0007-CVE-2022-27239.patch Normal file
View File

@ -0,0 +1,35 @@
From 955fb147e97a6a74e1aaa65766de91e2c1479765 Mon Sep 17 00:00:00 2001
From: Jeffrey Bencteux <jbe@improsec.com>
Date: Thu, 17 Mar 2022 12:58:52 -0400
Subject: [PATCH] CVE-2022-27239: mount.cifs: fix length check for ip option
parsing
Previous check was true whatever the length of the input string was,
leading to a buffer overflow in the subsequent strcpy call.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=15025
Signed-off-by: Jeffrey Bencteux <jbe@improsec.com>
Reviewed-by: David Disseldorp <ddiss@suse.de>
---
mount.cifs.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mount.cifs.c b/mount.cifs.c
index 84274c9..3a6b449 100644
--- a/mount.cifs.c
+++ b/mount.cifs.c
@@ -926,9 +926,10 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info)
if (!value || !*value) {
fprintf(stderr,
"target ip address argument missing\n");
- } else if (strnlen(value, MAX_ADDRESS_LEN) <=
+ } else if (strnlen(value, MAX_ADDRESS_LEN) <
MAX_ADDRESS_LEN) {
- strcpy(parsed_info->addrlist, value);
+ strlcpy(parsed_info->addrlist, value,
+ MAX_ADDRESS_LEN);
if (parsed_info->verboseflag)
fprintf(stderr,
"ip address %s override specified\n",
--

42
0008-CVE-2022-29869.patch Normal file
View File

@ -0,0 +1,42 @@
From 8acc963a2e7e9d63fe1f2e7f73f5a03f83d9c379 Mon Sep 17 00:00:00 2001
From: Jeffrey Bencteux <jbe@improsec.com>
Date: Sat, 19 Mar 2022 13:41:15 -0400
Subject: [PATCH] mount.cifs: fix verbose messages on option parsing
When verbose logging is enabled, invalid credentials file lines may be
dumped to stderr. This may lead to information disclosure in particular
conditions when the credentials file given is sensitive and contains '='
signs.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=15026
Signed-off-by: Jeffrey Bencteux <jbe@improsec.com>
Reviewed-by: David Disseldorp <ddiss@suse.de>
---
mount.cifs.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/mount.cifs.c b/mount.cifs.c
index 3a6b449..2278995 100644
--- a/mount.cifs.c
+++ b/mount.cifs.c
@@ -628,17 +628,13 @@ static int open_cred_file(char *file_name,
goto return_i;
break;
case CRED_DOM:
- if (parsed_info->verboseflag)
- fprintf(stderr, "domain=%s\n",
- temp_val);
strlcpy(parsed_info->domain, temp_val,
sizeof(parsed_info->domain));
break;
case CRED_UNPARSEABLE:
if (parsed_info->verboseflag)
fprintf(stderr, "Credential formatted "
- "incorrectly: %s\n",
- temp_val ? temp_val : "(null)");
+ "incorrectly\n");
break;
}
}
--

View File

@ -0,0 +1,65 @@
From 9ad46fc480818e48868ba841a8a1eed9a74e7294 Mon Sep 17 00:00:00 2001
From: Paulo Alcantara <pc@cjr.nz>
Date: Thu, 6 May 2021 16:25:13 -0300
Subject: [PATCH] mount.cifs: fix crash when mount point does not exist
@mountpointp is initially set to a statically allocated string in
main(), and if we fail to update it in acquire_mountpoint(), make sure
to set it to NULL and avoid freeing it at mount_exit.
This fixes the following crash
$ mount.cifs //srv/share /mnt/foo/bar -o ...
Couldn't chdir to /mnt/foo/bar: No such file or directory
munmap_chunk(): invalid pointer
Aborted
Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Aurelien Aptel <aaptel@suse.com>
---
mount.cifs.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/mount.cifs.c b/mount.cifs.c
index 7f898bb..84274c9 100644
--- a/mount.cifs.c
+++ b/mount.cifs.c
@@ -1996,9 +1996,9 @@ acquire_mountpoint(char **mountpointp)
*/
realuid = getuid();
if (realuid == 0) {
- dacrc = toggle_dac_capability(0, 1);
- if (dacrc)
- return dacrc;
+ rc = toggle_dac_capability(0, 1);
+ if (rc)
+ goto out;
} else {
oldfsuid = setfsuid(realuid);
oldfsgid = setfsgid(getgid());
@@ -2019,7 +2019,6 @@ acquire_mountpoint(char **mountpointp)
rc = EX_SYSERR;
}
- *mountpointp = mountpoint;
restore_privs:
if (realuid == 0) {
dacrc = toggle_dac_capability(0, 0);
@@ -2030,9 +2029,13 @@ restore_privs:
gid_t __attribute__((unused)) gignore = setfsgid(oldfsgid);
}
- if (rc)
+out:
+ if (rc) {
free(mountpoint);
+ mountpoint = NULL;
+ }
+ *mountpointp = mountpoint;
return rc;
}
--
2.33.0

View File

@ -0,0 +1,493 @@
From 7f9711dd902a239c499682015d708f73ec884af2 Mon Sep 17 00:00:00 2001
From: Aurelien Aptel <aaptel@suse.com>
Date: Wed, 21 Apr 2021 16:22:15 +0200
Subject: [PATCH] cifs.upcall: fix regression in kerberos mount
The fix for CVE-2021-20208 in commit e461afd ("cifs.upcall: try to use
container ipc/uts/net/pid/mnt/user namespaces") introduced a
regression for kerberos mounts when cifs-utils is built with
libcap-ng. It makes mount fail with ENOKEY "Required key not
available".
Current state:
mount.cifs
'---> mount() ---> kernel
negprot, session setup (need security blob for krb)
request_key("cifs.spnego", payload="pid=%d;username=...")
upcall
/sbin/request-key <--------------'
reads /etc/request-keys.conf
dispatch cifs.spnego request
calls /usr/sbin/cifs.upcall <key id>
- drop privileges (capabilities)
- fetch keyid
- parse payload
- switch to mount.cifs namespaces
- call krb5_xxx() funcs
- generate security blob
- set key value to security blob
'-----------------------------------> kernel
put blob in session setup packet
continue auth
open tcon
get share root
setup superblock
mount.cifs mount() returns <-----------'
By the time cifs.upcall tries to switch to namespaces, enough
capabilities have dropped in trim_capabilities() that it makes setns()
fail with EPERM.
setns() requires CAP_SYS_ADMIN.
With libcap trim_capabilities() is a no-op.
This fix:
- moves the namespace switch earlier so that operations like
setgroups(), setgid(), scanning of pid environment, ... happens in the
contained namespaces.
- moves trim_capabilities() after the namespace switch
- moves the string processing to decode the key request payload in a
child process with minimum capabilities. the decoded data is shared
with the parent process via shared memory obtained with mmap().
Fixes: e461afd ("cifs.upcall: try to use container ipc/uts/net/pid/mnt/user namespaces")
Signed-off-by: Aurelien Aptel <aaptel@suse.com>
---
cifs.upcall.c | 214 ++++++++++++++++++++++++++++++++------------------
1 file changed, 139 insertions(+), 75 deletions(-)
diff --git a/cifs.upcall.c b/cifs.upcall.c
index e413934..ad04301 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -52,6 +52,9 @@
#include <stdbool.h>
#include <errno.h>
#include <sched.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include "data_blob.h"
#include "spnego.h"
@@ -787,6 +790,25 @@ handle_krb5_mech(const char *oid, const char *host, DATA_BLOB * secblob,
return retval;
}
+
+
+struct decoded_args {
+ int ver;
+ char hostname[NI_MAXHOST + 1];
+ char ip[NI_MAXHOST + 1];
+
+/* Max user name length. */
+#define MAX_USERNAME_SIZE 256
+ char username[MAX_USERNAME_SIZE + 1];
+
+ uid_t uid;
+ uid_t creduid;
+ pid_t pid;
+ sectype_t sec;
+
+/*
+ * Flags to keep track of what was provided
+ */
#define DKD_HAVE_HOSTNAME 0x1
#define DKD_HAVE_VERSION 0x2
#define DKD_HAVE_SEC 0x4
@@ -796,23 +818,13 @@ handle_krb5_mech(const char *oid, const char *host, DATA_BLOB * secblob,
#define DKD_HAVE_CREDUID 0x40
#define DKD_HAVE_USERNAME 0x80
#define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC)
-
-struct decoded_args {
- int ver;
- char *hostname;
- char *ip;
- char *username;
- uid_t uid;
- uid_t creduid;
- pid_t pid;
- sectype_t sec;
+ int have;
};
static unsigned int
-decode_key_description(const char *desc, struct decoded_args *arg)
+__decode_key_description(const char *desc, struct decoded_args *arg)
{
- int len;
- int retval = 0;
+ size_t len;
char *pos;
const char *tkn = desc;
@@ -826,13 +838,13 @@ decode_key_description(const char *desc, struct decoded_args *arg)
len = pos - tkn;
len -= 5;
- free(arg->hostname);
- arg->hostname = strndup(tkn + 5, len);
- if (arg->hostname == NULL) {
- syslog(LOG_ERR, "Unable to allocate memory");
+ if (len > sizeof(arg->hostname)-1) {
+ syslog(LOG_ERR, "host= value too long for buffer");
return 1;
}
- retval |= DKD_HAVE_HOSTNAME;
+ memset(arg->hostname, 0, sizeof(arg->hostname));
+ strncpy(arg->hostname, tkn + 5, len);
+ arg->have |= DKD_HAVE_HOSTNAME;
syslog(LOG_DEBUG, "host=%s", arg->hostname);
} else if (!strncmp(tkn, "ip4=", 4) || !strncmp(tkn, "ip6=", 4)) {
if (pos == NULL)
@@ -841,13 +853,13 @@ decode_key_description(const char *desc, struct decoded_args *arg)
len = pos - tkn;
len -= 4;
- free(arg->ip);
- arg->ip = strndup(tkn + 4, len);
- if (arg->ip == NULL) {
- syslog(LOG_ERR, "Unable to allocate memory");
+ if (len > sizeof(arg->ip)-1) {
+ syslog(LOG_ERR, "ip[46]= value too long for buffer");
return 1;
}
- retval |= DKD_HAVE_IP;
+ memset(arg->ip, 0, sizeof(arg->ip));
+ strncpy(arg->ip, tkn + 4, len);
+ arg->have |= DKD_HAVE_IP;
syslog(LOG_DEBUG, "ip=%s", arg->ip);
} else if (strncmp(tkn, "user=", 5) == 0) {
if (pos == NULL)
@@ -856,13 +868,13 @@ decode_key_description(const char *desc, struct decoded_args *arg)
len = pos - tkn;
len -= 5;
- free(arg->username);
- arg->username = strndup(tkn + 5, len);
- if (arg->username == NULL) {
- syslog(LOG_ERR, "Unable to allocate memory");
+ if (len > sizeof(arg->username)-1) {
+ syslog(LOG_ERR, "user= value too long for buffer");
return 1;
}
- retval |= DKD_HAVE_USERNAME;
+ memset(arg->username, 0, sizeof(arg->username));
+ strncpy(arg->username, tkn + 5, len);
+ arg->have |= DKD_HAVE_USERNAME;
syslog(LOG_DEBUG, "user=%s", arg->username);
} else if (strncmp(tkn, "pid=", 4) == 0) {
errno = 0;
@@ -873,13 +885,13 @@ decode_key_description(const char *desc, struct decoded_args *arg)
return 1;
}
syslog(LOG_DEBUG, "pid=%u", arg->pid);
- retval |= DKD_HAVE_PID;
+ arg->have |= DKD_HAVE_PID;
} else if (strncmp(tkn, "sec=", 4) == 0) {
if (strncmp(tkn + 4, "krb5", 4) == 0) {
- retval |= DKD_HAVE_SEC;
+ arg->have |= DKD_HAVE_SEC;
arg->sec = KRB5;
} else if (strncmp(tkn + 4, "mskrb5", 6) == 0) {
- retval |= DKD_HAVE_SEC;
+ arg->have |= DKD_HAVE_SEC;
arg->sec = MS_KRB5;
}
syslog(LOG_DEBUG, "sec=%d", arg->sec);
@@ -891,7 +903,7 @@ decode_key_description(const char *desc, struct decoded_args *arg)
strerror(errno));
return 1;
}
- retval |= DKD_HAVE_UID;
+ arg->have |= DKD_HAVE_UID;
syslog(LOG_DEBUG, "uid=%u", arg->uid);
} else if (strncmp(tkn, "creduid=", 8) == 0) {
errno = 0;
@@ -901,7 +913,7 @@ decode_key_description(const char *desc, struct decoded_args *arg)
strerror(errno));
return 1;
}
- retval |= DKD_HAVE_CREDUID;
+ arg->have |= DKD_HAVE_CREDUID;
syslog(LOG_DEBUG, "creduid=%u", arg->creduid);
} else if (strncmp(tkn, "ver=", 4) == 0) { /* if version */
errno = 0;
@@ -911,14 +923,56 @@ decode_key_description(const char *desc, struct decoded_args *arg)
strerror(errno));
return 1;
}
- retval |= DKD_HAVE_VERSION;
+ arg->have |= DKD_HAVE_VERSION;
syslog(LOG_DEBUG, "ver=%d", arg->ver);
}
if (pos == NULL)
break;
tkn = pos + 1;
} while (tkn);
- return retval;
+ return 0;
+}
+
+static unsigned int
+decode_key_description(const char *desc, struct decoded_args **arg)
+{
+ pid_t pid;
+ pid_t rc;
+ int status;
+
+ /*
+ * Do all the decoding/string processing in a child process
+ * with low privileges.
+ */
+
+ *arg = mmap(NULL, sizeof(struct decoded_args), PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+ if (*arg == MAP_FAILED) {
+ syslog(LOG_ERR, "%s: mmap failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ syslog(LOG_ERR, "%s: fork failed: %s", __func__, strerror(errno));
+ munmap(*arg, sizeof(struct decoded_args));
+ *arg = NULL;
+ return -1;
+ }
+ if (pid == 0) {
+ /* do the parsing in child */
+ drop_all_capabilities();
+ exit(__decode_key_description(desc, *arg));
+ }
+
+ rc = waitpid(pid, &status, 0);
+ if (rc < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ munmap(*arg, sizeof(struct decoded_args));
+ *arg = NULL;
+ return 1;
+ }
+
+ return 0;
}
static int setup_key(const key_serial_t key, const void *data, size_t datalen)
@@ -1098,7 +1152,7 @@ int main(const int argc, char *const argv[])
bool try_dns = false, legacy_uid = false , env_probe = true;
char *buf;
char hostbuf[NI_MAXHOST], *host;
- struct decoded_args arg;
+ struct decoded_args *arg = NULL;
const char *oid;
uid_t uid;
char *keytab_name = NULL;
@@ -1109,7 +1163,6 @@ int main(const int argc, char *const argv[])
const char *key_descr = NULL;
hostbuf[0] = '\0';
- memset(&arg, 0, sizeof(arg));
openlog(prog, 0, LOG_DAEMON);
@@ -1150,9 +1203,6 @@ int main(const int argc, char *const argv[])
}
}
- if (trim_capabilities(env_probe))
- goto out;
-
/* is there a key? */
if (argc <= optind) {
usage();
@@ -1178,6 +1228,10 @@ int main(const int argc, char *const argv[])
syslog(LOG_DEBUG, "key description: %s", buf);
+ /*
+ * If we are requested a simple DNS query, do it and exit
+ */
+
if (strncmp(buf, "cifs.resolver", sizeof("cifs.resolver") - 1) == 0)
key_descr = ".cifs.resolver";
else if (strncmp(buf, "dns_resolver", sizeof("dns_resolver") - 1) == 0)
@@ -1187,33 +1241,42 @@ int main(const int argc, char *const argv[])
goto out;
}
- have = decode_key_description(buf, &arg);
+ /*
+ * Otherwise, it's a spnego key request
+ */
+
+ rc = decode_key_description(buf, &arg);
free(buf);
- if ((have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
+ if (rc) {
+ syslog(LOG_ERR, "failed to decode key description");
+ goto out;
+ }
+
+ if ((arg->have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
syslog(LOG_ERR, "unable to get necessary params from key "
"description (0x%x)", have);
rc = 1;
goto out;
}
- if (arg.ver > CIFS_SPNEGO_UPCALL_VERSION) {
+ if (arg->ver > CIFS_SPNEGO_UPCALL_VERSION) {
syslog(LOG_ERR, "incompatible kernel upcall version: 0x%x",
- arg.ver);
+ arg->ver);
rc = 1;
goto out;
}
- if (strlen(arg.hostname) >= NI_MAXHOST) {
+ if (strlen(arg->hostname) >= NI_MAXHOST) {
syslog(LOG_ERR, "hostname provided by kernel is too long");
rc = 1;
goto out;
}
- if (!legacy_uid && (have & DKD_HAVE_CREDUID))
- uid = arg.creduid;
- else if (have & DKD_HAVE_UID)
- uid = arg.uid;
+ if (!legacy_uid && (arg->have & DKD_HAVE_CREDUID))
+ uid = arg->creduid;
+ else if (arg->have & DKD_HAVE_UID)
+ uid = arg->uid;
else {
/* no uid= or creduid= parm -- something is wrong */
syslog(LOG_ERR, "No uid= or creduid= parm specified");
@@ -1221,6 +1284,21 @@ int main(const int argc, char *const argv[])
goto out;
}
+ /*
+ * Change to the process's namespace. This means that things will work
+ * acceptably in containers, because we'll be looking at the correct
+ * filesystem and have the correct network configuration.
+ */
+ rc = switch_to_process_ns(arg->pid);
+ if (rc == -1) {
+ syslog(LOG_ERR, "unable to switch to process namespace: %s", strerror(errno));
+ rc = 1;
+ goto out;
+ }
+
+ if (trim_capabilities(env_probe))
+ goto out;
+
/*
* The kernel doesn't pass down the gid, so we resort here to scraping
* one out of the passwd nss db. Note that this might not reflect the
@@ -1266,20 +1344,7 @@ int main(const int argc, char *const argv[])
* look at the environ file.
*/
env_cachename =
- get_cachename_from_process_env(env_probe ? arg.pid : 0);
-
- /*
- * Change to the process's namespace. This means that things will work
- * acceptably in containers, because we'll be looking at the correct
- * filesystem and have the correct network configuration.
- */
- rc = switch_to_process_ns(arg.pid);
- if (rc == -1) {
- syslog(LOG_ERR, "unable to switch to process namespace: %s",
- strerror(errno));
- rc = 1;
- goto out;
- }
+ get_cachename_from_process_env(env_probe ? arg->pid : 0);
rc = setuid(uid);
if (rc == -1) {
@@ -1301,18 +1366,18 @@ int main(const int argc, char *const argv[])
ccache = get_existing_cc(env_cachename);
/* Couldn't find credcache? Try to use keytab */
- if (ccache == NULL && arg.username != NULL)
- ccache = init_cc_from_keytab(keytab_name, arg.username);
+ if (ccache == NULL && arg->username[0] != '\0')
+ ccache = init_cc_from_keytab(keytab_name, arg->username);
if (ccache == NULL) {
rc = 1;
goto out;
}
- host = arg.hostname;
+ host = arg->hostname;
// do mech specific authorization
- switch (arg.sec) {
+ switch (arg->sec) {
case MS_KRB5:
case KRB5:
/*
@@ -1328,7 +1393,7 @@ int main(const int argc, char *const argv[])
* TRY only:
* cifs/bar.example.com@REALM
*/
- if (arg.sec == MS_KRB5)
+ if (arg->sec == MS_KRB5)
oid = OID_KERBEROS5_OLD;
else
oid = OID_KERBEROS5;
@@ -1385,10 +1450,10 @@ retry_new_hostname:
break;
}
- if (!try_dns || !(have & DKD_HAVE_IP))
+ if (!try_dns || !(arg->have & DKD_HAVE_IP))
break;
- rc = ip_to_fqdn(arg.ip, hostbuf, sizeof(hostbuf));
+ rc = ip_to_fqdn(arg->ip, hostbuf, sizeof(hostbuf));
if (rc)
break;
@@ -1396,7 +1461,7 @@ retry_new_hostname:
host = hostbuf;
goto retry_new_hostname;
default:
- syslog(LOG_ERR, "sectype: %d is not implemented", arg.sec);
+ syslog(LOG_ERR, "sectype: %d is not implemented", arg->sec);
rc = 1;
break;
}
@@ -1414,7 +1479,7 @@ retry_new_hostname:
rc = 1;
goto out;
}
- keydata->version = arg.ver;
+ keydata->version = arg->ver;
keydata->flags = 0;
keydata->sesskey_len = sess_key.length;
keydata->secblob_len = secblob.length;
@@ -1440,11 +1505,10 @@ out:
krb5_cc_close(context, ccache);
if (context)
krb5_free_context(context);
- free(arg.hostname);
- free(arg.ip);
- free(arg.username);
free(keydata);
free(env_cachename);
+ if (arg)
+ munmap(arg, sizeof(*arg));
syslog(LOG_DEBUG, "Exit status %ld", rc);
return rc;
}
--
2.33.0

View File

@ -1,15 +1,25 @@
Name: cifs-utils
Version: 6.10
Release: 1
Release: 6
Summary: Utilities for doing and managing mounts of the Linux CIFS filesystem
License: GPLv3+
URL: http://linux-cifs.samba.org/cifs-utils/
Source0: https://download.samba.org/pub/linux-cifs/cifs-utils/%{name}-%{version}.tar.bz2
Patch0: 0001-CVE-2020-14342-mount.cifs-fix-shell-command-injectio.patch
Patch0: 0000-Add-missing-position-handling-to-mount-parameters-gi.patch
Patch1: 0001-CVE-2020-14342-mount.cifs-fix-shell-command-injectio.patch
Patch2: 0002-CVE-2021-20208.patch
Patch3: 0003-cifs-utils-fix-probabilistic-compiling-error.patch
Patch4: 0004-mount.cifs-fix-max-buffer-size-when-parsing-snapshot.patch
Patch5: 0005-cifs.upcall-update-the-cap-bounding-set-only-when-CA.patch
Patch6: 0006-mount.cifs-update-the-cap-bounding-set-only-when-CAP.patch
Patch7: 0007-CVE-2022-27239.patch
Patch8: 0008-CVE-2022-29869.patch
Patch9: 0009-mount.cifs-fix-crash-when-mount-point-does-not-exist.patch
Patch10: 0010-cifs.upcall-fix-regression-in-kerberos-mount.patch
BuildRequires: python3-docutils libcap-ng-devel libtalloc-devel krb5-devel keyutils-libs-devel autoconf
BuildRequires: automake libwbclient-devel pam-devel git python3-samba pkg-config fdupes gcc
BuildRequires: automake libwbclient-devel pam-devel python3-samba pkg-config fdupes gcc
Provides: pam_cifscreds
Obsoletes: pam_cifscreds
Requires: keyutils
@ -40,7 +50,7 @@ Requires: man
This contains man files for the using of cifs-utils.
%prep
%autosetup -Sgit -n %{name}-%{version}
%autosetup -n %{name}-%{version} -p1
%build
autoreconf -i
@ -79,6 +89,21 @@ install -m 644 contrib/request-key.d/cifs.spnego.conf %{buildroot}%{_sysconfdir}
%{_mandir}/man8/*
%changelog
* Thu Mar 30 2023 Zhiqiang Liu <liuzhiqiang26@huawei.com> - 6.10-6
- backport some patches
* Thu May 5 2022 yanglongkang <yanglongkang@h-partners.com> - 6.10-5
- Fix CVE-2022-27239 and CVE-2022-29869
* Tue Nov 23 2021 konglidong <konglidong@uniontech.com> - 6.10-4
- sync patch from Upstream for fix capng apply for libcap-ng-0.8.1
* Tue Aug 17 2021 haowenchao <haowenchao@huawei.com> - 6.10-3
- DESC: delete -Sgit from %autosetup, and delete BuildRequires git
* Sat May 8 2021 yanglongkang <yanglongkang@huawei.com> - 6.10-2
- Fix CVE-2021-20208
* Thu Sep 24 2020 volcanodragon <linfeilong@huawei.com> - 6.10-1
- Type:CVE
- ID:CVE-2020-14342