Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * fs/cifs/connect.c |
| 3 | * |
Steve French | 1080ef7 | 2011-02-24 18:07:19 +0000 | [diff] [blame] | 4 | * Copyright (C) International Business Machines Corp., 2002,2011 |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 6 | * |
| 7 | * This library is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU Lesser General Public License as published |
| 9 | * by the Free Software Foundation; either version 2.1 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | * |
| 12 | * This library is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| 15 | * the GNU Lesser General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU Lesser General Public License |
| 18 | * along with this library; if not, write to the Free Software |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 20 | */ |
| 21 | #include <linux/fs.h> |
| 22 | #include <linux/net.h> |
| 23 | #include <linux/string.h> |
Eric Biggers | dc92027 | 2020-03-08 22:58:20 -0700 | [diff] [blame] | 24 | #include <linux/sched/mm.h> |
Ingo Molnar | 3f07c01 | 2017-02-08 18:51:30 +0100 | [diff] [blame] | 25 | #include <linux/sched/signal.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 26 | #include <linux/list.h> |
| 27 | #include <linux/wait.h> |
Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 28 | #include <linux/slab.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 29 | #include <linux/pagemap.h> |
| 30 | #include <linux/ctype.h> |
| 31 | #include <linux/utsname.h> |
| 32 | #include <linux/mempool.h> |
Steve French | b8643e1 | 2005-04-28 22:41:07 -0700 | [diff] [blame] | 33 | #include <linux/delay.h> |
Steve French | f191401 | 2005-08-18 09:37:34 -0700 | [diff] [blame] | 34 | #include <linux/completion.h> |
Igor Mammedov | aaf737a | 2007-04-03 19:16:43 +0000 | [diff] [blame] | 35 | #include <linux/kthread.h> |
Steve French | 0ae0efa | 2005-10-10 10:57:19 -0700 | [diff] [blame] | 36 | #include <linux/pagevec.h> |
Nigel Cunningham | 7dfb710 | 2006-12-06 20:34:23 -0800 | [diff] [blame] | 37 | #include <linux/freezer.h> |
Igor Mammedov | 5c2503a | 2009-04-21 19:31:05 +0400 | [diff] [blame] | 38 | #include <linux/namei.h> |
Andrew Lunn | c6e970a | 2017-03-28 23:45:06 +0200 | [diff] [blame] | 39 | #include <linux/uuid.h> |
Linus Torvalds | 7c0f6ba | 2016-12-24 11:46:01 -0800 | [diff] [blame] | 40 | #include <linux/uaccess.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 41 | #include <asm/processor.h> |
Jeff Layton | 50b64e3 | 2009-06-02 06:55:20 -0400 | [diff] [blame] | 42 | #include <linux/inet.h> |
Paul Gortmaker | 143cb49 | 2011-07-01 14:23:34 -0400 | [diff] [blame] | 43 | #include <linux/module.h> |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 44 | #include <keys/user-type.h> |
Steve French | 0e2beda | 2009-01-30 21:24:41 +0000 | [diff] [blame] | 45 | #include <net/ipv6.h> |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 46 | #include <linux/parser.h> |
Christoph Hellwig | 2f8b544 | 2016-11-01 07:40:13 -0600 | [diff] [blame] | 47 | #include <linux/bvec.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 48 | #include "cifspdu.h" |
| 49 | #include "cifsglob.h" |
| 50 | #include "cifsproto.h" |
| 51 | #include "cifs_unicode.h" |
| 52 | #include "cifs_debug.h" |
| 53 | #include "cifs_fs_sb.h" |
| 54 | #include "ntlmssp.h" |
| 55 | #include "nterr.h" |
| 56 | #include "rfc1002pdu.h" |
Suresh Jayaraman | 488f1d2d | 2010-07-05 18:12:15 +0530 | [diff] [blame] | 57 | #include "fscache.h" |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 58 | #include "smb2proto.h" |
Long Li | 2f89464 | 2017-11-22 17:38:34 -0700 | [diff] [blame] | 59 | #include "smbdirect.h" |
Paulo Alcantara | 1c78022 | 2018-11-14 16:24:03 -0200 | [diff] [blame] | 60 | #include "dns_resolve.h" |
| 61 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 62 | #include "dfs_cache.h" |
| 63 | #endif |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 64 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 | extern mempool_t *cifs_req_poolp; |
Steve French | f92a720 | 2018-05-24 04:11:07 -0500 | [diff] [blame] | 66 | extern bool disable_legacy_dialects; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 67 | |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 68 | /* FIXME: should these be tunable? */ |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 69 | #define TLINK_ERROR_EXPIRE (1 * HZ) |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 70 | #define TLINK_IDLE_EXPIRE (600 * HZ) |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 71 | |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 72 | enum { |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 73 | /* Mount options that take no arguments */ |
| 74 | Opt_user_xattr, Opt_nouser_xattr, |
| 75 | Opt_forceuid, Opt_noforceuid, |
Jeff Layton | 72bd481 | 2012-10-03 16:02:36 -0400 | [diff] [blame] | 76 | Opt_forcegid, Opt_noforcegid, |
Steve French | 3e7a02d | 2019-09-11 21:46:20 -0500 | [diff] [blame] | 77 | Opt_noblocksend, Opt_noautotune, Opt_nolease, |
Steve French | 82e9367 | 2020-05-19 03:06:57 -0500 | [diff] [blame] | 78 | Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_nodelete, |
Steve French | 2baa268 | 2014-09-27 02:19:01 -0500 | [diff] [blame] | 79 | Opt_mapposix, Opt_nomapposix, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 80 | Opt_mapchars, Opt_nomapchars, Opt_sfu, |
| 81 | Opt_nosfu, Opt_nodfs, Opt_posixpaths, |
Steve French | b326614 | 2018-05-20 23:41:10 -0500 | [diff] [blame] | 82 | Opt_noposixpaths, Opt_nounix, Opt_unix, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 83 | Opt_nocase, |
| 84 | Opt_brl, Opt_nobrl, |
Steve French | 3d4ef9a | 2018-04-25 22:19:09 -0500 | [diff] [blame] | 85 | Opt_handlecache, Opt_nohandlecache, |
Steve French | 9593265 | 2016-09-23 01:36:34 -0500 | [diff] [blame] | 86 | Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 87 | Opt_nosetuids, Opt_dynperm, Opt_nodynperm, |
| 88 | Opt_nohard, Opt_nosoft, |
| 89 | Opt_nointr, Opt_intr, |
| 90 | Opt_nostrictsync, Opt_strictsync, |
| 91 | Opt_serverino, Opt_noserverino, |
| 92 | Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl, |
| 93 | Opt_acl, Opt_noacl, Opt_locallease, |
Steve French | 4f5c10f | 2019-09-03 21:18:49 -0500 | [diff] [blame] | 94 | Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 95 | Opt_fsc, Opt_mfsymlinks, |
Jeff Layton | a0b3df5 | 2013-05-24 07:40:59 -0400 | [diff] [blame] | 96 | Opt_multiuser, Opt_sloppy, Opt_nosharesock, |
Steve French | b2a3077 | 2015-09-29 21:49:28 -0500 | [diff] [blame] | 97 | Opt_persistent, Opt_nopersistent, |
Steve French | 592fafe | 2015-11-03 10:08:53 -0600 | [diff] [blame] | 98 | Opt_resilient, Opt_noresilient, |
Paulo Alcantara (SUSE) | 8eecd1c | 2019-07-16 19:04:50 -0300 | [diff] [blame] | 99 | Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs, |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 100 | Opt_multichannel, Opt_nomultichannel, |
Steve French | 9fe5ff1 | 2019-06-24 20:39:04 -0500 | [diff] [blame] | 101 | Opt_compress, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 102 | |
| 103 | /* Mount options which take numeric value */ |
| 104 | Opt_backupuid, Opt_backupgid, Opt_uid, |
| 105 | Opt_cruid, Opt_gid, Opt_file_mode, |
| 106 | Opt_dirmode, Opt_port, |
Steve French | 563317e | 2019-09-08 23:22:02 -0500 | [diff] [blame] | 107 | Opt_min_enc_offload, |
Steve French | e8506d2 | 2019-02-28 21:32:15 -0600 | [diff] [blame] | 108 | Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo, |
Steve French | ca567eb | 2019-03-29 16:31:07 -0500 | [diff] [blame] | 109 | Opt_echo_interval, Opt_max_credits, Opt_handletimeout, |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 110 | Opt_snapshot, Opt_max_channels, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 111 | |
| 112 | /* Mount options which take string value */ |
| 113 | Opt_user, Opt_pass, Opt_ip, |
Jeff Layton | 73a999f | 2013-03-22 08:42:57 -0400 | [diff] [blame] | 114 | Opt_domain, Opt_srcaddr, Opt_iocharset, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 115 | Opt_netbiosname, Opt_servern, |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 116 | Opt_ver, Opt_vers, Opt_sec, Opt_cache, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 117 | |
| 118 | /* Mount options to be ignored */ |
| 119 | Opt_ignore, |
| 120 | |
| 121 | /* Options which could be blank */ |
| 122 | Opt_blank_pass, |
Sachin Prabhu | 4fe9e96 | 2012-04-10 18:12:27 +0100 | [diff] [blame] | 123 | Opt_blank_user, |
| 124 | Opt_blank_ip, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 125 | |
| 126 | Opt_err |
| 127 | }; |
| 128 | |
| 129 | static const match_table_t cifs_mount_option_tokens = { |
| 130 | |
| 131 | { Opt_user_xattr, "user_xattr" }, |
| 132 | { Opt_nouser_xattr, "nouser_xattr" }, |
| 133 | { Opt_forceuid, "forceuid" }, |
| 134 | { Opt_noforceuid, "noforceuid" }, |
Jeff Layton | 72bd481 | 2012-10-03 16:02:36 -0400 | [diff] [blame] | 135 | { Opt_forcegid, "forcegid" }, |
| 136 | { Opt_noforcegid, "noforcegid" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 137 | { Opt_noblocksend, "noblocksend" }, |
| 138 | { Opt_noautotune, "noautotune" }, |
Steve French | 3e7a02d | 2019-09-11 21:46:20 -0500 | [diff] [blame] | 139 | { Opt_nolease, "nolease" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 140 | { Opt_hard, "hard" }, |
| 141 | { Opt_soft, "soft" }, |
| 142 | { Opt_perm, "perm" }, |
| 143 | { Opt_noperm, "noperm" }, |
Steve French | 82e9367 | 2020-05-19 03:06:57 -0500 | [diff] [blame] | 144 | { Opt_nodelete, "nodelete" }, |
Steve French | 2baa268 | 2014-09-27 02:19:01 -0500 | [diff] [blame] | 145 | { Opt_mapchars, "mapchars" }, /* SFU style */ |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 146 | { Opt_nomapchars, "nomapchars" }, |
Steve French | 2baa268 | 2014-09-27 02:19:01 -0500 | [diff] [blame] | 147 | { Opt_mapposix, "mapposix" }, /* SFM style */ |
| 148 | { Opt_nomapposix, "nomapposix" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 149 | { Opt_sfu, "sfu" }, |
| 150 | { Opt_nosfu, "nosfu" }, |
| 151 | { Opt_nodfs, "nodfs" }, |
| 152 | { Opt_posixpaths, "posixpaths" }, |
| 153 | { Opt_noposixpaths, "noposixpaths" }, |
| 154 | { Opt_nounix, "nounix" }, |
| 155 | { Opt_nounix, "nolinux" }, |
Steve French | b326614 | 2018-05-20 23:41:10 -0500 | [diff] [blame] | 156 | { Opt_nounix, "noposix" }, |
| 157 | { Opt_unix, "unix" }, |
| 158 | { Opt_unix, "linux" }, |
| 159 | { Opt_unix, "posix" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 160 | { Opt_nocase, "nocase" }, |
| 161 | { Opt_nocase, "ignorecase" }, |
| 162 | { Opt_brl, "brl" }, |
| 163 | { Opt_nobrl, "nobrl" }, |
Steve French | 3d4ef9a | 2018-04-25 22:19:09 -0500 | [diff] [blame] | 164 | { Opt_handlecache, "handlecache" }, |
| 165 | { Opt_nohandlecache, "nohandlecache" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 166 | { Opt_nobrl, "nolock" }, |
| 167 | { Opt_forcemandatorylock, "forcemandatorylock" }, |
Pavel Shilovsky | 5cfdddc | 2012-03-27 20:51:15 +0400 | [diff] [blame] | 168 | { Opt_forcemandatorylock, "forcemand" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 169 | { Opt_setuids, "setuids" }, |
| 170 | { Opt_nosetuids, "nosetuids" }, |
Steve French | 9593265 | 2016-09-23 01:36:34 -0500 | [diff] [blame] | 171 | { Opt_setuidfromacl, "idsfromsid" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 172 | { Opt_dynperm, "dynperm" }, |
| 173 | { Opt_nodynperm, "nodynperm" }, |
| 174 | { Opt_nohard, "nohard" }, |
| 175 | { Opt_nosoft, "nosoft" }, |
| 176 | { Opt_nointr, "nointr" }, |
| 177 | { Opt_intr, "intr" }, |
| 178 | { Opt_nostrictsync, "nostrictsync" }, |
| 179 | { Opt_strictsync, "strictsync" }, |
| 180 | { Opt_serverino, "serverino" }, |
| 181 | { Opt_noserverino, "noserverino" }, |
| 182 | { Opt_rwpidforward, "rwpidforward" }, |
Steve French | 412094a | 2019-06-24 02:01:42 -0500 | [diff] [blame] | 183 | { Opt_modesid, "modefromsid" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 184 | { Opt_cifsacl, "cifsacl" }, |
| 185 | { Opt_nocifsacl, "nocifsacl" }, |
| 186 | { Opt_acl, "acl" }, |
| 187 | { Opt_noacl, "noacl" }, |
| 188 | { Opt_locallease, "locallease" }, |
| 189 | { Opt_sign, "sign" }, |
Steve French | 4f5c10f | 2019-09-03 21:18:49 -0500 | [diff] [blame] | 190 | { Opt_ignore_signature, "signloosely" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 191 | { Opt_seal, "seal" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 192 | { Opt_noac, "noac" }, |
| 193 | { Opt_fsc, "fsc" }, |
| 194 | { Opt_mfsymlinks, "mfsymlinks" }, |
| 195 | { Opt_multiuser, "multiuser" }, |
Jeff Layton | d816255 | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 196 | { Opt_sloppy, "sloppy" }, |
Jeff Layton | a0b3df5 | 2013-05-24 07:40:59 -0400 | [diff] [blame] | 197 | { Opt_nosharesock, "nosharesock" }, |
Steve French | b2a3077 | 2015-09-29 21:49:28 -0500 | [diff] [blame] | 198 | { Opt_persistent, "persistenthandles"}, |
| 199 | { Opt_nopersistent, "nopersistenthandles"}, |
Steve French | 592fafe | 2015-11-03 10:08:53 -0600 | [diff] [blame] | 200 | { Opt_resilient, "resilienthandles"}, |
| 201 | { Opt_noresilient, "noresilienthandles"}, |
Germano Percossi | 3956644 | 2016-12-15 12:31:18 +0530 | [diff] [blame] | 202 | { Opt_domainauto, "domainauto"}, |
Long Li | 8339dd3 | 2017-11-07 01:54:55 -0700 | [diff] [blame] | 203 | { Opt_rdma, "rdma"}, |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 204 | { Opt_multichannel, "multichannel" }, |
| 205 | { Opt_nomultichannel, "nomultichannel" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 206 | |
| 207 | { Opt_backupuid, "backupuid=%s" }, |
| 208 | { Opt_backupgid, "backupgid=%s" }, |
| 209 | { Opt_uid, "uid=%s" }, |
| 210 | { Opt_cruid, "cruid=%s" }, |
| 211 | { Opt_gid, "gid=%s" }, |
| 212 | { Opt_file_mode, "file_mode=%s" }, |
| 213 | { Opt_dirmode, "dirmode=%s" }, |
| 214 | { Opt_dirmode, "dir_mode=%s" }, |
| 215 | { Opt_port, "port=%s" }, |
Steve French | 563317e | 2019-09-08 23:22:02 -0500 | [diff] [blame] | 216 | { Opt_min_enc_offload, "esize=%s" }, |
Steve French | e8506d2 | 2019-02-28 21:32:15 -0600 | [diff] [blame] | 217 | { Opt_blocksize, "bsize=%s" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 218 | { Opt_rsize, "rsize=%s" }, |
| 219 | { Opt_wsize, "wsize=%s" }, |
| 220 | { Opt_actimeo, "actimeo=%s" }, |
Steve French | ca567eb | 2019-03-29 16:31:07 -0500 | [diff] [blame] | 221 | { Opt_handletimeout, "handletimeout=%s" }, |
Steve French | adfeb3e | 2015-12-18 12:31:36 -0600 | [diff] [blame] | 222 | { Opt_echo_interval, "echo_interval=%s" }, |
Steve French | 141891f | 2016-09-23 00:44:16 -0500 | [diff] [blame] | 223 | { Opt_max_credits, "max_credits=%s" }, |
Steve French | 8b217fe | 2016-11-11 22:36:20 -0600 | [diff] [blame] | 224 | { Opt_snapshot, "snapshot=%s" }, |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 225 | { Opt_max_channels, "max_channels=%s" }, |
Steve French | 9fe5ff1 | 2019-06-24 20:39:04 -0500 | [diff] [blame] | 226 | { Opt_compress, "compress=%s" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 227 | |
Sachin Prabhu | 4fe9e96 | 2012-04-10 18:12:27 +0100 | [diff] [blame] | 228 | { Opt_blank_user, "user=" }, |
| 229 | { Opt_blank_user, "username=" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 230 | { Opt_user, "user=%s" }, |
| 231 | { Opt_user, "username=%s" }, |
| 232 | { Opt_blank_pass, "pass=" }, |
Jesper Nilsson | 3c15b4c | 2012-11-29 17:31:16 +0100 | [diff] [blame] | 233 | { Opt_blank_pass, "password=" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 234 | { Opt_pass, "pass=%s" }, |
| 235 | { Opt_pass, "password=%s" }, |
Sachin Prabhu | 4fe9e96 | 2012-04-10 18:12:27 +0100 | [diff] [blame] | 236 | { Opt_blank_ip, "ip=" }, |
| 237 | { Opt_blank_ip, "addr=" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 238 | { Opt_ip, "ip=%s" }, |
| 239 | { Opt_ip, "addr=%s" }, |
Jeff Layton | 73a999f | 2013-03-22 08:42:57 -0400 | [diff] [blame] | 240 | { Opt_ignore, "unc=%s" }, |
| 241 | { Opt_ignore, "target=%s" }, |
| 242 | { Opt_ignore, "path=%s" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 243 | { Opt_domain, "dom=%s" }, |
| 244 | { Opt_domain, "domain=%s" }, |
| 245 | { Opt_domain, "workgroup=%s" }, |
| 246 | { Opt_srcaddr, "srcaddr=%s" }, |
Jeff Layton | 73a999f | 2013-03-22 08:42:57 -0400 | [diff] [blame] | 247 | { Opt_ignore, "prefixpath=%s" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 248 | { Opt_iocharset, "iocharset=%s" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 249 | { Opt_netbiosname, "netbiosname=%s" }, |
| 250 | { Opt_servern, "servern=%s" }, |
| 251 | { Opt_ver, "ver=%s" }, |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 252 | { Opt_vers, "vers=%s" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 253 | { Opt_sec, "sec=%s" }, |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 254 | { Opt_cache, "cache=%s" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 255 | |
| 256 | { Opt_ignore, "cred" }, |
| 257 | { Opt_ignore, "credentials" }, |
Jeff Layton | a557b97 | 2012-05-02 14:02:40 -0400 | [diff] [blame] | 258 | { Opt_ignore, "cred=%s" }, |
| 259 | { Opt_ignore, "credentials=%s" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 260 | { Opt_ignore, "guest" }, |
| 261 | { Opt_ignore, "rw" }, |
| 262 | { Opt_ignore, "ro" }, |
| 263 | { Opt_ignore, "suid" }, |
| 264 | { Opt_ignore, "nosuid" }, |
| 265 | { Opt_ignore, "exec" }, |
| 266 | { Opt_ignore, "noexec" }, |
| 267 | { Opt_ignore, "nodev" }, |
| 268 | { Opt_ignore, "noauto" }, |
| 269 | { Opt_ignore, "dev" }, |
| 270 | { Opt_ignore, "mand" }, |
| 271 | { Opt_ignore, "nomand" }, |
Steve French | 9b9c5be | 2018-09-22 12:07:06 -0500 | [diff] [blame] | 272 | { Opt_ignore, "relatime" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 273 | { Opt_ignore, "_netdev" }, |
Paulo Alcantara (SUSE) | 8eecd1c | 2019-07-16 19:04:50 -0300 | [diff] [blame] | 274 | { Opt_rootfs, "rootfs" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 275 | |
| 276 | { Opt_err, NULL } |
| 277 | }; |
| 278 | |
| 279 | enum { |
| 280 | Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p, |
| 281 | Opt_sec_ntlmsspi, Opt_sec_ntlmssp, |
Jeff Layton | 7659624 | 2012-07-23 20:34:17 -0400 | [diff] [blame] | 282 | Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2, |
| 283 | Opt_sec_ntlmv2i, Opt_sec_lanman, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 284 | Opt_sec_none, |
| 285 | |
| 286 | Opt_sec_err |
| 287 | }; |
| 288 | |
| 289 | static const match_table_t cifs_secflavor_tokens = { |
| 290 | { Opt_sec_krb5, "krb5" }, |
| 291 | { Opt_sec_krb5i, "krb5i" }, |
| 292 | { Opt_sec_krb5p, "krb5p" }, |
| 293 | { Opt_sec_ntlmsspi, "ntlmsspi" }, |
| 294 | { Opt_sec_ntlmssp, "ntlmssp" }, |
| 295 | { Opt_ntlm, "ntlm" }, |
| 296 | { Opt_sec_ntlmi, "ntlmi" }, |
Jeff Layton | 7659624 | 2012-07-23 20:34:17 -0400 | [diff] [blame] | 297 | { Opt_sec_ntlmv2, "nontlm" }, |
| 298 | { Opt_sec_ntlmv2, "ntlmv2" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 299 | { Opt_sec_ntlmv2i, "ntlmv2i" }, |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 300 | { Opt_sec_lanman, "lanman" }, |
| 301 | { Opt_sec_none, "none" }, |
| 302 | |
| 303 | { Opt_sec_err, NULL } |
| 304 | }; |
| 305 | |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 306 | /* cache flavors */ |
| 307 | enum { |
| 308 | Opt_cache_loose, |
| 309 | Opt_cache_strict, |
| 310 | Opt_cache_none, |
Steve French | 83bbfa7 | 2019-08-27 23:58:54 -0500 | [diff] [blame] | 311 | Opt_cache_ro, |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 312 | Opt_cache_rw, |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 313 | Opt_cache_err |
| 314 | }; |
| 315 | |
| 316 | static const match_table_t cifs_cacheflavor_tokens = { |
| 317 | { Opt_cache_loose, "loose" }, |
| 318 | { Opt_cache_strict, "strict" }, |
| 319 | { Opt_cache_none, "none" }, |
Steve French | 83bbfa7 | 2019-08-27 23:58:54 -0500 | [diff] [blame] | 320 | { Opt_cache_ro, "ro" }, |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 321 | { Opt_cache_rw, "singleclient" }, |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 322 | { Opt_cache_err, NULL } |
| 323 | }; |
| 324 | |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 325 | static const match_table_t cifs_smb_version_tokens = { |
| 326 | { Smb_1, SMB1_VERSION_STRING }, |
Steve French | dd446b1 | 2012-11-28 23:21:06 -0600 | [diff] [blame] | 327 | { Smb_20, SMB20_VERSION_STRING}, |
Steve French | 1080ef7 | 2011-02-24 18:07:19 +0000 | [diff] [blame] | 328 | { Smb_21, SMB21_VERSION_STRING }, |
Steve French | e4aa25e | 2012-10-01 12:26:22 -0500 | [diff] [blame] | 329 | { Smb_30, SMB30_VERSION_STRING }, |
Steve French | 20b6d8b | 2013-06-12 22:48:41 -0500 | [diff] [blame] | 330 | { Smb_302, SMB302_VERSION_STRING }, |
Kenneth D'souza | 4a3b38a | 2018-11-17 10:33:30 +0530 | [diff] [blame] | 331 | { Smb_302, ALT_SMB302_VERSION_STRING }, |
Steve French | 5f7fbf7 | 2014-12-17 22:52:58 -0600 | [diff] [blame] | 332 | { Smb_311, SMB311_VERSION_STRING }, |
Steve French | aab1893 | 2015-06-23 23:37:11 -0500 | [diff] [blame] | 333 | { Smb_311, ALT_SMB311_VERSION_STRING }, |
Steve French | 9764c02 | 2017-09-17 10:41:35 -0500 | [diff] [blame] | 334 | { Smb_3any, SMB3ANY_VERSION_STRING }, |
| 335 | { Smb_default, SMBDEFAULT_VERSION_STRING }, |
Steve French | 5f7fbf7 | 2014-12-17 22:52:58 -0600 | [diff] [blame] | 336 | { Smb_version_err, NULL } |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 337 | }; |
| 338 | |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 339 | static int ip_connect(struct TCP_Server_Info *server); |
| 340 | static int generic_ip_connect(struct TCP_Server_Info *server); |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 341 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 342 | static void cifs_prune_tlinks(struct work_struct *work); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 343 | static char *extract_hostname(const char *unc); |
| 344 | |
Paulo Alcantara | 28eb24f | 2018-11-20 15:16:36 -0200 | [diff] [blame] | 345 | /* |
| 346 | * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may |
| 347 | * get their ip addresses changed at some point. |
| 348 | * |
| 349 | * This should be called with server->srv_mutex held. |
| 350 | */ |
| 351 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 352 | static int reconn_set_ipaddr(struct TCP_Server_Info *server) |
| 353 | { |
| 354 | int rc; |
| 355 | int len; |
| 356 | char *unc, *ipaddr = NULL; |
| 357 | |
| 358 | if (!server->hostname) |
| 359 | return -EINVAL; |
| 360 | |
| 361 | len = strlen(server->hostname) + 3; |
| 362 | |
| 363 | unc = kmalloc(len, GFP_KERNEL); |
| 364 | if (!unc) { |
| 365 | cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__); |
| 366 | return -ENOMEM; |
| 367 | } |
Ronnie Sahlberg | 74ea5f9 | 2019-02-09 09:51:11 +1000 | [diff] [blame] | 368 | scnprintf(unc, len, "\\\\%s", server->hostname); |
Paulo Alcantara | 28eb24f | 2018-11-20 15:16:36 -0200 | [diff] [blame] | 369 | |
| 370 | rc = dns_resolve_server_name_to_ip(unc, &ipaddr); |
| 371 | kfree(unc); |
| 372 | |
| 373 | if (rc < 0) { |
| 374 | cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n", |
| 375 | __func__, server->hostname, rc); |
| 376 | return rc; |
| 377 | } |
| 378 | |
Ronnie Sahlberg | fada37f | 2020-04-21 12:37:39 +1000 | [diff] [blame] | 379 | spin_lock(&cifs_tcp_ses_lock); |
Paulo Alcantara | 28eb24f | 2018-11-20 15:16:36 -0200 | [diff] [blame] | 380 | rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, |
| 381 | strlen(ipaddr)); |
Ronnie Sahlberg | fada37f | 2020-04-21 12:37:39 +1000 | [diff] [blame] | 382 | spin_unlock(&cifs_tcp_ses_lock); |
Paulo Alcantara | 28eb24f | 2018-11-20 15:16:36 -0200 | [diff] [blame] | 383 | kfree(ipaddr); |
| 384 | |
| 385 | return !rc ? -1 : 0; |
| 386 | } |
| 387 | #else |
| 388 | static inline int reconn_set_ipaddr(struct TCP_Server_Info *server) |
| 389 | { |
| 390 | return 0; |
| 391 | } |
| 392 | #endif |
| 393 | |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 394 | #ifdef CONFIG_CIFS_DFS_UPCALL |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 395 | /* These functions must be called with server->srv_mutex held */ |
Paulo Alcantara | 7d397a0 | 2020-07-21 09:36:40 -0300 | [diff] [blame] | 396 | static void reconn_set_next_dfs_target(struct TCP_Server_Info *server, |
| 397 | struct cifs_sb_info *cifs_sb, |
| 398 | struct dfs_cache_tgt_list *tgt_list, |
| 399 | struct dfs_cache_tgt_iterator **tgt_it) |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 400 | { |
| 401 | const char *name; |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 402 | |
Paulo Alcantara | 7d397a0 | 2020-07-21 09:36:40 -0300 | [diff] [blame] | 403 | if (!cifs_sb || !cifs_sb->origin_fullpath) |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 404 | return; |
| 405 | |
| 406 | if (!*tgt_it) { |
| 407 | *tgt_it = dfs_cache_get_tgt_iterator(tgt_list); |
| 408 | } else { |
| 409 | *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it); |
| 410 | if (!*tgt_it) |
| 411 | *tgt_it = dfs_cache_get_tgt_iterator(tgt_list); |
| 412 | } |
| 413 | |
| 414 | cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath); |
| 415 | |
| 416 | name = dfs_cache_get_tgt_name(*tgt_it); |
| 417 | |
| 418 | kfree(server->hostname); |
| 419 | |
| 420 | server->hostname = extract_hostname(name); |
Dan Carpenter | 8428817 | 2019-01-05 15:25:29 +0300 | [diff] [blame] | 421 | if (IS_ERR(server->hostname)) { |
| 422 | cifs_dbg(FYI, |
| 423 | "%s: failed to extract hostname from target: %ld\n", |
| 424 | __func__, PTR_ERR(server->hostname)); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 425 | } |
| 426 | } |
| 427 | |
| 428 | static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb, |
Paulo Alcantara | baf3f08 | 2020-05-19 15:38:29 -0300 | [diff] [blame] | 429 | struct dfs_cache_tgt_list *tl) |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 430 | { |
| 431 | if (!cifs_sb->origin_fullpath) |
| 432 | return -EOPNOTSUPP; |
| 433 | return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl); |
| 434 | } |
| 435 | #endif |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 436 | |
Jeff Layton | d5c5605 | 2008-12-01 18:42:33 -0500 | [diff] [blame] | 437 | /* |
| 438 | * cifs tcp session reconnection |
| 439 | * |
| 440 | * mark tcp session as reconnecting so temporarily locked |
| 441 | * mark all smb sessions as reconnecting for tcp session |
| 442 | * reconnect tcp session |
| 443 | * wake up waiters on reconnection? - (not needed currently) |
| 444 | */ |
Pavel Shilovsky | 28ea529 | 2012-05-23 16:18:00 +0400 | [diff] [blame] | 445 | int |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 446 | cifs_reconnect(struct TCP_Server_Info *server) |
| 447 | { |
| 448 | int rc = 0; |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 449 | struct list_head *tmp, *tmp2; |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 450 | struct cifs_ses *ses; |
| 451 | struct cifs_tcon *tcon; |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 452 | struct mid_q_entry *mid_entry; |
Jeff Layton | 3c1105d | 2011-05-22 07:09:13 -0400 | [diff] [blame] | 453 | struct list_head retry_list; |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 454 | #ifdef CONFIG_CIFS_DFS_UPCALL |
Paulo Alcantara (SUSE) | 8354d88 | 2019-11-22 12:30:51 -0300 | [diff] [blame] | 455 | struct super_block *sb = NULL; |
Paulo Alcantara | 2332440 | 2018-11-20 14:37:18 -0200 | [diff] [blame] | 456 | struct cifs_sb_info *cifs_sb = NULL; |
| 457 | struct dfs_cache_tgt_list tgt_list = {0}; |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 458 | struct dfs_cache_tgt_iterator *tgt_it = NULL; |
| 459 | #endif |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 460 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 461 | spin_lock(&GlobalMid_Lock); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 462 | server->nr_targets = 1; |
| 463 | #ifdef CONFIG_CIFS_DFS_UPCALL |
Ronnie Sahlberg | 61cabc7 | 2019-06-14 13:02:29 +1000 | [diff] [blame] | 464 | spin_unlock(&GlobalMid_Lock); |
Paulo Alcantara (SUSE) | bacd704 | 2020-02-20 19:49:34 -0300 | [diff] [blame] | 465 | sb = cifs_get_tcp_super(server); |
Paulo Alcantara (SUSE) | 8354d88 | 2019-11-22 12:30:51 -0300 | [diff] [blame] | 466 | if (IS_ERR(sb)) { |
| 467 | rc = PTR_ERR(sb); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 468 | cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n", |
| 469 | __func__, rc); |
Paulo Alcantara (SUSE) | 8354d88 | 2019-11-22 12:30:51 -0300 | [diff] [blame] | 470 | sb = NULL; |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 471 | } else { |
Paulo Alcantara (SUSE) | 8354d88 | 2019-11-22 12:30:51 -0300 | [diff] [blame] | 472 | cifs_sb = CIFS_SB(sb); |
Paulo Alcantara | baf3f08 | 2020-05-19 15:38:29 -0300 | [diff] [blame] | 473 | rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list); |
Paulo Alcantara | a529303 | 2020-07-21 09:36:41 -0300 | [diff] [blame] | 474 | if (rc) { |
| 475 | cifs_sb = NULL; |
| 476 | if (rc != -EOPNOTSUPP) { |
| 477 | cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n", |
| 478 | __func__); |
| 479 | } |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 480 | } else { |
| 481 | server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list); |
| 482 | } |
| 483 | } |
| 484 | cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__, |
| 485 | server->nr_targets); |
Ronnie Sahlberg | 61cabc7 | 2019-06-14 13:02:29 +1000 | [diff] [blame] | 486 | spin_lock(&GlobalMid_Lock); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 487 | #endif |
Jeff Layton | 469ee61 | 2008-10-16 18:46:39 +0000 | [diff] [blame] | 488 | if (server->tcpStatus == CifsExiting) { |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 489 | /* the demux thread will exit normally |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 490 | next time through the loop */ |
| 491 | spin_unlock(&GlobalMid_Lock); |
Paulo Alcantara (SUSE) | 8354d88 | 2019-11-22 12:30:51 -0300 | [diff] [blame] | 492 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 493 | dfs_cache_free_tgts(&tgt_list); |
Paulo Alcantara (SUSE) | bacd704 | 2020-02-20 19:49:34 -0300 | [diff] [blame] | 494 | cifs_put_tcp_super(sb); |
Paulo Alcantara (SUSE) | 8354d88 | 2019-11-22 12:30:51 -0300 | [diff] [blame] | 495 | #endif |
Stefan Metzmacher | e2e8751 | 2020-02-24 14:31:02 -0600 | [diff] [blame] | 496 | wake_up(&server->response_q); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 497 | return rc; |
| 498 | } else |
| 499 | server->tcpStatus = CifsNeedReconnect; |
| 500 | spin_unlock(&GlobalMid_Lock); |
| 501 | server->maxBuf = 0; |
Pavel Shilovsky | aa24d1e | 2011-12-27 16:23:34 +0400 | [diff] [blame] | 502 | server->max_read = 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 503 | |
Steve French | 6e4d3bb | 2018-09-22 11:25:04 -0500 | [diff] [blame] | 504 | cifs_dbg(FYI, "Mark tcp session as need reconnect\n"); |
Steve French | bf1fdeb | 2018-07-30 19:23:09 -0500 | [diff] [blame] | 505 | trace_smb3_reconnect(server->CurrentMid, server->hostname); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 506 | |
| 507 | /* before reconnecting the tcp session, mark the smb session (uid) |
| 508 | and the tid bad so they are not used until reconnected */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 509 | cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", |
| 510 | __func__); |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 511 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 512 | list_for_each(tmp, &server->smb_ses_list) { |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 513 | ses = list_entry(tmp, struct cifs_ses, smb_ses_list); |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 514 | ses->need_reconnect = true; |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 515 | list_for_each(tmp2, &ses->tcon_list) { |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 516 | tcon = list_entry(tmp2, struct cifs_tcon, tcon_list); |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 517 | tcon->need_reconnect = true; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 518 | } |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 519 | if (ses->tcon_ipc) |
| 520 | ses->tcon_ipc->need_reconnect = true; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 521 | } |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 522 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | 2b84a36c | 2011-01-11 07:24:21 -0500 | [diff] [blame] | 523 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 524 | /* do not want to be sending data on a socket we are freeing */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 525 | cifs_dbg(FYI, "%s: tearing down socket\n", __func__); |
Jeff Layton | 72ca545 | 2008-12-01 07:09:36 -0500 | [diff] [blame] | 526 | mutex_lock(&server->srv_mutex); |
Long Li | 1d2a4f5 | 2019-05-13 21:01:28 -0700 | [diff] [blame] | 527 | if (server->ssocket) { |
| 528 | cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", |
| 529 | server->ssocket->state, server->ssocket->flags); |
| 530 | kernel_sock_shutdown(server->ssocket, SHUT_WR); |
| 531 | cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", |
| 532 | server->ssocket->state, server->ssocket->flags); |
| 533 | sock_release(server->ssocket); |
| 534 | server->ssocket = NULL; |
| 535 | } |
| 536 | server->sequence_number = 0; |
| 537 | server->session_estab = false; |
| 538 | kfree(server->session_key.response); |
| 539 | server->session_key.response = NULL; |
| 540 | server->session_key.len = 0; |
| 541 | server->lstrp = jiffies; |
Long Li | 214bab4 | 2019-04-05 21:36:35 +0000 | [diff] [blame] | 542 | |
| 543 | /* mark submitted MIDs for retry and issue callback */ |
| 544 | INIT_LIST_HEAD(&retry_list); |
| 545 | cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); |
| 546 | spin_lock(&GlobalMid_Lock); |
| 547 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
| 548 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
Pavel Shilovsky | abe5707 | 2019-10-22 08:41:42 -0700 | [diff] [blame] | 549 | kref_get(&mid_entry->refcount); |
Long Li | 214bab4 | 2019-04-05 21:36:35 +0000 | [diff] [blame] | 550 | if (mid_entry->mid_state == MID_REQUEST_SUBMITTED) |
| 551 | mid_entry->mid_state = MID_RETRY_NEEDED; |
| 552 | list_move(&mid_entry->qhead, &retry_list); |
Pavel Shilovsky | abe5707 | 2019-10-22 08:41:42 -0700 | [diff] [blame] | 553 | mid_entry->mid_flags |= MID_DELETED; |
Long Li | 214bab4 | 2019-04-05 21:36:35 +0000 | [diff] [blame] | 554 | } |
| 555 | spin_unlock(&GlobalMid_Lock); |
Long Li | 1d2a4f5 | 2019-05-13 21:01:28 -0700 | [diff] [blame] | 556 | mutex_unlock(&server->srv_mutex); |
Long Li | 214bab4 | 2019-04-05 21:36:35 +0000 | [diff] [blame] | 557 | |
| 558 | cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); |
| 559 | list_for_each_safe(tmp, tmp2, &retry_list) { |
| 560 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
| 561 | list_del_init(&mid_entry->qhead); |
| 562 | mid_entry->callback(mid_entry); |
Pavel Shilovsky | abe5707 | 2019-10-22 08:41:42 -0700 | [diff] [blame] | 563 | cifs_mid_q_entry_release(mid_entry); |
Long Li | 214bab4 | 2019-04-05 21:36:35 +0000 | [diff] [blame] | 564 | } |
| 565 | |
Long Li | 1d2a4f5 | 2019-05-13 21:01:28 -0700 | [diff] [blame] | 566 | if (cifs_rdma_enabled(server)) { |
| 567 | mutex_lock(&server->srv_mutex); |
Long Li | 050b8c3 | 2019-04-04 11:35:42 -0500 | [diff] [blame] | 568 | smbd_destroy(server); |
Long Li | 1d2a4f5 | 2019-05-13 21:01:28 -0700 | [diff] [blame] | 569 | mutex_unlock(&server->srv_mutex); |
| 570 | } |
Jeff Layton | 3c1105d | 2011-05-22 07:09:13 -0400 | [diff] [blame] | 571 | |
Jeff Layton | 7fdbaa1 | 2011-06-10 16:14:57 -0400 | [diff] [blame] | 572 | do { |
Steve French | 6c3d890 | 2006-07-31 22:46:20 +0000 | [diff] [blame] | 573 | try_to_freeze(); |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 574 | |
Jeff Layton | 73e216a | 2013-09-05 08:38:10 -0400 | [diff] [blame] | 575 | mutex_lock(&server->srv_mutex); |
Paulo Alcantara | aaa3aef | 2020-05-19 15:38:27 -0300 | [diff] [blame] | 576 | #ifdef CONFIG_CIFS_DFS_UPCALL |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 577 | /* |
| 578 | * Set up next DFS target server (if any) for reconnect. If DFS |
| 579 | * feature is disabled, then we will retry last server we |
| 580 | * connected to before. |
| 581 | */ |
Paulo Alcantara | 7d397a0 | 2020-07-21 09:36:40 -0300 | [diff] [blame] | 582 | reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it); |
Paulo Alcantara | aaa3aef | 2020-05-19 15:38:27 -0300 | [diff] [blame] | 583 | #endif |
| 584 | rc = reconn_set_ipaddr(server); |
| 585 | if (rc) { |
| 586 | cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", |
| 587 | __func__, rc); |
| 588 | } |
| 589 | |
Long Li | 781a805 | 2017-11-22 17:38:36 -0700 | [diff] [blame] | 590 | if (cifs_rdma_enabled(server)) |
| 591 | rc = smbd_reconnect(server); |
| 592 | else |
| 593 | rc = generic_ip_connect(server); |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 594 | if (rc) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 595 | cifs_dbg(FYI, "reconnect error %d\n", rc); |
Federico Sauter | 4afe260 | 2015-03-17 17:45:28 +0100 | [diff] [blame] | 596 | mutex_unlock(&server->srv_mutex); |
Steve French | 0cb766a | 2005-04-28 22:41:11 -0700 | [diff] [blame] | 597 | msleep(3000); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 598 | } else { |
| 599 | atomic_inc(&tcpSesReconnectCount); |
Pavel Shilovsky | 335b7b6 | 2019-01-16 11:12:41 -0800 | [diff] [blame] | 600 | set_credits(server, 1); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 601 | spin_lock(&GlobalMid_Lock); |
Jeff Layton | 469ee61 | 2008-10-16 18:46:39 +0000 | [diff] [blame] | 602 | if (server->tcpStatus != CifsExiting) |
Steve French | fd88ce9 | 2011-04-12 01:01:14 +0000 | [diff] [blame] | 603 | server->tcpStatus = CifsNeedNegotiate; |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 604 | spin_unlock(&GlobalMid_Lock); |
Federico Sauter | 4afe260 | 2015-03-17 17:45:28 +0100 | [diff] [blame] | 605 | mutex_unlock(&server->srv_mutex); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 606 | } |
Jeff Layton | 7fdbaa1 | 2011-06-10 16:14:57 -0400 | [diff] [blame] | 607 | } while (server->tcpStatus == CifsNeedReconnect); |
Jeff Layton | 2b84a36c | 2011-01-11 07:24:21 -0500 | [diff] [blame] | 608 | |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 609 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 610 | if (tgt_it) { |
| 611 | rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1, |
| 612 | tgt_it); |
| 613 | if (rc) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 614 | cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n", |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 615 | __func__, rc); |
| 616 | } |
| 617 | rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server); |
| 618 | if (rc) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 619 | cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n", |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 620 | __func__, rc); |
| 621 | } |
Paulo Alcantara | 2332440 | 2018-11-20 14:37:18 -0200 | [diff] [blame] | 622 | dfs_cache_free_tgts(&tgt_list); |
Paulo Alcantara (SUSE) | 8354d88 | 2019-11-22 12:30:51 -0300 | [diff] [blame] | 623 | |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 624 | } |
Paulo Alcantara (SUSE) | 8354d88 | 2019-11-22 12:30:51 -0300 | [diff] [blame] | 625 | |
Paulo Alcantara (SUSE) | bacd704 | 2020-02-20 19:49:34 -0300 | [diff] [blame] | 626 | cifs_put_tcp_super(sb); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 627 | #endif |
Sachin Prabhu | b8c6001 | 2016-10-20 19:52:24 -0400 | [diff] [blame] | 628 | if (server->tcpStatus == CifsNeedNegotiate) |
| 629 | mod_delayed_work(cifsiod_wq, &server->echo, 0); |
| 630 | |
Stefan Metzmacher | e2e8751 | 2020-02-24 14:31:02 -0600 | [diff] [blame] | 631 | wake_up(&server->response_q); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 632 | return rc; |
| 633 | } |
| 634 | |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 635 | static void |
| 636 | cifs_echo_request(struct work_struct *work) |
| 637 | { |
| 638 | int rc; |
| 639 | struct TCP_Server_Info *server = container_of(work, |
| 640 | struct TCP_Server_Info, echo.work); |
Sachin Prabhu | b8c6001 | 2016-10-20 19:52:24 -0400 | [diff] [blame] | 641 | unsigned long echo_interval; |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 642 | |
Jeff Layton | 247ec9b | 2011-02-04 17:09:50 -0500 | [diff] [blame] | 643 | /* |
Sachin Prabhu | b8c6001 | 2016-10-20 19:52:24 -0400 | [diff] [blame] | 644 | * If we need to renegotiate, set echo interval to zero to |
| 645 | * immediately call echo service where we can renegotiate. |
| 646 | */ |
| 647 | if (server->tcpStatus == CifsNeedNegotiate) |
| 648 | echo_interval = 0; |
| 649 | else |
| 650 | echo_interval = server->echo_interval; |
| 651 | |
| 652 | /* |
| 653 | * We cannot send an echo if it is disabled. |
| 654 | * Also, no need to ping if we got a response recently. |
Jeff Layton | 247ec9b | 2011-02-04 17:09:50 -0500 | [diff] [blame] | 655 | */ |
Steve French | 4fcd181 | 2016-06-22 20:12:05 -0500 | [diff] [blame] | 656 | |
| 657 | if (server->tcpStatus == CifsNeedReconnect || |
Sachin Prabhu | b8c6001 | 2016-10-20 19:52:24 -0400 | [diff] [blame] | 658 | server->tcpStatus == CifsExiting || |
| 659 | server->tcpStatus == CifsNew || |
Pavel Shilovsky | f6d7617 | 2012-05-25 14:47:16 +0400 | [diff] [blame] | 660 | (server->ops->can_echo && !server->ops->can_echo(server)) || |
Steve French | adfeb3e | 2015-12-18 12:31:36 -0600 | [diff] [blame] | 661 | time_before(jiffies, server->lstrp + echo_interval - HZ)) |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 662 | goto requeue_echo; |
| 663 | |
Pavel Shilovsky | f6d7617 | 2012-05-25 14:47:16 +0400 | [diff] [blame] | 664 | rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS; |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 665 | if (rc) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 666 | cifs_dbg(FYI, "Unable to send echo request to server: %s\n", |
| 667 | server->hostname); |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 668 | |
| 669 | requeue_echo: |
Sachin Prabhu | b8c6001 | 2016-10-20 19:52:24 -0400 | [diff] [blame] | 670 | queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval); |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 671 | } |
| 672 | |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 673 | static bool |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 674 | allocate_buffers(struct TCP_Server_Info *server) |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 675 | { |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 676 | if (!server->bigbuf) { |
| 677 | server->bigbuf = (char *)cifs_buf_get(); |
| 678 | if (!server->bigbuf) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 679 | cifs_server_dbg(VFS, "No memory for large SMB response\n"); |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 680 | msleep(3000); |
| 681 | /* retry will check if exiting */ |
| 682 | return false; |
| 683 | } |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 684 | } else if (server->large_buf) { |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 685 | /* we are reusing a dirty large buf, clear its start */ |
Pavel Shilovsky | 1887f60 | 2012-05-17 12:45:31 +0400 | [diff] [blame] | 686 | memset(server->bigbuf, 0, HEADER_SIZE(server)); |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 687 | } |
| 688 | |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 689 | if (!server->smallbuf) { |
| 690 | server->smallbuf = (char *)cifs_small_buf_get(); |
| 691 | if (!server->smallbuf) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 692 | cifs_server_dbg(VFS, "No memory for SMB response\n"); |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 693 | msleep(1000); |
| 694 | /* retry will check if exiting */ |
| 695 | return false; |
| 696 | } |
| 697 | /* beginning of smb buffer is cleared in our buf_get */ |
| 698 | } else { |
| 699 | /* if existing small buf clear beginning */ |
Pavel Shilovsky | 1887f60 | 2012-05-17 12:45:31 +0400 | [diff] [blame] | 700 | memset(server->smallbuf, 0, HEADER_SIZE(server)); |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 701 | } |
| 702 | |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 703 | return true; |
| 704 | } |
| 705 | |
Jeff Layton | ba749e6 | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 706 | static bool |
| 707 | server_unresponsive(struct TCP_Server_Info *server) |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 708 | { |
Pavel Shilovsky | 6dae51a | 2012-02-21 16:50:23 +0300 | [diff] [blame] | 709 | /* |
Ronnie Sahlberg | f2caf90 | 2019-07-06 06:52:46 +1000 | [diff] [blame] | 710 | * We need to wait 3 echo intervals to make sure we handle such |
Pavel Shilovsky | 6dae51a | 2012-02-21 16:50:23 +0300 | [diff] [blame] | 711 | * situations right: |
| 712 | * 1s client sends a normal SMB request |
Ronnie Sahlberg | becc2ba | 2019-07-24 11:43:49 +1000 | [diff] [blame] | 713 | * 2s client gets a response |
Pavel Shilovsky | 6dae51a | 2012-02-21 16:50:23 +0300 | [diff] [blame] | 714 | * 30s echo workqueue job pops, and decides we got a response recently |
| 715 | * and don't need to send another |
| 716 | * ... |
| 717 | * 65s kernel_recvmsg times out, and we see that we haven't gotten |
| 718 | * a response in >60s. |
| 719 | */ |
Samuel Cabrero | 76e7527 | 2017-07-11 12:44:39 +0200 | [diff] [blame] | 720 | if ((server->tcpStatus == CifsGood || |
| 721 | server->tcpStatus == CifsNeedNegotiate) && |
Ronnie Sahlberg | f2caf90 | 2019-07-06 06:52:46 +1000 | [diff] [blame] | 722 | time_after(jiffies, server->lstrp + 3 * server->echo_interval)) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 723 | cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n", |
| 724 | (3 * server->echo_interval) / HZ); |
Jeff Layton | ba749e6 | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 725 | cifs_reconnect(server); |
Jeff Layton | ba749e6 | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 726 | return true; |
| 727 | } |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 728 | |
Jeff Layton | ba749e6 | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 729 | return false; |
| 730 | } |
| 731 | |
Pavel Shilovsky | ef68e83 | 2019-01-18 17:25:36 -0800 | [diff] [blame] | 732 | static inline bool |
| 733 | zero_credits(struct TCP_Server_Info *server) |
| 734 | { |
| 735 | int val; |
| 736 | |
| 737 | spin_lock(&server->req_lock); |
| 738 | val = server->credits + server->echo_credits + server->oplock_credits; |
| 739 | if (server->in_flight == 0 && val == 0) { |
| 740 | spin_unlock(&server->req_lock); |
| 741 | return true; |
| 742 | } |
| 743 | spin_unlock(&server->req_lock); |
| 744 | return false; |
| 745 | } |
| 746 | |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 747 | static int |
| 748 | cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg) |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 749 | { |
Jeff Layton | a52c1eb | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 750 | int length = 0; |
| 751 | int total_read; |
Jeff Layton | 42c4dfc | 2011-10-19 15:28:17 -0400 | [diff] [blame] | 752 | |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 753 | smb_msg->msg_control = NULL; |
| 754 | smb_msg->msg_controllen = 0; |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 755 | |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 756 | for (total_read = 0; msg_data_left(smb_msg); total_read += length) { |
Jeff Layton | 95edcff | 2011-12-01 20:22:41 -0500 | [diff] [blame] | 757 | try_to_freeze(); |
| 758 | |
Pavel Shilovsky | ef68e83 | 2019-01-18 17:25:36 -0800 | [diff] [blame] | 759 | /* reconnect if no credits and no requests in flight */ |
| 760 | if (zero_credits(server)) { |
| 761 | cifs_reconnect(server); |
| 762 | return -ECONNABORTED; |
| 763 | } |
| 764 | |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 765 | if (server_unresponsive(server)) |
| 766 | return -ECONNABORTED; |
Long Li | 2fef137 | 2017-11-22 17:38:41 -0700 | [diff] [blame] | 767 | if (cifs_rdma_enabled(server) && server->smbd_conn) |
| 768 | length = smbd_recv(server->smbd_conn, smb_msg); |
| 769 | else |
| 770 | length = sock_recvmsg(server->ssocket, smb_msg, 0); |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 771 | |
| 772 | if (server->tcpStatus == CifsExiting) |
| 773 | return -ESHUTDOWN; |
| 774 | |
| 775 | if (server->tcpStatus == CifsNeedReconnect) { |
| 776 | cifs_reconnect(server); |
| 777 | return -ECONNABORTED; |
Jeff Layton | ba749e6 | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 778 | } |
| 779 | |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 780 | if (length == -ERESTARTSYS || |
| 781 | length == -EAGAIN || |
| 782 | length == -EINTR) { |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 783 | /* |
| 784 | * Minimum sleep to prevent looping, allowing socket |
| 785 | * to clear and app threads to set tcpStatus |
| 786 | * CifsNeedReconnect if server hung. |
| 787 | */ |
| 788 | usleep_range(1000, 2000); |
| 789 | length = 0; |
Jeff Layton | a52c1eb | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 790 | continue; |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 791 | } |
| 792 | |
| 793 | if (length <= 0) { |
Al Viro | 09aab88 | 2015-11-13 03:00:17 -0500 | [diff] [blame] | 794 | cifs_dbg(FYI, "Received no data or error: %d\n", length); |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 795 | cifs_reconnect(server); |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 796 | return -ECONNABORTED; |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 797 | } |
| 798 | } |
Jeff Layton | a52c1eb | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 799 | return total_read; |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 800 | } |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 801 | |
Jeff Layton | e28bc5b | 2011-10-19 15:30:07 -0400 | [diff] [blame] | 802 | int |
| 803 | cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, |
| 804 | unsigned int to_read) |
Jeff Layton | 42c4dfc | 2011-10-19 15:28:17 -0400 | [diff] [blame] | 805 | { |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 806 | struct msghdr smb_msg; |
| 807 | struct kvec iov = {.iov_base = buf, .iov_len = to_read}; |
David Howells | aa563d7 | 2018-10-20 00:57:56 +0100 | [diff] [blame] | 808 | iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read); |
Jeff Layton | 42c4dfc | 2011-10-19 15:28:17 -0400 | [diff] [blame] | 809 | |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 810 | return cifs_readv_from_socket(server, &smb_msg); |
| 811 | } |
Jeff Layton | 42c4dfc | 2011-10-19 15:28:17 -0400 | [diff] [blame] | 812 | |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 813 | int |
| 814 | cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page, |
Long Li | 1dbe346 | 2018-05-30 12:47:55 -0700 | [diff] [blame] | 815 | unsigned int page_offset, unsigned int to_read) |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 816 | { |
| 817 | struct msghdr smb_msg; |
Long Li | 1dbe346 | 2018-05-30 12:47:55 -0700 | [diff] [blame] | 818 | struct bio_vec bv = { |
| 819 | .bv_page = page, .bv_len = to_read, .bv_offset = page_offset}; |
David Howells | aa563d7 | 2018-10-20 00:57:56 +0100 | [diff] [blame] | 820 | iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read); |
Al Viro | 7133566 | 2016-01-09 19:54:50 -0500 | [diff] [blame] | 821 | return cifs_readv_from_socket(server, &smb_msg); |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 822 | } |
| 823 | |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 824 | static bool |
Jeff Layton | fe11e4c | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 825 | is_smb_response(struct TCP_Server_Info *server, unsigned char type) |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 826 | { |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 827 | /* |
| 828 | * The first byte big endian of the length field, |
| 829 | * is actually not part of the length but the type |
| 830 | * with the most common, zero, as regular data. |
| 831 | */ |
Jeff Layton | fe11e4c | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 832 | switch (type) { |
| 833 | case RFC1002_SESSION_MESSAGE: |
| 834 | /* Regular SMB response */ |
| 835 | return true; |
| 836 | case RFC1002_SESSION_KEEP_ALIVE: |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 837 | cifs_dbg(FYI, "RFC 1002 session keep alive\n"); |
Jeff Layton | fe11e4c | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 838 | break; |
| 839 | case RFC1002_POSITIVE_SESSION_RESPONSE: |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 840 | cifs_dbg(FYI, "RFC 1002 positive session response\n"); |
Jeff Layton | fe11e4c | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 841 | break; |
| 842 | case RFC1002_NEGATIVE_SESSION_RESPONSE: |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 843 | /* |
| 844 | * We get this from Windows 98 instead of an error on |
| 845 | * SMB negprot response. |
| 846 | */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 847 | cifs_dbg(FYI, "RFC 1002 negative session response\n"); |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 848 | /* give server a second to clean up */ |
| 849 | msleep(1000); |
| 850 | /* |
| 851 | * Always try 445 first on reconnect since we get NACK |
| 852 | * on some if we ever connected to port 139 (the NACK |
| 853 | * is since we do not begin with RFC1001 session |
| 854 | * initialize frame). |
| 855 | */ |
Jeff Layton | fe11e4c | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 856 | cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT); |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 857 | cifs_reconnect(server); |
Jeff Layton | fe11e4c | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 858 | break; |
| 859 | default: |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 860 | cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type); |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 861 | cifs_reconnect(server); |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 862 | } |
| 863 | |
Jeff Layton | fe11e4c | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 864 | return false; |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 865 | } |
| 866 | |
Jeff Layton | e28bc5b | 2011-10-19 15:30:07 -0400 | [diff] [blame] | 867 | void |
| 868 | dequeue_mid(struct mid_q_entry *mid, bool malformed) |
Jeff Layton | ea1f450 | 2011-10-19 15:29:05 -0400 | [diff] [blame] | 869 | { |
| 870 | #ifdef CONFIG_CIFS_STATS2 |
| 871 | mid->when_received = jiffies; |
| 872 | #endif |
| 873 | spin_lock(&GlobalMid_Lock); |
| 874 | if (!malformed) |
Pavel Shilovsky | 7c9421e | 2012-03-23 14:28:03 -0400 | [diff] [blame] | 875 | mid->mid_state = MID_RESPONSE_RECEIVED; |
Jeff Layton | ea1f450 | 2011-10-19 15:29:05 -0400 | [diff] [blame] | 876 | else |
Pavel Shilovsky | 7c9421e | 2012-03-23 14:28:03 -0400 | [diff] [blame] | 877 | mid->mid_state = MID_RESPONSE_MALFORMED; |
Ronnie Sahlberg | ddf83af | 2018-08-30 10:12:59 +1000 | [diff] [blame] | 878 | /* |
| 879 | * Trying to handle/dequeue a mid after the send_recv() |
| 880 | * function has finished processing it is a bug. |
| 881 | */ |
| 882 | if (mid->mid_flags & MID_DELETED) |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 883 | pr_warn_once("trying to dequeue a deleted mid\n"); |
Pavel Shilovsky | abe5707 | 2019-10-22 08:41:42 -0700 | [diff] [blame] | 884 | else { |
Ronnie Sahlberg | ddf83af | 2018-08-30 10:12:59 +1000 | [diff] [blame] | 885 | list_del_init(&mid->qhead); |
Pavel Shilovsky | abe5707 | 2019-10-22 08:41:42 -0700 | [diff] [blame] | 886 | mid->mid_flags |= MID_DELETED; |
| 887 | } |
Jeff Layton | ea1f450 | 2011-10-19 15:29:05 -0400 | [diff] [blame] | 888 | spin_unlock(&GlobalMid_Lock); |
| 889 | } |
| 890 | |
Pavel Shilovsky | 86a7964 | 2019-11-21 11:35:13 -0800 | [diff] [blame] | 891 | static unsigned int |
| 892 | smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server) |
| 893 | { |
| 894 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer; |
| 895 | |
| 896 | /* |
| 897 | * SMB1 does not use credits. |
| 898 | */ |
| 899 | if (server->vals->header_preamble_size) |
| 900 | return 0; |
| 901 | |
| 902 | return le16_to_cpu(shdr->CreditRequest); |
| 903 | } |
| 904 | |
Jeff Layton | c8054eb | 2011-10-19 15:29:31 -0400 | [diff] [blame] | 905 | static void |
| 906 | handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, |
Pavel Shilovsky | d4e4854 | 2012-03-23 14:28:02 -0400 | [diff] [blame] | 907 | char *buf, int malformed) |
Jeff Layton | ea1f450 | 2011-10-19 15:29:05 -0400 | [diff] [blame] | 908 | { |
Pavel Shilovsky | 316cf94 | 2012-05-23 14:31:03 +0400 | [diff] [blame] | 909 | if (server->ops->check_trans2 && |
| 910 | server->ops->check_trans2(mid, server, buf, malformed)) |
Jeff Layton | c8054eb | 2011-10-19 15:29:31 -0400 | [diff] [blame] | 911 | return; |
Pavel Shilovsky | 86a7964 | 2019-11-21 11:35:13 -0800 | [diff] [blame] | 912 | mid->credits_received = smb2_get_credits_from_hdr(buf, server); |
Jeff Layton | ea1f450 | 2011-10-19 15:29:05 -0400 | [diff] [blame] | 913 | mid->resp_buf = buf; |
Pavel Shilovsky | 7c9421e | 2012-03-23 14:28:03 -0400 | [diff] [blame] | 914 | mid->large_buf = server->large_buf; |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 915 | /* Was previous buf put in mpx struct for multi-rsp? */ |
| 916 | if (!mid->multiRsp) { |
| 917 | /* smb buffer will be freed by user thread */ |
| 918 | if (server->large_buf) |
| 919 | server->bigbuf = NULL; |
| 920 | else |
| 921 | server->smallbuf = NULL; |
| 922 | } |
Jeff Layton | ffc00e2 | 2011-10-19 15:29:13 -0400 | [diff] [blame] | 923 | dequeue_mid(mid, malformed); |
Pavel Shilovsky | ad69bae | 2011-08-01 13:19:43 +0400 | [diff] [blame] | 924 | } |
| 925 | |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 926 | static void clean_demultiplex_info(struct TCP_Server_Info *server) |
| 927 | { |
| 928 | int length; |
| 929 | |
| 930 | /* take it off the list, if it's not already */ |
| 931 | spin_lock(&cifs_tcp_ses_lock); |
| 932 | list_del_init(&server->tcp_ses_list); |
| 933 | spin_unlock(&cifs_tcp_ses_lock); |
| 934 | |
| 935 | spin_lock(&GlobalMid_Lock); |
| 936 | server->tcpStatus = CifsExiting; |
| 937 | spin_unlock(&GlobalMid_Lock); |
| 938 | wake_up_all(&server->response_q); |
| 939 | |
Pavel Shilovsky | 2d86dbc | 2012-02-06 15:59:18 +0400 | [diff] [blame] | 940 | /* check if we have blocked requests that need to free */ |
Pavel Shilovsky | fc40f9c | 2012-02-17 17:09:12 +0300 | [diff] [blame] | 941 | spin_lock(&server->req_lock); |
Pavel Shilovsky | 2d86dbc | 2012-02-06 15:59:18 +0400 | [diff] [blame] | 942 | if (server->credits <= 0) |
| 943 | server->credits = 1; |
Pavel Shilovsky | fc40f9c | 2012-02-17 17:09:12 +0300 | [diff] [blame] | 944 | spin_unlock(&server->req_lock); |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 945 | /* |
| 946 | * Although there should not be any requests blocked on this queue it |
| 947 | * can not hurt to be paranoid and try to wake up requests that may |
| 948 | * haven been blocked when more than 50 at time were on the wire to the |
| 949 | * same server - they now will see the session is in exit state and get |
| 950 | * out of SendReceive. |
| 951 | */ |
| 952 | wake_up_all(&server->request_q); |
| 953 | /* give those requests time to exit */ |
| 954 | msleep(125); |
Long Li | 050b8c3 | 2019-04-04 11:35:42 -0500 | [diff] [blame] | 955 | if (cifs_rdma_enabled(server)) |
| 956 | smbd_destroy(server); |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 957 | if (server->ssocket) { |
| 958 | sock_release(server->ssocket); |
| 959 | server->ssocket = NULL; |
| 960 | } |
| 961 | |
| 962 | if (!list_empty(&server->pending_mid_q)) { |
| 963 | struct list_head dispose_list; |
| 964 | struct mid_q_entry *mid_entry; |
| 965 | struct list_head *tmp, *tmp2; |
| 966 | |
| 967 | INIT_LIST_HEAD(&dispose_list); |
| 968 | spin_lock(&GlobalMid_Lock); |
| 969 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
| 970 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 971 | cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid); |
Pavel Shilovsky | abe5707 | 2019-10-22 08:41:42 -0700 | [diff] [blame] | 972 | kref_get(&mid_entry->refcount); |
Pavel Shilovsky | 7c9421e | 2012-03-23 14:28:03 -0400 | [diff] [blame] | 973 | mid_entry->mid_state = MID_SHUTDOWN; |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 974 | list_move(&mid_entry->qhead, &dispose_list); |
Pavel Shilovsky | abe5707 | 2019-10-22 08:41:42 -0700 | [diff] [blame] | 975 | mid_entry->mid_flags |= MID_DELETED; |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 976 | } |
| 977 | spin_unlock(&GlobalMid_Lock); |
| 978 | |
| 979 | /* now walk dispose list and issue callbacks */ |
| 980 | list_for_each_safe(tmp, tmp2, &dispose_list) { |
| 981 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 982 | cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid); |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 983 | list_del_init(&mid_entry->qhead); |
| 984 | mid_entry->callback(mid_entry); |
Pavel Shilovsky | abe5707 | 2019-10-22 08:41:42 -0700 | [diff] [blame] | 985 | cifs_mid_q_entry_release(mid_entry); |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 986 | } |
| 987 | /* 1/8th of sec is more than enough time for them to exit */ |
| 988 | msleep(125); |
| 989 | } |
| 990 | |
| 991 | if (!list_empty(&server->pending_mid_q)) { |
| 992 | /* |
| 993 | * mpx threads have not exited yet give them at least the smb |
| 994 | * send timeout time for long ops. |
| 995 | * |
| 996 | * Due to delays on oplock break requests, we need to wait at |
| 997 | * least 45 seconds before giving up on a request getting a |
| 998 | * response and going ahead and killing cifsd. |
| 999 | */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1000 | cifs_dbg(FYI, "Wait for exit from demultiplex thread\n"); |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 1001 | msleep(46000); |
| 1002 | /* |
| 1003 | * If threads still have not exited they are probably never |
| 1004 | * coming home not much else we can do but free the memory. |
| 1005 | */ |
| 1006 | } |
| 1007 | |
| 1008 | kfree(server->hostname); |
| 1009 | kfree(server); |
| 1010 | |
| 1011 | length = atomic_dec_return(&tcpSesAllocCount); |
| 1012 | if (length > 0) |
David Rientjes | 11d8336 | 2015-04-14 15:48:21 -0700 | [diff] [blame] | 1013 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv); |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 1014 | } |
| 1015 | |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 1016 | static int |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1017 | standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) |
| 1018 | { |
| 1019 | int length; |
| 1020 | char *buf = server->smallbuf; |
Ronnie Sahlberg | 2e96467 | 2018-04-09 18:06:26 +1000 | [diff] [blame] | 1021 | unsigned int pdu_length = server->pdu_size; |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1022 | |
| 1023 | /* make sure this will fit in a large buffer */ |
Ronnie Sahlberg | 93012bf | 2018-03-31 11:45:31 +1100 | [diff] [blame] | 1024 | if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - |
| 1025 | server->vals->header_preamble_size) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 1026 | cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1027 | cifs_reconnect(server); |
Pavel Shilovsky | 3fabaa2 | 2014-07-10 09:55:52 +0400 | [diff] [blame] | 1028 | return -ECONNABORTED; |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1029 | } |
| 1030 | |
| 1031 | /* switch to large buffer if too big for a small one */ |
| 1032 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { |
| 1033 | server->large_buf = true; |
Pavel Shilovsky | d4e4854 | 2012-03-23 14:28:02 -0400 | [diff] [blame] | 1034 | memcpy(server->bigbuf, buf, server->total_read); |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1035 | buf = server->bigbuf; |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1036 | } |
| 1037 | |
| 1038 | /* now read the rest */ |
Pavel Shilovsky | 1887f60 | 2012-05-17 12:45:31 +0400 | [diff] [blame] | 1039 | length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, |
Ronnie Sahlberg | 93012bf | 2018-03-31 11:45:31 +1100 | [diff] [blame] | 1040 | pdu_length - HEADER_SIZE(server) + 1 |
| 1041 | + server->vals->header_preamble_size); |
| 1042 | |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1043 | if (length < 0) |
| 1044 | return length; |
| 1045 | server->total_read += length; |
| 1046 | |
Pavel Shilovsky | d4e4854 | 2012-03-23 14:28:02 -0400 | [diff] [blame] | 1047 | dump_smb(buf, server->total_read); |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1048 | |
Pavel Shilovsky | 4326ed2 | 2016-11-17 15:24:46 -0800 | [diff] [blame] | 1049 | return cifs_handle_standard(server, mid); |
| 1050 | } |
| 1051 | |
| 1052 | int |
| 1053 | cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) |
| 1054 | { |
| 1055 | char *buf = server->large_buf ? server->bigbuf : server->smallbuf; |
| 1056 | int length; |
| 1057 | |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1058 | /* |
| 1059 | * We know that we received enough to get to the MID as we |
| 1060 | * checked the pdu_length earlier. Now check to see |
| 1061 | * if the rest of the header is OK. We borrow the length |
| 1062 | * var for the rest of the loop to avoid a new stack var. |
| 1063 | * |
| 1064 | * 48 bytes is enough to display the header and a little bit |
| 1065 | * into the payload for debugging purposes. |
| 1066 | */ |
Steve French | 373512e | 2015-12-18 13:05:30 -0600 | [diff] [blame] | 1067 | length = server->ops->check_message(buf, server->total_read, server); |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1068 | if (length != 0) |
| 1069 | cifs_dump_mem("Bad SMB: ", buf, |
| 1070 | min_t(unsigned int, server->total_read, 48)); |
| 1071 | |
Pavel Shilovsky | 511c54a | 2017-07-08 14:32:00 -0700 | [diff] [blame] | 1072 | if (server->ops->is_session_expired && |
| 1073 | server->ops->is_session_expired(buf)) { |
| 1074 | cifs_reconnect(server); |
Pavel Shilovsky | 511c54a | 2017-07-08 14:32:00 -0700 | [diff] [blame] | 1075 | return -1; |
| 1076 | } |
| 1077 | |
Pavel Shilovsky | 2e44b28 | 2012-09-18 16:20:33 -0700 | [diff] [blame] | 1078 | if (server->ops->is_status_pending && |
Pavel Shilovsky | 66265f1 | 2019-01-23 17:11:16 -0800 | [diff] [blame] | 1079 | server->ops->is_status_pending(buf, server)) |
Pavel Shilovsky | 2e44b28 | 2012-09-18 16:20:33 -0700 | [diff] [blame] | 1080 | return -1; |
| 1081 | |
Jeff Layton | ff4fa4a | 2012-02-07 06:31:05 -0500 | [diff] [blame] | 1082 | if (!mid) |
| 1083 | return length; |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1084 | |
Pavel Shilovsky | d4e4854 | 2012-03-23 14:28:02 -0400 | [diff] [blame] | 1085 | handle_mid(mid, server, buf, length); |
Jeff Layton | ff4fa4a | 2012-02-07 06:31:05 -0500 | [diff] [blame] | 1086 | return 0; |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1087 | } |
| 1088 | |
Ronnie Sahlberg | eca0045 | 2019-02-05 12:56:44 +1000 | [diff] [blame] | 1089 | static void |
| 1090 | smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server) |
| 1091 | { |
| 1092 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer; |
| 1093 | |
| 1094 | /* |
| 1095 | * SMB1 does not use credits. |
| 1096 | */ |
| 1097 | if (server->vals->header_preamble_size) |
| 1098 | return; |
| 1099 | |
| 1100 | if (shdr->CreditRequest) { |
| 1101 | spin_lock(&server->req_lock); |
| 1102 | server->credits += le16_to_cpu(shdr->CreditRequest); |
| 1103 | spin_unlock(&server->req_lock); |
| 1104 | wake_up(&server->request_q); |
| 1105 | } |
| 1106 | } |
| 1107 | |
| 1108 | |
Jeff Layton | e9097ab | 2011-10-19 15:29:40 -0400 | [diff] [blame] | 1109 | static int |
Al Viro | 7c97c20 | 2011-06-21 08:51:28 -0400 | [diff] [blame] | 1110 | cifs_demultiplex_thread(void *p) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1111 | { |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1112 | int i, num_mids, length; |
Al Viro | 7c97c20 | 2011-06-21 08:51:28 -0400 | [diff] [blame] | 1113 | struct TCP_Server_Info *server = p; |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 1114 | unsigned int pdu_length; |
Ronnie Sahlberg | 8ce79ec | 2018-06-01 10:53:08 +1000 | [diff] [blame] | 1115 | unsigned int next_offset; |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 1116 | char *buf = NULL; |
Steve French | a5c3e1c | 2014-09-16 04:16:19 -0500 | [diff] [blame] | 1117 | struct task_struct *task_to_wake = NULL; |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1118 | struct mid_q_entry *mids[MAX_COMPOUND]; |
| 1119 | char *bufs[MAX_COMPOUND]; |
Eric Biggers | dc92027 | 2020-03-08 22:58:20 -0700 | [diff] [blame] | 1120 | unsigned int noreclaim_flag; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1121 | |
Eric Biggers | dc92027 | 2020-03-08 22:58:20 -0700 | [diff] [blame] | 1122 | noreclaim_flag = memalloc_noreclaim_save(); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1123 | cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current)); |
Jeff Layton | 93d0ec8 | 2008-08-02 08:00:48 -0400 | [diff] [blame] | 1124 | |
| 1125 | length = atomic_inc_return(&tcpSesAllocCount); |
| 1126 | if (length > 1) |
David Rientjes | 11d8336 | 2015-04-14 15:48:21 -0700 | [diff] [blame] | 1127 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1128 | |
Rafael J. Wysocki | 8314418 | 2007-07-17 04:03:35 -0700 | [diff] [blame] | 1129 | set_freezable(); |
Eric W. Biederman | 33da8e7 | 2019-08-16 12:33:54 -0500 | [diff] [blame] | 1130 | allow_kernel_signal(SIGKILL); |
Jeff Layton | 469ee61 | 2008-10-16 18:46:39 +0000 | [diff] [blame] | 1131 | while (server->tcpStatus != CifsExiting) { |
Steve French | ede1327 | 2005-08-30 20:10:14 -0700 | [diff] [blame] | 1132 | if (try_to_freeze()) |
| 1133 | continue; |
Steve French | b8643e1 | 2005-04-28 22:41:07 -0700 | [diff] [blame] | 1134 | |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 1135 | if (!allocate_buffers(server)) |
Pavel Shilovsky | 3d9c247 | 2011-08-01 13:19:40 +0400 | [diff] [blame] | 1136 | continue; |
Steve French | b8643e1 | 2005-04-28 22:41:07 -0700 | [diff] [blame] | 1137 | |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 1138 | server->large_buf = false; |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 1139 | buf = server->smallbuf; |
Steve French | f01d5e1 | 2007-08-30 21:13:31 +0000 | [diff] [blame] | 1140 | pdu_length = 4; /* enough to get RFC1001 header */ |
Steve French | fda3594 | 2011-01-20 18:06:34 +0000 | [diff] [blame] | 1141 | |
Jeff Layton | e28bc5b | 2011-10-19 15:30:07 -0400 | [diff] [blame] | 1142 | length = cifs_read_from_socket(server, buf, pdu_length); |
Jeff Layton | a52c1eb | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 1143 | if (length < 0) |
Steve French | fda3594 | 2011-01-20 18:06:34 +0000 | [diff] [blame] | 1144 | continue; |
Ronnie Sahlberg | 977b617 | 2018-06-01 10:53:02 +1000 | [diff] [blame] | 1145 | |
| 1146 | if (server->vals->header_preamble_size == 0) |
| 1147 | server->total_read = 0; |
| 1148 | else |
| 1149 | server->total_read = length; |
Steve French | 67010fb | 2005-04-28 22:41:09 -0700 | [diff] [blame] | 1150 | |
Pavel Shilovsky | 98bac62 | 2011-08-01 13:19:42 +0400 | [diff] [blame] | 1151 | /* |
| 1152 | * The right amount was read from socket - 4 bytes, |
| 1153 | * so we can now interpret the length field. |
| 1154 | */ |
Pavel Shilovsky | d4e4854 | 2012-03-23 14:28:02 -0400 | [diff] [blame] | 1155 | pdu_length = get_rfc1002_length(buf); |
Steve French | 46810cb | 2005-04-28 22:41:09 -0700 | [diff] [blame] | 1156 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1157 | cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length); |
Jeff Layton | fe11e4c | 2011-10-11 06:41:32 -0400 | [diff] [blame] | 1158 | if (!is_smb_response(server, buf[0])) |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 1159 | continue; |
Ronnie Sahlberg | 8ce79ec | 2018-06-01 10:53:08 +1000 | [diff] [blame] | 1160 | next_pdu: |
| 1161 | server->pdu_size = pdu_length; |
Steve French | e4eb295 | 2005-04-28 22:41:09 -0700 | [diff] [blame] | 1162 | |
Jeff Layton | 89482a5 | 2011-10-19 15:28:57 -0400 | [diff] [blame] | 1163 | /* make sure we have enough to get to the MID */ |
Ronnie Sahlberg | 8ce79ec | 2018-06-01 10:53:08 +1000 | [diff] [blame] | 1164 | if (server->pdu_size < HEADER_SIZE(server) - 1 - |
Ronnie Sahlberg | 93012bf | 2018-03-31 11:45:31 +1100 | [diff] [blame] | 1165 | server->vals->header_preamble_size) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 1166 | cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n", |
Ronnie Sahlberg | 8ce79ec | 2018-06-01 10:53:08 +1000 | [diff] [blame] | 1167 | server->pdu_size); |
Jeff Layton | 89482a5 | 2011-10-19 15:28:57 -0400 | [diff] [blame] | 1168 | cifs_reconnect(server); |
Jeff Layton | 89482a5 | 2011-10-19 15:28:57 -0400 | [diff] [blame] | 1169 | continue; |
Steve French | e4eb295 | 2005-04-28 22:41:09 -0700 | [diff] [blame] | 1170 | } |
Pavel Shilovsky | e7015fb | 2011-08-01 13:19:41 +0400 | [diff] [blame] | 1171 | |
Jeff Layton | 89482a5 | 2011-10-19 15:28:57 -0400 | [diff] [blame] | 1172 | /* read down to the MID */ |
Ronnie Sahlberg | 93012bf | 2018-03-31 11:45:31 +1100 | [diff] [blame] | 1173 | length = cifs_read_from_socket(server, |
| 1174 | buf + server->vals->header_preamble_size, |
| 1175 | HEADER_SIZE(server) - 1 |
| 1176 | - server->vals->header_preamble_size); |
Jeff Layton | 89482a5 | 2011-10-19 15:28:57 -0400 | [diff] [blame] | 1177 | if (length < 0) |
| 1178 | continue; |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 1179 | server->total_read += length; |
Jeff Layton | 89482a5 | 2011-10-19 15:28:57 -0400 | [diff] [blame] | 1180 | |
Ronnie Sahlberg | 8ce79ec | 2018-06-01 10:53:08 +1000 | [diff] [blame] | 1181 | if (server->ops->next_header) { |
| 1182 | next_offset = server->ops->next_header(buf); |
| 1183 | if (next_offset) |
| 1184 | server->pdu_size = next_offset; |
| 1185 | } |
| 1186 | |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1187 | memset(mids, 0, sizeof(mids)); |
| 1188 | memset(bufs, 0, sizeof(bufs)); |
| 1189 | num_mids = 0; |
| 1190 | |
Pavel Shilovsky | 9bb17e0 | 2016-11-17 15:24:34 -0800 | [diff] [blame] | 1191 | if (server->ops->is_transform_hdr && |
| 1192 | server->ops->receive_transform && |
| 1193 | server->ops->is_transform_hdr(buf)) { |
| 1194 | length = server->ops->receive_transform(server, |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1195 | mids, |
| 1196 | bufs, |
| 1197 | &num_mids); |
Pavel Shilovsky | 9bb17e0 | 2016-11-17 15:24:34 -0800 | [diff] [blame] | 1198 | } else { |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1199 | mids[0] = server->ops->find_mid(server, buf); |
| 1200 | bufs[0] = buf; |
Steve French | 7af929d | 2018-10-02 18:54:09 -0500 | [diff] [blame] | 1201 | num_mids = 1; |
Jeff Layton | c8054eb | 2011-10-19 15:29:31 -0400 | [diff] [blame] | 1202 | |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1203 | if (!mids[0] || !mids[0]->receive) |
| 1204 | length = standard_receive3(server, mids[0]); |
Pavel Shilovsky | 9bb17e0 | 2016-11-17 15:24:34 -0800 | [diff] [blame] | 1205 | else |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1206 | length = mids[0]->receive(server, mids[0]); |
Pavel Shilovsky | 9bb17e0 | 2016-11-17 15:24:34 -0800 | [diff] [blame] | 1207 | } |
Jeff Layton | 44d22d8 | 2011-10-19 15:29:49 -0400 | [diff] [blame] | 1208 | |
Lars Persson | 696e420 | 2018-06-25 14:05:25 +0200 | [diff] [blame] | 1209 | if (length < 0) { |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1210 | for (i = 0; i < num_mids; i++) |
| 1211 | if (mids[i]) |
| 1212 | cifs_mid_q_entry_release(mids[i]); |
Steve French | e4eb295 | 2005-04-28 22:41:09 -0700 | [diff] [blame] | 1213 | continue; |
Lars Persson | 696e420 | 2018-06-25 14:05:25 +0200 | [diff] [blame] | 1214 | } |
Steve French | e4eb295 | 2005-04-28 22:41:09 -0700 | [diff] [blame] | 1215 | |
Steve French | fda3594 | 2011-01-20 18:06:34 +0000 | [diff] [blame] | 1216 | server->lstrp = jiffies; |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1217 | |
| 1218 | for (i = 0; i < num_mids; i++) { |
| 1219 | if (mids[i] != NULL) { |
| 1220 | mids[i]->resp_buf_size = server->pdu_size; |
Sachin Prabhu | 38bd490 | 2017-03-03 15:41:38 -0800 | [diff] [blame] | 1221 | |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1222 | if (!mids[i]->multiRsp || mids[i]->multiEnd) |
| 1223 | mids[i]->callback(mids[i]); |
Lars Persson | 696e420 | 2018-06-25 14:05:25 +0200 | [diff] [blame] | 1224 | |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1225 | cifs_mid_q_entry_release(mids[i]); |
| 1226 | } else if (server->ops->is_oplock_break && |
| 1227 | server->ops->is_oplock_break(bufs[i], |
| 1228 | server)) { |
Ronnie Sahlberg | eca0045 | 2019-02-05 12:56:44 +1000 | [diff] [blame] | 1229 | smb2_add_credits_from_hdr(bufs[i], server); |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1230 | cifs_dbg(FYI, "Received oplock break\n"); |
| 1231 | } else { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 1232 | cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n", |
| 1233 | atomic_read(&midCount)); |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1234 | cifs_dump_mem("Received Data is: ", bufs[i], |
| 1235 | HEADER_SIZE(server)); |
Ronnie Sahlberg | 3e27257 | 2019-07-06 06:43:08 +1000 | [diff] [blame] | 1236 | smb2_add_credits_from_hdr(bufs[i], server); |
Steve French | 3979877 | 2006-05-31 22:40:51 +0000 | [diff] [blame] | 1237 | #ifdef CONFIG_CIFS_DEBUG2 |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1238 | if (server->ops->dump_detail) |
| 1239 | server->ops->dump_detail(bufs[i], |
| 1240 | server); |
| 1241 | cifs_dump_mids(server); |
Steve French | 3979877 | 2006-05-31 22:40:51 +0000 | [diff] [blame] | 1242 | #endif /* CIFS_DEBUG2 */ |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1243 | } |
Ronnie Sahlberg | 8ce79ec | 2018-06-01 10:53:08 +1000 | [diff] [blame] | 1244 | } |
Ronnie Sahlberg | b24df3e | 2018-08-08 15:07:45 +1000 | [diff] [blame] | 1245 | |
Ronnie Sahlberg | 8ce79ec | 2018-06-01 10:53:08 +1000 | [diff] [blame] | 1246 | if (pdu_length > server->pdu_size) { |
| 1247 | if (!allocate_buffers(server)) |
| 1248 | continue; |
| 1249 | pdu_length -= server->pdu_size; |
| 1250 | server->total_read = 0; |
| 1251 | server->large_buf = false; |
| 1252 | buf = server->smallbuf; |
| 1253 | goto next_pdu; |
Steve French | e4eb295 | 2005-04-28 22:41:09 -0700 | [diff] [blame] | 1254 | } |
| 1255 | } /* end while !EXITING */ |
| 1256 | |
Justin P. Mattock | fd62cb7 | 2011-02-24 22:15:02 -0800 | [diff] [blame] | 1257 | /* buffer usually freed in free_mid - need to free it here on exit */ |
Jeff Layton | 2a37ef9 | 2011-10-19 15:29:23 -0400 | [diff] [blame] | 1258 | cifs_buf_release(server->bigbuf); |
| 1259 | if (server->smallbuf) /* no sense logging a debug message if NULL */ |
| 1260 | cifs_small_buf_release(server->smallbuf); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1261 | |
Steve French | a5c3e1c | 2014-09-16 04:16:19 -0500 | [diff] [blame] | 1262 | task_to_wake = xchg(&server->tsk, NULL); |
Pavel Shilovsky | 762dfd1 | 2011-08-01 13:19:44 +0400 | [diff] [blame] | 1263 | clean_demultiplex_info(server); |
Steve French | a5c3e1c | 2014-09-16 04:16:19 -0500 | [diff] [blame] | 1264 | |
| 1265 | /* if server->tsk was NULL then wait for a signal before exiting */ |
| 1266 | if (!task_to_wake) { |
| 1267 | set_current_state(TASK_INTERRUPTIBLE); |
| 1268 | while (!signal_pending(current)) { |
| 1269 | schedule(); |
| 1270 | set_current_state(TASK_INTERRUPTIBLE); |
| 1271 | } |
| 1272 | set_current_state(TASK_RUNNING); |
| 1273 | } |
| 1274 | |
Eric Biggers | dc92027 | 2020-03-08 22:58:20 -0700 | [diff] [blame] | 1275 | memalloc_noreclaim_restore(noreclaim_flag); |
Jeff Layton | 0468a2c | 2008-12-01 07:09:35 -0500 | [diff] [blame] | 1276 | module_put_and_exit(0); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1277 | } |
| 1278 | |
Jeff Layton | c359cf3 | 2007-11-16 22:22:06 +0000 | [diff] [blame] | 1279 | /* extract the host portion of the UNC string */ |
| 1280 | static char * |
| 1281 | extract_hostname(const char *unc) |
| 1282 | { |
| 1283 | const char *src; |
| 1284 | char *dst, *delim; |
| 1285 | unsigned int len; |
| 1286 | |
| 1287 | /* skip double chars at beginning of string */ |
| 1288 | /* BB: check validity of these bytes? */ |
Paulo Alcantara | c34fea5 | 2018-11-14 14:03:40 -0200 | [diff] [blame] | 1289 | if (strlen(unc) < 3) |
| 1290 | return ERR_PTR(-EINVAL); |
| 1291 | for (src = unc; *src && *src == '\\'; src++) |
| 1292 | ; |
| 1293 | if (!*src) |
| 1294 | return ERR_PTR(-EINVAL); |
Jeff Layton | c359cf3 | 2007-11-16 22:22:06 +0000 | [diff] [blame] | 1295 | |
| 1296 | /* delimiter between hostname and sharename is always '\\' now */ |
| 1297 | delim = strchr(src, '\\'); |
| 1298 | if (!delim) |
| 1299 | return ERR_PTR(-EINVAL); |
| 1300 | |
| 1301 | len = delim - src; |
| 1302 | dst = kmalloc((len + 1), GFP_KERNEL); |
| 1303 | if (dst == NULL) |
| 1304 | return ERR_PTR(-ENOMEM); |
| 1305 | |
| 1306 | memcpy(dst, src, len); |
| 1307 | dst[len] = '\0'; |
| 1308 | |
| 1309 | return dst; |
| 1310 | } |
| 1311 | |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1312 | static int get_option_ul(substring_t args[], unsigned long *option) |
| 1313 | { |
| 1314 | int rc; |
| 1315 | char *string; |
| 1316 | |
| 1317 | string = match_strdup(args); |
| 1318 | if (string == NULL) |
| 1319 | return -ENOMEM; |
Sachin Prabhu | bfa890a | 2012-04-13 14:04:32 +0100 | [diff] [blame] | 1320 | rc = kstrtoul(string, 0, option); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1321 | kfree(string); |
| 1322 | |
| 1323 | return rc; |
| 1324 | } |
| 1325 | |
Eric W. Biederman | 3da4656 | 2013-02-06 01:37:39 -0800 | [diff] [blame] | 1326 | static int get_option_uid(substring_t args[], kuid_t *result) |
| 1327 | { |
| 1328 | unsigned long value; |
| 1329 | kuid_t uid; |
| 1330 | int rc; |
| 1331 | |
| 1332 | rc = get_option_ul(args, &value); |
| 1333 | if (rc) |
| 1334 | return rc; |
| 1335 | |
| 1336 | uid = make_kuid(current_user_ns(), value); |
| 1337 | if (!uid_valid(uid)) |
| 1338 | return -EINVAL; |
| 1339 | |
| 1340 | *result = uid; |
| 1341 | return 0; |
| 1342 | } |
| 1343 | |
| 1344 | static int get_option_gid(substring_t args[], kgid_t *result) |
| 1345 | { |
| 1346 | unsigned long value; |
| 1347 | kgid_t gid; |
| 1348 | int rc; |
| 1349 | |
| 1350 | rc = get_option_ul(args, &value); |
| 1351 | if (rc) |
| 1352 | return rc; |
| 1353 | |
| 1354 | gid = make_kgid(current_user_ns(), value); |
| 1355 | if (!gid_valid(gid)) |
| 1356 | return -EINVAL; |
| 1357 | |
| 1358 | *result = gid; |
| 1359 | return 0; |
| 1360 | } |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1361 | |
| 1362 | static int cifs_parse_security_flavors(char *value, |
| 1363 | struct smb_vol *vol) |
| 1364 | { |
| 1365 | |
| 1366 | substring_t args[MAX_OPT_ARGS]; |
| 1367 | |
Jeff Layton | 1e3cc57 | 2013-06-10 17:12:23 -0500 | [diff] [blame] | 1368 | /* |
| 1369 | * With mount options, the last one should win. Reset any existing |
| 1370 | * settings back to default. |
| 1371 | */ |
| 1372 | vol->sectype = Unspecified; |
| 1373 | vol->sign = false; |
| 1374 | |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1375 | switch (match_token(value, cifs_secflavor_tokens, args)) { |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 1376 | case Opt_sec_krb5p: |
| 1377 | cifs_dbg(VFS, "sec=krb5p is not supported!\n"); |
| 1378 | return 1; |
| 1379 | case Opt_sec_krb5i: |
| 1380 | vol->sign = true; |
Gustavo A. R. Silva | df561f66 | 2020-08-23 17:36:59 -0500 | [diff] [blame] | 1381 | fallthrough; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1382 | case Opt_sec_krb5: |
Jeff Layton | 1e3cc57 | 2013-06-10 17:12:23 -0500 | [diff] [blame] | 1383 | vol->sectype = Kerberos; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1384 | break; |
| 1385 | case Opt_sec_ntlmsspi: |
Jeff Layton | 1e3cc57 | 2013-06-10 17:12:23 -0500 | [diff] [blame] | 1386 | vol->sign = true; |
Gustavo A. R. Silva | df561f66 | 2020-08-23 17:36:59 -0500 | [diff] [blame] | 1387 | fallthrough; |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 1388 | case Opt_sec_ntlmssp: |
| 1389 | vol->sectype = RawNTLMSSP; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1390 | break; |
| 1391 | case Opt_sec_ntlmi: |
Jeff Layton | 1e3cc57 | 2013-06-10 17:12:23 -0500 | [diff] [blame] | 1392 | vol->sign = true; |
Gustavo A. R. Silva | df561f66 | 2020-08-23 17:36:59 -0500 | [diff] [blame] | 1393 | fallthrough; |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 1394 | case Opt_ntlm: |
| 1395 | vol->sectype = NTLM; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1396 | break; |
| 1397 | case Opt_sec_ntlmv2i: |
Jeff Layton | 1e3cc57 | 2013-06-10 17:12:23 -0500 | [diff] [blame] | 1398 | vol->sign = true; |
Gustavo A. R. Silva | df561f66 | 2020-08-23 17:36:59 -0500 | [diff] [blame] | 1399 | fallthrough; |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 1400 | case Opt_sec_ntlmv2: |
| 1401 | vol->sectype = NTLMv2; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1402 | break; |
| 1403 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
| 1404 | case Opt_sec_lanman: |
Jeff Layton | 1e3cc57 | 2013-06-10 17:12:23 -0500 | [diff] [blame] | 1405 | vol->sectype = LANMAN; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1406 | break; |
| 1407 | #endif |
| 1408 | case Opt_sec_none: |
| 1409 | vol->nullauth = 1; |
| 1410 | break; |
| 1411 | default: |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1412 | cifs_dbg(VFS, "bad security option: %s\n", value); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1413 | return 1; |
| 1414 | } |
| 1415 | |
| 1416 | return 0; |
| 1417 | } |
| 1418 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1419 | static int |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 1420 | cifs_parse_cache_flavor(char *value, struct smb_vol *vol) |
| 1421 | { |
| 1422 | substring_t args[MAX_OPT_ARGS]; |
| 1423 | |
| 1424 | switch (match_token(value, cifs_cacheflavor_tokens, args)) { |
| 1425 | case Opt_cache_loose: |
| 1426 | vol->direct_io = false; |
| 1427 | vol->strict_io = false; |
Steve French | 83bbfa7 | 2019-08-27 23:58:54 -0500 | [diff] [blame] | 1428 | vol->cache_ro = false; |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 1429 | vol->cache_rw = false; |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 1430 | break; |
| 1431 | case Opt_cache_strict: |
| 1432 | vol->direct_io = false; |
| 1433 | vol->strict_io = true; |
Steve French | 83bbfa7 | 2019-08-27 23:58:54 -0500 | [diff] [blame] | 1434 | vol->cache_ro = false; |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 1435 | vol->cache_rw = false; |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 1436 | break; |
| 1437 | case Opt_cache_none: |
| 1438 | vol->direct_io = true; |
| 1439 | vol->strict_io = false; |
Steve French | 83bbfa7 | 2019-08-27 23:58:54 -0500 | [diff] [blame] | 1440 | vol->cache_ro = false; |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 1441 | vol->cache_rw = false; |
Steve French | 83bbfa7 | 2019-08-27 23:58:54 -0500 | [diff] [blame] | 1442 | break; |
| 1443 | case Opt_cache_ro: |
| 1444 | vol->direct_io = false; |
| 1445 | vol->strict_io = false; |
| 1446 | vol->cache_ro = true; |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 1447 | vol->cache_rw = false; |
| 1448 | break; |
| 1449 | case Opt_cache_rw: |
| 1450 | vol->direct_io = false; |
| 1451 | vol->strict_io = false; |
| 1452 | vol->cache_ro = false; |
| 1453 | vol->cache_rw = true; |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 1454 | break; |
| 1455 | default: |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1456 | cifs_dbg(VFS, "bad cache= option: %s\n", value); |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 1457 | return 1; |
| 1458 | } |
| 1459 | return 0; |
| 1460 | } |
| 1461 | |
| 1462 | static int |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 1463 | cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3) |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 1464 | { |
| 1465 | substring_t args[MAX_OPT_ARGS]; |
| 1466 | |
| 1467 | switch (match_token(value, cifs_smb_version_tokens, args)) { |
Steve French | 7420451 | 2018-06-19 14:34:08 -0500 | [diff] [blame] | 1468 | #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 1469 | case Smb_1: |
Steve French | f92a720 | 2018-05-24 04:11:07 -0500 | [diff] [blame] | 1470 | if (disable_legacy_dialects) { |
| 1471 | cifs_dbg(VFS, "mount with legacy dialect disabled\n"); |
| 1472 | return 1; |
| 1473 | } |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 1474 | if (is_smb3) { |
| 1475 | cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n"); |
| 1476 | return 1; |
| 1477 | } |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 1478 | cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n"); |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 1479 | vol->ops = &smb1_operations; |
| 1480 | vol->vals = &smb1_values; |
| 1481 | break; |
Steve French | dd446b1 | 2012-11-28 23:21:06 -0600 | [diff] [blame] | 1482 | case Smb_20: |
Steve French | f92a720 | 2018-05-24 04:11:07 -0500 | [diff] [blame] | 1483 | if (disable_legacy_dialects) { |
| 1484 | cifs_dbg(VFS, "mount with legacy dialect disabled\n"); |
| 1485 | return 1; |
| 1486 | } |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 1487 | if (is_smb3) { |
| 1488 | cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n"); |
| 1489 | return 1; |
| 1490 | } |
Pavel Shilovsky | 53ef101 | 2013-09-05 16:11:28 +0400 | [diff] [blame] | 1491 | vol->ops = &smb20_operations; |
Steve French | dd446b1 | 2012-11-28 23:21:06 -0600 | [diff] [blame] | 1492 | vol->vals = &smb20_values; |
| 1493 | break; |
Steve French | 7420451 | 2018-06-19 14:34:08 -0500 | [diff] [blame] | 1494 | #else |
| 1495 | case Smb_1: |
| 1496 | cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n"); |
| 1497 | return 1; |
| 1498 | case Smb_20: |
| 1499 | cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n"); |
| 1500 | return 1; |
| 1501 | #endif /* CIFS_ALLOW_INSECURE_LEGACY */ |
Steve French | 1080ef7 | 2011-02-24 18:07:19 +0000 | [diff] [blame] | 1502 | case Smb_21: |
| 1503 | vol->ops = &smb21_operations; |
| 1504 | vol->vals = &smb21_values; |
| 1505 | break; |
Steve French | e4aa25e | 2012-10-01 12:26:22 -0500 | [diff] [blame] | 1506 | case Smb_30: |
Steve French | 38107d4 | 2012-12-08 22:08:06 -0600 | [diff] [blame] | 1507 | vol->ops = &smb30_operations; |
Steve French | e4aa25e | 2012-10-01 12:26:22 -0500 | [diff] [blame] | 1508 | vol->vals = &smb30_values; |
| 1509 | break; |
Steve French | 20b6d8b | 2013-06-12 22:48:41 -0500 | [diff] [blame] | 1510 | case Smb_302: |
| 1511 | vol->ops = &smb30_operations; /* currently identical with 3.0 */ |
| 1512 | vol->vals = &smb302_values; |
| 1513 | break; |
Steve French | 5f7fbf7 | 2014-12-17 22:52:58 -0600 | [diff] [blame] | 1514 | case Smb_311: |
Steve French | aab1893 | 2015-06-23 23:37:11 -0500 | [diff] [blame] | 1515 | vol->ops = &smb311_operations; |
Steve French | 5f7fbf7 | 2014-12-17 22:52:58 -0600 | [diff] [blame] | 1516 | vol->vals = &smb311_values; |
| 1517 | break; |
Steve French | 9764c02 | 2017-09-17 10:41:35 -0500 | [diff] [blame] | 1518 | case Smb_3any: |
| 1519 | vol->ops = &smb30_operations; /* currently identical with 3.0 */ |
| 1520 | vol->vals = &smb3any_values; |
| 1521 | break; |
| 1522 | case Smb_default: |
| 1523 | vol->ops = &smb30_operations; /* currently identical with 3.0 */ |
| 1524 | vol->vals = &smbdefault_values; |
| 1525 | break; |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 1526 | default: |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1527 | cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value); |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 1528 | return 1; |
| 1529 | } |
| 1530 | return 0; |
| 1531 | } |
| 1532 | |
Jeff Layton | d387a5c | 2012-12-10 06:10:46 -0500 | [diff] [blame] | 1533 | /* |
| 1534 | * Parse a devname into substrings and populate the vol->UNC and vol->prepath |
| 1535 | * fields with the result. Returns 0 on success and an error otherwise. |
| 1536 | */ |
| 1537 | static int |
| 1538 | cifs_parse_devname(const char *devname, struct smb_vol *vol) |
| 1539 | { |
| 1540 | char *pos; |
| 1541 | const char *delims = "/\\"; |
| 1542 | size_t len; |
| 1543 | |
Yao Liu | 68e2672 | 2019-01-28 19:47:28 +0800 | [diff] [blame] | 1544 | if (unlikely(!devname || !*devname)) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 1545 | cifs_dbg(VFS, "Device name not specified\n"); |
Yao Liu | 68e2672 | 2019-01-28 19:47:28 +0800 | [diff] [blame] | 1546 | return -EINVAL; |
| 1547 | } |
| 1548 | |
Jeff Layton | d387a5c | 2012-12-10 06:10:46 -0500 | [diff] [blame] | 1549 | /* make sure we have a valid UNC double delimiter prefix */ |
| 1550 | len = strspn(devname, delims); |
| 1551 | if (len != 2) |
| 1552 | return -EINVAL; |
| 1553 | |
| 1554 | /* find delimiter between host and sharename */ |
| 1555 | pos = strpbrk(devname + 2, delims); |
| 1556 | if (!pos) |
| 1557 | return -EINVAL; |
| 1558 | |
| 1559 | /* skip past delimiter */ |
| 1560 | ++pos; |
| 1561 | |
| 1562 | /* now go until next delimiter or end of string */ |
| 1563 | len = strcspn(pos, delims); |
| 1564 | |
| 1565 | /* move "pos" up to delimiter or NULL */ |
| 1566 | pos += len; |
| 1567 | vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL); |
| 1568 | if (!vol->UNC) |
| 1569 | return -ENOMEM; |
| 1570 | |
| 1571 | convert_delimiter(vol->UNC, '\\'); |
| 1572 | |
Sachin Prabhu | 11e3164 | 2016-02-08 13:44:01 +0530 | [diff] [blame] | 1573 | /* skip any delimiter */ |
| 1574 | if (*pos == '/' || *pos == '\\') |
| 1575 | pos++; |
| 1576 | |
| 1577 | /* If pos is NULL then no prepath */ |
| 1578 | if (!*pos) |
Jeff Layton | d387a5c | 2012-12-10 06:10:46 -0500 | [diff] [blame] | 1579 | return 0; |
| 1580 | |
| 1581 | vol->prepath = kstrdup(pos, GFP_KERNEL); |
| 1582 | if (!vol->prepath) |
| 1583 | return -ENOMEM; |
| 1584 | |
| 1585 | return 0; |
| 1586 | } |
| 1587 | |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 1588 | static int |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 1589 | cifs_parse_mount_options(const char *mountdata, const char *devname, |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 1590 | struct smb_vol *vol, bool is_smb3) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1591 | { |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1592 | char *data, *end; |
Vasily Averin | 957df45 | 2011-06-06 11:33:12 +0400 | [diff] [blame] | 1593 | char *mountdata_copy = NULL, *options; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1594 | unsigned int temp_len, i, j; |
| 1595 | char separator[2]; |
Jeff Layton | 9b9d6b24 | 2009-07-31 06:56:09 -0400 | [diff] [blame] | 1596 | short int override_uid = -1; |
| 1597 | short int override_gid = -1; |
| 1598 | bool uid_specified = false; |
| 1599 | bool gid_specified = false; |
Jeff Layton | d816255 | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1600 | bool sloppy = false; |
| 1601 | char *invalid = NULL; |
Jeff Layton | 8846399 | 2010-11-22 15:31:03 -0500 | [diff] [blame] | 1602 | char *nodename = utsname()->nodename; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1603 | char *string = NULL; |
| 1604 | char *tmp_end, *value; |
| 1605 | char delim; |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 1606 | bool got_ip = false; |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 1607 | bool got_version = false; |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 1608 | unsigned short port = 0; |
| 1609 | struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1610 | |
| 1611 | separator[0] = ','; |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 1612 | separator[1] = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1613 | delim = separator[0]; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1614 | |
Jeff Layton | 6ee9542 | 2012-11-26 11:09:57 -0500 | [diff] [blame] | 1615 | /* ensure we always start with zeroed-out smb_vol */ |
| 1616 | memset(vol, 0, sizeof(*vol)); |
| 1617 | |
Jeff Layton | 8846399 | 2010-11-22 15:31:03 -0500 | [diff] [blame] | 1618 | /* |
| 1619 | * does not have to be perfect mapping since field is |
| 1620 | * informational, only used for servers that do not support |
| 1621 | * port 445 and it can be overridden at mount time |
| 1622 | */ |
Jeff Layton | 1397f2e | 2011-01-07 11:30:28 -0500 | [diff] [blame] | 1623 | memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); |
| 1624 | for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++) |
Jeff Layton | 8846399 | 2010-11-22 15:31:03 -0500 | [diff] [blame] | 1625 | vol->source_rfc1001_name[i] = toupper(nodename[i]); |
| 1626 | |
Jeff Layton | 1397f2e | 2011-01-07 11:30:28 -0500 | [diff] [blame] | 1627 | vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0; |
Steve French | a10faeb2 | 2005-08-22 21:38:31 -0700 | [diff] [blame] | 1628 | /* null target name indicates to use *SMBSERVR default called name |
| 1629 | if we end up sending RFC1001 session initialize */ |
| 1630 | vol->target_rfc1001_name[0] = 0; |
Jeff Layton | 3e4b3e1 | 2010-07-19 18:00:17 -0400 | [diff] [blame] | 1631 | vol->cred_uid = current_uid(); |
| 1632 | vol->linux_uid = current_uid(); |
David Howells | a001e5b | 2008-11-14 10:38:47 +1100 | [diff] [blame] | 1633 | vol->linux_gid = current_gid(); |
Steve French | e8506d2 | 2019-02-28 21:32:15 -0600 | [diff] [blame] | 1634 | vol->bsize = 1024 * 1024; /* can improve cp performance significantly */ |
Steve French | 2baa268 | 2014-09-27 02:19:01 -0500 | [diff] [blame] | 1635 | /* |
| 1636 | * default to SFM style remapping of seven reserved characters |
| 1637 | * unless user overrides it or we negotiate CIFS POSIX where |
| 1638 | * it is unnecessary. Can not simultaneously use more than one mapping |
| 1639 | * since then readdir could list files that open could not open |
| 1640 | */ |
| 1641 | vol->remap = true; |
| 1642 | |
Jeff Layton | f55ed1a | 2009-05-26 16:28:11 -0400 | [diff] [blame] | 1643 | /* default to only allowing write access to owner of the mount */ |
| 1644 | vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1645 | |
| 1646 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
Jeremy Allison | ac67055 | 2005-06-22 17:26:35 -0700 | [diff] [blame] | 1647 | /* default is always to request posix paths. */ |
| 1648 | vol->posix_paths = 1; |
Jeff Layton | a0c9217 | 2009-05-27 15:40:47 -0400 | [diff] [blame] | 1649 | /* default to using server inode numbers where available */ |
| 1650 | vol->server_ino = 1; |
Jeremy Allison | ac67055 | 2005-06-22 17:26:35 -0700 | [diff] [blame] | 1651 | |
Jeff Layton | 1b35920 | 2012-09-19 15:20:27 -0700 | [diff] [blame] | 1652 | /* default is to use strict cifs caching semantics */ |
| 1653 | vol->strict_io = true; |
| 1654 | |
Suresh Jayaraman | 6d20e84 | 2010-12-01 14:42:28 +0530 | [diff] [blame] | 1655 | vol->actimeo = CIFS_DEF_ACTIMEO; |
| 1656 | |
Steve French | ca567eb | 2019-03-29 16:31:07 -0500 | [diff] [blame] | 1657 | /* Most clients set timeout to 0, allows server to use its default */ |
| 1658 | vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */ |
| 1659 | |
Steve French | 9764c02 | 2017-09-17 10:41:35 -0500 | [diff] [blame] | 1660 | /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */ |
| 1661 | vol->ops = &smb30_operations; |
| 1662 | vol->vals = &smbdefault_values; |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 1663 | |
Rabin Vincent | b782fcc | 2016-07-19 09:25:45 +0200 | [diff] [blame] | 1664 | vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT; |
| 1665 | |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 1666 | /* default to no multichannel (single server connection) */ |
| 1667 | vol->multichannel = false; |
| 1668 | vol->max_channels = 1; |
| 1669 | |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 1670 | if (!mountdata) |
| 1671 | goto cifs_parse_mount_err; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1672 | |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 1673 | mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL); |
| 1674 | if (!mountdata_copy) |
| 1675 | goto cifs_parse_mount_err; |
| 1676 | |
| 1677 | options = mountdata_copy; |
Pavel Shilovsky | 4906e50 | 2011-04-14 22:00:56 +0400 | [diff] [blame] | 1678 | end = options + strlen(options); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1679 | |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 1680 | if (strncmp(options, "sep=", 4) == 0) { |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 1681 | if (options[4] != 0) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1682 | separator[0] = options[4]; |
| 1683 | options += 5; |
| 1684 | } else { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1685 | cifs_dbg(FYI, "Null separator not allowed\n"); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1686 | } |
| 1687 | } |
Shirish Pargaonkar | 3d3ea8e | 2011-09-26 09:56:44 -0500 | [diff] [blame] | 1688 | vol->backupuid_specified = false; /* no backup intent for a user */ |
| 1689 | vol->backupgid_specified = false; /* no backup intent for a group */ |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 1690 | |
Jeff Layton | 37d4f99 | 2013-05-24 07:40:05 -0400 | [diff] [blame] | 1691 | switch (cifs_parse_devname(devname, vol)) { |
| 1692 | case 0: |
| 1693 | break; |
| 1694 | case -ENOMEM: |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 1695 | cifs_dbg(VFS, "Unable to allocate memory for devname\n"); |
Jeff Layton | 37d4f99 | 2013-05-24 07:40:05 -0400 | [diff] [blame] | 1696 | goto cifs_parse_mount_err; |
| 1697 | case -EINVAL: |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 1698 | cifs_dbg(VFS, "Malformed UNC in devname\n"); |
Jeff Layton | 37d4f99 | 2013-05-24 07:40:05 -0400 | [diff] [blame] | 1699 | goto cifs_parse_mount_err; |
| 1700 | default: |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 1701 | cifs_dbg(VFS, "Unknown error parsing devname\n"); |
Jeff Layton | 37d4f99 | 2013-05-24 07:40:05 -0400 | [diff] [blame] | 1702 | goto cifs_parse_mount_err; |
Jeff Layton | d387a5c | 2012-12-10 06:10:46 -0500 | [diff] [blame] | 1703 | } |
| 1704 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1705 | while ((data = strsep(&options, separator)) != NULL) { |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1706 | substring_t args[MAX_OPT_ARGS]; |
| 1707 | unsigned long option; |
| 1708 | int token; |
| 1709 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1710 | if (!*data) |
| 1711 | continue; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1712 | |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1713 | token = match_token(data, cifs_mount_option_tokens, args); |
| 1714 | |
| 1715 | switch (token) { |
| 1716 | |
| 1717 | /* Ingnore the following */ |
| 1718 | case Opt_ignore: |
| 1719 | break; |
| 1720 | |
| 1721 | /* Boolean values */ |
| 1722 | case Opt_user_xattr: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1723 | vol->no_xattr = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1724 | break; |
| 1725 | case Opt_nouser_xattr: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1726 | vol->no_xattr = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1727 | break; |
| 1728 | case Opt_forceuid: |
Jeff Layton | 9b9d6b24 | 2009-07-31 06:56:09 -0400 | [diff] [blame] | 1729 | override_uid = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1730 | break; |
| 1731 | case Opt_noforceuid: |
Jeff Layton | 9b9d6b24 | 2009-07-31 06:56:09 -0400 | [diff] [blame] | 1732 | override_uid = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1733 | break; |
Jeff Layton | 72bd481 | 2012-10-03 16:02:36 -0400 | [diff] [blame] | 1734 | case Opt_forcegid: |
| 1735 | override_gid = 1; |
| 1736 | break; |
| 1737 | case Opt_noforcegid: |
| 1738 | override_gid = 0; |
| 1739 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1740 | case Opt_noblocksend: |
Steve French | edf1ae4 | 2008-10-29 00:47:57 +0000 | [diff] [blame] | 1741 | vol->noblocksnd = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1742 | break; |
| 1743 | case Opt_noautotune: |
Steve French | edf1ae4 | 2008-10-29 00:47:57 +0000 | [diff] [blame] | 1744 | vol->noautotune = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1745 | break; |
Steve French | 3e7a02d | 2019-09-11 21:46:20 -0500 | [diff] [blame] | 1746 | case Opt_nolease: |
| 1747 | vol->no_lease = 1; |
| 1748 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1749 | case Opt_hard: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1750 | vol->retry = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1751 | break; |
| 1752 | case Opt_soft: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1753 | vol->retry = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1754 | break; |
| 1755 | case Opt_perm: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1756 | vol->noperm = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1757 | break; |
| 1758 | case Opt_noperm: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1759 | vol->noperm = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1760 | break; |
Steve French | 82e9367 | 2020-05-19 03:06:57 -0500 | [diff] [blame] | 1761 | case Opt_nodelete: |
| 1762 | vol->nodelete = 1; |
| 1763 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1764 | case Opt_mapchars: |
Steve French | 2baa268 | 2014-09-27 02:19:01 -0500 | [diff] [blame] | 1765 | vol->sfu_remap = true; |
| 1766 | vol->remap = false; /* disable SFM mapping */ |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1767 | break; |
| 1768 | case Opt_nomapchars: |
Steve French | 2baa268 | 2014-09-27 02:19:01 -0500 | [diff] [blame] | 1769 | vol->sfu_remap = false; |
| 1770 | break; |
| 1771 | case Opt_mapposix: |
| 1772 | vol->remap = true; |
| 1773 | vol->sfu_remap = false; /* disable SFU mapping */ |
| 1774 | break; |
| 1775 | case Opt_nomapposix: |
| 1776 | vol->remap = false; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1777 | break; |
| 1778 | case Opt_sfu: |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 1779 | vol->sfu_emul = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1780 | break; |
| 1781 | case Opt_nosfu: |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 1782 | vol->sfu_emul = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1783 | break; |
| 1784 | case Opt_nodfs: |
Steve French | 2c1b861 | 2008-10-16 18:35:21 +0000 | [diff] [blame] | 1785 | vol->nodfs = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1786 | break; |
Paulo Alcantara (SUSE) | 8eecd1c | 2019-07-16 19:04:50 -0300 | [diff] [blame] | 1787 | case Opt_rootfs: |
| 1788 | #ifdef CONFIG_CIFS_ROOT |
| 1789 | vol->rootfs = true; |
| 1790 | #endif |
| 1791 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1792 | case Opt_posixpaths: |
Jeremy Allison | ac67055 | 2005-06-22 17:26:35 -0700 | [diff] [blame] | 1793 | vol->posix_paths = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1794 | break; |
| 1795 | case Opt_noposixpaths: |
Jeremy Allison | ac67055 | 2005-06-22 17:26:35 -0700 | [diff] [blame] | 1796 | vol->posix_paths = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1797 | break; |
| 1798 | case Opt_nounix: |
Steve French | b326614 | 2018-05-20 23:41:10 -0500 | [diff] [blame] | 1799 | if (vol->linux_ext) |
| 1800 | cifs_dbg(VFS, |
| 1801 | "conflicting unix mount options\n"); |
Steve French | c18c842 | 2007-07-18 23:21:09 +0000 | [diff] [blame] | 1802 | vol->no_linux_ext = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1803 | break; |
Steve French | b326614 | 2018-05-20 23:41:10 -0500 | [diff] [blame] | 1804 | case Opt_unix: |
| 1805 | if (vol->no_linux_ext) |
| 1806 | cifs_dbg(VFS, |
| 1807 | "conflicting unix mount options\n"); |
| 1808 | vol->linux_ext = 1; |
| 1809 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1810 | case Opt_nocase: |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 1811 | vol->nocase = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1812 | break; |
| 1813 | case Opt_brl: |
Steve French | c46fa8a | 2005-08-18 20:49:57 -0700 | [diff] [blame] | 1814 | vol->nobrl = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1815 | break; |
| 1816 | case Opt_nobrl: |
Steve French | c46fa8a | 2005-08-18 20:49:57 -0700 | [diff] [blame] | 1817 | vol->nobrl = 1; |
Pavel Shilovsky | 5cfdddc | 2012-03-27 20:51:15 +0400 | [diff] [blame] | 1818 | /* |
| 1819 | * turn off mandatory locking in mode |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1820 | * if remote locking is turned off since the |
Pavel Shilovsky | 5cfdddc | 2012-03-27 20:51:15 +0400 | [diff] [blame] | 1821 | * local vfs will do advisory |
| 1822 | */ |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 1823 | if (vol->file_mode == |
| 1824 | (S_IALLUGO & ~(S_ISUID | S_IXGRP))) |
Steve French | d3485d3 | 2005-08-19 11:04:29 -0700 | [diff] [blame] | 1825 | vol->file_mode = S_IALLUGO; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1826 | break; |
Steve French | 3d4ef9a | 2018-04-25 22:19:09 -0500 | [diff] [blame] | 1827 | case Opt_nohandlecache: |
| 1828 | vol->nohandlecache = 1; |
| 1829 | break; |
| 1830 | case Opt_handlecache: |
| 1831 | vol->nohandlecache = 0; |
| 1832 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1833 | case Opt_forcemandatorylock: |
Steve French | 13a6e42 | 2008-12-02 17:24:33 +0000 | [diff] [blame] | 1834 | vol->mand_lock = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1835 | break; |
| 1836 | case Opt_setuids: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1837 | vol->setuids = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1838 | break; |
| 1839 | case Opt_nosetuids: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1840 | vol->setuids = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1841 | break; |
Steve French | 9593265 | 2016-09-23 01:36:34 -0500 | [diff] [blame] | 1842 | case Opt_setuidfromacl: |
| 1843 | vol->setuidfromacl = 1; |
| 1844 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1845 | case Opt_dynperm: |
Jeff Layton | d0a9c07 | 2008-05-12 22:23:49 +0000 | [diff] [blame] | 1846 | vol->dynperm = true; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1847 | break; |
| 1848 | case Opt_nodynperm: |
Jeff Layton | d0a9c07 | 2008-05-12 22:23:49 +0000 | [diff] [blame] | 1849 | vol->dynperm = false; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1850 | break; |
| 1851 | case Opt_nohard: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1852 | vol->retry = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1853 | break; |
| 1854 | case Opt_nosoft: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1855 | vol->retry = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1856 | break; |
| 1857 | case Opt_nointr: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1858 | vol->intr = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1859 | break; |
| 1860 | case Opt_intr: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1861 | vol->intr = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1862 | break; |
| 1863 | case Opt_nostrictsync: |
Steve French | be65244 | 2009-02-23 15:21:59 +0000 | [diff] [blame] | 1864 | vol->nostrictsync = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1865 | break; |
| 1866 | case Opt_strictsync: |
Steve French | be65244 | 2009-02-23 15:21:59 +0000 | [diff] [blame] | 1867 | vol->nostrictsync = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1868 | break; |
| 1869 | case Opt_serverino: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1870 | vol->server_ino = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1871 | break; |
| 1872 | case Opt_noserverino: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1873 | vol->server_ino = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1874 | break; |
| 1875 | case Opt_rwpidforward: |
Pavel Shilovsky | d4ffff1 | 2011-05-26 06:02:00 +0000 | [diff] [blame] | 1876 | vol->rwpidforward = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1877 | break; |
Steve French | 412094a | 2019-06-24 02:01:42 -0500 | [diff] [blame] | 1878 | case Opt_modesid: |
| 1879 | vol->mode_ace = 1; |
| 1880 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1881 | case Opt_cifsacl: |
Steve French | 0a4b92c | 2006-01-12 15:44:21 -0800 | [diff] [blame] | 1882 | vol->cifs_acl = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1883 | break; |
| 1884 | case Opt_nocifsacl: |
Steve French | 0a4b92c | 2006-01-12 15:44:21 -0800 | [diff] [blame] | 1885 | vol->cifs_acl = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1886 | break; |
| 1887 | case Opt_acl: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1888 | vol->no_psx_acl = 0; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1889 | break; |
| 1890 | case Opt_noacl: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1891 | vol->no_psx_acl = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1892 | break; |
| 1893 | case Opt_locallease: |
Steve French | 84210e9 | 2008-10-23 04:42:37 +0000 | [diff] [blame] | 1894 | vol->local_lease = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1895 | break; |
| 1896 | case Opt_sign: |
Jeff Layton | 1e3cc57 | 2013-06-10 17:12:23 -0500 | [diff] [blame] | 1897 | vol->sign = true; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1898 | break; |
Steve French | 4f5c10f | 2019-09-03 21:18:49 -0500 | [diff] [blame] | 1899 | case Opt_ignore_signature: |
| 1900 | vol->sign = true; |
| 1901 | vol->ignore_signature = true; |
| 1902 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1903 | case Opt_seal: |
Steve French | 95b1cb9 | 2008-05-15 16:44:38 +0000 | [diff] [blame] | 1904 | /* we do not do the following in secFlags because seal |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1905 | * is a per tree connection (mount) not a per socket |
| 1906 | * or per-smb connection option in the protocol |
| 1907 | * vol->secFlg |= CIFSSEC_MUST_SEAL; |
| 1908 | */ |
Steve French | 95b1cb9 | 2008-05-15 16:44:38 +0000 | [diff] [blame] | 1909 | vol->seal = 1; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1910 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1911 | case Opt_noac: |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 1912 | pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1913 | break; |
| 1914 | case Opt_fsc: |
Suresh Jayaraman | 607a569 | 2010-11-24 17:49:05 +0530 | [diff] [blame] | 1915 | #ifndef CONFIG_CIFS_FSCACHE |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1916 | cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n"); |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 1917 | goto cifs_parse_mount_err; |
Suresh Jayaraman | 607a569 | 2010-11-24 17:49:05 +0530 | [diff] [blame] | 1918 | #endif |
Suresh Jayaraman | fa1df75 | 2010-07-05 18:13:36 +0530 | [diff] [blame] | 1919 | vol->fsc = true; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1920 | break; |
| 1921 | case Opt_mfsymlinks: |
Stefan Metzmacher | 736a3320 | 2010-07-30 14:56:00 +0200 | [diff] [blame] | 1922 | vol->mfsymlinks = true; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1923 | break; |
| 1924 | case Opt_multiuser: |
Jeff Layton | 0eb8a13 | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 1925 | vol->multiuser = true; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1926 | break; |
Jeff Layton | d816255 | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1927 | case Opt_sloppy: |
| 1928 | sloppy = true; |
| 1929 | break; |
Jeff Layton | a0b3df5 | 2013-05-24 07:40:59 -0400 | [diff] [blame] | 1930 | case Opt_nosharesock: |
| 1931 | vol->nosharesock = true; |
| 1932 | break; |
Steve French | b2a3077 | 2015-09-29 21:49:28 -0500 | [diff] [blame] | 1933 | case Opt_nopersistent: |
| 1934 | vol->nopersistent = true; |
| 1935 | if (vol->persistent) { |
| 1936 | cifs_dbg(VFS, |
| 1937 | "persistenthandles mount options conflict\n"); |
| 1938 | goto cifs_parse_mount_err; |
| 1939 | } |
| 1940 | break; |
| 1941 | case Opt_persistent: |
| 1942 | vol->persistent = true; |
Steve French | 592fafe | 2015-11-03 10:08:53 -0600 | [diff] [blame] | 1943 | if ((vol->nopersistent) || (vol->resilient)) { |
Steve French | b2a3077 | 2015-09-29 21:49:28 -0500 | [diff] [blame] | 1944 | cifs_dbg(VFS, |
| 1945 | "persistenthandles mount options conflict\n"); |
| 1946 | goto cifs_parse_mount_err; |
| 1947 | } |
| 1948 | break; |
Steve French | 592fafe | 2015-11-03 10:08:53 -0600 | [diff] [blame] | 1949 | case Opt_resilient: |
| 1950 | vol->resilient = true; |
| 1951 | if (vol->persistent) { |
| 1952 | cifs_dbg(VFS, |
| 1953 | "persistenthandles mount options conflict\n"); |
| 1954 | goto cifs_parse_mount_err; |
| 1955 | } |
| 1956 | break; |
| 1957 | case Opt_noresilient: |
| 1958 | vol->resilient = false; /* already the default */ |
| 1959 | break; |
Germano Percossi | 3956644 | 2016-12-15 12:31:18 +0530 | [diff] [blame] | 1960 | case Opt_domainauto: |
| 1961 | vol->domainauto = true; |
| 1962 | break; |
Long Li | 8339dd3 | 2017-11-07 01:54:55 -0700 | [diff] [blame] | 1963 | case Opt_rdma: |
| 1964 | vol->rdma = true; |
| 1965 | break; |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 1966 | case Opt_multichannel: |
| 1967 | vol->multichannel = true; |
Steve French | 1ee0e6d | 2020-06-02 23:17:16 -0500 | [diff] [blame] | 1968 | /* if number of channels not specified, default to 2 */ |
| 1969 | if (vol->max_channels < 2) |
| 1970 | vol->max_channels = 2; |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 1971 | break; |
| 1972 | case Opt_nomultichannel: |
| 1973 | vol->multichannel = false; |
Steve French | 1ee0e6d | 2020-06-02 23:17:16 -0500 | [diff] [blame] | 1974 | vol->max_channels = 1; |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 1975 | break; |
Steve French | 9fe5ff1 | 2019-06-24 20:39:04 -0500 | [diff] [blame] | 1976 | case Opt_compress: |
| 1977 | vol->compression = UNKNOWN_TYPE; |
| 1978 | cifs_dbg(VFS, |
| 1979 | "SMB3 compression support is experimental\n"); |
| 1980 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1981 | |
| 1982 | /* Numeric Values */ |
| 1983 | case Opt_backupuid: |
Eric W. Biederman | 3da4656 | 2013-02-06 01:37:39 -0800 | [diff] [blame] | 1984 | if (get_option_uid(args, &vol->backupuid)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1985 | cifs_dbg(VFS, "%s: Invalid backupuid value\n", |
| 1986 | __func__); |
Shirish Pargaonkar | 3d3ea8e | 2011-09-26 09:56:44 -0500 | [diff] [blame] | 1987 | goto cifs_parse_mount_err; |
| 1988 | } |
| 1989 | vol->backupuid_specified = true; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1990 | break; |
| 1991 | case Opt_backupgid: |
Eric W. Biederman | 3da4656 | 2013-02-06 01:37:39 -0800 | [diff] [blame] | 1992 | if (get_option_gid(args, &vol->backupgid)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 1993 | cifs_dbg(VFS, "%s: Invalid backupgid value\n", |
| 1994 | __func__); |
Shirish Pargaonkar | 3d3ea8e | 2011-09-26 09:56:44 -0500 | [diff] [blame] | 1995 | goto cifs_parse_mount_err; |
| 1996 | } |
| 1997 | vol->backupgid_specified = true; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 1998 | break; |
| 1999 | case Opt_uid: |
Eric W. Biederman | 3da4656 | 2013-02-06 01:37:39 -0800 | [diff] [blame] | 2000 | if (get_option_uid(args, &vol->linux_uid)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2001 | cifs_dbg(VFS, "%s: Invalid uid value\n", |
| 2002 | __func__); |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 2003 | goto cifs_parse_mount_err; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2004 | } |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2005 | uid_specified = true; |
| 2006 | break; |
| 2007 | case Opt_cruid: |
Eric W. Biederman | 3da4656 | 2013-02-06 01:37:39 -0800 | [diff] [blame] | 2008 | if (get_option_uid(args, &vol->cred_uid)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2009 | cifs_dbg(VFS, "%s: Invalid cruid value\n", |
| 2010 | __func__); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2011 | goto cifs_parse_mount_err; |
| 2012 | } |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2013 | break; |
| 2014 | case Opt_gid: |
Eric W. Biederman | 3da4656 | 2013-02-06 01:37:39 -0800 | [diff] [blame] | 2015 | if (get_option_gid(args, &vol->linux_gid)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2016 | cifs_dbg(VFS, "%s: Invalid gid value\n", |
| 2017 | __func__); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2018 | goto cifs_parse_mount_err; |
| 2019 | } |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2020 | gid_specified = true; |
| 2021 | break; |
| 2022 | case Opt_file_mode: |
| 2023 | if (get_option_ul(args, &option)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2024 | cifs_dbg(VFS, "%s: Invalid file_mode value\n", |
| 2025 | __func__); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2026 | goto cifs_parse_mount_err; |
| 2027 | } |
| 2028 | vol->file_mode = option; |
| 2029 | break; |
| 2030 | case Opt_dirmode: |
| 2031 | if (get_option_ul(args, &option)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2032 | cifs_dbg(VFS, "%s: Invalid dir_mode value\n", |
| 2033 | __func__); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2034 | goto cifs_parse_mount_err; |
| 2035 | } |
| 2036 | vol->dir_mode = option; |
| 2037 | break; |
| 2038 | case Opt_port: |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 2039 | if (get_option_ul(args, &option) || |
| 2040 | option > USHRT_MAX) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2041 | cifs_dbg(VFS, "%s: Invalid port value\n", |
| 2042 | __func__); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2043 | goto cifs_parse_mount_err; |
| 2044 | } |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 2045 | port = (unsigned short)option; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2046 | break; |
Steve French | 563317e | 2019-09-08 23:22:02 -0500 | [diff] [blame] | 2047 | case Opt_min_enc_offload: |
| 2048 | if (get_option_ul(args, &option)) { |
| 2049 | cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n"); |
| 2050 | goto cifs_parse_mount_err; |
| 2051 | } |
| 2052 | vol->min_offload = option; |
| 2053 | break; |
Steve French | e8506d2 | 2019-02-28 21:32:15 -0600 | [diff] [blame] | 2054 | case Opt_blocksize: |
| 2055 | if (get_option_ul(args, &option)) { |
| 2056 | cifs_dbg(VFS, "%s: Invalid blocksize value\n", |
| 2057 | __func__); |
| 2058 | goto cifs_parse_mount_err; |
| 2059 | } |
| 2060 | /* |
| 2061 | * inode blocksize realistically should never need to be |
| 2062 | * less than 16K or greater than 16M and default is 1MB. |
| 2063 | * Note that small inode block sizes (e.g. 64K) can lead |
| 2064 | * to very poor performance of common tools like cp and scp |
| 2065 | */ |
| 2066 | if ((option < CIFS_MAX_MSGSIZE) || |
| 2067 | (option > (4 * SMB3_DEFAULT_IOSIZE))) { |
| 2068 | cifs_dbg(VFS, "%s: Invalid blocksize\n", |
| 2069 | __func__); |
| 2070 | goto cifs_parse_mount_err; |
| 2071 | } |
| 2072 | vol->bsize = option; |
| 2073 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2074 | case Opt_rsize: |
| 2075 | if (get_option_ul(args, &option)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2076 | cifs_dbg(VFS, "%s: Invalid rsize value\n", |
| 2077 | __func__); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2078 | goto cifs_parse_mount_err; |
| 2079 | } |
| 2080 | vol->rsize = option; |
| 2081 | break; |
| 2082 | case Opt_wsize: |
| 2083 | if (get_option_ul(args, &option)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2084 | cifs_dbg(VFS, "%s: Invalid wsize value\n", |
| 2085 | __func__); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2086 | goto cifs_parse_mount_err; |
| 2087 | } |
| 2088 | vol->wsize = option; |
| 2089 | break; |
| 2090 | case Opt_actimeo: |
| 2091 | if (get_option_ul(args, &option)) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2092 | cifs_dbg(VFS, "%s: Invalid actimeo value\n", |
| 2093 | __func__); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2094 | goto cifs_parse_mount_err; |
| 2095 | } |
| 2096 | vol->actimeo = HZ * option; |
| 2097 | if (vol->actimeo > CIFS_MAX_ACTIMEO) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2098 | cifs_dbg(VFS, "attribute cache timeout too large\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2099 | goto cifs_parse_mount_err; |
| 2100 | } |
| 2101 | break; |
Steve French | ca567eb | 2019-03-29 16:31:07 -0500 | [diff] [blame] | 2102 | case Opt_handletimeout: |
| 2103 | if (get_option_ul(args, &option)) { |
| 2104 | cifs_dbg(VFS, "%s: Invalid handletimeout value\n", |
| 2105 | __func__); |
| 2106 | goto cifs_parse_mount_err; |
| 2107 | } |
| 2108 | vol->handle_timeout = option; |
| 2109 | if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) { |
| 2110 | cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n"); |
| 2111 | goto cifs_parse_mount_err; |
| 2112 | } |
| 2113 | break; |
Steve French | adfeb3e | 2015-12-18 12:31:36 -0600 | [diff] [blame] | 2114 | case Opt_echo_interval: |
| 2115 | if (get_option_ul(args, &option)) { |
| 2116 | cifs_dbg(VFS, "%s: Invalid echo interval value\n", |
| 2117 | __func__); |
| 2118 | goto cifs_parse_mount_err; |
| 2119 | } |
| 2120 | vol->echo_interval = option; |
| 2121 | break; |
Steve French | 8b217fe | 2016-11-11 22:36:20 -0600 | [diff] [blame] | 2122 | case Opt_snapshot: |
| 2123 | if (get_option_ul(args, &option)) { |
| 2124 | cifs_dbg(VFS, "%s: Invalid snapshot time\n", |
| 2125 | __func__); |
| 2126 | goto cifs_parse_mount_err; |
| 2127 | } |
| 2128 | vol->snapshot_time = option; |
| 2129 | break; |
Steve French | 141891f | 2016-09-23 00:44:16 -0500 | [diff] [blame] | 2130 | case Opt_max_credits: |
| 2131 | if (get_option_ul(args, &option) || (option < 20) || |
| 2132 | (option > 60000)) { |
| 2133 | cifs_dbg(VFS, "%s: Invalid max_credits value\n", |
| 2134 | __func__); |
| 2135 | goto cifs_parse_mount_err; |
| 2136 | } |
| 2137 | vol->max_credits = option; |
| 2138 | break; |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 2139 | case Opt_max_channels: |
| 2140 | if (get_option_ul(args, &option) || option < 1 || |
| 2141 | option > CIFS_MAX_CHANNELS) { |
| 2142 | cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n", |
| 2143 | __func__, CIFS_MAX_CHANNELS); |
| 2144 | goto cifs_parse_mount_err; |
| 2145 | } |
| 2146 | vol->max_channels = option; |
| 2147 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2148 | |
| 2149 | /* String Arguments */ |
| 2150 | |
Sachin Prabhu | 4fe9e96 | 2012-04-10 18:12:27 +0100 | [diff] [blame] | 2151 | case Opt_blank_user: |
| 2152 | /* null user, ie. anonymous authentication */ |
| 2153 | vol->nullauth = 1; |
| 2154 | vol->username = NULL; |
| 2155 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2156 | case Opt_user: |
| 2157 | string = match_strdup(args); |
| 2158 | if (string == NULL) |
| 2159 | goto out_nomem; |
| 2160 | |
Scott Lovenberg | 8c3a2b4 | 2013-08-09 08:47:17 -0400 | [diff] [blame] | 2161 | if (strnlen(string, CIFS_MAX_USERNAME_LEN) > |
| 2162 | CIFS_MAX_USERNAME_LEN) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2163 | pr_warn("username too long\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2164 | goto cifs_parse_mount_err; |
| 2165 | } |
Taesoo Kim | 2bd50fb | 2015-03-21 19:08:30 -0400 | [diff] [blame] | 2166 | |
| 2167 | kfree(vol->username); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2168 | vol->username = kstrdup(string, GFP_KERNEL); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2169 | if (!vol->username) |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2170 | goto cifs_parse_mount_err; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2171 | break; |
| 2172 | case Opt_blank_pass: |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2173 | /* passwords have to be handled differently |
| 2174 | * to allow the character used for deliminator |
| 2175 | * to be passed within them |
| 2176 | */ |
| 2177 | |
Sachin Prabhu | c369c9a | 2013-04-09 18:17:41 +0100 | [diff] [blame] | 2178 | /* |
| 2179 | * Check if this is a case where the password |
| 2180 | * starts with a delimiter |
| 2181 | */ |
| 2182 | tmp_end = strchr(data, '='); |
| 2183 | tmp_end++; |
| 2184 | if (!(tmp_end < end && tmp_end[1] == delim)) { |
| 2185 | /* No it is not. Set the password to NULL */ |
Waiman Long | 453431a | 2020-08-06 23:18:13 -0700 | [diff] [blame] | 2186 | kfree_sensitive(vol->password); |
Sachin Prabhu | c369c9a | 2013-04-09 18:17:41 +0100 | [diff] [blame] | 2187 | vol->password = NULL; |
| 2188 | break; |
| 2189 | } |
Gustavo A. R. Silva | df561f66 | 2020-08-23 17:36:59 -0500 | [diff] [blame] | 2190 | fallthrough; /* to Opt_pass below */ |
Sachin Prabhu | c369c9a | 2013-04-09 18:17:41 +0100 | [diff] [blame] | 2191 | case Opt_pass: |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2192 | /* Obtain the value string */ |
| 2193 | value = strchr(data, '='); |
Sachin Prabhu | 1023807 | 2012-03-28 18:07:08 +0100 | [diff] [blame] | 2194 | value++; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2195 | |
| 2196 | /* Set tmp_end to end of the string */ |
| 2197 | tmp_end = (char *) value + strlen(value); |
| 2198 | |
| 2199 | /* Check if following character is the deliminator |
| 2200 | * If yes, we have encountered a double deliminator |
| 2201 | * reset the NULL character to the deliminator |
| 2202 | */ |
Suresh Jayaraman | e73f843 | 2012-06-12 07:15:50 +0530 | [diff] [blame] | 2203 | if (tmp_end < end && tmp_end[1] == delim) { |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2204 | tmp_end[0] = delim; |
| 2205 | |
Suresh Jayaraman | e73f843 | 2012-06-12 07:15:50 +0530 | [diff] [blame] | 2206 | /* Keep iterating until we get to a single |
| 2207 | * deliminator OR the end |
| 2208 | */ |
| 2209 | while ((tmp_end = strchr(tmp_end, delim)) |
| 2210 | != NULL && (tmp_end[1] == delim)) { |
| 2211 | tmp_end = (char *) &tmp_end[2]; |
| 2212 | } |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2213 | |
Suresh Jayaraman | e73f843 | 2012-06-12 07:15:50 +0530 | [diff] [blame] | 2214 | /* Reset var options to point to next element */ |
| 2215 | if (tmp_end) { |
| 2216 | tmp_end[0] = '\0'; |
| 2217 | options = (char *) &tmp_end[1]; |
| 2218 | } else |
| 2219 | /* Reached the end of the mount option |
| 2220 | * string */ |
| 2221 | options = end; |
| 2222 | } |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2223 | |
Waiman Long | 453431a | 2020-08-06 23:18:13 -0700 | [diff] [blame] | 2224 | kfree_sensitive(vol->password); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2225 | /* Now build new password string */ |
| 2226 | temp_len = strlen(value); |
| 2227 | vol->password = kzalloc(temp_len+1, GFP_KERNEL); |
| 2228 | if (vol->password == NULL) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2229 | pr_warn("no memory for password\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2230 | goto cifs_parse_mount_err; |
| 2231 | } |
| 2232 | |
| 2233 | for (i = 0, j = 0; i < temp_len; i++, j++) { |
| 2234 | vol->password[j] = value[i]; |
| 2235 | if ((value[i] == delim) && |
| 2236 | value[i+1] == delim) |
| 2237 | /* skip the second deliminator */ |
| 2238 | i++; |
| 2239 | } |
| 2240 | vol->password[j] = '\0'; |
| 2241 | break; |
Sachin Prabhu | 4fe9e96 | 2012-04-10 18:12:27 +0100 | [diff] [blame] | 2242 | case Opt_blank_ip: |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 2243 | /* FIXME: should this be an error instead? */ |
| 2244 | got_ip = false; |
Sachin Prabhu | 4fe9e96 | 2012-04-10 18:12:27 +0100 | [diff] [blame] | 2245 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2246 | case Opt_ip: |
| 2247 | string = match_strdup(args); |
| 2248 | if (string == NULL) |
| 2249 | goto out_nomem; |
| 2250 | |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 2251 | if (!cifs_convert_address(dstaddr, string, |
| 2252 | strlen(string))) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2253 | pr_err("bad ip= option (%s)\n", string); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2254 | goto cifs_parse_mount_err; |
| 2255 | } |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 2256 | got_ip = true; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2257 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2258 | case Opt_domain: |
| 2259 | string = match_strdup(args); |
| 2260 | if (string == NULL) |
| 2261 | goto out_nomem; |
| 2262 | |
Chen Gang | 057d633 | 2013-07-19 09:01:36 +0800 | [diff] [blame] | 2263 | if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN) |
| 2264 | == CIFS_MAX_DOMAINNAME_LEN) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2265 | pr_warn("domain name too long\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2266 | goto cifs_parse_mount_err; |
| 2267 | } |
| 2268 | |
Taesoo Kim | 2bd50fb | 2015-03-21 19:08:30 -0400 | [diff] [blame] | 2269 | kfree(vol->domainname); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2270 | vol->domainname = kstrdup(string, GFP_KERNEL); |
| 2271 | if (!vol->domainname) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2272 | pr_warn("no memory for domainname\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2273 | goto cifs_parse_mount_err; |
| 2274 | } |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2275 | cifs_dbg(FYI, "Domain name set\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2276 | break; |
| 2277 | case Opt_srcaddr: |
| 2278 | string = match_strdup(args); |
| 2279 | if (string == NULL) |
| 2280 | goto out_nomem; |
| 2281 | |
Sachin Prabhu | 4fe9e96 | 2012-04-10 18:12:27 +0100 | [diff] [blame] | 2282 | if (!cifs_convert_address( |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2283 | (struct sockaddr *)&vol->srcaddr, |
| 2284 | string, strlen(string))) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2285 | pr_warn("Could not parse srcaddr: %s\n", |
Andy Shevchenko | 0b456f0 | 2014-08-27 16:49:44 +0300 | [diff] [blame] | 2286 | string); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2287 | goto cifs_parse_mount_err; |
| 2288 | } |
| 2289 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2290 | case Opt_iocharset: |
| 2291 | string = match_strdup(args); |
| 2292 | if (string == NULL) |
| 2293 | goto out_nomem; |
| 2294 | |
Sachin Prabhu | 4fe9e96 | 2012-04-10 18:12:27 +0100 | [diff] [blame] | 2295 | if (strnlen(string, 1024) >= 65) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2296 | pr_warn("iocharset name too long\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2297 | goto cifs_parse_mount_err; |
| 2298 | } |
| 2299 | |
Rasmus Villemoes | 87e747c | 2014-10-13 15:54:35 -0700 | [diff] [blame] | 2300 | if (strncasecmp(string, "default", 7) != 0) { |
Taesoo Kim | 2bd50fb | 2015-03-21 19:08:30 -0400 | [diff] [blame] | 2301 | kfree(vol->iocharset); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2302 | vol->iocharset = kstrdup(string, |
| 2303 | GFP_KERNEL); |
| 2304 | if (!vol->iocharset) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2305 | pr_warn("no memory for charset\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2306 | goto cifs_parse_mount_err; |
| 2307 | } |
| 2308 | } |
| 2309 | /* if iocharset not set then load_nls_default |
| 2310 | * is used by caller |
| 2311 | */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2312 | cifs_dbg(FYI, "iocharset set to %s\n", string); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2313 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2314 | case Opt_netbiosname: |
| 2315 | string = match_strdup(args); |
| 2316 | if (string == NULL) |
| 2317 | goto out_nomem; |
| 2318 | |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2319 | memset(vol->source_rfc1001_name, 0x20, |
| 2320 | RFC1001_NAME_LEN); |
| 2321 | /* |
| 2322 | * FIXME: are there cases in which a comma can |
| 2323 | * be valid in workstation netbios name (and |
| 2324 | * need special handling)? |
| 2325 | */ |
| 2326 | for (i = 0; i < RFC1001_NAME_LEN; i++) { |
| 2327 | /* don't ucase netbiosname for user */ |
| 2328 | if (string[i] == 0) |
| 2329 | break; |
| 2330 | vol->source_rfc1001_name[i] = string[i]; |
| 2331 | } |
| 2332 | /* The string has 16th byte zero still from |
| 2333 | * set at top of the function |
| 2334 | */ |
| 2335 | if (i == RFC1001_NAME_LEN && string[i] != 0) |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2336 | pr_warn("netbiosname longer than 15 truncated\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2337 | break; |
| 2338 | case Opt_servern: |
| 2339 | /* servernetbiosname specified override *SMBSERVER */ |
| 2340 | string = match_strdup(args); |
| 2341 | if (string == NULL) |
| 2342 | goto out_nomem; |
| 2343 | |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2344 | /* last byte, type, is 0x20 for servr type */ |
| 2345 | memset(vol->target_rfc1001_name, 0x20, |
| 2346 | RFC1001_NAME_LEN_WITH_NULL); |
| 2347 | |
| 2348 | /* BB are there cases in which a comma can be |
| 2349 | valid in this workstation netbios name |
| 2350 | (and need special handling)? */ |
| 2351 | |
| 2352 | /* user or mount helper must uppercase the |
| 2353 | netbios name */ |
| 2354 | for (i = 0; i < 15; i++) { |
| 2355 | if (string[i] == 0) |
| 2356 | break; |
| 2357 | vol->target_rfc1001_name[i] = string[i]; |
| 2358 | } |
| 2359 | /* The string has 16th byte zero still from |
| 2360 | set at top of the function */ |
| 2361 | if (i == RFC1001_NAME_LEN && string[i] != 0) |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2362 | pr_warn("server netbiosname longer than 15 truncated\n"); |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2363 | break; |
| 2364 | case Opt_ver: |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 2365 | /* version of mount userspace tools, not dialect */ |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2366 | string = match_strdup(args); |
| 2367 | if (string == NULL) |
| 2368 | goto out_nomem; |
| 2369 | |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 2370 | /* If interface changes in mount.cifs bump to new ver */ |
Rasmus Villemoes | 87e747c | 2014-10-13 15:54:35 -0700 | [diff] [blame] | 2371 | if (strncasecmp(string, "1", 1) == 0) { |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 2372 | if (strlen(string) > 1) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2373 | pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n", |
| 2374 | string); |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 2375 | goto cifs_parse_mount_err; |
| 2376 | } |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2377 | /* This is the default */ |
| 2378 | break; |
| 2379 | } |
| 2380 | /* For all other value, error */ |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2381 | pr_warn("Invalid mount helper version specified\n"); |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 2382 | goto cifs_parse_mount_err; |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 2383 | case Opt_vers: |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 2384 | /* protocol version (dialect) */ |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 2385 | string = match_strdup(args); |
| 2386 | if (string == NULL) |
| 2387 | goto out_nomem; |
| 2388 | |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 2389 | if (cifs_parse_smb_version(string, vol, is_smb3) != 0) |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 2390 | goto cifs_parse_mount_err; |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 2391 | got_version = true; |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 2392 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2393 | case Opt_sec: |
| 2394 | string = match_strdup(args); |
| 2395 | if (string == NULL) |
| 2396 | goto out_nomem; |
| 2397 | |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2398 | if (cifs_parse_security_flavors(string, vol) != 0) |
| 2399 | goto cifs_parse_mount_err; |
| 2400 | break; |
Jeff Layton | 15b6a47 | 2012-05-16 07:50:15 -0400 | [diff] [blame] | 2401 | case Opt_cache: |
| 2402 | string = match_strdup(args); |
| 2403 | if (string == NULL) |
| 2404 | goto out_nomem; |
| 2405 | |
| 2406 | if (cifs_parse_cache_flavor(string, vol) != 0) |
| 2407 | goto cifs_parse_mount_err; |
| 2408 | break; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2409 | default: |
Jeff Layton | d816255 | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2410 | /* |
| 2411 | * An option we don't recognize. Save it off for later |
| 2412 | * if we haven't already found one |
| 2413 | */ |
| 2414 | if (!invalid) |
| 2415 | invalid = data; |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2416 | break; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2417 | } |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2418 | /* Free up any allocated string */ |
| 2419 | kfree(string); |
| 2420 | string = NULL; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2421 | } |
Jeff Layton | 0eb8a13 | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 2422 | |
Jeff Layton | d816255 | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2423 | if (!sloppy && invalid) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2424 | pr_err("Unknown mount option \"%s\"\n", invalid); |
Jeff Layton | d816255 | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2425 | goto cifs_parse_mount_err; |
| 2426 | } |
| 2427 | |
Long Li | 8339dd3 | 2017-11-07 01:54:55 -0700 | [diff] [blame] | 2428 | if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) { |
| 2429 | cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n"); |
| 2430 | goto cifs_parse_mount_err; |
| 2431 | } |
| 2432 | |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 2433 | #ifndef CONFIG_KEYS |
| 2434 | /* Muliuser mounts require CONFIG_KEYS support */ |
| 2435 | if (vol->multiuser) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2436 | cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n"); |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 2437 | goto cifs_parse_mount_err; |
Jeff Layton | 0eb8a13 | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 2438 | } |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 2439 | #endif |
Jeff Layton | e5e69ab | 2012-11-25 08:00:42 -0500 | [diff] [blame] | 2440 | if (!vol->UNC) { |
Jeff Layton | 37d4f99 | 2013-05-24 07:40:05 -0400 | [diff] [blame] | 2441 | cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n"); |
Jeff Layton | e5e69ab | 2012-11-25 08:00:42 -0500 | [diff] [blame] | 2442 | goto cifs_parse_mount_err; |
| 2443 | } |
Jeff Layton | 0eb8a13 | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 2444 | |
Jeff Layton | 62a1a43 | 2012-12-10 06:10:45 -0500 | [diff] [blame] | 2445 | /* make sure UNC has a share name */ |
| 2446 | if (!strchr(vol->UNC + 3, '\\')) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2447 | cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n"); |
Jeff Layton | 62a1a43 | 2012-12-10 06:10:45 -0500 | [diff] [blame] | 2448 | goto cifs_parse_mount_err; |
| 2449 | } |
| 2450 | |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 2451 | if (!got_ip) { |
Daniel N Pettersson | 29bb315 | 2017-04-27 11:32:36 +0200 | [diff] [blame] | 2452 | int len; |
| 2453 | const char *slash; |
| 2454 | |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 2455 | /* No ip= option specified? Try to get it from UNC */ |
Daniel N Pettersson | 29bb315 | 2017-04-27 11:32:36 +0200 | [diff] [blame] | 2456 | /* Use the address part of the UNC. */ |
| 2457 | slash = strchr(&vol->UNC[2], '\\'); |
| 2458 | len = slash - &vol->UNC[2]; |
| 2459 | if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2460 | pr_err("Unable to determine destination address\n"); |
Jeff Layton | b979aaa | 2012-11-26 11:09:55 -0500 | [diff] [blame] | 2461 | goto cifs_parse_mount_err; |
| 2462 | } |
| 2463 | } |
| 2464 | |
| 2465 | /* set the port that we got earlier */ |
| 2466 | cifs_set_port(dstaddr, port); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2467 | |
Jeff Layton | 9b9d6b24 | 2009-07-31 06:56:09 -0400 | [diff] [blame] | 2468 | if (uid_specified) |
| 2469 | vol->override_uid = override_uid; |
| 2470 | else if (override_uid == 1) |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2471 | pr_notice("ignoring forceuid mount option specified with no uid= option\n"); |
Jeff Layton | 9b9d6b24 | 2009-07-31 06:56:09 -0400 | [diff] [blame] | 2472 | |
| 2473 | if (gid_specified) |
| 2474 | vol->override_gid = override_gid; |
| 2475 | else if (override_gid == 1) |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2476 | pr_notice("ignoring forcegid mount option specified with no gid= option\n"); |
Jeff Layton | 9b9d6b24 | 2009-07-31 06:56:09 -0400 | [diff] [blame] | 2477 | |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 2478 | if (got_version == false) |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 2479 | pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n"); |
Steve French | 7e682f7 | 2017-08-31 21:34:24 -0500 | [diff] [blame] | 2480 | |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 2481 | kfree(mountdata_copy); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2482 | return 0; |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 2483 | |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2484 | out_nomem: |
Andy Shevchenko | 0b456f0 | 2014-08-27 16:49:44 +0300 | [diff] [blame] | 2485 | pr_warn("Could not allocate temporary buffer\n"); |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 2486 | cifs_parse_mount_err: |
Sachin Prabhu | 8830d7e | 2012-03-23 14:40:56 -0400 | [diff] [blame] | 2487 | kfree(string); |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 2488 | kfree(mountdata_copy); |
| 2489 | return 1; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2490 | } |
| 2491 | |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 2492 | /** Returns true if srcaddr isn't specified and rhs isn't |
| 2493 | * specified, or if srcaddr is specified and |
| 2494 | * matches the IP address of the rhs argument. |
| 2495 | */ |
Paulo Alcantara | e4af35f | 2020-05-19 15:38:28 -0300 | [diff] [blame] | 2496 | bool |
| 2497 | cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs) |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 2498 | { |
| 2499 | switch (srcaddr->sa_family) { |
| 2500 | case AF_UNSPEC: |
| 2501 | return (rhs->sa_family == AF_UNSPEC); |
| 2502 | case AF_INET: { |
| 2503 | struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr; |
| 2504 | struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs; |
| 2505 | return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr); |
| 2506 | } |
| 2507 | case AF_INET6: { |
| 2508 | struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr; |
Nickolai Zeldovich | e3e2775 | 2013-01-16 21:36:17 -0500 | [diff] [blame] | 2509 | struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs; |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 2510 | return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr); |
| 2511 | } |
| 2512 | default: |
| 2513 | WARN_ON(1); |
| 2514 | return false; /* don't expect to be here */ |
| 2515 | } |
| 2516 | } |
| 2517 | |
Pavel Shilovsky | 4b88613 | 2010-12-13 22:18:07 +0300 | [diff] [blame] | 2518 | /* |
| 2519 | * If no port is specified in addr structure, we try to match with 445 port |
| 2520 | * and if it fails - with 139 ports. It should be called only if address |
| 2521 | * families of server and addr are equal. |
| 2522 | */ |
| 2523 | static bool |
| 2524 | match_port(struct TCP_Server_Info *server, struct sockaddr *addr) |
| 2525 | { |
Steve French | 6da9791 | 2011-03-13 18:55:55 +0000 | [diff] [blame] | 2526 | __be16 port, *sport; |
Pavel Shilovsky | 4b88613 | 2010-12-13 22:18:07 +0300 | [diff] [blame] | 2527 | |
Long Li | 3b24911 | 2019-05-15 14:09:04 -0700 | [diff] [blame] | 2528 | /* SMBDirect manages its own ports, don't match it here */ |
| 2529 | if (server->rdma) |
| 2530 | return true; |
| 2531 | |
Pavel Shilovsky | 4b88613 | 2010-12-13 22:18:07 +0300 | [diff] [blame] | 2532 | switch (addr->sa_family) { |
| 2533 | case AF_INET: |
| 2534 | sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; |
| 2535 | port = ((struct sockaddr_in *) addr)->sin_port; |
| 2536 | break; |
| 2537 | case AF_INET6: |
| 2538 | sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port; |
| 2539 | port = ((struct sockaddr_in6 *) addr)->sin6_port; |
| 2540 | break; |
| 2541 | default: |
| 2542 | WARN_ON(1); |
| 2543 | return false; |
| 2544 | } |
| 2545 | |
| 2546 | if (!port) { |
| 2547 | port = htons(CIFS_PORT); |
| 2548 | if (port == *sport) |
| 2549 | return true; |
| 2550 | |
| 2551 | port = htons(RFC1001_PORT); |
| 2552 | } |
| 2553 | |
| 2554 | return port == *sport; |
| 2555 | } |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 2556 | |
| 2557 | static bool |
| 2558 | match_address(struct TCP_Server_Info *server, struct sockaddr *addr, |
| 2559 | struct sockaddr *srcaddr) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2560 | { |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2561 | switch (addr->sa_family) { |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 2562 | case AF_INET: { |
| 2563 | struct sockaddr_in *addr4 = (struct sockaddr_in *)addr; |
| 2564 | struct sockaddr_in *srv_addr4 = |
| 2565 | (struct sockaddr_in *)&server->dstaddr; |
| 2566 | |
| 2567 | if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr) |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2568 | return false; |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2569 | break; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 2570 | } |
| 2571 | case AF_INET6: { |
| 2572 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; |
| 2573 | struct sockaddr_in6 *srv_addr6 = |
| 2574 | (struct sockaddr_in6 *)&server->dstaddr; |
| 2575 | |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2576 | if (!ipv6_addr_equal(&addr6->sin6_addr, |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 2577 | &srv_addr6->sin6_addr)) |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2578 | return false; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 2579 | if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id) |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2580 | return false; |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2581 | break; |
| 2582 | } |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 2583 | default: |
| 2584 | WARN_ON(1); |
| 2585 | return false; /* don't expect to be here */ |
| 2586 | } |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2587 | |
Paulo Alcantara | e4af35f | 2020-05-19 15:38:28 -0300 | [diff] [blame] | 2588 | if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr)) |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 2589 | return false; |
| 2590 | |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2591 | return true; |
| 2592 | } |
| 2593 | |
Jeff Layton | daf5b0b | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2594 | static bool |
| 2595 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) |
| 2596 | { |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 2597 | /* |
| 2598 | * The select_sectype function should either return the vol->sectype |
| 2599 | * that was specified, or "Unspecified" if that sectype was not |
| 2600 | * compatible with the given NEGOTIATE request. |
| 2601 | */ |
Sachin Prabhu | ef65aae | 2017-01-18 15:35:57 +0530 | [diff] [blame] | 2602 | if (server->ops->select_sectype(server, vol->sectype) |
| 2603 | == Unspecified) |
Jeff Layton | daf5b0b | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2604 | return false; |
Jeff Layton | daf5b0b | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2605 | |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 2606 | /* |
| 2607 | * Now check if signing mode is acceptable. No need to check |
| 2608 | * global_secflags at this point since if MUST_SIGN is set then |
| 2609 | * the server->sign had better be too. |
| 2610 | */ |
Jeff Layton | 38d77c5 | 2013-05-26 07:01:00 -0400 | [diff] [blame] | 2611 | if (vol->sign && !server->sign) |
| 2612 | return false; |
Jeff Layton | daf5b0b | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2613 | |
| 2614 | return true; |
| 2615 | } |
| 2616 | |
Jeff Layton | 9fa114f | 2012-11-26 11:09:57 -0500 | [diff] [blame] | 2617 | static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2618 | { |
Jeff Layton | 9fa114f | 2012-11-26 11:09:57 -0500 | [diff] [blame] | 2619 | struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr; |
| 2620 | |
Jeff Layton | a0b3df5 | 2013-05-24 07:40:59 -0400 | [diff] [blame] | 2621 | if (vol->nosharesock) |
| 2622 | return 0; |
| 2623 | |
Steve French | 43cdae8 | 2019-06-13 14:26:49 -0500 | [diff] [blame] | 2624 | /* If multidialect negotiation see if existing sessions match one */ |
| 2625 | if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { |
| 2626 | if (server->vals->protocol_id < SMB30_PROT_ID) |
| 2627 | return 0; |
| 2628 | } else if (strcmp(vol->vals->version_string, |
| 2629 | SMBDEFAULT_VERSION_STRING) == 0) { |
| 2630 | if (server->vals->protocol_id < SMB21_PROT_ID) |
| 2631 | return 0; |
| 2632 | } else if ((server->vals != vol->vals) || (server->ops != vol->ops)) |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 2633 | return 0; |
| 2634 | |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2635 | if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) |
| 2636 | return 0; |
| 2637 | |
| 2638 | if (!match_address(server, addr, |
| 2639 | (struct sockaddr *)&vol->srcaddr)) |
| 2640 | return 0; |
| 2641 | |
| 2642 | if (!match_port(server, addr)) |
| 2643 | return 0; |
| 2644 | |
| 2645 | if (!match_security(server, vol)) |
| 2646 | return 0; |
| 2647 | |
Rabin Vincent | b782fcc | 2016-07-19 09:25:45 +0200 | [diff] [blame] | 2648 | if (server->echo_interval != vol->echo_interval * HZ) |
Steve French | adfeb3e | 2015-12-18 12:31:36 -0600 | [diff] [blame] | 2649 | return 0; |
| 2650 | |
Long Li | 8339dd3 | 2017-11-07 01:54:55 -0700 | [diff] [blame] | 2651 | if (server->rdma != vol->rdma) |
| 2652 | return 0; |
| 2653 | |
Steve French | 4f5c10f | 2019-09-03 21:18:49 -0500 | [diff] [blame] | 2654 | if (server->ignore_signature != vol->ignore_signature) |
| 2655 | return 0; |
| 2656 | |
Steve French | 563317e | 2019-09-08 23:22:02 -0500 | [diff] [blame] | 2657 | if (server->min_offload != vol->min_offload) |
| 2658 | return 0; |
| 2659 | |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2660 | return 1; |
| 2661 | } |
| 2662 | |
Paulo Alcantara | 54be1f6 | 2018-11-14 16:01:21 -0200 | [diff] [blame] | 2663 | struct TCP_Server_Info * |
Jeff Layton | 9fa114f | 2012-11-26 11:09:57 -0500 | [diff] [blame] | 2664 | cifs_find_tcp_session(struct smb_vol *vol) |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2665 | { |
Jeff Layton | e7ddee9 | 2008-11-14 13:44:38 -0500 | [diff] [blame] | 2666 | struct TCP_Server_Info *server; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2667 | |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 2668 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | 4515148 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2669 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { |
Paulo Alcantara (SUSE) | 3345bb4 | 2019-12-04 11:25:06 -0300 | [diff] [blame] | 2670 | /* |
| 2671 | * Skip ses channels since they're only handled in lower layers |
| 2672 | * (e.g. cifs_send_recv). |
| 2673 | */ |
| 2674 | if (server->is_channel || !match_server(server, vol)) |
Jeff Layton | daf5b0b | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 2675 | continue; |
| 2676 | |
Jeff Layton | e7ddee9 | 2008-11-14 13:44:38 -0500 | [diff] [blame] | 2677 | ++server->srv_count; |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 2678 | spin_unlock(&cifs_tcp_ses_lock); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2679 | cifs_dbg(FYI, "Existing tcp session with server found\n"); |
Jeff Layton | e7ddee9 | 2008-11-14 13:44:38 -0500 | [diff] [blame] | 2680 | return server; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2681 | } |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 2682 | spin_unlock(&cifs_tcp_ses_lock); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2683 | return NULL; |
| 2684 | } |
| 2685 | |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 2686 | void |
| 2687 | cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2688 | { |
Steve French | a5c3e1c | 2014-09-16 04:16:19 -0500 | [diff] [blame] | 2689 | struct task_struct *task; |
| 2690 | |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 2691 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | e7ddee9 | 2008-11-14 13:44:38 -0500 | [diff] [blame] | 2692 | if (--server->srv_count > 0) { |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 2693 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | e7ddee9 | 2008-11-14 13:44:38 -0500 | [diff] [blame] | 2694 | return; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2695 | } |
Steve French | dea570e0 | 2008-05-06 22:05:51 +0000 | [diff] [blame] | 2696 | |
Rob Landley | f1d0c99 | 2011-01-22 15:44:05 -0600 | [diff] [blame] | 2697 | put_net(cifs_net_ns(server)); |
| 2698 | |
Jeff Layton | e7ddee9 | 2008-11-14 13:44:38 -0500 | [diff] [blame] | 2699 | list_del_init(&server->tcp_ses_list); |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 2700 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | e7ddee9 | 2008-11-14 13:44:38 -0500 | [diff] [blame] | 2701 | |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 2702 | cancel_delayed_work_sync(&server->echo); |
| 2703 | |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 2704 | if (from_reconnect) |
| 2705 | /* |
| 2706 | * Avoid deadlock here: reconnect work calls |
| 2707 | * cifs_put_tcp_session() at its end. Need to be sure |
| 2708 | * that reconnect work does nothing with server pointer after |
| 2709 | * that step. |
| 2710 | */ |
| 2711 | cancel_delayed_work(&server->reconnect); |
| 2712 | else |
| 2713 | cancel_delayed_work_sync(&server->reconnect); |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 2714 | |
Jeff Layton | e7ddee9 | 2008-11-14 13:44:38 -0500 | [diff] [blame] | 2715 | spin_lock(&GlobalMid_Lock); |
| 2716 | server->tcpStatus = CifsExiting; |
| 2717 | spin_unlock(&GlobalMid_Lock); |
| 2718 | |
Pavel Shilovsky | 026e93d | 2016-11-03 16:47:37 -0700 | [diff] [blame] | 2719 | cifs_crypto_secmech_release(server); |
Suresh Jayaraman | 488f1d2d | 2010-07-05 18:12:15 +0530 | [diff] [blame] | 2720 | cifs_fscache_release_client_cookie(server); |
| 2721 | |
Shirish Pargaonkar | 21e7339 | 2010-10-21 06:42:55 -0500 | [diff] [blame] | 2722 | kfree(server->session_key.response); |
| 2723 | server->session_key.response = NULL; |
| 2724 | server->session_key.len = 0; |
Steve French | a5c3e1c | 2014-09-16 04:16:19 -0500 | [diff] [blame] | 2725 | |
| 2726 | task = xchg(&server->tsk, NULL); |
| 2727 | if (task) |
Eric W. Biederman | 72abe3b | 2019-05-15 12:33:50 -0500 | [diff] [blame] | 2728 | send_sig(SIGKILL, task, 1); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2729 | } |
| 2730 | |
Aurelien Aptel | d70e9fa | 2019-09-20 06:31:10 +0200 | [diff] [blame] | 2731 | struct TCP_Server_Info * |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2732 | cifs_get_tcp_session(struct smb_vol *volume_info) |
| 2733 | { |
| 2734 | struct TCP_Server_Info *tcp_ses = NULL; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2735 | int rc; |
| 2736 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2737 | cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2738 | |
| 2739 | /* see if we already have a matching tcp_ses */ |
Jeff Layton | 9fa114f | 2012-11-26 11:09:57 -0500 | [diff] [blame] | 2740 | tcp_ses = cifs_find_tcp_session(volume_info); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2741 | if (tcp_ses) |
| 2742 | return tcp_ses; |
| 2743 | |
| 2744 | tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); |
| 2745 | if (!tcp_ses) { |
| 2746 | rc = -ENOMEM; |
| 2747 | goto out_err; |
| 2748 | } |
| 2749 | |
Jeff Layton | 23db65f | 2012-05-15 12:20:51 -0400 | [diff] [blame] | 2750 | tcp_ses->ops = volume_info->ops; |
| 2751 | tcp_ses->vals = volume_info->vals; |
Rob Landley | f1d0c99 | 2011-01-22 15:44:05 -0600 | [diff] [blame] | 2752 | cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2753 | tcp_ses->hostname = extract_hostname(volume_info->UNC); |
| 2754 | if (IS_ERR(tcp_ses->hostname)) { |
| 2755 | rc = PTR_ERR(tcp_ses->hostname); |
Shirish Pargaonkar | f7c5445a | 2010-10-26 18:10:24 -0500 | [diff] [blame] | 2756 | goto out_err_crypto_release; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2757 | } |
| 2758 | |
Paulo Alcantara (SUSE) | 8eecd1c | 2019-07-16 19:04:50 -0300 | [diff] [blame] | 2759 | tcp_ses->noblockcnt = volume_info->rootfs; |
| 2760 | tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2761 | tcp_ses->noautotune = volume_info->noautotune; |
Steve French | 6a5fa236 | 2010-01-01 01:28:43 +0000 | [diff] [blame] | 2762 | tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; |
Long Li | 8339dd3 | 2017-11-07 01:54:55 -0700 | [diff] [blame] | 2763 | tcp_ses->rdma = volume_info->rdma; |
Pavel Shilovsky | fc40f9c | 2012-02-17 17:09:12 +0300 | [diff] [blame] | 2764 | tcp_ses->in_flight = 0; |
Steve French | 1b63f18 | 2019-09-09 22:57:11 -0500 | [diff] [blame] | 2765 | tcp_ses->max_in_flight = 0; |
Pavel Shilovsky | 2d86dbc | 2012-02-06 15:59:18 +0400 | [diff] [blame] | 2766 | tcp_ses->credits = 1; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2767 | init_waitqueue_head(&tcp_ses->response_q); |
| 2768 | init_waitqueue_head(&tcp_ses->request_q); |
| 2769 | INIT_LIST_HEAD(&tcp_ses->pending_mid_q); |
| 2770 | mutex_init(&tcp_ses->srv_mutex); |
| 2771 | memcpy(tcp_ses->workstation_RFC1001_name, |
| 2772 | volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); |
| 2773 | memcpy(tcp_ses->server_RFC1001_name, |
| 2774 | volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); |
Shirish Pargaonkar | 5d0d288 | 2010-10-13 18:15:00 -0500 | [diff] [blame] | 2775 | tcp_ses->session_estab = false; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2776 | tcp_ses->sequence_number = 0; |
Pavel Shilovsky | 5b96485 | 2019-01-18 11:30:26 -0800 | [diff] [blame] | 2777 | tcp_ses->reconnect_instance = 1; |
Steve French | fda3594 | 2011-01-20 18:06:34 +0000 | [diff] [blame] | 2778 | tcp_ses->lstrp = jiffies; |
Steve French | 9fe5ff1 | 2019-06-24 20:39:04 -0500 | [diff] [blame] | 2779 | tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression); |
Jeff Layton | 58fa015 | 2012-05-01 17:41:16 -0400 | [diff] [blame] | 2780 | spin_lock_init(&tcp_ses->req_lock); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2781 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); |
| 2782 | INIT_LIST_HEAD(&tcp_ses->smb_ses_list); |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 2783 | INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 2784 | INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); |
| 2785 | mutex_init(&tcp_ses->reconnect_mutex); |
Jeff Layton | 9fa114f | 2012-11-26 11:09:57 -0500 | [diff] [blame] | 2786 | memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr, |
| 2787 | sizeof(tcp_ses->srcaddr)); |
| 2788 | memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr, |
| 2789 | sizeof(tcp_ses->dstaddr)); |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 2790 | if (volume_info->use_client_guid) |
| 2791 | memcpy(tcp_ses->client_guid, volume_info->client_guid, |
| 2792 | SMB2_CLIENT_GUID_SIZE); |
| 2793 | else |
| 2794 | generate_random_uuid(tcp_ses->client_guid); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2795 | /* |
| 2796 | * at this point we are the only ones with the pointer |
| 2797 | * to the struct since the kernel thread not created yet |
| 2798 | * no need to spinlock this init of tcpStatus or srv_count |
| 2799 | */ |
| 2800 | tcp_ses->tcpStatus = CifsNew; |
| 2801 | ++tcp_ses->srv_count; |
| 2802 | |
Steve French | adfeb3e | 2015-12-18 12:31:36 -0600 | [diff] [blame] | 2803 | if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN && |
| 2804 | volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX) |
| 2805 | tcp_ses->echo_interval = volume_info->echo_interval * HZ; |
| 2806 | else |
| 2807 | tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ; |
Long Li | 2f89464 | 2017-11-22 17:38:34 -0700 | [diff] [blame] | 2808 | if (tcp_ses->rdma) { |
| 2809 | #ifndef CONFIG_CIFS_SMB_DIRECT |
| 2810 | cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n"); |
| 2811 | rc = -ENOENT; |
| 2812 | goto out_err_crypto_release; |
| 2813 | #endif |
| 2814 | tcp_ses->smbd_conn = smbd_get_connection( |
| 2815 | tcp_ses, (struct sockaddr *)&volume_info->dstaddr); |
| 2816 | if (tcp_ses->smbd_conn) { |
| 2817 | cifs_dbg(VFS, "RDMA transport established\n"); |
| 2818 | rc = 0; |
| 2819 | goto smbd_connected; |
| 2820 | } else { |
| 2821 | rc = -ENOENT; |
| 2822 | goto out_err_crypto_release; |
| 2823 | } |
| 2824 | } |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 2825 | rc = ip_connect(tcp_ses); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2826 | if (rc < 0) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2827 | cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n"); |
Shirish Pargaonkar | f7c5445a | 2010-10-26 18:10:24 -0500 | [diff] [blame] | 2828 | goto out_err_crypto_release; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2829 | } |
Long Li | 2f89464 | 2017-11-22 17:38:34 -0700 | [diff] [blame] | 2830 | smbd_connected: |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2831 | /* |
| 2832 | * since we're in a cifs function already, we know that |
| 2833 | * this will succeed. No need for try_module_get(). |
| 2834 | */ |
| 2835 | __module_get(THIS_MODULE); |
Al Viro | 7c97c20 | 2011-06-21 08:51:28 -0400 | [diff] [blame] | 2836 | tcp_ses->tsk = kthread_run(cifs_demultiplex_thread, |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2837 | tcp_ses, "cifsd"); |
| 2838 | if (IS_ERR(tcp_ses->tsk)) { |
| 2839 | rc = PTR_ERR(tcp_ses->tsk); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 2840 | cifs_dbg(VFS, "error %d create cifsd thread\n", rc); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2841 | module_put(THIS_MODULE); |
Shirish Pargaonkar | f7c5445a | 2010-10-26 18:10:24 -0500 | [diff] [blame] | 2842 | goto out_err_crypto_release; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2843 | } |
Steve French | 563317e | 2019-09-08 23:22:02 -0500 | [diff] [blame] | 2844 | tcp_ses->min_offload = volume_info->min_offload; |
Steve French | fd88ce9 | 2011-04-12 01:01:14 +0000 | [diff] [blame] | 2845 | tcp_ses->tcpStatus = CifsNeedNegotiate; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2846 | |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 2847 | tcp_ses->nr_targets = 1; |
Steve French | 4f5c10f | 2019-09-03 21:18:49 -0500 | [diff] [blame] | 2848 | tcp_ses->ignore_signature = volume_info->ignore_signature; |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2849 | /* thread spawned, put it on the list */ |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 2850 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2851 | list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 2852 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2853 | |
Suresh Jayaraman | 488f1d2d | 2010-07-05 18:12:15 +0530 | [diff] [blame] | 2854 | cifs_fscache_get_client_cookie(tcp_ses); |
| 2855 | |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 2856 | /* queue echo request delayed work */ |
Steve French | adfeb3e | 2015-12-18 12:31:36 -0600 | [diff] [blame] | 2857 | queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); |
Jeff Layton | c74093b | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 2858 | |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2859 | return tcp_ses; |
| 2860 | |
Shirish Pargaonkar | f7c5445a | 2010-10-26 18:10:24 -0500 | [diff] [blame] | 2861 | out_err_crypto_release: |
Pavel Shilovsky | 026e93d | 2016-11-03 16:47:37 -0700 | [diff] [blame] | 2862 | cifs_crypto_secmech_release(tcp_ses); |
Shirish Pargaonkar | d2b9152 | 2010-10-21 14:25:08 -0500 | [diff] [blame] | 2863 | |
Rob Landley | f1d0c99 | 2011-01-22 15:44:05 -0600 | [diff] [blame] | 2864 | put_net(cifs_net_ns(tcp_ses)); |
| 2865 | |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2866 | out_err: |
| 2867 | if (tcp_ses) { |
Steve French | 8347a5c | 2009-10-06 18:31:29 +0000 | [diff] [blame] | 2868 | if (!IS_ERR(tcp_ses->hostname)) |
| 2869 | kfree(tcp_ses->hostname); |
Jeff Layton | 63c038c | 2008-12-01 18:41:46 -0500 | [diff] [blame] | 2870 | if (tcp_ses->ssocket) |
| 2871 | sock_release(tcp_ses->ssocket); |
| 2872 | kfree(tcp_ses); |
| 2873 | } |
| 2874 | return ERR_PTR(rc); |
| 2875 | } |
| 2876 | |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 2877 | static int match_session(struct cifs_ses *ses, struct smb_vol *vol) |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2878 | { |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 2879 | if (vol->sectype != Unspecified && |
| 2880 | vol->sectype != ses->sectype) |
| 2881 | return 0; |
| 2882 | |
Aurelien Aptel | bcc8880 | 2019-09-20 04:32:20 +0200 | [diff] [blame] | 2883 | /* |
| 2884 | * If an existing session is limited to less channels than |
| 2885 | * requested, it should not be reused |
| 2886 | */ |
| 2887 | if (ses->chan_max < vol->max_channels) |
| 2888 | return 0; |
| 2889 | |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 2890 | switch (ses->sectype) { |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2891 | case Kerberos: |
Eric W. Biederman | 64ed39d | 2013-02-06 02:30:39 -0800 | [diff] [blame] | 2892 | if (!uid_eq(vol->cred_uid, ses->cred_uid)) |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2893 | return 0; |
| 2894 | break; |
| 2895 | default: |
Jeff Layton | 04febab | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 2896 | /* NULL username means anonymous session */ |
| 2897 | if (ses->user_name == NULL) { |
| 2898 | if (!vol->nullauth) |
| 2899 | return 0; |
| 2900 | break; |
| 2901 | } |
| 2902 | |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2903 | /* anything else takes username/password */ |
Jeff Layton | 04febab | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 2904 | if (strncmp(ses->user_name, |
| 2905 | vol->username ? vol->username : "", |
Scott Lovenberg | 8c3a2b4 | 2013-08-09 08:47:17 -0400 | [diff] [blame] | 2906 | CIFS_MAX_USERNAME_LEN)) |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2907 | return 0; |
Jeff Layton | 08b37d5 | 2014-05-23 06:53:10 -0400 | [diff] [blame] | 2908 | if ((vol->username && strlen(vol->username) != 0) && |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2909 | ses->password != NULL && |
| 2910 | strncmp(ses->password, |
| 2911 | vol->password ? vol->password : "", |
Scott Lovenberg | 8c3a2b4 | 2013-08-09 08:47:17 -0400 | [diff] [blame] | 2912 | CIFS_MAX_PASSWORD_LEN)) |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 2913 | return 0; |
| 2914 | } |
| 2915 | return 1; |
| 2916 | } |
| 2917 | |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 2918 | /** |
| 2919 | * cifs_setup_ipc - helper to setup the IPC tcon for the session |
| 2920 | * |
| 2921 | * A new IPC connection is made and stored in the session |
| 2922 | * tcon_ipc. The IPC tcon has the same lifetime as the session. |
| 2923 | */ |
| 2924 | static int |
| 2925 | cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) |
| 2926 | { |
| 2927 | int rc = 0, xid; |
| 2928 | struct cifs_tcon *tcon; |
| 2929 | struct nls_table *nls_codepage; |
| 2930 | char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0}; |
| 2931 | bool seal = false; |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 2932 | struct TCP_Server_Info *server = ses->server; |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 2933 | |
| 2934 | /* |
| 2935 | * If the mount request that resulted in the creation of the |
| 2936 | * session requires encryption, force IPC to be encrypted too. |
| 2937 | */ |
| 2938 | if (volume_info->seal) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 2939 | if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 2940 | seal = true; |
| 2941 | else { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 2942 | cifs_server_dbg(VFS, |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 2943 | "IPC: server doesn't support encryption\n"); |
| 2944 | return -EOPNOTSUPP; |
| 2945 | } |
| 2946 | } |
| 2947 | |
| 2948 | tcon = tconInfoAlloc(); |
| 2949 | if (tcon == NULL) |
| 2950 | return -ENOMEM; |
| 2951 | |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 2952 | scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname); |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 2953 | |
| 2954 | /* cannot fail */ |
| 2955 | nls_codepage = load_nls_default(); |
| 2956 | |
| 2957 | xid = get_xid(); |
| 2958 | tcon->ses = ses; |
| 2959 | tcon->ipc = true; |
| 2960 | tcon->seal = seal; |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 2961 | rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage); |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 2962 | free_xid(xid); |
| 2963 | |
| 2964 | if (rc) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 2965 | cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc); |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 2966 | tconInfoFree(tcon); |
| 2967 | goto out; |
| 2968 | } |
| 2969 | |
| 2970 | cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid); |
| 2971 | |
| 2972 | ses->tcon_ipc = tcon; |
| 2973 | out: |
| 2974 | unload_nls(nls_codepage); |
| 2975 | return rc; |
| 2976 | } |
| 2977 | |
| 2978 | /** |
| 2979 | * cifs_free_ipc - helper to release the session IPC tcon |
| 2980 | * |
| 2981 | * Needs to be called everytime a session is destroyed |
| 2982 | */ |
| 2983 | static int |
| 2984 | cifs_free_ipc(struct cifs_ses *ses) |
| 2985 | { |
| 2986 | int rc = 0, xid; |
| 2987 | struct cifs_tcon *tcon = ses->tcon_ipc; |
| 2988 | |
| 2989 | if (tcon == NULL) |
| 2990 | return 0; |
| 2991 | |
| 2992 | if (ses->server->ops->tree_disconnect) { |
| 2993 | xid = get_xid(); |
| 2994 | rc = ses->server->ops->tree_disconnect(xid, tcon); |
| 2995 | free_xid(xid); |
| 2996 | } |
| 2997 | |
| 2998 | if (rc) |
| 2999 | cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc); |
| 3000 | |
| 3001 | tconInfoFree(tcon); |
| 3002 | ses->tcon_ipc = NULL; |
| 3003 | return rc; |
| 3004 | } |
| 3005 | |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3006 | static struct cifs_ses * |
Jeff Layton | 4ff67b7 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 3007 | cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3008 | { |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3009 | struct cifs_ses *ses; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3010 | |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3011 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | 4ff67b7 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 3012 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { |
Shirish Pargaonkar | 7f48558 | 2013-10-12 10:06:03 -0500 | [diff] [blame] | 3013 | if (ses->status == CifsExiting) |
| 3014 | continue; |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 3015 | if (!match_session(ses, vol)) |
| 3016 | continue; |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3017 | ++ses->ses_count; |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3018 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3019 | return ses; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3020 | } |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3021 | spin_unlock(&cifs_tcp_ses_lock); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3022 | return NULL; |
| 3023 | } |
| 3024 | |
Paulo Alcantara (SUSE) | 5072010 | 2019-03-19 16:54:29 -0300 | [diff] [blame] | 3025 | void cifs_put_smb_ses(struct cifs_ses *ses) |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3026 | { |
Shirish Pargaonkar | 7f48558 | 2013-10-12 10:06:03 -0500 | [diff] [blame] | 3027 | unsigned int rc, xid; |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3028 | struct TCP_Server_Info *server = ses->server; |
| 3029 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3030 | cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); |
Shirish Pargaonkar | 7f48558 | 2013-10-12 10:06:03 -0500 | [diff] [blame] | 3031 | |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3032 | spin_lock(&cifs_tcp_ses_lock); |
Shirish Pargaonkar | 7f48558 | 2013-10-12 10:06:03 -0500 | [diff] [blame] | 3033 | if (ses->status == CifsExiting) { |
| 3034 | spin_unlock(&cifs_tcp_ses_lock); |
| 3035 | return; |
| 3036 | } |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3037 | if (--ses->ses_count > 0) { |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3038 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3039 | return; |
| 3040 | } |
Shirish Pargaonkar | 7f48558 | 2013-10-12 10:06:03 -0500 | [diff] [blame] | 3041 | if (ses->status == CifsGood) |
| 3042 | ses->status = CifsExiting; |
| 3043 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3044 | |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 3045 | cifs_free_ipc(ses); |
| 3046 | |
Shirish Pargaonkar | 7f48558 | 2013-10-12 10:06:03 -0500 | [diff] [blame] | 3047 | if (ses->status == CifsExiting && server->ops->logoff) { |
| 3048 | xid = get_xid(); |
| 3049 | rc = server->ops->logoff(xid, ses); |
| 3050 | if (rc) |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 3051 | cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n", |
Shirish Pargaonkar | 7f48558 | 2013-10-12 10:06:03 -0500 | [diff] [blame] | 3052 | __func__, rc); |
| 3053 | _free_xid(xid); |
| 3054 | } |
| 3055 | |
| 3056 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3057 | list_del_init(&ses->smb_ses_list); |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3058 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3059 | |
Aurelien Aptel | d70e9fa | 2019-09-20 06:31:10 +0200 | [diff] [blame] | 3060 | /* close any extra channels */ |
| 3061 | if (ses->chan_count > 1) { |
| 3062 | int i; |
| 3063 | |
| 3064 | for (i = 1; i < ses->chan_count; i++) |
| 3065 | cifs_put_tcp_session(ses->chans[i].server, 0); |
| 3066 | } |
| 3067 | |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3068 | sesInfoFree(ses); |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 3069 | cifs_put_tcp_session(server, 0); |
Jeff Layton | 14fbf50 | 2008-11-14 13:53:46 -0500 | [diff] [blame] | 3070 | } |
| 3071 | |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3072 | #ifdef CONFIG_KEYS |
| 3073 | |
Chen Gang | 057d633 | 2013-07-19 09:01:36 +0800 | [diff] [blame] | 3074 | /* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */ |
| 3075 | #define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1) |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3076 | |
| 3077 | /* Populate username and pw fields from keyring if possible */ |
| 3078 | static int |
| 3079 | cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) |
| 3080 | { |
| 3081 | int rc = 0; |
Ronnie Sahlberg | f2aee32 | 2019-08-22 08:09:50 +1000 | [diff] [blame] | 3082 | int is_domain = 0; |
David Howells | 146aa8b | 2015-10-21 14:04:48 +0100 | [diff] [blame] | 3083 | const char *delim, *payload; |
| 3084 | char *desc; |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3085 | ssize_t len; |
| 3086 | struct key *key; |
| 3087 | struct TCP_Server_Info *server = ses->server; |
| 3088 | struct sockaddr_in *sa; |
| 3089 | struct sockaddr_in6 *sa6; |
David Howells | 146aa8b | 2015-10-21 14:04:48 +0100 | [diff] [blame] | 3090 | const struct user_key_payload *upayload; |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3091 | |
| 3092 | desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL); |
| 3093 | if (!desc) |
| 3094 | return -ENOMEM; |
| 3095 | |
| 3096 | /* try to find an address key first */ |
| 3097 | switch (server->dstaddr.ss_family) { |
| 3098 | case AF_INET: |
| 3099 | sa = (struct sockaddr_in *)&server->dstaddr; |
| 3100 | sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr); |
| 3101 | break; |
| 3102 | case AF_INET6: |
| 3103 | sa6 = (struct sockaddr_in6 *)&server->dstaddr; |
| 3104 | sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr); |
| 3105 | break; |
| 3106 | default: |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3107 | cifs_dbg(FYI, "Bad ss_family (%hu)\n", |
| 3108 | server->dstaddr.ss_family); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3109 | rc = -EINVAL; |
| 3110 | goto out_err; |
| 3111 | } |
| 3112 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3113 | cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc); |
Linus Torvalds | 028db3e | 2019-07-10 18:43:43 -0700 | [diff] [blame] | 3114 | key = request_key(&key_type_logon, desc, ""); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3115 | if (IS_ERR(key)) { |
| 3116 | if (!ses->domainName) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3117 | cifs_dbg(FYI, "domainName is NULL\n"); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3118 | rc = PTR_ERR(key); |
| 3119 | goto out_err; |
| 3120 | } |
| 3121 | |
| 3122 | /* didn't work, try to find a domain key */ |
| 3123 | sprintf(desc, "cifs:d:%s", ses->domainName); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3124 | cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc); |
Linus Torvalds | 028db3e | 2019-07-10 18:43:43 -0700 | [diff] [blame] | 3125 | key = request_key(&key_type_logon, desc, ""); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3126 | if (IS_ERR(key)) { |
| 3127 | rc = PTR_ERR(key); |
| 3128 | goto out_err; |
| 3129 | } |
Ronnie Sahlberg | f2aee32 | 2019-08-22 08:09:50 +1000 | [diff] [blame] | 3130 | is_domain = 1; |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3131 | } |
| 3132 | |
| 3133 | down_read(&key->sem); |
David Howells | 0837e49 | 2017-03-01 15:11:23 +0000 | [diff] [blame] | 3134 | upayload = user_key_payload_locked(key); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3135 | if (IS_ERR_OR_NULL(upayload)) { |
Jeff Layton | 4edc53c | 2012-02-07 06:30:51 -0500 | [diff] [blame] | 3136 | rc = upayload ? PTR_ERR(upayload) : -EINVAL; |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3137 | goto out_key_put; |
| 3138 | } |
| 3139 | |
| 3140 | /* find first : in payload */ |
David Howells | 146aa8b | 2015-10-21 14:04:48 +0100 | [diff] [blame] | 3141 | payload = upayload->data; |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3142 | delim = strnchr(payload, upayload->datalen, ':'); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3143 | cifs_dbg(FYI, "payload=%s\n", payload); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3144 | if (!delim) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3145 | cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n", |
| 3146 | upayload->datalen); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3147 | rc = -EINVAL; |
| 3148 | goto out_key_put; |
| 3149 | } |
| 3150 | |
| 3151 | len = delim - payload; |
Scott Lovenberg | 8c3a2b4 | 2013-08-09 08:47:17 -0400 | [diff] [blame] | 3152 | if (len > CIFS_MAX_USERNAME_LEN || len <= 0) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3153 | cifs_dbg(FYI, "Bad value from username search (len=%zd)\n", |
| 3154 | len); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3155 | rc = -EINVAL; |
| 3156 | goto out_key_put; |
| 3157 | } |
| 3158 | |
| 3159 | vol->username = kstrndup(payload, len, GFP_KERNEL); |
| 3160 | if (!vol->username) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3161 | cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n", |
| 3162 | len); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3163 | rc = -ENOMEM; |
| 3164 | goto out_key_put; |
| 3165 | } |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3166 | cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3167 | |
| 3168 | len = key->datalen - (len + 1); |
Scott Lovenberg | 8c3a2b4 | 2013-08-09 08:47:17 -0400 | [diff] [blame] | 3169 | if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3170 | cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3171 | rc = -EINVAL; |
| 3172 | kfree(vol->username); |
| 3173 | vol->username = NULL; |
| 3174 | goto out_key_put; |
| 3175 | } |
| 3176 | |
| 3177 | ++delim; |
| 3178 | vol->password = kstrndup(delim, len, GFP_KERNEL); |
| 3179 | if (!vol->password) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3180 | cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n", |
| 3181 | len); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3182 | rc = -ENOMEM; |
| 3183 | kfree(vol->username); |
| 3184 | vol->username = NULL; |
| 3185 | goto out_key_put; |
| 3186 | } |
| 3187 | |
Ronnie Sahlberg | f2aee32 | 2019-08-22 08:09:50 +1000 | [diff] [blame] | 3188 | /* |
| 3189 | * If we have a domain key then we must set the domainName in the |
| 3190 | * for the request. |
| 3191 | */ |
| 3192 | if (is_domain && ses->domainName) { |
| 3193 | vol->domainname = kstrndup(ses->domainName, |
| 3194 | strlen(ses->domainName), |
| 3195 | GFP_KERNEL); |
| 3196 | if (!vol->domainname) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 3197 | cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n", |
| 3198 | len); |
Ronnie Sahlberg | f2aee32 | 2019-08-22 08:09:50 +1000 | [diff] [blame] | 3199 | rc = -ENOMEM; |
| 3200 | kfree(vol->username); |
| 3201 | vol->username = NULL; |
Waiman Long | 453431a | 2020-08-06 23:18:13 -0700 | [diff] [blame] | 3202 | kfree_sensitive(vol->password); |
Ronnie Sahlberg | f2aee32 | 2019-08-22 08:09:50 +1000 | [diff] [blame] | 3203 | vol->password = NULL; |
| 3204 | goto out_key_put; |
| 3205 | } |
| 3206 | } |
| 3207 | |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3208 | out_key_put: |
| 3209 | up_read(&key->sem); |
| 3210 | key_put(key); |
| 3211 | out_err: |
| 3212 | kfree(desc); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3213 | cifs_dbg(FYI, "%s: returning %d\n", __func__, rc); |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 3214 | return rc; |
| 3215 | } |
| 3216 | #else /* ! CONFIG_KEYS */ |
| 3217 | static inline int |
| 3218 | cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)), |
| 3219 | struct cifs_ses *ses __attribute__((unused))) |
| 3220 | { |
| 3221 | return -ENOSYS; |
| 3222 | } |
| 3223 | #endif /* CONFIG_KEYS */ |
| 3224 | |
Aurelien Aptel | 4a1360d | 2018-01-25 18:47:52 +0100 | [diff] [blame] | 3225 | /** |
| 3226 | * cifs_get_smb_ses - get a session matching @volume_info data from @server |
| 3227 | * |
| 3228 | * This function assumes it is being called from cifs_mount() where we |
| 3229 | * already got a server reference (server refcount +1). See |
| 3230 | * cifs_get_tcon() for refcount explanations. |
| 3231 | */ |
Paulo Alcantara (SUSE) | 5072010 | 2019-03-19 16:54:29 -0300 | [diff] [blame] | 3232 | struct cifs_ses * |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3233 | cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) |
| 3234 | { |
Pavel Shilovsky | 286170a | 2012-05-25 10:43:58 +0400 | [diff] [blame] | 3235 | int rc = -ENOMEM; |
| 3236 | unsigned int xid; |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3237 | struct cifs_ses *ses; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3238 | struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; |
| 3239 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3240 | |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3241 | xid = get_xid(); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3242 | |
Jeff Layton | 4ff67b7 | 2010-07-06 20:43:02 -0400 | [diff] [blame] | 3243 | ses = cifs_find_smb_ses(server, volume_info); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3244 | if (ses) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3245 | cifs_dbg(FYI, "Existing smb sess found (status=%d)\n", |
| 3246 | ses->status); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3247 | |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3248 | mutex_lock(&ses->session_mutex); |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 3249 | rc = cifs_negotiate_protocol(xid, ses); |
| 3250 | if (rc) { |
| 3251 | mutex_unlock(&ses->session_mutex); |
| 3252 | /* problem -- put our ses reference */ |
| 3253 | cifs_put_smb_ses(ses); |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3254 | free_xid(xid); |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 3255 | return ERR_PTR(rc); |
| 3256 | } |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3257 | if (ses->need_reconnect) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3258 | cifs_dbg(FYI, "Session needs reconnect\n"); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3259 | rc = cifs_setup_session(xid, ses, |
| 3260 | volume_info->local_nls); |
| 3261 | if (rc) { |
| 3262 | mutex_unlock(&ses->session_mutex); |
| 3263 | /* problem -- put our reference */ |
| 3264 | cifs_put_smb_ses(ses); |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3265 | free_xid(xid); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3266 | return ERR_PTR(rc); |
| 3267 | } |
| 3268 | } |
| 3269 | mutex_unlock(&ses->session_mutex); |
Jeff Layton | 460cf34 | 2010-09-14 11:38:24 -0400 | [diff] [blame] | 3270 | |
| 3271 | /* existing SMB ses has a server reference already */ |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 3272 | cifs_put_tcp_session(server, 0); |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3273 | free_xid(xid); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3274 | return ses; |
| 3275 | } |
| 3276 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3277 | cifs_dbg(FYI, "Existing smb sess not found\n"); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3278 | ses = sesInfoAlloc(); |
| 3279 | if (ses == NULL) |
| 3280 | goto get_ses_fail; |
| 3281 | |
| 3282 | /* new SMB session uses our server ref */ |
| 3283 | ses->server = server; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3284 | if (server->dstaddr.ss_family == AF_INET6) |
| 3285 | sprintf(ses->serverName, "%pI6", &addr6->sin6_addr); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3286 | else |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3287 | sprintf(ses->serverName, "%pI4", &addr->sin_addr); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3288 | |
Steve French | 8727c8a | 2011-02-25 01:11:56 -0600 | [diff] [blame] | 3289 | if (volume_info->username) { |
| 3290 | ses->user_name = kstrdup(volume_info->username, GFP_KERNEL); |
| 3291 | if (!ses->user_name) |
| 3292 | goto get_ses_fail; |
| 3293 | } |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3294 | |
| 3295 | /* volume_info->password freed at unmount */ |
| 3296 | if (volume_info->password) { |
| 3297 | ses->password = kstrdup(volume_info->password, GFP_KERNEL); |
| 3298 | if (!ses->password) |
| 3299 | goto get_ses_fail; |
| 3300 | } |
| 3301 | if (volume_info->domainname) { |
Shirish Pargaonkar | d3686d5 | 2010-10-28 09:53:07 -0500 | [diff] [blame] | 3302 | ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL); |
| 3303 | if (!ses->domainName) |
| 3304 | goto get_ses_fail; |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3305 | } |
Germano Percossi | 3956644 | 2016-12-15 12:31:18 +0530 | [diff] [blame] | 3306 | if (volume_info->domainauto) |
| 3307 | ses->domainAuto = volume_info->domainauto; |
Jeff Layton | 3e4b3e1 | 2010-07-19 18:00:17 -0400 | [diff] [blame] | 3308 | ses->cred_uid = volume_info->cred_uid; |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3309 | ses->linux_uid = volume_info->linux_uid; |
Steve French | d9b9420 | 2011-04-12 01:24:57 +0000 | [diff] [blame] | 3310 | |
Jeff Layton | 28e11bd | 2013-05-26 07:01:00 -0400 | [diff] [blame] | 3311 | ses->sectype = volume_info->sectype; |
| 3312 | ses->sign = volume_info->sign; |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3313 | mutex_lock(&ses->session_mutex); |
Aurelien Aptel | d70e9fa | 2019-09-20 06:31:10 +0200 | [diff] [blame] | 3314 | |
| 3315 | /* add server as first channel */ |
| 3316 | ses->chans[0].server = server; |
| 3317 | ses->chan_count = 1; |
| 3318 | ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1; |
| 3319 | |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 3320 | rc = cifs_negotiate_protocol(xid, ses); |
| 3321 | if (!rc) |
| 3322 | rc = cifs_setup_session(xid, ses, volume_info->local_nls); |
Aurelien Aptel | d70e9fa | 2019-09-20 06:31:10 +0200 | [diff] [blame] | 3323 | |
| 3324 | /* each channel uses a different signing key */ |
| 3325 | memcpy(ses->chans[0].signkey, ses->smb3signingkey, |
| 3326 | sizeof(ses->smb3signingkey)); |
| 3327 | |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3328 | mutex_unlock(&ses->session_mutex); |
Steve French | c8e56f1 | 2010-09-08 21:10:58 +0000 | [diff] [blame] | 3329 | if (rc) |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3330 | goto get_ses_fail; |
| 3331 | |
Aurelien Aptel | d70e9fa | 2019-09-20 06:31:10 +0200 | [diff] [blame] | 3332 | /* success, put it on the list and add it as first channel */ |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3333 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3334 | list_add(&ses->smb_ses_list, &server->smb_ses_list); |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3335 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3336 | |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3337 | free_xid(xid); |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 3338 | |
| 3339 | cifs_setup_ipc(ses, volume_info); |
| 3340 | |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3341 | return ses; |
| 3342 | |
| 3343 | get_ses_fail: |
| 3344 | sesInfoFree(ses); |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3345 | free_xid(xid); |
Jeff Layton | 36988c7 | 2010-04-24 07:57:43 -0400 | [diff] [blame] | 3346 | return ERR_PTR(rc); |
| 3347 | } |
| 3348 | |
Pavel Shilovsky | ae6f8dd | 2016-11-17 13:59:23 -0800 | [diff] [blame] | 3349 | static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info) |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 3350 | { |
| 3351 | if (tcon->tidStatus == CifsExiting) |
| 3352 | return 0; |
Pavel Shilovsky | ae6f8dd | 2016-11-17 13:59:23 -0800 | [diff] [blame] | 3353 | if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE)) |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 3354 | return 0; |
Pavel Shilovsky | ae6f8dd | 2016-11-17 13:59:23 -0800 | [diff] [blame] | 3355 | if (tcon->seal != volume_info->seal) |
| 3356 | return 0; |
Pavel Shilovsky | ae6f8dd | 2016-11-17 13:59:23 -0800 | [diff] [blame] | 3357 | if (tcon->snapshot_time != volume_info->snapshot_time) |
| 3358 | return 0; |
Steve French | ca567eb | 2019-03-29 16:31:07 -0500 | [diff] [blame] | 3359 | if (tcon->handle_timeout != volume_info->handle_timeout) |
| 3360 | return 0; |
Steve French | 3e7a02d | 2019-09-11 21:46:20 -0500 | [diff] [blame] | 3361 | if (tcon->no_lease != volume_info->no_lease) |
| 3362 | return 0; |
Steve French | 82e9367 | 2020-05-19 03:06:57 -0500 | [diff] [blame] | 3363 | if (tcon->nodelete != volume_info->nodelete) |
| 3364 | return 0; |
Pavel Shilovsky | 37bb04e | 2011-05-05 09:55:11 +0000 | [diff] [blame] | 3365 | return 1; |
| 3366 | } |
| 3367 | |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3368 | static struct cifs_tcon * |
Steve French | 8b217fe | 2016-11-11 22:36:20 -0600 | [diff] [blame] | 3369 | cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3370 | { |
| 3371 | struct list_head *tmp; |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3372 | struct cifs_tcon *tcon; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3373 | |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3374 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3375 | list_for_each(tmp, &ses->tcon_list) { |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3376 | tcon = list_entry(tmp, struct cifs_tcon, tcon_list); |
Paulo Alcantara | 65303de | 2020-04-20 19:42:57 -0300 | [diff] [blame] | 3377 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 3378 | if (tcon->dfs_path) |
| 3379 | continue; |
| 3380 | #endif |
Pavel Shilovsky | ae6f8dd | 2016-11-17 13:59:23 -0800 | [diff] [blame] | 3381 | if (!match_tcon(tcon, volume_info)) |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3382 | continue; |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3383 | ++tcon->tc_count; |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3384 | spin_unlock(&cifs_tcp_ses_lock); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3385 | return tcon; |
| 3386 | } |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3387 | spin_unlock(&cifs_tcp_ses_lock); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3388 | return NULL; |
| 3389 | } |
| 3390 | |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 3391 | void |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3392 | cifs_put_tcon(struct cifs_tcon *tcon) |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3393 | { |
Pavel Shilovsky | 2e6e02a | 2012-05-25 11:11:39 +0400 | [diff] [blame] | 3394 | unsigned int xid; |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 3395 | struct cifs_ses *ses; |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3396 | |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 3397 | /* |
| 3398 | * IPC tcon share the lifetime of their session and are |
| 3399 | * destroyed in the session put function |
| 3400 | */ |
| 3401 | if (tcon == NULL || tcon->ipc) |
| 3402 | return; |
| 3403 | |
| 3404 | ses = tcon->ses; |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3405 | cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3406 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3407 | if (--tcon->tc_count > 0) { |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3408 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3409 | return; |
| 3410 | } |
| 3411 | |
| 3412 | list_del_init(&tcon->tcon_list); |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3413 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3414 | |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3415 | xid = get_xid(); |
Pavel Shilovsky | 2e6e02a | 2012-05-25 11:11:39 +0400 | [diff] [blame] | 3416 | if (ses->server->ops->tree_disconnect) |
| 3417 | ses->server->ops->tree_disconnect(xid, tcon); |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3418 | _free_xid(xid); |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3419 | |
Suresh Jayaraman | d03382c | 2010-07-05 18:12:27 +0530 | [diff] [blame] | 3420 | cifs_fscache_release_super_cookie(tcon); |
Steve French | 9f84159 | 2010-07-23 20:37:53 +0000 | [diff] [blame] | 3421 | tconInfoFree(tcon); |
Jeff Layton | f1987b4 | 2008-11-15 11:12:47 -0500 | [diff] [blame] | 3422 | cifs_put_smb_ses(ses); |
| 3423 | } |
| 3424 | |
Aurelien Aptel | 4a1360d | 2018-01-25 18:47:52 +0100 | [diff] [blame] | 3425 | /** |
| 3426 | * cifs_get_tcon - get a tcon matching @volume_info data from @ses |
| 3427 | * |
| 3428 | * - tcon refcount is the number of mount points using the tcon. |
| 3429 | * - ses refcount is the number of tcon using the session. |
| 3430 | * |
| 3431 | * 1. This function assumes it is being called from cifs_mount() where |
| 3432 | * we already got a session reference (ses refcount +1). |
| 3433 | * |
| 3434 | * 2. Since we're in the context of adding a mount point, the end |
| 3435 | * result should be either: |
| 3436 | * |
| 3437 | * a) a new tcon already allocated with refcount=1 (1 mount point) and |
| 3438 | * its session refcount incremented (1 new tcon). This +1 was |
| 3439 | * already done in (1). |
| 3440 | * |
| 3441 | * b) an existing tcon with refcount+1 (add a mount point to it) and |
| 3442 | * identical ses refcount (no new tcon). Because of (1) we need to |
| 3443 | * decrement the ses refcount. |
| 3444 | */ |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3445 | static struct cifs_tcon * |
| 3446 | cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3447 | { |
| 3448 | int rc, xid; |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3449 | struct cifs_tcon *tcon; |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3450 | |
Steve French | 8b217fe | 2016-11-11 22:36:20 -0600 | [diff] [blame] | 3451 | tcon = cifs_find_tcon(ses, volume_info); |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3452 | if (tcon) { |
Aurelien Aptel | 4a1360d | 2018-01-25 18:47:52 +0100 | [diff] [blame] | 3453 | /* |
| 3454 | * tcon has refcount already incremented but we need to |
| 3455 | * decrement extra ses reference gotten by caller (case b) |
| 3456 | */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3457 | cifs_dbg(FYI, "Found match on UNC path\n"); |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3458 | cifs_put_smb_ses(ses); |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3459 | return tcon; |
| 3460 | } |
| 3461 | |
Pavel Shilovsky | 2e6e02a | 2012-05-25 11:11:39 +0400 | [diff] [blame] | 3462 | if (!ses->server->ops->tree_connect) { |
| 3463 | rc = -ENOSYS; |
| 3464 | goto out_fail; |
| 3465 | } |
| 3466 | |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3467 | tcon = tconInfoAlloc(); |
| 3468 | if (tcon == NULL) { |
| 3469 | rc = -ENOMEM; |
| 3470 | goto out_fail; |
| 3471 | } |
| 3472 | |
Steve French | 8b217fe | 2016-11-11 22:36:20 -0600 | [diff] [blame] | 3473 | if (volume_info->snapshot_time) { |
Steve French | 8b217fe | 2016-11-11 22:36:20 -0600 | [diff] [blame] | 3474 | if (ses->server->vals->protocol_id == 0) { |
| 3475 | cifs_dbg(VFS, |
| 3476 | "Use SMB2 or later for snapshot mount option\n"); |
| 3477 | rc = -EOPNOTSUPP; |
| 3478 | goto out_fail; |
| 3479 | } else |
| 3480 | tcon->snapshot_time = volume_info->snapshot_time; |
Steve French | 8b217fe | 2016-11-11 22:36:20 -0600 | [diff] [blame] | 3481 | } |
| 3482 | |
Steve French | ca567eb | 2019-03-29 16:31:07 -0500 | [diff] [blame] | 3483 | if (volume_info->handle_timeout) { |
| 3484 | if (ses->server->vals->protocol_id == 0) { |
| 3485 | cifs_dbg(VFS, |
| 3486 | "Use SMB2.1 or later for handle timeout option\n"); |
| 3487 | rc = -EOPNOTSUPP; |
| 3488 | goto out_fail; |
| 3489 | } else |
| 3490 | tcon->handle_timeout = volume_info->handle_timeout; |
| 3491 | } |
| 3492 | |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3493 | tcon->ses = ses; |
| 3494 | if (volume_info->password) { |
| 3495 | tcon->password = kstrdup(volume_info->password, GFP_KERNEL); |
| 3496 | if (!tcon->password) { |
| 3497 | rc = -ENOMEM; |
| 3498 | goto out_fail; |
| 3499 | } |
| 3500 | } |
| 3501 | |
Steve French | 23657ad | 2018-04-22 15:14:58 -0500 | [diff] [blame] | 3502 | if (volume_info->seal) { |
| 3503 | if (ses->server->vals->protocol_id == 0) { |
| 3504 | cifs_dbg(VFS, |
| 3505 | "SMB3 or later required for encryption\n"); |
| 3506 | rc = -EOPNOTSUPP; |
| 3507 | goto out_fail; |
| 3508 | } else if (tcon->ses->server->capabilities & |
| 3509 | SMB2_GLOBAL_CAP_ENCRYPTION) |
| 3510 | tcon->seal = true; |
| 3511 | else { |
| 3512 | cifs_dbg(VFS, "Encryption is not supported on share\n"); |
| 3513 | rc = -EOPNOTSUPP; |
| 3514 | goto out_fail; |
| 3515 | } |
| 3516 | } |
| 3517 | |
Steve French | 8505c8b | 2018-06-18 14:01:59 -0500 | [diff] [blame] | 3518 | if (volume_info->linux_ext) { |
| 3519 | if (ses->server->posix_ext_supported) { |
Steve French | b326614 | 2018-05-20 23:41:10 -0500 | [diff] [blame] | 3520 | tcon->posix_extensions = true; |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 3521 | pr_warn_once("SMB3.11 POSIX Extensions are experimental\n"); |
Steve French | 8505c8b | 2018-06-18 14:01:59 -0500 | [diff] [blame] | 3522 | } else { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 3523 | cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n"); |
Steve French | 8505c8b | 2018-06-18 14:01:59 -0500 | [diff] [blame] | 3524 | rc = -EOPNOTSUPP; |
| 3525 | goto out_fail; |
Steve French | 2fbb564 | 2018-06-12 12:11:31 -0500 | [diff] [blame] | 3526 | } |
Steve French | b326614 | 2018-05-20 23:41:10 -0500 | [diff] [blame] | 3527 | } |
Steve French | b326614 | 2018-05-20 23:41:10 -0500 | [diff] [blame] | 3528 | |
Pavel Shilovsky | 2e6e02a | 2012-05-25 11:11:39 +0400 | [diff] [blame] | 3529 | /* |
| 3530 | * BB Do we need to wrap session_mutex around this TCon call and Unix |
| 3531 | * SetFS as we do on SessSetup and reconnect? |
| 3532 | */ |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3533 | xid = get_xid(); |
Pavel Shilovsky | 2e6e02a | 2012-05-25 11:11:39 +0400 | [diff] [blame] | 3534 | rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon, |
| 3535 | volume_info->local_nls); |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3536 | free_xid(xid); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3537 | cifs_dbg(FYI, "Tcon rc = %d\n", rc); |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3538 | if (rc) |
| 3539 | goto out_fail; |
| 3540 | |
Steve French | b618f00 | 2015-11-03 09:15:03 -0600 | [diff] [blame] | 3541 | tcon->use_persistent = false; |
| 3542 | /* check if SMB2 or later, CIFS does not support persistent handles */ |
| 3543 | if (volume_info->persistent) { |
| 3544 | if (ses->server->vals->protocol_id == 0) { |
| 3545 | cifs_dbg(VFS, |
| 3546 | "SMB3 or later required for persistent handles\n"); |
| 3547 | rc = -EOPNOTSUPP; |
| 3548 | goto out_fail; |
| 3549 | } else if (ses->server->capabilities & |
| 3550 | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) |
| 3551 | tcon->use_persistent = true; |
| 3552 | else /* persistent handles requested but not supported */ { |
| 3553 | cifs_dbg(VFS, |
| 3554 | "Persistent handles not supported on share\n"); |
| 3555 | rc = -EOPNOTSUPP; |
| 3556 | goto out_fail; |
| 3557 | } |
| 3558 | } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY) |
| 3559 | && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) |
| 3560 | && (volume_info->nopersistent == false)) { |
| 3561 | cifs_dbg(FYI, "enabling persistent handles\n"); |
| 3562 | tcon->use_persistent = true; |
Steve French | 592fafe | 2015-11-03 10:08:53 -0600 | [diff] [blame] | 3563 | } else if (volume_info->resilient) { |
| 3564 | if (ses->server->vals->protocol_id == 0) { |
| 3565 | cifs_dbg(VFS, |
| 3566 | "SMB2.1 or later required for resilient handles\n"); |
| 3567 | rc = -EOPNOTSUPP; |
| 3568 | goto out_fail; |
| 3569 | } |
| 3570 | tcon->use_resilient = true; |
Steve French | b618f00 | 2015-11-03 09:15:03 -0600 | [diff] [blame] | 3571 | } |
| 3572 | |
Steve French | cae53f7 | 2019-09-03 17:49:46 -0500 | [diff] [blame] | 3573 | /* If the user really knows what they are doing they can override */ |
| 3574 | if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) { |
| 3575 | if (volume_info->cache_ro) |
| 3576 | cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n"); |
| 3577 | else if (volume_info->cache_rw) |
| 3578 | cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n"); |
| 3579 | } |
| 3580 | |
Kenneth D'souza | 8fd6e1d | 2020-05-18 13:01:34 +0530 | [diff] [blame] | 3581 | if (volume_info->no_lease) { |
| 3582 | if (ses->server->vals->protocol_id == 0) { |
| 3583 | cifs_dbg(VFS, |
| 3584 | "SMB2 or later required for nolease option\n"); |
| 3585 | rc = -EOPNOTSUPP; |
| 3586 | goto out_fail; |
| 3587 | } else |
| 3588 | tcon->no_lease = volume_info->no_lease; |
| 3589 | } |
| 3590 | |
Pavel Shilovsky | 2e6e02a | 2012-05-25 11:11:39 +0400 | [diff] [blame] | 3591 | /* |
| 3592 | * We can have only one retry value for a connection to a share so for |
| 3593 | * resources mounted more than once to the same server share the last |
| 3594 | * value passed in for the retry flag is used. |
| 3595 | */ |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3596 | tcon->retry = volume_info->retry; |
| 3597 | tcon->nocase = volume_info->nocase; |
Steve French | 3d4ef9a | 2018-04-25 22:19:09 -0500 | [diff] [blame] | 3598 | tcon->nohandlecache = volume_info->nohandlecache; |
Steve French | 82e9367 | 2020-05-19 03:06:57 -0500 | [diff] [blame] | 3599 | tcon->nodelete = volume_info->nodelete; |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3600 | tcon->local_lease = volume_info->local_lease; |
Pavel Shilovsky | 233839b | 2012-09-19 06:22:45 -0700 | [diff] [blame] | 3601 | INIT_LIST_HEAD(&tcon->pending_opens); |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3602 | |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3603 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3604 | list_add(&tcon->tcon_list, &ses->tcon_list); |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 3605 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3606 | |
Suresh Jayaraman | d03382c | 2010-07-05 18:12:27 +0530 | [diff] [blame] | 3607 | cifs_fscache_get_super_cookie(tcon); |
| 3608 | |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3609 | return tcon; |
| 3610 | |
| 3611 | out_fail: |
| 3612 | tconInfoFree(tcon); |
| 3613 | return ERR_PTR(rc); |
| 3614 | } |
| 3615 | |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 3616 | void |
| 3617 | cifs_put_tlink(struct tcon_link *tlink) |
| 3618 | { |
| 3619 | if (!tlink || IS_ERR(tlink)) |
| 3620 | return; |
| 3621 | |
| 3622 | if (!atomic_dec_and_test(&tlink->tl_count) || |
| 3623 | test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) { |
| 3624 | tlink->tl_time = jiffies; |
| 3625 | return; |
| 3626 | } |
| 3627 | |
| 3628 | if (!IS_ERR(tlink_tcon(tlink))) |
| 3629 | cifs_put_tcon(tlink_tcon(tlink)); |
| 3630 | kfree(tlink); |
| 3631 | return; |
| 3632 | } |
Jeff Layton | d00c28d | 2010-04-24 07:57:44 -0400 | [diff] [blame] | 3633 | |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3634 | static int |
| 3635 | compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) |
| 3636 | { |
| 3637 | struct cifs_sb_info *old = CIFS_SB(sb); |
| 3638 | struct cifs_sb_info *new = mnt_data->cifs_sb; |
Paulo Alcantara (SUSE) | 29fbeb7 | 2019-06-18 16:16:02 -0300 | [diff] [blame] | 3639 | unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK; |
| 3640 | unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK; |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3641 | |
| 3642 | if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK)) |
| 3643 | return 0; |
| 3644 | |
Paulo Alcantara (SUSE) | 29fbeb7 | 2019-06-18 16:16:02 -0300 | [diff] [blame] | 3645 | if (old->mnt_cifs_serverino_autodisabled) |
| 3646 | newflags &= ~CIFS_MOUNT_SERVER_INUM; |
| 3647 | |
| 3648 | if (oldflags != newflags) |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3649 | return 0; |
| 3650 | |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3651 | /* |
Jeff Layton | 5eba8ab | 2011-10-19 15:30:26 -0400 | [diff] [blame] | 3652 | * We want to share sb only if we don't specify an r/wsize or |
| 3653 | * specified r/wsize is greater than or equal to existing one. |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3654 | */ |
| 3655 | if (new->wsize && new->wsize < old->wsize) |
| 3656 | return 0; |
| 3657 | |
Jeff Layton | 5eba8ab | 2011-10-19 15:30:26 -0400 | [diff] [blame] | 3658 | if (new->rsize && new->rsize < old->rsize) |
| 3659 | return 0; |
| 3660 | |
Eric W. Biederman | 1f68233 | 2013-02-06 01:20:20 -0800 | [diff] [blame] | 3661 | if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid)) |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3662 | return 0; |
| 3663 | |
| 3664 | if (old->mnt_file_mode != new->mnt_file_mode || |
| 3665 | old->mnt_dir_mode != new->mnt_dir_mode) |
| 3666 | return 0; |
| 3667 | |
| 3668 | if (strcmp(old->local_nls->charset, new->local_nls->charset)) |
| 3669 | return 0; |
| 3670 | |
| 3671 | if (old->actimeo != new->actimeo) |
| 3672 | return 0; |
| 3673 | |
| 3674 | return 1; |
| 3675 | } |
| 3676 | |
Sachin Prabhu | c1d8b24 | 2016-07-29 22:38:20 +0100 | [diff] [blame] | 3677 | static int |
| 3678 | match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data) |
| 3679 | { |
| 3680 | struct cifs_sb_info *old = CIFS_SB(sb); |
| 3681 | struct cifs_sb_info *new = mnt_data->cifs_sb; |
Ronnie Sahlberg | fe12926 | 2020-01-22 11:07:56 +1000 | [diff] [blame] | 3682 | bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && |
| 3683 | old->prepath; |
| 3684 | bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && |
| 3685 | new->prepath; |
Sachin Prabhu | c1d8b24 | 2016-07-29 22:38:20 +0100 | [diff] [blame] | 3686 | |
Sachin Prabhu | cd8c429 | 2017-04-26 14:05:46 +0100 | [diff] [blame] | 3687 | if (old_set && new_set && !strcmp(new->prepath, old->prepath)) |
Sachin Prabhu | c1d8b24 | 2016-07-29 22:38:20 +0100 | [diff] [blame] | 3688 | return 1; |
Sachin Prabhu | cd8c429 | 2017-04-26 14:05:46 +0100 | [diff] [blame] | 3689 | else if (!old_set && !new_set) |
| 3690 | return 1; |
| 3691 | |
Sachin Prabhu | c1d8b24 | 2016-07-29 22:38:20 +0100 | [diff] [blame] | 3692 | return 0; |
| 3693 | } |
| 3694 | |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3695 | int |
| 3696 | cifs_match_super(struct super_block *sb, void *data) |
| 3697 | { |
| 3698 | struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data; |
| 3699 | struct smb_vol *volume_info; |
| 3700 | struct cifs_sb_info *cifs_sb; |
| 3701 | struct TCP_Server_Info *tcp_srv; |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 3702 | struct cifs_ses *ses; |
| 3703 | struct cifs_tcon *tcon; |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3704 | struct tcon_link *tlink; |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3705 | int rc = 0; |
| 3706 | |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3707 | spin_lock(&cifs_tcp_ses_lock); |
| 3708 | cifs_sb = CIFS_SB(sb); |
| 3709 | tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb)); |
| 3710 | if (IS_ERR(tlink)) { |
| 3711 | spin_unlock(&cifs_tcp_ses_lock); |
| 3712 | return rc; |
| 3713 | } |
| 3714 | tcon = tlink_tcon(tlink); |
| 3715 | ses = tcon->ses; |
| 3716 | tcp_srv = ses->server; |
| 3717 | |
| 3718 | volume_info = mnt_data->vol; |
| 3719 | |
Jeff Layton | 9fa114f | 2012-11-26 11:09:57 -0500 | [diff] [blame] | 3720 | if (!match_server(tcp_srv, volume_info) || |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3721 | !match_session(ses, volume_info) || |
Pavel Shilovsky | ae6f8dd | 2016-11-17 13:59:23 -0800 | [diff] [blame] | 3722 | !match_tcon(tcon, volume_info) || |
Sachin Prabhu | c1d8b24 | 2016-07-29 22:38:20 +0100 | [diff] [blame] | 3723 | !match_prepath(sb, mnt_data)) { |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3724 | rc = 0; |
| 3725 | goto out; |
| 3726 | } |
| 3727 | |
| 3728 | rc = compare_mount_options(sb, mnt_data); |
| 3729 | out: |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3730 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | f484b5d0 | 2011-07-11 10:16:34 -0400 | [diff] [blame] | 3731 | cifs_put_tlink(tlink); |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 3732 | return rc; |
| 3733 | } |
| 3734 | |
Jeff Layton | 09e50d5 | 2008-07-23 10:11:19 -0400 | [diff] [blame] | 3735 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 3736 | static struct lock_class_key cifs_key[2]; |
| 3737 | static struct lock_class_key cifs_slock_key[2]; |
| 3738 | |
| 3739 | static inline void |
| 3740 | cifs_reclassify_socket4(struct socket *sock) |
| 3741 | { |
| 3742 | struct sock *sk = sock->sk; |
Hannes Frederic Sowa | fafc4e1 | 2016-04-08 15:11:27 +0200 | [diff] [blame] | 3743 | BUG_ON(!sock_allow_reclassification(sk)); |
Jeff Layton | 09e50d5 | 2008-07-23 10:11:19 -0400 | [diff] [blame] | 3744 | sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS", |
| 3745 | &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]); |
| 3746 | } |
| 3747 | |
| 3748 | static inline void |
| 3749 | cifs_reclassify_socket6(struct socket *sock) |
| 3750 | { |
| 3751 | struct sock *sk = sock->sk; |
Hannes Frederic Sowa | fafc4e1 | 2016-04-08 15:11:27 +0200 | [diff] [blame] | 3752 | BUG_ON(!sock_allow_reclassification(sk)); |
Jeff Layton | 09e50d5 | 2008-07-23 10:11:19 -0400 | [diff] [blame] | 3753 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS", |
| 3754 | &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]); |
| 3755 | } |
| 3756 | #else |
| 3757 | static inline void |
| 3758 | cifs_reclassify_socket4(struct socket *sock) |
| 3759 | { |
| 3760 | } |
| 3761 | |
| 3762 | static inline void |
| 3763 | cifs_reclassify_socket6(struct socket *sock) |
| 3764 | { |
| 3765 | } |
| 3766 | #endif |
| 3767 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3768 | /* See RFC1001 section 14 on representation of Netbios names */ |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 3769 | static void rfc1002mangle(char *target, char *source, unsigned int length) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3770 | { |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 3771 | unsigned int i, j; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3772 | |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 3773 | for (i = 0, j = 0; i < (length); i++) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3774 | /* mask a nibble at a time and encode */ |
| 3775 | target[j] = 'A' + (0x0F & (source[i] >> 4)); |
| 3776 | target[j+1] = 'A' + (0x0F & source[i]); |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 3777 | j += 2; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3778 | } |
| 3779 | |
| 3780 | } |
| 3781 | |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 3782 | static int |
| 3783 | bind_socket(struct TCP_Server_Info *server) |
| 3784 | { |
| 3785 | int rc = 0; |
| 3786 | if (server->srcaddr.ss_family != AF_UNSPEC) { |
| 3787 | /* Bind to the specified local IP address */ |
| 3788 | struct socket *socket = server->ssocket; |
| 3789 | rc = socket->ops->bind(socket, |
| 3790 | (struct sockaddr *) &server->srcaddr, |
| 3791 | sizeof(server->srcaddr)); |
| 3792 | if (rc < 0) { |
| 3793 | struct sockaddr_in *saddr4; |
| 3794 | struct sockaddr_in6 *saddr6; |
| 3795 | saddr4 = (struct sockaddr_in *)&server->srcaddr; |
| 3796 | saddr6 = (struct sockaddr_in6 *)&server->srcaddr; |
| 3797 | if (saddr6->sin6_family == AF_INET6) |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 3798 | cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n", |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3799 | &saddr6->sin6_addr, rc); |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 3800 | else |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 3801 | cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n", |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3802 | &saddr4->sin_addr.s_addr, rc); |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 3803 | } |
| 3804 | } |
| 3805 | return rc; |
| 3806 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3807 | |
| 3808 | static int |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3809 | ip_rfc1001_connect(struct TCP_Server_Info *server) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3810 | { |
| 3811 | int rc = 0; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3812 | /* |
| 3813 | * some servers require RFC1001 sessinit before sending |
| 3814 | * negprot - BB check reconnection in case where second |
| 3815 | * sessinit is sent but no second negprot |
| 3816 | */ |
| 3817 | struct rfc1002_session_packet *ses_init_buf; |
| 3818 | struct smb_hdr *smb_buf; |
| 3819 | ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), |
| 3820 | GFP_KERNEL); |
| 3821 | if (ses_init_buf) { |
| 3822 | ses_init_buf->trailer.session_req.called_len = 32; |
| 3823 | |
Colin Ian King | 997152f | 2016-01-25 16:25:54 +0000 | [diff] [blame] | 3824 | if (server->server_RFC1001_name[0] != 0) |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3825 | rfc1002mangle(ses_init_buf->trailer. |
| 3826 | session_req.called_name, |
| 3827 | server->server_RFC1001_name, |
| 3828 | RFC1001_NAME_LEN_WITH_NULL); |
| 3829 | else |
| 3830 | rfc1002mangle(ses_init_buf->trailer. |
| 3831 | session_req.called_name, |
| 3832 | DEFAULT_CIFS_CALLED_NAME, |
| 3833 | RFC1001_NAME_LEN_WITH_NULL); |
| 3834 | |
| 3835 | ses_init_buf->trailer.session_req.calling_len = 32; |
| 3836 | |
| 3837 | /* |
| 3838 | * calling name ends in null (byte 16) from old smb |
| 3839 | * convention. |
| 3840 | */ |
Steve French | c85c35f | 2015-03-27 01:15:02 -0500 | [diff] [blame] | 3841 | if (server->workstation_RFC1001_name[0] != 0) |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3842 | rfc1002mangle(ses_init_buf->trailer. |
| 3843 | session_req.calling_name, |
| 3844 | server->workstation_RFC1001_name, |
| 3845 | RFC1001_NAME_LEN_WITH_NULL); |
| 3846 | else |
| 3847 | rfc1002mangle(ses_init_buf->trailer. |
| 3848 | session_req.calling_name, |
| 3849 | "LINUX_CIFS_CLNT", |
| 3850 | RFC1001_NAME_LEN_WITH_NULL); |
| 3851 | |
| 3852 | ses_init_buf->trailer.session_req.scope1 = 0; |
| 3853 | ses_init_buf->trailer.session_req.scope2 = 0; |
| 3854 | smb_buf = (struct smb_hdr *)ses_init_buf; |
| 3855 | |
| 3856 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ |
Steve French | be8e3b0 | 2011-04-29 05:40:20 +0000 | [diff] [blame] | 3857 | smb_buf->smb_buf_length = cpu_to_be32(0x81000044); |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3858 | rc = smb_send(server, smb_buf, 0x44); |
| 3859 | kfree(ses_init_buf); |
| 3860 | /* |
| 3861 | * RFC1001 layer in at least one server |
| 3862 | * requires very short break before negprot |
| 3863 | * presumably because not expecting negprot |
| 3864 | * to follow so fast. This is a simple |
| 3865 | * solution that works without |
| 3866 | * complicating the code and causes no |
| 3867 | * significant slowing down on mount |
| 3868 | * for everyone else |
| 3869 | */ |
| 3870 | usleep_range(1000, 2000); |
| 3871 | } |
| 3872 | /* |
| 3873 | * else the negprot may still work without this |
| 3874 | * even though malloc failed |
| 3875 | */ |
| 3876 | |
| 3877 | return rc; |
| 3878 | } |
| 3879 | |
| 3880 | static int |
| 3881 | generic_ip_connect(struct TCP_Server_Info *server) |
| 3882 | { |
| 3883 | int rc = 0; |
Steve French | 6da9791 | 2011-03-13 18:55:55 +0000 | [diff] [blame] | 3884 | __be16 sport; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3885 | int slen, sfamily; |
Jeff Layton | bcf4b10 | 2008-12-01 18:42:15 -0500 | [diff] [blame] | 3886 | struct socket *socket = server->ssocket; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3887 | struct sockaddr *saddr; |
| 3888 | |
| 3889 | saddr = (struct sockaddr *) &server->dstaddr; |
| 3890 | |
| 3891 | if (server->dstaddr.ss_family == AF_INET6) { |
| 3892 | sport = ((struct sockaddr_in6 *) saddr)->sin6_port; |
| 3893 | slen = sizeof(struct sockaddr_in6); |
| 3894 | sfamily = AF_INET6; |
| 3895 | } else { |
| 3896 | sport = ((struct sockaddr_in *) saddr)->sin_port; |
| 3897 | slen = sizeof(struct sockaddr_in); |
| 3898 | sfamily = AF_INET; |
| 3899 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3900 | |
Jeff Layton | bcf4b10 | 2008-12-01 18:42:15 -0500 | [diff] [blame] | 3901 | if (socket == NULL) { |
Rob Landley | f1d0c99 | 2011-01-22 15:44:05 -0600 | [diff] [blame] | 3902 | rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM, |
| 3903 | IPPROTO_TCP, &socket, 1); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3904 | if (rc < 0) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 3905 | cifs_server_dbg(VFS, "Error %d creating socket\n", rc); |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3906 | server->ssocket = NULL; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3907 | return rc; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3908 | } |
Jeff Layton | bcf4b10 | 2008-12-01 18:42:15 -0500 | [diff] [blame] | 3909 | |
| 3910 | /* BB other socket options to set KEEPALIVE, NODELAY? */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3911 | cifs_dbg(FYI, "Socket created\n"); |
Jeff Layton | bcf4b10 | 2008-12-01 18:42:15 -0500 | [diff] [blame] | 3912 | server->ssocket = socket; |
| 3913 | socket->sk->sk_allocation = GFP_NOFS; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3914 | if (sfamily == AF_INET6) |
| 3915 | cifs_reclassify_socket6(socket); |
| 3916 | else |
| 3917 | cifs_reclassify_socket4(socket); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3918 | } |
| 3919 | |
Ben Greear | 3eb9a88 | 2010-09-01 17:06:02 -0700 | [diff] [blame] | 3920 | rc = bind_socket(server); |
| 3921 | if (rc < 0) |
| 3922 | return rc; |
| 3923 | |
Jeff Layton | d5c5605 | 2008-12-01 18:42:33 -0500 | [diff] [blame] | 3924 | /* |
| 3925 | * Eventually check for other socket options to change from |
| 3926 | * the default. sock_setsockopt not used because it expects |
| 3927 | * user space buffer |
| 3928 | */ |
| 3929 | socket->sk->sk_rcvtimeo = 7 * HZ; |
Steve French | da505c3 | 2009-01-19 03:49:35 +0000 | [diff] [blame] | 3930 | socket->sk->sk_sndtimeo = 5 * HZ; |
Steve French | 6a5fa236 | 2010-01-01 01:28:43 +0000 | [diff] [blame] | 3931 | |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3932 | /* make the bufsizes depend on wsize/rsize and max requests */ |
| 3933 | if (server->noautotune) { |
| 3934 | if (socket->sk->sk_sndbuf < (200 * 1024)) |
| 3935 | socket->sk->sk_sndbuf = 200 * 1024; |
| 3936 | if (socket->sk->sk_rcvbuf < (140 * 1024)) |
| 3937 | socket->sk->sk_rcvbuf = 140 * 1024; |
| 3938 | } |
| 3939 | |
Christoph Hellwig | 12abc5e | 2020-05-28 07:12:19 +0200 | [diff] [blame] | 3940 | if (server->tcp_nodelay) |
| 3941 | tcp_sock_set_nodelay(socket->sk); |
Steve French | 6a5fa236 | 2010-01-01 01:28:43 +0000 | [diff] [blame] | 3942 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3943 | cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n", |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3944 | socket->sk->sk_sndbuf, |
| 3945 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); |
| 3946 | |
Paulo Alcantara (SUSE) | 8eecd1c | 2019-07-16 19:04:50 -0300 | [diff] [blame] | 3947 | rc = socket->ops->connect(socket, saddr, slen, |
| 3948 | server->noblockcnt ? O_NONBLOCK : 0); |
Paulo Alcantara (SUSE) | d532cc7 | 2019-10-10 12:31:58 -0300 | [diff] [blame] | 3949 | /* |
| 3950 | * When mounting SMB root file systems, we do not want to block in |
| 3951 | * connect. Otherwise bail out and then let cifs_reconnect() perform |
| 3952 | * reconnect failover - if possible. |
| 3953 | */ |
| 3954 | if (server->noblockcnt && rc == -EINPROGRESS) |
Paulo Alcantara (SUSE) | 8eecd1c | 2019-07-16 19:04:50 -0300 | [diff] [blame] | 3955 | rc = 0; |
Jeff Layton | ee1b3ea | 2011-06-21 07:18:26 -0400 | [diff] [blame] | 3956 | if (rc < 0) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 3957 | cifs_dbg(FYI, "Error %d connecting to server\n", rc); |
Jeff Layton | ee1b3ea | 2011-06-21 07:18:26 -0400 | [diff] [blame] | 3958 | sock_release(socket); |
| 3959 | server->ssocket = NULL; |
| 3960 | return rc; |
| 3961 | } |
| 3962 | |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3963 | if (sport == htons(RFC1001_PORT)) |
| 3964 | rc = ip_rfc1001_connect(server); |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 3965 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3966 | return rc; |
| 3967 | } |
| 3968 | |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3969 | static int |
| 3970 | ip_connect(struct TCP_Server_Info *server) |
| 3971 | { |
Steve French | 6da9791 | 2011-03-13 18:55:55 +0000 | [diff] [blame] | 3972 | __be16 *sport; |
Pavel Shilovsky | a9f1b85 | 2010-12-13 19:08:35 +0300 | [diff] [blame] | 3973 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; |
| 3974 | struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; |
| 3975 | |
| 3976 | if (server->dstaddr.ss_family == AF_INET6) |
| 3977 | sport = &addr6->sin6_port; |
| 3978 | else |
| 3979 | sport = &addr->sin_port; |
| 3980 | |
| 3981 | if (*sport == 0) { |
| 3982 | int rc; |
| 3983 | |
| 3984 | /* try with 445 port at first */ |
| 3985 | *sport = htons(CIFS_PORT); |
| 3986 | |
| 3987 | rc = generic_ip_connect(server); |
| 3988 | if (rc >= 0) |
| 3989 | return rc; |
| 3990 | |
| 3991 | /* if it failed, try with 139 port */ |
| 3992 | *sport = htons(RFC1001_PORT); |
| 3993 | } |
| 3994 | |
| 3995 | return generic_ip_connect(server); |
| 3996 | } |
| 3997 | |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 3998 | void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, |
Al Viro | 2c6292a | 2011-06-17 09:05:48 -0400 | [diff] [blame] | 3999 | struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info) |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4000 | { |
| 4001 | /* if we are reconnecting then should we check to see if |
| 4002 | * any requested capabilities changed locally e.g. via |
| 4003 | * remount but we can not do much about it here |
| 4004 | * if they have (even if we could detect it by the following) |
| 4005 | * Perhaps we could add a backpointer to array of sb from tcon |
| 4006 | * or if we change to make all sb to same share the same |
| 4007 | * sb as NFS - then we only have one backpointer to sb. |
| 4008 | * What if we wanted to mount the server share twice once with |
| 4009 | * and once without posixacls or posix paths? */ |
| 4010 | __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 4011 | |
Steve French | c18c842 | 2007-07-18 23:21:09 +0000 | [diff] [blame] | 4012 | if (vol_info && vol_info->no_linux_ext) { |
| 4013 | tcon->fsUnixInfo.Capability = 0; |
| 4014 | tcon->unix_ext = 0; /* Unix Extensions disabled */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4015 | cifs_dbg(FYI, "Linux protocol extensions disabled\n"); |
Steve French | c18c842 | 2007-07-18 23:21:09 +0000 | [diff] [blame] | 4016 | return; |
| 4017 | } else if (vol_info) |
| 4018 | tcon->unix_ext = 1; /* Unix Extensions supported */ |
| 4019 | |
| 4020 | if (tcon->unix_ext == 0) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4021 | cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n"); |
Steve French | c18c842 | 2007-07-18 23:21:09 +0000 | [diff] [blame] | 4022 | return; |
| 4023 | } |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 4024 | |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 4025 | if (!CIFSSMBQFSUnixInfo(xid, tcon)) { |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4026 | __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4027 | cifs_dbg(FYI, "unix caps which server supports %lld\n", cap); |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4028 | /* check for reconnect case in which we do not |
| 4029 | want to change the mount behavior if we can avoid it */ |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 4030 | if (vol_info == NULL) { |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 4031 | /* turn off POSIX ACL and PATHNAMES if not set |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4032 | originally at mount time */ |
| 4033 | if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0) |
| 4034 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; |
Igor Mammedov | 11b6d64 | 2008-02-15 19:06:04 +0000 | [diff] [blame] | 4035 | if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) { |
| 4036 | if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4037 | cifs_dbg(VFS, "POSIXPATH support change\n"); |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4038 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; |
Igor Mammedov | 11b6d64 | 2008-02-15 19:06:04 +0000 | [diff] [blame] | 4039 | } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4040 | cifs_dbg(VFS, "possible reconnect error\n"); |
| 4041 | cifs_dbg(VFS, "server disabled POSIX path support\n"); |
Igor Mammedov | 11b6d64 | 2008-02-15 19:06:04 +0000 | [diff] [blame] | 4042 | } |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4043 | } |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 4044 | |
Steve French | 6848b73 | 2011-05-26 18:38:54 +0000 | [diff] [blame] | 4045 | if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4046 | cifs_dbg(VFS, "per-share encryption not supported yet\n"); |
Steve French | 6848b73 | 2011-05-26 18:38:54 +0000 | [diff] [blame] | 4047 | |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4048 | cap &= CIFS_UNIX_CAP_MASK; |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4049 | if (vol_info && vol_info->no_psx_acl) |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4050 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4051 | else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4052 | cifs_dbg(FYI, "negotiated posix acl support\n"); |
Al Viro | 2c6292a | 2011-06-17 09:05:48 -0400 | [diff] [blame] | 4053 | if (cifs_sb) |
| 4054 | cifs_sb->mnt_cifs_flags |= |
| 4055 | CIFS_MOUNT_POSIXACL; |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4056 | } |
| 4057 | |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4058 | if (vol_info && vol_info->posix_paths == 0) |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4059 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4060 | else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4061 | cifs_dbg(FYI, "negotiate posix pathnames\n"); |
Al Viro | 2c6292a | 2011-06-17 09:05:48 -0400 | [diff] [blame] | 4062 | if (cifs_sb) |
| 4063 | cifs_sb->mnt_cifs_flags |= |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4064 | CIFS_MOUNT_POSIX_PATHS; |
| 4065 | } |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 4066 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4067 | cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap); |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4068 | #ifdef CONFIG_CIFS_DEBUG2 |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4069 | if (cap & CIFS_UNIX_FCNTL_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4070 | cifs_dbg(FYI, "FCNTL cap\n"); |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4071 | if (cap & CIFS_UNIX_EXTATTR_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4072 | cifs_dbg(FYI, "EXTATTR cap\n"); |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4073 | if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4074 | cifs_dbg(FYI, "POSIX path cap\n"); |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4075 | if (cap & CIFS_UNIX_XATTR_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4076 | cifs_dbg(FYI, "XATTR cap\n"); |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4077 | if (cap & CIFS_UNIX_POSIX_ACL_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4078 | cifs_dbg(FYI, "POSIX ACL cap\n"); |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4079 | if (cap & CIFS_UNIX_LARGE_READ_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4080 | cifs_dbg(FYI, "very large read cap\n"); |
Steve French | 75865f8c | 2007-06-24 18:30:48 +0000 | [diff] [blame] | 4081 | if (cap & CIFS_UNIX_LARGE_WRITE_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4082 | cifs_dbg(FYI, "very large write cap\n"); |
Steve French | 6848b73 | 2011-05-26 18:38:54 +0000 | [diff] [blame] | 4083 | if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4084 | cifs_dbg(FYI, "transport encryption cap\n"); |
Steve French | 6848b73 | 2011-05-26 18:38:54 +0000 | [diff] [blame] | 4085 | if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4086 | cifs_dbg(FYI, "mandatory transport encryption cap\n"); |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4087 | #endif /* CIFS_DEBUG2 */ |
| 4088 | if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { |
Steve French | 442aa31 | 2007-09-24 20:25:46 +0000 | [diff] [blame] | 4089 | if (vol_info == NULL) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4090 | cifs_dbg(FYI, "resetting capabilities failed\n"); |
Steve French | 442aa31 | 2007-09-24 20:25:46 +0000 | [diff] [blame] | 4091 | } else |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4092 | cifs_dbg(VFS, "Negotiating Unix capabilities with the server failed. Consider mounting with the Unix Extensions disabled if problems are found by specifying the nounix mount option.\n"); |
Steve French | 5a44b31 | 2007-09-20 15:16:24 +0000 | [diff] [blame] | 4093 | |
Steve French | 8af1897 | 2007-02-14 04:42:51 +0000 | [diff] [blame] | 4094 | } |
| 4095 | } |
| 4096 | } |
| 4097 | |
Sachin Prabhu | 4214ebf | 2016-07-29 22:38:19 +0100 | [diff] [blame] | 4098 | int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, |
Pavel Shilovsky | 724d9f1 | 2011-05-05 09:55:12 +0000 | [diff] [blame] | 4099 | struct cifs_sb_info *cifs_sb) |
Jeff Layton | b1c8d2b | 2008-10-22 13:57:07 -0400 | [diff] [blame] | 4100 | { |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 4101 | INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); |
| 4102 | |
Al Viro | 2ced6f6 | 2011-06-17 09:20:04 -0400 | [diff] [blame] | 4103 | spin_lock_init(&cifs_sb->tlink_tree_lock); |
| 4104 | cifs_sb->tlink_tree = RB_ROOT; |
| 4105 | |
Steve French | e8506d2 | 2019-02-28 21:32:15 -0600 | [diff] [blame] | 4106 | cifs_sb->bsize = pvolume_info->bsize; |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 4107 | /* |
Jeff Layton | 5eba8ab | 2011-10-19 15:30:26 -0400 | [diff] [blame] | 4108 | * Temporarily set r/wsize for matching superblock. If we end up using |
| 4109 | * new sb then client will later negotiate it downward if needed. |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 4110 | */ |
Jeff Layton | 5eba8ab | 2011-10-19 15:30:26 -0400 | [diff] [blame] | 4111 | cifs_sb->rsize = pvolume_info->rsize; |
Pavel Shilovsky | 25c7f41 | 2011-05-26 23:35:47 +0400 | [diff] [blame] | 4112 | cifs_sb->wsize = pvolume_info->wsize; |
| 4113 | |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4114 | cifs_sb->mnt_uid = pvolume_info->linux_uid; |
| 4115 | cifs_sb->mnt_gid = pvolume_info->linux_gid; |
| 4116 | cifs_sb->mnt_file_mode = pvolume_info->file_mode; |
| 4117 | cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; |
Frank Sorenson | f52aa79 | 2020-02-12 15:31:48 -0600 | [diff] [blame] | 4118 | cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n", |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4119 | cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4120 | |
Suresh Jayaraman | 6d20e84 | 2010-12-01 14:42:28 +0530 | [diff] [blame] | 4121 | cifs_sb->actimeo = pvolume_info->actimeo; |
Pavel Shilovsky | 724d9f1 | 2011-05-05 09:55:12 +0000 | [diff] [blame] | 4122 | cifs_sb->local_nls = pvolume_info->local_nls; |
Suresh Jayaraman | 6d20e84 | 2010-12-01 14:42:28 +0530 | [diff] [blame] | 4123 | |
Aurelien Aptel | 8393072 | 2018-09-20 18:10:25 -0700 | [diff] [blame] | 4124 | if (pvolume_info->nodfs) |
| 4125 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS; |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4126 | if (pvolume_info->noperm) |
| 4127 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; |
| 4128 | if (pvolume_info->setuids) |
| 4129 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; |
Steve French | 9593265 | 2016-09-23 01:36:34 -0500 | [diff] [blame] | 4130 | if (pvolume_info->setuidfromacl) |
| 4131 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL; |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4132 | if (pvolume_info->server_ino) |
| 4133 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; |
| 4134 | if (pvolume_info->remap) |
Steve French | 2baa268 | 2014-09-27 02:19:01 -0500 | [diff] [blame] | 4135 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR; |
| 4136 | if (pvolume_info->sfu_remap) |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4137 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; |
| 4138 | if (pvolume_info->no_xattr) |
| 4139 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; |
| 4140 | if (pvolume_info->sfu_emul) |
| 4141 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; |
| 4142 | if (pvolume_info->nobrl) |
| 4143 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; |
Steve French | 3d4ef9a | 2018-04-25 22:19:09 -0500 | [diff] [blame] | 4144 | if (pvolume_info->nohandlecache) |
| 4145 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE; |
Steve French | be65244 | 2009-02-23 15:21:59 +0000 | [diff] [blame] | 4146 | if (pvolume_info->nostrictsync) |
Steve French | 4717bed | 2009-02-24 14:44:19 +0000 | [diff] [blame] | 4147 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; |
Steve French | 13a6e42 | 2008-12-02 17:24:33 +0000 | [diff] [blame] | 4148 | if (pvolume_info->mand_lock) |
| 4149 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; |
Pavel Shilovsky | d4ffff1 | 2011-05-26 06:02:00 +0000 | [diff] [blame] | 4150 | if (pvolume_info->rwpidforward) |
| 4151 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD; |
Steve French | 412094a | 2019-06-24 02:01:42 -0500 | [diff] [blame] | 4152 | if (pvolume_info->mode_ace) |
| 4153 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID; |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4154 | if (pvolume_info->cifs_acl) |
| 4155 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; |
Sachin Prabhu | 3c7c87f | 2012-04-24 15:28:14 +0100 | [diff] [blame] | 4156 | if (pvolume_info->backupuid_specified) { |
Shirish Pargaonkar | 3d3ea8e | 2011-09-26 09:56:44 -0500 | [diff] [blame] | 4157 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID; |
Sachin Prabhu | 3c7c87f | 2012-04-24 15:28:14 +0100 | [diff] [blame] | 4158 | cifs_sb->mnt_backupuid = pvolume_info->backupuid; |
| 4159 | } |
| 4160 | if (pvolume_info->backupgid_specified) { |
Shirish Pargaonkar | 3d3ea8e | 2011-09-26 09:56:44 -0500 | [diff] [blame] | 4161 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID; |
Sachin Prabhu | 3c7c87f | 2012-04-24 15:28:14 +0100 | [diff] [blame] | 4162 | cifs_sb->mnt_backupgid = pvolume_info->backupgid; |
| 4163 | } |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4164 | if (pvolume_info->override_uid) |
| 4165 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; |
| 4166 | if (pvolume_info->override_gid) |
| 4167 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; |
| 4168 | if (pvolume_info->dynperm) |
| 4169 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; |
Suresh Jayaraman | fa1df75 | 2010-07-05 18:13:36 +0530 | [diff] [blame] | 4170 | if (pvolume_info->fsc) |
| 4171 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE; |
Jeff Layton | 0eb8a13 | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 4172 | if (pvolume_info->multiuser) |
| 4173 | cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | |
| 4174 | CIFS_MOUNT_NO_PERM); |
Pavel Shilovsky | d39454f | 2011-01-24 14:16:35 -0500 | [diff] [blame] | 4175 | if (pvolume_info->strict_io) |
| 4176 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO; |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4177 | if (pvolume_info->direct_io) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4178 | cifs_dbg(FYI, "mounting share using direct i/o\n"); |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4179 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
| 4180 | } |
Steve French | 83bbfa7 | 2019-08-27 23:58:54 -0500 | [diff] [blame] | 4181 | if (pvolume_info->cache_ro) { |
| 4182 | cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n"); |
| 4183 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE; |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 4184 | } else if (pvolume_info->cache_rw) { |
| 4185 | cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n"); |
| 4186 | cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE | |
| 4187 | CIFS_MOUNT_RW_CACHE); |
Steve French | 83bbfa7 | 2019-08-27 23:58:54 -0500 | [diff] [blame] | 4188 | } |
Stefan Metzmacher | 736a3320 | 2010-07-30 14:56:00 +0200 | [diff] [blame] | 4189 | if (pvolume_info->mfsymlinks) { |
| 4190 | if (pvolume_info->sfu_emul) { |
Steve French | db8b631 | 2014-09-22 05:13:55 -0500 | [diff] [blame] | 4191 | /* |
| 4192 | * Our SFU ("Services for Unix" emulation does not allow |
| 4193 | * creating symlinks but does allow reading existing SFU |
| 4194 | * symlinks (it does allow both creating and reading SFU |
| 4195 | * style mknod and FIFOs though). When "mfsymlinks" and |
| 4196 | * "sfu" are both enabled at the same time, it allows |
| 4197 | * reading both types of symlinks, but will only create |
| 4198 | * them with mfsymlinks format. This allows better |
| 4199 | * Apple compatibility (probably better for Samba too) |
| 4200 | * while still recognizing old Windows style symlinks. |
| 4201 | */ |
| 4202 | cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n"); |
Stefan Metzmacher | 736a3320 | 2010-07-30 14:56:00 +0200 | [diff] [blame] | 4203 | } |
Steve French | db8b631 | 2014-09-22 05:13:55 -0500 | [diff] [blame] | 4204 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS; |
Stefan Metzmacher | 736a3320 | 2010-07-30 14:56:00 +0200 | [diff] [blame] | 4205 | } |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 4206 | |
| 4207 | if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm)) |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4208 | cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n"); |
Sachin Prabhu | 4214ebf | 2016-07-29 22:38:19 +0100 | [diff] [blame] | 4209 | |
| 4210 | if (pvolume_info->prepath) { |
| 4211 | cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL); |
| 4212 | if (cifs_sb->prepath == NULL) |
| 4213 | return -ENOMEM; |
| 4214 | } |
| 4215 | |
| 4216 | return 0; |
Jeff Layton | b1c8d2b | 2008-10-22 13:57:07 -0400 | [diff] [blame] | 4217 | } |
| 4218 | |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4219 | void |
| 4220 | cifs_cleanup_volume_info_contents(struct smb_vol *volume_info) |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4221 | { |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 4222 | kfree(volume_info->username); |
Waiman Long | 453431a | 2020-08-06 23:18:13 -0700 | [diff] [blame] | 4223 | kfree_sensitive(volume_info->password); |
Jesper Juhl | 95c7545 | 2011-08-27 18:58:34 +0200 | [diff] [blame] | 4224 | kfree(volume_info->UNC); |
Sean Finney | b946845 | 2011-04-11 13:19:32 +0000 | [diff] [blame] | 4225 | kfree(volume_info->domainname); |
| 4226 | kfree(volume_info->iocharset); |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4227 | kfree(volume_info->prepath); |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4228 | } |
| 4229 | |
Jeff Layton | b9bce2e | 2011-07-06 08:10:39 -0400 | [diff] [blame] | 4230 | void |
| 4231 | cifs_cleanup_volume_info(struct smb_vol *volume_info) |
| 4232 | { |
| 4233 | if (!volume_info) |
| 4234 | return; |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4235 | cifs_cleanup_volume_info_contents(volume_info); |
Jeff Layton | b9bce2e | 2011-07-06 08:10:39 -0400 | [diff] [blame] | 4236 | kfree(volume_info); |
| 4237 | } |
| 4238 | |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4239 | /* Release all succeed connections */ |
| 4240 | static inline void mount_put_conns(struct cifs_sb_info *cifs_sb, |
| 4241 | unsigned int xid, |
| 4242 | struct TCP_Server_Info *server, |
| 4243 | struct cifs_ses *ses, struct cifs_tcon *tcon) |
| 4244 | { |
| 4245 | int rc = 0; |
| 4246 | |
| 4247 | if (tcon) |
| 4248 | cifs_put_tcon(tcon); |
| 4249 | else if (ses) |
| 4250 | cifs_put_smb_ses(ses); |
| 4251 | else if (server) |
| 4252 | cifs_put_tcp_session(server, 0); |
| 4253 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS; |
| 4254 | free_xid(xid); |
| 4255 | } |
| 4256 | |
| 4257 | /* Get connections for tcp, ses and tcon */ |
| 4258 | static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, |
| 4259 | unsigned int *xid, |
| 4260 | struct TCP_Server_Info **nserver, |
| 4261 | struct cifs_ses **nses, struct cifs_tcon **ntcon) |
| 4262 | { |
| 4263 | int rc = 0; |
| 4264 | struct TCP_Server_Info *server; |
| 4265 | struct cifs_ses *ses; |
| 4266 | struct cifs_tcon *tcon; |
| 4267 | |
| 4268 | *nserver = NULL; |
| 4269 | *nses = NULL; |
| 4270 | *ntcon = NULL; |
| 4271 | |
| 4272 | *xid = get_xid(); |
| 4273 | |
| 4274 | /* get a reference to a tcp session */ |
| 4275 | server = cifs_get_tcp_session(vol); |
| 4276 | if (IS_ERR(server)) { |
| 4277 | rc = PTR_ERR(server); |
| 4278 | return rc; |
| 4279 | } |
| 4280 | |
| 4281 | *nserver = server; |
| 4282 | |
| 4283 | if ((vol->max_credits < 20) || (vol->max_credits > 60000)) |
| 4284 | server->max_credits = SMB2_MAX_CREDITS_AVAILABLE; |
| 4285 | else |
| 4286 | server->max_credits = vol->max_credits; |
| 4287 | |
| 4288 | /* get a reference to a SMB session */ |
| 4289 | ses = cifs_get_smb_ses(server, vol); |
| 4290 | if (IS_ERR(ses)) { |
| 4291 | rc = PTR_ERR(ses); |
| 4292 | return rc; |
| 4293 | } |
| 4294 | |
| 4295 | *nses = ses; |
| 4296 | |
| 4297 | if ((vol->persistent == true) && (!(ses->server->capabilities & |
| 4298 | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) { |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 4299 | cifs_server_dbg(VFS, "persistent handles not supported by server\n"); |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4300 | return -EOPNOTSUPP; |
| 4301 | } |
| 4302 | |
| 4303 | /* search for existing tcon to this server share */ |
| 4304 | tcon = cifs_get_tcon(ses, vol); |
| 4305 | if (IS_ERR(tcon)) { |
| 4306 | rc = PTR_ERR(tcon); |
| 4307 | return rc; |
| 4308 | } |
| 4309 | |
| 4310 | *ntcon = tcon; |
| 4311 | |
| 4312 | /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */ |
| 4313 | if (tcon->posix_extensions) |
| 4314 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; |
| 4315 | |
| 4316 | /* tell server which Unix caps we support */ |
| 4317 | if (cap_unix(tcon->ses)) { |
| 4318 | /* |
| 4319 | * reset of caps checks mount to see if unix extensions disabled |
| 4320 | * for just this mount. |
| 4321 | */ |
| 4322 | reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol); |
| 4323 | if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && |
| 4324 | (le64_to_cpu(tcon->fsUnixInfo.Capability) & |
| 4325 | CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) |
| 4326 | return -EACCES; |
| 4327 | } else |
| 4328 | tcon->unix_ext = 0; /* server does not support them */ |
| 4329 | |
| 4330 | /* do not care if a following call succeed - informational */ |
Steve French | 1981eba | 2019-08-29 22:33:38 -0500 | [diff] [blame] | 4331 | if (!tcon->pipe && server->ops->qfs_tcon) { |
Amir Goldstein | 0f06093 | 2020-02-03 21:46:43 +0200 | [diff] [blame] | 4332 | server->ops->qfs_tcon(*xid, tcon, cifs_sb); |
Steve French | 1981eba | 2019-08-29 22:33:38 -0500 | [diff] [blame] | 4333 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { |
| 4334 | if (tcon->fsDevInfo.DeviceCharacteristics & |
Steve French | 52870d5 | 2019-10-01 21:25:46 -0500 | [diff] [blame] | 4335 | cpu_to_le32(FILE_READ_ONLY_DEVICE)) |
Steve French | 1981eba | 2019-08-29 22:33:38 -0500 | [diff] [blame] | 4336 | cifs_dbg(VFS, "mounted to read only share\n"); |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 4337 | else if ((cifs_sb->mnt_cifs_flags & |
| 4338 | CIFS_MOUNT_RW_CACHE) == 0) |
Steve French | 1981eba | 2019-08-29 22:33:38 -0500 | [diff] [blame] | 4339 | cifs_dbg(VFS, "read only mount of RW share\n"); |
Steve French | 41e033f | 2019-08-30 02:12:41 -0500 | [diff] [blame] | 4340 | /* no need to log a RW mount of a typical RW share */ |
Steve French | 1981eba | 2019-08-29 22:33:38 -0500 | [diff] [blame] | 4341 | } |
| 4342 | } |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4343 | |
| 4344 | cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol); |
| 4345 | cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol); |
| 4346 | |
| 4347 | return 0; |
| 4348 | } |
| 4349 | |
| 4350 | static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, |
| 4351 | struct cifs_tcon *tcon) |
| 4352 | { |
| 4353 | struct tcon_link *tlink; |
| 4354 | |
| 4355 | /* hang the tcon off of the superblock */ |
| 4356 | tlink = kzalloc(sizeof(*tlink), GFP_KERNEL); |
| 4357 | if (tlink == NULL) |
| 4358 | return -ENOMEM; |
| 4359 | |
| 4360 | tlink->tl_uid = ses->linux_uid; |
| 4361 | tlink->tl_tcon = tcon; |
| 4362 | tlink->tl_time = jiffies; |
| 4363 | set_bit(TCON_LINK_MASTER, &tlink->tl_flags); |
| 4364 | set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); |
| 4365 | |
| 4366 | cifs_sb->master_tlink = tlink; |
| 4367 | spin_lock(&cifs_sb->tlink_tree_lock); |
| 4368 | tlink_rb_insert(&cifs_sb->tlink_tree, tlink); |
| 4369 | spin_unlock(&cifs_sb->tlink_tree_lock); |
| 4370 | |
| 4371 | queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, |
| 4372 | TLINK_IDLE_EXPIRE); |
| 4373 | return 0; |
| 4374 | } |
Jeff Layton | b9bce2e | 2011-07-06 08:10:39 -0400 | [diff] [blame] | 4375 | |
Steve French | 2d6d589 | 2009-04-09 00:36:44 +0000 | [diff] [blame] | 4376 | #ifdef CONFIG_CIFS_DFS_UPCALL |
Steve French | 6d3ea7e | 2012-11-28 22:34:41 -0600 | [diff] [blame] | 4377 | /* |
| 4378 | * cifs_build_path_to_root returns full path to root when we do not have an |
| 4379 | * exiting connection (tcon) |
| 4380 | */ |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4381 | static char * |
Jeff Layton | b2a0fa1 | 2011-07-06 08:10:36 -0400 | [diff] [blame] | 4382 | build_unc_path_to_root(const struct smb_vol *vol, |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4383 | const struct cifs_sb_info *cifs_sb, bool useppath) |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4384 | { |
Jeff Layton | b2a0fa1 | 2011-07-06 08:10:36 -0400 | [diff] [blame] | 4385 | char *full_path, *pos; |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4386 | unsigned int pplen = useppath && vol->prepath ? |
| 4387 | strlen(vol->prepath) + 1 : 0; |
Jeff Layton | b2a0fa1 | 2011-07-06 08:10:36 -0400 | [diff] [blame] | 4388 | unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1); |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4389 | |
Ronnie Sahlberg | 340625e | 2019-08-27 09:30:14 +1000 | [diff] [blame] | 4390 | if (unc_len > MAX_TREE_SIZE) |
| 4391 | return ERR_PTR(-EINVAL); |
| 4392 | |
Jeff Layton | b2a0fa1 | 2011-07-06 08:10:36 -0400 | [diff] [blame] | 4393 | full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL); |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4394 | if (full_path == NULL) |
| 4395 | return ERR_PTR(-ENOMEM); |
| 4396 | |
Ronnie Sahlberg | 340625e | 2019-08-27 09:30:14 +1000 | [diff] [blame] | 4397 | memcpy(full_path, vol->UNC, unc_len); |
Jeff Layton | b2a0fa1 | 2011-07-06 08:10:36 -0400 | [diff] [blame] | 4398 | pos = full_path + unc_len; |
| 4399 | |
| 4400 | if (pplen) { |
Jeff Layton | 1fc29ba | 2013-05-31 10:00:18 -0400 | [diff] [blame] | 4401 | *pos = CIFS_DIR_SEP(cifs_sb); |
Ronnie Sahlberg | 340625e | 2019-08-27 09:30:14 +1000 | [diff] [blame] | 4402 | memcpy(pos + 1, vol->prepath, pplen); |
Jeff Layton | b2a0fa1 | 2011-07-06 08:10:36 -0400 | [diff] [blame] | 4403 | pos += pplen; |
| 4404 | } |
| 4405 | |
| 4406 | *pos = '\0'; /* add trailing null */ |
Steve French | f87d39d | 2011-05-27 03:50:55 +0000 | [diff] [blame] | 4407 | convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4408 | cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path); |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4409 | return full_path; |
| 4410 | } |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4411 | |
Paulo Alcantara | 1c78022 | 2018-11-14 16:24:03 -0200 | [diff] [blame] | 4412 | /** |
| 4413 | * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb |
| 4414 | * |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4415 | * |
Sean Finney | 046462a | 2011-04-11 13:19:33 +0000 | [diff] [blame] | 4416 | * If a referral is found, cifs_sb->mountdata will be (re-)allocated |
| 4417 | * to a string containing updated options for the submount. Otherwise it |
| 4418 | * will be left untouched. |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4419 | * |
| 4420 | * Returns the rc from get_dfs_path to the caller, which can be used to |
| 4421 | * determine whether there were referrals. |
| 4422 | */ |
| 4423 | static int |
Pavel Shilovsky | b669f33 | 2012-05-27 20:21:53 +0400 | [diff] [blame] | 4424 | expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4425 | struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb, |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4426 | char *ref_path) |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4427 | { |
| 4428 | int rc; |
Paulo Alcantara | 1c78022 | 2018-11-14 16:24:03 -0200 | [diff] [blame] | 4429 | struct dfs_info3_param referral = {0}; |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4430 | char *full_path = NULL, *mdata = NULL; |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4431 | |
Aurelien Aptel | 8393072 | 2018-09-20 18:10:25 -0700 | [diff] [blame] | 4432 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) |
| 4433 | return -EREMOTE; |
| 4434 | |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4435 | full_path = build_unc_path_to_root(volume_info, cifs_sb, true); |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4436 | if (IS_ERR(full_path)) |
| 4437 | return PTR_ERR(full_path); |
| 4438 | |
Paulo Alcantara | 1c78022 | 2018-11-14 16:24:03 -0200 | [diff] [blame] | 4439 | rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), |
| 4440 | ref_path, &referral, NULL); |
| 4441 | if (!rc) { |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4442 | char *fake_devname = NULL; |
| 4443 | |
| 4444 | mdata = cifs_compose_mount_options(cifs_sb->mountdata, |
Paulo Alcantara | 1c78022 | 2018-11-14 16:24:03 -0200 | [diff] [blame] | 4445 | full_path + 1, &referral, |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4446 | &fake_devname); |
Paulo Alcantara | 1c78022 | 2018-11-14 16:24:03 -0200 | [diff] [blame] | 4447 | free_dfs_info_param(&referral); |
Sean Finney | 046462a | 2011-04-11 13:19:33 +0000 | [diff] [blame] | 4448 | |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4449 | if (IS_ERR(mdata)) { |
| 4450 | rc = PTR_ERR(mdata); |
| 4451 | mdata = NULL; |
Jeff Layton | b9bce2e | 2011-07-06 08:10:39 -0400 | [diff] [blame] | 4452 | } else { |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4453 | cifs_cleanup_volume_info_contents(volume_info); |
Jeff Layton | b9bce2e | 2011-07-06 08:10:39 -0400 | [diff] [blame] | 4454 | rc = cifs_setup_volume_info(volume_info, mdata, |
Paulo Alcantara | 1c78022 | 2018-11-14 16:24:03 -0200 | [diff] [blame] | 4455 | fake_devname, false); |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4456 | } |
Jeff Layton | b9bce2e | 2011-07-06 08:10:39 -0400 | [diff] [blame] | 4457 | kfree(fake_devname); |
| 4458 | kfree(cifs_sb->mountdata); |
Sean Finney | 046462a | 2011-04-11 13:19:33 +0000 | [diff] [blame] | 4459 | cifs_sb->mountdata = mdata; |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4460 | } |
| 4461 | kfree(full_path); |
| 4462 | return rc; |
| 4463 | } |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4464 | |
| 4465 | static inline int get_next_dfs_tgt(const char *path, |
| 4466 | struct dfs_cache_tgt_list *tgt_list, |
| 4467 | struct dfs_cache_tgt_iterator **tgt_it) |
| 4468 | { |
| 4469 | if (!*tgt_it) |
| 4470 | *tgt_it = dfs_cache_get_tgt_iterator(tgt_list); |
| 4471 | else |
| 4472 | *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it); |
| 4473 | return !*tgt_it ? -EHOSTDOWN : 0; |
| 4474 | } |
| 4475 | |
| 4476 | static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it, |
| 4477 | struct smb_vol *fake_vol, struct smb_vol *vol) |
| 4478 | { |
| 4479 | const char *tgt = dfs_cache_get_tgt_name(tgt_it); |
| 4480 | int len = strlen(tgt) + 2; |
| 4481 | char *new_unc; |
| 4482 | |
| 4483 | new_unc = kmalloc(len, GFP_KERNEL); |
| 4484 | if (!new_unc) |
| 4485 | return -ENOMEM; |
Ronnie Sahlberg | 74ea5f9 | 2019-02-09 09:51:11 +1000 | [diff] [blame] | 4486 | scnprintf(new_unc, len, "\\%s", tgt); |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4487 | |
| 4488 | kfree(vol->UNC); |
| 4489 | vol->UNC = new_unc; |
| 4490 | |
| 4491 | if (fake_vol->prepath) { |
| 4492 | kfree(vol->prepath); |
| 4493 | vol->prepath = fake_vol->prepath; |
| 4494 | fake_vol->prepath = NULL; |
| 4495 | } |
| 4496 | memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr)); |
| 4497 | |
| 4498 | return 0; |
| 4499 | } |
| 4500 | |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4501 | static int setup_dfs_tgt_conn(const char *path, const char *full_path, |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4502 | const struct dfs_cache_tgt_iterator *tgt_it, |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4503 | struct cifs_sb_info *cifs_sb, struct smb_vol *vol, unsigned int *xid, |
| 4504 | struct TCP_Server_Info **server, struct cifs_ses **ses, |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4505 | struct cifs_tcon **tcon) |
| 4506 | { |
| 4507 | int rc; |
| 4508 | struct dfs_info3_param ref = {0}; |
| 4509 | char *mdata = NULL, *fake_devname = NULL; |
Steve French | d0959b0 | 2019-10-05 10:53:58 -0500 | [diff] [blame] | 4510 | struct smb_vol fake_vol = {NULL}; |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4511 | |
| 4512 | cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path); |
| 4513 | |
| 4514 | rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref); |
| 4515 | if (rc) |
| 4516 | return rc; |
| 4517 | |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4518 | mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname); |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4519 | free_dfs_info_param(&ref); |
| 4520 | |
| 4521 | if (IS_ERR(mdata)) { |
| 4522 | rc = PTR_ERR(mdata); |
| 4523 | mdata = NULL; |
| 4524 | } else { |
| 4525 | cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname); |
| 4526 | rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname, |
| 4527 | false); |
| 4528 | } |
| 4529 | kfree(mdata); |
| 4530 | kfree(fake_devname); |
| 4531 | |
| 4532 | if (!rc) { |
| 4533 | /* |
| 4534 | * We use a 'fake_vol' here because we need pass it down to the |
| 4535 | * mount_{get,put} functions to test connection against new DFS |
| 4536 | * targets. |
| 4537 | */ |
| 4538 | mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon); |
| 4539 | rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses, |
| 4540 | tcon); |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4541 | if (!rc || (*server && *ses)) { |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4542 | /* |
| 4543 | * We were able to connect to new target server. |
| 4544 | * Update current volume info with new target server. |
| 4545 | */ |
| 4546 | rc = update_vol_info(tgt_it, &fake_vol, vol); |
| 4547 | } |
| 4548 | } |
| 4549 | cifs_cleanup_volume_info_contents(&fake_vol); |
| 4550 | return rc; |
| 4551 | } |
| 4552 | |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4553 | static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb, |
| 4554 | struct smb_vol *vol, struct cifs_ses *root_ses, unsigned int *xid, |
| 4555 | struct TCP_Server_Info **server, struct cifs_ses **ses, |
| 4556 | struct cifs_tcon **tcon) |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4557 | { |
| 4558 | int rc; |
| 4559 | struct dfs_cache_tgt_list tgt_list; |
| 4560 | struct dfs_cache_tgt_iterator *tgt_it = NULL; |
| 4561 | |
| 4562 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) |
| 4563 | return -EOPNOTSUPP; |
| 4564 | |
| 4565 | rc = dfs_cache_noreq_find(path, NULL, &tgt_list); |
| 4566 | if (rc) |
| 4567 | return rc; |
| 4568 | |
| 4569 | for (;;) { |
| 4570 | /* Get next DFS target server - if any */ |
| 4571 | rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it); |
| 4572 | if (rc) |
| 4573 | break; |
| 4574 | /* Connect to next DFS target */ |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4575 | rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, vol, xid, server, ses, |
| 4576 | tcon); |
| 4577 | if (!rc || (*server && *ses)) |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4578 | break; |
| 4579 | } |
| 4580 | if (!rc) { |
| 4581 | /* |
| 4582 | * Update DFS target hint in DFS referral cache with the target |
| 4583 | * server we successfully reconnected to. |
| 4584 | */ |
| 4585 | rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses, |
| 4586 | cifs_sb->local_nls, |
| 4587 | cifs_remap(cifs_sb), path, |
| 4588 | tgt_it); |
| 4589 | } |
| 4590 | dfs_cache_free_tgts(&tgt_list); |
| 4591 | return rc; |
| 4592 | } |
Steve French | 2d6d589 | 2009-04-09 00:36:44 +0000 | [diff] [blame] | 4593 | #endif |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4594 | |
Paulo Alcantara (SUSE) | 5072010 | 2019-03-19 16:54:29 -0300 | [diff] [blame] | 4595 | int |
Jeff Layton | 04db79b | 2011-07-06 08:10:38 -0400 | [diff] [blame] | 4596 | cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 4597 | const char *devname, bool is_smb3) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4598 | { |
Pavel Shilovsky | 724d9f1 | 2011-05-05 09:55:12 +0000 | [diff] [blame] | 4599 | int rc = 0; |
Sean Finney | dd61394 | 2011-04-11 13:19:30 +0000 | [diff] [blame] | 4600 | |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 4601 | if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3)) |
Jeff Layton | 04db79b | 2011-07-06 08:10:38 -0400 | [diff] [blame] | 4602 | return -EINVAL; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4603 | |
Jeff Layton | 7586b76 | 2008-12-01 18:41:49 -0500 | [diff] [blame] | 4604 | if (volume_info->nullauth) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4605 | cifs_dbg(FYI, "Anonymous login\n"); |
Jeff Layton | 04febab | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 4606 | kfree(volume_info->username); |
| 4607 | volume_info->username = NULL; |
Jeff Layton | 7586b76 | 2008-12-01 18:41:49 -0500 | [diff] [blame] | 4608 | } else if (volume_info->username) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4609 | /* BB fixme parse for domain name here */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4610 | cifs_dbg(FYI, "Username: %s\n", volume_info->username); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4611 | } else { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4612 | cifs_dbg(VFS, "No username specified\n"); |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 4613 | /* In userspace mount helper we can get user name from alternate |
| 4614 | locations such as env variables and files on disk */ |
Jeff Layton | 04db79b | 2011-07-06 08:10:38 -0400 | [diff] [blame] | 4615 | return -EINVAL; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4616 | } |
| 4617 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4618 | /* this is needed for ASCII cp to Unicode converts */ |
Jeff Layton | 7586b76 | 2008-12-01 18:41:49 -0500 | [diff] [blame] | 4619 | if (volume_info->iocharset == NULL) { |
Jeff Layton | a5fc4ce | 2010-04-24 07:57:42 -0400 | [diff] [blame] | 4620 | /* load_nls_default cannot return null */ |
| 4621 | volume_info->local_nls = load_nls_default(); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4622 | } else { |
Jeff Layton | a5fc4ce | 2010-04-24 07:57:42 -0400 | [diff] [blame] | 4623 | volume_info->local_nls = load_nls(volume_info->iocharset); |
| 4624 | if (volume_info->local_nls == NULL) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 4625 | cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n", |
Joe Perches | b6b38f7 | 2010-04-21 03:50:45 +0000 | [diff] [blame] | 4626 | volume_info->iocharset); |
Jeff Layton | 04db79b | 2011-07-06 08:10:38 -0400 | [diff] [blame] | 4627 | return -ELIBACC; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4628 | } |
| 4629 | } |
Pavel Shilovsky | 724d9f1 | 2011-05-05 09:55:12 +0000 | [diff] [blame] | 4630 | |
Pavel Shilovsky | 724d9f1 | 2011-05-05 09:55:12 +0000 | [diff] [blame] | 4631 | return rc; |
Jeff Layton | 04db79b | 2011-07-06 08:10:38 -0400 | [diff] [blame] | 4632 | } |
| 4633 | |
| 4634 | struct smb_vol * |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 4635 | cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3) |
Jeff Layton | 04db79b | 2011-07-06 08:10:38 -0400 | [diff] [blame] | 4636 | { |
| 4637 | int rc; |
| 4638 | struct smb_vol *volume_info; |
| 4639 | |
Jeff Layton | 6ee9542 | 2012-11-26 11:09:57 -0500 | [diff] [blame] | 4640 | volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL); |
Jeff Layton | 04db79b | 2011-07-06 08:10:38 -0400 | [diff] [blame] | 4641 | if (!volume_info) |
| 4642 | return ERR_PTR(-ENOMEM); |
| 4643 | |
Steve French | c7c137b | 2018-06-06 17:59:29 -0500 | [diff] [blame] | 4644 | rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3); |
Jeff Layton | 04db79b | 2011-07-06 08:10:38 -0400 | [diff] [blame] | 4645 | if (rc) { |
| 4646 | cifs_cleanup_volume_info(volume_info); |
| 4647 | volume_info = ERR_PTR(rc); |
| 4648 | } |
| 4649 | |
| 4650 | return volume_info; |
Pavel Shilovsky | 724d9f1 | 2011-05-05 09:55:12 +0000 | [diff] [blame] | 4651 | } |
| 4652 | |
Aurelien Aptel | a6b5058 | 2016-05-25 19:59:09 +0200 | [diff] [blame] | 4653 | static int |
| 4654 | cifs_are_all_path_components_accessible(struct TCP_Server_Info *server, |
| 4655 | unsigned int xid, |
| 4656 | struct cifs_tcon *tcon, |
| 4657 | struct cifs_sb_info *cifs_sb, |
Ronnie Sahlberg | ce465bf | 2019-07-11 13:46:58 +1000 | [diff] [blame] | 4658 | char *full_path, |
| 4659 | int added_treename) |
Aurelien Aptel | a6b5058 | 2016-05-25 19:59:09 +0200 | [diff] [blame] | 4660 | { |
| 4661 | int rc; |
| 4662 | char *s; |
| 4663 | char sep, tmp; |
Ronnie Sahlberg | ce465bf | 2019-07-11 13:46:58 +1000 | [diff] [blame] | 4664 | int skip = added_treename ? 1 : 0; |
Aurelien Aptel | a6b5058 | 2016-05-25 19:59:09 +0200 | [diff] [blame] | 4665 | |
| 4666 | sep = CIFS_DIR_SEP(cifs_sb); |
| 4667 | s = full_path; |
| 4668 | |
| 4669 | rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, ""); |
| 4670 | while (rc == 0) { |
| 4671 | /* skip separators */ |
| 4672 | while (*s == sep) |
| 4673 | s++; |
| 4674 | if (!*s) |
| 4675 | break; |
| 4676 | /* next separator */ |
| 4677 | while (*s && *s != sep) |
| 4678 | s++; |
Ronnie Sahlberg | ce465bf | 2019-07-11 13:46:58 +1000 | [diff] [blame] | 4679 | /* |
| 4680 | * if the treename is added, we then have to skip the first |
| 4681 | * part within the separators |
| 4682 | */ |
| 4683 | if (skip) { |
| 4684 | skip = 0; |
| 4685 | continue; |
| 4686 | } |
Aurelien Aptel | a6b5058 | 2016-05-25 19:59:09 +0200 | [diff] [blame] | 4687 | /* |
| 4688 | * temporarily null-terminate the path at the end of |
| 4689 | * the current component |
| 4690 | */ |
| 4691 | tmp = *s; |
| 4692 | *s = 0; |
| 4693 | rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, |
| 4694 | full_path); |
| 4695 | *s = tmp; |
| 4696 | } |
| 4697 | return rc; |
| 4698 | } |
| 4699 | |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4700 | /* |
| 4701 | * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is, |
| 4702 | * otherwise 0. |
| 4703 | */ |
| 4704 | static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, |
| 4705 | const unsigned int xid, |
| 4706 | struct TCP_Server_Info *server, |
| 4707 | struct cifs_tcon *tcon) |
Pavel Shilovsky | 724d9f1 | 2011-05-05 09:55:12 +0000 | [diff] [blame] | 4708 | { |
Jeff Layton | 1daaae8 | 2012-03-21 06:30:40 -0400 | [diff] [blame] | 4709 | int rc; |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4710 | char *full_path; |
| 4711 | |
| 4712 | if (!server->ops->is_path_accessible) |
| 4713 | return -EOPNOTSUPP; |
| 4714 | |
| 4715 | /* |
| 4716 | * cifs_build_path_to_root works only when we have a valid tcon |
| 4717 | */ |
| 4718 | full_path = cifs_build_path_to_root(vol, cifs_sb, tcon, |
| 4719 | tcon->Flags & SMB_SHARE_IS_IN_DFS); |
| 4720 | if (full_path == NULL) |
| 4721 | return -ENOMEM; |
| 4722 | |
| 4723 | cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path); |
| 4724 | |
| 4725 | rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, |
| 4726 | full_path); |
| 4727 | if (rc != 0 && rc != -EREMOTE) { |
| 4728 | kfree(full_path); |
| 4729 | return rc; |
| 4730 | } |
| 4731 | |
| 4732 | if (rc != -EREMOTE) { |
| 4733 | rc = cifs_are_all_path_components_accessible(server, xid, tcon, |
Ronnie Sahlberg | ce465bf | 2019-07-11 13:46:58 +1000 | [diff] [blame] | 4734 | cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS); |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4735 | if (rc != 0) { |
Joe Perches | a0a3036 | 2020-04-14 22:42:53 -0700 | [diff] [blame] | 4736 | cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n"); |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4737 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; |
| 4738 | rc = 0; |
| 4739 | } |
| 4740 | } |
| 4741 | |
| 4742 | kfree(full_path); |
| 4743 | return rc; |
| 4744 | } |
| 4745 | |
| 4746 | #ifdef CONFIG_CIFS_DFS_UPCALL |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4747 | static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, |
| 4748 | struct cifs_ses **root_ses) |
Paulo Alcantara (SUSE) | 5bb30a4 | 2019-11-22 12:30:56 -0300 | [diff] [blame] | 4749 | { |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4750 | if (ses) { |
| 4751 | spin_lock(&cifs_tcp_ses_lock); |
| 4752 | ses->ses_count++; |
| 4753 | ses->tcon_ipc->remap = cifs_remap(cifs_sb); |
| 4754 | spin_unlock(&cifs_tcp_ses_lock); |
| 4755 | } |
| 4756 | *root_ses = ses; |
| 4757 | } |
| 4758 | |
| 4759 | static void put_root_ses(struct cifs_ses *ses) |
| 4760 | { |
| 4761 | if (ses) |
| 4762 | cifs_put_smb_ses(ses); |
| 4763 | } |
| 4764 | |
| 4765 | /* Check if a path component is remote and then update @dfs_path accordingly */ |
| 4766 | static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, |
| 4767 | const unsigned int xid, struct TCP_Server_Info *server, |
| 4768 | struct cifs_tcon *tcon, char **dfs_path) |
| 4769 | { |
| 4770 | char *path, *s; |
| 4771 | char sep = CIFS_DIR_SEP(cifs_sb), tmp; |
| 4772 | char *npath; |
| 4773 | int rc = 0; |
| 4774 | int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS; |
| 4775 | int skip = added_treename; |
| 4776 | |
| 4777 | path = cifs_build_path_to_root(vol, cifs_sb, tcon, added_treename); |
| 4778 | if (!path) |
| 4779 | return -ENOMEM; |
| 4780 | |
| 4781 | /* |
| 4782 | * Walk through the path components in @path and check if they're accessible. In case any of |
| 4783 | * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path |
| 4784 | * (NOT including the remaining components). |
| 4785 | */ |
| 4786 | s = path; |
| 4787 | do { |
| 4788 | /* skip separators */ |
| 4789 | while (*s && *s == sep) |
| 4790 | s++; |
| 4791 | if (!*s) |
| 4792 | break; |
| 4793 | /* next separator */ |
| 4794 | while (*s && *s != sep) |
| 4795 | s++; |
| 4796 | /* |
| 4797 | * if the treename is added, we then have to skip the first |
| 4798 | * part within the separators |
| 4799 | */ |
| 4800 | if (skip) { |
| 4801 | skip = 0; |
| 4802 | continue; |
| 4803 | } |
| 4804 | tmp = *s; |
| 4805 | *s = 0; |
| 4806 | rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path); |
| 4807 | if (rc && rc == -EREMOTE) { |
| 4808 | struct smb_vol v = {NULL}; |
| 4809 | /* if @path contains a tree name, skip it in the prefix path */ |
| 4810 | if (added_treename) { |
| 4811 | rc = cifs_parse_devname(path, &v); |
| 4812 | if (rc) |
| 4813 | break; |
| 4814 | rc = -EREMOTE; |
| 4815 | npath = build_unc_path_to_root(&v, cifs_sb, true); |
| 4816 | cifs_cleanup_volume_info_contents(&v); |
| 4817 | } else { |
| 4818 | v.UNC = vol->UNC; |
| 4819 | v.prepath = path + 1; |
| 4820 | npath = build_unc_path_to_root(&v, cifs_sb, true); |
| 4821 | } |
| 4822 | if (IS_ERR(npath)) { |
| 4823 | rc = PTR_ERR(npath); |
| 4824 | break; |
| 4825 | } |
| 4826 | kfree(*dfs_path); |
| 4827 | *dfs_path = npath; |
| 4828 | } |
| 4829 | *s = tmp; |
| 4830 | } while (rc == 0); |
| 4831 | |
| 4832 | kfree(path); |
| 4833 | return rc; |
Paulo Alcantara (SUSE) | 5bb30a4 | 2019-11-22 12:30:56 -0300 | [diff] [blame] | 4834 | } |
| 4835 | |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4836 | int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) |
| 4837 | { |
| 4838 | int rc = 0; |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 4839 | unsigned int xid; |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4840 | struct TCP_Server_Info *server = NULL; |
| 4841 | struct cifs_ses *ses = NULL, *root_ses = NULL; |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4842 | struct cifs_tcon *tcon = NULL; |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4843 | int count = 0; |
| 4844 | char *ref_path = NULL, *full_path = NULL; |
| 4845 | char *oldmnt = NULL; |
| 4846 | char *mntdata = NULL; |
Al Viro | dd85446 | 2011-06-17 08:24:42 -0400 | [diff] [blame] | 4847 | |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4848 | rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4849 | /* |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4850 | * Unconditionally try to get an DFS referral (even cached) to determine whether it is an |
| 4851 | * DFS mount. |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4852 | * |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4853 | * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem |
| 4854 | * to respond with PATH_NOT_COVERED to requests that include the prefix. |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4855 | */ |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4856 | if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), vol->UNC + 1, NULL, |
| 4857 | NULL)) { |
| 4858 | /* No DFS referral was returned. Looks like a regular share. */ |
| 4859 | if (rc) |
| 4860 | goto error; |
| 4861 | /* Check if it is fully accessible and then mount it */ |
| 4862 | rc = is_path_remote(cifs_sb, vol, xid, server, tcon); |
| 4863 | if (!rc) |
| 4864 | goto out; |
| 4865 | if (rc != -EREMOTE) |
| 4866 | goto error; |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4867 | } |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4868 | /* Save mount options */ |
| 4869 | mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL); |
| 4870 | if (!mntdata) { |
Paulo Alcantara (SUSE) | 5072010 | 2019-03-19 16:54:29 -0300 | [diff] [blame] | 4871 | rc = -ENOMEM; |
| 4872 | goto error; |
| 4873 | } |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4874 | /* Get path of DFS root */ |
| 4875 | ref_path = build_unc_path_to_root(vol, cifs_sb, false); |
| 4876 | if (IS_ERR(ref_path)) { |
| 4877 | rc = PTR_ERR(ref_path); |
| 4878 | ref_path = NULL; |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4879 | goto error; |
| 4880 | } |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4881 | |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4882 | set_root_ses(cifs_sb, ses, &root_ses); |
| 4883 | do { |
| 4884 | /* Save full path of last DFS path we used to resolve final target server */ |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4885 | kfree(full_path); |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4886 | full_path = build_unc_path_to_root(vol, cifs_sb, !!count); |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4887 | if (IS_ERR(full_path)) { |
| 4888 | rc = PTR_ERR(full_path); |
Dan Carpenter | 20b135e | 2020-08-05 12:52:07 +0300 | [diff] [blame] | 4889 | full_path = NULL; |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4890 | break; |
| 4891 | } |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4892 | /* Chase referral */ |
| 4893 | oldmnt = cifs_sb->mountdata; |
| 4894 | rc = expand_dfs_referral(xid, root_ses, vol, cifs_sb, ref_path + 1); |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4895 | if (rc) |
| 4896 | break; |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4897 | /* Connect to new DFS target only if we were redirected */ |
| 4898 | if (oldmnt != cifs_sb->mountdata) { |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4899 | mount_put_conns(cifs_sb, xid, server, ses, tcon); |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4900 | rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4901 | } |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4902 | if (rc && !server && !ses) { |
| 4903 | /* Failed to connect. Try to connect to other targets in the referral. */ |
| 4904 | rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, vol, root_ses, &xid, |
| 4905 | &server, &ses, &tcon); |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4906 | } |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4907 | if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses) |
| 4908 | break; |
| 4909 | if (!tcon) |
| 4910 | continue; |
| 4911 | /* Make sure that requests go through new root servers */ |
Paulo Alcantara | e183785 | 2020-08-27 11:20:19 -0300 | [diff] [blame] | 4912 | if (is_tcon_dfs(tcon)) { |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4913 | put_root_ses(root_ses); |
| 4914 | set_root_ses(cifs_sb, ses, &root_ses); |
| 4915 | } |
| 4916 | /* Check for remaining path components and then continue chasing them (-EREMOTE) */ |
| 4917 | rc = check_dfs_prepath(cifs_sb, vol, xid, server, tcon, &ref_path); |
| 4918 | /* Prevent recursion on broken link referrals */ |
| 4919 | if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS) |
| 4920 | rc = -ELOOP; |
| 4921 | } while (rc == -EREMOTE); |
Igor Mammedov | 1bfe73c | 2009-04-01 17:54:42 +0400 | [diff] [blame] | 4922 | |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 4923 | if (rc) |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4924 | goto error; |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4925 | put_root_ses(root_ses); |
| 4926 | root_ses = NULL; |
| 4927 | kfree(ref_path); |
| 4928 | ref_path = NULL; |
| 4929 | /* |
| 4930 | * Store DFS full path in both superblock and tree connect structures. |
| 4931 | * |
| 4932 | * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so |
| 4933 | * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS |
| 4934 | * links, the prefix path is included in both and may be changed during reconnect. See |
| 4935 | * cifs_tree_connect(). |
| 4936 | */ |
| 4937 | cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 4938 | if (!cifs_sb->origin_fullpath) { |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 4939 | rc = -ENOMEM; |
| 4940 | goto error; |
| 4941 | } |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4942 | spin_lock(&cifs_tcp_ses_lock); |
| 4943 | tcon->dfs_path = full_path; |
| 4944 | full_path = NULL; |
| 4945 | tcon->remap = cifs_remap(cifs_sb); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 4946 | spin_unlock(&cifs_tcp_ses_lock); |
| 4947 | |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4948 | /* Add original volume information for DFS cache to be used when refreshing referrals */ |
| 4949 | rc = dfs_cache_add_vol(mntdata, vol, cifs_sb->origin_fullpath); |
| 4950 | if (rc) |
Paulo Alcantara | e511d31 | 2018-11-14 17:16:44 -0200 | [diff] [blame] | 4951 | goto error; |
Aurelien Aptel | 5fc7fcd | 2018-11-16 16:13:25 +0100 | [diff] [blame] | 4952 | /* |
| 4953 | * After reconnecting to a different server, unique ids won't |
| 4954 | * match anymore, so we disable serverino. This prevents |
| 4955 | * dentry revalidation to think the dentry are stale (ESTALE). |
| 4956 | */ |
| 4957 | cifs_autodisable_serverino(cifs_sb); |
Paulo Alcantara (SUSE) | bacd704 | 2020-02-20 19:49:34 -0300 | [diff] [blame] | 4958 | /* |
| 4959 | * Force the use of prefix path to support failover on DFS paths that |
| 4960 | * resolve to targets that have different prefix paths. |
| 4961 | */ |
| 4962 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; |
| 4963 | kfree(cifs_sb->prepath); |
| 4964 | cifs_sb->prepath = vol->prepath; |
| 4965 | vol->prepath = NULL; |
| 4966 | |
Jeff Layton | 70fe7dc | 2007-11-16 22:21:07 +0000 | [diff] [blame] | 4967 | out: |
Pavel Shilovsky | 6d5786a | 2012-06-20 11:21:16 +0400 | [diff] [blame] | 4968 | free_xid(xid); |
Aurelien Aptel | d70e9fa | 2019-09-20 06:31:10 +0200 | [diff] [blame] | 4969 | cifs_try_adding_channels(ses); |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4970 | return mount_setup_tlink(cifs_sb, ses, tcon); |
| 4971 | |
| 4972 | error: |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4973 | kfree(ref_path); |
Paulo Alcantara | 4a367dc | 2018-11-14 16:53:52 -0200 | [diff] [blame] | 4974 | kfree(full_path); |
Paulo Alcantara | 7efd081 | 2020-07-21 09:36:44 -0300 | [diff] [blame] | 4975 | kfree(mntdata); |
| 4976 | kfree(cifs_sb->origin_fullpath); |
| 4977 | put_root_ses(root_ses); |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4978 | mount_put_conns(cifs_sb, xid, server, ses, tcon); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4979 | return rc; |
| 4980 | } |
Paulo Alcantara | 56c762e | 2018-11-14 13:03:14 -0200 | [diff] [blame] | 4981 | #else |
| 4982 | int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) |
| 4983 | { |
| 4984 | int rc = 0; |
| 4985 | unsigned int xid; |
| 4986 | struct cifs_ses *ses; |
| 4987 | struct cifs_tcon *tcon; |
| 4988 | struct TCP_Server_Info *server; |
| 4989 | |
| 4990 | rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); |
| 4991 | if (rc) |
| 4992 | goto error; |
| 4993 | |
| 4994 | if (tcon) { |
| 4995 | rc = is_path_remote(cifs_sb, vol, xid, server, tcon); |
| 4996 | if (rc == -EREMOTE) |
| 4997 | rc = -EOPNOTSUPP; |
| 4998 | if (rc) |
| 4999 | goto error; |
| 5000 | } |
| 5001 | |
| 5002 | free_xid(xid); |
| 5003 | |
| 5004 | return mount_setup_tlink(cifs_sb, ses, tcon); |
| 5005 | |
| 5006 | error: |
| 5007 | mount_put_conns(cifs_sb, xid, server, ses, tcon); |
| 5008 | return rc; |
| 5009 | } |
| 5010 | #endif |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5011 | |
Jeff Layton | 8d1bca3 | 2011-06-11 21:17:10 -0400 | [diff] [blame] | 5012 | /* |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 5013 | * Issue a TREE_CONNECT request. |
Jeff Layton | 8d1bca3 | 2011-06-11 21:17:10 -0400 | [diff] [blame] | 5014 | */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5015 | int |
Pavel Shilovsky | 2e6e02a | 2012-05-25 11:11:39 +0400 | [diff] [blame] | 5016 | CIFSTCon(const unsigned int xid, struct cifs_ses *ses, |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 5017 | const char *tree, struct cifs_tcon *tcon, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5018 | const struct nls_table *nls_codepage) |
| 5019 | { |
| 5020 | struct smb_hdr *smb_buffer; |
| 5021 | struct smb_hdr *smb_buffer_response; |
| 5022 | TCONX_REQ *pSMB; |
| 5023 | TCONX_RSP *pSMBr; |
| 5024 | unsigned char *bcc_ptr; |
| 5025 | int rc = 0; |
Jeff Layton | 690c522 | 2011-01-20 13:36:51 -0500 | [diff] [blame] | 5026 | int length; |
| 5027 | __u16 bytes_left, count; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5028 | |
| 5029 | if (ses == NULL) |
| 5030 | return -EIO; |
| 5031 | |
| 5032 | smb_buffer = cifs_buf_get(); |
Steve French | ca43e3b | 2009-09-01 17:20:50 +0000 | [diff] [blame] | 5033 | if (smb_buffer == NULL) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5034 | return -ENOMEM; |
Steve French | ca43e3b | 2009-09-01 17:20:50 +0000 | [diff] [blame] | 5035 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5036 | smb_buffer_response = smb_buffer; |
| 5037 | |
| 5038 | header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, |
| 5039 | NULL /*no tid */ , 4 /*wct */ ); |
Steve French | 1982c34 | 2005-08-17 12:38:22 -0700 | [diff] [blame] | 5040 | |
Pavel Shilovsky | 8825736 | 2012-05-23 14:01:59 +0400 | [diff] [blame] | 5041 | smb_buffer->Mid = get_next_mid(ses->server); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5042 | smb_buffer->Uid = ses->Suid; |
| 5043 | pSMB = (TCONX_REQ *) smb_buffer; |
| 5044 | pSMBr = (TCONX_RSP *) smb_buffer_response; |
| 5045 | |
| 5046 | pSMB->AndXCommand = 0xFF; |
| 5047 | pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5048 | bcc_ptr = &pSMB->Password[0]; |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 5049 | if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) { |
Steve French | eeac804 | 2006-01-13 21:34:58 -0800 | [diff] [blame] | 5050 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ |
Steve French | 7c7b25b | 2006-06-01 19:20:10 +0000 | [diff] [blame] | 5051 | *bcc_ptr = 0; /* password is null byte */ |
Steve French | eeac804 | 2006-01-13 21:34:58 -0800 | [diff] [blame] | 5052 | bcc_ptr++; /* skip password */ |
Steve French | 7c7b25b | 2006-06-01 19:20:10 +0000 | [diff] [blame] | 5053 | /* already aligned so no need to do it below */ |
Steve French | eeac804 | 2006-01-13 21:34:58 -0800 | [diff] [blame] | 5054 | } else { |
Shirish Pargaonkar | 540b2e3 | 2011-01-18 22:33:54 -0600 | [diff] [blame] | 5055 | pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE); |
Steve French | eeac804 | 2006-01-13 21:34:58 -0800 | [diff] [blame] | 5056 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos |
| 5057 | specified as required (when that support is added to |
| 5058 | the vfs in the future) as only NTLM or the much |
Steve French | 7c7b25b | 2006-06-01 19:20:10 +0000 | [diff] [blame] | 5059 | weaker LANMAN (which we do not send by default) is accepted |
Steve French | eeac804 | 2006-01-13 21:34:58 -0800 | [diff] [blame] | 5060 | by Samba (not sure whether other servers allow |
| 5061 | NTLMv2 password here) */ |
Steve French | 7c7b25b | 2006-06-01 19:20:10 +0000 | [diff] [blame] | 5062 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
Jeff Layton | 04912d6 | 2010-04-24 07:57:45 -0400 | [diff] [blame] | 5063 | if ((global_secflags & CIFSSEC_MAY_LANMAN) && |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 5064 | (ses->sectype == LANMAN)) |
Shirish Pargaonkar | d3ba50b | 2010-10-27 15:20:36 -0500 | [diff] [blame] | 5065 | calc_lanman_hash(tcon->password, ses->server->cryptkey, |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 5066 | ses->server->sec_mode & |
Jeff Layton | 4e53a3f | 2008-12-05 20:41:21 -0500 | [diff] [blame] | 5067 | SECMODE_PW_ENCRYPT ? true : false, |
| 5068 | bcc_ptr); |
Steve French | 7c7b25b | 2006-06-01 19:20:10 +0000 | [diff] [blame] | 5069 | else |
| 5070 | #endif /* CIFS_WEAK_PW_HASH */ |
Shirish Pargaonkar | ee2c925 | 2011-01-27 09:58:04 -0600 | [diff] [blame] | 5071 | rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, |
Shirish Pargaonkar | 9ef5992 | 2011-10-20 13:21:59 -0500 | [diff] [blame] | 5072 | bcc_ptr, nls_codepage); |
Steve French | f3a31a2 | 2015-03-26 19:23:20 -0500 | [diff] [blame] | 5073 | if (rc) { |
| 5074 | cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n", |
| 5075 | __func__, rc); |
| 5076 | cifs_buf_release(smb_buffer); |
| 5077 | return rc; |
| 5078 | } |
Steve French | eeac804 | 2006-01-13 21:34:58 -0800 | [diff] [blame] | 5079 | |
Shirish Pargaonkar | 540b2e3 | 2011-01-18 22:33:54 -0600 | [diff] [blame] | 5080 | bcc_ptr += CIFS_AUTH_RESP_SIZE; |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 5081 | if (ses->capabilities & CAP_UNICODE) { |
Steve French | 7c7b25b | 2006-06-01 19:20:10 +0000 | [diff] [blame] | 5082 | /* must align unicode strings */ |
| 5083 | *bcc_ptr = 0; /* null byte password */ |
| 5084 | bcc_ptr++; |
| 5085 | } |
Steve French | eeac804 | 2006-01-13 21:34:58 -0800 | [diff] [blame] | 5086 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5087 | |
Jeff Layton | 38d77c5 | 2013-05-26 07:01:00 -0400 | [diff] [blame] | 5088 | if (ses->server->sign) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5089 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
| 5090 | |
| 5091 | if (ses->capabilities & CAP_STATUS32) { |
| 5092 | smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; |
| 5093 | } |
| 5094 | if (ses->capabilities & CAP_DFS) { |
| 5095 | smb_buffer->Flags2 |= SMBFLG2_DFS; |
| 5096 | } |
| 5097 | if (ses->capabilities & CAP_UNICODE) { |
| 5098 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; |
| 5099 | length = |
Steve French | acbbb76 | 2012-01-18 22:32:33 -0600 | [diff] [blame] | 5100 | cifs_strtoUTF16((__le16 *) bcc_ptr, tree, |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 5101 | 6 /* max utf8 char length in bytes */ * |
Steve French | a878fb2 | 2006-05-30 18:04:19 +0000 | [diff] [blame] | 5102 | (/* server len*/ + 256 /* share len */), nls_codepage); |
| 5103 | bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5104 | bcc_ptr += 2; /* skip trailing null */ |
| 5105 | } else { /* ASCII */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5106 | strcpy(bcc_ptr, tree); |
| 5107 | bcc_ptr += strlen(tree) + 1; |
| 5108 | } |
| 5109 | strcpy(bcc_ptr, "?????"); |
| 5110 | bcc_ptr += strlen("?????"); |
| 5111 | bcc_ptr += 1; |
| 5112 | count = bcc_ptr - &pSMB->Password[0]; |
Qinglang Miao | 1a0e7f7 | 2020-07-25 16:56:01 +0800 | [diff] [blame] | 5113 | be32_add_cpu(&pSMB->hdr.smb_buf_length, count); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5114 | pSMB->ByteCount = cpu_to_le16(count); |
| 5115 | |
Steve French | 133672e | 2007-11-13 22:41:37 +0000 | [diff] [blame] | 5116 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, |
Jeff Layton | 7749981 | 2011-01-11 07:24:23 -0500 | [diff] [blame] | 5117 | 0); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5118 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5119 | /* above now done in SendReceive */ |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 5120 | if (rc == 0) { |
Steve French | 0e0d2cf | 2009-05-01 05:27:32 +0000 | [diff] [blame] | 5121 | bool is_unicode; |
| 5122 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5123 | tcon->tidStatus = CifsGood; |
Steve French | 3b79521 | 2008-11-13 19:45:32 +0000 | [diff] [blame] | 5124 | tcon->need_reconnect = false; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5125 | tcon->tid = smb_buffer_response->Tid; |
| 5126 | bcc_ptr = pByteArea(smb_buffer_response); |
Jeff Layton | 690c522 | 2011-01-20 13:36:51 -0500 | [diff] [blame] | 5127 | bytes_left = get_bcc(smb_buffer_response); |
Jeff Layton | cc20c03 | 2009-04-30 07:16:21 -0400 | [diff] [blame] | 5128 | length = strnlen(bcc_ptr, bytes_left - 2); |
Steve French | 0e0d2cf | 2009-05-01 05:27:32 +0000 | [diff] [blame] | 5129 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) |
| 5130 | is_unicode = true; |
| 5131 | else |
| 5132 | is_unicode = false; |
| 5133 | |
Jeff Layton | cc20c03 | 2009-04-30 07:16:21 -0400 | [diff] [blame] | 5134 | |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 5135 | /* skip service field (NB: this field is always ASCII) */ |
Steve French | 7f8ed42 | 2007-09-28 22:28:55 +0000 | [diff] [blame] | 5136 | if (length == 3) { |
| 5137 | if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && |
| 5138 | (bcc_ptr[2] == 'C')) { |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 5139 | cifs_dbg(FYI, "IPC connection\n"); |
Aurelien Aptel | b327a71 | 2018-01-24 13:46:10 +0100 | [diff] [blame] | 5140 | tcon->ipc = true; |
| 5141 | tcon->pipe = true; |
Steve French | 7f8ed42 | 2007-09-28 22:28:55 +0000 | [diff] [blame] | 5142 | } |
| 5143 | } else if (length == 2) { |
| 5144 | if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) { |
| 5145 | /* the most common case */ |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 5146 | cifs_dbg(FYI, "disk share connection\n"); |
Steve French | 7f8ed42 | 2007-09-28 22:28:55 +0000 | [diff] [blame] | 5147 | } |
| 5148 | } |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 5149 | bcc_ptr += length + 1; |
Jeff Layton | cc20c03 | 2009-04-30 07:16:21 -0400 | [diff] [blame] | 5150 | bytes_left -= (length + 1); |
Zhao Hongjiang | 46b51d0 | 2013-06-24 01:57:47 -0500 | [diff] [blame] | 5151 | strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); |
Jeff Layton | cc20c03 | 2009-04-30 07:16:21 -0400 | [diff] [blame] | 5152 | |
| 5153 | /* mostly informational -- no need to fail on error here */ |
Jeff Layton | 90a98b2 | 2009-07-20 13:40:52 -0400 | [diff] [blame] | 5154 | kfree(tcon->nativeFileSystem); |
Steve French | acbbb76 | 2012-01-18 22:32:33 -0600 | [diff] [blame] | 5155 | tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr, |
Steve French | 0e0d2cf | 2009-05-01 05:27:32 +0000 | [diff] [blame] | 5156 | bytes_left, is_unicode, |
Jeff Layton | cc20c03 | 2009-04-30 07:16:21 -0400 | [diff] [blame] | 5157 | nls_codepage); |
| 5158 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 5159 | cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem); |
Jeff Layton | cc20c03 | 2009-04-30 07:16:21 -0400 | [diff] [blame] | 5160 | |
Steve French | fb8c4b1 | 2007-07-10 01:16:18 +0000 | [diff] [blame] | 5161 | if ((smb_buffer_response->WordCount == 3) || |
Steve French | 1a4e15a | 2006-10-12 21:33:51 +0000 | [diff] [blame] | 5162 | (smb_buffer_response->WordCount == 7)) |
| 5163 | /* field is in same location */ |
Steve French | 3979877 | 2006-05-31 22:40:51 +0000 | [diff] [blame] | 5164 | tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); |
| 5165 | else |
| 5166 | tcon->Flags = 0; |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 5167 | cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5168 | } |
| 5169 | |
Mariusz Kozlowski | a8a11d3 | 2007-10-03 16:41:24 +0000 | [diff] [blame] | 5170 | cifs_buf_release(smb_buffer); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5171 | return rc; |
| 5172 | } |
| 5173 | |
Al Viro | 2e32cf5 | 2013-10-03 12:53:37 -0400 | [diff] [blame] | 5174 | static void delayed_free(struct rcu_head *p) |
| 5175 | { |
| 5176 | struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu); |
| 5177 | unload_nls(sbi->local_nls); |
| 5178 | kfree(sbi); |
| 5179 | } |
| 5180 | |
Al Viro | 2a9b995 | 2011-06-17 09:27:16 -0400 | [diff] [blame] | 5181 | void |
| 5182 | cifs_umount(struct cifs_sb_info *cifs_sb) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5183 | { |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5184 | struct rb_root *root = &cifs_sb->tlink_tree; |
| 5185 | struct rb_node *node; |
| 5186 | struct tcon_link *tlink; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5187 | |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 5188 | cancel_delayed_work_sync(&cifs_sb->prune_tlinks); |
| 5189 | |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5190 | spin_lock(&cifs_sb->tlink_tree_lock); |
| 5191 | while ((node = rb_first(root))) { |
| 5192 | tlink = rb_entry(node, struct tcon_link, tl_rbnode); |
| 5193 | cifs_get_tlink(tlink); |
| 5194 | clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); |
| 5195 | rb_erase(node, root); |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 5196 | |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5197 | spin_unlock(&cifs_sb->tlink_tree_lock); |
| 5198 | cifs_put_tlink(tlink); |
| 5199 | spin_lock(&cifs_sb->tlink_tree_lock); |
| 5200 | } |
| 5201 | spin_unlock(&cifs_sb->tlink_tree_lock); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5202 | |
Al Viro | d757d71 | 2011-06-17 09:42:43 -0400 | [diff] [blame] | 5203 | kfree(cifs_sb->mountdata); |
Aurelien Aptel | a6b5058 | 2016-05-25 19:59:09 +0200 | [diff] [blame] | 5204 | kfree(cifs_sb->prepath); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 5205 | #ifdef CONFIG_CIFS_DFS_UPCALL |
Paulo Alcantara | e511d31 | 2018-11-14 17:16:44 -0200 | [diff] [blame] | 5206 | dfs_cache_del_vol(cifs_sb->origin_fullpath); |
Paulo Alcantara | 93d5cb5 | 2018-11-14 17:13:25 -0200 | [diff] [blame] | 5207 | kfree(cifs_sb->origin_fullpath); |
| 5208 | #endif |
Al Viro | 2e32cf5 | 2013-10-03 12:53:37 -0400 | [diff] [blame] | 5209 | call_rcu(&cifs_sb->rcu, delayed_free); |
Steve French | 50c2f75 | 2007-07-13 00:33:32 +0000 | [diff] [blame] | 5210 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5211 | |
Pavel Shilovsky | 286170a | 2012-05-25 10:43:58 +0400 | [diff] [blame] | 5212 | int |
| 5213 | cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5214 | { |
| 5215 | int rc = 0; |
Aurelien Aptel | f6a6bf7 | 2019-09-20 06:22:14 +0200 | [diff] [blame] | 5216 | struct TCP_Server_Info *server = cifs_ses_server(ses); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5217 | |
Pavel Shilovsky | 286170a | 2012-05-25 10:43:58 +0400 | [diff] [blame] | 5218 | if (!server->ops->need_neg || !server->ops->negotiate) |
| 5219 | return -ENOSYS; |
| 5220 | |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 5221 | /* only send once per connect */ |
Pavel Shilovsky | 286170a | 2012-05-25 10:43:58 +0400 | [diff] [blame] | 5222 | if (!server->ops->need_neg(server)) |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 5223 | return 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5224 | |
Pavel Shilovsky | 286170a | 2012-05-25 10:43:58 +0400 | [diff] [blame] | 5225 | rc = server->ops->negotiate(xid, ses); |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 5226 | if (rc == 0) { |
| 5227 | spin_lock(&GlobalMid_Lock); |
Jeff Layton | 7fdbaa1 | 2011-06-10 16:14:57 -0400 | [diff] [blame] | 5228 | if (server->tcpStatus == CifsNeedNegotiate) |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 5229 | server->tcpStatus = CifsGood; |
| 5230 | else |
| 5231 | rc = -EHOSTDOWN; |
| 5232 | spin_unlock(&GlobalMid_Lock); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5233 | } |
Steve French | 26b994f | 2008-08-06 05:11:33 +0000 | [diff] [blame] | 5234 | |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 5235 | return rc; |
| 5236 | } |
Steve French | 26b994f | 2008-08-06 05:11:33 +0000 | [diff] [blame] | 5237 | |
Pavel Shilovsky | 58c45c5 | 2012-05-25 10:54:49 +0400 | [diff] [blame] | 5238 | int |
| 5239 | cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, |
| 5240 | struct nls_table *nls_info) |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 5241 | { |
Pavel Shilovsky | 58c45c5 | 2012-05-25 10:54:49 +0400 | [diff] [blame] | 5242 | int rc = -ENOSYS; |
Aurelien Aptel | f6a6bf7 | 2019-09-20 06:22:14 +0200 | [diff] [blame] | 5243 | struct TCP_Server_Info *server = cifs_ses_server(ses); |
Jeff Layton | 198b568 | 2010-04-24 07:57:48 -0400 | [diff] [blame] | 5244 | |
Aurelien Aptel | d70e9fa | 2019-09-20 06:31:10 +0200 | [diff] [blame] | 5245 | if (!ses->binding) { |
| 5246 | ses->capabilities = server->capabilities; |
| 5247 | if (linuxExtEnabled == 0) |
| 5248 | ses->capabilities &= (~server->vals->cap_unix); |
| 5249 | |
| 5250 | if (ses->auth_key.response) { |
| 5251 | cifs_dbg(FYI, "Free previous auth_key.response = %p\n", |
| 5252 | ses->auth_key.response); |
| 5253 | kfree(ses->auth_key.response); |
| 5254 | ses->auth_key.response = NULL; |
| 5255 | ses->auth_key.len = 0; |
| 5256 | } |
| 5257 | } |
Steve French | 20418ac | 2009-04-30 16:13:32 +0000 | [diff] [blame] | 5258 | |
Joe Perches | f96637b | 2013-05-04 22:12:25 -0500 | [diff] [blame] | 5259 | cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n", |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 5260 | server->sec_mode, server->capabilities, server->timeAdj); |
Jeff Layton | cb7691b | 2008-08-18 15:41:05 -0400 | [diff] [blame] | 5261 | |
Pavel Shilovsky | 58c45c5 | 2012-05-25 10:54:49 +0400 | [diff] [blame] | 5262 | if (server->ops->sess_setup) |
| 5263 | rc = server->ops->sess_setup(xid, ses, nls_info); |
| 5264 | |
Shirish Pargaonkar | d4e63bd | 2013-08-29 08:35:09 -0500 | [diff] [blame] | 5265 | if (rc) |
Ronnie Sahlberg | afe6f65 | 2019-08-28 17:15:35 +1000 | [diff] [blame] | 5266 | cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); |
Shirish Pargaonkar | 21e7339 | 2010-10-21 06:42:55 -0500 | [diff] [blame] | 5267 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5268 | return rc; |
| 5269 | } |
| 5270 | |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 5271 | static int |
| 5272 | cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) |
| 5273 | { |
Jeff Layton | 3f61822 | 2013-06-12 19:52:14 -0500 | [diff] [blame] | 5274 | vol->sectype = ses->sectype; |
| 5275 | |
| 5276 | /* krb5 is special, since we don't need username or pw */ |
| 5277 | if (vol->sectype == Kerberos) |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 5278 | return 0; |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 5279 | |
| 5280 | return cifs_set_cifscreds(vol, ses); |
| 5281 | } |
| 5282 | |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 5283 | static struct cifs_tcon * |
Eric W. Biederman | 6d4a083 | 2013-02-06 01:48:56 -0800 | [diff] [blame] | 5284 | cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5285 | { |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 5286 | int rc; |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 5287 | struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb); |
| 5288 | struct cifs_ses *ses; |
| 5289 | struct cifs_tcon *tcon = NULL; |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5290 | struct smb_vol *vol_info; |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5291 | |
| 5292 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); |
Dan Carpenter | 803ab97 | 2012-01-24 11:39:22 +0300 | [diff] [blame] | 5293 | if (vol_info == NULL) |
| 5294 | return ERR_PTR(-ENOMEM); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5295 | |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5296 | vol_info->local_nls = cifs_sb->local_nls; |
| 5297 | vol_info->linux_uid = fsuid; |
| 5298 | vol_info->cred_uid = fsuid; |
| 5299 | vol_info->UNC = master_tcon->treeName; |
| 5300 | vol_info->retry = master_tcon->retry; |
| 5301 | vol_info->nocase = master_tcon->nocase; |
Steve French | 3d4ef9a | 2018-04-25 22:19:09 -0500 | [diff] [blame] | 5302 | vol_info->nohandlecache = master_tcon->nohandlecache; |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5303 | vol_info->local_lease = master_tcon->local_lease; |
Paul Aurich | ad35f16 | 2020-06-26 12:58:07 -0700 | [diff] [blame] | 5304 | vol_info->no_lease = master_tcon->no_lease; |
Paul Aurich | 00dfbc2 | 2020-06-26 12:58:06 -0700 | [diff] [blame] | 5305 | vol_info->resilient = master_tcon->use_resilient; |
| 5306 | vol_info->persistent = master_tcon->use_persistent; |
Paul Aurich | 6b356f6c | 2020-06-26 12:58:08 -0700 | [diff] [blame] | 5307 | vol_info->handle_timeout = master_tcon->handle_timeout; |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5308 | vol_info->no_linux_ext = !master_tcon->unix_ext; |
Paul Aurich | 5391b8e | 2020-06-26 12:58:09 -0700 | [diff] [blame] | 5309 | vol_info->linux_ext = master_tcon->posix_extensions; |
Jeff Layton | 28e11bd | 2013-05-26 07:01:00 -0400 | [diff] [blame] | 5310 | vol_info->sectype = master_tcon->ses->sectype; |
| 5311 | vol_info->sign = master_tcon->ses->sign; |
Paul Aurich | cc15461 | 2020-06-26 12:58:05 -0700 | [diff] [blame] | 5312 | vol_info->seal = master_tcon->seal; |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5313 | |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 5314 | rc = cifs_set_vol_auth(vol_info, master_tcon->ses); |
| 5315 | if (rc) { |
| 5316 | tcon = ERR_PTR(rc); |
| 5317 | goto out; |
| 5318 | } |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5319 | |
| 5320 | /* get a reference for the same TCP session */ |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 5321 | spin_lock(&cifs_tcp_ses_lock); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5322 | ++master_tcon->ses->server->srv_count; |
Suresh Jayaraman | 3f9bcca | 2010-10-18 23:29:37 +0530 | [diff] [blame] | 5323 | spin_unlock(&cifs_tcp_ses_lock); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5324 | |
| 5325 | ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info); |
| 5326 | if (IS_ERR(ses)) { |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 5327 | tcon = (struct cifs_tcon *)ses; |
Pavel Shilovsky | 53e0e11 | 2016-11-04 11:50:31 -0700 | [diff] [blame] | 5328 | cifs_put_tcp_session(master_tcon->ses->server, 0); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5329 | goto out; |
| 5330 | } |
| 5331 | |
| 5332 | tcon = cifs_get_tcon(ses, vol_info); |
| 5333 | if (IS_ERR(tcon)) { |
| 5334 | cifs_put_smb_ses(ses); |
| 5335 | goto out; |
| 5336 | } |
| 5337 | |
Pavel Shilovsky | 29e20f9 | 2012-07-13 13:58:14 +0400 | [diff] [blame] | 5338 | if (cap_unix(ses)) |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5339 | reset_cifs_unix_caps(0, tcon, NULL, vol_info); |
Steve French | b326614 | 2018-05-20 23:41:10 -0500 | [diff] [blame] | 5340 | |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5341 | out: |
Jeff Layton | 8a8798a | 2012-01-17 16:09:15 -0500 | [diff] [blame] | 5342 | kfree(vol_info->username); |
Waiman Long | 453431a | 2020-08-06 23:18:13 -0700 | [diff] [blame] | 5343 | kfree_sensitive(vol_info->password); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5344 | kfree(vol_info); |
| 5345 | |
| 5346 | return tcon; |
| 5347 | } |
| 5348 | |
Steve French | 96daf2b | 2011-05-27 04:34:02 +0000 | [diff] [blame] | 5349 | struct cifs_tcon * |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5350 | cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) |
| 5351 | { |
| 5352 | return tlink_tcon(cifs_sb_master_tlink(cifs_sb)); |
| 5353 | } |
| 5354 | |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5355 | /* find and return a tlink with given uid */ |
| 5356 | static struct tcon_link * |
Eric W. Biederman | 6d4a083 | 2013-02-06 01:48:56 -0800 | [diff] [blame] | 5357 | tlink_rb_search(struct rb_root *root, kuid_t uid) |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5358 | { |
| 5359 | struct rb_node *node = root->rb_node; |
| 5360 | struct tcon_link *tlink; |
| 5361 | |
| 5362 | while (node) { |
| 5363 | tlink = rb_entry(node, struct tcon_link, tl_rbnode); |
| 5364 | |
Eric W. Biederman | 6d4a083 | 2013-02-06 01:48:56 -0800 | [diff] [blame] | 5365 | if (uid_gt(tlink->tl_uid, uid)) |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5366 | node = node->rb_left; |
Eric W. Biederman | 6d4a083 | 2013-02-06 01:48:56 -0800 | [diff] [blame] | 5367 | else if (uid_lt(tlink->tl_uid, uid)) |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5368 | node = node->rb_right; |
| 5369 | else |
| 5370 | return tlink; |
| 5371 | } |
| 5372 | return NULL; |
| 5373 | } |
| 5374 | |
| 5375 | /* insert a tcon_link into the tree */ |
| 5376 | static void |
| 5377 | tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink) |
| 5378 | { |
| 5379 | struct rb_node **new = &(root->rb_node), *parent = NULL; |
| 5380 | struct tcon_link *tlink; |
| 5381 | |
| 5382 | while (*new) { |
| 5383 | tlink = rb_entry(*new, struct tcon_link, tl_rbnode); |
| 5384 | parent = *new; |
| 5385 | |
Eric W. Biederman | 6d4a083 | 2013-02-06 01:48:56 -0800 | [diff] [blame] | 5386 | if (uid_gt(tlink->tl_uid, new_tlink->tl_uid)) |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5387 | new = &((*new)->rb_left); |
| 5388 | else |
| 5389 | new = &((*new)->rb_right); |
| 5390 | } |
| 5391 | |
| 5392 | rb_link_node(&new_tlink->tl_rbnode, parent, new); |
| 5393 | rb_insert_color(&new_tlink->tl_rbnode, root); |
| 5394 | } |
| 5395 | |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5396 | /* |
| 5397 | * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the |
| 5398 | * current task. |
| 5399 | * |
| 5400 | * If the superblock doesn't refer to a multiuser mount, then just return |
| 5401 | * the master tcon for the mount. |
| 5402 | * |
Suresh Jayaraman | 6ef933a | 2010-11-03 10:53:49 +0530 | [diff] [blame] | 5403 | * First, search the rbtree for an existing tcon for this fsuid. If one |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5404 | * exists, then check to see if it's pending construction. If it is then wait |
| 5405 | * for construction to complete. Once it's no longer pending, check to see if |
| 5406 | * it failed and either return an error or retry construction, depending on |
| 5407 | * the timeout. |
| 5408 | * |
| 5409 | * If one doesn't exist then insert a new tcon_link struct into the tree and |
| 5410 | * try to construct a new one. |
| 5411 | */ |
| 5412 | struct tcon_link * |
| 5413 | cifs_sb_tlink(struct cifs_sb_info *cifs_sb) |
| 5414 | { |
| 5415 | int ret; |
Eric W. Biederman | 6d4a083 | 2013-02-06 01:48:56 -0800 | [diff] [blame] | 5416 | kuid_t fsuid = current_fsuid(); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5417 | struct tcon_link *tlink, *newtlink; |
| 5418 | |
| 5419 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) |
| 5420 | return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb)); |
| 5421 | |
| 5422 | spin_lock(&cifs_sb->tlink_tree_lock); |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5423 | tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5424 | if (tlink) |
| 5425 | cifs_get_tlink(tlink); |
| 5426 | spin_unlock(&cifs_sb->tlink_tree_lock); |
| 5427 | |
| 5428 | if (tlink == NULL) { |
| 5429 | newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL); |
| 5430 | if (newtlink == NULL) |
| 5431 | return ERR_PTR(-ENOMEM); |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5432 | newtlink->tl_uid = fsuid; |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5433 | newtlink->tl_tcon = ERR_PTR(-EACCES); |
| 5434 | set_bit(TCON_LINK_PENDING, &newtlink->tl_flags); |
| 5435 | set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags); |
| 5436 | cifs_get_tlink(newtlink); |
| 5437 | |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5438 | spin_lock(&cifs_sb->tlink_tree_lock); |
| 5439 | /* was one inserted after previous search? */ |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5440 | tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5441 | if (tlink) { |
| 5442 | cifs_get_tlink(tlink); |
| 5443 | spin_unlock(&cifs_sb->tlink_tree_lock); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5444 | kfree(newtlink); |
| 5445 | goto wait_for_construction; |
| 5446 | } |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5447 | tlink = newtlink; |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5448 | tlink_rb_insert(&cifs_sb->tlink_tree, tlink); |
| 5449 | spin_unlock(&cifs_sb->tlink_tree_lock); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5450 | } else { |
| 5451 | wait_for_construction: |
| 5452 | ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING, |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5453 | TASK_INTERRUPTIBLE); |
| 5454 | if (ret) { |
| 5455 | cifs_put_tlink(tlink); |
NeilBrown | 7431620 | 2014-07-07 15:16:04 +1000 | [diff] [blame] | 5456 | return ERR_PTR(-ERESTARTSYS); |
Jeff Layton | 9d002df | 2010-10-06 19:51:11 -0400 | [diff] [blame] | 5457 | } |
| 5458 | |
| 5459 | /* if it's good, return it */ |
| 5460 | if (!IS_ERR(tlink->tl_tcon)) |
| 5461 | return tlink; |
| 5462 | |
| 5463 | /* return error if we tried this already recently */ |
| 5464 | if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) { |
| 5465 | cifs_put_tlink(tlink); |
| 5466 | return ERR_PTR(-EACCES); |
| 5467 | } |
| 5468 | |
| 5469 | if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags)) |
| 5470 | goto wait_for_construction; |
| 5471 | } |
| 5472 | |
| 5473 | tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid); |
| 5474 | clear_bit(TCON_LINK_PENDING, &tlink->tl_flags); |
| 5475 | wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING); |
| 5476 | |
| 5477 | if (IS_ERR(tlink->tl_tcon)) { |
| 5478 | cifs_put_tlink(tlink); |
| 5479 | return ERR_PTR(-EACCES); |
| 5480 | } |
| 5481 | |
| 5482 | return tlink; |
| 5483 | } |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 5484 | |
| 5485 | /* |
| 5486 | * periodic workqueue job that scans tcon_tree for a superblock and closes |
| 5487 | * out tcons. |
| 5488 | */ |
| 5489 | static void |
| 5490 | cifs_prune_tlinks(struct work_struct *work) |
| 5491 | { |
| 5492 | struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info, |
| 5493 | prune_tlinks.work); |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5494 | struct rb_root *root = &cifs_sb->tlink_tree; |
Colin Ian King | 37e12f5 | 2018-01-17 09:52:39 +0000 | [diff] [blame] | 5495 | struct rb_node *node; |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5496 | struct rb_node *tmp; |
| 5497 | struct tcon_link *tlink; |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 5498 | |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5499 | /* |
| 5500 | * Because we drop the spinlock in the loop in order to put the tlink |
| 5501 | * it's not guarded against removal of links from the tree. The only |
| 5502 | * places that remove entries from the tree are this function and |
| 5503 | * umounts. Because this function is non-reentrant and is canceled |
| 5504 | * before umount can proceed, this is safe. |
| 5505 | */ |
| 5506 | spin_lock(&cifs_sb->tlink_tree_lock); |
| 5507 | node = rb_first(root); |
| 5508 | while (node != NULL) { |
| 5509 | tmp = node; |
| 5510 | node = rb_next(tmp); |
| 5511 | tlink = rb_entry(tmp, struct tcon_link, tl_rbnode); |
| 5512 | |
| 5513 | if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) || |
| 5514 | atomic_read(&tlink->tl_count) != 0 || |
| 5515 | time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies)) |
| 5516 | continue; |
| 5517 | |
| 5518 | cifs_get_tlink(tlink); |
| 5519 | clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); |
| 5520 | rb_erase(tmp, root); |
| 5521 | |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 5522 | spin_unlock(&cifs_sb->tlink_tree_lock); |
Jeff Layton | b647c35 | 2010-10-28 11:16:44 -0400 | [diff] [blame] | 5523 | cifs_put_tlink(tlink); |
| 5524 | spin_lock(&cifs_sb->tlink_tree_lock); |
| 5525 | } |
| 5526 | spin_unlock(&cifs_sb->tlink_tree_lock); |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 5527 | |
Jeff Layton | da472fc | 2012-03-23 14:40:53 -0400 | [diff] [blame] | 5528 | queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, |
Jeff Layton | 2de970f | 2010-10-06 19:51:12 -0400 | [diff] [blame] | 5529 | TLINK_IDLE_EXPIRE); |
| 5530 | } |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5531 | |
| 5532 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 5533 | int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) |
| 5534 | { |
| 5535 | int rc; |
| 5536 | struct TCP_Server_Info *server = tcon->ses->server; |
| 5537 | const struct smb_version_operations *ops = server->ops; |
| 5538 | struct dfs_cache_tgt_list tl; |
| 5539 | struct dfs_cache_tgt_iterator *it = NULL; |
| 5540 | char *tree; |
| 5541 | const char *tcp_host; |
| 5542 | size_t tcp_host_len; |
| 5543 | const char *dfs_host; |
| 5544 | size_t dfs_host_len; |
Paulo Alcantara | 7548e1d | 2020-07-21 09:36:42 -0300 | [diff] [blame] | 5545 | char *share = NULL, *prefix = NULL; |
Paulo Alcantara | 11375a5 | 2020-07-21 09:36:43 -0300 | [diff] [blame] | 5546 | struct dfs_info3_param ref = {0}; |
| 5547 | bool isroot; |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5548 | |
| 5549 | tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); |
| 5550 | if (!tree) |
| 5551 | return -ENOMEM; |
| 5552 | |
| 5553 | if (!tcon->dfs_path) { |
| 5554 | if (tcon->ipc) { |
| 5555 | scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); |
| 5556 | rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); |
| 5557 | } else { |
| 5558 | rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); |
| 5559 | } |
| 5560 | goto out; |
| 5561 | } |
| 5562 | |
Paulo Alcantara | 11375a5 | 2020-07-21 09:36:43 -0300 | [diff] [blame] | 5563 | rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl); |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5564 | if (rc) |
| 5565 | goto out; |
Paulo Alcantara | 11375a5 | 2020-07-21 09:36:43 -0300 | [diff] [blame] | 5566 | isroot = ref.server_type == DFS_TYPE_ROOT; |
| 5567 | free_dfs_info_param(&ref); |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5568 | |
| 5569 | extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); |
| 5570 | |
| 5571 | for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) { |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5572 | bool target_match; |
| 5573 | |
Paulo Alcantara | 7548e1d | 2020-07-21 09:36:42 -0300 | [diff] [blame] | 5574 | kfree(share); |
| 5575 | kfree(prefix); |
Colin Ian King | c6a80e1 | 2020-07-31 18:13:42 +0100 | [diff] [blame] | 5576 | share = NULL; |
| 5577 | prefix = NULL; |
Paulo Alcantara | 7548e1d | 2020-07-21 09:36:42 -0300 | [diff] [blame] | 5578 | |
| 5579 | rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix); |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5580 | if (rc) { |
| 5581 | cifs_dbg(VFS, "%s: failed to parse target share %d\n", |
| 5582 | __func__, rc); |
| 5583 | continue; |
| 5584 | } |
| 5585 | |
| 5586 | extract_unc_hostname(share, &dfs_host, &dfs_host_len); |
| 5587 | |
| 5588 | if (dfs_host_len != tcp_host_len |
| 5589 | || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { |
| 5590 | cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len, |
| 5591 | dfs_host, (int)tcp_host_len, tcp_host); |
| 5592 | |
| 5593 | rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match); |
| 5594 | if (rc) { |
| 5595 | cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc); |
| 5596 | break; |
| 5597 | } |
| 5598 | |
| 5599 | if (!target_match) { |
| 5600 | cifs_dbg(FYI, "%s: skipping target\n", __func__); |
| 5601 | continue; |
| 5602 | } |
| 5603 | } |
| 5604 | |
| 5605 | if (tcon->ipc) { |
Paulo Alcantara | 7548e1d | 2020-07-21 09:36:42 -0300 | [diff] [blame] | 5606 | scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share); |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5607 | rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); |
| 5608 | } else { |
Paulo Alcantara | 7548e1d | 2020-07-21 09:36:42 -0300 | [diff] [blame] | 5609 | scnprintf(tree, MAX_TREE_SIZE, "\\%s", share); |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5610 | rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); |
Paulo Alcantara | 11375a5 | 2020-07-21 09:36:43 -0300 | [diff] [blame] | 5611 | /* Only handle prefix paths of DFS link targets */ |
| 5612 | if (!rc && !isroot) { |
Paulo Alcantara | 7548e1d | 2020-07-21 09:36:42 -0300 | [diff] [blame] | 5613 | rc = update_super_prepath(tcon, prefix); |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5614 | break; |
| 5615 | } |
| 5616 | } |
| 5617 | if (rc == -EREMOTE) |
| 5618 | break; |
| 5619 | } |
| 5620 | |
Paulo Alcantara | 7548e1d | 2020-07-21 09:36:42 -0300 | [diff] [blame] | 5621 | kfree(share); |
| 5622 | kfree(prefix); |
| 5623 | |
Stefan Metzmacher | 565674d | 2020-07-21 09:36:38 -0300 | [diff] [blame] | 5624 | if (!rc) { |
| 5625 | if (it) |
| 5626 | rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it); |
| 5627 | else |
| 5628 | rc = -ENOENT; |
| 5629 | } |
| 5630 | dfs_cache_free_tgts(&tl); |
| 5631 | out: |
| 5632 | kfree(tree); |
| 5633 | return rc; |
| 5634 | } |
| 5635 | #else |
| 5636 | int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) |
| 5637 | { |
| 5638 | const struct smb_version_operations *ops = tcon->ses->server->ops; |
| 5639 | |
| 5640 | return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); |
| 5641 | } |
| 5642 | #endif |