Skip to content

Commit 433f016

Browse files
committed
fs: refactor file ownership checks
Refactor the file ownership checks so that callers can provide discrete information about the ownership expectations to a single function.
1 parent df354ec commit 433f016

File tree

3 files changed

+53
-103
lines changed

3 files changed

+53
-103
lines changed

src/libgit2/config.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1170,10 +1170,13 @@ int git_config_find_programdata(git_buf *path)
11701170

11711171
int git_config__find_programdata(git_str *path)
11721172
{
1173+
git_fs_path_owner_t owner_level =
1174+
GIT_FS_PATH_OWNER_CURRENT_USER |
1175+
GIT_FS_PATH_OWNER_ADMINISTRATOR;
11731176
bool is_safe;
11741177

11751178
if (git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA) < 0 ||
1176-
git_fs_path_owner_is_system_or_current_user(&is_safe, path->ptr) < 0)
1179+
git_fs_path_owner_is(&is_safe, path->ptr, owner_level) < 0)
11771180
return -1;
11781181

11791182
if (!is_safe) {

src/util/fs_path.c

Lines changed: 42 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,74 +1879,41 @@ static int file_owner_sid(PSID *out, const char *path)
18791879
return error;
18801880
}
18811881

1882-
int git_fs_path_owner_is_current_user(bool *out, const char *path)
1882+
int git_fs_path_owner_is(
1883+
bool *out,
1884+
const char *path,
1885+
git_fs_path_owner_t owner_type)
18831886
{
18841887
PSID owner_sid = NULL, user_sid = NULL;
1885-
int error = -1;
1888+
int error;
18861889

18871890
if (mock_owner) {
1888-
*out = (mock_owner == GIT_FS_PATH_OWNER_CURRENT_USER);
1891+
*out = ((mock_owner & owner_type) != 0);
18891892
return 0;
18901893
}
18911894

1892-
if ((error = file_owner_sid(&owner_sid, path)) < 0 ||
1893-
(error = current_user_sid(&user_sid)) < 0)
1895+
if ((error = file_owner_sid(&owner_sid, path)) < 0)
18941896
goto done;
18951897

1896-
*out = EqualSid(owner_sid, user_sid);
1897-
error = 0;
1898-
1899-
done:
1900-
git__free(owner_sid);
1901-
git__free(user_sid);
1902-
return error;
1903-
}
1904-
1905-
int git_fs_path_owner_is_system(bool *out, const char *path)
1906-
{
1907-
PSID owner_sid;
1908-
1909-
if (mock_owner) {
1910-
*out = (mock_owner == GIT_FS_PATH_OWNER_ADMINISTRATOR);
1911-
return 0;
1912-
}
1898+
if ((owner_type & GIT_FS_PATH_OWNER_CURRENT_USER) != 0) {
1899+
if ((error = current_user_sid(&user_sid)) < 0)
1900+
goto done;
19131901

1914-
if (file_owner_sid(&owner_sid, path) < 0)
1915-
return -1;
1916-
1917-
*out = IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
1918-
IsWellKnownSid(owner_sid, WinLocalSystemSid);
1919-
1920-
git__free(owner_sid);
1921-
return 0;
1922-
}
1923-
1924-
int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
1925-
{
1926-
PSID owner_sid = NULL, user_sid = NULL;
1927-
int error = -1;
1928-
1929-
if (mock_owner) {
1930-
*out = (mock_owner == GIT_FS_PATH_OWNER_ADMINISTRATOR ||
1931-
mock_owner == GIT_FS_PATH_OWNER_CURRENT_USER);
1932-
return 0;
1902+
if (EqualSid(owner_sid, user_sid)) {
1903+
*out = true;
1904+
goto done;
1905+
}
19331906
}
19341907

1935-
if (file_owner_sid(&owner_sid, path) < 0)
1936-
goto done;
1937-
1938-
if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
1939-
IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
1940-
*out = 1;
1941-
error = 0;
1942-
goto done;
1908+
if ((owner_type & GIT_FS_PATH_OWNER_ADMINISTRATOR) != 0) {
1909+
if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
1910+
IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
1911+
*out = true;
1912+
goto done;
1913+
}
19431914
}
19441915

1945-
if (current_user_sid(&user_sid) < 0)
1946-
goto done;
1947-
1948-
*out = EqualSid(owner_sid, user_sid);
1949-
error = 0;
1916+
*out = false;
19501917

19511918
done:
19521919
git__free(owner_sid);
@@ -1956,10 +1923,25 @@ int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
19561923

19571924
#else
19581925

1959-
static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uids_len)
1926+
int git_fs_path_owner_is(
1927+
bool *out,
1928+
const char *path,
1929+
git_fs_path_owner_t owner_type)
19601930
{
1931+
uid_t uids[2] = { 0 };
1932+
size_t uid_count = 0, i;
19611933
struct stat st;
1962-
size_t i;
1934+
1935+
if (mock_owner) {
1936+
*out = ((mock_owner & owner_type) != 0);
1937+
return 0;
1938+
}
1939+
1940+
if (owner_type & GIT_FS_PATH_OWNER_CURRENT_USER)
1941+
uids[uid_count++] = geteuid();
1942+
1943+
if (owner_type & GIT_FS_PATH_OWNER_ADMINISTRATOR)
1944+
uids[uid_count++] = 0;
19631945

19641946
*out = false;
19651947

@@ -1971,7 +1953,7 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid
19711953
return -1;
19721954
}
19731955

1974-
for (i = 0; i < uids_len; i++) {
1956+
for (i = 0; i < uid_count; i++) {
19751957
if (uids[i] == st.st_uid) {
19761958
*out = true;
19771959
break;
@@ -1980,46 +1962,18 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid
19801962

19811963
return 0;
19821964
}
1965+
#endif
19831966

19841967
int git_fs_path_owner_is_current_user(bool *out, const char *path)
19851968
{
1986-
uid_t userid = geteuid();
1987-
1988-
if (mock_owner) {
1989-
*out = (mock_owner == GIT_FS_PATH_OWNER_CURRENT_USER);
1990-
return 0;
1991-
}
1992-
1993-
return fs_path_owner_is(out, path, &userid, 1);
1969+
return git_fs_path_owner_is(out, path, GIT_FS_PATH_OWNER_CURRENT_USER);
19941970
}
19951971

19961972
int git_fs_path_owner_is_system(bool *out, const char *path)
19971973
{
1998-
uid_t userid = 0;
1999-
2000-
if (mock_owner) {
2001-
*out = (mock_owner == GIT_FS_PATH_OWNER_ADMINISTRATOR);
2002-
return 0;
2003-
}
2004-
2005-
return fs_path_owner_is(out, path, &userid, 1);
1974+
return git_fs_path_owner_is(out, path, GIT_FS_PATH_OWNER_ADMINISTRATOR);
20061975
}
20071976

2008-
int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
2009-
{
2010-
uid_t userids[2] = { geteuid(), 0 };
2011-
2012-
if (mock_owner) {
2013-
*out = (mock_owner == GIT_FS_PATH_OWNER_ADMINISTRATOR ||
2014-
mock_owner == GIT_FS_PATH_OWNER_CURRENT_USER);
2015-
return 0;
2016-
}
2017-
2018-
return fs_path_owner_is(out, path, userids, 2);
2019-
}
2020-
2021-
#endif
2022-
20231977
int git_fs_path_find_executable(git_str *fullpath, const char *executable)
20241978
{
20251979
#ifdef GIT_WIN32

src/util/fs_path.h

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -740,15 +740,8 @@ typedef enum {
740740
/** The file must be owned by the system account. */
741741
GIT_FS_PATH_OWNER_ADMINISTRATOR = (1 << 1),
742742

743-
/**
744-
* The file may be owned by a system account if the current
745-
* user is in an administrator group. Windows only; this is
746-
* a noop on non-Windows systems.
747-
*/
748-
GIT_FS_PATH_OWNER_CURRENT_USER_IS_ADMINISTRATOR = (1 << 2),
749-
750743
/** The file may be owned by another user. */
751-
GIT_FS_PATH_OWNER_OTHER = (1 << 4)
744+
GIT_FS_PATH_OWNER_OTHER = (1 << 2)
752745
} git_fs_path_owner_t;
753746

754747
/**
@@ -758,6 +751,12 @@ typedef enum {
758751
*/
759752
void git_fs_path__set_owner(git_fs_path_owner_t owner);
760753

754+
/** Verify that the file in question is owned by the given owner. */
755+
int git_fs_path_owner_is(
756+
bool *out,
757+
const char *path,
758+
git_fs_path_owner_t owner_type);
759+
761760
/**
762761
* Verify that the file in question is owned by an administrator or system
763762
* account.
@@ -770,12 +769,6 @@ int git_fs_path_owner_is_system(bool *out, const char *path);
770769

771770
int git_fs_path_owner_is_current_user(bool *out, const char *path);
772771

773-
/**
774-
* Verify that the file in question is owned by an administrator or system
775-
* account _or_ the current user;
776-
*/
777-
int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path);
778-
779772
/**
780773
* Search the current PATH for the given executable, returning the full
781774
* path if it is found.

0 commit comments

Comments
 (0)