diff options
author | Ronnie Sahlberg <lsahlber@redhat.com> | 2019-07-09 04:41:11 -0400 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-07-10 17:15:45 -0400 |
commit | df070afd9b8c952eacf49db54cae7138eb9deaeb (patch) | |
tree | 537e6118629e984ee62764f450abe0bf66738f3b /fs/cifs | |
parent | f5f111c231f56e56e186c9a61a9d22fb8bf05faa (diff) |
cifs: fix parsing of symbolic link error response
RHBZ: 1672539
In smb2_query_symlink(), if we are parsing the error buffer but it is not something
we recognize as a symlink we should return -EINVAL and not -ENOENT.
I.e. the entry does exist, it is just not something we recognize.
Additionally, add check to verify that that the errortag and the reparsetag all make sense.
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Acked-by: Paulo Alcantara <palcantara@suse.de>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/smb2ops.c | 14 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 2 |
2 files changed, 12 insertions, 4 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 4b0b14946343..e704e04891fb 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -2605,26 +2605,32 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, | |||
2605 | err_buf = err_iov.iov_base; | 2605 | err_buf = err_iov.iov_base; |
2606 | if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) || | 2606 | if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) || |
2607 | err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) { | 2607 | err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) { |
2608 | rc = -ENOENT; | 2608 | rc = -EINVAL; |
2609 | goto querty_exit; | ||
2610 | } | ||
2611 | |||
2612 | symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData; | ||
2613 | if (le32_to_cpu(symlink->SymLinkErrorTag) != SYMLINK_ERROR_TAG || | ||
2614 | le32_to_cpu(symlink->ReparseTag) != IO_REPARSE_TAG_SYMLINK) { | ||
2615 | rc = -EINVAL; | ||
2609 | goto querty_exit; | 2616 | goto querty_exit; |
2610 | } | 2617 | } |
2611 | 2618 | ||
2612 | /* open must fail on symlink - reset rc */ | 2619 | /* open must fail on symlink - reset rc */ |
2613 | rc = 0; | 2620 | rc = 0; |
2614 | symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData; | ||
2615 | sub_len = le16_to_cpu(symlink->SubstituteNameLength); | 2621 | sub_len = le16_to_cpu(symlink->SubstituteNameLength); |
2616 | sub_offset = le16_to_cpu(symlink->SubstituteNameOffset); | 2622 | sub_offset = le16_to_cpu(symlink->SubstituteNameOffset); |
2617 | print_len = le16_to_cpu(symlink->PrintNameLength); | 2623 | print_len = le16_to_cpu(symlink->PrintNameLength); |
2618 | print_offset = le16_to_cpu(symlink->PrintNameOffset); | 2624 | print_offset = le16_to_cpu(symlink->PrintNameOffset); |
2619 | 2625 | ||
2620 | if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) { | 2626 | if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) { |
2621 | rc = -ENOENT; | 2627 | rc = -EINVAL; |
2622 | goto querty_exit; | 2628 | goto querty_exit; |
2623 | } | 2629 | } |
2624 | 2630 | ||
2625 | if (err_iov.iov_len < | 2631 | if (err_iov.iov_len < |
2626 | SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) { | 2632 | SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) { |
2627 | rc = -ENOENT; | 2633 | rc = -EINVAL; |
2628 | goto querty_exit; | 2634 | goto querty_exit; |
2629 | } | 2635 | } |
2630 | 2636 | ||
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 458bad01ca74..7e2e782f8edd 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -166,6 +166,8 @@ struct smb2_err_rsp { | |||
166 | __u8 ErrorData[1]; /* variable length */ | 166 | __u8 ErrorData[1]; /* variable length */ |
167 | } __packed; | 167 | } __packed; |
168 | 168 | ||
169 | #define SYMLINK_ERROR_TAG 0x4c4d5953 | ||
170 | |||
169 | struct smb2_symlink_err_rsp { | 171 | struct smb2_symlink_err_rsp { |
170 | __le32 SymLinkLength; | 172 | __le32 SymLinkLength; |
171 | __le32 SymLinkErrorTag; | 173 | __le32 SymLinkErrorTag; |