[v1] cifs: smb2ops: Fix listxattr() when there are no EAs

Message ID 20180504142526.9504-1-palcantara@suse.de
State New
Headers show
Series
  • [v1] cifs: smb2ops: Fix listxattr() when there are no EAs
Related show

Commit Message

Paulo Alcantara May 4, 2018, 2:25 p.m.
As per listxattr(2):

       On success, a nonnegative number is returned indicating the size
       of the extended attribute name list.  On failure, -1 is returned
       and errno  is set appropriately.

In SMB1, when the server returns an empty EA list through a listxattr(),
it will correctly return 0 as there are no EAs for the given file.

However, in SMB2+, it returns -ENODATA in listxattr() which is wrong since
the request and response were sent successfully, although there's no actual
EA for the given file.

This patch fixes listxattr() for SMB2+ by returning 0 in cifs_listxattr()
when the server returns an empty list of EAs.

Signed-off-by: Paulo Alcantara <palcantara@suse.de>
---
 fs/cifs/smb2ops.c | 6 ++++++
 1 file changed, 6 insertions(+)

Comments

Aurélien Aptel May 4, 2018, 2:35 p.m. | #1
The bug can be triggered by listing the xattr with getfattr on a samba
smb2 mount point:

    $ echo foo > foo.txt ; getfattr foo.txt ; echo $?
    getfattr: foo.txt: No such attribute
    1

vs on an xfs mount point and on a patched kernel:

    $ echo foo > foo.txt ; getfattr foo.txt ; echo $?
    0

Reviewed-by: Aurelien Aptel <aaptel@suse.com>
David Disseldorp May 4, 2018, 2:38 p.m. | #2
On Fri, 04 May 2018 16:35:27 +0200, Aurélien Aptel wrote:

> The bug can be triggered by listing the xattr with getfattr on a samba
> smb2 mount point:
> 
>     $ echo foo > foo.txt ; getfattr foo.txt ; echo $?
>     getfattr: foo.txt: No such attribute
>     1
> 
> vs on an xfs mount point and on a patched kernel:
> 
>     $ echo foo > foo.txt ; getfattr foo.txt ; echo $?
>     0

Is there already coverage of this in xfstests? If not, please make sure
it gets submitted.

Cheers, David
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Disseldorp May 4, 2018, 5:50 p.m. | #3
Looks good.
Reviewed-by: David Disseldorp <ddiss@suse.de>

Cheers, David
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Steve French May 4, 2018, 7:14 p.m. | #4
On Fri, May 4, 2018 at 9:38 AM, David Disseldorp <ddiss@suse.de> wrote:
> On Fri, 04 May 2018 16:35:27 +0200, Aurélien Aptel wrote:
>
>> The bug can be triggered by listing the xattr with getfattr on a samba
>> smb2 mount point:
>>
>>     $ echo foo > foo.txt ; getfattr foo.txt ; echo $?
>>     getfattr: foo.txt: No such attribute
>>     1
>>
>> vs on an xfs mount point and on a patched kernel:
>>
>>     $ echo foo > foo.txt ; getfattr foo.txt ; echo $?
>>     0
>
> Is there already coverage of this in xfstests? If not, please make sure
> it gets submitted.

That is a good point.

The new xfstest could be mount with nouser_xattr and see what happens
(as we see with tests which append other mount options like nodiratime
etc.)

user_xattr Enables Extended User Attributes. Additionally, you
need to have extended attribute support enabled in the
kernel configuration (CONFIG_EXT4_FS_XATTR). See the
attr(5) manual page and http://acl.bestbits.at/ to
learn more about extended attributes.

nouser_xattr Disables Extended User Attributes.
Steve French May 6, 2018, 5:44 p.m. | #5
merged into cifs-2.6.git for-next thx

On Fri, May 4, 2018 at 9:25 AM, Paulo Alcantara <palcantara@suse.de> wrote:
> As per listxattr(2):
>
>        On success, a nonnegative number is returned indicating the size
>        of the extended attribute name list.  On failure, -1 is returned
>        and errno  is set appropriately.
>
> In SMB1, when the server returns an empty EA list through a listxattr(),
> it will correctly return 0 as there are no EAs for the given file.
>
> However, in SMB2+, it returns -ENODATA in listxattr() which is wrong since
> the request and response were sent successfully, although there's no actual
> EA for the given file.
>
> This patch fixes listxattr() for SMB2+ by returning 0 in cifs_listxattr()
> when the server returns an empty list of EAs.
>
> Signed-off-by: Paulo Alcantara <palcantara@suse.de>
> ---
>  fs/cifs/smb2ops.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 117603b83b6c..12875d55c5a9 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -632,9 +632,15 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
>
>         SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
>
> +       /*
> +        * If ea_name is NULL (listxattr) and there are no EAs, return 0 as it's
> +        * not an error. Otherwise, the specified ea_name was not found.
> +        */
>         if (!rc)
>                 rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data,
>                                           SMB2_MAX_EA_BUF, ea_name);
> +       else if (!ea_name && rc == -ENODATA)
> +               rc = 0;
>
>         kfree(smb2_data);
>         return rc;
> --
> 2.13.6
>

Patch

diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 117603b83b6c..12875d55c5a9 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -632,9 +632,15 @@  smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
 
 	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
 
+	/*
+	 * If ea_name is NULL (listxattr) and there are no EAs, return 0 as it's
+	 * not an error. Otherwise, the specified ea_name was not found.
+	 */
 	if (!rc)
 		rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data,
 					  SMB2_MAX_EA_BUF, ea_name);
+	else if (!ea_name && rc == -ENODATA)
+		rc = 0;
 
 	kfree(smb2_data);
 	return rc;