diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-09-03 12:00:50 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-09-08 17:22:35 -0400 |
commit | 32670396e7fc6e4f37451a69339968985461a374 (patch) | |
tree | df01cb3461125f341d61bde1d527f575372803ef | |
parent | 7332f2a6217ee6925f83ef0e725013067ed316ba (diff) |
cifs: prevent possible memory corruption in cifs_demultiplex_thread
cifs_demultiplex_thread sets the addr.sockAddr.sin_port without any
regard for the socket family. While it may be that the error in question
here never occurs on an IPv6 socket, it's probably best to be safe and
set the port properly if it ever does.
Break the port setting code out of cifs_fill_sockaddr and into a new
function, and call that from cifs_demultiplex_thread.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
-rw-r--r-- | fs/cifs/connect.c | 3 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 22 |
3 files changed, 17 insertions, 11 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index f399b16cb7d5..1d60c655e3e0 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | |||
87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
88 | struct TCP_Server_Info *server); | 88 | struct TCP_Server_Info *server); |
89 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); | 89 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); |
90 | extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); | ||
90 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | 91 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, |
91 | unsigned short int port); | 92 | const unsigned short int port); |
92 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); | 93 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); |
93 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 94 | extern void header_assemble(struct smb_hdr *, char /* command */ , |
94 | const struct cifsTconInfo *, int /* length of | 95 | const struct cifsTconInfo *, int /* length of |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5fde83f0c75e..67dad54fbfa1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -463,7 +463,8 @@ incomplete_rcv: | |||
463 | * is since we do not begin with RFC1001 session | 463 | * is since we do not begin with RFC1001 session |
464 | * initialize frame) | 464 | * initialize frame) |
465 | */ | 465 | */ |
466 | server->addr.sockAddr.sin_port = htons(CIFS_PORT); | 466 | cifs_set_port((struct sockaddr *) |
467 | &server->addr.sockAddr, CIFS_PORT); | ||
467 | cifs_reconnect(server); | 468 | cifs_reconnect(server); |
468 | csocket = server->ssocket; | 469 | csocket = server->ssocket; |
469 | wake_up(&server->response_q); | 470 | wake_up(&server->response_q); |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f97851119e6c..9aad47a2d62f 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -206,26 +206,30 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) | |||
206 | } | 206 | } |
207 | 207 | ||
208 | int | 208 | int |
209 | cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | 209 | cifs_set_port(struct sockaddr *addr, const unsigned short int port) |
210 | const unsigned short int port) | ||
211 | { | 210 | { |
212 | if (!cifs_convert_address(dst, src, len)) | 211 | switch (addr->sa_family) { |
213 | return 0; | ||
214 | |||
215 | switch (dst->sa_family) { | ||
216 | case AF_INET: | 212 | case AF_INET: |
217 | ((struct sockaddr_in *)dst)->sin_port = htons(port); | 213 | ((struct sockaddr_in *)addr)->sin_port = htons(port); |
218 | break; | 214 | break; |
219 | case AF_INET6: | 215 | case AF_INET6: |
220 | ((struct sockaddr_in6 *)dst)->sin6_port = htons(port); | 216 | ((struct sockaddr_in6 *)addr)->sin6_port = htons(port); |
221 | break; | 217 | break; |
222 | default: | 218 | default: |
223 | return 0; | 219 | return 0; |
224 | } | 220 | } |
225 | |||
226 | return 1; | 221 | return 1; |
227 | } | 222 | } |
228 | 223 | ||
224 | int | ||
225 | cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | ||
226 | const unsigned short int port) | ||
227 | { | ||
228 | if (!cifs_convert_address(dst, src, len)) | ||
229 | return 0; | ||
230 | return cifs_set_port(dst, port); | ||
231 | } | ||
232 | |||
229 | /***************************************************************************** | 233 | /***************************************************************************** |
230 | convert a NT status code to a dos class/code | 234 | convert a NT status code to a dos class/code |
231 | *****************************************************************************/ | 235 | *****************************************************************************/ |