File 0020-repo-allow-users-running-with-sudo-to-access-their-r.patch of Package libgit2.28344
From 749f5fdbdc1a923ca3c49db328f448b613e75585 Mon Sep 17 00:00:00 2001
From: Edward Thomson <ethomson@edwardthomson.com>
Date: Tue, 5 Jul 2022 23:47:15 -0400
Subject: [PATCH 20/20] repo: allow users running with sudo to access their
repositories
In the ownership checks implemented for CVE-2022-24765, we disallowed
users to access their own repositories when running with `sudo`.
Examine the `SUDO_UID` environment variable and allow users running
with `sudo`. This matches git's behavior.
---
src/path.c | 51 +++++++++++++++++++++++++++++++++++-------------
src/path.h | 7 ++++++-
src/repository.c | 3 ++-
3 files changed, 45 insertions(+), 16 deletions(-)
diff --git a/src/path.c b/src/path.c
index 606b2ed5e..309f24442 100644
--- a/src/path.c
+++ b/src/path.c
@@ -2173,27 +2173,36 @@ done:
#else
+static int sudo_uid_lookup(uid_t *out)
+{
+ git_buf uid_str = GIT_BUF_INIT;
+ int64_t uid;
+ int error;
+
+ if ((error = git__getenv(&uid_str, "SUDO_UID")) == 0 &&
+ (error = git__strntol64(&uid, uid_str.ptr, uid_str.size, NULL, 10)) == 0 &&
+ uid == (int64_t)((uid_t)uid)) {
+ *out = (uid_t)uid;
+ }
+
+ git_buf_dispose(&uid_str);
+ return error;
+}
+
int git_path_owner_is(
bool *out,
const char *path,
git_path_owner_t owner_type)
{
- uid_t uids[2] = { 0 };
- size_t uid_count = 0, i;
struct stat st;
+ uid_t euid, sudo_uid;
if (mock_owner) {
*out = ((mock_owner & owner_type) != 0);
return 0;
}
- if (owner_type & GIT_PATH_OWNER_CURRENT_USER)
- uids[uid_count++] = geteuid();
-
- if (owner_type & GIT_PATH_OWNER_ADMINISTRATOR)
- uids[uid_count++] = 0;
-
- *out = false;
+ euid = geteuid();
if (p_lstat(path, &st) != 0) {
if (errno == ENOENT)
@@ -2203,13 +2212,27 @@ int git_path_owner_is(
return -1;
}
- for (i = 0; i < uid_count; i++) {
- if (uids[i] == st.st_uid) {
- *out = true;
- break;
- }
+ if ((owner_type & GIT_PATH_OWNER_CURRENT_USER) != 0 &&
+ st.st_uid == euid) {
+ *out = true;
+ return 0;
+ }
+
+ if ((owner_type & GIT_PATH_OWNER_ADMINISTRATOR) != 0 &&
+ st.st_uid == 0) {
+ *out = true;
+ return 0;
+ }
+
+ if ((owner_type & GIT_PATH_OWNER_RUNNING_SUDO) != 0 &&
+ euid == 0 &&
+ sudo_uid_lookup(&sudo_uid) == 0 &&
+ st.st_uid == sudo_uid) {
+ *out = true;
+ return 0;
}
+ *out = false;
return 0;
}
diff --git a/src/path.h b/src/path.h
index bb51cff11..f697c8f3e 100644
--- a/src/path.h
+++ b/src/path.h
@@ -738,8 +738,13 @@ typedef enum {
*/
GIT_PATH_USER_IS_ADMINISTRATOR = (1 << 2),
+ /**
+ * The file is owned by the current user, who is running `sudo`.
+ */
+ GIT_PATH_OWNER_RUNNING_SUDO = (1 << 3),
+
/** The file may be owned by another user. */
- GIT_PATH_OWNER_OTHER = (1 << 3)
+ GIT_PATH_OWNER_OTHER = (1 << 4)
} git_path_owner_t;
/**
diff --git a/src/repository.c b/src/repository.c
index ac32085da..2518c8b03 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -530,7 +530,8 @@ static int validate_ownership_path(bool *is_safe, const char *path)
{
git_path_owner_t owner_level =
GIT_PATH_OWNER_CURRENT_USER |
- GIT_PATH_USER_IS_ADMINISTRATOR;
+ GIT_PATH_USER_IS_ADMINISTRATOR |
+ GIT_PATH_OWNER_RUNNING_SUDO;
int error = 0;
if (path)
--
2.37.1