aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c111
1 files changed, 51 insertions, 60 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a89c4cb4e6cf..4baf35949b51 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -463,7 +463,6 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
463 cifs_max_pending); 463 cifs_max_pending);
464 set_credits(server, server->maxReq); 464 set_credits(server, server->maxReq);
465 server->maxBuf = le16_to_cpu(rsp->MaxBufSize); 465 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
466 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
467 /* even though we do not use raw we might as well set this 466 /* even though we do not use raw we might as well set this
468 accurately, in case we ever find a need for it */ 467 accurately, in case we ever find a need for it */
469 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { 468 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
@@ -3067,7 +3066,6 @@ querySymLinkRetry:
3067 return rc; 3066 return rc;
3068} 3067}
3069 3068
3070#ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3071/* 3069/*
3072 * Recent Windows versions now create symlinks more frequently 3070 * Recent Windows versions now create symlinks more frequently
3073 * and they use the "reparse point" mechanism below. We can of course 3071 * and they use the "reparse point" mechanism below. We can of course
@@ -3079,18 +3077,22 @@ querySymLinkRetry:
3079 * it is not compiled in by default until callers fixed up and more tested. 3077 * it is not compiled in by default until callers fixed up and more tested.
3080 */ 3078 */
3081int 3079int
3082CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon, 3080CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3083 const unsigned char *searchName, 3081 __u16 fid, char **symlinkinfo,
3084 char *symlinkinfo, const int buflen, __u16 fid, 3082 const struct nls_table *nls_codepage)
3085 const struct nls_table *nls_codepage)
3086{ 3083{
3087 int rc = 0; 3084 int rc = 0;
3088 int bytes_returned; 3085 int bytes_returned;
3089 struct smb_com_transaction_ioctl_req *pSMB; 3086 struct smb_com_transaction_ioctl_req *pSMB;
3090 struct smb_com_transaction_ioctl_rsp *pSMBr; 3087 struct smb_com_transaction_ioctl_rsp *pSMBr;
3088 bool is_unicode;
3089 unsigned int sub_len;
3090 char *sub_start;
3091 struct reparse_data *reparse_buf;
3092 __u32 data_offset, data_count;
3093 char *end_of_smb;
3091 3094
3092 cifs_dbg(FYI, "In Windows reparse style QueryLink for path %s\n", 3095 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3093 searchName);
3094 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, 3096 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3095 (void **) &pSMBr); 3097 (void **) &pSMBr);
3096 if (rc) 3098 if (rc)
@@ -3119,66 +3121,55 @@ CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3119 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 3121 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3120 if (rc) { 3122 if (rc) {
3121 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc); 3123 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3122 } else { /* decode response */ 3124 goto qreparse_out;
3123 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); 3125 }
3124 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3125 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3126 /* BB also check enough total bytes returned */
3127 rc = -EIO; /* bad smb */
3128 goto qreparse_out;
3129 }
3130 if (data_count && (data_count < 2048)) {
3131 char *end_of_smb = 2 /* sizeof byte count */ +
3132 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3133
3134 struct reparse_data *reparse_buf =
3135 (struct reparse_data *)
3136 ((char *)&pSMBr->hdr.Protocol
3137 + data_offset);
3138 if ((char *)reparse_buf >= end_of_smb) {
3139 rc = -EIO;
3140 goto qreparse_out;
3141 }
3142 if ((reparse_buf->LinkNamesBuf +
3143 reparse_buf->TargetNameOffset +
3144 reparse_buf->TargetNameLen) > end_of_smb) {
3145 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3146 rc = -EIO;
3147 goto qreparse_out;
3148 }
3149 3126
3150 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 3127 data_offset = le32_to_cpu(pSMBr->DataOffset);
3151 cifs_from_ucs2(symlinkinfo, (__le16 *) 3128 data_count = le32_to_cpu(pSMBr->DataCount);
3152 (reparse_buf->LinkNamesBuf + 3129 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3153 reparse_buf->TargetNameOffset), 3130 /* BB also check enough total bytes returned */
3154 buflen, 3131 rc = -EIO; /* bad smb */
3155 reparse_buf->TargetNameLen, 3132 goto qreparse_out;
3156 nls_codepage, 0); 3133 }
3157 } else { /* ASCII names */ 3134 if (!data_count || (data_count > 2048)) {
3158 strncpy(symlinkinfo, 3135 rc = -EIO;
3159 reparse_buf->LinkNamesBuf + 3136 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3160 reparse_buf->TargetNameOffset, 3137 goto qreparse_out;
3161 min_t(const int, buflen, 3138 }
3162 reparse_buf->TargetNameLen)); 3139 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3163 } 3140 reparse_buf = (struct reparse_data *)
3164 } else { 3141 ((char *)&pSMBr->hdr.Protocol + data_offset);
3165 rc = -EIO; 3142 if ((char *)reparse_buf >= end_of_smb) {
3166 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n"); 3143 rc = -EIO;
3167 } 3144 goto qreparse_out;
3168 symlinkinfo[buflen] = 0; /* just in case so the caller
3169 does not go off the end of the buffer */
3170 cifs_dbg(FYI, "readlink result - %s\n", symlinkinfo);
3171 } 3145 }
3146 if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
3147 reparse_buf->PrintNameLength) > end_of_smb) {
3148 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3149 rc = -EIO;
3150 goto qreparse_out;
3151 }
3152 sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer;
3153 sub_len = reparse_buf->SubstituteNameLength;
3154 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3155 is_unicode = true;
3156 else
3157 is_unicode = false;
3172 3158
3159 /* BB FIXME investigate remapping reserved chars here */
3160 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3161 nls_codepage);
3162 if (!*symlinkinfo)
3163 rc = -ENOMEM;
3173qreparse_out: 3164qreparse_out:
3174 cifs_buf_release(pSMB); 3165 cifs_buf_release(pSMB);
3175 3166
3176 /* Note: On -EAGAIN error only caller can retry on handle based calls 3167 /*
3177 since file handle passed in no longer valid */ 3168 * Note: On -EAGAIN error only caller can retry on handle based calls
3178 3169 * since file handle passed in no longer valid.
3170 */
3179 return rc; 3171 return rc;
3180} 3172}
3181#endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3182 3173
3183#ifdef CONFIG_CIFS_POSIX 3174#ifdef CONFIG_CIFS_POSIX
3184 3175