diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsglob.h | 4 | ||||
-rw-r--r-- | fs/cifs/connect.c | 37 | ||||
-rw-r--r-- | fs/cifs/transport.c | 3 | ||||
-rw-r--r-- | fs/namei.c | 20 | ||||
-rw-r--r-- | fs/open.c | 2 | ||||
-rw-r--r-- | fs/super.c | 5 |
6 files changed, 51 insertions, 20 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index edd5b29b53c9..17afb0fbcaed 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -188,6 +188,8 @@ struct TCP_Server_Info { | |||
188 | /* multiplexed reads or writes */ | 188 | /* multiplexed reads or writes */ |
189 | unsigned int maxBuf; /* maxBuf specifies the maximum */ | 189 | unsigned int maxBuf; /* maxBuf specifies the maximum */ |
190 | /* message size the server can send or receive for non-raw SMBs */ | 190 | /* message size the server can send or receive for non-raw SMBs */ |
191 | /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */ | ||
192 | /* when socket is setup (and during reconnect) before NegProt sent */ | ||
191 | unsigned int max_rw; /* maxRw specifies the maximum */ | 193 | unsigned int max_rw; /* maxRw specifies the maximum */ |
192 | /* message size the server can send or receive for */ | 194 | /* message size the server can send or receive for */ |
193 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ | 195 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ |
@@ -652,7 +654,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param, | |||
652 | #define MID_REQUEST_SUBMITTED 2 | 654 | #define MID_REQUEST_SUBMITTED 2 |
653 | #define MID_RESPONSE_RECEIVED 4 | 655 | #define MID_RESPONSE_RECEIVED 4 |
654 | #define MID_RETRY_NEEDED 8 /* session closed while this request out */ | 656 | #define MID_RETRY_NEEDED 8 /* session closed while this request out */ |
655 | #define MID_NO_RESP_NEEDED 0x10 | 657 | #define MID_RESPONSE_MALFORMED 0x10 |
656 | 658 | ||
657 | /* Types of response buffer returned from SendReceive2 */ | 659 | /* Types of response buffer returned from SendReceive2 */ |
658 | #define CIFS_NO_BUFFER 0 /* Response buffer not returned */ | 660 | #define CIFS_NO_BUFFER 0 /* Response buffer not returned */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 257b6d895e20..8d6c17ab593d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -338,10 +338,11 @@ cifs_echo_request(struct work_struct *work) | |||
338 | struct TCP_Server_Info, echo.work); | 338 | struct TCP_Server_Info, echo.work); |
339 | 339 | ||
340 | /* | 340 | /* |
341 | * We cannot send an echo until the NEGOTIATE_PROTOCOL request is done. | 341 | * We cannot send an echo until the NEGOTIATE_PROTOCOL request is |
342 | * Also, no need to ping if we got a response recently | 342 | * done, which is indicated by maxBuf != 0. Also, no need to ping if |
343 | * we got a response recently | ||
343 | */ | 344 | */ |
344 | if (server->tcpStatus != CifsGood || | 345 | if (server->maxBuf == 0 || |
345 | time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) | 346 | time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) |
346 | goto requeue_echo; | 347 | goto requeue_echo; |
347 | 348 | ||
@@ -585,11 +586,20 @@ incomplete_rcv: | |||
585 | total_read += 4; /* account for rfc1002 hdr */ | 586 | total_read += 4; /* account for rfc1002 hdr */ |
586 | 587 | ||
587 | dump_smb(smb_buffer, total_read); | 588 | dump_smb(smb_buffer, total_read); |
588 | if (checkSMB(smb_buffer, smb_buffer->Mid, total_read)) { | 589 | |
590 | /* | ||
591 | * We know that we received enough to get to the MID as we | ||
592 | * checked the pdu_length earlier. Now check to see | ||
593 | * if the rest of the header is OK. We borrow the length | ||
594 | * var for the rest of the loop to avoid a new stack var. | ||
595 | * | ||
596 | * 48 bytes is enough to display the header and a little bit | ||
597 | * into the payload for debugging purposes. | ||
598 | */ | ||
599 | length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); | ||
600 | if (length != 0) | ||
589 | cifs_dump_mem("Bad SMB: ", smb_buffer, | 601 | cifs_dump_mem("Bad SMB: ", smb_buffer, |
590 | total_read < 48 ? total_read : 48); | 602 | min_t(unsigned int, total_read, 48)); |
591 | continue; | ||
592 | } | ||
593 | 603 | ||
594 | mid_entry = NULL; | 604 | mid_entry = NULL; |
595 | server->lstrp = jiffies; | 605 | server->lstrp = jiffies; |
@@ -601,7 +611,8 @@ incomplete_rcv: | |||
601 | if ((mid_entry->mid == smb_buffer->Mid) && | 611 | if ((mid_entry->mid == smb_buffer->Mid) && |
602 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && | 612 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && |
603 | (mid_entry->command == smb_buffer->Command)) { | 613 | (mid_entry->command == smb_buffer->Command)) { |
604 | if (check2ndT2(smb_buffer,server->maxBuf) > 0) { | 614 | if (length == 0 && |
615 | check2ndT2(smb_buffer, server->maxBuf) > 0) { | ||
605 | /* We have a multipart transact2 resp */ | 616 | /* We have a multipart transact2 resp */ |
606 | isMultiRsp = true; | 617 | isMultiRsp = true; |
607 | if (mid_entry->resp_buf) { | 618 | if (mid_entry->resp_buf) { |
@@ -636,7 +647,12 @@ incomplete_rcv: | |||
636 | mid_entry->resp_buf = smb_buffer; | 647 | mid_entry->resp_buf = smb_buffer; |
637 | mid_entry->largeBuf = isLargeBuf; | 648 | mid_entry->largeBuf = isLargeBuf; |
638 | multi_t2_fnd: | 649 | multi_t2_fnd: |
639 | mid_entry->midState = MID_RESPONSE_RECEIVED; | 650 | if (length == 0) |
651 | mid_entry->midState = | ||
652 | MID_RESPONSE_RECEIVED; | ||
653 | else | ||
654 | mid_entry->midState = | ||
655 | MID_RESPONSE_MALFORMED; | ||
640 | #ifdef CONFIG_CIFS_STATS2 | 656 | #ifdef CONFIG_CIFS_STATS2 |
641 | mid_entry->when_received = jiffies; | 657 | mid_entry->when_received = jiffies; |
642 | #endif | 658 | #endif |
@@ -657,6 +673,9 @@ multi_t2_fnd: | |||
657 | else | 673 | else |
658 | smallbuf = NULL; | 674 | smallbuf = NULL; |
659 | } | 675 | } |
676 | } else if (length != 0) { | ||
677 | /* response sanity checks failed */ | ||
678 | continue; | ||
660 | } else if (!is_valid_oplock_break(smb_buffer, server) && | 679 | } else if (!is_valid_oplock_break(smb_buffer, server) && |
661 | !isMultiRsp) { | 680 | !isMultiRsp) { |
662 | cERROR(1, "No task to wake, unknown frame received! " | 681 | cERROR(1, "No task to wake, unknown frame received! " |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index fbc5aace54b1..46d8756f2b24 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -457,6 +457,9 @@ sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) | |||
457 | case MID_RETRY_NEEDED: | 457 | case MID_RETRY_NEEDED: |
458 | rc = -EAGAIN; | 458 | rc = -EAGAIN; |
459 | break; | 459 | break; |
460 | case MID_RESPONSE_MALFORMED: | ||
461 | rc = -EIO; | ||
462 | break; | ||
460 | default: | 463 | default: |
461 | cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, | 464 | cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, |
462 | mid->mid, mid->midState); | 465 | mid->mid, mid->midState); |
diff --git a/fs/namei.c b/fs/namei.c index 7d77f24d32a9..ec4b2d0190a8 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -561,10 +561,14 @@ static inline int nameidata_drop_rcu_last_maybe(struct nameidata *nd) | |||
561 | */ | 561 | */ |
562 | void release_open_intent(struct nameidata *nd) | 562 | void release_open_intent(struct nameidata *nd) |
563 | { | 563 | { |
564 | if (nd->intent.open.file->f_path.dentry == NULL) | 564 | struct file *file = nd->intent.open.file; |
565 | put_filp(nd->intent.open.file); | 565 | |
566 | else | 566 | if (file && !IS_ERR(file)) { |
567 | fput(nd->intent.open.file); | 567 | if (file->f_path.dentry == NULL) |
568 | put_filp(file); | ||
569 | else | ||
570 | fput(file); | ||
571 | } | ||
568 | } | 572 | } |
569 | 573 | ||
570 | /* | 574 | /* |
@@ -2265,8 +2269,6 @@ static struct file *finish_open(struct nameidata *nd, | |||
2265 | return filp; | 2269 | return filp; |
2266 | 2270 | ||
2267 | exit: | 2271 | exit: |
2268 | if (!IS_ERR(nd->intent.open.file)) | ||
2269 | release_open_intent(nd); | ||
2270 | path_put(&nd->path); | 2272 | path_put(&nd->path); |
2271 | return ERR_PTR(error); | 2273 | return ERR_PTR(error); |
2272 | } | 2274 | } |
@@ -2389,8 +2391,6 @@ exit_mutex_unlock: | |||
2389 | exit_dput: | 2391 | exit_dput: |
2390 | path_put_conditional(path, nd); | 2392 | path_put_conditional(path, nd); |
2391 | exit: | 2393 | exit: |
2392 | if (!IS_ERR(nd->intent.open.file)) | ||
2393 | release_open_intent(nd); | ||
2394 | path_put(&nd->path); | 2394 | path_put(&nd->path); |
2395 | return ERR_PTR(error); | 2395 | return ERR_PTR(error); |
2396 | } | 2396 | } |
@@ -2477,6 +2477,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
2477 | } | 2477 | } |
2478 | audit_inode(pathname, nd.path.dentry); | 2478 | audit_inode(pathname, nd.path.dentry); |
2479 | filp = finish_open(&nd, open_flag, acc_mode); | 2479 | filp = finish_open(&nd, open_flag, acc_mode); |
2480 | release_open_intent(&nd); | ||
2480 | return filp; | 2481 | return filp; |
2481 | 2482 | ||
2482 | creat: | 2483 | creat: |
@@ -2553,6 +2554,7 @@ out: | |||
2553 | path_put(&nd.root); | 2554 | path_put(&nd.root); |
2554 | if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL)) | 2555 | if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL)) |
2555 | goto reval; | 2556 | goto reval; |
2557 | release_open_intent(&nd); | ||
2556 | return filp; | 2558 | return filp; |
2557 | 2559 | ||
2558 | exit_dput: | 2560 | exit_dput: |
@@ -2560,8 +2562,6 @@ exit_dput: | |||
2560 | out_path: | 2562 | out_path: |
2561 | path_put(&nd.path); | 2563 | path_put(&nd.path); |
2562 | out_filp: | 2564 | out_filp: |
2563 | if (!IS_ERR(nd.intent.open.file)) | ||
2564 | release_open_intent(&nd); | ||
2565 | filp = ERR_PTR(error); | 2565 | filp = ERR_PTR(error); |
2566 | goto out; | 2566 | goto out; |
2567 | } | 2567 | } |
@@ -790,6 +790,8 @@ struct file *nameidata_to_filp(struct nameidata *nd) | |||
790 | 790 | ||
791 | /* Pick up the filp from the open intent */ | 791 | /* Pick up the filp from the open intent */ |
792 | filp = nd->intent.open.file; | 792 | filp = nd->intent.open.file; |
793 | nd->intent.open.file = NULL; | ||
794 | |||
793 | /* Has the filesystem initialised the file for us? */ | 795 | /* Has the filesystem initialised the file for us? */ |
794 | if (filp->f_path.dentry == NULL) { | 796 | if (filp->f_path.dentry == NULL) { |
795 | path_get(&nd->path); | 797 | path_get(&nd->path); |
diff --git a/fs/super.c b/fs/super.c index 74e149efed81..7e9dd4cc2c01 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -177,6 +177,11 @@ void deactivate_locked_super(struct super_block *s) | |||
177 | struct file_system_type *fs = s->s_type; | 177 | struct file_system_type *fs = s->s_type; |
178 | if (atomic_dec_and_test(&s->s_active)) { | 178 | if (atomic_dec_and_test(&s->s_active)) { |
179 | fs->kill_sb(s); | 179 | fs->kill_sb(s); |
180 | /* | ||
181 | * We need to call rcu_barrier so all the delayed rcu free | ||
182 | * inodes are flushed before we release the fs module. | ||
183 | */ | ||
184 | rcu_barrier(); | ||
180 | put_filesystem(fs); | 185 | put_filesystem(fs); |
181 | put_super(s); | 186 | put_super(s); |
182 | } else { | 187 | } else { |