cifs: fix return value for cifs_listxattr
authorRonnie Sahlberg <lsahlber@redhat.com>
Thu, 25 Oct 2018 05:43:36 +0000 (15:43 +1000)
committerSteve French <stfrench@microsoft.com>
Fri, 2 Nov 2018 19:09:41 +0000 (14:09 -0500)
If the application buffer was too small to fit all the names
we would still count the number of bytes and return this for
listxattr. This would then trigger a BUG in usercopy.c

Fix the computation of the size so that we return -ERANGE
correctly when the buffer is too small.

This fixes the kernel BUG for xfstest generic/377

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Reviewed-by: Aurelien Aptel <aaptel@suse.com>
fs/cifs/smb2ops.c

index 23c0a21..8489b5f 100644 (file)
@@ -747,6 +747,7 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size,
        int rc = 0;
        unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
        char *name, *value;
+       size_t buf_size = dst_size;
        size_t name_len, value_len, user_name_len;
 
        while (src_size > 0) {
@@ -782,9 +783,10 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size,
                        /* 'user.' plus a terminating null */
                        user_name_len = 5 + 1 + name_len;
 
-                       rc += user_name_len;
-
-                       if (dst_size >= user_name_len) {
+                       if (buf_size == 0) {
+                               /* skip copy - calc size only */
+                               rc += user_name_len;
+                       } else if (dst_size >= user_name_len) {
                                dst_size -= user_name_len;
                                memcpy(dst, "user.", 5);
                                dst += 5;
@@ -792,8 +794,7 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size,
                                dst += name_len;
                                *dst = 0;
                                ++dst;
-                       } else if (dst_size == 0) {
-                               /* skip copy - calc size only */
+                               rc += user_name_len;
                        } else {
                                /* stop before overrun buffer */
                                rc = -ERANGE;