Skip to content

Commit ed24b8b

Browse files
committed
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.
1 parent af9e003 commit ed24b8b

File tree

3 files changed

+45
-16
lines changed

3 files changed

+45
-16
lines changed

src/libgit2/repository.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,8 @@ static int validate_ownership_path(bool *is_safe, const char *path)
531531
{
532532
git_fs_path_owner_t owner_level =
533533
GIT_FS_PATH_OWNER_CURRENT_USER |
534-
GIT_FS_PATH_USER_IS_ADMINISTRATOR;
534+
GIT_FS_PATH_USER_IS_ADMINISTRATOR |
535+
GIT_FS_PATH_OWNER_RUNNING_SUDO;
535536
int error = 0;
536537

537538
if (path)

src/util/fs_path.c

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,27 +1934,36 @@ int git_fs_path_owner_is(
19341934

19351935
#else
19361936

1937+
static int sudo_uid_lookup(uid_t *out)
1938+
{
1939+
git_str uid_str = GIT_STR_INIT;
1940+
int64_t uid;
1941+
int error;
1942+
1943+
if ((error = git__getenv(&uid_str, "SUDO_UID")) == 0 &&
1944+
(error = git__strntol64(&uid, uid_str.ptr, uid_str.size, NULL, 10)) == 0 &&
1945+
uid == (int64_t)((uid_t)uid)) {
1946+
*out = (uid_t)uid;
1947+
}
1948+
1949+
git_str_dispose(&uid_str);
1950+
return error;
1951+
}
1952+
19371953
int git_fs_path_owner_is(
19381954
bool *out,
19391955
const char *path,
19401956
git_fs_path_owner_t owner_type)
19411957
{
1942-
uid_t uids[2] = { 0 };
1943-
size_t uid_count = 0, i;
19441958
struct stat st;
1959+
uid_t euid, sudo_uid;
19451960

19461961
if (mock_owner) {
19471962
*out = ((mock_owner & owner_type) != 0);
19481963
return 0;
19491964
}
19501965

1951-
if (owner_type & GIT_FS_PATH_OWNER_CURRENT_USER)
1952-
uids[uid_count++] = geteuid();
1953-
1954-
if (owner_type & GIT_FS_PATH_OWNER_ADMINISTRATOR)
1955-
uids[uid_count++] = 0;
1956-
1957-
*out = false;
1966+
euid = geteuid();
19581967

19591968
if (p_lstat(path, &st) != 0) {
19601969
if (errno == ENOENT)
@@ -1964,13 +1973,27 @@ int git_fs_path_owner_is(
19641973
return -1;
19651974
}
19661975

1967-
for (i = 0; i < uid_count; i++) {
1968-
if (uids[i] == st.st_uid) {
1969-
*out = true;
1970-
break;
1971-
}
1976+
if ((owner_type & GIT_FS_PATH_OWNER_CURRENT_USER) != 0 &&
1977+
st.st_uid == euid) {
1978+
*out = true;
1979+
return 0;
1980+
}
1981+
1982+
if ((owner_type & GIT_FS_PATH_OWNER_ADMINISTRATOR) != 0 &&
1983+
st.st_uid == 0) {
1984+
*out = true;
1985+
return 0;
1986+
}
1987+
1988+
if ((owner_type & GIT_FS_PATH_OWNER_RUNNING_SUDO) != 0 &&
1989+
euid == 0 &&
1990+
sudo_uid_lookup(&sudo_uid) == 0 &&
1991+
st.st_uid == sudo_uid) {
1992+
*out = true;
1993+
return 0;
19721994
}
19731995

1996+
*out = false;
19741997
return 0;
19751998
}
19761999

src/util/fs_path.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,8 +747,13 @@ typedef enum {
747747
*/
748748
GIT_FS_PATH_USER_IS_ADMINISTRATOR = (1 << 2),
749749

750+
/**
751+
* The file is owned by the current user, who is running `sudo`.
752+
*/
753+
GIT_FS_PATH_OWNER_RUNNING_SUDO = (1 << 3),
754+
750755
/** The file may be owned by another user. */
751-
GIT_FS_PATH_OWNER_OTHER = (1 << 3)
756+
GIT_FS_PATH_OWNER_OTHER = (1 << 4)
752757
} git_fs_path_owner_t;
753758

754759
/**

0 commit comments

Comments
 (0)