aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-09-02 14:30:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-09-02 14:30:10 -0400
commit5b716ac728bcc01b1f2a7ed6e437196602237c27 (patch)
treeb2c31c641ca04b72218e00ffebc07d3e8fe303f4
parent0b1a34c992853ecb47daa5be598d7ed2930342dc (diff)
parentea7b4887e7266b93fa0c203cc452a926a0fef4f0 (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.c11
-rw-r--r--fs/cifs/dir.c9
-rw-r--r--fs/cifs/inode.c24
-rw-r--r--fs/cifs/link.c2
-rw-r--r--fs/cifs/smb2misc.c16
-rw-r--r--fs/cifs/smb2pdu.h10
-rw-r--r--fs/cifs/transport.c9
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:
356cifs_create_set_dentry: 356cifs_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
372out: 365out:
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 */
1112static void
1113cifs_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:
1166psx_del_no_retry: 1173psx_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
102struct smb2_hdr { 101struct 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
143struct smb2_err_rsp { 145struct 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? */