diff options
-rw-r--r-- | fs/cifs/cifssmb.c | 14 | ||||
-rw-r--r-- | fs/cifs/connect.c | 23 | ||||
-rw-r--r-- | fs/cifs/link.c | 87 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 37 |
4 files changed, 58 insertions, 103 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index df5276e628bf..b968e5bd7df3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2451,16 +2451,20 @@ querySymLinkRetry: | |||
2451 | if (rc || (pSMBr->ByteCount < 2)) | 2451 | if (rc || (pSMBr->ByteCount < 2)) |
2452 | rc = -EIO; | 2452 | rc = -EIO; |
2453 | else { | 2453 | else { |
2454 | bool is_unicode; | ||
2454 | u16 count = le16_to_cpu(pSMBr->t2.DataCount); | 2455 | u16 count = le16_to_cpu(pSMBr->t2.DataCount); |
2455 | 2456 | ||
2456 | data_start = ((char *) &pSMBr->hdr.Protocol) + | 2457 | data_start = ((char *) &pSMBr->hdr.Protocol) + |
2457 | le16_to_cpu(pSMBr->t2.DataOffset); | 2458 | le16_to_cpu(pSMBr->t2.DataOffset); |
2458 | 2459 | ||
2460 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) | ||
2461 | is_unicode = true; | ||
2462 | else | ||
2463 | is_unicode = false; | ||
2464 | |||
2459 | /* BB FIXME investigate remapping reserved chars here */ | 2465 | /* BB FIXME investigate remapping reserved chars here */ |
2460 | *symlinkinfo = cifs_strndup_from_ucs(data_start, count, | 2466 | *symlinkinfo = cifs_strndup_from_ucs(data_start, count, |
2461 | pSMBr->hdr.Flags2 & | 2467 | is_unicode, nls_codepage); |
2462 | SMBFLG2_UNICODE, | ||
2463 | nls_codepage); | ||
2464 | if (!symlinkinfo) | 2468 | if (!symlinkinfo) |
2465 | rc = -ENOMEM; | 2469 | rc = -ENOMEM; |
2466 | } | 2470 | } |
@@ -3930,7 +3934,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | |||
3930 | 3934 | ||
3931 | cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", | 3935 | cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", |
3932 | *num_of_nodes, | 3936 | *num_of_nodes, |
3933 | le16_to_cpu(pSMBr->DFSFlags))); | 3937 | le32_to_cpu(pSMBr->DFSFlags))); |
3934 | 3938 | ||
3935 | *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * | 3939 | *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * |
3936 | *num_of_nodes, GFP_KERNEL); | 3940 | *num_of_nodes, GFP_KERNEL); |
@@ -3946,7 +3950,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | |||
3946 | int max_len; | 3950 | int max_len; |
3947 | struct dfs_info3_param *node = (*target_nodes)+i; | 3951 | struct dfs_info3_param *node = (*target_nodes)+i; |
3948 | 3952 | ||
3949 | node->flags = le16_to_cpu(pSMBr->DFSFlags); | 3953 | node->flags = le32_to_cpu(pSMBr->DFSFlags); |
3950 | if (is_unicode) { | 3954 | if (is_unicode) { |
3951 | __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, | 3955 | __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, |
3952 | GFP_KERNEL); | 3956 | GFP_KERNEL); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5bce2778163b..9dcdb0c707ea 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -2681,8 +2681,6 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2681 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; | 2681 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; |
2682 | if (sign_CIFS_PDUs) | 2682 | if (sign_CIFS_PDUs) |
2683 | negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; | 2683 | negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; |
2684 | /* if (ntlmv2_support) | ||
2685 | negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/ | ||
2686 | /* setup pointers to domain name and workstation name */ | 2684 | /* setup pointers to domain name and workstation name */ |
2687 | bcc_ptr += SecurityBlobLength; | 2685 | bcc_ptr += SecurityBlobLength; |
2688 | 2686 | ||
@@ -2780,9 +2778,10 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2780 | memcpy(ses->server->cryptKey, | 2778 | memcpy(ses->server->cryptKey, |
2781 | SecurityBlob2->Challenge, | 2779 | SecurityBlob2->Challenge, |
2782 | CIFS_CRYPTO_KEY_SIZE); | 2780 | CIFS_CRYPTO_KEY_SIZE); |
2783 | if (SecurityBlob2->NegotiateFlags & | 2781 | /* NTLMV2 flag is not for NTLMv2 password hash */ |
2782 | /* if (SecurityBlob2->NegotiateFlags & | ||
2784 | cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) | 2783 | cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) |
2785 | *pNTLMv2_flag = true; | 2784 | *pNTLMv2_flag = true; */ /* BB wrong */ |
2786 | 2785 | ||
2787 | if ((SecurityBlob2->NegotiateFlags & | 2786 | if ((SecurityBlob2->NegotiateFlags & |
2788 | cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) | 2787 | cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) |
@@ -3012,11 +3011,10 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3012 | bcc_ptr += SecurityBlobLength; | 3011 | bcc_ptr += SecurityBlobLength; |
3013 | negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | | 3012 | negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | |
3014 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | | 3013 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | |
3015 | 0x80000000 | NTLMSSP_NEGOTIATE_128; | 3014 | NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_128 | |
3015 | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | ||
3016 | if (sign_CIFS_PDUs) | 3016 | if (sign_CIFS_PDUs) |
3017 | negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; | 3017 | negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; |
3018 | if (ntlmv2_flag) | ||
3019 | negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; | ||
3020 | 3018 | ||
3021 | /* setup pointers to domain name and workstation name */ | 3019 | /* setup pointers to domain name and workstation name */ |
3022 | 3020 | ||
@@ -3438,12 +3436,19 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3438 | 3436 | ||
3439 | /* above now done in SendReceive */ | 3437 | /* above now done in SendReceive */ |
3440 | if ((rc == 0) && (tcon != NULL)) { | 3438 | if ((rc == 0) && (tcon != NULL)) { |
3439 | bool is_unicode; | ||
3440 | |||
3441 | tcon->tidStatus = CifsGood; | 3441 | tcon->tidStatus = CifsGood; |
3442 | tcon->need_reconnect = false; | 3442 | tcon->need_reconnect = false; |
3443 | tcon->tid = smb_buffer_response->Tid; | 3443 | tcon->tid = smb_buffer_response->Tid; |
3444 | bcc_ptr = pByteArea(smb_buffer_response); | 3444 | bcc_ptr = pByteArea(smb_buffer_response); |
3445 | bytes_left = BCC(smb_buffer_response); | 3445 | bytes_left = BCC(smb_buffer_response); |
3446 | length = strnlen(bcc_ptr, bytes_left - 2); | 3446 | length = strnlen(bcc_ptr, bytes_left - 2); |
3447 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) | ||
3448 | is_unicode = true; | ||
3449 | else | ||
3450 | is_unicode = false; | ||
3451 | |||
3447 | 3452 | ||
3448 | /* skip service field (NB: this field is always ASCII) */ | 3453 | /* skip service field (NB: this field is always ASCII) */ |
3449 | if (length == 3) { | 3454 | if (length == 3) { |
@@ -3464,9 +3469,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3464 | 3469 | ||
3465 | /* mostly informational -- no need to fail on error here */ | 3470 | /* mostly informational -- no need to fail on error here */ |
3466 | tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, | 3471 | tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, |
3467 | bytes_left, | 3472 | bytes_left, is_unicode, |
3468 | smb_buffer->Flags2 & | ||
3469 | SMBFLG2_UNICODE, | ||
3470 | nls_codepage); | 3473 | nls_codepage); |
3471 | 3474 | ||
3472 | cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem)); | 3475 | cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem)); |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index eb2fbbe865d2..ea9d11e3dcbb 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -212,93 +212,6 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
212 | return rc; | 212 | return rc; |
213 | } | 213 | } |
214 | 214 | ||
215 | int | ||
216 | cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) | ||
217 | { | ||
218 | struct inode *inode = direntry->d_inode; | ||
219 | int rc = -EACCES; | ||
220 | int xid; | ||
221 | int oplock = 0; | ||
222 | struct cifs_sb_info *cifs_sb; | ||
223 | struct cifsTconInfo *pTcon; | ||
224 | char *full_path = NULL; | ||
225 | char *tmpbuffer; | ||
226 | int len; | ||
227 | __u16 fid; | ||
228 | |||
229 | xid = GetXid(); | ||
230 | cifs_sb = CIFS_SB(inode->i_sb); | ||
231 | pTcon = cifs_sb->tcon; | ||
232 | |||
233 | /* BB would it be safe against deadlock to grab this sem | ||
234 | even though rename itself grabs the sem and calls lookup? */ | ||
235 | /* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/ | ||
236 | full_path = build_path_from_dentry(direntry); | ||
237 | /* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/ | ||
238 | |||
239 | if (full_path == NULL) { | ||
240 | FreeXid(xid); | ||
241 | return -ENOMEM; | ||
242 | } | ||
243 | |||
244 | cFYI(1, | ||
245 | ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", | ||
246 | full_path, inode, pBuffer, buflen)); | ||
247 | if (buflen > PATH_MAX) | ||
248 | len = PATH_MAX; | ||
249 | else | ||
250 | len = buflen; | ||
251 | tmpbuffer = kmalloc(len, GFP_KERNEL); | ||
252 | if (tmpbuffer == NULL) { | ||
253 | kfree(full_path); | ||
254 | FreeXid(xid); | ||
255 | return -ENOMEM; | ||
256 | } | ||
257 | |||
258 | /* BB add read reparse point symlink code and | ||
259 | Unix extensions symlink code here BB */ | ||
260 | |||
261 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | ||
262 | cERROR(1, ("SFU style symlinks not implemented yet")); | ||
263 | /* add open and read as in fs/cifs/inode.c */ | ||
264 | } else { | ||
265 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, | ||
266 | OPEN_REPARSE_POINT, &fid, &oplock, NULL, | ||
267 | cifs_sb->local_nls, | ||
268 | cifs_sb->mnt_cifs_flags & | ||
269 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
270 | if (!rc) { | ||
271 | rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, | ||
272 | tmpbuffer, | ||
273 | len - 1, | ||
274 | fid, | ||
275 | cifs_sb->local_nls); | ||
276 | if (CIFSSMBClose(xid, pTcon, fid)) { | ||
277 | cFYI(1, ("Error closing junction point " | ||
278 | "(open for ioctl)")); | ||
279 | } | ||
280 | /* If it is a DFS junction earlier we would have gotten | ||
281 | PATH_NOT_COVERED returned from server so we do | ||
282 | not need to request the DFS info here */ | ||
283 | } | ||
284 | } | ||
285 | /* BB Anything else to do to handle recursive links? */ | ||
286 | /* BB Should we be using page ops here? */ | ||
287 | |||
288 | /* BB null terminate returned string in pBuffer? BB */ | ||
289 | if (rc == 0) { | ||
290 | rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer); | ||
291 | cFYI(1, | ||
292 | ("vfs_readlink called from cifs_readlink returned %d", | ||
293 | rc)); | ||
294 | } | ||
295 | |||
296 | kfree(tmpbuffer); | ||
297 | kfree(full_path); | ||
298 | FreeXid(xid); | ||
299 | return rc; | ||
300 | } | ||
301 | |||
302 | void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) | 215 | void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) |
303 | { | 216 | { |
304 | char *p = nd_get_link(nd); | 217 | char *p = nd_get_link(nd); |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 5bc9ab7586bc..df003fe3710f 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -445,6 +445,38 @@ static void unix_fill_in_inode(struct inode *tmp_inode, | |||
445 | } | 445 | } |
446 | } | 446 | } |
447 | 447 | ||
448 | /* BB eventually need to add the following helper function to | ||
449 | resolve NT_STATUS_STOPPED_ON_SYMLINK return code when | ||
450 | we try to do FindFirst on (NTFS) directory symlinks */ | ||
451 | /* | ||
452 | int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, | ||
453 | int xid) | ||
454 | { | ||
455 | __u16 fid; | ||
456 | int len; | ||
457 | int oplock = 0; | ||
458 | int rc; | ||
459 | struct cifsTconInfo *ptcon = cifs_sb->tcon; | ||
460 | char *tmpbuffer; | ||
461 | |||
462 | rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, | ||
463 | OPEN_REPARSE_POINT, &fid, &oplock, NULL, | ||
464 | cifs_sb->local_nls, | ||
465 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
466 | if (!rc) { | ||
467 | tmpbuffer = kmalloc(maxpath); | ||
468 | rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, | ||
469 | tmpbuffer, | ||
470 | maxpath -1, | ||
471 | fid, | ||
472 | cifs_sb->local_nls); | ||
473 | if (CIFSSMBClose(xid, ptcon, fid)) { | ||
474 | cFYI(1, ("Error closing temporary reparsepoint open)")); | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 | */ | ||
479 | |||
448 | static int initiate_cifs_search(const int xid, struct file *file) | 480 | static int initiate_cifs_search(const int xid, struct file *file) |
449 | { | 481 | { |
450 | int rc = 0; | 482 | int rc = 0; |
@@ -500,7 +532,10 @@ ffirst_retry: | |||
500 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); | 532 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); |
501 | if (rc == 0) | 533 | if (rc == 0) |
502 | cifsFile->invalidHandle = false; | 534 | cifsFile->invalidHandle = false; |
503 | if ((rc == -EOPNOTSUPP) && | 535 | /* BB add following call to handle readdir on new NTFS symlink errors |
536 | else if STATUS_STOPPED_ON_SYMLINK | ||
537 | call get_symlink_reparse_path and retry with new path */ | ||
538 | else if ((rc == -EOPNOTSUPP) && | ||
504 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { | 539 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { |
505 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; | 540 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; |
506 | goto ffirst_retry; | 541 | goto ffirst_retry; |