!60 Fix CVE-2022-24765
From: @fly_fzc Reviewed-by: @overweight Signed-off-by: @overweight
This commit is contained in:
commit
70c380e324
118
backport-0001-CVE-2022-24765.patch
Normal file
118
backport-0001-CVE-2022-24765.patch
Normal file
@ -0,0 +1,118 @@
|
||||
From fdcad5a53e14bd397e4fa323e7fd0c3bf16dd373 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
Date: Wed, 23 Mar 2022 23:00:41 +0100
|
||||
Subject: [PATCH] Fix `GIT_CEILING_DIRECTORIES` with `C:\` and the likes
|
||||
|
||||
When determining the length of the longest ancestor of a given path with
|
||||
respect to to e.g. `GIT_CEILING_DIRECTORIES`, we special-case the root
|
||||
directory by returning 0 (i.e. we pretend that the path `/` does not end
|
||||
in a slash by virtually stripping it).
|
||||
|
||||
That is the correct behavior because when normalizing paths, the root
|
||||
directory is special: all other directory paths have their trailing
|
||||
slash stripped, but not the root directory's path (because it would
|
||||
become the empty string, which is not a legal path).
|
||||
|
||||
However, this special-casing of the root directory in
|
||||
`longest_ancestor_length()` completely forgets about Windows-style root
|
||||
directories, e.g. `C:\`. These _also_ get normalized with a trailing
|
||||
slash (because `C:` would actually refer to the current directory on
|
||||
that drive, not necessarily to its root directory).
|
||||
|
||||
In fc56c7b34b (mingw: accomodate t0060-path-utils for MSYS2,
|
||||
2016-01-27), we almost got it right. We noticed that
|
||||
`longest_ancestor_length()` expects a slash _after_ the matched prefix,
|
||||
and if the prefix already ends in a slash, the normalized path won't
|
||||
ever match and -1 is returned.
|
||||
|
||||
But then that commit went astray: The correct fix is not to adjust the
|
||||
_tests_ to expect an incorrect -1 when that function is fed a prefix
|
||||
that ends in a slash, but instead to treat such a prefix as if the
|
||||
trailing slash had been removed.
|
||||
|
||||
Likewise, that function needs to handle the case where it is fed a path
|
||||
that ends in a slash (not only a prefix that ends in a slash): if it
|
||||
matches the prefix (plus trailing slash), we still need to verify that
|
||||
the path does not end there, otherwise the prefix is not actually an
|
||||
ancestor of the path but identical to it (and we need to return -1 in
|
||||
that case).
|
||||
|
||||
With these two adjustments, we no longer need to play games in t0060
|
||||
where we only add `$rootoff` if the passed prefix is different from the
|
||||
MSYS2 pseudo root, instead we also add it for the MSYS2 pseudo root
|
||||
itself. We do have to be careful to skip that logic entirely for Windows
|
||||
paths, though, because they do are not subject to that MSYS2 pseudo root
|
||||
treatment.
|
||||
|
||||
This patch fixes the scenario where a user has set
|
||||
`GIT_CEILING_DIRECTORIES=C:\`, which would be ignored otherwise.
|
||||
|
||||
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
---
|
||||
path.c | 14 +++++++++-----
|
||||
t/t0060-path-utils.sh | 20 ++++++++++++++------
|
||||
2 files changed, 23 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/path.c b/path.c
|
||||
index 7b385e5eb28227..853e7165c89fd0 100644
|
||||
--- a/path.c
|
||||
+++ b/path.c
|
||||
@@ -1218,11 +1218,15 @@ int longest_ancestor_length(const char *path, struct string_list *prefixes)
|
||||
const char *ceil = prefixes->items[i].string;
|
||||
int len = strlen(ceil);
|
||||
|
||||
- if (len == 1 && ceil[0] == '/')
|
||||
- len = 0; /* root matches anything, with length 0 */
|
||||
- else if (!strncmp(path, ceil, len) && path[len] == '/')
|
||||
- ; /* match of length len */
|
||||
- else
|
||||
+ /*
|
||||
+ * For root directories (`/`, `C:/`, `//server/share/`)
|
||||
+ * adjust the length to exclude the trailing slash.
|
||||
+ */
|
||||
+ if (len > 0 && ceil[len - 1] == '/')
|
||||
+ len--;
|
||||
+
|
||||
+ if (strncmp(path, ceil, len) ||
|
||||
+ path[len] != '/' || !path[len + 1])
|
||||
continue; /* no match */
|
||||
|
||||
if (len > max_len)
|
||||
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
|
||||
index 56db5c8abab62e..f538264cdd3382 100755
|
||||
--- a/t/t0060-path-utils.sh
|
||||
+++ b/t/t0060-path-utils.sh
|
||||
@@ -55,12 +55,15 @@ fi
|
||||
ancestor() {
|
||||
# We do some math with the expected ancestor length.
|
||||
expected=$3
|
||||
- if test -n "$rootoff" && test "x$expected" != x-1; then
|
||||
- expected=$(($expected-$rootslash))
|
||||
- test $expected -lt 0 ||
|
||||
- expected=$(($expected+$rootoff))
|
||||
- fi
|
||||
- test_expect_success "longest ancestor: $1 $2 => $expected" \
|
||||
+ case "$rootoff,$expected,$2" in
|
||||
+ *,*,//*) ;; # leave UNC paths alone
|
||||
+ [0-9]*,[0-9]*,/*)
|
||||
+ # On Windows, expect MSYS2 pseudo root translation for
|
||||
+ # Unix-style absolute paths
|
||||
+ expected=$(($expected-$rootslash+$rootoff))
|
||||
+ ;;
|
||||
+ esac
|
||||
+ test_expect_success $4 "longest ancestor: $1 $2 => $expected" \
|
||||
"actual=\$(test-tool path-utils longest_ancestor_length '$1' '$2') &&
|
||||
test \"\$actual\" = '$expected'"
|
||||
}
|
||||
@@ -156,6 +159,11 @@ ancestor /foo/bar /foo 4
|
||||
ancestor /foo/bar /foo:/bar 4
|
||||
ancestor /foo/bar /bar -1
|
||||
|
||||
+# Windows-specific: DOS drives, network shares
|
||||
+ancestor C:/Users/me C:/ 2 MINGW
|
||||
+ancestor D:/Users/me C:/ -1 MINGW
|
||||
+ancestor //server/share/my-directory //server/share/ 14 MINGW
|
||||
+
|
||||
test_expect_success 'strip_path_suffix' '
|
||||
test c:/msysgit = $(test-tool path-utils strip_path_suffix \
|
||||
c:/msysgit/libexec//git-core libexec/git-core)
|
||||
187
backport-0002-CVE-2022-24765.patch
Normal file
187
backport-0002-CVE-2022-24765.patch
Normal file
@ -0,0 +1,187 @@
|
||||
From 8959555cee7ec045958f9b6dd62e541affb7e7d9 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
Date: Wed, 2 Mar 2022 12:23:04 +0100
|
||||
Subject: [PATCH] setup_git_directory(): add an owner check for the top-level
|
||||
directory
|
||||
|
||||
It poses a security risk to search for a git directory outside of the
|
||||
directories owned by the current user.
|
||||
|
||||
For example, it is common e.g. in computer pools of educational
|
||||
institutes to have a "scratch" space: a mounted disk with plenty of
|
||||
space that is regularly swiped where any authenticated user can create
|
||||
a directory to do their work. Merely navigating to such a space with a
|
||||
Git-enabled `PS1` when there is a maliciously-crafted `/scratch/.git/`
|
||||
can lead to a compromised account.
|
||||
|
||||
The same holds true in multi-user setups running Windows, as `C:\` is
|
||||
writable to every authenticated user by default.
|
||||
|
||||
To plug this vulnerability, we stop Git from accepting top-level
|
||||
directories owned by someone other than the current user. We avoid
|
||||
looking at the ownership of each and every directories between the
|
||||
current and the top-level one (if there are any between) to avoid
|
||||
introducing a performance bottleneck.
|
||||
|
||||
This new default behavior is obviously incompatible with the concept of
|
||||
shared repositories, where we expect the top-level directory to be owned
|
||||
by only one of its legitimate users. To re-enable that use case, we add
|
||||
support for adding exceptions from the new default behavior via the
|
||||
config setting `safe.directory`.
|
||||
|
||||
The `safe.directory` config setting is only respected in the system and
|
||||
global configs, not from repository configs or via the command-line, and
|
||||
can have multiple values to allow for multiple shared repositories.
|
||||
|
||||
We are particularly careful to provide a helpful message to any user
|
||||
trying to use a shared repository.
|
||||
|
||||
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
---
|
||||
Documentation/config.txt | 2 ++
|
||||
Documentation/config/safe.txt | 21 +++++++++++++
|
||||
setup.c | 57 ++++++++++++++++++++++++++++++++++-
|
||||
3 files changed, 79 insertions(+), 1 deletion(-)
|
||||
create mode 100644 Documentation/config/safe.txt
|
||||
|
||||
diff --git a/Documentation/config.txt b/Documentation/config.txt
|
||||
index 6ba50b1104aa79..34e6d477d669f1 100644
|
||||
--- a/Documentation/config.txt
|
||||
+++ b/Documentation/config.txt
|
||||
@@ -438,6 +438,8 @@ include::config/rerere.txt[]
|
||||
|
||||
include::config/reset.txt[]
|
||||
|
||||
+include::config/safe.txt[]
|
||||
+
|
||||
include::config/sendemail.txt[]
|
||||
|
||||
include::config/sequencer.txt[]
|
||||
diff --git a/Documentation/config/safe.txt b/Documentation/config/safe.txt
|
||||
new file mode 100644
|
||||
index 00000000000000..63597b2df8f80f
|
||||
--- /dev/null
|
||||
+++ b/Documentation/config/safe.txt
|
||||
@@ -0,0 +1,21 @@
|
||||
+safe.directory::
|
||||
+ These config entries specify Git-tracked directories that are
|
||||
+ considered safe even if they are owned by someone other than the
|
||||
+ current user. By default, Git will refuse to even parse a Git
|
||||
+ config of a repository owned by someone else, let alone run its
|
||||
+ hooks, and this config setting allows users to specify exceptions,
|
||||
+ e.g. for intentionally shared repositories (see the `--shared`
|
||||
+ option in linkgit:git-init[1]).
|
||||
++
|
||||
+This is a multi-valued setting, i.e. you can add more than one directory
|
||||
+via `git config --add`. To reset the list of safe directories (e.g. to
|
||||
+override any such directories specified in the system config), add a
|
||||
+`safe.directory` entry with an empty value.
|
||||
++
|
||||
+This config setting is only respected when specified in a system or global
|
||||
+config, not when it is specified in a repository config or via the command
|
||||
+line option `-c safe.directory=<path>`.
|
||||
++
|
||||
+The value of this setting is interpolated, i.e. `~/<path>` expands to a
|
||||
+path relative to the home directory and `%(prefix)/<path>` expands to a
|
||||
+path relative to Git's (runtime) prefix.
|
||||
diff --git a/setup.c b/setup.c
|
||||
index c04cd25a30dfe0..95d5b00940a87e 100644
|
||||
--- a/setup.c
|
||||
+++ b/setup.c
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "string-list.h"
|
||||
#include "chdir-notify.h"
|
||||
#include "promisor-remote.h"
|
||||
+#include "quote.h"
|
||||
|
||||
static int inside_git_dir = -1;
|
||||
static int inside_work_tree = -1;
|
||||
@@ -1024,6 +1025,42 @@ static int canonicalize_ceiling_entry(struct string_list_item *item,
|
||||
}
|
||||
}
|
||||
|
||||
+struct safe_directory_data {
|
||||
+ const char *path;
|
||||
+ int is_safe;
|
||||
+};
|
||||
+
|
||||
+static int safe_directory_cb(const char *key, const char *value, void *d)
|
||||
+{
|
||||
+ struct safe_directory_data *data = d;
|
||||
+
|
||||
+ if (!value || !*value)
|
||||
+ data->is_safe = 0;
|
||||
+ else {
|
||||
+ const char *interpolated = NULL;
|
||||
+
|
||||
+ if (!git_config_pathname(&interpolated, key, value) &&
|
||||
+ !fspathcmp(data->path, interpolated ? interpolated : value))
|
||||
+ data->is_safe = 1;
|
||||
+
|
||||
+ free((char *)interpolated);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ensure_valid_ownership(const char *path)
|
||||
+{
|
||||
+ struct safe_directory_data data = { .path = path };
|
||||
+
|
||||
+ if (is_path_owned_by_current_user(path))
|
||||
+ return 1;
|
||||
+
|
||||
+ read_very_early_config(safe_directory_cb, &data);
|
||||
+
|
||||
+ return data.is_safe;
|
||||
+}
|
||||
+
|
||||
enum discovery_result {
|
||||
GIT_DIR_NONE = 0,
|
||||
GIT_DIR_EXPLICIT,
|
||||
@@ -1032,7 +1069,8 @@ enum discovery_result {
|
||||
/* these are errors */
|
||||
GIT_DIR_HIT_CEILING = -1,
|
||||
GIT_DIR_HIT_MOUNT_POINT = -2,
|
||||
- GIT_DIR_INVALID_GITFILE = -3
|
||||
+ GIT_DIR_INVALID_GITFILE = -3,
|
||||
+ GIT_DIR_INVALID_OWNERSHIP = -4
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1122,11 +1160,15 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
|
||||
}
|
||||
strbuf_setlen(dir, offset);
|
||||
if (gitdirenv) {
|
||||
+ if (!ensure_valid_ownership(dir->buf))
|
||||
+ return GIT_DIR_INVALID_OWNERSHIP;
|
||||
strbuf_addstr(gitdir, gitdirenv);
|
||||
return GIT_DIR_DISCOVERED;
|
||||
}
|
||||
|
||||
if (is_git_directory(dir->buf)) {
|
||||
+ if (!ensure_valid_ownership(dir->buf))
|
||||
+ return GIT_DIR_INVALID_OWNERSHIP;
|
||||
strbuf_addstr(gitdir, ".");
|
||||
return GIT_DIR_BARE;
|
||||
}
|
||||
@@ -1253,6 +1295,19 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||
dir.buf);
|
||||
*nongit_ok = 1;
|
||||
break;
|
||||
+ case GIT_DIR_INVALID_OWNERSHIP:
|
||||
+ if (!nongit_ok) {
|
||||
+ struct strbuf quoted = STRBUF_INIT;
|
||||
+
|
||||
+ sq_quote_buf_pretty("ed, dir.buf);
|
||||
+ die(_("unsafe repository ('%s' is owned by someone else)\n"
|
||||
+ "To add an exception for this directory, call:\n"
|
||||
+ "\n"
|
||||
+ "\tgit config --global --add safe.directory %s"),
|
||||
+ dir.buf, quoted.buf);
|
||||
+ }
|
||||
+ *nongit_ok = 1;
|
||||
+ break;
|
||||
case GIT_DIR_NONE:
|
||||
/*
|
||||
* As a safeguard against setup_git_directory_gently_1 returning
|
||||
174
backport-0003-CVE-2022-24765.patch
Normal file
174
backport-0003-CVE-2022-24765.patch
Normal file
@ -0,0 +1,174 @@
|
||||
From bdc77d1d685be9c10b88abb281a42bc620548595 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
Date: Wed, 2 Mar 2022 11:06:24 +0100
|
||||
Subject: [PATCH] Add a function to determine whether a path is owned by the
|
||||
current user
|
||||
|
||||
This function will be used in the next commit to prevent
|
||||
`setup_git_directory()` from discovering a repository in a directory
|
||||
that is owned by someone other than the current user.
|
||||
|
||||
Note: We cannot simply use `st.st_uid` on Windows just like we do on
|
||||
Linux and other Unix-like platforms: according to
|
||||
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions
|
||||
this field is always zero on Windows (because Windows' idea of a user ID
|
||||
does not fit into a single numerical value). Therefore, we have to do
|
||||
something a little involved to replicate the same functionality there.
|
||||
|
||||
Also note: On Windows, a user's home directory is not actually owned by
|
||||
said user, but by the administrator. For all practical purposes, it is
|
||||
under the user's control, though, therefore we pretend that it is owned
|
||||
by the user.
|
||||
|
||||
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
---
|
||||
compat/mingw.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
compat/mingw.h | 7 ++++
|
||||
git-compat-util.h | 12 +++++++
|
||||
3 files changed, 106 insertions(+)
|
||||
|
||||
diff --git a/compat/mingw.c b/compat/mingw.c
|
||||
index abb4d26ce940f3..38ac35913df78e 100644
|
||||
--- a/compat/mingw.c
|
||||
+++ b/compat/mingw.c
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "../git-compat-util.h"
|
||||
#include "win32.h"
|
||||
+#include <aclapi.h>
|
||||
#include <conio.h>
|
||||
#include <wchar.h>
|
||||
#include "../strbuf.h"
|
||||
@@ -2601,6 +2602,92 @@ static void setup_windows_environment(void)
|
||||
}
|
||||
}
|
||||
|
||||
+static PSID get_current_user_sid(void)
|
||||
+{
|
||||
+ HANDLE token;
|
||||
+ DWORD len = 0;
|
||||
+ PSID result = NULL;
|
||||
+
|
||||
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
|
||||
+ TOKEN_USER *info = xmalloc((size_t)len);
|
||||
+ if (GetTokenInformation(token, TokenUser, info, len, &len)) {
|
||||
+ len = GetLengthSid(info->User.Sid);
|
||||
+ result = xmalloc(len);
|
||||
+ if (!CopySid(len, result, info->User.Sid)) {
|
||||
+ error(_("failed to copy SID (%ld)"),
|
||||
+ GetLastError());
|
||||
+ FREE_AND_NULL(result);
|
||||
+ }
|
||||
+ }
|
||||
+ FREE_AND_NULL(info);
|
||||
+ }
|
||||
+ CloseHandle(token);
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+int is_path_owned_by_current_sid(const char *path)
|
||||
+{
|
||||
+ WCHAR wpath[MAX_PATH];
|
||||
+ PSID sid = NULL;
|
||||
+ PSECURITY_DESCRIPTOR descriptor = NULL;
|
||||
+ DWORD err;
|
||||
+
|
||||
+ static wchar_t home[MAX_PATH];
|
||||
+
|
||||
+ int result = 0;
|
||||
+
|
||||
+ if (xutftowcs_path(wpath, path) < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * On Windows, the home directory is owned by the administrator, but for
|
||||
+ * all practical purposes, it belongs to the user. Do pretend that it is
|
||||
+ * owned by the user.
|
||||
+ */
|
||||
+ if (!*home) {
|
||||
+ DWORD size = ARRAY_SIZE(home);
|
||||
+ DWORD len = GetEnvironmentVariableW(L"HOME", home, size);
|
||||
+ if (!len || len > size)
|
||||
+ wcscpy(home, L"::N/A::");
|
||||
+ }
|
||||
+ if (!wcsicmp(wpath, home))
|
||||
+ return 1;
|
||||
+
|
||||
+ /* Get the owner SID */
|
||||
+ err = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
|
||||
+ OWNER_SECURITY_INFORMATION |
|
||||
+ DACL_SECURITY_INFORMATION,
|
||||
+ &sid, NULL, NULL, NULL, &descriptor);
|
||||
+
|
||||
+ if (err != ERROR_SUCCESS)
|
||||
+ error(_("failed to get owner for '%s' (%ld)"), path, err);
|
||||
+ else if (sid && IsValidSid(sid)) {
|
||||
+ /* Now, verify that the SID matches the current user's */
|
||||
+ static PSID current_user_sid;
|
||||
+
|
||||
+ if (!current_user_sid)
|
||||
+ current_user_sid = get_current_user_sid();
|
||||
+
|
||||
+ if (current_user_sid &&
|
||||
+ IsValidSid(current_user_sid) &&
|
||||
+ EqualSid(sid, current_user_sid))
|
||||
+ result = 1;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * We can release the security descriptor struct only now because `sid`
|
||||
+ * actually points into this struct.
|
||||
+ */
|
||||
+ if (descriptor)
|
||||
+ LocalFree(descriptor);
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
int is_valid_win32_path(const char *path, int allow_literal_nul)
|
||||
{
|
||||
const char *p = path;
|
||||
diff --git a/compat/mingw.h b/compat/mingw.h
|
||||
index af8eddd73edb2b..f6bab548f4cf44 100644
|
||||
--- a/compat/mingw.h
|
||||
+++ b/compat/mingw.h
|
||||
@@ -452,6 +452,13 @@ char *mingw_query_user_email(void);
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
+/**
|
||||
+ * Verifies that the specified path is owned by the user running the
|
||||
+ * current process.
|
||||
+ */
|
||||
+int is_path_owned_by_current_sid(const char *path);
|
||||
+#define is_path_owned_by_current_user is_path_owned_by_current_sid
|
||||
+
|
||||
/**
|
||||
* Verifies that the given path is a valid one on Windows.
|
||||
*
|
||||
diff --git a/git-compat-util.h b/git-compat-util.h
|
||||
index 3da9f975e27712..63ba89dd31d947 100644
|
||||
--- a/git-compat-util.h
|
||||
+++ b/git-compat-util.h
|
||||
@@ -392,6 +392,18 @@ static inline int git_offset_1st_component(const char *path)
|
||||
#define is_valid_path(path) 1
|
||||
#endif
|
||||
|
||||
+#ifndef is_path_owned_by_current_user
|
||||
+static inline int is_path_owned_by_current_uid(const char *path)
|
||||
+{
|
||||
+ struct stat st;
|
||||
+ if (lstat(path, &st))
|
||||
+ return 0;
|
||||
+ return st.st_uid == geteuid();
|
||||
+}
|
||||
+
|
||||
+#define is_path_owned_by_current_user is_path_owned_by_current_uid
|
||||
+#endif
|
||||
+
|
||||
#ifndef find_last_dir_sep
|
||||
static inline char *git_find_last_dir_sep(const char *path)
|
||||
{
|
||||
66
backport-0004-CVE-2022-24765.patch
Normal file
66
backport-0004-CVE-2022-24765.patch
Normal file
@ -0,0 +1,66 @@
|
||||
From 6e7ad1e4c22e7038975ba37c7413374fe566b064 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Carlo=20Marcelo=20Arenas=20Bel=C3=B3n?= <carenas@gmail.com>
|
||||
Date: Sat, 27 Nov 2021 10:15:32 +0000
|
||||
Subject: [PATCH] mingw: avoid fallback for {local,gm}time_r()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
mingw-w64's pthread_unistd.h had a bug that mistakenly (because there is
|
||||
no support for the *lockfile() functions required[1]) defined
|
||||
_POSIX_THREAD_SAFE_FUNCTIONS and that was being worked around since
|
||||
3ecd153a3b (compat/mingw: support MSys2-based MinGW build, 2016-01-14).
|
||||
|
||||
The bug was fixed in winphtreads, but as a side effect, leaves the
|
||||
reentrant functions from time.h no longer visible and therefore breaks
|
||||
the build.
|
||||
|
||||
Since the intention all along was to avoid using the fallback functions,
|
||||
formalize the use of POSIX by setting the corresponding feature flag and
|
||||
compile out the implementation for the fallback functions.
|
||||
|
||||
[1] https://unix.org/whitepapers/reentrant.html
|
||||
|
||||
Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
|
||||
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
|
||||
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||||
---
|
||||
compat/mingw.c | 2 ++
|
||||
git-compat-util.h | 4 +++-
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/compat/mingw.c b/compat/mingw.c
|
||||
index a43599841c6c6b..abb4d26ce940f3 100644
|
||||
--- a/compat/mingw.c
|
||||
+++ b/compat/mingw.c
|
||||
@@ -1060,6 +1060,7 @@ int pipe(int filedes[2])
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#ifndef __MINGW64__
|
||||
struct tm *gmtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
if (gmtime_s(result, timep) == 0)
|
||||
@@ -1073,6 +1074,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||
return result;
|
||||
return NULL;
|
||||
}
|
||||
+#endif
|
||||
|
||||
char *mingw_getcwd(char *pointer, int len)
|
||||
{
|
||||
diff --git a/git-compat-util.h b/git-compat-util.h
|
||||
index 7d3db43f11d049..3da9f975e27712 100644
|
||||
--- a/git-compat-util.h
|
||||
+++ b/git-compat-util.h
|
||||
@@ -127,7 +127,9 @@
|
||||
/* Approximation of the length of the decimal representation of this type. */
|
||||
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
|
||||
|
||||
-#if defined(__sun__)
|
||||
+#ifdef __MINGW64__
|
||||
+#define _POSIX_C_SOURCE 1
|
||||
+#elif defined(__sun__)
|
||||
/*
|
||||
* On Solaris, when _XOPEN_EXTENDED is set, its header file
|
||||
* forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
|
||||
48
backport-0005-CVE-2022-24765.patch
Normal file
48
backport-0005-CVE-2022-24765.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From bb50ec3cc300eeff3aba7a2bea145aabdb477d31 Mon Sep 17 00:00:00 2001
|
||||
From: Matheus Valadares <me@m28.io>
|
||||
Date: Wed, 13 Apr 2022 15:32:30 +0000
|
||||
Subject: [PATCH] setup: fix safe.directory key not being checked
|
||||
|
||||
It seems that nothing is ever checking to make sure the safe directories
|
||||
in the configs actually have the key safe.directory, so some unrelated
|
||||
config that has a value with a certain directory would also make it a
|
||||
safe directory.
|
||||
|
||||
Signed-off-by: Matheus Valadares <me@m28.io>
|
||||
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
|
||||
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||||
---
|
||||
setup.c | 3 +++
|
||||
t/t0033-safe-directory.sh | 5 +++++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
diff --git a/setup.c b/setup.c
|
||||
index 3c6ed17af9566a..4b9f073617c2c6 100644
|
||||
--- a/setup.c
|
||||
+++ b/setup.c
|
||||
@@ -1034,6 +1034,9 @@ static int safe_directory_cb(const char *key, const char *value, void *d)
|
||||
{
|
||||
struct safe_directory_data *data = d;
|
||||
|
||||
+ if (strcmp(key, "safe.directory"))
|
||||
+ return 0;
|
||||
+
|
||||
if (!value || !*value)
|
||||
data->is_safe = 0;
|
||||
else {
|
||||
diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh
|
||||
index 9380ff3d017096..6f33c0dfefaaf3 100755
|
||||
--- a/t/t0033-safe-directory.sh
|
||||
+++ b/t/t0033-safe-directory.sh
|
||||
@@ -21,6 +21,11 @@ test_expect_success 'safe.directory does not match' '
|
||||
expect_rejected_dir
|
||||
'
|
||||
|
||||
+test_expect_success 'path exist as different key' '
|
||||
+ git config --global foo.bar "$(pwd)" &&
|
||||
+ expect_rejected_dir
|
||||
+'
|
||||
+
|
||||
test_expect_success 'safe.directory matches' '
|
||||
git config --global --add safe.directory "$(pwd)" &&
|
||||
git status
|
||||
88
backport-0006-CVE-2022-24765.patch
Normal file
88
backport-0006-CVE-2022-24765.patch
Normal file
@ -0,0 +1,88 @@
|
||||
From 0f85c4a30b072a26d74af8bbf63cc8f6a5dfc1b8 Mon Sep 17 00:00:00 2001
|
||||
From: Derrick Stolee <derrickstolee@github.com>
|
||||
Date: Wed, 13 Apr 2022 15:32:31 +0000
|
||||
Subject: [PATCH] setup: opt-out of check with safe.directory=*
|
||||
|
||||
With the addition of the safe.directory in 8959555ce
|
||||
(setup_git_directory(): add an owner check for the top-level directory,
|
||||
2022-03-02) released in v2.35.2, we are receiving feedback from a
|
||||
variety of users about the feature.
|
||||
|
||||
Some users have a very large list of shared repositories and find it
|
||||
cumbersome to add this config for every one of them.
|
||||
|
||||
In a more difficult case, certain workflows involve running Git commands
|
||||
within containers. The container boundary prevents any global or system
|
||||
config from communicating `safe.directory` values from the host into the
|
||||
container. Further, the container almost always runs as a different user
|
||||
than the owner of the directory in the host.
|
||||
|
||||
To simplify the reactions necessary for these users, extend the
|
||||
definition of the safe.directory config value to include a possible '*'
|
||||
value. This value implies that all directories are safe, providing a
|
||||
single setting to opt-out of this protection.
|
||||
|
||||
Note that an empty assignment of safe.directory clears all previous
|
||||
values, and this is already the case with the "if (!value || !*value)"
|
||||
condition.
|
||||
|
||||
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
|
||||
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||||
---
|
||||
Documentation/config/safe.txt | 7 +++++++
|
||||
setup.c | 6 ++++--
|
||||
t/t0033-safe-directory.sh | 10 ++++++++++
|
||||
3 files changed, 21 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Documentation/config/safe.txt b/Documentation/config/safe.txt
|
||||
index 63597b2df8f80f..6d764fe0ccf3a8 100644
|
||||
--- a/Documentation/config/safe.txt
|
||||
+++ b/Documentation/config/safe.txt
|
||||
@@ -19,3 +19,10 @@ line option `-c safe.directory=<path>`.
|
||||
The value of this setting is interpolated, i.e. `~/<path>` expands to a
|
||||
path relative to the home directory and `%(prefix)/<path>` expands to a
|
||||
path relative to Git's (runtime) prefix.
|
||||
++
|
||||
+To completely opt-out of this security check, set `safe.directory` to the
|
||||
+string `*`. This will allow all repositories to be treated as if their
|
||||
+directory was listed in the `safe.directory` list. If `safe.directory=*`
|
||||
+is set in system config and you want to re-enable this protection, then
|
||||
+initialize your list with an empty value before listing the repositories
|
||||
+that you deem safe.
|
||||
diff --git a/setup.c b/setup.c
|
||||
index 4b9f073617c2c6..aad9ace0af97ef 100644
|
||||
--- a/setup.c
|
||||
+++ b/setup.c
|
||||
@@ -1037,9 +1037,11 @@ static int safe_directory_cb(const char *key, const char *value, void *d)
|
||||
if (strcmp(key, "safe.directory"))
|
||||
return 0;
|
||||
|
||||
- if (!value || !*value)
|
||||
+ if (!value || !*value) {
|
||||
data->is_safe = 0;
|
||||
- else {
|
||||
+ } else if (!strcmp(value, "*")) {
|
||||
+ data->is_safe = 1;
|
||||
+ } else {
|
||||
const char *interpolated = NULL;
|
||||
|
||||
if (!git_config_pathname(&interpolated, key, value) &&
|
||||
diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh
|
||||
index 6f33c0dfefaaf3..239d93f4d21141 100755
|
||||
--- a/t/t0033-safe-directory.sh
|
||||
+++ b/t/t0033-safe-directory.sh
|
||||
@@ -36,4 +36,14 @@ test_expect_success 'safe.directory matches, but is reset' '
|
||||
expect_rejected_dir
|
||||
'
|
||||
|
||||
+test_expect_success 'safe.directory=*' '
|
||||
+ git config --global --add safe.directory "*" &&
|
||||
+ git status
|
||||
+'
|
||||
+
|
||||
+test_expect_success 'safe.directory=*, but is reset' '
|
||||
+ git config --global --add safe.directory "" &&
|
||||
+ expect_rejected_dir
|
||||
+'
|
||||
+
|
||||
test_done
|
||||
72
backport-t0033-add-tests-for-safe.directory.patch
Normal file
72
backport-t0033-add-tests-for-safe.directory.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From e47363e5a8bdf5144059d664c45c0975243ef05b Mon Sep 17 00:00:00 2001
|
||||
From: Derrick Stolee <derrickstolee@github.com>
|
||||
Date: Wed, 13 Apr 2022 15:32:29 +0000
|
||||
Subject: [PATCH] t0033: add tests for safe.directory
|
||||
|
||||
It is difficult to change the ownership on a directory in our test
|
||||
suite, so insert a new GIT_TEST_ASSUME_DIFFERENT_OWNER environment
|
||||
variable to trick Git into thinking we are in a differently-owned
|
||||
directory. This allows us to test that the config is parsed correctly.
|
||||
|
||||
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
|
||||
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||||
---
|
||||
setup.c | 3 ++-
|
||||
t/t0033-safe-directory.sh | 34 ++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 36 insertions(+), 1 deletion(-)
|
||||
create mode 100755 t/t0033-safe-directory.sh
|
||||
|
||||
diff --git a/setup.c b/setup.c
|
||||
index 95d5b00940a87e..3c6ed17af9566a 100644
|
||||
--- a/setup.c
|
||||
+++ b/setup.c
|
||||
@@ -1053,7 +1053,8 @@ static int ensure_valid_ownership(const char *path)
|
||||
{
|
||||
struct safe_directory_data data = { .path = path };
|
||||
|
||||
- if (is_path_owned_by_current_user(path))
|
||||
+ if (!git_env_bool("GIT_TEST_ASSUME_DIFFERENT_OWNER", 0) &&
|
||||
+ is_path_owned_by_current_user(path))
|
||||
return 1;
|
||||
|
||||
read_very_early_config(safe_directory_cb, &data);
|
||||
diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh
|
||||
new file mode 100755
|
||||
index 00000000000000..9380ff3d017096
|
||||
--- /dev/null
|
||||
+++ b/t/t0033-safe-directory.sh
|
||||
@@ -0,0 +1,34 @@
|
||||
+#!/bin/sh
|
||||
+
|
||||
+test_description='verify safe.directory checks'
|
||||
+
|
||||
+. ./test-lib.sh
|
||||
+
|
||||
+GIT_TEST_ASSUME_DIFFERENT_OWNER=1
|
||||
+export GIT_TEST_ASSUME_DIFFERENT_OWNER
|
||||
+
|
||||
+expect_rejected_dir () {
|
||||
+ test_must_fail git status 2>err &&
|
||||
+ grep "safe.directory" err
|
||||
+}
|
||||
+
|
||||
+test_expect_success 'safe.directory is not set' '
|
||||
+ expect_rejected_dir
|
||||
+'
|
||||
+
|
||||
+test_expect_success 'safe.directory does not match' '
|
||||
+ git config --global safe.directory bogus &&
|
||||
+ expect_rejected_dir
|
||||
+'
|
||||
+
|
||||
+test_expect_success 'safe.directory matches' '
|
||||
+ git config --global --add safe.directory "$(pwd)" &&
|
||||
+ git status
|
||||
+'
|
||||
+
|
||||
+test_expect_success 'safe.directory matches, but is reset' '
|
||||
+ git config --global --add safe.directory "" &&
|
||||
+ expect_rejected_dir
|
||||
+'
|
||||
+
|
||||
+test_done
|
||||
16
git.spec
16
git.spec
@ -1,7 +1,7 @@
|
||||
%global gitexecdir %{_libexecdir}/git-core
|
||||
Name: git
|
||||
Version: 2.33.0
|
||||
Release: 2
|
||||
Release: 3
|
||||
Summary: A popular and widely used Version Control System
|
||||
License: GPLv2+ or LGPLv2.1
|
||||
URL: https://git-scm.com/
|
||||
@ -12,6 +12,14 @@ Source100: git-gui.desktop
|
||||
Source101: git@.service.in
|
||||
Source102: git.socket
|
||||
|
||||
Patch0: backport-0001-CVE-2022-24765.patch
|
||||
Patch1: backport-0002-CVE-2022-24765.patch
|
||||
Patch2: backport-0003-CVE-2022-24765.patch
|
||||
Patch3: backport-0004-CVE-2022-24765.patch
|
||||
Patch4: backport-t0033-add-tests-for-safe.directory.patch
|
||||
Patch5: backport-0005-CVE-2022-24765.patch
|
||||
Patch6: backport-0006-CVE-2022-24765.patch
|
||||
|
||||
BuildRequires: gcc gettext
|
||||
BuildRequires: openssl-devel libcurl-devel expat-devel systemd asciidoc xmlto glib2-devel libsecret-devel pcre-devel desktop-file-utils
|
||||
BuildRequires: python3-devel perl-generators perl-interpreter perl-Error perl(Test::More) perl-MailTools perl(Test)
|
||||
@ -291,6 +299,12 @@ make %{?_smp_mflags} test
|
||||
%{_mandir}/man7/git*.7.*
|
||||
|
||||
%changelog
|
||||
* Fri May 20 2022 fuanan <fuanan3@h-partners.com> - 2.33.0-3
|
||||
- Type:CVE
|
||||
- ID:CVE-2022-24765
|
||||
- SUG:NA
|
||||
- DESC:Fix CVE-2022-24765
|
||||
|
||||
* Thu Feb 17 2022 duyiwei <duyiwei@kylinos.cn> - 2.33.0-2
|
||||
- add subpackage git-core
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user