From 0496e02d8791e7f06673a19a181be30dad6eff70 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 30 Dec 2008 12:39:16 -0500 Subject: cifs: turn smb_send into a wrapper around smb_sendv cifs: turn smb_send into a wrapper around smb_sendv Rename smb_send2 to smb_sendv to make it consistent with kernel naming conventions for functions that take a vector. There's no need to have 2 functions to handle sending SMB calls. Turn smb_send into a wrapper around smb_sendv. This also allows us to properly mark the socket as needing to be reconnected when there's a partial send from smb_send. Also, in practice we always use the address and noblocksnd flag that's attached to the TCP_Server_Info. There's no need to pass them in as separate args to smb_sendv. Signed-off-by: Jeff Layton Acked-by: Dave Kleikamp Signed-off-by: Steve French --- fs/cifs/connect.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e9ea394ee07..7419576228f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1860,9 +1860,7 @@ ipv4_connect(struct TCP_Server_Info *server) smb_buf = (struct smb_hdr *)ses_init_buf; /* sizeof RFC1002_SESSION_REQUEST with no scope */ smb_buf->smb_buf_length = 0x81000044; - rc = smb_send(socket, smb_buf, 0x44, - (struct sockaddr *) &server->addr.sockAddr, - server->noblocksnd); + rc = smb_send(server, smb_buf, 0x44); kfree(ses_init_buf); msleep(1); /* RFC1001 layer in at least one server requires very short break before negprot -- cgit From da505c386c9f993e43861791dae339b2219cf8dd Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 19 Jan 2009 03:49:35 +0000 Subject: [CIFS] Make socket retry timeouts consistent between blocking and nonblocking cases We have used approximately 15 second timeouts on nonblocking sends in the past, and also 15 second SMB timeout (waiting for server responses, for most request types). Now that we can do blocking tcp sends, make blocking send timeout approximately the same (15 seconds). Signed-off-by: Steve French --- fs/cifs/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 7419576228f..a3537a90a9d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1802,7 +1802,7 @@ ipv4_connect(struct TCP_Server_Info *server) * user space buffer */ socket->sk->sk_rcvtimeo = 7 * HZ; - socket->sk->sk_sndtimeo = 3 * HZ; + socket->sk->sk_sndtimeo = 5 * HZ; /* make the bufsizes depend on wsize/rsize and max requests */ if (server->noautotune) { @@ -1953,7 +1953,7 @@ ipv6_connect(struct TCP_Server_Info *server) * user space buffer */ socket->sk->sk_rcvtimeo = 7 * HZ; - socket->sk->sk_sndtimeo = 3 * HZ; + socket->sk->sk_sndtimeo = 5 * HZ; server->ssocket = socket; return rc; -- cgit From a9ac49d303f967be0dabd97cb722c4a13109c6c2 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 22 Jan 2009 14:43:21 -0500 Subject: cifs: make sure we allocate enough storage for socket address The sockaddr declared on the stack in cifs_get_tcp_session is too small for IPv6 addresses. Change it from "struct sockaddr" to "struct sockaddr_storage" to prevent stack corruption when IPv6 is used. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a3537a90a9d..2209be94305 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1354,7 +1354,7 @@ cifs_parse_mount_options(char *options, const char *devname, } 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; @@ -1374,11 +1374,11 @@ cifs_find_tcp_session(struct sockaddr *addr) 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; @@ -1419,12 +1419,12 @@ static struct TCP_Server_Info * cifs_get_tcp_session(struct smb_vol *volume_info) { struct TCP_Server_Info *tcp_ses = 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; int rc; - memset(&addr, 0, sizeof(struct sockaddr)); + memset(&addr, 0, sizeof(struct sockaddr_storage)); if (volume_info->UNCip && volume_info->UNC) { rc = cifs_inet_pton(AF_INET, volume_info->UNCip, @@ -1435,9 +1435,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info) 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) { @@ -1502,7 +1502,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) tcp_ses->tcpStatus = CifsNew; ++tcp_ses->srv_count; - 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 */ -- cgit From 0e2bedaa394f74fa9f75ee937488c33d90039b5a Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 30 Jan 2009 21:24:41 +0000 Subject: [CIFS] ipv6_addr_equal for address comparison Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2209be94305..005df85219a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -35,6 +34,7 @@ #include #include #include +#include #include "cifspdu.h" #include "cifsglob.h" #include "cifsproto.h" @@ -1379,8 +1379,8 @@ cifs_find_tcp_session(struct sockaddr_storage *addr) server->addr.sockAddr.sin_addr.s_addr)) continue; else if (addr->ss_family == AF_INET6 && - memcmp(&server->addr.sockAddr6.sin6_addr, - &addr6->sin6_addr, sizeof(addr6->sin6_addr))) + !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, + &addr6->sin6_addr)) continue; ++server->srv_count; -- cgit From e4cce94c9c8797b08faf6a79396df4d175e377fa Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Tue, 10 Feb 2009 14:10:26 +0300 Subject: [CIFS] Prevent OOPs when mounting with remote prefixpath. Fixes OOPs with message 'kernel BUG at fs/cifs/cifs_dfs_ref.c:274!'. Checks if the prefixpath in an accesible while we are still in cifs_mount and fails with reporting a error if we can't access the prefixpath Should fix Samba bugs 6086 and 5861 and kernel bug 12192 Signed-off-by: Igor Mammedov Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 005df85219a..da0f4ffa061 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2180,6 +2180,33 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, "mount option supported")); } +static int +is_path_accessible(int xid, struct cifsTconInfo *tcon, + struct cifs_sb_info *cifs_sb, const char *full_path) +{ + int rc; + __u64 inode_num; + FILE_ALL_INFO *pfile_info; + + rc = CIFSGetSrvInodeNumber(xid, tcon, full_path, &inode_num, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + if (rc != -EOPNOTSUPP) + return rc; + + pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); + if (pfile_info == NULL) + return -ENOMEM; + + rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info, + 0 /* not legacy */, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + kfree(pfile_info); + return rc; +} + int cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, char *mount_data, const char *devname) @@ -2190,6 +2217,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, struct cifsSesInfo *pSesInfo = NULL; struct cifsTconInfo *tcon = NULL; struct TCP_Server_Info *srvTcp = NULL; + char *full_path; xid = GetXid(); @@ -2426,6 +2454,23 @@ mount_fail_check: cifs_sb->rsize = min(cifs_sb->rsize, (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); + if (!rc && cifs_sb->prepathlen) { + /* build_path_to_root works only when we have a valid tcon */ + full_path = cifs_build_path_to_root(cifs_sb); + if (full_path == NULL) { + rc = -ENOMEM; + goto mount_fail_check; + } + rc = is_path_accessible(xid, tcon, cifs_sb, full_path); + if (rc) { + cERROR(1, ("Path %s in not accessible: %d", + full_path, rc)); + kfree(full_path); + goto mount_fail_check; + } + kfree(full_path); + } + /* volume_info->password is freed above when existing session found (in which case it is not needed anymore) but when new sesion is created the password ptr is put in the new session structure (in which case the -- cgit