]> git.ipfire.org Git - thirdparty/git.git/blobdiff - git-compat-util.h
Sync with 2.30.5
[thirdparty/git.git] / git-compat-util.h
index 261516231e95bcb3d234908709d59b8bf0abd6c1..5ed0f0000116513167582830998365204c25481d 100644 (file)
@@ -393,12 +393,68 @@ static inline int git_offset_1st_component(const char *path)
 #endif
 
 #ifndef is_path_owned_by_current_user
+
+#ifdef __TANDEM
+#define ROOT_UID 65535
+#else
+#define ROOT_UID 0
+#endif
+
+/*
+ * Do not use this function when
+ * (1) geteuid() did not say we are running as 'root', or
+ * (2) using this function will compromise the system.
+ *
+ * PORTABILITY WARNING:
+ * This code assumes uid_t is unsigned because that is what sudo does.
+ * If your uid_t type is signed and all your ids are positive then it
+ * should all work fine.
+ * If your version of sudo uses negative values for uid_t or it is
+ * buggy and return an overflowed value in SUDO_UID, then git might
+ * fail to grant access to your repository properly or even mistakenly
+ * grant access to someone else.
+ * In the unlikely scenario this happened to you, and that is how you
+ * got to this message, we would like to know about it; so sent us an
+ * email to git@vger.kernel.org indicating which platform you are
+ * using and which version of sudo, so we can improve this logic and
+ * maybe provide you with a patch that would prevent this issue again
+ * in the future.
+ */
+static inline void extract_id_from_env(const char *env, uid_t *id)
+{
+       const char *real_uid = getenv(env);
+
+       /* discard anything empty to avoid a more complex check below */
+       if (real_uid && *real_uid) {
+               char *endptr = NULL;
+               unsigned long env_id;
+
+               errno = 0;
+               /* silent overflow errors could trigger a bug here */
+               env_id = strtoul(real_uid, &endptr, 10);
+               if (!*endptr && !errno)
+                       *id = env_id;
+       }
+}
+
 static inline int is_path_owned_by_current_uid(const char *path)
 {
        struct stat st;
+       uid_t euid;
+
        if (lstat(path, &st))
                return 0;
-       return st.st_uid == geteuid();
+
+       euid = geteuid();
+       if (euid == ROOT_UID)
+       {
+               if (st.st_uid == ROOT_UID)
+                       return 1;
+               else
+                       extract_id_from_env("SUDO_UID", &euid);
+       }
+
+       return st.st_uid == euid;
 }
 
 #define is_path_owned_by_current_user is_path_owned_by_current_uid