diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-09-02 14:30:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-09-02 14:30:10 -0400 |
commit | 5b716ac728bcc01b1f2a7ed6e437196602237c27 (patch) | |
tree | b2c31c641ca04b72218e00ffebc07d3e8fe303f4 | |
parent | 0b1a34c992853ecb47daa5be598d7ed2930342dc (diff) | |
parent | ea7b4887e7266b93fa0c203cc452a926a0fef4f0 (diff) |
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French.
* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
CIFS: Fix cifs_do_create error hadnling
cifs: print error code if smb signature verification fails
CIFS: Fix log messages in packet checking for SMB2
CIFS: Protect i_nlink from being negative
-rw-r--r-- | fs/cifs/cifssmb.c | 11 | ||||
-rw-r--r-- | fs/cifs/dir.c | 9 | ||||
-rw-r--r-- | fs/cifs/inode.c | 24 | ||||
-rw-r--r-- | fs/cifs/link.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 16 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 10 | ||||
-rw-r--r-- | fs/cifs/transport.c | 9 |
7 files changed, 48 insertions, 33 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 074923ce593d..f0cf934ba877 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1576,9 +1576,14 @@ cifs_readv_callback(struct mid_q_entry *mid) | |||
1576 | /* result already set, check signature */ | 1576 | /* result already set, check signature */ |
1577 | if (server->sec_mode & | 1577 | if (server->sec_mode & |
1578 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | 1578 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { |
1579 | if (cifs_verify_signature(rdata->iov, rdata->nr_iov, | 1579 | int rc = 0; |
1580 | server, mid->sequence_number + 1)) | 1580 | |
1581 | cERROR(1, "Unexpected SMB signature"); | 1581 | rc = cifs_verify_signature(rdata->iov, rdata->nr_iov, |
1582 | server, | ||
1583 | mid->sequence_number + 1); | ||
1584 | if (rc) | ||
1585 | cERROR(1, "SMB signature verification returned " | ||
1586 | "error = %d", rc); | ||
1582 | } | 1587 | } |
1583 | /* FIXME: should this be counted toward the initiating task? */ | 1588 | /* FIXME: should this be counted toward the initiating task? */ |
1584 | task_io_account_read(rdata->bytes); | 1589 | task_io_account_read(rdata->bytes); |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index cbe709ad6663..781025be48bc 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -356,19 +356,12 @@ cifs_create_get_file_info: | |||
356 | cifs_create_set_dentry: | 356 | cifs_create_set_dentry: |
357 | if (rc != 0) { | 357 | if (rc != 0) { |
358 | cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); | 358 | cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); |
359 | CIFSSMBClose(xid, tcon, *fileHandle); | ||
359 | goto out; | 360 | goto out; |
360 | } | 361 | } |
361 | d_drop(direntry); | 362 | d_drop(direntry); |
362 | d_add(direntry, newinode); | 363 | d_add(direntry, newinode); |
363 | 364 | ||
364 | /* ENOENT for create? How weird... */ | ||
365 | rc = -ENOENT; | ||
366 | if (!newinode) { | ||
367 | CIFSSMBClose(xid, tcon, *fileHandle); | ||
368 | goto out; | ||
369 | } | ||
370 | rc = 0; | ||
371 | |||
372 | out: | 365 | out: |
373 | kfree(buf); | 366 | kfree(buf); |
374 | kfree(full_path); | 367 | kfree(full_path); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 7354877fa3bd..cb79c7edecb0 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -124,10 +124,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
124 | { | 124 | { |
125 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 125 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
126 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 126 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
127 | unsigned long oldtime = cifs_i->time; | ||
128 | 127 | ||
129 | cifs_revalidate_cache(inode, fattr); | 128 | cifs_revalidate_cache(inode, fattr); |
130 | 129 | ||
130 | spin_lock(&inode->i_lock); | ||
131 | inode->i_atime = fattr->cf_atime; | 131 | inode->i_atime = fattr->cf_atime; |
132 | inode->i_mtime = fattr->cf_mtime; | 132 | inode->i_mtime = fattr->cf_mtime; |
133 | inode->i_ctime = fattr->cf_ctime; | 133 | inode->i_ctime = fattr->cf_ctime; |
@@ -148,9 +148,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
148 | else | 148 | else |
149 | cifs_i->time = jiffies; | 149 | cifs_i->time = jiffies; |
150 | 150 | ||
151 | cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode, | ||
152 | oldtime, cifs_i->time); | ||
153 | |||
154 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; | 151 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; |
155 | 152 | ||
156 | cifs_i->server_eof = fattr->cf_eof; | 153 | cifs_i->server_eof = fattr->cf_eof; |
@@ -158,7 +155,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
158 | * Can't safely change the file size here if the client is writing to | 155 | * Can't safely change the file size here if the client is writing to |
159 | * it due to potential races. | 156 | * it due to potential races. |
160 | */ | 157 | */ |
161 | spin_lock(&inode->i_lock); | ||
162 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { | 158 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { |
163 | i_size_write(inode, fattr->cf_eof); | 159 | i_size_write(inode, fattr->cf_eof); |
164 | 160 | ||
@@ -859,12 +855,14 @@ struct inode *cifs_root_iget(struct super_block *sb) | |||
859 | 855 | ||
860 | if (rc && tcon->ipc) { | 856 | if (rc && tcon->ipc) { |
861 | cFYI(1, "ipc connection - fake read inode"); | 857 | cFYI(1, "ipc connection - fake read inode"); |
858 | spin_lock(&inode->i_lock); | ||
862 | inode->i_mode |= S_IFDIR; | 859 | inode->i_mode |= S_IFDIR; |
863 | set_nlink(inode, 2); | 860 | set_nlink(inode, 2); |
864 | inode->i_op = &cifs_ipc_inode_ops; | 861 | inode->i_op = &cifs_ipc_inode_ops; |
865 | inode->i_fop = &simple_dir_operations; | 862 | inode->i_fop = &simple_dir_operations; |
866 | inode->i_uid = cifs_sb->mnt_uid; | 863 | inode->i_uid = cifs_sb->mnt_uid; |
867 | inode->i_gid = cifs_sb->mnt_gid; | 864 | inode->i_gid = cifs_sb->mnt_gid; |
865 | spin_unlock(&inode->i_lock); | ||
868 | } else if (rc) { | 866 | } else if (rc) { |
869 | iget_failed(inode); | 867 | iget_failed(inode); |
870 | inode = ERR_PTR(rc); | 868 | inode = ERR_PTR(rc); |
@@ -1110,6 +1108,15 @@ undo_setattr: | |||
1110 | goto out_close; | 1108 | goto out_close; |
1111 | } | 1109 | } |
1112 | 1110 | ||
1111 | /* copied from fs/nfs/dir.c with small changes */ | ||
1112 | static void | ||
1113 | cifs_drop_nlink(struct inode *inode) | ||
1114 | { | ||
1115 | spin_lock(&inode->i_lock); | ||
1116 | if (inode->i_nlink > 0) | ||
1117 | drop_nlink(inode); | ||
1118 | spin_unlock(&inode->i_lock); | ||
1119 | } | ||
1113 | 1120 | ||
1114 | /* | 1121 | /* |
1115 | * If dentry->d_inode is null (usually meaning the cached dentry | 1122 | * If dentry->d_inode is null (usually meaning the cached dentry |
@@ -1166,13 +1173,13 @@ retry_std_delete: | |||
1166 | psx_del_no_retry: | 1173 | psx_del_no_retry: |
1167 | if (!rc) { | 1174 | if (!rc) { |
1168 | if (inode) | 1175 | if (inode) |
1169 | drop_nlink(inode); | 1176 | cifs_drop_nlink(inode); |
1170 | } else if (rc == -ENOENT) { | 1177 | } else if (rc == -ENOENT) { |
1171 | d_drop(dentry); | 1178 | d_drop(dentry); |
1172 | } else if (rc == -ETXTBSY) { | 1179 | } else if (rc == -ETXTBSY) { |
1173 | rc = cifs_rename_pending_delete(full_path, dentry, xid); | 1180 | rc = cifs_rename_pending_delete(full_path, dentry, xid); |
1174 | if (rc == 0) | 1181 | if (rc == 0) |
1175 | drop_nlink(inode); | 1182 | cifs_drop_nlink(inode); |
1176 | } else if ((rc == -EACCES) && (dosattr == 0) && inode) { | 1183 | } else if ((rc == -EACCES) && (dosattr == 0) && inode) { |
1177 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); | 1184 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); |
1178 | if (attrs == NULL) { | 1185 | if (attrs == NULL) { |
@@ -1241,9 +1248,10 @@ cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode, | |||
1241 | * setting nlink not necessary except in cases where we failed to get it | 1248 | * setting nlink not necessary except in cases where we failed to get it |
1242 | * from the server or was set bogus | 1249 | * from the server or was set bogus |
1243 | */ | 1250 | */ |
1251 | spin_lock(&dentry->d_inode->i_lock); | ||
1244 | if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2)) | 1252 | if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2)) |
1245 | set_nlink(dentry->d_inode, 2); | 1253 | set_nlink(dentry->d_inode, 2); |
1246 | 1254 | spin_unlock(&dentry->d_inode->i_lock); | |
1247 | mode &= ~current_umask(); | 1255 | mode &= ~current_umask(); |
1248 | /* must turn on setgid bit if parent dir has it */ | 1256 | /* must turn on setgid bit if parent dir has it */ |
1249 | if (inode->i_mode & S_ISGID) | 1257 | if (inode->i_mode & S_ISGID) |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 09e4b3ae4564..e6ce3b112875 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -433,7 +433,9 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
433 | if (old_file->d_inode) { | 433 | if (old_file->d_inode) { |
434 | cifsInode = CIFS_I(old_file->d_inode); | 434 | cifsInode = CIFS_I(old_file->d_inode); |
435 | if (rc == 0) { | 435 | if (rc == 0) { |
436 | spin_lock(&old_file->d_inode->i_lock); | ||
436 | inc_nlink(old_file->d_inode); | 437 | inc_nlink(old_file->d_inode); |
438 | spin_unlock(&old_file->d_inode->i_lock); | ||
437 | /* BB should we make this contingent on superblock flag NOATIME? */ | 439 | /* BB should we make this contingent on superblock flag NOATIME? */ |
438 | /* old_file->d_inode->i_ctime = CURRENT_TIME;*/ | 440 | /* old_file->d_inode->i_ctime = CURRENT_TIME;*/ |
439 | /* parent dir timestamps will update from srv | 441 | /* parent dir timestamps will update from srv |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index a4ff5d547554..e4d3b9964167 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
@@ -52,7 +52,8 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | |||
52 | cERROR(1, "Bad protocol string signature header %x", | 52 | cERROR(1, "Bad protocol string signature header %x", |
53 | *(unsigned int *) hdr->ProtocolId); | 53 | *(unsigned int *) hdr->ProtocolId); |
54 | if (mid != hdr->MessageId) | 54 | if (mid != hdr->MessageId) |
55 | cERROR(1, "Mids do not match"); | 55 | cERROR(1, "Mids do not match: %llu and %llu", mid, |
56 | hdr->MessageId); | ||
56 | } | 57 | } |
57 | cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId); | 58 | cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId); |
58 | return 1; | 59 | return 1; |
@@ -107,7 +108,7 @@ smb2_check_message(char *buf, unsigned int length) | |||
107 | * ie Validate the wct via smb2_struct_sizes table above | 108 | * ie Validate the wct via smb2_struct_sizes table above |
108 | */ | 109 | */ |
109 | 110 | ||
110 | if (length < 2 + sizeof(struct smb2_hdr)) { | 111 | if (length < sizeof(struct smb2_pdu)) { |
111 | if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { | 112 | if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { |
112 | pdu->StructureSize2 = 0; | 113 | pdu->StructureSize2 = 0; |
113 | /* | 114 | /* |
@@ -121,15 +122,15 @@ smb2_check_message(char *buf, unsigned int length) | |||
121 | return 1; | 122 | return 1; |
122 | } | 123 | } |
123 | if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) { | 124 | if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) { |
124 | cERROR(1, "SMB length greater than maximum, mid=%lld", mid); | 125 | cERROR(1, "SMB length greater than maximum, mid=%llu", mid); |
125 | return 1; | 126 | return 1; |
126 | } | 127 | } |
127 | 128 | ||
128 | if (check_smb2_hdr(hdr, mid)) | 129 | if (check_smb2_hdr(hdr, mid)) |
129 | return 1; | 130 | return 1; |
130 | 131 | ||
131 | if (hdr->StructureSize != SMB2_HEADER_SIZE) { | 132 | if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { |
132 | cERROR(1, "Illegal structure size %d", | 133 | cERROR(1, "Illegal structure size %u", |
133 | le16_to_cpu(hdr->StructureSize)); | 134 | le16_to_cpu(hdr->StructureSize)); |
134 | return 1; | 135 | return 1; |
135 | } | 136 | } |
@@ -161,8 +162,9 @@ smb2_check_message(char *buf, unsigned int length) | |||
161 | if (4 + len != clc_len) { | 162 | if (4 + len != clc_len) { |
162 | cFYI(1, "Calculated size %u length %u mismatch mid %llu", | 163 | cFYI(1, "Calculated size %u length %u mismatch mid %llu", |
163 | clc_len, 4 + len, mid); | 164 | clc_len, 4 + len, mid); |
164 | if (clc_len == 4 + len + 1) /* BB FIXME (fix samba) */ | 165 | /* server can return one byte more */ |
165 | return 0; /* BB workaround Samba 3 bug SessSetup rsp */ | 166 | if (clc_len == 4 + len + 1) |
167 | return 0; | ||
166 | return 1; | 168 | return 1; |
167 | } | 169 | } |
168 | return 0; | 170 | return 0; |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index f37a1b41b402..c5fbfac5d576 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -87,10 +87,6 @@ | |||
87 | 87 | ||
88 | #define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe) | 88 | #define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe) |
89 | 89 | ||
90 | #define SMB2_HEADER_SIZE __constant_le16_to_cpu(64) | ||
91 | |||
92 | #define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9) | ||
93 | |||
94 | /* | 90 | /* |
95 | * SMB2 Header Definition | 91 | * SMB2 Header Definition |
96 | * | 92 | * |
@@ -99,6 +95,9 @@ | |||
99 | * "PDU" : "Protocol Data Unit" (ie a network "frame") | 95 | * "PDU" : "Protocol Data Unit" (ie a network "frame") |
100 | * | 96 | * |
101 | */ | 97 | */ |
98 | |||
99 | #define SMB2_HEADER_STRUCTURE_SIZE __constant_le16_to_cpu(64) | ||
100 | |||
102 | struct smb2_hdr { | 101 | struct smb2_hdr { |
103 | __be32 smb2_buf_length; /* big endian on wire */ | 102 | __be32 smb2_buf_length; /* big endian on wire */ |
104 | /* length is only two or three bytes - with | 103 | /* length is only two or three bytes - with |
@@ -140,6 +139,9 @@ struct smb2_pdu { | |||
140 | * command code name for the struct. Note that structures must be packed. | 139 | * command code name for the struct. Note that structures must be packed. |
141 | * | 140 | * |
142 | */ | 141 | */ |
142 | |||
143 | #define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9) | ||
144 | |||
143 | struct smb2_err_rsp { | 145 | struct smb2_err_rsp { |
144 | struct smb2_hdr hdr; | 146 | struct smb2_hdr hdr; |
145 | __le16 StructureSize; | 147 | __le16 StructureSize; |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 83867ef348df..d9b639b95fa8 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -503,13 +503,16 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
503 | /* convert the length into a more usable form */ | 503 | /* convert the length into a more usable form */ |
504 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | 504 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { |
505 | struct kvec iov; | 505 | struct kvec iov; |
506 | int rc = 0; | ||
506 | 507 | ||
507 | iov.iov_base = mid->resp_buf; | 508 | iov.iov_base = mid->resp_buf; |
508 | iov.iov_len = len; | 509 | iov.iov_len = len; |
509 | /* FIXME: add code to kill session */ | 510 | /* FIXME: add code to kill session */ |
510 | if (cifs_verify_signature(&iov, 1, server, | 511 | rc = cifs_verify_signature(&iov, 1, server, |
511 | mid->sequence_number + 1) != 0) | 512 | mid->sequence_number + 1); |
512 | cERROR(1, "Unexpected SMB signature"); | 513 | if (rc) |
514 | cERROR(1, "SMB signature verification returned error = " | ||
515 | "%d", rc); | ||
513 | } | 516 | } |
514 | 517 | ||
515 | /* BB special case reconnect tid and uid here? */ | 518 | /* BB special case reconnect tid and uid here? */ |