[patch 07/33] cifs: make sure we allocate enough storage forsocket address

From: Greg KH
Date: Wed Feb 04 2009 - 13:39:49 EST


2.6.28-stable review patch. If anyone has any objections, please let us know.

------------------

From: Jeff Layton <jlayton@xxxxxxxxxx>

commit a9ac49d303f967be0dabd97cb722c4a13109c6c2 upstream.

cifs_mount declares a struct sockaddr on the stack and then casts it
to the proper address type. The storage allocated is fine for ipv4,
but is too small for ipv6 addresses. Declare it as
"struct sockaddr_storage" instead of struct sockaddr".

This bug was manifesting itself as oopses and address corruption when
mounting IPv6 addresses.

Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
Tested-by: Stefan Bader <stefan.bader@xxxxxxxxxxxxx>
Signed-off-by: Steve French <sfrench@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
fs/cifs/connect.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1356,7 +1356,7 @@ cifs_parse_mount_options(char *options,
}

static struct TCP_Server_Info *
-cifs_find_tcp_session(struct sockaddr *addr)
+cifs_find_tcp_session(struct sockaddr_storage *addr)
{
struct list_head *tmp;
struct TCP_Server_Info *server;
@@ -1376,11 +1376,11 @@ cifs_find_tcp_session(struct sockaddr *a
if (server->tcpStatus == CifsNew)
continue;

- if (addr->sa_family == AF_INET &&
+ if (addr->ss_family == AF_INET &&
(addr4->sin_addr.s_addr !=
server->addr.sockAddr.sin_addr.s_addr))
continue;
- else if (addr->sa_family == AF_INET6 &&
+ else if (addr->ss_family == AF_INET6 &&
memcmp(&server->addr.sockAddr6.sin6_addr,
&addr6->sin6_addr, sizeof(addr6->sin6_addr)))
continue;
@@ -2036,7 +2036,7 @@ cifs_mount(struct super_block *sb, struc
int rc = 0;
int xid;
struct socket *csocket = NULL;
- struct sockaddr addr;
+ struct sockaddr_storage addr;
struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
struct smb_vol volume_info;
@@ -2048,7 +2048,7 @@ cifs_mount(struct super_block *sb, struc

/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */

- memset(&addr, 0, sizeof(struct sockaddr));
+ memset(&addr, 0, sizeof(struct sockaddr_storage));
memset(&volume_info, 0, sizeof(struct smb_vol));
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
rc = -EINVAL;
@@ -2078,9 +2078,9 @@ cifs_mount(struct super_block *sb, struc
rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
&sin_server6->sin6_addr.in6_u);
if (rc > 0)
- addr.sa_family = AF_INET6;
+ addr.ss_family = AF_INET6;
} else {
- addr.sa_family = AF_INET;
+ addr.ss_family = AF_INET;
}

if (rc <= 0) {
@@ -2122,7 +2122,7 @@ cifs_mount(struct super_block *sb, struc

srvTcp = cifs_find_tcp_session(&addr);
if (!srvTcp) { /* create socket */
- if (addr.sa_family == AF_INET6) {
+ if (addr.ss_family == AF_INET6) {
cFYI(1, ("attempting ipv6 connect"));
/* BB should we allow ipv6 on port 139? */
/* other OS never observed in Wild doing 139 with v6 */
@@ -2153,7 +2153,7 @@ cifs_mount(struct super_block *sb, struc
} else {
srvTcp->noblocksnd = volume_info.noblocksnd;
srvTcp->noautotune = volume_info.noautotune;
- if (addr.sa_family == AF_INET6)
+ if (addr.ss_family == AF_INET6)
memcpy(&srvTcp->addr.sockAddr6, sin_server6,
sizeof(struct sockaddr_in6));
else

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/