[BUG] [PATCH] infinite loop due to broken symlink

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi guys,
git goes into an infinite loop due to broken symlink (minimal reproducer [0]). Affected code is in function
"resolve_ref_unsafe" in file refs.c - notice 'stat_ref'. There is comment
about problem with race condition, hovewer in that case it's regular broken
symlink which cause infinite loop. Possible patch could be something like this:

-------------------------------------------------------
diff --git a/refs.c b/refs.c
index e23542b..9efe8d2 100644
--- a/refs.c
+++ b/refs.c
@@ -1356,6 +1356,7 @@ static struct ref_dir *get_loose_refs(struct ref_cache *refs)
 /* We allow "recursive" symbolic refs. Only within reason, though */
 #define MAXDEPTH 5
 #define MAXREFLEN (1024)
+#define MAXLOOP 1024

 /*
  * Called by resolve_gitlink_ref_recursive() after it failed to read
@@ -1482,6 +1483,7 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
        char buffer[256];
        static char refname_buffer[256];
        int bad_name = 0;
+    int loop_counter = 0;

        if (flags)
                *flags = 0;
@@ -1546,7 +1548,8 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
                if (S_ISLNK(st.st_mode)) {
                        len = readlink(path, buffer, sizeof(buffer)-1);
                        if (len < 0) {
-                               if (errno == ENOENT || errno == EINVAL)
+                               if (loop_counter++ < MAXLOOP &&
+                    (errno == ENOENT || errno == EINVAL))
/* inconsistent with lstat; retry */
                                        goto stat_ref;
                                else
@@ -1579,7 +1582,7 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
                 */
                fd = open(path, O_RDONLY);
                if (fd < 0) {
-                       if (errno == ENOENT)
+                       if (loop_counter++ < MAXLOOP && errno == ENOENT)
                                /* inconsistent with lstat; retry */
                                goto stat_ref;
                        else
-------------------------------------------------------

If I understand well that simple check of broken symlink is not possible
due to race conditions.

Regards,
Petr

[0] https://bugzilla.redhat.com/show_bug.cgi?id=1204193
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]