]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.fixes/cifs-fix-ssh-tunneled-mounts
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / cifs-fix-ssh-tunneled-mounts
1 From: Suresh Jayaraman <sjayaraman@suse.de>
2 Subject: [PATCH] cifs: fix broken mounts when a SSH tunnel is used (try #4)
3 References: bnc#527754
4 Patch-mainline: in cifs-2.6.git (merge expected in 2.6.32-rcX)
5
6 It seems there is a regression that got introduced while Jeff fixed
7 all the mount/umount races. While attempting to find whether a tcp
8 session is already existing, we were not checking whether the "port"
9 used are the same. When a second mount is attempted with a different
10 "port=" option, it is being ignored. Because of this the cifs mounts
11 that uses a SSH tunnel appears to be broken.
12
13 Steps to reproduce:
14
15 1. create 2 shares
16 # SSH Tunnel a SMB session
17 2. ssh -f -L 6111:127.0.0.1:445 root@localhost "sleep 86400"
18 3. ssh -f -L 6222:127.0.0.1:445 root@localhost "sleep 86400"
19 4. tcpdump -i lo 6111 &
20 5. mkdir -p /mnt/mnt1
21 6. mkdir -p /mnt/mnt2
22 7. mount.cifs //localhost/a /mnt/mnt1 -o username=guest,ip=127.0.0.1,port=6111
23 #(shows tcpdump activity on port 6111)
24 8. mount.cifs //localhost/b /mnt/mnt2 -o username=guest,ip=127.0.0.1,port=6222
25 #(shows tcpdump activity only on port 6111 and not on 6222
26
27 Fix by adding a check to compare the port _only_ if the user tries to
28 override the tcp port with "port=" option, before deciding that an
29 existing tcp session is found. Also, clean up a bit by replacing
30 if-else if by a switch statment while at it as suggested by Jeff.
31
32 Reviewed-by: Jeff Layton <jlayton@redhat.com>
33 Reviewed-by: Shirish Pargaonkar <shirishp@us.ibm.com>
34 Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
35 Signed-off-by: Steve French <sfrench@us.ibm.com>
36 ---
37 fs/cifs/connect.c | 44 ++++++++++++++++++++++++++++++++++----------
38 1 file changed, 34 insertions(+), 10 deletions(-)
39
40 Index: linux-2.6.27-SLE11_BRANCH/fs/cifs/connect.c
41 ===================================================================
42 --- linux-2.6.27-SLE11_BRANCH.orig/fs/cifs/connect.c
43 +++ linux-2.6.27-SLE11_BRANCH/fs/cifs/connect.c
44 @@ -35,6 +35,7 @@
45 #include <linux/freezer.h>
46 #include <asm/uaccess.h>
47 #include <asm/processor.h>
48 +#include <net/ipv6.h>
49 #include "cifspdu.h"
50 #include "cifsglob.h"
51 #include "cifsproto.h"
52 @@ -1349,7 +1350,7 @@ cifs_parse_mount_options(char *options,
53 }
54
55 static struct TCP_Server_Info *
56 -cifs_find_tcp_session(struct sockaddr_storage *addr)
57 +cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
58 {
59 struct list_head *tmp;
60 struct TCP_Server_Info *server;
61 @@ -1369,14 +1370,37 @@ cifs_find_tcp_session(struct sockaddr_st
62 if (server->tcpStatus == CifsNew)
63 continue;
64
65 - if (addr->ss_family == AF_INET &&
66 - (addr4->sin_addr.s_addr !=
67 - server->addr.sockAddr.sin_addr.s_addr))
68 - continue;
69 - else if (addr->ss_family == AF_INET6 &&
70 - memcmp(&server->addr.sockAddr6.sin6_addr,
71 - &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
72 - continue;
73 + switch (addr->ss_family) {
74 + case AF_INET:
75 + if (addr4->sin_addr.s_addr ==
76 + server->addr.sockAddr.sin_addr.s_addr) {
77 + addr4->sin_port = htons(port);
78 + /* user overrode default port? */
79 + if (addr4->sin_port) {
80 + if (addr4->sin_port !=
81 + server->addr.sockAddr.sin_port)
82 + continue;
83 + }
84 + break;
85 + } else
86 + continue;
87 +
88 + case AF_INET6:
89 + if (ipv6_addr_equal(&addr6->sin6_addr,
90 + &server->addr.sockAddr6.sin6_addr) &&
91 + (addr6->sin6_scope_id ==
92 + server->addr.sockAddr6.sin6_scope_id)) {
93 + addr6->sin6_port = htons(port);
94 + /* user overrode default port? */
95 + if (addr6->sin6_port) {
96 + if (addr6->sin6_port !=
97 + server->addr.sockAddr6.sin6_port)
98 + continue;
99 + }
100 + break;
101 + } else
102 + continue;
103 + }
104
105 ++server->srv_count;
106 write_unlock(&cifs_tcp_ses_lock);
107 @@ -2111,7 +2135,7 @@ cifs_mount(struct super_block *sb, struc
108 }
109 }
110
111 - srvTcp = cifs_find_tcp_session(&addr);
112 + srvTcp = cifs_find_tcp_session(&addr, volume_info.port);
113 if (!srvTcp) { /* create socket */
114 if (addr.ss_family == AF_INET6) {
115 cFYI(1, ("attempting ipv6 connect"));