aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilovsky@samba.org>2016-07-24 03:37:38 -0400
committerSteve French <smfrench@gmail.com>2016-07-27 23:55:56 -0400
commit7893242e2465aea6f2cbc2639da8fa5ce96e8cc2 (patch)
tree1cab64729128945784e3e72ac5796a1671187eb7
parenta6b5058fafdf508904bbf16c29b24042cef3c496 (diff)
CIFS: Fix a possible invalid memory access in smb2_query_symlink()
During following a symbolic link we received err_buf from SMB2_open(). While the validity of SMB2 error response is checked previously in smb2_check_message() a symbolic link payload is not checked at all. Fix it by adding such checks. Cc: Dan Carpenter <dan.carpenter@oracle.com> CC: Stable <stable@vger.kernel.org> Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/smb2ops.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 527d1ac8583b..d203c0329626 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1044,6 +1044,9 @@ smb2_new_lease_key(struct cifs_fid *fid)
1044 get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE); 1044 get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
1045} 1045}
1046 1046
1047#define SMB2_SYMLINK_STRUCT_SIZE \
1048 (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
1049
1047static int 1050static int
1048smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, 1051smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
1049 const char *full_path, char **target_path, 1052 const char *full_path, char **target_path,
@@ -1056,7 +1059,10 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
1056 struct cifs_fid fid; 1059 struct cifs_fid fid;
1057 struct smb2_err_rsp *err_buf = NULL; 1060 struct smb2_err_rsp *err_buf = NULL;
1058 struct smb2_symlink_err_rsp *symlink; 1061 struct smb2_symlink_err_rsp *symlink;
1059 unsigned int sub_len, sub_offset; 1062 unsigned int sub_len;
1063 unsigned int sub_offset;
1064 unsigned int print_len;
1065 unsigned int print_offset;
1060 1066
1061 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); 1067 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
1062 1068
@@ -1077,11 +1083,33 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
1077 kfree(utf16_path); 1083 kfree(utf16_path);
1078 return -ENOENT; 1084 return -ENOENT;
1079 } 1085 }
1086
1087 if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
1088 get_rfc1002_length(err_buf) + 4 < SMB2_SYMLINK_STRUCT_SIZE) {
1089 kfree(utf16_path);
1090 return -ENOENT;
1091 }
1092
1080 /* open must fail on symlink - reset rc */ 1093 /* open must fail on symlink - reset rc */
1081 rc = 0; 1094 rc = 0;
1082 symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData; 1095 symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
1083 sub_len = le16_to_cpu(symlink->SubstituteNameLength); 1096 sub_len = le16_to_cpu(symlink->SubstituteNameLength);
1084 sub_offset = le16_to_cpu(symlink->SubstituteNameOffset); 1097 sub_offset = le16_to_cpu(symlink->SubstituteNameOffset);
1098 print_len = le16_to_cpu(symlink->PrintNameLength);
1099 print_offset = le16_to_cpu(symlink->PrintNameOffset);
1100
1101 if (get_rfc1002_length(err_buf) + 4 <
1102 SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
1103 kfree(utf16_path);
1104 return -ENOENT;
1105 }
1106
1107 if (get_rfc1002_length(err_buf) + 4 <
1108 SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
1109 kfree(utf16_path);
1110 return -ENOENT;
1111 }
1112
1085 *target_path = cifs_strndup_from_utf16( 1113 *target_path = cifs_strndup_from_utf16(
1086 (char *)symlink->PathBuffer + sub_offset, 1114 (char *)symlink->PathBuffer + sub_offset,
1087 sub_len, true, cifs_sb->local_nls); 1115 sub_len, true, cifs_sb->local_nls);