138c8a9a5SSteve French // SPDX-License-Identifier: LGPL-2.1
238c8a9a5SSteve French /*
338c8a9a5SSteve French *
438c8a9a5SSteve French * Copyright (C) International Business Machines Corp., 2002,2008
538c8a9a5SSteve French * Author(s): Steve French (sfrench@us.ibm.com)
638c8a9a5SSteve French *
738c8a9a5SSteve French */
838c8a9a5SSteve French
938c8a9a5SSteve French #include <linux/slab.h>
1038c8a9a5SSteve French #include <linux/ctype.h>
1138c8a9a5SSteve French #include <linux/mempool.h>
1238c8a9a5SSteve French #include <linux/vmalloc.h>
1338c8a9a5SSteve French #include "cifspdu.h"
1438c8a9a5SSteve French #include "cifsglob.h"
1538c8a9a5SSteve French #include "cifsproto.h"
1638c8a9a5SSteve French #include "cifs_debug.h"
1738c8a9a5SSteve French #include "smberr.h"
1838c8a9a5SSteve French #include "nterr.h"
1938c8a9a5SSteve French #include "cifs_unicode.h"
2038c8a9a5SSteve French #include "smb2pdu.h"
2138c8a9a5SSteve French #include "cifsfs.h"
2238c8a9a5SSteve French #ifdef CONFIG_CIFS_DFS_UPCALL
2338c8a9a5SSteve French #include "dns_resolve.h"
2438c8a9a5SSteve French #include "dfs_cache.h"
2538c8a9a5SSteve French #include "dfs.h"
2638c8a9a5SSteve French #endif
2738c8a9a5SSteve French #include "fs_context.h"
2838c8a9a5SSteve French #include "cached_dir.h"
2938c8a9a5SSteve French
3038c8a9a5SSteve French /* The xid serves as a useful identifier for each incoming vfs request,
3138c8a9a5SSteve French in a similar way to the mid which is useful to track each sent smb,
3238c8a9a5SSteve French and CurrentXid can also provide a running counter (although it
3338c8a9a5SSteve French will eventually wrap past zero) of the total vfs operations handled
3438c8a9a5SSteve French since the cifs fs was mounted */
3538c8a9a5SSteve French
3638c8a9a5SSteve French unsigned int
_get_xid(void)3738c8a9a5SSteve French _get_xid(void)
3838c8a9a5SSteve French {
3938c8a9a5SSteve French unsigned int xid;
4038c8a9a5SSteve French
4138c8a9a5SSteve French spin_lock(&GlobalMid_Lock);
4238c8a9a5SSteve French GlobalTotalActiveXid++;
4338c8a9a5SSteve French
4438c8a9a5SSteve French /* keep high water mark for number of simultaneous ops in filesystem */
4538c8a9a5SSteve French if (GlobalTotalActiveXid > GlobalMaxActiveXid)
4638c8a9a5SSteve French GlobalMaxActiveXid = GlobalTotalActiveXid;
4738c8a9a5SSteve French if (GlobalTotalActiveXid > 65000)
4838c8a9a5SSteve French cifs_dbg(FYI, "warning: more than 65000 requests active\n");
4938c8a9a5SSteve French xid = GlobalCurrentXid++;
5038c8a9a5SSteve French spin_unlock(&GlobalMid_Lock);
5138c8a9a5SSteve French return xid;
5238c8a9a5SSteve French }
5338c8a9a5SSteve French
5438c8a9a5SSteve French void
_free_xid(unsigned int xid)5538c8a9a5SSteve French _free_xid(unsigned int xid)
5638c8a9a5SSteve French {
5738c8a9a5SSteve French spin_lock(&GlobalMid_Lock);
5838c8a9a5SSteve French /* if (GlobalTotalActiveXid == 0)
5938c8a9a5SSteve French BUG(); */
6038c8a9a5SSteve French GlobalTotalActiveXid--;
6138c8a9a5SSteve French spin_unlock(&GlobalMid_Lock);
6238c8a9a5SSteve French }
6338c8a9a5SSteve French
6438c8a9a5SSteve French struct cifs_ses *
sesInfoAlloc(void)6538c8a9a5SSteve French sesInfoAlloc(void)
6638c8a9a5SSteve French {
6738c8a9a5SSteve French struct cifs_ses *ret_buf;
6838c8a9a5SSteve French
6938c8a9a5SSteve French ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL);
7038c8a9a5SSteve French if (ret_buf) {
7138c8a9a5SSteve French atomic_inc(&sesInfoAllocCount);
7238c8a9a5SSteve French spin_lock_init(&ret_buf->ses_lock);
7338c8a9a5SSteve French ret_buf->ses_status = SES_NEW;
7438c8a9a5SSteve French ++ret_buf->ses_count;
7538c8a9a5SSteve French INIT_LIST_HEAD(&ret_buf->smb_ses_list);
7638c8a9a5SSteve French INIT_LIST_HEAD(&ret_buf->tcon_list);
7738c8a9a5SSteve French mutex_init(&ret_buf->session_mutex);
7838c8a9a5SSteve French spin_lock_init(&ret_buf->iface_lock);
7938c8a9a5SSteve French INIT_LIST_HEAD(&ret_buf->iface_list);
8038c8a9a5SSteve French spin_lock_init(&ret_buf->chan_lock);
8138c8a9a5SSteve French }
8238c8a9a5SSteve French return ret_buf;
8338c8a9a5SSteve French }
8438c8a9a5SSteve French
8538c8a9a5SSteve French void
sesInfoFree(struct cifs_ses * buf_to_free)8638c8a9a5SSteve French sesInfoFree(struct cifs_ses *buf_to_free)
8738c8a9a5SSteve French {
8838c8a9a5SSteve French struct cifs_server_iface *iface = NULL, *niface = NULL;
8938c8a9a5SSteve French
9038c8a9a5SSteve French if (buf_to_free == NULL) {
9138c8a9a5SSteve French cifs_dbg(FYI, "Null buffer passed to sesInfoFree\n");
9238c8a9a5SSteve French return;
9338c8a9a5SSteve French }
9438c8a9a5SSteve French
95a43f95fdSWinston Wen unload_nls(buf_to_free->local_nls);
9638c8a9a5SSteve French atomic_dec(&sesInfoAllocCount);
9738c8a9a5SSteve French kfree(buf_to_free->serverOS);
9838c8a9a5SSteve French kfree(buf_to_free->serverDomain);
9938c8a9a5SSteve French kfree(buf_to_free->serverNOS);
10038c8a9a5SSteve French kfree_sensitive(buf_to_free->password);
10108bedfbcSSteve French kfree_sensitive(buf_to_free->password2);
10238c8a9a5SSteve French kfree(buf_to_free->user_name);
10338c8a9a5SSteve French kfree(buf_to_free->domainName);
10438c8a9a5SSteve French kfree_sensitive(buf_to_free->auth_key.response);
10538c8a9a5SSteve French spin_lock(&buf_to_free->iface_lock);
10638c8a9a5SSteve French list_for_each_entry_safe(iface, niface, &buf_to_free->iface_list,
10738c8a9a5SSteve French iface_head)
10838c8a9a5SSteve French kref_put(&iface->refcount, release_iface);
10938c8a9a5SSteve French spin_unlock(&buf_to_free->iface_lock);
11038c8a9a5SSteve French kfree_sensitive(buf_to_free);
11138c8a9a5SSteve French }
11238c8a9a5SSteve French
11338c8a9a5SSteve French struct cifs_tcon *
tcon_info_alloc(bool dir_leases_enabled,enum smb3_tcon_ref_trace trace)11407e76ea1SDavid Howells tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace)
11538c8a9a5SSteve French {
11638c8a9a5SSteve French struct cifs_tcon *ret_buf;
11707e76ea1SDavid Howells static atomic_t tcon_debug_id;
11838c8a9a5SSteve French
11938c8a9a5SSteve French ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
12038c8a9a5SSteve French if (!ret_buf)
12138c8a9a5SSteve French return NULL;
1222da338ffSSteve French
1232da338ffSSteve French if (dir_leases_enabled == true) {
12438c8a9a5SSteve French ret_buf->cfids = init_cached_dirs();
12538c8a9a5SSteve French if (!ret_buf->cfids) {
12638c8a9a5SSteve French kfree(ret_buf);
12738c8a9a5SSteve French return NULL;
12838c8a9a5SSteve French }
1292da338ffSSteve French }
1302da338ffSSteve French /* else ret_buf->cfids is already set to NULL above */
13138c8a9a5SSteve French
13238c8a9a5SSteve French atomic_inc(&tconInfoAllocCount);
13338c8a9a5SSteve French ret_buf->status = TID_NEW;
13407e76ea1SDavid Howells ret_buf->debug_id = atomic_inc_return(&tcon_debug_id);
13507e76ea1SDavid Howells ret_buf->tc_count = 1;
13638c8a9a5SSteve French spin_lock_init(&ret_buf->tc_lock);
13738c8a9a5SSteve French INIT_LIST_HEAD(&ret_buf->openFileList);
13838c8a9a5SSteve French INIT_LIST_HEAD(&ret_buf->tcon_list);
13938c8a9a5SSteve French spin_lock_init(&ret_buf->open_file_lock);
14038c8a9a5SSteve French spin_lock_init(&ret_buf->stat_lock);
14138c8a9a5SSteve French atomic_set(&ret_buf->num_local_opens, 0);
14238c8a9a5SSteve French atomic_set(&ret_buf->num_remote_opens, 0);
143441786beSSteve French ret_buf->stats_from_time = ktime_get_real_seconds();
1444a5c16d0SDavid Howells #ifdef CONFIG_CIFS_FSCACHE
1454a5c16d0SDavid Howells mutex_init(&ret_buf->fscache_lock);
1464a5c16d0SDavid Howells #endif
14707e76ea1SDavid Howells trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace);
14838c8a9a5SSteve French
14938c8a9a5SSteve French return ret_buf;
15038c8a9a5SSteve French }
15138c8a9a5SSteve French
15238c8a9a5SSteve French void
tconInfoFree(struct cifs_tcon * tcon,enum smb3_tcon_ref_trace trace)15307e76ea1SDavid Howells tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
15438c8a9a5SSteve French {
15538c8a9a5SSteve French if (tcon == NULL) {
15638c8a9a5SSteve French cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
15738c8a9a5SSteve French return;
15838c8a9a5SSteve French }
15907e76ea1SDavid Howells trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace);
16038c8a9a5SSteve French free_cached_dirs(tcon->cfids);
16138c8a9a5SSteve French atomic_dec(&tconInfoAllocCount);
16238c8a9a5SSteve French kfree(tcon->nativeFileSystem);
16338c8a9a5SSteve French kfree_sensitive(tcon->password);
1643ae872deSPaulo Alcantara kfree(tcon->origin_fullpath);
16538c8a9a5SSteve French kfree(tcon);
16638c8a9a5SSteve French }
16738c8a9a5SSteve French
16838c8a9a5SSteve French struct smb_hdr *
cifs_buf_get(void)16938c8a9a5SSteve French cifs_buf_get(void)
17038c8a9a5SSteve French {
17138c8a9a5SSteve French struct smb_hdr *ret_buf = NULL;
17238c8a9a5SSteve French /*
17338c8a9a5SSteve French * SMB2 header is bigger than CIFS one - no problems to clean some
17438c8a9a5SSteve French * more bytes for CIFS.
17538c8a9a5SSteve French */
17638c8a9a5SSteve French size_t buf_size = sizeof(struct smb2_hdr);
17738c8a9a5SSteve French
17838c8a9a5SSteve French /*
17938c8a9a5SSteve French * We could use negotiated size instead of max_msgsize -
18038c8a9a5SSteve French * but it may be more efficient to always alloc same size
18138c8a9a5SSteve French * albeit slightly larger than necessary and maxbuffersize
18238c8a9a5SSteve French * defaults to this and can not be bigger.
18338c8a9a5SSteve French */
18438c8a9a5SSteve French ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS);
18538c8a9a5SSteve French
18638c8a9a5SSteve French /* clear the first few header bytes */
18738c8a9a5SSteve French /* for most paths, more is cleared in header_assemble */
18838c8a9a5SSteve French memset(ret_buf, 0, buf_size + 3);
18938c8a9a5SSteve French atomic_inc(&buf_alloc_count);
19038c8a9a5SSteve French #ifdef CONFIG_CIFS_STATS2
19138c8a9a5SSteve French atomic_inc(&total_buf_alloc_count);
19238c8a9a5SSteve French #endif /* CONFIG_CIFS_STATS2 */
19338c8a9a5SSteve French
19438c8a9a5SSteve French return ret_buf;
19538c8a9a5SSteve French }
19638c8a9a5SSteve French
19738c8a9a5SSteve French void
cifs_buf_release(void * buf_to_free)19838c8a9a5SSteve French cifs_buf_release(void *buf_to_free)
19938c8a9a5SSteve French {
20038c8a9a5SSteve French if (buf_to_free == NULL) {
20138c8a9a5SSteve French /* cifs_dbg(FYI, "Null buffer passed to cifs_buf_release\n");*/
20238c8a9a5SSteve French return;
20338c8a9a5SSteve French }
20438c8a9a5SSteve French mempool_free(buf_to_free, cifs_req_poolp);
20538c8a9a5SSteve French
20638c8a9a5SSteve French atomic_dec(&buf_alloc_count);
20738c8a9a5SSteve French return;
20838c8a9a5SSteve French }
20938c8a9a5SSteve French
21038c8a9a5SSteve French struct smb_hdr *
cifs_small_buf_get(void)21138c8a9a5SSteve French cifs_small_buf_get(void)
21238c8a9a5SSteve French {
21338c8a9a5SSteve French struct smb_hdr *ret_buf = NULL;
21438c8a9a5SSteve French
21538c8a9a5SSteve French /* We could use negotiated size instead of max_msgsize -
21638c8a9a5SSteve French but it may be more efficient to always alloc same size
21738c8a9a5SSteve French albeit slightly larger than necessary and maxbuffersize
21838c8a9a5SSteve French defaults to this and can not be bigger */
21938c8a9a5SSteve French ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS);
22038c8a9a5SSteve French /* No need to clear memory here, cleared in header assemble */
22138c8a9a5SSteve French /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
22238c8a9a5SSteve French atomic_inc(&small_buf_alloc_count);
22338c8a9a5SSteve French #ifdef CONFIG_CIFS_STATS2
22438c8a9a5SSteve French atomic_inc(&total_small_buf_alloc_count);
22538c8a9a5SSteve French #endif /* CONFIG_CIFS_STATS2 */
22638c8a9a5SSteve French
22738c8a9a5SSteve French return ret_buf;
22838c8a9a5SSteve French }
22938c8a9a5SSteve French
23038c8a9a5SSteve French void
cifs_small_buf_release(void * buf_to_free)23138c8a9a5SSteve French cifs_small_buf_release(void *buf_to_free)
23238c8a9a5SSteve French {
23338c8a9a5SSteve French
23438c8a9a5SSteve French if (buf_to_free == NULL) {
23538c8a9a5SSteve French cifs_dbg(FYI, "Null buffer passed to cifs_small_buf_release\n");
23638c8a9a5SSteve French return;
23738c8a9a5SSteve French }
23838c8a9a5SSteve French mempool_free(buf_to_free, cifs_sm_req_poolp);
23938c8a9a5SSteve French
24038c8a9a5SSteve French atomic_dec(&small_buf_alloc_count);
24138c8a9a5SSteve French return;
24238c8a9a5SSteve French }
24338c8a9a5SSteve French
24438c8a9a5SSteve French void
free_rsp_buf(int resp_buftype,void * rsp)24538c8a9a5SSteve French free_rsp_buf(int resp_buftype, void *rsp)
24638c8a9a5SSteve French {
24738c8a9a5SSteve French if (resp_buftype == CIFS_SMALL_BUFFER)
24838c8a9a5SSteve French cifs_small_buf_release(rsp);
24938c8a9a5SSteve French else if (resp_buftype == CIFS_LARGE_BUFFER)
25038c8a9a5SSteve French cifs_buf_release(rsp);
25138c8a9a5SSteve French }
25238c8a9a5SSteve French
25338c8a9a5SSteve French /* NB: MID can not be set if treeCon not passed in, in that
25438c8a9a5SSteve French case it is responsbility of caller to set the mid */
25538c8a9a5SSteve French void
header_assemble(struct smb_hdr * buffer,char smb_command,const struct cifs_tcon * treeCon,int word_count)25638c8a9a5SSteve French header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
25738c8a9a5SSteve French const struct cifs_tcon *treeCon, int word_count
25838c8a9a5SSteve French /* length of fixed section (word count) in two byte units */)
25938c8a9a5SSteve French {
26038c8a9a5SSteve French char *temp = (char *) buffer;
26138c8a9a5SSteve French
26238c8a9a5SSteve French memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
26338c8a9a5SSteve French
26438c8a9a5SSteve French buffer->smb_buf_length = cpu_to_be32(
26538c8a9a5SSteve French (2 * word_count) + sizeof(struct smb_hdr) -
26638c8a9a5SSteve French 4 /* RFC 1001 length field does not count */ +
26738c8a9a5SSteve French 2 /* for bcc field itself */) ;
26838c8a9a5SSteve French
26938c8a9a5SSteve French buffer->Protocol[0] = 0xFF;
27038c8a9a5SSteve French buffer->Protocol[1] = 'S';
27138c8a9a5SSteve French buffer->Protocol[2] = 'M';
27238c8a9a5SSteve French buffer->Protocol[3] = 'B';
27338c8a9a5SSteve French buffer->Command = smb_command;
27438c8a9a5SSteve French buffer->Flags = 0x00; /* case sensitive */
27538c8a9a5SSteve French buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
27638c8a9a5SSteve French buffer->Pid = cpu_to_le16((__u16)current->tgid);
27738c8a9a5SSteve French buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
27838c8a9a5SSteve French if (treeCon) {
27938c8a9a5SSteve French buffer->Tid = treeCon->tid;
28038c8a9a5SSteve French if (treeCon->ses) {
28138c8a9a5SSteve French if (treeCon->ses->capabilities & CAP_UNICODE)
28238c8a9a5SSteve French buffer->Flags2 |= SMBFLG2_UNICODE;
28338c8a9a5SSteve French if (treeCon->ses->capabilities & CAP_STATUS32)
28438c8a9a5SSteve French buffer->Flags2 |= SMBFLG2_ERR_STATUS;
28538c8a9a5SSteve French
28638c8a9a5SSteve French /* Uid is not converted */
28738c8a9a5SSteve French buffer->Uid = treeCon->ses->Suid;
28838c8a9a5SSteve French if (treeCon->ses->server)
28938c8a9a5SSteve French buffer->Mid = get_next_mid(treeCon->ses->server);
29038c8a9a5SSteve French }
29138c8a9a5SSteve French if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
29238c8a9a5SSteve French buffer->Flags2 |= SMBFLG2_DFS;
29338c8a9a5SSteve French if (treeCon->nocase)
29438c8a9a5SSteve French buffer->Flags |= SMBFLG_CASELESS;
29538c8a9a5SSteve French if ((treeCon->ses) && (treeCon->ses->server))
29638c8a9a5SSteve French if (treeCon->ses->server->sign)
29738c8a9a5SSteve French buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
29838c8a9a5SSteve French }
29938c8a9a5SSteve French
30038c8a9a5SSteve French /* endian conversion of flags is now done just before sending */
30138c8a9a5SSteve French buffer->WordCount = (char) word_count;
30238c8a9a5SSteve French return;
30338c8a9a5SSteve French }
30438c8a9a5SSteve French
30538c8a9a5SSteve French static int
check_smb_hdr(struct smb_hdr * smb)30638c8a9a5SSteve French check_smb_hdr(struct smb_hdr *smb)
30738c8a9a5SSteve French {
30838c8a9a5SSteve French /* does it have the right SMB "signature" ? */
30938c8a9a5SSteve French if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
31038c8a9a5SSteve French cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
31138c8a9a5SSteve French *(unsigned int *)smb->Protocol);
31238c8a9a5SSteve French return 1;
31338c8a9a5SSteve French }
31438c8a9a5SSteve French
31538c8a9a5SSteve French /* if it's a response then accept */
31638c8a9a5SSteve French if (smb->Flags & SMBFLG_RESPONSE)
31738c8a9a5SSteve French return 0;
31838c8a9a5SSteve French
31938c8a9a5SSteve French /* only one valid case where server sends us request */
32038c8a9a5SSteve French if (smb->Command == SMB_COM_LOCKING_ANDX)
32138c8a9a5SSteve French return 0;
32238c8a9a5SSteve French
32338c8a9a5SSteve French cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
32438c8a9a5SSteve French get_mid(smb));
32538c8a9a5SSteve French return 1;
32638c8a9a5SSteve French }
32738c8a9a5SSteve French
32838c8a9a5SSteve French int
checkSMB(char * buf,unsigned int total_read,struct TCP_Server_Info * server)32938c8a9a5SSteve French checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
33038c8a9a5SSteve French {
33138c8a9a5SSteve French struct smb_hdr *smb = (struct smb_hdr *)buf;
33238c8a9a5SSteve French __u32 rfclen = be32_to_cpu(smb->smb_buf_length);
33338c8a9a5SSteve French __u32 clc_len; /* calculated length */
33438c8a9a5SSteve French cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
33538c8a9a5SSteve French total_read, rfclen);
33638c8a9a5SSteve French
33738c8a9a5SSteve French /* is this frame too small to even get to a BCC? */
33838c8a9a5SSteve French if (total_read < 2 + sizeof(struct smb_hdr)) {
33938c8a9a5SSteve French if ((total_read >= sizeof(struct smb_hdr) - 1)
34038c8a9a5SSteve French && (smb->Status.CifsError != 0)) {
34138c8a9a5SSteve French /* it's an error return */
34238c8a9a5SSteve French smb->WordCount = 0;
34338c8a9a5SSteve French /* some error cases do not return wct and bcc */
34438c8a9a5SSteve French return 0;
34538c8a9a5SSteve French } else if ((total_read == sizeof(struct smb_hdr) + 1) &&
34638c8a9a5SSteve French (smb->WordCount == 0)) {
34738c8a9a5SSteve French char *tmp = (char *)smb;
34838c8a9a5SSteve French /* Need to work around a bug in two servers here */
34938c8a9a5SSteve French /* First, check if the part of bcc they sent was zero */
35038c8a9a5SSteve French if (tmp[sizeof(struct smb_hdr)] == 0) {
35138c8a9a5SSteve French /* some servers return only half of bcc
35238c8a9a5SSteve French * on simple responses (wct, bcc both zero)
35338c8a9a5SSteve French * in particular have seen this on
35438c8a9a5SSteve French * ulogoffX and FindClose. This leaves
35538c8a9a5SSteve French * one byte of bcc potentially unitialized
35638c8a9a5SSteve French */
35738c8a9a5SSteve French /* zero rest of bcc */
35838c8a9a5SSteve French tmp[sizeof(struct smb_hdr)+1] = 0;
35938c8a9a5SSteve French return 0;
36038c8a9a5SSteve French }
36138c8a9a5SSteve French cifs_dbg(VFS, "rcvd invalid byte count (bcc)\n");
36238c8a9a5SSteve French } else {
36338c8a9a5SSteve French cifs_dbg(VFS, "Length less than smb header size\n");
36438c8a9a5SSteve French }
36538c8a9a5SSteve French return -EIO;
366ac48fcefSPaulo Alcantara } else if (total_read < sizeof(*smb) + 2 * smb->WordCount) {
367ac48fcefSPaulo Alcantara cifs_dbg(VFS, "%s: can't read BCC due to invalid WordCount(%u)\n",
368ac48fcefSPaulo Alcantara __func__, smb->WordCount);
369ac48fcefSPaulo Alcantara return -EIO;
37038c8a9a5SSteve French }
37138c8a9a5SSteve French
37238c8a9a5SSteve French /* otherwise, there is enough to get to the BCC */
37338c8a9a5SSteve French if (check_smb_hdr(smb))
37438c8a9a5SSteve French return -EIO;
37538c8a9a5SSteve French clc_len = smbCalcSize(smb);
37638c8a9a5SSteve French
37738c8a9a5SSteve French if (4 + rfclen != total_read) {
37838c8a9a5SSteve French cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n",
37938c8a9a5SSteve French rfclen);
38038c8a9a5SSteve French return -EIO;
38138c8a9a5SSteve French }
38238c8a9a5SSteve French
38338c8a9a5SSteve French if (4 + rfclen != clc_len) {
38438c8a9a5SSteve French __u16 mid = get_mid(smb);
38538c8a9a5SSteve French /* check if bcc wrapped around for large read responses */
38638c8a9a5SSteve French if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
38738c8a9a5SSteve French /* check if lengths match mod 64K */
38838c8a9a5SSteve French if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
38938c8a9a5SSteve French return 0; /* bcc wrapped */
39038c8a9a5SSteve French }
39138c8a9a5SSteve French cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
39238c8a9a5SSteve French clc_len, 4 + rfclen, mid);
39338c8a9a5SSteve French
39438c8a9a5SSteve French if (4 + rfclen < clc_len) {
39538c8a9a5SSteve French cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
39638c8a9a5SSteve French rfclen, mid);
39738c8a9a5SSteve French return -EIO;
39838c8a9a5SSteve French } else if (rfclen > clc_len + 512) {
39938c8a9a5SSteve French /*
40038c8a9a5SSteve French * Some servers (Windows XP in particular) send more
40138c8a9a5SSteve French * data than the lengths in the SMB packet would
40238c8a9a5SSteve French * indicate on certain calls (byte range locks and
40338c8a9a5SSteve French * trans2 find first calls in particular). While the
40438c8a9a5SSteve French * client can handle such a frame by ignoring the
40538c8a9a5SSteve French * trailing data, we choose limit the amount of extra
40638c8a9a5SSteve French * data to 512 bytes.
40738c8a9a5SSteve French */
40838c8a9a5SSteve French cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
40938c8a9a5SSteve French rfclen, mid);
41038c8a9a5SSteve French return -EIO;
41138c8a9a5SSteve French }
41238c8a9a5SSteve French }
41338c8a9a5SSteve French return 0;
41438c8a9a5SSteve French }
41538c8a9a5SSteve French
41638c8a9a5SSteve French bool
is_valid_oplock_break(char * buffer,struct TCP_Server_Info * srv)41738c8a9a5SSteve French is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
41838c8a9a5SSteve French {
41938c8a9a5SSteve French struct smb_hdr *buf = (struct smb_hdr *)buffer;
42038c8a9a5SSteve French struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
42138c8a9a5SSteve French struct TCP_Server_Info *pserver;
42238c8a9a5SSteve French struct cifs_ses *ses;
42338c8a9a5SSteve French struct cifs_tcon *tcon;
42438c8a9a5SSteve French struct cifsInodeInfo *pCifsInode;
42538c8a9a5SSteve French struct cifsFileInfo *netfile;
42638c8a9a5SSteve French
42738c8a9a5SSteve French cifs_dbg(FYI, "Checking for oplock break or dnotify response\n");
42838c8a9a5SSteve French if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
42938c8a9a5SSteve French (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
43038c8a9a5SSteve French struct smb_com_transaction_change_notify_rsp *pSMBr =
43138c8a9a5SSteve French (struct smb_com_transaction_change_notify_rsp *)buf;
43238c8a9a5SSteve French struct file_notify_information *pnotify;
43338c8a9a5SSteve French __u32 data_offset = 0;
43438c8a9a5SSteve French size_t len = srv->total_read - sizeof(pSMBr->hdr.smb_buf_length);
43538c8a9a5SSteve French
43638c8a9a5SSteve French if (get_bcc(buf) > sizeof(struct file_notify_information)) {
43738c8a9a5SSteve French data_offset = le32_to_cpu(pSMBr->DataOffset);
43838c8a9a5SSteve French
43938c8a9a5SSteve French if (data_offset >
44038c8a9a5SSteve French len - sizeof(struct file_notify_information)) {
44138c8a9a5SSteve French cifs_dbg(FYI, "Invalid data_offset %u\n",
44238c8a9a5SSteve French data_offset);
44338c8a9a5SSteve French return true;
44438c8a9a5SSteve French }
44538c8a9a5SSteve French pnotify = (struct file_notify_information *)
44638c8a9a5SSteve French ((char *)&pSMBr->hdr.Protocol + data_offset);
44738c8a9a5SSteve French cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",
44838c8a9a5SSteve French pnotify->FileName, pnotify->Action);
44938c8a9a5SSteve French /* cifs_dump_mem("Rcvd notify Data: ",buf,
45038c8a9a5SSteve French sizeof(struct smb_hdr)+60); */
45138c8a9a5SSteve French return true;
45238c8a9a5SSteve French }
45338c8a9a5SSteve French if (pSMBr->hdr.Status.CifsError) {
45438c8a9a5SSteve French cifs_dbg(FYI, "notify err 0x%x\n",
45538c8a9a5SSteve French pSMBr->hdr.Status.CifsError);
45638c8a9a5SSteve French return true;
45738c8a9a5SSteve French }
45838c8a9a5SSteve French return false;
45938c8a9a5SSteve French }
46038c8a9a5SSteve French if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
46138c8a9a5SSteve French return false;
46238c8a9a5SSteve French if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
46338c8a9a5SSteve French /* no sense logging error on invalid handle on oplock
46438c8a9a5SSteve French break - harmless race between close request and oplock
46538c8a9a5SSteve French break response is expected from time to time writing out
46638c8a9a5SSteve French large dirty files cached on the client */
46738c8a9a5SSteve French if ((NT_STATUS_INVALID_HANDLE) ==
46838c8a9a5SSteve French le32_to_cpu(pSMB->hdr.Status.CifsError)) {
46938c8a9a5SSteve French cifs_dbg(FYI, "Invalid handle on oplock break\n");
47038c8a9a5SSteve French return true;
47138c8a9a5SSteve French } else if (ERRbadfid ==
47238c8a9a5SSteve French le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
47338c8a9a5SSteve French return true;
47438c8a9a5SSteve French } else {
47538c8a9a5SSteve French return false; /* on valid oplock brk we get "request" */
47638c8a9a5SSteve French }
47738c8a9a5SSteve French }
47838c8a9a5SSteve French if (pSMB->hdr.WordCount != 8)
47938c8a9a5SSteve French return false;
48038c8a9a5SSteve French
48138c8a9a5SSteve French cifs_dbg(FYI, "oplock type 0x%x level 0x%x\n",
48238c8a9a5SSteve French pSMB->LockType, pSMB->OplockLevel);
48338c8a9a5SSteve French if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
48438c8a9a5SSteve French return false;
48538c8a9a5SSteve French
48638c8a9a5SSteve French /* If server is a channel, select the primary channel */
487b3773b19SSteve French pserver = SERVER_IS_CHAN(srv) ? srv->primary_server : srv;
48838c8a9a5SSteve French
48938c8a9a5SSteve French /* look up tcon based on tid & uid */
49038c8a9a5SSteve French spin_lock(&cifs_tcp_ses_lock);
49138c8a9a5SSteve French list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
4920a15ba88SPaulo Alcantara if (cifs_ses_exiting(ses))
4930a15ba88SPaulo Alcantara continue;
49438c8a9a5SSteve French list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
49538c8a9a5SSteve French if (tcon->tid != buf->Tid)
49638c8a9a5SSteve French continue;
49738c8a9a5SSteve French
49838c8a9a5SSteve French cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
49938c8a9a5SSteve French spin_lock(&tcon->open_file_lock);
50038c8a9a5SSteve French list_for_each_entry(netfile, &tcon->openFileList, tlist) {
50138c8a9a5SSteve French if (pSMB->Fid != netfile->fid.netfid)
50238c8a9a5SSteve French continue;
50338c8a9a5SSteve French
50438c8a9a5SSteve French cifs_dbg(FYI, "file id match, oplock break\n");
50538c8a9a5SSteve French pCifsInode = CIFS_I(d_inode(netfile->dentry));
50638c8a9a5SSteve French
50738c8a9a5SSteve French set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
50838c8a9a5SSteve French &pCifsInode->flags);
50938c8a9a5SSteve French
51038c8a9a5SSteve French netfile->oplock_epoch = 0;
51138c8a9a5SSteve French netfile->oplock_level = pSMB->OplockLevel;
51238c8a9a5SSteve French netfile->oplock_break_cancelled = false;
51338c8a9a5SSteve French cifs_queue_oplock_break(netfile);
51438c8a9a5SSteve French
51538c8a9a5SSteve French spin_unlock(&tcon->open_file_lock);
51638c8a9a5SSteve French spin_unlock(&cifs_tcp_ses_lock);
51738c8a9a5SSteve French return true;
51838c8a9a5SSteve French }
51938c8a9a5SSteve French spin_unlock(&tcon->open_file_lock);
52038c8a9a5SSteve French spin_unlock(&cifs_tcp_ses_lock);
52138c8a9a5SSteve French cifs_dbg(FYI, "No matching file for oplock break\n");
52238c8a9a5SSteve French return true;
52338c8a9a5SSteve French }
52438c8a9a5SSteve French }
52538c8a9a5SSteve French spin_unlock(&cifs_tcp_ses_lock);
52638c8a9a5SSteve French cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
52738c8a9a5SSteve French return true;
52838c8a9a5SSteve French }
52938c8a9a5SSteve French
53038c8a9a5SSteve French void
dump_smb(void * buf,int smb_buf_length)53138c8a9a5SSteve French dump_smb(void *buf, int smb_buf_length)
53238c8a9a5SSteve French {
53338c8a9a5SSteve French if (traceSMB == 0)
53438c8a9a5SSteve French return;
53538c8a9a5SSteve French
53638c8a9a5SSteve French print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 8, 2, buf,
53738c8a9a5SSteve French smb_buf_length, true);
53838c8a9a5SSteve French }
53938c8a9a5SSteve French
54038c8a9a5SSteve French void
cifs_autodisable_serverino(struct cifs_sb_info * cifs_sb)54138c8a9a5SSteve French cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
54238c8a9a5SSteve French {
54338c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
54438c8a9a5SSteve French struct cifs_tcon *tcon = NULL;
54538c8a9a5SSteve French
54638c8a9a5SSteve French if (cifs_sb->master_tlink)
54738c8a9a5SSteve French tcon = cifs_sb_master_tcon(cifs_sb);
54838c8a9a5SSteve French
54938c8a9a5SSteve French cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
55038c8a9a5SSteve French cifs_sb->mnt_cifs_serverino_autodisabled = true;
55138c8a9a5SSteve French cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s\n",
55238c8a9a5SSteve French tcon ? tcon->tree_name : "new server");
55338c8a9a5SSteve French cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS)\n");
55438c8a9a5SSteve French cifs_dbg(VFS, "Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n");
55538c8a9a5SSteve French
55638c8a9a5SSteve French }
55738c8a9a5SSteve French }
55838c8a9a5SSteve French
cifs_set_oplock_level(struct cifsInodeInfo * cinode,__u32 oplock)55938c8a9a5SSteve French void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
56038c8a9a5SSteve French {
56138c8a9a5SSteve French oplock &= 0xF;
56238c8a9a5SSteve French
56338c8a9a5SSteve French if (oplock == OPLOCK_EXCLUSIVE) {
56438c8a9a5SSteve French cinode->oplock = CIFS_CACHE_WRITE_FLG | CIFS_CACHE_READ_FLG;
56538c8a9a5SSteve French cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
56638c8a9a5SSteve French &cinode->netfs.inode);
56738c8a9a5SSteve French } else if (oplock == OPLOCK_READ) {
56838c8a9a5SSteve French cinode->oplock = CIFS_CACHE_READ_FLG;
56938c8a9a5SSteve French cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
57038c8a9a5SSteve French &cinode->netfs.inode);
57138c8a9a5SSteve French } else
57238c8a9a5SSteve French cinode->oplock = 0;
57338c8a9a5SSteve French }
57438c8a9a5SSteve French
57538c8a9a5SSteve French /*
57638c8a9a5SSteve French * We wait for oplock breaks to be processed before we attempt to perform
57738c8a9a5SSteve French * writes.
57838c8a9a5SSteve French */
cifs_get_writer(struct cifsInodeInfo * cinode)57938c8a9a5SSteve French int cifs_get_writer(struct cifsInodeInfo *cinode)
58038c8a9a5SSteve French {
58138c8a9a5SSteve French int rc;
58238c8a9a5SSteve French
58338c8a9a5SSteve French start:
58438c8a9a5SSteve French rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK,
58538c8a9a5SSteve French TASK_KILLABLE);
58638c8a9a5SSteve French if (rc)
58738c8a9a5SSteve French return rc;
58838c8a9a5SSteve French
58938c8a9a5SSteve French spin_lock(&cinode->writers_lock);
59038c8a9a5SSteve French if (!cinode->writers)
59138c8a9a5SSteve French set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
59238c8a9a5SSteve French cinode->writers++;
59338c8a9a5SSteve French /* Check to see if we have started servicing an oplock break */
59438c8a9a5SSteve French if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) {
59538c8a9a5SSteve French cinode->writers--;
59638c8a9a5SSteve French if (cinode->writers == 0) {
59738c8a9a5SSteve French clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
59838c8a9a5SSteve French wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
59938c8a9a5SSteve French }
60038c8a9a5SSteve French spin_unlock(&cinode->writers_lock);
60138c8a9a5SSteve French goto start;
60238c8a9a5SSteve French }
60338c8a9a5SSteve French spin_unlock(&cinode->writers_lock);
60438c8a9a5SSteve French return 0;
60538c8a9a5SSteve French }
60638c8a9a5SSteve French
cifs_put_writer(struct cifsInodeInfo * cinode)60738c8a9a5SSteve French void cifs_put_writer(struct cifsInodeInfo *cinode)
60838c8a9a5SSteve French {
60938c8a9a5SSteve French spin_lock(&cinode->writers_lock);
61038c8a9a5SSteve French cinode->writers--;
61138c8a9a5SSteve French if (cinode->writers == 0) {
61238c8a9a5SSteve French clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
61338c8a9a5SSteve French wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
61438c8a9a5SSteve French }
61538c8a9a5SSteve French spin_unlock(&cinode->writers_lock);
61638c8a9a5SSteve French }
61738c8a9a5SSteve French
61838c8a9a5SSteve French /**
61938c8a9a5SSteve French * cifs_queue_oplock_break - queue the oplock break handler for cfile
62038c8a9a5SSteve French * @cfile: The file to break the oplock on
62138c8a9a5SSteve French *
62238c8a9a5SSteve French * This function is called from the demultiplex thread when it
62338c8a9a5SSteve French * receives an oplock break for @cfile.
62438c8a9a5SSteve French *
62538c8a9a5SSteve French * Assumes the tcon->open_file_lock is held.
62638c8a9a5SSteve French * Assumes cfile->file_info_lock is NOT held.
62738c8a9a5SSteve French */
cifs_queue_oplock_break(struct cifsFileInfo * cfile)62838c8a9a5SSteve French void cifs_queue_oplock_break(struct cifsFileInfo *cfile)
62938c8a9a5SSteve French {
63038c8a9a5SSteve French /*
63138c8a9a5SSteve French * Bump the handle refcount now while we hold the
63238c8a9a5SSteve French * open_file_lock to enforce the validity of it for the oplock
63338c8a9a5SSteve French * break handler. The matching put is done at the end of the
63438c8a9a5SSteve French * handler.
63538c8a9a5SSteve French */
63638c8a9a5SSteve French cifsFileInfo_get(cfile);
63738c8a9a5SSteve French
63838c8a9a5SSteve French queue_work(cifsoplockd_wq, &cfile->oplock_break);
63938c8a9a5SSteve French }
64038c8a9a5SSteve French
cifs_done_oplock_break(struct cifsInodeInfo * cinode)64138c8a9a5SSteve French void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
64238c8a9a5SSteve French {
64338c8a9a5SSteve French clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
64438c8a9a5SSteve French wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK);
64538c8a9a5SSteve French }
64638c8a9a5SSteve French
64738c8a9a5SSteve French bool
backup_cred(struct cifs_sb_info * cifs_sb)64838c8a9a5SSteve French backup_cred(struct cifs_sb_info *cifs_sb)
64938c8a9a5SSteve French {
65038c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) {
65138c8a9a5SSteve French if (uid_eq(cifs_sb->ctx->backupuid, current_fsuid()))
65238c8a9a5SSteve French return true;
65338c8a9a5SSteve French }
65438c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) {
65538c8a9a5SSteve French if (in_group_p(cifs_sb->ctx->backupgid))
65638c8a9a5SSteve French return true;
65738c8a9a5SSteve French }
65838c8a9a5SSteve French
65938c8a9a5SSteve French return false;
66038c8a9a5SSteve French }
66138c8a9a5SSteve French
66238c8a9a5SSteve French void
cifs_del_pending_open(struct cifs_pending_open * open)66338c8a9a5SSteve French cifs_del_pending_open(struct cifs_pending_open *open)
66438c8a9a5SSteve French {
66538c8a9a5SSteve French spin_lock(&tlink_tcon(open->tlink)->open_file_lock);
66638c8a9a5SSteve French list_del(&open->olist);
66738c8a9a5SSteve French spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
66838c8a9a5SSteve French }
66938c8a9a5SSteve French
67038c8a9a5SSteve French void
cifs_add_pending_open_locked(struct cifs_fid * fid,struct tcon_link * tlink,struct cifs_pending_open * open)67138c8a9a5SSteve French cifs_add_pending_open_locked(struct cifs_fid *fid, struct tcon_link *tlink,
67238c8a9a5SSteve French struct cifs_pending_open *open)
67338c8a9a5SSteve French {
67438c8a9a5SSteve French memcpy(open->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
67538c8a9a5SSteve French open->oplock = CIFS_OPLOCK_NO_CHANGE;
67638c8a9a5SSteve French open->tlink = tlink;
67738c8a9a5SSteve French fid->pending_open = open;
67838c8a9a5SSteve French list_add_tail(&open->olist, &tlink_tcon(tlink)->pending_opens);
67938c8a9a5SSteve French }
68038c8a9a5SSteve French
68138c8a9a5SSteve French void
cifs_add_pending_open(struct cifs_fid * fid,struct tcon_link * tlink,struct cifs_pending_open * open)68238c8a9a5SSteve French cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
68338c8a9a5SSteve French struct cifs_pending_open *open)
68438c8a9a5SSteve French {
68538c8a9a5SSteve French spin_lock(&tlink_tcon(tlink)->open_file_lock);
68638c8a9a5SSteve French cifs_add_pending_open_locked(fid, tlink, open);
68738c8a9a5SSteve French spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
68838c8a9a5SSteve French }
68938c8a9a5SSteve French
69038c8a9a5SSteve French /*
69138c8a9a5SSteve French * Critical section which runs after acquiring deferred_lock.
69238c8a9a5SSteve French * As there is no reference count on cifs_deferred_close, pdclose
69338c8a9a5SSteve French * should not be used outside deferred_lock.
69438c8a9a5SSteve French */
69538c8a9a5SSteve French bool
cifs_is_deferred_close(struct cifsFileInfo * cfile,struct cifs_deferred_close ** pdclose)69638c8a9a5SSteve French cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **pdclose)
69738c8a9a5SSteve French {
69838c8a9a5SSteve French struct cifs_deferred_close *dclose;
69938c8a9a5SSteve French
70038c8a9a5SSteve French list_for_each_entry(dclose, &CIFS_I(d_inode(cfile->dentry))->deferred_closes, dlist) {
70138c8a9a5SSteve French if ((dclose->netfid == cfile->fid.netfid) &&
70238c8a9a5SSteve French (dclose->persistent_fid == cfile->fid.persistent_fid) &&
70338c8a9a5SSteve French (dclose->volatile_fid == cfile->fid.volatile_fid)) {
70438c8a9a5SSteve French *pdclose = dclose;
70538c8a9a5SSteve French return true;
70638c8a9a5SSteve French }
70738c8a9a5SSteve French }
70838c8a9a5SSteve French return false;
70938c8a9a5SSteve French }
71038c8a9a5SSteve French
71138c8a9a5SSteve French /*
71238c8a9a5SSteve French * Critical section which runs after acquiring deferred_lock.
71338c8a9a5SSteve French */
71438c8a9a5SSteve French void
cifs_add_deferred_close(struct cifsFileInfo * cfile,struct cifs_deferred_close * dclose)71538c8a9a5SSteve French cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *dclose)
71638c8a9a5SSteve French {
71738c8a9a5SSteve French bool is_deferred = false;
71838c8a9a5SSteve French struct cifs_deferred_close *pdclose;
71938c8a9a5SSteve French
72038c8a9a5SSteve French is_deferred = cifs_is_deferred_close(cfile, &pdclose);
72138c8a9a5SSteve French if (is_deferred) {
72238c8a9a5SSteve French kfree(dclose);
72338c8a9a5SSteve French return;
72438c8a9a5SSteve French }
72538c8a9a5SSteve French
72638c8a9a5SSteve French dclose->tlink = cfile->tlink;
72738c8a9a5SSteve French dclose->netfid = cfile->fid.netfid;
72838c8a9a5SSteve French dclose->persistent_fid = cfile->fid.persistent_fid;
72938c8a9a5SSteve French dclose->volatile_fid = cfile->fid.volatile_fid;
73038c8a9a5SSteve French list_add_tail(&dclose->dlist, &CIFS_I(d_inode(cfile->dentry))->deferred_closes);
73138c8a9a5SSteve French }
73238c8a9a5SSteve French
73338c8a9a5SSteve French /*
73438c8a9a5SSteve French * Critical section which runs after acquiring deferred_lock.
73538c8a9a5SSteve French */
73638c8a9a5SSteve French void
cifs_del_deferred_close(struct cifsFileInfo * cfile)73738c8a9a5SSteve French cifs_del_deferred_close(struct cifsFileInfo *cfile)
73838c8a9a5SSteve French {
73938c8a9a5SSteve French bool is_deferred = false;
74038c8a9a5SSteve French struct cifs_deferred_close *dclose;
74138c8a9a5SSteve French
74238c8a9a5SSteve French is_deferred = cifs_is_deferred_close(cfile, &dclose);
74338c8a9a5SSteve French if (!is_deferred)
74438c8a9a5SSteve French return;
74538c8a9a5SSteve French list_del(&dclose->dlist);
74638c8a9a5SSteve French kfree(dclose);
74738c8a9a5SSteve French }
74838c8a9a5SSteve French
74938c8a9a5SSteve French void
cifs_close_deferred_file(struct cifsInodeInfo * cifs_inode)75038c8a9a5SSteve French cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
75138c8a9a5SSteve French {
75238c8a9a5SSteve French struct cifsFileInfo *cfile = NULL;
75338c8a9a5SSteve French struct file_list *tmp_list, *tmp_next_list;
75438c8a9a5SSteve French struct list_head file_head;
75538c8a9a5SSteve French
75638c8a9a5SSteve French if (cifs_inode == NULL)
75738c8a9a5SSteve French return;
75838c8a9a5SSteve French
75938c8a9a5SSteve French INIT_LIST_HEAD(&file_head);
76038c8a9a5SSteve French spin_lock(&cifs_inode->open_file_lock);
76138c8a9a5SSteve French list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
76238c8a9a5SSteve French if (delayed_work_pending(&cfile->deferred)) {
76338c8a9a5SSteve French if (cancel_delayed_work(&cfile->deferred)) {
76438c8a9a5SSteve French spin_lock(&cifs_inode->deferred_lock);
76538c8a9a5SSteve French cifs_del_deferred_close(cfile);
76638c8a9a5SSteve French spin_unlock(&cifs_inode->deferred_lock);
76738c8a9a5SSteve French
76838c8a9a5SSteve French tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
76938c8a9a5SSteve French if (tmp_list == NULL)
77038c8a9a5SSteve French break;
77138c8a9a5SSteve French tmp_list->cfile = cfile;
77238c8a9a5SSteve French list_add_tail(&tmp_list->list, &file_head);
77338c8a9a5SSteve French }
77438c8a9a5SSteve French }
77538c8a9a5SSteve French }
77638c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock);
77738c8a9a5SSteve French
77838c8a9a5SSteve French list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
77938c8a9a5SSteve French _cifsFileInfo_put(tmp_list->cfile, false, false);
78038c8a9a5SSteve French list_del(&tmp_list->list);
78138c8a9a5SSteve French kfree(tmp_list);
78238c8a9a5SSteve French }
78338c8a9a5SSteve French }
78438c8a9a5SSteve French
78538c8a9a5SSteve French void
cifs_close_all_deferred_files(struct cifs_tcon * tcon)78638c8a9a5SSteve French cifs_close_all_deferred_files(struct cifs_tcon *tcon)
78738c8a9a5SSteve French {
78838c8a9a5SSteve French struct cifsFileInfo *cfile;
78938c8a9a5SSteve French struct file_list *tmp_list, *tmp_next_list;
79038c8a9a5SSteve French struct list_head file_head;
79138c8a9a5SSteve French
79238c8a9a5SSteve French INIT_LIST_HEAD(&file_head);
79338c8a9a5SSteve French spin_lock(&tcon->open_file_lock);
79438c8a9a5SSteve French list_for_each_entry(cfile, &tcon->openFileList, tlist) {
79538c8a9a5SSteve French if (delayed_work_pending(&cfile->deferred)) {
79638c8a9a5SSteve French if (cancel_delayed_work(&cfile->deferred)) {
79738c8a9a5SSteve French spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
79838c8a9a5SSteve French cifs_del_deferred_close(cfile);
79938c8a9a5SSteve French spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
80038c8a9a5SSteve French
80138c8a9a5SSteve French tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
80238c8a9a5SSteve French if (tmp_list == NULL)
80338c8a9a5SSteve French break;
80438c8a9a5SSteve French tmp_list->cfile = cfile;
80538c8a9a5SSteve French list_add_tail(&tmp_list->list, &file_head);
80638c8a9a5SSteve French }
80738c8a9a5SSteve French }
80838c8a9a5SSteve French }
80938c8a9a5SSteve French spin_unlock(&tcon->open_file_lock);
81038c8a9a5SSteve French
81138c8a9a5SSteve French list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
81238c8a9a5SSteve French _cifsFileInfo_put(tmp_list->cfile, true, false);
81338c8a9a5SSteve French list_del(&tmp_list->list);
81438c8a9a5SSteve French kfree(tmp_list);
81538c8a9a5SSteve French }
81638c8a9a5SSteve French }
81738c8a9a5SSteve French void
cifs_close_deferred_file_under_dentry(struct cifs_tcon * tcon,const char * path)81838c8a9a5SSteve French cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
81938c8a9a5SSteve French {
82038c8a9a5SSteve French struct cifsFileInfo *cfile;
82138c8a9a5SSteve French struct file_list *tmp_list, *tmp_next_list;
82238c8a9a5SSteve French struct list_head file_head;
82338c8a9a5SSteve French void *page;
82438c8a9a5SSteve French const char *full_path;
82538c8a9a5SSteve French
82638c8a9a5SSteve French INIT_LIST_HEAD(&file_head);
82738c8a9a5SSteve French page = alloc_dentry_path();
82838c8a9a5SSteve French spin_lock(&tcon->open_file_lock);
82938c8a9a5SSteve French list_for_each_entry(cfile, &tcon->openFileList, tlist) {
83038c8a9a5SSteve French full_path = build_path_from_dentry(cfile->dentry, page);
83138c8a9a5SSteve French if (strstr(full_path, path)) {
83238c8a9a5SSteve French if (delayed_work_pending(&cfile->deferred)) {
83338c8a9a5SSteve French if (cancel_delayed_work(&cfile->deferred)) {
83438c8a9a5SSteve French spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
83538c8a9a5SSteve French cifs_del_deferred_close(cfile);
83638c8a9a5SSteve French spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
83738c8a9a5SSteve French
83838c8a9a5SSteve French tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
83938c8a9a5SSteve French if (tmp_list == NULL)
84038c8a9a5SSteve French break;
84138c8a9a5SSteve French tmp_list->cfile = cfile;
84238c8a9a5SSteve French list_add_tail(&tmp_list->list, &file_head);
84338c8a9a5SSteve French }
84438c8a9a5SSteve French }
84538c8a9a5SSteve French }
84638c8a9a5SSteve French }
84738c8a9a5SSteve French spin_unlock(&tcon->open_file_lock);
84838c8a9a5SSteve French
84938c8a9a5SSteve French list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
85038c8a9a5SSteve French _cifsFileInfo_put(tmp_list->cfile, true, false);
85138c8a9a5SSteve French list_del(&tmp_list->list);
85238c8a9a5SSteve French kfree(tmp_list);
85338c8a9a5SSteve French }
85438c8a9a5SSteve French free_dentry_path(page);
85538c8a9a5SSteve French }
85638c8a9a5SSteve French
857b6e27f7fSSteve French /*
858b6e27f7fSSteve French * If a dentry has been deleted, all corresponding open handles should know that
859b6e27f7fSSteve French * so that we do not defer close them.
860b6e27f7fSSteve French */
cifs_mark_open_handles_for_deleted_file(struct inode * inode,const char * path)861b6e27f7fSSteve French void cifs_mark_open_handles_for_deleted_file(struct inode *inode,
862b6e27f7fSSteve French const char *path)
863b6e27f7fSSteve French {
864b6e27f7fSSteve French struct cifsFileInfo *cfile;
865b6e27f7fSSteve French void *page;
866b6e27f7fSSteve French const char *full_path;
867b6e27f7fSSteve French struct cifsInodeInfo *cinode = CIFS_I(inode);
868b6e27f7fSSteve French
869b6e27f7fSSteve French page = alloc_dentry_path();
870b6e27f7fSSteve French spin_lock(&cinode->open_file_lock);
871b6e27f7fSSteve French
872b6e27f7fSSteve French /*
873b6e27f7fSSteve French * note: we need to construct path from dentry and compare only if the
874b6e27f7fSSteve French * inode has any hardlinks. When number of hardlinks is 1, we can just
875b6e27f7fSSteve French * mark all open handles since they are going to be from the same file.
876b6e27f7fSSteve French */
877b6e27f7fSSteve French if (inode->i_nlink > 1) {
878b6e27f7fSSteve French list_for_each_entry(cfile, &cinode->openFileList, flist) {
879b6e27f7fSSteve French full_path = build_path_from_dentry(cfile->dentry, page);
880b6e27f7fSSteve French if (!IS_ERR(full_path) && strcmp(full_path, path) == 0)
881b6e27f7fSSteve French cfile->status_file_deleted = true;
882b6e27f7fSSteve French }
883b6e27f7fSSteve French } else {
884b6e27f7fSSteve French list_for_each_entry(cfile, &cinode->openFileList, flist)
885b6e27f7fSSteve French cfile->status_file_deleted = true;
886b6e27f7fSSteve French }
887b6e27f7fSSteve French spin_unlock(&cinode->open_file_lock);
888b6e27f7fSSteve French free_dentry_path(page);
889b6e27f7fSSteve French }
890b6e27f7fSSteve French
89138c8a9a5SSteve French /* parses DFS referral V3 structure
89238c8a9a5SSteve French * caller is responsible for freeing target_nodes
89338c8a9a5SSteve French * returns:
89438c8a9a5SSteve French * - on success - 0
89538c8a9a5SSteve French * - on failure - errno
89638c8a9a5SSteve French */
89738c8a9a5SSteve French int
parse_dfs_referrals(struct get_dfs_referral_rsp * rsp,u32 rsp_size,unsigned int * num_of_nodes,struct dfs_info3_param ** target_nodes,const struct nls_table * nls_codepage,int remap,const char * searchName,bool is_unicode)89838c8a9a5SSteve French parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
89938c8a9a5SSteve French unsigned int *num_of_nodes,
90038c8a9a5SSteve French struct dfs_info3_param **target_nodes,
90138c8a9a5SSteve French const struct nls_table *nls_codepage, int remap,
90238c8a9a5SSteve French const char *searchName, bool is_unicode)
90338c8a9a5SSteve French {
90438c8a9a5SSteve French int i, rc = 0;
90538c8a9a5SSteve French char *data_end;
90638c8a9a5SSteve French struct dfs_referral_level_3 *ref;
90738c8a9a5SSteve French
90838c8a9a5SSteve French *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);
90938c8a9a5SSteve French
91038c8a9a5SSteve French if (*num_of_nodes < 1) {
91138c8a9a5SSteve French cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
91238c8a9a5SSteve French *num_of_nodes);
91338c8a9a5SSteve French rc = -EINVAL;
91438c8a9a5SSteve French goto parse_DFS_referrals_exit;
91538c8a9a5SSteve French }
91638c8a9a5SSteve French
91738c8a9a5SSteve French ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
91838c8a9a5SSteve French if (ref->VersionNumber != cpu_to_le16(3)) {
91938c8a9a5SSteve French cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
92038c8a9a5SSteve French le16_to_cpu(ref->VersionNumber));
92138c8a9a5SSteve French rc = -EINVAL;
92238c8a9a5SSteve French goto parse_DFS_referrals_exit;
92338c8a9a5SSteve French }
92438c8a9a5SSteve French
92538c8a9a5SSteve French /* get the upper boundary of the resp buffer */
92638c8a9a5SSteve French data_end = (char *)rsp + rsp_size;
92738c8a9a5SSteve French
92838c8a9a5SSteve French cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
92938c8a9a5SSteve French *num_of_nodes, le32_to_cpu(rsp->DFSFlags));
93038c8a9a5SSteve French
93138c8a9a5SSteve French *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
93238c8a9a5SSteve French GFP_KERNEL);
93338c8a9a5SSteve French if (*target_nodes == NULL) {
93438c8a9a5SSteve French rc = -ENOMEM;
93538c8a9a5SSteve French goto parse_DFS_referrals_exit;
93638c8a9a5SSteve French }
93738c8a9a5SSteve French
93838c8a9a5SSteve French /* collect necessary data from referrals */
93938c8a9a5SSteve French for (i = 0; i < *num_of_nodes; i++) {
94038c8a9a5SSteve French char *temp;
94138c8a9a5SSteve French int max_len;
94238c8a9a5SSteve French struct dfs_info3_param *node = (*target_nodes)+i;
94338c8a9a5SSteve French
94438c8a9a5SSteve French node->flags = le32_to_cpu(rsp->DFSFlags);
94538c8a9a5SSteve French if (is_unicode) {
94638c8a9a5SSteve French __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
94738c8a9a5SSteve French GFP_KERNEL);
94838c8a9a5SSteve French if (tmp == NULL) {
94938c8a9a5SSteve French rc = -ENOMEM;
95038c8a9a5SSteve French goto parse_DFS_referrals_exit;
95138c8a9a5SSteve French }
95238c8a9a5SSteve French cifsConvertToUTF16((__le16 *) tmp, searchName,
95338c8a9a5SSteve French PATH_MAX, nls_codepage, remap);
95438c8a9a5SSteve French node->path_consumed = cifs_utf16_bytes(tmp,
95538c8a9a5SSteve French le16_to_cpu(rsp->PathConsumed),
95638c8a9a5SSteve French nls_codepage);
95738c8a9a5SSteve French kfree(tmp);
95838c8a9a5SSteve French } else
95938c8a9a5SSteve French node->path_consumed = le16_to_cpu(rsp->PathConsumed);
96038c8a9a5SSteve French
96138c8a9a5SSteve French node->server_type = le16_to_cpu(ref->ServerType);
96238c8a9a5SSteve French node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
96338c8a9a5SSteve French
96438c8a9a5SSteve French /* copy DfsPath */
96538c8a9a5SSteve French temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
96638c8a9a5SSteve French max_len = data_end - temp;
96738c8a9a5SSteve French node->path_name = cifs_strndup_from_utf16(temp, max_len,
96838c8a9a5SSteve French is_unicode, nls_codepage);
96938c8a9a5SSteve French if (!node->path_name) {
97038c8a9a5SSteve French rc = -ENOMEM;
97138c8a9a5SSteve French goto parse_DFS_referrals_exit;
97238c8a9a5SSteve French }
97338c8a9a5SSteve French
97438c8a9a5SSteve French /* copy link target UNC */
97538c8a9a5SSteve French temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
97638c8a9a5SSteve French max_len = data_end - temp;
97738c8a9a5SSteve French node->node_name = cifs_strndup_from_utf16(temp, max_len,
97838c8a9a5SSteve French is_unicode, nls_codepage);
97938c8a9a5SSteve French if (!node->node_name) {
98038c8a9a5SSteve French rc = -ENOMEM;
98138c8a9a5SSteve French goto parse_DFS_referrals_exit;
98238c8a9a5SSteve French }
98338c8a9a5SSteve French
98438c8a9a5SSteve French node->ttl = le32_to_cpu(ref->TimeToLive);
98538c8a9a5SSteve French
98638c8a9a5SSteve French ref++;
98738c8a9a5SSteve French }
98838c8a9a5SSteve French
98938c8a9a5SSteve French parse_DFS_referrals_exit:
99038c8a9a5SSteve French if (rc) {
99138c8a9a5SSteve French free_dfs_info_array(*target_nodes, *num_of_nodes);
99238c8a9a5SSteve French *target_nodes = NULL;
99338c8a9a5SSteve French *num_of_nodes = 0;
99438c8a9a5SSteve French }
99538c8a9a5SSteve French return rc;
99638c8a9a5SSteve French }
99738c8a9a5SSteve French
99838c8a9a5SSteve French struct cifs_aio_ctx *
cifs_aio_ctx_alloc(void)99938c8a9a5SSteve French cifs_aio_ctx_alloc(void)
100038c8a9a5SSteve French {
100138c8a9a5SSteve French struct cifs_aio_ctx *ctx;
100238c8a9a5SSteve French
100338c8a9a5SSteve French /*
100438c8a9a5SSteve French * Must use kzalloc to initialize ctx->bv to NULL and ctx->direct_io
100538c8a9a5SSteve French * to false so that we know when we have to unreference pages within
100638c8a9a5SSteve French * cifs_aio_ctx_release()
100738c8a9a5SSteve French */
100838c8a9a5SSteve French ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL);
100938c8a9a5SSteve French if (!ctx)
101038c8a9a5SSteve French return NULL;
101138c8a9a5SSteve French
101238c8a9a5SSteve French INIT_LIST_HEAD(&ctx->list);
101338c8a9a5SSteve French mutex_init(&ctx->aio_mutex);
101438c8a9a5SSteve French init_completion(&ctx->done);
101538c8a9a5SSteve French kref_init(&ctx->refcount);
101638c8a9a5SSteve French return ctx;
101738c8a9a5SSteve French }
101838c8a9a5SSteve French
101938c8a9a5SSteve French void
cifs_aio_ctx_release(struct kref * refcount)102038c8a9a5SSteve French cifs_aio_ctx_release(struct kref *refcount)
102138c8a9a5SSteve French {
102238c8a9a5SSteve French struct cifs_aio_ctx *ctx = container_of(refcount,
102338c8a9a5SSteve French struct cifs_aio_ctx, refcount);
102438c8a9a5SSteve French
102538c8a9a5SSteve French cifsFileInfo_put(ctx->cfile);
102638c8a9a5SSteve French
102738c8a9a5SSteve French /*
102838c8a9a5SSteve French * ctx->bv is only set if setup_aio_ctx_iter() was call successfuly
102938c8a9a5SSteve French * which means that iov_iter_extract_pages() was a success and thus
103038c8a9a5SSteve French * that we may have references or pins on pages that we need to
103138c8a9a5SSteve French * release.
103238c8a9a5SSteve French */
103338c8a9a5SSteve French if (ctx->bv) {
103438c8a9a5SSteve French if (ctx->should_dirty || ctx->bv_need_unpin) {
103538c8a9a5SSteve French unsigned int i;
103638c8a9a5SSteve French
103738c8a9a5SSteve French for (i = 0; i < ctx->nr_pinned_pages; i++) {
103838c8a9a5SSteve French struct page *page = ctx->bv[i].bv_page;
103938c8a9a5SSteve French
104038c8a9a5SSteve French if (ctx->should_dirty)
104138c8a9a5SSteve French set_page_dirty(page);
104238c8a9a5SSteve French if (ctx->bv_need_unpin)
104338c8a9a5SSteve French unpin_user_page(page);
104438c8a9a5SSteve French }
104538c8a9a5SSteve French }
104638c8a9a5SSteve French kvfree(ctx->bv);
104738c8a9a5SSteve French }
104838c8a9a5SSteve French
104938c8a9a5SSteve French kfree(ctx);
105038c8a9a5SSteve French }
105138c8a9a5SSteve French
105238c8a9a5SSteve French /**
105338c8a9a5SSteve French * cifs_alloc_hash - allocate hash and hash context together
105438c8a9a5SSteve French * @name: The name of the crypto hash algo
105538c8a9a5SSteve French * @sdesc: SHASH descriptor where to put the pointer to the hash TFM
105638c8a9a5SSteve French *
105738c8a9a5SSteve French * The caller has to make sure @sdesc is initialized to either NULL or
105838c8a9a5SSteve French * a valid context. It can be freed via cifs_free_hash().
105938c8a9a5SSteve French */
106038c8a9a5SSteve French int
cifs_alloc_hash(const char * name,struct shash_desc ** sdesc)106138c8a9a5SSteve French cifs_alloc_hash(const char *name, struct shash_desc **sdesc)
106238c8a9a5SSteve French {
106338c8a9a5SSteve French int rc = 0;
106438c8a9a5SSteve French struct crypto_shash *alg = NULL;
106538c8a9a5SSteve French
106638c8a9a5SSteve French if (*sdesc)
106738c8a9a5SSteve French return 0;
106838c8a9a5SSteve French
106938c8a9a5SSteve French alg = crypto_alloc_shash(name, 0, 0);
107038c8a9a5SSteve French if (IS_ERR(alg)) {
107138c8a9a5SSteve French cifs_dbg(VFS, "Could not allocate shash TFM '%s'\n", name);
107238c8a9a5SSteve French rc = PTR_ERR(alg);
107338c8a9a5SSteve French *sdesc = NULL;
107438c8a9a5SSteve French return rc;
107538c8a9a5SSteve French }
107638c8a9a5SSteve French
107738c8a9a5SSteve French *sdesc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(alg), GFP_KERNEL);
107838c8a9a5SSteve French if (*sdesc == NULL) {
107938c8a9a5SSteve French cifs_dbg(VFS, "no memory left to allocate shash TFM '%s'\n", name);
108038c8a9a5SSteve French crypto_free_shash(alg);
108138c8a9a5SSteve French return -ENOMEM;
108238c8a9a5SSteve French }
108338c8a9a5SSteve French
108438c8a9a5SSteve French (*sdesc)->tfm = alg;
108538c8a9a5SSteve French return 0;
108638c8a9a5SSteve French }
108738c8a9a5SSteve French
108838c8a9a5SSteve French /**
108938c8a9a5SSteve French * cifs_free_hash - free hash and hash context together
109038c8a9a5SSteve French * @sdesc: Where to find the pointer to the hash TFM
109138c8a9a5SSteve French *
109238c8a9a5SSteve French * Freeing a NULL descriptor is safe.
109338c8a9a5SSteve French */
109438c8a9a5SSteve French void
cifs_free_hash(struct shash_desc ** sdesc)109538c8a9a5SSteve French cifs_free_hash(struct shash_desc **sdesc)
109638c8a9a5SSteve French {
109738c8a9a5SSteve French if (unlikely(!sdesc) || !*sdesc)
109838c8a9a5SSteve French return;
109938c8a9a5SSteve French
110038c8a9a5SSteve French if ((*sdesc)->tfm) {
110138c8a9a5SSteve French crypto_free_shash((*sdesc)->tfm);
110238c8a9a5SSteve French (*sdesc)->tfm = NULL;
110338c8a9a5SSteve French }
110438c8a9a5SSteve French
110538c8a9a5SSteve French kfree_sensitive(*sdesc);
110638c8a9a5SSteve French *sdesc = NULL;
110738c8a9a5SSteve French }
110838c8a9a5SSteve French
extract_unc_hostname(const char * unc,const char ** h,size_t * len)110938c8a9a5SSteve French void extract_unc_hostname(const char *unc, const char **h, size_t *len)
111038c8a9a5SSteve French {
111138c8a9a5SSteve French const char *end;
111238c8a9a5SSteve French
111338c8a9a5SSteve French /* skip initial slashes */
111438c8a9a5SSteve French while (*unc && (*unc == '\\' || *unc == '/'))
111538c8a9a5SSteve French unc++;
111638c8a9a5SSteve French
111738c8a9a5SSteve French end = unc;
111838c8a9a5SSteve French
111938c8a9a5SSteve French while (*end && !(*end == '\\' || *end == '/'))
112038c8a9a5SSteve French end++;
112138c8a9a5SSteve French
112238c8a9a5SSteve French *h = unc;
112338c8a9a5SSteve French *len = end - unc;
112438c8a9a5SSteve French }
112538c8a9a5SSteve French
112638c8a9a5SSteve French /**
112738c8a9a5SSteve French * copy_path_name - copy src path to dst, possibly truncating
112838c8a9a5SSteve French * @dst: The destination buffer
112938c8a9a5SSteve French * @src: The source name
113038c8a9a5SSteve French *
113138c8a9a5SSteve French * returns number of bytes written (including trailing nul)
113238c8a9a5SSteve French */
copy_path_name(char * dst,const char * src)113338c8a9a5SSteve French int copy_path_name(char *dst, const char *src)
113438c8a9a5SSteve French {
113538c8a9a5SSteve French int name_len;
113638c8a9a5SSteve French
113738c8a9a5SSteve French /*
113838c8a9a5SSteve French * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it
113938c8a9a5SSteve French * will truncate and strlen(dst) will be PATH_MAX-1
114038c8a9a5SSteve French */
114138c8a9a5SSteve French name_len = strscpy(dst, src, PATH_MAX);
114238c8a9a5SSteve French if (WARN_ON_ONCE(name_len < 0))
114338c8a9a5SSteve French name_len = PATH_MAX-1;
114438c8a9a5SSteve French
114538c8a9a5SSteve French /* we count the trailing nul */
114638c8a9a5SSteve French name_len++;
114738c8a9a5SSteve French return name_len;
114838c8a9a5SSteve French }
114938c8a9a5SSteve French
115038c8a9a5SSteve French struct super_cb_data {
115138c8a9a5SSteve French void *data;
115238c8a9a5SSteve French struct super_block *sb;
115338c8a9a5SSteve French };
115438c8a9a5SSteve French
tcon_super_cb(struct super_block * sb,void * arg)11553ae872deSPaulo Alcantara static void tcon_super_cb(struct super_block *sb, void *arg)
115638c8a9a5SSteve French {
115738c8a9a5SSteve French struct super_cb_data *sd = arg;
115838c8a9a5SSteve French struct cifs_sb_info *cifs_sb;
11593ae872deSPaulo Alcantara struct cifs_tcon *t1 = sd->data, *t2;
116038c8a9a5SSteve French
116138c8a9a5SSteve French if (sd->sb)
116238c8a9a5SSteve French return;
116338c8a9a5SSteve French
116438c8a9a5SSteve French cifs_sb = CIFS_SB(sb);
11653ae872deSPaulo Alcantara t2 = cifs_sb_master_tcon(cifs_sb);
11663ae872deSPaulo Alcantara
11673ae872deSPaulo Alcantara spin_lock(&t2->tc_lock);
11683ae872deSPaulo Alcantara if (t1->ses == t2->ses &&
11693ae872deSPaulo Alcantara t1->ses->server == t2->ses->server &&
11703ae872deSPaulo Alcantara t2->origin_fullpath &&
11713ae872deSPaulo Alcantara dfs_src_pathname_equal(t2->origin_fullpath, t1->origin_fullpath))
117238c8a9a5SSteve French sd->sb = sb;
11733ae872deSPaulo Alcantara spin_unlock(&t2->tc_lock);
117438c8a9a5SSteve French }
117538c8a9a5SSteve French
__cifs_get_super(void (* f)(struct super_block *,void *),void * data)117638c8a9a5SSteve French static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *),
117738c8a9a5SSteve French void *data)
117838c8a9a5SSteve French {
117938c8a9a5SSteve French struct super_cb_data sd = {
118038c8a9a5SSteve French .data = data,
118138c8a9a5SSteve French .sb = NULL,
118238c8a9a5SSteve French };
118338c8a9a5SSteve French struct file_system_type **fs_type = (struct file_system_type *[]) {
118438c8a9a5SSteve French &cifs_fs_type, &smb3_fs_type, NULL,
118538c8a9a5SSteve French };
118638c8a9a5SSteve French
118738c8a9a5SSteve French for (; *fs_type; fs_type++) {
118838c8a9a5SSteve French iterate_supers_type(*fs_type, f, &sd);
118938c8a9a5SSteve French if (sd.sb) {
119038c8a9a5SSteve French /*
119138c8a9a5SSteve French * Grab an active reference in order to prevent automounts (DFS links)
119238c8a9a5SSteve French * of expiring and then freeing up our cifs superblock pointer while
119338c8a9a5SSteve French * we're doing failover.
119438c8a9a5SSteve French */
119538c8a9a5SSteve French cifs_sb_active(sd.sb);
119638c8a9a5SSteve French return sd.sb;
119738c8a9a5SSteve French }
119838c8a9a5SSteve French }
11993ae872deSPaulo Alcantara pr_warn_once("%s: could not find dfs superblock\n", __func__);
120038c8a9a5SSteve French return ERR_PTR(-EINVAL);
120138c8a9a5SSteve French }
120238c8a9a5SSteve French
__cifs_put_super(struct super_block * sb)120338c8a9a5SSteve French static void __cifs_put_super(struct super_block *sb)
120438c8a9a5SSteve French {
120538c8a9a5SSteve French if (!IS_ERR_OR_NULL(sb))
120638c8a9a5SSteve French cifs_sb_deactive(sb);
120738c8a9a5SSteve French }
120838c8a9a5SSteve French
cifs_get_dfs_tcon_super(struct cifs_tcon * tcon)12093ae872deSPaulo Alcantara struct super_block *cifs_get_dfs_tcon_super(struct cifs_tcon *tcon)
121038c8a9a5SSteve French {
12113ae872deSPaulo Alcantara spin_lock(&tcon->tc_lock);
12123ae872deSPaulo Alcantara if (!tcon->origin_fullpath) {
12133ae872deSPaulo Alcantara spin_unlock(&tcon->tc_lock);
12143ae872deSPaulo Alcantara return ERR_PTR(-ENOENT);
12153ae872deSPaulo Alcantara }
12163ae872deSPaulo Alcantara spin_unlock(&tcon->tc_lock);
12173ae872deSPaulo Alcantara return __cifs_get_super(tcon_super_cb, tcon);
121838c8a9a5SSteve French }
121938c8a9a5SSteve French
cifs_put_tcp_super(struct super_block * sb)122038c8a9a5SSteve French void cifs_put_tcp_super(struct super_block *sb)
122138c8a9a5SSteve French {
122238c8a9a5SSteve French __cifs_put_super(sb);
122338c8a9a5SSteve French }
122438c8a9a5SSteve French
122538c8a9a5SSteve French #ifdef CONFIG_CIFS_DFS_UPCALL
match_target_ip(struct TCP_Server_Info * server,const char * share,size_t share_len,bool * result)122638c8a9a5SSteve French int match_target_ip(struct TCP_Server_Info *server,
122738c8a9a5SSteve French const char *share, size_t share_len,
122838c8a9a5SSteve French bool *result)
122938c8a9a5SSteve French {
123038c8a9a5SSteve French int rc;
123138c8a9a5SSteve French char *target;
123238c8a9a5SSteve French struct sockaddr_storage ss;
123338c8a9a5SSteve French
123438c8a9a5SSteve French *result = false;
123538c8a9a5SSteve French
123638c8a9a5SSteve French target = kzalloc(share_len + 3, GFP_KERNEL);
123738c8a9a5SSteve French if (!target)
123838c8a9a5SSteve French return -ENOMEM;
123938c8a9a5SSteve French
124038c8a9a5SSteve French scnprintf(target, share_len + 3, "\\\\%.*s", (int)share_len, share);
124138c8a9a5SSteve French
124238c8a9a5SSteve French cifs_dbg(FYI, "%s: target name: %s\n", __func__, target + 2);
124338c8a9a5SSteve French
124438c8a9a5SSteve French rc = dns_resolve_server_name_to_ip(target, (struct sockaddr *)&ss, NULL);
124538c8a9a5SSteve French kfree(target);
124638c8a9a5SSteve French
124738c8a9a5SSteve French if (rc < 0)
124838c8a9a5SSteve French return rc;
124938c8a9a5SSteve French
125038c8a9a5SSteve French spin_lock(&server->srv_lock);
125138c8a9a5SSteve French *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);
125238c8a9a5SSteve French spin_unlock(&server->srv_lock);
125338c8a9a5SSteve French cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result);
125438c8a9a5SSteve French return 0;
125538c8a9a5SSteve French }
125638c8a9a5SSteve French
cifs_update_super_prepath(struct cifs_sb_info * cifs_sb,char * prefix)125738c8a9a5SSteve French int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
125838c8a9a5SSteve French {
125949024ec8SPaulo Alcantara int rc;
126049024ec8SPaulo Alcantara
126138c8a9a5SSteve French kfree(cifs_sb->prepath);
126249024ec8SPaulo Alcantara cifs_sb->prepath = NULL;
126338c8a9a5SSteve French
126438c8a9a5SSteve French if (prefix && *prefix) {
126538c8a9a5SSteve French cifs_sb->prepath = cifs_sanitize_prepath(prefix, GFP_ATOMIC);
126649024ec8SPaulo Alcantara if (IS_ERR(cifs_sb->prepath)) {
126749024ec8SPaulo Alcantara rc = PTR_ERR(cifs_sb->prepath);
126838c8a9a5SSteve French cifs_sb->prepath = NULL;
126949024ec8SPaulo Alcantara return rc;
127049024ec8SPaulo Alcantara }
127149024ec8SPaulo Alcantara if (cifs_sb->prepath)
127249024ec8SPaulo Alcantara convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
127349024ec8SPaulo Alcantara }
127438c8a9a5SSteve French
127538c8a9a5SSteve French cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
127638c8a9a5SSteve French return 0;
127738c8a9a5SSteve French }
127838c8a9a5SSteve French
127938c8a9a5SSteve French /*
128038c8a9a5SSteve French * Handle weird Windows SMB server behaviour. It responds with
128138c8a9a5SSteve French * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request for
128238c8a9a5SSteve French * "\<server>\<dfsname>\<linkpath>" DFS reference, where <dfsname> contains
128338c8a9a5SSteve French * non-ASCII unicode symbols.
128438c8a9a5SSteve French */
cifs_inval_name_dfs_link_error(const unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const char * full_path,bool * islink)128538c8a9a5SSteve French int cifs_inval_name_dfs_link_error(const unsigned int xid,
128638c8a9a5SSteve French struct cifs_tcon *tcon,
128738c8a9a5SSteve French struct cifs_sb_info *cifs_sb,
128838c8a9a5SSteve French const char *full_path,
128938c8a9a5SSteve French bool *islink)
129038c8a9a5SSteve French {
1291*c0f767deSGleb Korobeynikov struct TCP_Server_Info *server = tcon->ses->server;
129238c8a9a5SSteve French struct cifs_ses *ses = tcon->ses;
129338c8a9a5SSteve French size_t len;
129438c8a9a5SSteve French char *path;
129538c8a9a5SSteve French char *ref_path;
129638c8a9a5SSteve French
129738c8a9a5SSteve French *islink = false;
129838c8a9a5SSteve French
129938c8a9a5SSteve French /*
130038c8a9a5SSteve French * Fast path - skip check when @full_path doesn't have a prefix path to
130138c8a9a5SSteve French * look up or tcon is not DFS.
130238c8a9a5SSteve French */
130338c8a9a5SSteve French if (strlen(full_path) < 2 || !cifs_sb ||
130438c8a9a5SSteve French (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) ||
13053ae872deSPaulo Alcantara !is_tcon_dfs(tcon))
130638c8a9a5SSteve French return 0;
130738c8a9a5SSteve French
1308*c0f767deSGleb Korobeynikov spin_lock(&server->srv_lock);
1309*c0f767deSGleb Korobeynikov if (!server->leaf_fullpath) {
1310*c0f767deSGleb Korobeynikov spin_unlock(&server->srv_lock);
13113ae872deSPaulo Alcantara return 0;
13123ae872deSPaulo Alcantara }
1313*c0f767deSGleb Korobeynikov spin_unlock(&server->srv_lock);
13143ae872deSPaulo Alcantara
131538c8a9a5SSteve French /*
131638c8a9a5SSteve French * Slow path - tcon is DFS and @full_path has prefix path, so attempt
131738c8a9a5SSteve French * to get a referral to figure out whether it is an DFS link.
131838c8a9a5SSteve French */
131938c8a9a5SSteve French len = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1) + strlen(full_path) + 1;
132038c8a9a5SSteve French path = kmalloc(len, GFP_KERNEL);
132138c8a9a5SSteve French if (!path)
132238c8a9a5SSteve French return -ENOMEM;
132338c8a9a5SSteve French
132438c8a9a5SSteve French scnprintf(path, len, "%s%s", tcon->tree_name, full_path);
132538c8a9a5SSteve French ref_path = dfs_cache_canonical_path(path + 1, cifs_sb->local_nls,
132638c8a9a5SSteve French cifs_remap(cifs_sb));
132738c8a9a5SSteve French kfree(path);
132838c8a9a5SSteve French
132938c8a9a5SSteve French if (IS_ERR(ref_path)) {
133038c8a9a5SSteve French if (PTR_ERR(ref_path) != -EINVAL)
133138c8a9a5SSteve French return PTR_ERR(ref_path);
133238c8a9a5SSteve French } else {
133338c8a9a5SSteve French struct dfs_info3_param *refs = NULL;
133438c8a9a5SSteve French int num_refs = 0;
133538c8a9a5SSteve French
133638c8a9a5SSteve French /*
133738c8a9a5SSteve French * XXX: we are not using dfs_cache_find() here because we might
13383ae872deSPaulo Alcantara * end up filling all the DFS cache and thus potentially
133938c8a9a5SSteve French * removing cached DFS targets that the client would eventually
134038c8a9a5SSteve French * need during failover.
134138c8a9a5SSteve French */
134238c8a9a5SSteve French ses = CIFS_DFS_ROOT_SES(ses);
134338c8a9a5SSteve French if (ses->server->ops->get_dfs_refer &&
134438c8a9a5SSteve French !ses->server->ops->get_dfs_refer(xid, ses, ref_path, &refs,
134538c8a9a5SSteve French &num_refs, cifs_sb->local_nls,
134638c8a9a5SSteve French cifs_remap(cifs_sb)))
134738c8a9a5SSteve French *islink = refs[0].server_type == DFS_TYPE_LINK;
134838c8a9a5SSteve French free_dfs_info_array(refs, num_refs);
134938c8a9a5SSteve French kfree(ref_path);
135038c8a9a5SSteve French }
135138c8a9a5SSteve French return 0;
135238c8a9a5SSteve French }
135338c8a9a5SSteve French #endif
135438c8a9a5SSteve French
cifs_wait_for_server_reconnect(struct TCP_Server_Info * server,bool retry)135538c8a9a5SSteve French int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry)
135638c8a9a5SSteve French {
135738c8a9a5SSteve French int timeout = 10;
135838c8a9a5SSteve French int rc;
135938c8a9a5SSteve French
136038c8a9a5SSteve French spin_lock(&server->srv_lock);
136138c8a9a5SSteve French if (server->tcpStatus != CifsNeedReconnect) {
136238c8a9a5SSteve French spin_unlock(&server->srv_lock);
136338c8a9a5SSteve French return 0;
136438c8a9a5SSteve French }
136538c8a9a5SSteve French timeout *= server->nr_targets;
136638c8a9a5SSteve French spin_unlock(&server->srv_lock);
136738c8a9a5SSteve French
136838c8a9a5SSteve French /*
136938c8a9a5SSteve French * Give demultiplex thread up to 10 seconds to each target available for
137038c8a9a5SSteve French * reconnect -- should be greater than cifs socket timeout which is 7
137138c8a9a5SSteve French * seconds.
137238c8a9a5SSteve French *
137338c8a9a5SSteve French * On "soft" mounts we wait once. Hard mounts keep retrying until
137438c8a9a5SSteve French * process is killed or server comes back on-line.
137538c8a9a5SSteve French */
137638c8a9a5SSteve French do {
137738c8a9a5SSteve French rc = wait_event_interruptible_timeout(server->response_q,
137838c8a9a5SSteve French (server->tcpStatus != CifsNeedReconnect),
137938c8a9a5SSteve French timeout * HZ);
138038c8a9a5SSteve French if (rc < 0) {
138138c8a9a5SSteve French cifs_dbg(FYI, "%s: aborting reconnect due to received signal\n",
138238c8a9a5SSteve French __func__);
138338c8a9a5SSteve French return -ERESTARTSYS;
138438c8a9a5SSteve French }
138538c8a9a5SSteve French
138638c8a9a5SSteve French /* are we still trying to reconnect? */
138738c8a9a5SSteve French spin_lock(&server->srv_lock);
138838c8a9a5SSteve French if (server->tcpStatus != CifsNeedReconnect) {
138938c8a9a5SSteve French spin_unlock(&server->srv_lock);
139038c8a9a5SSteve French return 0;
139138c8a9a5SSteve French }
139238c8a9a5SSteve French spin_unlock(&server->srv_lock);
139338c8a9a5SSteve French } while (retry);
139438c8a9a5SSteve French
139538c8a9a5SSteve French cifs_dbg(FYI, "%s: gave up waiting on reconnect\n", __func__);
139638c8a9a5SSteve French return -EHOSTDOWN;
139738c8a9a5SSteve French }
1398