]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mount-util: drop exponential buffer growing in name_to_handle_at_loop()
authorLennart Poettering <lennart@poettering.net>
Thu, 23 Nov 2017 11:42:24 +0000 (12:42 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 23 Nov 2017 12:28:06 +0000 (13:28 +0100)
So, it appears name_to_handle_at() always returns the right buffer size
on EOVERFLOW, when it's returned due to a too small buffer. Let's rely
on that exclusively for sizing the buffer, and let's drop the
exponential buffer growing.

The new logic is now: if we see EOVERFLOW and the returned size has
increased, resize our buffer and try again. But if it didn't increase,
then propagate the EOVERFLOW as it likely has other causes.

src/basic/mount-util.c

index 5f22bd68cec8758be2536e113a52d19a3e708e37..fc7b0b599e5689b107d6e9e4a8d0c081e227c43f 100644 (file)
@@ -65,7 +65,6 @@ int name_to_handle_at_loop(
 
         for (;;) {
                 int mnt_id = -1;
-                size_t m;
 
                 if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) {
 
@@ -84,22 +83,24 @@ int name_to_handle_at_loop(
 
                 if (!ret_handle && ret_mnt_id && mnt_id >= 0) {
 
-                        /* As it appears, name_to_handle_at() fills in mnt_id even when it returns EOVERFLOW, but
-                         * that's undocumented. Hence, let's make use of this if it appears to be filled in, and the
-                         * caller was interested in only the mount ID an nothing else. */
+                        /* As it appears, name_to_handle_at() fills in mnt_id even when it returns EOVERFLOW when the
+                         * buffer is too small, but that's undocumented. Hence, let's make use of this if it appears to
+                         * be filled in, and the caller was interested in only the mount ID an nothing else. */
 
                         *ret_mnt_id = mnt_id;
                         return 0;
                 }
 
-                /* The buffer was too small. Size the new buffer by what name_to_handle_at() returned, but make sure it
-                 * is always larger than what we passed in before */
-                m = h->handle_bytes > n ? h->handle_bytes : n * 2;
-                if (m < n) /* Check for multiplication overflow */
+                /* If name_to_handle_at() didn't increase the byte size, then this EOVERFLOW is caused by something
+                 * else (apparently EOVERFLOW is returned for untriggered nfs4 mounts sometimes), not by the too small
+                 * buffer. In that case propagate EOVERFLOW */
+                if (h->handle_bytes <= n)
                         return -EOVERFLOW;
-                if (offsetof(struct file_handle, f_handle) + m < m) /* check for addition overflow */
+
+                /* The buffer was too small. Size the new buffer by what name_to_handle_at() returned. */
+                n = h->handle_bytes;
+                if (offsetof(struct file_handle, f_handle) + n < n) /* check for addition overflow */
                         return -EOVERFLOW;
-                n = m;
 
                 free(h);
                 h = malloc0(offsetof(struct file_handle, f_handle) + n);