Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2)  *   fs/cifs/smb2pdu.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *   Copyright (C) International Business Machines  Corp., 2009, 2013
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *                 Etersoft, 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *   Author(s): Steve French (sfrench@us.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *              Pavel Shilovsky (pshilovsky@samba.org) 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *   Contains the routines for constructing the SMB2 PDUs themselves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *   This library is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *   it under the terms of the GNU Lesser General Public License as published
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *   by the Free Software Foundation; either version 2.1 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  *   (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  *   This library is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  *   the GNU Lesser General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  *   You should have received a copy of the GNU Lesser General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  *   along with this library; if not, write to the Free Software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  /* SMB2 PDU handling routines here - except for leftovers (eg session setup) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  /* Note that there are handle based routines which must be		      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  /* treated slightly differently for reconnection purposes since we never     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  /* want to reuse a stale file handle and only the caller knows the file info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/vfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <linux/task_io_accounting_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/uuid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <linux/xattr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include "smb2pdu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #include "cifsglob.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include "cifsacl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include "cifsproto.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #include "smb2proto.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include "cifs_unicode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include "cifs_debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #include "ntlmssp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #include "smb2status.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #include "smb2glob.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #include "cifspdu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #include "cifs_spnego.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #include "smbdirect.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #include "trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #ifdef CONFIG_CIFS_DFS_UPCALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #include "dfs_cache.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58)  *  The following table defines the expected "StructureSize" of SMB2 requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59)  *  in order by SMB2 command.  This is similar to "wct" in SMB/CIFS requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61)  *  Note that commands are defined in smb2pdu.h in le16 but the array below is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62)  *  indexed by command in host byte order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	/* SMB2_NEGOTIATE */ 36,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	/* SMB2_SESSION_SETUP */ 25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	/* SMB2_LOGOFF */ 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	/* SMB2_TREE_CONNECT */	9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	/* SMB2_TREE_DISCONNECT */ 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	/* SMB2_CREATE */ 57,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	/* SMB2_CLOSE */ 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	/* SMB2_FLUSH */ 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	/* SMB2_READ */	49,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	/* SMB2_WRITE */ 49,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	/* SMB2_LOCK */	48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	/* SMB2_IOCTL */ 57,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 	/* SMB2_CANCEL */ 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	/* SMB2_ECHO */ 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	/* SMB2_QUERY_DIRECTORY */ 33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	/* SMB2_CHANGE_NOTIFY */ 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	/* SMB2_QUERY_INFO */ 41,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 	/* SMB2_SET_INFO */ 33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 	/* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) int smb3_encryption_required(const struct cifs_tcon *tcon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	if (!tcon || !tcon->ses)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	    (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	if (tcon->seal &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	    (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 		  const struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 		  struct TCP_Server_Info *server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	shdr->ProtocolId = SMB2_PROTO_NUMBER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	shdr->StructureSize = cpu_to_le16(64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	shdr->Command = smb2_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	if (server) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 		spin_lock(&server->req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 		/* Request up to 10 credits but don't go over the limit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 		if (server->credits >= server->max_credits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 			shdr->CreditRequest = cpu_to_le16(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 			shdr->CreditRequest = cpu_to_le16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 				min_t(int, server->max_credits -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 						server->credits, 10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 		spin_unlock(&server->req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 		shdr->CreditRequest = cpu_to_le16(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	shdr->ProcessId = cpu_to_le32((__u16)current->tgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	if (!tcon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	/* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	/* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	if (server && (server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 		shdr->CreditCharge = cpu_to_le16(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	/* else CreditCharge MBZ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	shdr->TreeId = tcon->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	/* Uid is not converted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	if (tcon->ses)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		shdr->SessionId = tcon->ses->Suid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	 * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	 * to pass the path on the Open SMB prefixed by \\server\share.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	 * Not sure when we would need to do the augmented path (if ever) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	 * setting this flag breaks the SMB2 open operation since it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	 * illegal to send an empty path name (without \\server\share prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	 * when the DFS flag is set in the SMB open header. We could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	 * consider setting the flag on all operations other than open
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	 * but it is safer to net set it for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) /*	if (tcon->share_flags & SHI1005_FLAGS_DFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 		shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	if (server && server->sign && !smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 		shdr->Flags |= SMB2_FLAGS_SIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	       struct TCP_Server_Info *server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	struct nls_table *nls_codepage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	struct cifs_ses *ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	int retries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	 * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	 * check for tcp and smb session status done differently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	 * for those three - in the calling routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	if (tcon == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	if (smb2_command == SMB2_TREE_CONNECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	if (tcon->tidStatus == CifsExiting) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 		 * only tree disconnect, open, and write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		 * (and ulogoff which does not have tcon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 		 * are allowed as we start force umount.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 		if ((smb2_command != SMB2_WRITE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 		   (smb2_command != SMB2_CREATE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 		   (smb2_command != SMB2_TREE_DISCONNECT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 			cifs_dbg(FYI, "can not send cmd %d while umounting\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 				 smb2_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 			return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	if ((!tcon->ses) || (tcon->ses->status == CifsExiting) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	    (!tcon->ses->server) || !server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	retries = server->nr_targets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	 * Give demultiplex thread up to 10 seconds to each target available for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	 * reconnect -- should be greater than cifs socket timeout which is 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	 * seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	while (server->tcpStatus == CifsNeedReconnect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 		 * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 		 * here since they are implicitly done when session drops.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 		switch (smb2_command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		 * BB Should we keep oplock break and add flush to exceptions?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 		case SMB2_TREE_DISCONNECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 		case SMB2_CANCEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 		case SMB2_CLOSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 		case SMB2_OPLOCK_BREAK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 			return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 		rc = wait_event_interruptible_timeout(server->response_q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 						      (server->tcpStatus != CifsNeedReconnect),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 						      10 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 		if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 			cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 				 __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 			return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 		/* are we still trying to reconnect? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 		if (server->tcpStatus != CifsNeedReconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 		if (retries && --retries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		 * on "soft" mounts we wait once. Hard mounts keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		 * retrying until process is killed or server comes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 		 * back on-line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 		if (!tcon->retry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 			cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 			return -EHOSTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 		retries = server->nr_targets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	nls_codepage = load_nls_default();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	 * need to prevent multiple threads trying to simultaneously reconnect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	 * the same SMB session
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	mutex_lock(&tcon->ses->session_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	 * Recheck after acquire mutex. If another thread is negotiating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	 * and the server never sends an answer the socket will be closed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	 * and tcpStatus set to reconnect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	if (server->tcpStatus == CifsNeedReconnect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 		rc = -EHOSTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 		mutex_unlock(&tcon->ses->session_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	 * If we are reconnecting an extra channel, bind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	if (server->is_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 		ses->binding = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 		ses->binding_chan = cifs_ses_find_chan(ses, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	rc = cifs_negotiate_protocol(0, tcon->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	if (!rc && tcon->ses->need_reconnect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 		rc = cifs_setup_session(0, tcon->ses, nls_codepage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 		if ((rc == -EACCES) && !tcon->retry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 			rc = -EHOSTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 			ses->binding = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 			ses->binding_chan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 			mutex_unlock(&tcon->ses->session_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 			goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	 * End of channel binding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	ses->binding = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	ses->binding_chan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	if (rc || !tcon->need_reconnect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		mutex_unlock(&tcon->ses->session_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	cifs_mark_open_files_invalid(tcon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	if (tcon->use_persistent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 		tcon->need_reopen_files = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	rc = cifs_tree_connect(0, tcon, nls_codepage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	mutex_unlock(&tcon->ses->session_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 		/* If sess reconnected but tcon didn't, something strange ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		pr_warn_once("reconnect tcon failed rc = %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	if (smb2_command != SMB2_INTERNAL_CMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 		mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	atomic_inc(&tconInfoReconnectCount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	 * Check if handle based operation so we know whether we can continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	 * or not without returning to caller to reset file handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	 * BB Is flush done by server on drop of tcp session? Should we special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	 * case it and skip above?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	switch (smb2_command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	case SMB2_FLUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	case SMB2_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	case SMB2_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	case SMB2_LOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	case SMB2_IOCTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	case SMB2_QUERY_DIRECTORY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	case SMB2_CHANGE_NOTIFY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	case SMB2_QUERY_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	case SMB2_SET_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		rc = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	unload_nls(nls_codepage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	       struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	       void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	       unsigned int *total_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	/* lookup word count ie StructureSize from table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	__u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	 * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	 * largest operations (Create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	memset(buf, 0, 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	spdu->StructureSize2 = cpu_to_le16(parmsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 	*total_len = parmsize + sizeof(struct smb2_sync_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364)  * Allocate and return pointer to an SMB request hdr, and set basic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365)  * SMB information in the SMB header. If the return code is zero, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366)  * function must have filled in request_buf pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 				 struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 				 void **request_buf, unsigned int *total_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	/* BB eventually switch this to SMB2 specific small buf size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	if (smb2_command == SMB2_SET_INFO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		*request_buf = cifs_buf_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		*request_buf = cifs_small_buf_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	if (*request_buf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		/* BB should we add a retry in here if not a writepage? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	fill_small_buf(smb2_command, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		       (struct smb2_sync_hdr *)(*request_buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 		       total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	if (tcon != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 		uint16_t com_code = le16_to_cpu(smb2_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 		cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		cifs_stats_inc(&tcon->num_smbs_sent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) static int smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 			       struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 			       void **request_buf, unsigned int *total_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	rc = smb2_reconnect(smb2_command, tcon, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	return __smb2_plain_req_init(smb2_command, tcon, server, request_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 				     total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) static int smb2_ioctl_req_init(u32 opcode, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 			       struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 			       void **request_buf, unsigned int *total_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	/* Skip reconnect only for FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		return __smb2_plain_req_init(SMB2_IOCTL, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 					     request_buf, total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	return smb2_plain_req_init(SMB2_IOCTL, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 				   request_buf, total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) /* For explanation of negotiate contexts see MS-SMB2 section 2.2.3.1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	pneg_ctxt->DataLength = cpu_to_le16(38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	pneg_ctxt->SaltLength = cpu_to_le16(SMB311_LINUX_CLIENT_SALT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	get_random_bytes(pneg_ctxt->Salt, SMB311_LINUX_CLIENT_SALT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	pneg_ctxt->DataLength =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		cpu_to_le16(sizeof(struct smb2_compression_capabilities_context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 			  - sizeof(struct smb2_neg_context));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	pneg_ctxt->CompressionAlgorithms[0] = SMB3_COMPRESS_LZ77;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	pneg_ctxt->CompressionAlgorithms[1] = SMB3_COMPRESS_LZ77_HUFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	pneg_ctxt->CompressionAlgorithms[2] = SMB3_COMPRESS_LZNT1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	if (require_gcm_256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + 1 cipher */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 		pneg_ctxt->CipherCount = cpu_to_le16(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES256_GCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	} else if (enable_gcm_256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		pneg_ctxt->DataLength = cpu_to_le16(8); /* Cipher Count + 3 ciphers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		pneg_ctxt->CipherCount = cpu_to_le16(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 		pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES256_GCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		pneg_ctxt->Ciphers[2] = SMB2_ENCRYPTION_AES128_CCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		pneg_ctxt->DataLength = cpu_to_le16(6); /* Cipher Count + 2 ciphers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		pneg_ctxt->CipherCount = cpu_to_le16(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES128_CCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) build_netname_ctxt(struct smb2_netname_neg_context *pneg_ctxt, char *hostname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	struct nls_table *cp = load_nls_default();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	pneg_ctxt->ContextType = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	/* copy up to max of first 100 bytes of server name to NetName field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	pneg_ctxt->DataLength = cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	/* context size is DataLength + minimal smb2_neg_context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	return DIV_ROUND_UP(le16_to_cpu(pneg_ctxt->DataLength) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 			sizeof(struct smb2_neg_context), 8) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	/* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	pneg_ctxt->Name[0] = 0x93;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	pneg_ctxt->Name[1] = 0xAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	pneg_ctxt->Name[2] = 0x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	pneg_ctxt->Name[3] = 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	pneg_ctxt->Name[4] = 0x9C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	pneg_ctxt->Name[5] = 0xB4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	pneg_ctxt->Name[6] = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	pneg_ctxt->Name[7] = 0xE7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	pneg_ctxt->Name[8] = 0xB4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	pneg_ctxt->Name[9] = 0x23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	pneg_ctxt->Name[10] = 0x83;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	pneg_ctxt->Name[11] = 0xDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	pneg_ctxt->Name[12] = 0x96;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	pneg_ctxt->Name[13] = 0x8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	pneg_ctxt->Name[14] = 0xCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	pneg_ctxt->Name[15] = 0x7C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) assemble_neg_contexts(struct smb2_negotiate_req *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 		      struct TCP_Server_Info *server, unsigned int *total_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	char *pneg_ctxt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	unsigned int ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	if (*total_len > 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		/* In case length corrupted don't want to overrun smb buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		cifs_server_dbg(VFS, "Bad frame length assembling neg contexts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	 * round up total_len of fixed part of SMB3 negotiate request to 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	 * byte boundary before adding negotiate contexts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	*total_len = roundup(*total_len, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	pneg_ctxt = (*total_len) + (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	req->NegotiateContextOffset = cpu_to_le32(*total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	*total_len += ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	pneg_ctxt += ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_encryption_neg_context), 8) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	*total_len += ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	pneg_ctxt += ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	if (server->compress_algorithm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		build_compression_ctxt((struct smb2_compression_capabilities_context *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 				pneg_ctxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		ctxt_len = DIV_ROUND_UP(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 			sizeof(struct smb2_compression_capabilities_context),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 				8) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		*total_len += ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		pneg_ctxt += ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		req->NegotiateContextCount = cpu_to_le16(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 		req->NegotiateContextCount = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 					server->hostname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	*total_len += ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	pneg_ctxt += ctxt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	*total_len += sizeof(struct smb2_posix_neg_context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	unsigned int len = le16_to_cpu(ctxt->DataLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	/* If invalid preauth context warn but use what we requested, SHA-512 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	if (len < MIN_PREAUTH_CTXT_DATA_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		pr_warn_once("server sent bad preauth context\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	} else if (len < MIN_PREAUTH_CTXT_DATA_LEN + le16_to_cpu(ctxt->SaltLength)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		pr_warn_once("server sent invalid SaltLength\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 		pr_warn_once("Invalid SMB3 hash algorithm count\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		pr_warn_once("unknown SMB3 hash algorithm\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) static void decode_compress_ctx(struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 			 struct smb2_compression_capabilities_context *ctxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	unsigned int len = le16_to_cpu(ctxt->DataLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	/* sizeof compress context is a one element compression capbility struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	if (len < 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		pr_warn_once("server sent bad compression cntxt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 		pr_warn_once("Invalid SMB3 compress algorithm count\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		pr_warn_once("unknown compression algorithm\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	server->compress_algorithm = ctxt->CompressionAlgorithms[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) static int decode_encrypt_ctx(struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 			      struct smb2_encryption_neg_context *ctxt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	unsigned int len = le16_to_cpu(ctxt->DataLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	if (len < MIN_ENCRYPT_CTXT_DATA_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 		pr_warn_once("server sent bad crypto ctxt len\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	if (le16_to_cpu(ctxt->CipherCount) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		pr_warn_once("Invalid SMB3.11 cipher count\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	cifs_dbg(FYI, "SMB311 cipher type:%d\n", le16_to_cpu(ctxt->Ciphers[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	if (require_gcm_256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		if (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES256_GCM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 			cifs_dbg(VFS, "Server does not support requested encryption type (AES256 GCM)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 			return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	} else if (ctxt->Ciphers[0] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		 * e.g. if server only supported AES256_CCM (very unlikely)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 		 * or server supported no encryption types or had all disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 		 * Since GLOBAL_CAP_ENCRYPTION will be not set, in the case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 		 * in which mount requested encryption ("seal") checks later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 		 * on during tree connection will return proper rc, but if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		 * seal not requested by client, since server is allowed to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 		 * return 0 to indicate no supported cipher, we can't fail here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 		server->cipher_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		server->capabilities &= ~SMB2_GLOBAL_CAP_ENCRYPTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 		pr_warn_once("Server does not support requested encryption types\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	} else if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		   (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		   (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES256_GCM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 		/* server returned a cipher we didn't ask for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 		pr_warn_once("Invalid SMB3.11 cipher returned\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	server->cipher_type = ctxt->Ciphers[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	server->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 				     struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 				     unsigned int len_of_smb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	struct smb2_neg_context *pctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	unsigned int len_of_ctxts, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	if (len_of_smb <= offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 		cifs_server_dbg(VFS, "Invalid response: negotiate context offset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	len_of_ctxts = len_of_smb - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	for (i = 0; i < ctxt_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		int clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		/* check that offset is not beyond end of SMB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		if (len_of_ctxts == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 		if (len_of_ctxts < sizeof(struct smb2_neg_context))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 		pctx = (struct smb2_neg_context *)(offset + (char *)rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		clen = le16_to_cpu(pctx->DataLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		if (clen > len_of_ctxts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 			decode_preauth_context(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 				(struct smb2_preauth_neg_context *)pctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 		else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 			rc = decode_encrypt_ctx(server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 				(struct smb2_encryption_neg_context *)pctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 		else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 			decode_compress_ctx(server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 				(struct smb2_compression_capabilities_context *)pctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 			server->posix_ext_supported = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 			cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 				le16_to_cpu(pctx->ContextType));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		/* offsets must be 8 byte aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		clen = (clen + 7) & ~0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		offset += clen + sizeof(struct smb2_neg_context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		len_of_ctxts -= clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) static struct create_posix *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) create_posix_buf(umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	struct create_posix *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	buf = kzalloc(sizeof(struct create_posix),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 			GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	buf->ccontext.DataOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 		cpu_to_le16(offsetof(struct create_posix, Mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	buf->ccontext.DataLength = cpu_to_le32(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	buf->ccontext.NameOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		cpu_to_le16(offsetof(struct create_posix, Name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	buf->ccontext.NameLength = cpu_to_le16(16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	/* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	buf->Name[0] = 0x93;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	buf->Name[1] = 0xAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	buf->Name[2] = 0x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	buf->Name[3] = 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	buf->Name[4] = 0x9C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	buf->Name[5] = 0xB4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	buf->Name[6] = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	buf->Name[7] = 0xE7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	buf->Name[8] = 0xB4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	buf->Name[9] = 0x23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	buf->Name[10] = 0x83;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	buf->Name[11] = 0xDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	buf->Name[12] = 0x96;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	buf->Name[13] = 0x8B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	buf->Name[14] = 0xCD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	buf->Name[15] = 0x7C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	buf->Mode = cpu_to_le32(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	cifs_dbg(FYI, "mode on posix create 0%o\n", mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	struct smb2_create_req *req = iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	unsigned int num = *num_iovec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	iov[num].iov_base = create_posix_buf(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	if (mode == ACL_NO_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 		cifs_dbg(FYI, "Invalid mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	if (iov[num].iov_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	iov[num].iov_len = sizeof(struct create_posix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	if (!req->CreateContextsOffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		req->CreateContextsOffset = cpu_to_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 				sizeof(struct smb2_create_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 				iov[num - 1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	*num_iovec = num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767)  *	SMB2 Worker functions follow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769)  *	The general structure of the worker functions is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770)  *	1) Call smb2_init (assembles SMB2 header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771)  *	2) Initialize SMB2 command specific fields in fixed length area of SMB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772)  *	3) Call smb_sendrcv2 (sends request on socket and waits for response)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773)  *	4) Decode SMB2 command specific fields in the fixed length area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774)  *	5) Decode variable length data area (if any for this SMB2 command type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775)  *	6) Call free smb buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776)  *	7) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	struct smb2_negotiate_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	struct smb2_negotiate_rsp *rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	int resp_buftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	struct TCP_Server_Info *server = cifs_ses_server(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	int blob_offset, blob_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	char *security_blob;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	int flags = CIFS_NEG_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	cifs_dbg(FYI, "Negotiate protocol\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	if (!server) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 		WARN(1, "%s: server is NULL!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	req->sync_hdr.SessionId = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	if (strcmp(server->vals->version_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		   SMB3ANY_VERSION_STRING) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		req->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 		req->DialectCount = cpu_to_le16(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 		total_len += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	} else if (strcmp(server->vals->version_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 		   SMBDEFAULT_VERSION_STRING) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 		req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 		req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		req->Dialects[3] = cpu_to_le16(SMB311_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		req->DialectCount = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 		total_len += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 		/* otherwise send specific dialect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 		req->Dialects[0] = cpu_to_le16(server->vals->protocol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		req->DialectCount = cpu_to_le16(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		total_len += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	/* only one of SMB2 signing flags may be set in SMB2 request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	if (ses->sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	else if (global_secflags & CIFSSEC_MAY_SIGN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 		req->SecurityMode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 	req->Capabilities = cpu_to_le32(server->vals->req_capabilities);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	if (ses->chan_max > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		req->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	/* ClientGUID must be zero for SMB2.02 dialect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	if (server->vals->protocol_id == SMB20_PROT_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 		memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		memcpy(req->ClientGUID, server->client_guid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			SMB2_CLIENT_GUID_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 		if ((server->vals->protocol_id == SMB311_PROT_ID) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 		    (strcmp(server->vals->version_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		     SMBDEFAULT_VERSION_STRING) == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 			assemble_neg_contexts(req, server, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	 * No tcon so can't do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	if (rc == -EOPNOTSUPP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		cifs_server_dbg(VFS, "Dialect not supported by server. Consider  specifying vers=1.0 or vers=2.0 on mount for accessing older servers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		goto neg_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	} else if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		goto neg_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	if (strcmp(server->vals->version_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		   SMB3ANY_VERSION_STRING) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 			cifs_server_dbg(VFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 				"SMB2 dialect returned but not requested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 		} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 			cifs_server_dbg(VFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 				"SMB2.1 dialect returned but not requested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	} else if (strcmp(server->vals->version_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		   SMBDEFAULT_VERSION_STRING) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 		if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 			cifs_server_dbg(VFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 				"SMB2 dialect returned but not requested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 		} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 			/* ops set to 3.0 by default for default so update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 			server->ops = &smb21_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 			server->vals = &smb21_values;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 		} else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 			server->ops = &smb311_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 			server->vals = &smb311_values;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	} else if (le16_to_cpu(rsp->DialectRevision) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 				server->vals->protocol_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		/* if requested single dialect ensure returned dialect matched */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 				le16_to_cpu(rsp->DialectRevision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		cifs_dbg(FYI, "negotiated smb2.0 dialect\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		cifs_dbg(FYI, "negotiated smb2.1 dialect\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		cifs_dbg(FYI, "negotiated smb3.0 dialect\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	else if (rsp->DialectRevision == cpu_to_le16(SMB302_PROT_ID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		cifs_dbg(FYI, "negotiated smb3.02 dialect\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 				le16_to_cpu(rsp->DialectRevision));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 		goto neg_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	server->dialect = le16_to_cpu(rsp->DialectRevision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	 * Keep a copy of the hash after negprot. This hash will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	 * the starting hash value for all sessions made from this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	 * server.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	memcpy(server->preauth_sha_hash, ses->preauth_sha_hash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	       SMB2_PREAUTH_HASH_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	/* SMB2 only has an extended negflavor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	/* set it to the maximum buffer size value we can send with 1 credit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 			       SMB2_MAX_BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	server->max_read = le32_to_cpu(rsp->MaxReadSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	server->max_write = le32_to_cpu(rsp->MaxWriteSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	server->sec_mode = le16_to_cpu(rsp->SecurityMode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	if ((server->sec_mode & SMB2_SEC_MODE_FLAGS_ALL) != server->sec_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		cifs_dbg(FYI, "Server returned unexpected security mode 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 				server->sec_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	server->capabilities = le32_to_cpu(rsp->Capabilities);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	/* Internal types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	 * SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	 * Set the cipher type manually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 					       (struct smb2_sync_hdr *)rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	 * See MS-SMB2 section 2.2.4: if no blob, client picks default which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	 * for us will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	 *	ses->sectype = RawNTLMSSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	 * but for time being this is our only auth choice so doesn't matter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	 * We just found a server which sets blob length to zero expecting raw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	if (blob_length == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		cifs_dbg(FYI, "missing security blob on negprot\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		server->sec_ntlmssp = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	rc = cifs_enable_signing(server, ses->sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		goto neg_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	if (blob_length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 		rc = decode_negTokenInit(security_blob, blob_length, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		if (rc == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 			rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 		else if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 			rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		if (rsp->NegotiateContextCount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 			rc = smb311_decode_neg_context(rsp, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 						       rsp_iov.iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 			cifs_server_dbg(VFS, "Missing expected negotiate contexts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) neg_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	struct validate_negotiate_info_req *pneg_inbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	struct validate_negotiate_info_rsp *pneg_rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	u32 rsplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	u32 inbuflen; /* max of 4 dialects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	struct TCP_Server_Info *server = tcon->ses->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	cifs_dbg(FYI, "validate negotiate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	/* In SMB3.11 preauth integrity supersedes validate negotiate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	if (server->dialect == SMB311_PROT_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	 * validation ioctl must be signed, so no point sending this if we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	 * can not sign it (ie are not known user).  Even if signing is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	 * required (enabled but not negotiated), in those cases we selectively
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	 * sign just this, the first and only signed request on a connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	 * Having validation of negotiate info  helps reduce attack vectors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		return 0; /* validation requires signing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	if (tcon->ses->user_name == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 		cifs_dbg(FYI, "Can't validate negotiate: null user mount\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		return 0; /* validation requires signing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		cifs_tcon_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	if (!pneg_inbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	pneg_inbuf->Capabilities =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 			cpu_to_le32(server->vals->req_capabilities);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	if (tcon->ses->chan_max > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		pneg_inbuf->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	memcpy(pneg_inbuf->Guid, server->client_guid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 					SMB2_CLIENT_GUID_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	if (tcon->ses->sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 		pneg_inbuf->SecurityMode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 			cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	else if (global_secflags & CIFSSEC_MAY_SIGN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 		pneg_inbuf->SecurityMode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 			cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 		pneg_inbuf->SecurityMode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	if (strcmp(server->vals->version_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		SMB3ANY_VERSION_STRING) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 		pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		pneg_inbuf->DialectCount = cpu_to_le16(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		/* structure is big enough for 3 dialects, sending only 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 		inbuflen = sizeof(*pneg_inbuf) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 				(2 * sizeof(pneg_inbuf->Dialects[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	} else if (strcmp(server->vals->version_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		SMBDEFAULT_VERSION_STRING) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 		pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 		pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 		pneg_inbuf->Dialects[3] = cpu_to_le16(SMB311_PROT_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 		pneg_inbuf->DialectCount = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 		/* structure is big enough for 3 dialects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 		inbuflen = sizeof(*pneg_inbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 		/* otherwise specific dialect was requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 		pneg_inbuf->Dialects[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 			cpu_to_le16(server->vals->protocol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 		pneg_inbuf->DialectCount = cpu_to_le16(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 		/* structure is big enough for 3 dialects, sending only 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 		inbuflen = sizeof(*pneg_inbuf) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 				sizeof(pneg_inbuf->Dialects[0]) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 		(char *)pneg_inbuf, inbuflen, CIFSMaxBufSize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 		(char **)&pneg_rsp, &rsplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	if (rc == -EOPNOTSUPP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 		 * Old Windows versions or Netapp SMB server can return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 		 * not supported error. Client should accept it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 		cifs_tcon_dbg(VFS, "Server does not support validate negotiate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		goto out_free_inbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	} else if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 		cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			      rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 		goto out_free_inbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	if (rsplen != sizeof(*pneg_rsp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 		cifs_tcon_dbg(VFS, "Invalid protocol negotiate response size: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 			      rsplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		/* relax check since Mac returns max bufsize allowed on ioctl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 			goto out_free_rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	/* check validate negotiate info response matches what we got earlier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 	if (pneg_rsp->Dialect != cpu_to_le16(server->dialect))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 		goto vneg_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	if (pneg_rsp->SecurityMode != cpu_to_le16(server->sec_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		goto vneg_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	/* do not validate server guid because not saved at negprot time yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	      SMB2_LARGE_FILES) != server->capabilities)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		goto vneg_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	/* validate negotiate successful */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	cifs_dbg(FYI, "validate negotiate info successful\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	goto out_free_rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) vneg_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	cifs_tcon_dbg(VFS, "protocol revalidation - security settings mismatch\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) out_free_rsp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 	kfree(pneg_rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) out_free_inbuf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	kfree(pneg_inbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) enum securityEnum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	switch (requested) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	case Kerberos:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	case RawNTLMSSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		return requested;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	case NTLMv2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		return RawNTLMSSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	case Unspecified:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 		if (server->sec_ntlmssp &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 			(global_secflags & CIFSSEC_MAY_NTLMSSP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 			return RawNTLMSSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 		if ((server->sec_kerberos || server->sec_mskerberos) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 			(global_secflags & CIFSSEC_MAY_KRB5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 			return Kerberos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 		return Unspecified;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) struct SMB2_sess_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	unsigned int xid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	struct cifs_ses *ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	struct nls_table *nls_cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	void (*func)(struct SMB2_sess_data *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	u64 previous_session;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	/* we will send the SMB in three pieces:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	 * a fixed length beginning part, an optional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	 * SPNEGO blob (which can be zero length), and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 	 * last part which will include the strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	 * and rest of bcc area. This allows us to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	 * a large buffer 17K allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	int buf0_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	struct kvec iov[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	struct cifs_ses *ses = sess_data->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	struct smb2_sess_setup_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	struct TCP_Server_Info *server = cifs_ses_server(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 				 (void **) &req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 				 &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	if (sess_data->ses->binding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 		req->sync_hdr.SessionId = sess_data->ses->Suid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		req->PreviousSessionId = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 		req->Flags = SMB2_SESSION_REQ_FLAG_BINDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		/* First session, not a reauthenticate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		req->sync_hdr.SessionId = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		 * if reconnect, we need to send previous sess id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 		 * otherwise it is 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 		req->PreviousSessionId = sess_data->previous_session;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 		req->Flags = 0; /* MBZ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	/* enough to enable echos and oplocks and one max size write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	req->sync_hdr.CreditRequest = cpu_to_le16(130);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	/* only one of SMB2 signing flags may be set in SMB2 request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	if (server->sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		req->SecurityMode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	else if (global_secflags & CIFSSEC_MAY_SIGN) /* one flag unlike MUST_ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 		req->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 		req->SecurityMode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) #ifdef CONFIG_CIFS_DFS_UPCALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	req->Capabilities = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) #endif /* DFS_UPCALL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	req->Channel = 0; /* MBZ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	sess_data->iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	/* 1 for pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	sess_data->iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	 * This variable will be used to clear the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	 * allocated above in case of any error in the calling function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	sess_data->buf0_type = CIFS_SMALL_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	sess_data->buf0_type = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 	struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	struct kvec rsp_iov = { NULL, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	/* Testing shows that buffer offset must be at location of Buffer[0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 	req->SecurityBufferOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 		cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 1 /* pad */);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 	req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 	rqst.rq_iov = sess_data->iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 	rqst.rq_nvec = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	/* BB add code to build os and lm fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	rc = cifs_send_recv(sess_data->xid, sess_data->ses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 			    cifs_ses_server(sess_data->ses),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 			    &rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 			    &sess_data->buf0_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 			    CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 	cifs_small_buf_release(sess_data->iov[0].iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 	memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	struct cifs_ses *ses = sess_data->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	struct TCP_Server_Info *server = cifs_ses_server(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	mutex_lock(&server->srv_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	if (server->ops->generate_signingkey) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 		rc = server->ops->generate_signingkey(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 		if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 			cifs_dbg(FYI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 				"SMB3 session key generation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 			mutex_unlock(&server->srv_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 	if (!server->session_estab) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 		server->sequence_number = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 		server->session_estab = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	mutex_unlock(&server->srv_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 	cifs_dbg(FYI, "SMB2/3 session established successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 	/* keep existing ses state if binding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	if (!ses->binding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 		spin_lock(&GlobalMid_Lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 		ses->status = CifsGood;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 		ses->need_reconnect = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 		spin_unlock(&GlobalMid_Lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) #ifdef CONFIG_CIFS_UPCALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 	struct cifs_ses *ses = sess_data->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	struct cifs_spnego_msg *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 	struct key *spnego_key = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 	struct smb2_sess_setup_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	rc = SMB2_sess_alloc_buffer(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	spnego_key = cifs_get_spnego_key(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	if (IS_ERR(spnego_key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 		rc = PTR_ERR(spnego_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 		if (rc == -ENOKEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 			cifs_dbg(VFS, "Verify user has a krb5 ticket and keyutils is installed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 		spnego_key = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	msg = spnego_key->payload.data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 	 * check version field to make sure that cifs.upcall is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 	 * sending us a response in an expected form
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 	if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		cifs_dbg(VFS, "bad cifs.upcall version. Expected %d got %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 			 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 		rc = -EKEYREJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 		goto out_put_spnego_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 	/* keep session key if binding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 	if (!ses->binding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 		ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 						 GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 		if (!ses->auth_key.response) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 			cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 				 msg->sesskey_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 			rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 			goto out_put_spnego_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 		ses->auth_key.len = msg->sesskey_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 	sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 	sess_data->iov[1].iov_len = msg->secblob_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 	rc = SMB2_sess_sendreceive(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 		goto out_put_spnego_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 	rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 	/* keep session id and flags if binding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 	if (!ses->binding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 		ses->Suid = rsp->sync_hdr.SessionId;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 		ses->session_flags = le16_to_cpu(rsp->SessionFlags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 	rc = SMB2_sess_establish_session(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) out_put_spnego_key:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 	key_invalidate(spnego_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 	key_put(spnego_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 	sess_data->result = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 	sess_data->func = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 	SMB2_sess_free_buffer(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 	cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	sess_data->result = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	sess_data->func = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	struct cifs_ses *ses = sess_data->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 	struct smb2_sess_setup_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 	char *ntlmssp_blob = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 	bool use_spnego = false; /* else use raw ntlmssp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 	u16 blob_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 	 * If memory allocation is successful, caller of this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 	 * frees it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 	ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 	if (!ses->ntlmssp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 		rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 		goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 	ses->ntlmssp->sesskey_per_smbsess = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	rc = SMB2_sess_alloc_buffer(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 		goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 			       GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 	if (ntlmssp_blob == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 		rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	build_ntlmssp_negotiate_blob(ntlmssp_blob, ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 	if (use_spnego) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 		/* BB eventually need to add this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 		cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 		rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 		blob_length = sizeof(struct _NEGOTIATE_MESSAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 		/* with raw NTLMSSP we don't encapsulate in SPNEGO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 	sess_data->iov[1].iov_base = ntlmssp_blob;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 	sess_data->iov[1].iov_len = blob_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 	rc = SMB2_sess_sendreceive(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 	rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 	/* If true, rc here is expected and not an error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 	if (sess_data->buf0_type != CIFS_NO_BUFFER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 		rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 	if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 			le16_to_cpu(rsp->SecurityBufferOffset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 		cifs_dbg(VFS, "Invalid security buffer offset %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 			le16_to_cpu(rsp->SecurityBufferOffset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 	rc = decode_ntlmssp_challenge(rsp->Buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 			le16_to_cpu(rsp->SecurityBufferLength), ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 	/* keep existing ses id and flags if binding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 	if (!ses->binding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 		ses->Suid = rsp->sync_hdr.SessionId;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 		ses->session_flags = le16_to_cpu(rsp->SessionFlags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 	kfree(ntlmssp_blob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 	SMB2_sess_free_buffer(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 		sess_data->result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 		sess_data->func = SMB2_sess_auth_rawntlmssp_authenticate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 	kfree(ses->ntlmssp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 	ses->ntlmssp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 	sess_data->result = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 	sess_data->func = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 	struct cifs_ses *ses = sess_data->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 	struct smb2_sess_setup_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 	struct smb2_sess_setup_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 	unsigned char *ntlmssp_blob = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 	bool use_spnego = false; /* else use raw ntlmssp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 	u16 blob_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 	rc = SMB2_sess_alloc_buffer(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 	req->sync_hdr.SessionId = ses->Suid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 					sess_data->nls_cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 		cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 	if (use_spnego) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 		/* BB eventually need to add this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 		cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 		rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 	sess_data->iov[1].iov_base = ntlmssp_blob;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 	sess_data->iov[1].iov_len = blob_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	rc = SMB2_sess_sendreceive(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 	rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	/* keep existing ses id and flags if binding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	if (!ses->binding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 		ses->Suid = rsp->sync_hdr.SessionId;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 		ses->session_flags = le16_to_cpu(rsp->SessionFlags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 	rc = SMB2_sess_establish_session(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) #ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 	if (ses->server->dialect < SMB30_PROT_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 		cifs_dbg(VFS, "%s: dumping generated SMB2 session keys\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 		 * The session id is opaque in terms of endianness, so we can't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 		 * print it as a long long. we dump it as we got it on the wire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 		cifs_dbg(VFS, "Session Id    %*ph\n", (int)sizeof(ses->Suid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 			 &ses->Suid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 		cifs_dbg(VFS, "Session Key   %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) 			 SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 		cifs_dbg(VFS, "Signing Key   %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) 			 SMB3_SIGN_KEY_SIZE, ses->auth_key.response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 	kfree(ntlmssp_blob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 	SMB2_sess_free_buffer(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 	kfree(ses->ntlmssp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	ses->ntlmssp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 	sess_data->result = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 	sess_data->func = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 	int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 	type = smb2_select_sectype(cifs_ses_server(ses), ses->sectype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 	cifs_dbg(FYI, "sess setup type %d\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 	if (type == Unspecified) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 		cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) 	switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 	case Kerberos:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 		sess_data->func = SMB2_auth_kerberos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 	case RawNTLMSSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 		sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 		cifs_dbg(VFS, "secType %d not supported!\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) 		const struct nls_table *nls_cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 	struct TCP_Server_Info *server = cifs_ses_server(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 	struct SMB2_sess_data *sess_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 	cifs_dbg(FYI, "Session Setup\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 	if (!server) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) 		WARN(1, "%s: server is NULL!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 	sess_data = kzalloc(sizeof(struct SMB2_sess_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	if (!sess_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 	rc = SMB2_select_sec(ses, sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 	sess_data->xid = xid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 	sess_data->ses = ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 	sess_data->buf0_type = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 	sess_data->nls_cp = (struct nls_table *) nls_cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 	sess_data->previous_session = ses->Suid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 	 * Initialize the session hash with the server one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 	memcpy(ses->preauth_sha_hash, server->preauth_sha_hash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 	       SMB2_PREAUTH_HASH_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 	while (sess_data->func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 		sess_data->func(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 	if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 		cifs_server_dbg(VFS, "signing requested but authenticated as guest\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 	rc = sess_data->result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 	kfree(sess_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 	struct smb2_logoff_req *req; /* response is also trivial struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 	struct TCP_Server_Info *server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 	int resp_buf_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 	cifs_dbg(FYI, "disconnect session %p\n", ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 	if (ses && (ses->server))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 		server = ses->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 	/* no need to send SMB logoff if uid already closed due to reconnect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 	if (ses->need_reconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 		goto smb2_session_already_dead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 	rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 	 /* since no tcon, smb2_init can not do this, so do here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 	req->sync_hdr.SessionId = ses->Suid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 	if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 	else if (server->sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 		req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 	flags |= CIFS_NO_RSP_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 	rc = cifs_send_recv(xid, ses, ses->server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 			    &rqst, &resp_buf_type, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 	 * No tcon so can't do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 	 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) smb2_session_already_dead:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 	cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_failed[code]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) #define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) /* These are similar values to what Windows uses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) static inline void init_copy_chunk_defaults(struct cifs_tcon *tcon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 	tcon->max_chunks = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 	tcon->max_bytes_chunk = 1048576;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 	tcon->max_bytes_copy = 16777216;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 	  struct cifs_tcon *tcon, const struct nls_table *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 	struct smb2_tree_connect_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 	struct smb2_tree_connect_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 	struct kvec iov[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 	struct kvec rsp_iov = { NULL, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 	int resp_buftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 	int unc_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 	__le16 *unc_path = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 	struct TCP_Server_Info *server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 	/* always use master channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 	server = ses->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) 	cifs_dbg(FYI, "TCON\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 	if (!server || !tree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 	unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 	if (unc_path == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 	unc_path_len = cifs_strtoUTF16(unc_path, tree, strlen(tree), cp) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 	unc_path_len *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 	if (unc_path_len < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 		kfree(unc_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 	/* SMB2 TREE_CONNECT request must be called with TreeId == 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 	tcon->tid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 	atomic_set(&tcon->num_remote_opens, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 	rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 		kfree(unc_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) 	/* 1 for pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 	iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 	/* Testing shows that buffer offset must be at location of Buffer[0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 	req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 			- 1 /* pad */);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 	req->PathLength = cpu_to_le16(unc_path_len - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 	iov[1].iov_base = unc_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) 	iov[1].iov_len = unc_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 	 * 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 	 * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 	 * (Samba servers don't always set the flag so also check if null user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 	if ((server->dialect == SMB311_PROT_ID) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 	    !smb3_encryption_required(tcon) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 	    !(ses->session_flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 		    (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 	    ((ses->user_name != NULL) || (ses->sectype == Kerberos)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 		req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 	rqst.rq_nvec = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 	/* Need 64 for max size write so ask for more in case not there yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 	req->sync_hdr.CreditRequest = cpu_to_le16(64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 	rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 	trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 		if (tcon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) 			cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 			tcon->need_reconnect = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 		goto tcon_error_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 	switch (rsp->ShareType) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 	case SMB2_SHARE_TYPE_DISK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 		cifs_dbg(FYI, "connection to disk share\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 	case SMB2_SHARE_TYPE_PIPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 		tcon->pipe = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 		cifs_dbg(FYI, "connection to pipe share\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 	case SMB2_SHARE_TYPE_PRINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 		tcon->print = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 		cifs_dbg(FYI, "connection to printer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 		cifs_server_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 		rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 		goto tcon_error_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 	tcon->share_flags = le32_to_cpu(rsp->ShareFlags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 	tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 	tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 	tcon->tidStatus = CifsGood;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 	tcon->need_reconnect = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 	tcon->tid = rsp->sync_hdr.TreeId;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 	strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 	if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 	    ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 		cifs_tcon_dbg(VFS, "DFS capability contradicts DFS flag\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 	if (tcon->seal &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 	    !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 		cifs_tcon_dbg(VFS, "Encryption is requested but not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 	init_copy_chunk_defaults(tcon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) 	if (server->ops->validate_negotiate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 		rc = server->ops->validate_negotiate(xid, tcon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) tcon_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 	kfree(unc_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) tcon_error_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 	if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) 		cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 	goto tcon_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 	struct smb2_tree_disconnect_req *req; /* response is trivial */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) 	int resp_buf_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 	cifs_dbg(FYI, "Tree Disconnect\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) 	if (!ses || !(ses->server))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) 	if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 	close_shroot_lease(&tcon->crfid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 	rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, ses->server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) 				 (void **) &req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 				 &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) 	flags |= CIFS_NO_RSP_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) 	rc = cifs_send_recv(xid, ses, ses->server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) 			    &rqst, &resp_buf_type, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) 		cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) static struct create_durable *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) create_durable_buf(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) 	struct create_durable *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) 	buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) 	buf->ccontext.DataOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) 					(struct create_durable, Data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) 	buf->ccontext.DataLength = cpu_to_le32(16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) 	buf->ccontext.NameOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) 				(struct create_durable, Name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) 	buf->ccontext.NameLength = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) 	/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) 	buf->Name[0] = 'D';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) 	buf->Name[1] = 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) 	buf->Name[2] = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) 	buf->Name[3] = 'Q';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) static struct create_durable *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) create_reconnect_durable_buf(struct cifs_fid *fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) 	struct create_durable *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) 	buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) 	buf->ccontext.DataOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) 					(struct create_durable, Data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) 	buf->ccontext.DataLength = cpu_to_le32(16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) 	buf->ccontext.NameOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) 				(struct create_durable, Name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) 	buf->ccontext.NameLength = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) 	buf->Data.Fid.PersistentFileId = fid->persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) 	buf->Data.Fid.VolatileFileId = fid->volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) 	/* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) 	buf->Name[0] = 'D';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) 	buf->Name[1] = 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) 	buf->Name[2] = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) 	buf->Name[3] = 'C';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) 	struct create_on_disk_id *pdisk_id = (struct create_on_disk_id *)cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) 	cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) 		pdisk_id->DiskFileId, pdisk_id->VolumeId);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) 	buf->IndexNumber = pdisk_id->DiskFileId;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) 		 struct create_posix_rsp *posix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) 	int sid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) 	u8 *beg = (u8 *)cc + le16_to_cpu(cc->DataOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) 	u8 *end = beg + le32_to_cpu(cc->DataLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) 	u8 *sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) 	memset(posix, 0, sizeof(*posix));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) 	posix->nlink = le32_to_cpu(*(__le32 *)(beg + 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) 	posix->reparse_tag = le32_to_cpu(*(__le32 *)(beg + 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) 	posix->mode = le32_to_cpu(*(__le32 *)(beg + 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) 	sid = beg + 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) 	sid_len = posix_info_sid_size(sid, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) 	if (sid_len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) 		cifs_dbg(VFS, "bad owner sid in posix create response\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) 	memcpy(&posix->owner, sid, sid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) 	sid = sid + sid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) 	sid_len = posix_info_sid_size(sid, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) 	if (sid_len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) 		cifs_dbg(VFS, "bad group sid in posix create response\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) 	memcpy(&posix->group, sid, sid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) 	cifs_dbg(FYI, "nlink=%d mode=%o reparse_tag=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) 		 posix->nlink, posix->mode, posix->reparse_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) smb2_parse_contexts(struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) 		    struct smb2_create_rsp *rsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) 		    unsigned int *epoch, char *lease_key, __u8 *oplock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) 		    struct smb2_file_all_info *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) 		    struct create_posix_rsp *posix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) 	char *data_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) 	struct create_context *cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) 	unsigned int next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) 	unsigned int remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) 	static const char smb3_create_tag_posix[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) 		0x93, 0xAD, 0x25, 0x50, 0x9C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) 		0xB4, 0x11, 0xE7, 0xB4, 0x23, 0x83,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) 		0xDE, 0x96, 0x8B, 0xCD, 0x7C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) 	*oplock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) 	data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) 	remaining = le32_to_cpu(rsp->CreateContextsLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) 	cc = (struct create_context *)data_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) 	/* Initialize inode number to 0 in case no valid data in qfid context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) 	if (buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) 		buf->IndexNumber = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) 	while (remaining >= sizeof(struct create_context)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) 		name = le16_to_cpu(cc->NameOffset) + (char *)cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) 		if (le16_to_cpu(cc->NameLength) == 4 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) 		    strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) 			*oplock = server->ops->parse_lease_buf(cc, epoch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) 							   lease_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) 		else if (buf && (le16_to_cpu(cc->NameLength) == 4) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) 		    strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) 			parse_query_id_ctxt(cc, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) 		else if ((le16_to_cpu(cc->NameLength) == 16)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) 			if (posix &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) 			    memcmp(name, smb3_create_tag_posix, 16) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) 				parse_posix_ctxt(cc, buf, posix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) 		/* else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) 			cifs_dbg(FYI, "Context not matched with len %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) 				le16_to_cpu(cc->NameLength));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) 			cifs_dump_mem("Cctxt name: ", name, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) 		} */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) 		next = le32_to_cpu(cc->Next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) 		if (!next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) 		remaining -= next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) 		cc = (struct create_context *)((char *)cc + next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) 	if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) 		*oplock = rsp->OplockLevel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) 		  unsigned int *num_iovec, u8 *lease_key, __u8 *oplock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) 	struct smb2_create_req *req = iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) 	unsigned int num = *num_iovec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) 	iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) 	if (iov[num].iov_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) 	iov[num].iov_len = server->vals->create_lease_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) 	req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) 	if (!req->CreateContextsOffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) 		req->CreateContextsOffset = cpu_to_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) 				sizeof(struct smb2_create_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) 				iov[num - 1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) 	le32_add_cpu(&req->CreateContextsLength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) 		     server->vals->create_lease_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) 	*num_iovec = num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) static struct create_durable_v2 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) create_durable_v2_buf(struct cifs_open_parms *oparms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) 	struct cifs_fid *pfid = oparms->fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) 	struct create_durable_v2 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) 	buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) 	buf->ccontext.DataOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) 					(struct create_durable_v2, dcontext));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) 	buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) 	buf->ccontext.NameOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) 				(struct create_durable_v2, Name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) 	buf->ccontext.NameLength = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) 	 * NB: Handle timeout defaults to 0, which allows server to choose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) 	 * (most servers default to 120 seconds) and most clients default to 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) 	 * This can be overridden at mount ("handletimeout=") if the user wants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) 	 * a different persistent (or resilient) handle timeout for all opens
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) 	 * opens on a particular SMB3 mount.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) 	buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) 	buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) 	generate_random_uuid(buf->dcontext.CreateGuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) 	memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) 	/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) 	buf->Name[0] = 'D';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) 	buf->Name[1] = 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) 	buf->Name[2] = '2';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) 	buf->Name[3] = 'Q';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) static struct create_durable_handle_reconnect_v2 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) create_reconnect_durable_v2_buf(struct cifs_fid *fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) 	struct create_durable_handle_reconnect_v2 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) 	buf = kzalloc(sizeof(struct create_durable_handle_reconnect_v2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) 			GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) 	buf->ccontext.DataOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) 		cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) 				     dcontext));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) 	buf->ccontext.DataLength =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) 		cpu_to_le32(sizeof(struct durable_reconnect_context_v2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) 	buf->ccontext.NameOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) 		cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) 			    Name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) 	buf->ccontext.NameLength = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) 	buf->dcontext.Fid.PersistentFileId = fid->persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) 	buf->dcontext.Fid.VolatileFileId = fid->volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) 	buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) 	memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) 	/* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) 	buf->Name[0] = 'D';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) 	buf->Name[1] = 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) 	buf->Name[2] = '2';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) 	buf->Name[3] = 'C';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) 		    struct cifs_open_parms *oparms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) 	struct smb2_create_req *req = iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) 	unsigned int num = *num_iovec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) 	iov[num].iov_base = create_durable_v2_buf(oparms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) 	if (iov[num].iov_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) 	iov[num].iov_len = sizeof(struct create_durable_v2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) 	if (!req->CreateContextsOffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) 		req->CreateContextsOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) 			cpu_to_le32(sizeof(struct smb2_create_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) 								iov[1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) 	le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) 	*num_iovec = num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) 		    struct cifs_open_parms *oparms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) 	struct smb2_create_req *req = iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) 	unsigned int num = *num_iovec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) 	/* indicate that we don't need to relock the file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) 	oparms->reconnect = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) 	iov[num].iov_base = create_reconnect_durable_v2_buf(oparms->fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) 	if (iov[num].iov_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) 	iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) 	if (!req->CreateContextsOffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) 		req->CreateContextsOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) 			cpu_to_le32(sizeof(struct smb2_create_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) 								iov[1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) 	le32_add_cpu(&req->CreateContextsLength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) 			sizeof(struct create_durable_handle_reconnect_v2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) 	*num_iovec = num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) add_durable_context(struct kvec *iov, unsigned int *num_iovec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) 		    struct cifs_open_parms *oparms, bool use_persistent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) 	struct smb2_create_req *req = iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) 	unsigned int num = *num_iovec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) 	if (use_persistent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) 		if (oparms->reconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) 			return add_durable_reconnect_v2_context(iov, num_iovec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) 								oparms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) 			return add_durable_v2_context(iov, num_iovec, oparms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) 	if (oparms->reconnect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) 		iov[num].iov_base = create_reconnect_durable_buf(oparms->fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) 		/* indicate that we don't need to relock the file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) 		oparms->reconnect = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) 		iov[num].iov_base = create_durable_buf();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) 	if (iov[num].iov_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) 	iov[num].iov_len = sizeof(struct create_durable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) 	if (!req->CreateContextsOffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) 		req->CreateContextsOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) 			cpu_to_le32(sizeof(struct smb2_create_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) 								iov[1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) 	le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) 	*num_iovec = num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) /* See MS-SMB2 2.2.13.2.7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) static struct crt_twarp_ctxt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) create_twarp_buf(__u64 timewarp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) 	struct crt_twarp_ctxt *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) 	buf = kzalloc(sizeof(struct crt_twarp_ctxt), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) 	buf->ccontext.DataOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) 					(struct crt_twarp_ctxt, Timestamp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) 	buf->ccontext.DataLength = cpu_to_le32(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) 	buf->ccontext.NameOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) 				(struct crt_twarp_ctxt, Name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) 	buf->ccontext.NameLength = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) 	/* SMB2_CREATE_TIMEWARP_TOKEN is "TWrp" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) 	buf->Name[0] = 'T';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) 	buf->Name[1] = 'W';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) 	buf->Name[2] = 'r';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) 	buf->Name[3] = 'p';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) 	buf->Timestamp = cpu_to_le64(timewarp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) /* See MS-SMB2 2.2.13.2.7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) 	struct smb2_create_req *req = iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) 	unsigned int num = *num_iovec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) 	iov[num].iov_base = create_twarp_buf(timewarp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) 	if (iov[num].iov_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) 	iov[num].iov_len = sizeof(struct crt_twarp_ctxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) 	if (!req->CreateContextsOffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) 		req->CreateContextsOffset = cpu_to_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) 				sizeof(struct smb2_create_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) 				iov[num - 1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) 	le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_twarp_ctxt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) 	*num_iovec = num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) /* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) static void setup_owner_group_sids(char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) 	struct owner_group_sids *sids = (struct owner_group_sids *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) 	/* Populate the user ownership fields S-1-5-88-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) 	sids->owner.Revision = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) 	sids->owner.NumAuth = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) 	sids->owner.Authority[5] = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) 	sids->owner.SubAuthorities[0] = cpu_to_le32(88);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) 	sids->owner.SubAuthorities[1] = cpu_to_le32(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) 	sids->owner.SubAuthorities[2] = cpu_to_le32(current_fsuid().val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) 	/* Populate the group ownership fields S-1-5-88-2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) 	sids->group.Revision = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) 	sids->group.NumAuth = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) 	sids->group.Authority[5] = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) 	sids->group.SubAuthorities[0] = cpu_to_le32(88);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) 	sids->group.SubAuthorities[1] = cpu_to_le32(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) 	sids->group.SubAuthorities[2] = cpu_to_le32(current_fsgid().val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) 	cifs_dbg(FYI, "owner S-1-5-88-1-%d, group S-1-5-88-2-%d\n", current_fsuid().val, current_fsgid().val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) /* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) static struct crt_sd_ctxt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) 	struct crt_sd_ctxt *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) 	__u8 *ptr, *aclptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) 	unsigned int acelen, acl_size, ace_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) 	unsigned int owner_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) 	unsigned int group_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) 	struct smb3_acl acl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) 	*len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) 	if (set_owner) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) 		/* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) 		*len += sizeof(struct owner_group_sids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) 	buf = kzalloc(*len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) 	if (buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) 		return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) 	ptr = (__u8 *)&buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) 	if (set_owner) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) 		/* offset fields are from beginning of security descriptor not of create context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) 		owner_offset = ptr - (__u8 *)&buf->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) 		buf->sd.OffsetOwner = cpu_to_le32(owner_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) 		group_offset = owner_offset + offsetof(struct owner_group_sids, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) 		buf->sd.OffsetGroup = cpu_to_le32(group_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) 		setup_owner_group_sids(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) 		ptr += sizeof(struct owner_group_sids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) 		buf->sd.OffsetOwner = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) 		buf->sd.OffsetGroup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) 	buf->ccontext.DataOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, sd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) 	buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) 	buf->ccontext.NameLength = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) 	/* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) 	buf->Name[0] = 'S';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) 	buf->Name[1] = 'e';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) 	buf->Name[2] = 'c';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) 	buf->Name[3] = 'D';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) 	buf->sd.Revision = 1;  /* Must be one see MS-DTYP 2.4.6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) 	 * ACL is "self relative" ie ACL is stored in contiguous block of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) 	 * and "DP" ie the DACL is present
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) 	buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) 	/* offset owner, group and Sbz1 and SACL are all zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) 	buf->sd.OffsetDacl = cpu_to_le32(ptr - (__u8 *)&buf->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) 	/* Ship the ACL for now. we will copy it into buf later. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) 	aclptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) 	ptr += sizeof(struct smb3_acl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) 	/* create one ACE to hold the mode embedded in reserved special SID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) 	acelen = setup_special_mode_ACE((struct cifs_ace *)ptr, (__u64)mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) 	ptr += acelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) 	acl_size = acelen + sizeof(struct smb3_acl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) 	ace_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) 	if (set_owner) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) 		/* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) 		acelen = setup_special_user_owner_ACE((struct cifs_ace *)ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) 		ptr += acelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) 		acl_size += acelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) 		ace_count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) 	/* and one more ACE to allow access for authenticated users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) 	acelen = setup_authusers_ACE((struct cifs_ace *)ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) 	ptr += acelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) 	acl_size += acelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) 	ace_count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) 	acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) 	acl.AclSize = cpu_to_le16(acl_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) 	acl.AceCount = cpu_to_le16(ace_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) 	memcpy(aclptr, &acl, sizeof(struct smb3_acl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) 	buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) 	*len = roundup(ptr - (__u8 *)buf, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) 	struct smb2_create_req *req = iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) 	unsigned int num = *num_iovec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) 	unsigned int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) 	iov[num].iov_base = create_sd_buf(mode, set_owner, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) 	if (iov[num].iov_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) 	iov[num].iov_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) 	if (!req->CreateContextsOffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) 		req->CreateContextsOffset = cpu_to_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) 				sizeof(struct smb2_create_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) 				iov[num - 1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) 	le32_add_cpu(&req->CreateContextsLength, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) 	*num_iovec = num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) static struct crt_query_id_ctxt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) create_query_id_buf(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) 	struct crt_query_id_ctxt *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) 	buf = kzalloc(sizeof(struct crt_query_id_ctxt), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) 	buf->ccontext.DataOffset = cpu_to_le16(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) 	buf->ccontext.DataLength = cpu_to_le32(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) 	buf->ccontext.NameOffset = cpu_to_le16(offsetof
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) 				(struct crt_query_id_ctxt, Name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) 	buf->ccontext.NameLength = cpu_to_le16(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) 	/* SMB2_CREATE_QUERY_ON_DISK_ID is "QFid" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) 	buf->Name[0] = 'Q';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) 	buf->Name[1] = 'F';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) 	buf->Name[2] = 'i';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) 	buf->Name[3] = 'd';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) /* See MS-SMB2 2.2.13.2.9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) add_query_id_context(struct kvec *iov, unsigned int *num_iovec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) 	struct smb2_create_req *req = iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) 	unsigned int num = *num_iovec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) 	iov[num].iov_base = create_query_id_buf();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) 	if (iov[num].iov_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) 	iov[num].iov_len = sizeof(struct crt_query_id_ctxt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) 	if (!req->CreateContextsOffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) 		req->CreateContextsOffset = cpu_to_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) 				sizeof(struct smb2_create_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) 				iov[num - 1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) 	le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_query_id_ctxt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) 	*num_iovec = num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) 			    const char *treename, const __le16 *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) 	int treename_len, path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) 	struct nls_table *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) 	const __le16 sep[] = {cpu_to_le16('\\'), cpu_to_le16(0x0000)};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) 	 * skip leading "\\"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) 	treename_len = strlen(treename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) 	if (treename_len < 2 || !(treename[0] == '\\' && treename[1] == '\\'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) 	treename += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) 	treename_len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) 	path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) 	 * make room for one path separator between the treename and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) 	 * path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) 	*out_len = treename_len + 1 + path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) 	 * final path needs to be null-terminated UTF16 with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) 	 * size aligned to 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) 	*out_size = roundup((*out_len+1)*2, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) 	*out_path = kzalloc(*out_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) 	if (!*out_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) 	cp = load_nls_default();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) 	cifs_strtoUTF16(*out_path, treename, treename_len, cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) 	UniStrcat(*out_path, sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) 	UniStrcat(*out_path, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) 	unload_nls(cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) 			       umode_t mode, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) 			       const char *full_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) 			       struct cifs_sb_info *cifs_sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) 	struct smb2_create_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) 	struct smb2_create_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) 	struct kvec iov[3]; /* make sure at least one for each open context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) 	struct kvec rsp_iov = {NULL, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) 	int resp_buftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) 	int uni_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) 	__le16 *copy_path = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) 	int copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) 	unsigned int n_iov = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) 	__u32 file_attributes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) 	char *pc_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) 	__le16 *utf16_path = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) 	cifs_dbg(FYI, "mkdir\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) 	/* resource #1: path allocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) 	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) 	if (!utf16_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) 	if (!ses || !server) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) 		goto err_free_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) 	/* resource #2: request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) 	rc = smb2_plain_req_init(SMB2_CREATE, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) 		goto err_free_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) 	req->ImpersonationLevel = IL_IMPERSONATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) 	req->DesiredAccess = cpu_to_le32(FILE_WRITE_ATTRIBUTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) 	/* File attributes ignored on open (used in create though) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) 	req->FileAttributes = cpu_to_le32(file_attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) 	req->ShareAccess = FILE_SHARE_ALL_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) 	req->CreateDisposition = cpu_to_le32(FILE_CREATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) 	req->CreateOptions = cpu_to_le32(CREATE_NOT_FILE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) 	/* -1 since last byte is buf[0] which is sent below (path) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) 	iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) 	req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) 	/* [MS-SMB2] 2.2.13 NameOffset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) 	 * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) 	 * the SMB2 header, the file name includes a prefix that will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) 	 * be processed during DFS name normalization as specified in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) 	 * section 3.3.5.9. Otherwise, the file name is relative to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) 	 * the share that is identified by the TreeId in the SMB2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) 	 * header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) 	if (tcon->share_flags & SHI1005_FLAGS_DFS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) 		int name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) 		req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) 		rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) 						 &name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) 						 tcon->treeName, utf16_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) 			goto err_free_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) 		req->NameLength = cpu_to_le16(name_len * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) 		uni_path_len = copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) 		/* free before overwriting resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) 		kfree(utf16_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) 		utf16_path = copy_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) 		uni_path_len = (2 * UniStrnlen((wchar_t *)utf16_path, PATH_MAX)) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) 		/* MUST set path len (NameLength) to 0 opening root of share */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) 		req->NameLength = cpu_to_le16(uni_path_len - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) 		if (uni_path_len % 8 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) 			copy_size = roundup(uni_path_len, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) 			copy_path = kzalloc(copy_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) 			if (!copy_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) 				rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) 				goto err_free_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) 			memcpy((char *)copy_path, (const char *)utf16_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) 			       uni_path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) 			uni_path_len = copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) 			/* free before overwriting resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) 			kfree(utf16_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) 			utf16_path = copy_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) 	iov[1].iov_len = uni_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) 	iov[1].iov_base = utf16_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) 	req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) 	if (tcon->posix_extensions) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) 		/* resource #3: posix buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) 		rc = add_posix_context(iov, &n_iov, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) 			goto err_free_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) 		pc_buf = iov[n_iov-1].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) 	rqst.rq_nvec = n_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) 	/* no need to inc num_remote_opens because we close it just below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) 	trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, CREATE_NOT_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) 				    FILE_WRITE_ATTRIBUTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) 	/* resource #4: response buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) 		cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) 		trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) 					   CREATE_NOT_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) 					   FILE_WRITE_ATTRIBUTES, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) 		goto err_free_rsp_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) 	rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) 	trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) 				    ses->Suid, CREATE_NOT_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) 				    FILE_WRITE_ATTRIBUTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) 	SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) 	/* Eventually save off posix specific response info and timestaps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) err_free_rsp_buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) 	kfree(pc_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) err_free_req:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) err_free_path:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) 	kfree(utf16_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) 	       struct smb_rqst *rqst, __u8 *oplock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) 	       struct cifs_open_parms *oparms, __le16 *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) 	struct smb2_create_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) 	unsigned int n_iov = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) 	__u32 file_attributes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) 	int copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) 	int uni_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) 	struct kvec *iov = rqst->rq_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) 	__le16 *copy_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) 	rc = smb2_plain_req_init(SMB2_CREATE, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) 	/* -1 since last byte is buf[0] which is sent below (path) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) 	iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) 	if (oparms->create_options & CREATE_OPTION_READONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) 		file_attributes |= ATTR_READONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) 	if (oparms->create_options & CREATE_OPTION_SPECIAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) 		file_attributes |= ATTR_SYSTEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) 	req->ImpersonationLevel = IL_IMPERSONATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) 	req->DesiredAccess = cpu_to_le32(oparms->desired_access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) 	/* File attributes ignored on open (used in create though) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) 	req->FileAttributes = cpu_to_le32(file_attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) 	req->ShareAccess = FILE_SHARE_ALL_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) 	req->CreateDisposition = cpu_to_le32(oparms->disposition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) 	req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) 	req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) 	/* [MS-SMB2] 2.2.13 NameOffset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) 	 * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) 	 * the SMB2 header, the file name includes a prefix that will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) 	 * be processed during DFS name normalization as specified in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) 	 * section 3.3.5.9. Otherwise, the file name is relative to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) 	 * the share that is identified by the TreeId in the SMB2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) 	 * header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) 	if (tcon->share_flags & SHI1005_FLAGS_DFS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) 		int name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) 		req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) 		rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) 						 &name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) 						 tcon->treeName, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) 		req->NameLength = cpu_to_le16(name_len * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) 		uni_path_len = copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) 		path = copy_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) 		uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) 		/* MUST set path len (NameLength) to 0 opening root of share */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) 		req->NameLength = cpu_to_le16(uni_path_len - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) 		copy_size = uni_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) 		if (copy_size % 8 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) 			copy_size = roundup(copy_size, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) 		copy_path = kzalloc(copy_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) 		if (!copy_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) 		memcpy((char *)copy_path, (const char *)path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) 		       uni_path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) 		uni_path_len = copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) 		path = copy_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) 	iov[1].iov_len = uni_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) 	iov[1].iov_base = path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) 	if ((!server->oplocks) || (tcon->no_lease))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) 		*oplock = SMB2_OPLOCK_LEVEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) 	if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) 	    *oplock == SMB2_OPLOCK_LEVEL_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) 		req->RequestedOplockLevel = *oplock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) 	else if (!(server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) 		  (oparms->create_options & CREATE_NOT_FILE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) 		req->RequestedOplockLevel = *oplock; /* no srv lease support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) 		rc = add_lease_context(server, iov, &n_iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) 				       oparms->fid->lease_key, oplock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) 	if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) 		/* need to set Next field of lease context if we request it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) 		if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) 			struct create_context *ccontext =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) 			    (struct create_context *)iov[n_iov-1].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) 			ccontext->Next =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) 				cpu_to_le32(server->vals->create_lease_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) 		rc = add_durable_context(iov, &n_iov, oparms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) 					tcon->use_persistent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) 	if (tcon->posix_extensions) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) 		if (n_iov > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) 			struct create_context *ccontext =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) 			    (struct create_context *)iov[n_iov-1].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) 			ccontext->Next =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) 				cpu_to_le32(iov[n_iov-1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) 		rc = add_posix_context(iov, &n_iov, oparms->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) 	if (tcon->snapshot_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) 		cifs_dbg(FYI, "adding snapshot context\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) 		if (n_iov > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) 			struct create_context *ccontext =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) 			    (struct create_context *)iov[n_iov-1].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) 			ccontext->Next =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) 				cpu_to_le32(iov[n_iov-1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) 		rc = add_twarp_context(iov, &n_iov, tcon->snapshot_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) 	if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) 		bool set_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) 		bool set_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) 		if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) 		    (oparms->mode != ACL_NO_MODE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) 			set_mode = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) 			set_mode = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) 			oparms->mode = ACL_NO_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) 		if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) 			set_owner = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) 			set_owner = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) 		if (set_owner | set_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) 			if (n_iov > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) 				struct create_context *ccontext =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) 				    (struct create_context *)iov[n_iov-1].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) 				ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) 			cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) 			rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) 			if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) 				return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) 	if (n_iov > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) 		struct create_context *ccontext =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) 			(struct create_context *)iov[n_iov-1].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) 		ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) 	add_query_id_context(iov, &n_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) 	rqst->rq_nvec = n_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) /* rq_iov[0] is the request and is released by cifs_small_buf_release().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814)  * All other vectors are freed by kfree().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) SMB2_open_free(struct smb_rqst *rqst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) 	if (rqst && rqst->rq_iov) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) 		cifs_small_buf_release(rqst->rq_iov[0].iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) 		for (i = 1; i < rqst->rq_nvec; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) 			if (rqst->rq_iov[i].iov_base != smb2_padding)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) 				kfree(rqst->rq_iov[i].iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) 	  __u8 *oplock, struct smb2_file_all_info *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) 	  struct create_posix_rsp *posix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) 	  struct kvec *err_iov, int *buftype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) 	struct smb2_create_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) 	struct cifs_tcon *tcon = oparms->tcon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) 	struct kvec iov[SMB2_CREATE_IOV_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) 	struct kvec rsp_iov = {NULL, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) 	int resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) 	cifs_dbg(FYI, "create/open\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) 	if (!ses || !server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) 	memset(&iov, 0, sizeof(iov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) 	rqst.rq_nvec = SMB2_CREATE_IOV_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) 	rc = SMB2_open_init(tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) 			    &rqst, oplock, oparms, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) 		goto creat_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) 	trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) 		oparms->create_options, oparms->desired_access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) 			    &rqst, &resp_buftype, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) 			    &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) 	rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) 		cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) 		if (err_iov && rsp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) 			*err_iov = rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) 			*buftype = resp_buftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) 			resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) 			rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) 		trace_smb3_open_err(xid, tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) 				    oparms->create_options, oparms->desired_access, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) 		if (rc == -EREMCHG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) 			pr_warn_once("server share %s deleted\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) 				     tcon->treeName);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) 			tcon->need_reconnect = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) 		goto creat_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) 		trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) 				     ses->Suid, oparms->create_options,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) 				     oparms->desired_access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) 	atomic_inc(&tcon->num_remote_opens);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) 	oparms->fid->persistent_fid = rsp->PersistentFileId;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) 	oparms->fid->volatile_fid = rsp->VolatileFileId;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) 	oparms->fid->access = oparms->desired_access;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) #ifdef CONFIG_CIFS_DEBUG2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) 	oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) #endif /* CIFS_DEBUG2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) 	if (buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) 		memcpy(buf, &rsp->CreationTime, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) 		buf->AllocationSize = rsp->AllocationSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) 		buf->EndOfFile = rsp->EndofFile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) 		buf->Attributes = rsp->FileAttributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) 		buf->NumberOfLinks = cpu_to_le32(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) 		buf->DeletePending = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) 	smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) 			    oparms->fid->lease_key, oplock, buf, posix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) creat_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) 	SMB2_open_free(&rqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) 		struct smb_rqst *rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) 		u64 persistent_fid, u64 volatile_fid, u32 opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) 		bool is_fsctl, char *in_data, u32 indatalen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) 		__u32 max_response_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) 	struct smb2_ioctl_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) 	struct kvec *iov = rqst->rq_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) 	char *in_data_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) 	rc = smb2_ioctl_req_init(opcode, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) 	if (indatalen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) 		 * indatalen is usually small at a couple of bytes max, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) 		 * just allocate through generic pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) 		in_data_buf = kmemdup(in_data, indatalen, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) 		if (!in_data_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) 			cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) 	req->CtlCode = cpu_to_le32(opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) 	req->PersistentFileId = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) 	 * If no input data, the size of ioctl struct in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) 	 * protocol spec still includes a 1 byte data buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) 	 * but if input data passed to ioctl, we do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) 	 * want to double count this, so we do not send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) 	 * the dummy one byte of data in iovec[0] if sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) 	 * input data (in iovec[1]).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) 	if (indatalen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) 		req->InputCount = cpu_to_le32(indatalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) 		/* do not set InputOffset if no input data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) 		req->InputOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) 		       cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) 		rqst->rq_nvec = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) 		iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) 		iov[1].iov_base = in_data_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) 		iov[1].iov_len = indatalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) 		rqst->rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) 		iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) 	req->OutputOffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) 	req->OutputCount = 0; /* MBZ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) 	 * In most cases max_response_size is set to 16K (CIFSMaxBufSize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) 	 * We Could increase default MaxOutputResponse, but that could require
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) 	 * more credits. Windows typically sets this smaller, but for some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) 	 * ioctls it may be useful to allow server to send more. No point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) 	 * limiting what the server can send as long as fits in one credit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) 	 * We can not handle more than CIFS_MAX_BUF_SIZE yet but may want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) 	 * to increase this limit up in the future.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) 	 * Note that for snapshot queries that servers like Azure expect that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) 	 * the first query be minimal size (and just used to get the number/size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) 	 * of previous versions) so response size must be specified as EXACTLY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) 	 * sizeof(struct snapshot_array) which is 16 when rounded up to multiple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) 	 * of eight bytes.  Currently that is the only case where we set max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) 	 * response size smaller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) 	req->MaxOutputResponse = cpu_to_le32(max_response_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) 	req->sync_hdr.CreditCharge =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) 		cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) 					 SMB2_MAX_BUFFER_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) 	if (is_fsctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) 		req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) 		req->Flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) 	/* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) 	if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) 		req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) SMB2_ioctl_free(struct smb_rqst *rqst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) 	if (rqst && rqst->rq_iov) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) 		cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) 		for (i = 1; i < rqst->rq_nvec; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) 			if (rqst->rq_iov[i].iov_base != smb2_padding)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) 				kfree(rqst->rq_iov[i].iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023)  *	SMB2 IOCTL is used for both IOCTLs and FSCTLs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) 	   u64 volatile_fid, u32 opcode, bool is_fsctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) 	   char *in_data, u32 indatalen, u32 max_out_data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) 	   char **out_data, u32 *plen /* returned data len */)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) 	struct smb2_ioctl_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) 	struct cifs_ses *ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) 	struct TCP_Server_Info *server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) 	struct kvec iov[SMB2_IOCTL_IOV_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) 	struct kvec rsp_iov = {NULL, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) 	int resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) 	cifs_dbg(FYI, "SMB2 IOCTL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) 	if (out_data != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) 		*out_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) 	/* zero out returned data len, in case of error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) 	if (plen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) 		*plen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) 	if (!tcon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) 	ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) 	if (!ses)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) 	server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) 	if (!server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) 	memset(&iov, 0, sizeof(iov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) 	rqst.rq_nvec = SMB2_IOCTL_IOV_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) 	rc = SMB2_ioctl_init(tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) 			     &rqst, persistent_fid, volatile_fid, opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) 			     is_fsctl, in_data, indatalen, max_out_data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) 		goto ioctl_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) 			    &rqst, &resp_buftype, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) 			    &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) 	rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) 	if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) 		trace_smb3_fsctl_err(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) 				ses->Suid, 0, opcode, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) 	if ((rc != 0) && (rc != -EINVAL) && (rc != -E2BIG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) 		cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) 		goto ioctl_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) 	} else if (rc == -EINVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) 		if ((opcode != FSCTL_SRV_COPYCHUNK_WRITE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) 		    (opcode != FSCTL_SRV_COPYCHUNK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) 			cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) 			goto ioctl_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) 	} else if (rc == -E2BIG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) 		if (opcode != FSCTL_QUERY_ALLOCATED_RANGES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) 			cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) 			goto ioctl_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) 	/* check if caller wants to look at return data or just return rc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) 	if ((plen == NULL) || (out_data == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) 		goto ioctl_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) 	*plen = le32_to_cpu(rsp->OutputCount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) 	/* We check for obvious errors in the output buffer length and offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) 	if (*plen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) 		goto ioctl_exit; /* server returned no data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) 	else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) 		cifs_tcon_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) 		*plen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) 		goto ioctl_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) 	if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) 		cifs_tcon_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) 			le32_to_cpu(rsp->OutputOffset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) 		*plen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) 		goto ioctl_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) 	*out_data = kmemdup((char *)rsp + le32_to_cpu(rsp->OutputOffset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) 			    *plen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) 	if (*out_data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) 		rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) 		goto ioctl_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) ioctl_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) 	SMB2_ioctl_free(&rqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138)  *   Individual callers to ioctl worker function follow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) 		     u64 persistent_fid, u64 volatile_fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) 	struct  compress_ioctl fsctl_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) 	char *ret_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) 	fsctl_input.CompressionState =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) 			cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) 	rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) 			FSCTL_SET_COMPRESSION, true /* is_fsctl */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) 			(char *)&fsctl_input /* data input */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) 			2 /* in data len */, CIFSMaxBufSize /* max out data */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) 			&ret_data /* out data */, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) 	cifs_dbg(FYI, "set compression rc %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) SMB2_close_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) 		struct smb_rqst *rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) 		u64 persistent_fid, u64 volatile_fid, bool query_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) 	struct smb2_close_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) 	struct kvec *iov = rqst->rq_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) 	rc = smb2_plain_req_init(SMB2_CLOSE, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) 	req->PersistentFileId = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) 	if (query_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) 		req->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) 		req->Flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) SMB2_close_free(struct smb_rqst *rqst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) 	if (rqst && rqst->rq_iov)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) 		cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) 	     u64 persistent_fid, u64 volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) 	     struct smb2_file_network_open_info *pbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) 	struct smb2_close_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) 	int resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) 	bool query_attrs = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) 	cifs_dbg(FYI, "Close\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) 	if (!ses || !server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) 	memset(&iov, 0, sizeof(iov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) 	/* check if need to ask server to return timestamps in close response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) 	if (pbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) 		query_attrs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) 	trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) 	rc = SMB2_close_init(tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) 			     &rqst, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) 			     query_attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) 		goto close_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) 	rsp = (struct smb2_close_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) 		cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) 		trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) 				     rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) 		goto close_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) 		trace_smb3_close_done(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) 				      ses->Suid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) 		 * Note that have to subtract 4 since struct network_open_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) 		 * has a final 4 byte pad that close response does not have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) 		if (pbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) 			memcpy(pbuf, (char *)&rsp->CreationTime, sizeof(*pbuf) - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) 	atomic_dec(&tcon->num_remote_opens);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) close_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) 	SMB2_close_free(&rqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) 	/* retry close in a worker thread if this one is interrupted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) 	if (is_interrupt_error(rc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) 		int tmp_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) 		tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) 						     volatile_fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) 		if (tmp_rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) 			cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) 				 persistent_fid, tmp_rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) 		u64 persistent_fid, u64 volatile_fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) 	return __SMB2_close(xid, tcon, persistent_fid, volatile_fid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) 		  struct kvec *iov, unsigned int min_buf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) 	unsigned int smb_len = iov->iov_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) 	char *end_of_smb = smb_len + (char *)iov->iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) 	char *begin_of_buf = offset + (char *)iov->iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) 	char *end_of_buf = begin_of_buf + buffer_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) 	if (buffer_length < min_buf_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) 		cifs_dbg(VFS, "buffer length %d smaller than minimum size %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) 			 buffer_length, min_buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) 	/* check if beyond RFC1001 maximum length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) 	if ((smb_len > 0x7FFFFF) || (buffer_length > 0x7FFFFF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) 		cifs_dbg(VFS, "buffer length %d or smb length %d too large\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) 			 buffer_length, smb_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) 	if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) 		cifs_dbg(VFS, "Invalid server response, bad offset to data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314)  * If SMB buffer fields are valid, copy into temporary buffer to hold result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315)  * Caller must free buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) smb2_validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) 			   struct kvec *iov, unsigned int minbufsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) 			   char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) 	char *begin_of_buf = offset + (char *)iov->iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) 	if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) 	rc = smb2_validate_iov(offset, buffer_length, iov, minbufsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) 	memcpy(data, begin_of_buf, buffer_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) 		     struct smb_rqst *rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) 		     u64 persistent_fid, u64 volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) 		     u8 info_class, u8 info_type, u32 additional_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) 		     size_t output_len, size_t input_len, void *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) 	struct smb2_query_info_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) 	struct kvec *iov = rqst->rq_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) 	rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) 	req->InfoType = info_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) 	req->FileInfoClass = info_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) 	req->PersistentFileId = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) 	req->AdditionalInformation = cpu_to_le32(additional_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) 	req->OutputBufferLength = cpu_to_le32(output_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) 	if (input_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) 		req->InputBufferLength = cpu_to_le32(input_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) 		/* total_len for smb query request never close to le16 max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) 		req->InputBufferOffset = cpu_to_le16(total_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) 		memcpy(req->Buffer, input, input_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) 	/* 1 for Buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) 	iov[0].iov_len = total_len - 1 + input_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) SMB2_query_info_free(struct smb_rqst *rqst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) 	if (rqst && rqst->rq_iov)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) 		cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) query_info(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) 	   u64 persistent_fid, u64 volatile_fid, u8 info_class, u8 info_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) 	   u32 additional_info, size_t output_len, size_t min_len, void **data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) 		u32 *dlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) 	struct smb2_query_info_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) 	int resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) 	struct TCP_Server_Info *server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) 	bool allocated = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) 	cifs_dbg(FYI, "Query Info\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) 	if (!ses)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) 	server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) 	if (!server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) 	memset(&iov, 0, sizeof(iov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) 	rc = SMB2_query_info_init(tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) 				  &rqst, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) 				  info_class, info_type, additional_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) 				  output_len, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) 		goto qinf_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) 	trace_smb3_query_info_enter(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) 				    ses->Suid, info_class, (__u32)info_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) 	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) 		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) 		trace_smb3_query_info_err(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) 				ses->Suid, info_class, (__u32)info_type, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) 		goto qinf_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) 	trace_smb3_query_info_done(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) 				ses->Suid, info_class, (__u32)info_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) 	if (dlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) 		*dlen = le32_to_cpu(rsp->OutputBufferLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) 		if (!*data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) 			*data = kmalloc(*dlen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) 			if (!*data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) 				cifs_tcon_dbg(VFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) 					"Error %d allocating memory for acl\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) 					rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) 				*dlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) 				rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) 				goto qinf_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) 			allocated = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) 	rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) 					le32_to_cpu(rsp->OutputBufferLength),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) 					&rsp_iov, min_len, *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) 	if (rc && allocated) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) 		kfree(*data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) 		*data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) 		*dlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) qinf_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) 	SMB2_query_info_free(&rqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) 	u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) 	return query_info(xid, tcon, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) 			  FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) 			  sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) 			  sizeof(struct smb2_file_all_info), (void **)&data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) 			  NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) 		u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) 	size_t output_len = sizeof(struct smb311_posix_qinfo *) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) 			(sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) 	*plen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) 	return query_info(xid, tcon, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) 			  SMB_FIND_FILE_POSIX_INFO, SMB2_O_INFO_FILE, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) 			  output_len, sizeof(struct smb311_posix_qinfo), (void **)&data, plen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) 		u64 persistent_fid, u64 volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) 		void **data, u32 *plen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) 	__u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) 	*plen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) 	return query_info(xid, tcon, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) 			  0, SMB2_O_INFO_SECURITY, additional_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) 			  SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) 		 u64 persistent_fid, u64 volatile_fid, __le64 *uniqueid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) 	return query_info(xid, tcon, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) 			  FILE_INTERNAL_INFORMATION, SMB2_O_INFO_FILE, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) 			  sizeof(struct smb2_file_internal_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) 			  sizeof(struct smb2_file_internal_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) 			  (void **)&uniqueid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517)  * CHANGE_NOTIFY Request is sent to get notifications on changes to a directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518)  * See MS-SMB2 2.2.35 and 2.2.36
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) 		 struct cifs_tcon *tcon, struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) 		 u64 persistent_fid, u64 volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) 		 u32 completion_filter, bool watch_tree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) 	struct smb2_change_notify_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) 	struct kvec *iov = rqst->rq_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) 	rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) 	req->PersistentFileId = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) 	/* See note 354 of MS-SMB2, 64K max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) 	req->OutputBufferLength =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) 		cpu_to_le32(SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) 	req->CompletionFilter = cpu_to_le32(completion_filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) 	if (watch_tree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) 		req->Flags = cpu_to_le16(SMB2_WATCH_TREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) 		req->Flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) 		u64 persistent_fid, u64 volatile_fid, bool watch_tree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) 		u32 completion_filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) 	struct kvec rsp_iov = {NULL, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) 	int resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) 	cifs_dbg(FYI, "change notify\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) 	if (!ses || !server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) 	memset(&iov, 0, sizeof(iov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) 	rc = SMB2_notify_init(xid, &rqst, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) 			      persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) 			      completion_filter, watch_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) 		goto cnotify_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) 	trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) 				(u8)watch_tree, completion_filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) 		cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) 		trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) 				(u8)watch_tree, completion_filter, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) 		trace_smb3_notify_done(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) 				ses->Suid, (u8)watch_tree, completion_filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599)  cnotify_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) 	if (rqst.rq_iov)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) 		cifs_small_buf_release(rqst.rq_iov[0].iov_base); /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) 	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609)  * This is a no-op for now. We're not really interested in the reply, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610)  * rather in the fact that the server sent one and that server->lstrp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611)  * gets updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613)  * FIXME: maybe we should consider checking that the reply matches request?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) smb2_echo_callback(struct mid_q_entry *mid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) 	struct TCP_Server_Info *server = mid->callback_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) 	struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) 	struct cifs_credits credits = { .value = 0, .instance = 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) 	if (mid->mid_state == MID_RESPONSE_RECEIVED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) 	    || mid->mid_state == MID_RESPONSE_MALFORMED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) 		credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) 		credits.instance = server->reconnect_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) 	DeleteMidQEntry(mid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) 	add_credits(server, &credits, CIFS_ECHO_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) void smb2_reconnect_server(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) 	struct TCP_Server_Info *server = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) 					struct TCP_Server_Info, reconnect.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) 	struct cifs_ses *ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) 	struct cifs_tcon *tcon, *tcon2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) 	struct list_head tmp_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) 	int tcon_exist = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) 	int resched = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) 	/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) 	mutex_lock(&server->reconnect_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) 	INIT_LIST_HEAD(&tmp_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) 	cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) 	spin_lock(&cifs_tcp_ses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) 	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) 		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) 			if (tcon->need_reconnect || tcon->need_reopen_files) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) 				tcon->tc_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) 				list_add_tail(&tcon->rlist, &tmp_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) 				tcon_exist = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) 		 * IPC has the same lifetime as its session and uses its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) 		 * refcount.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) 		if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) 			list_add_tail(&ses->tcon_ipc->rlist, &tmp_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) 			tcon_exist = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) 			ses->ses_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) 	 * Get the reference to server struct to be sure that the last call of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) 	 * cifs_put_tcon() in the loop below won't release the server pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) 	if (tcon_exist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) 		server->srv_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) 	spin_unlock(&cifs_tcp_ses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) 	list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) 		rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) 		if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) 			cifs_reopen_persistent_handles(tcon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) 			resched = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) 		list_del_init(&tcon->rlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) 		if (tcon->ipc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) 			cifs_put_smb_ses(tcon->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) 			cifs_put_tcon(tcon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) 	cifs_dbg(FYI, "Reconnecting tcons finished\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) 	if (resched)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) 		queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) 	mutex_unlock(&server->reconnect_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) 	/* now we can safely release srv struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) 	if (tcon_exist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) 		cifs_put_tcp_session(server, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) SMB2_echo(struct TCP_Server_Info *server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) 	struct smb2_echo_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) 	struct smb_rqst rqst = { .rq_iov = iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) 				 .rq_nvec = 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) 	cifs_dbg(FYI, "In echo request\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) 	if (server->tcpStatus == CifsNeedNegotiate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) 		/* No need to send echo on newly established connections */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) 		mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) 	rc = smb2_plain_req_init(SMB2_ECHO, NULL, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) 				 (void **)&req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) 	req->sync_hdr.CreditRequest = cpu_to_le16(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) 	rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) 			     server, CIFS_ECHO_OP, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) 		cifs_dbg(FYI, "Echo request failed: %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) SMB2_flush_free(struct smb_rqst *rqst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) 	if (rqst && rqst->rq_iov)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) 		cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) 		struct cifs_tcon *tcon, struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) 		u64 persistent_fid, u64 volatile_fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) 	struct smb2_flush_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) 	struct kvec *iov = rqst->rq_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) 	rc = smb2_plain_req_init(SMB2_FLUSH, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) 	req->PersistentFileId = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) 	   u64 volatile_fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) 	struct kvec rsp_iov = {NULL, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) 	int resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) 	cifs_dbg(FYI, "flush\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) 	if (!ses || !(ses->server))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) 	memset(&iov, 0, sizeof(iov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) 	rc = SMB2_flush_init(xid, &rqst, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) 			     persistent_fid, volatile_fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) 		goto flush_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) 	trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) 		cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) 		trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) 				     rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) 		trace_smb3_flush_done(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) 				      ses->Suid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811)  flush_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) 	SMB2_flush_free(&rqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) 	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818)  * To form a chain of read requests, any read requests after the first should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819)  * have the end_of_chain boolean set to true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) smb2_new_read_req(void **buf, unsigned int *total_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) 	struct cifs_io_parms *io_parms, struct cifs_readdata *rdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) 	unsigned int remaining_bytes, int request_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) 	int rc = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) 	struct smb2_read_plain_req *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) 	struct smb2_sync_hdr *shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) 	struct TCP_Server_Info *server = io_parms->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) 	rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) 				 (void **) &req, total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) 	if (server == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) 		return -ECONNABORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) 	shdr = &req->sync_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) 	shdr->ProcessId = cpu_to_le32(io_parms->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) 	req->PersistentFileId = io_parms->persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) 	req->VolatileFileId = io_parms->volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) 	req->ReadChannelInfoOffset = 0; /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) 	req->ReadChannelInfoLength = 0; /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) 	req->Channel = 0; /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) 	req->MinimumCount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) 	req->Length = cpu_to_le32(io_parms->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) 	req->Offset = cpu_to_le64(io_parms->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) 	trace_smb3_read_enter(0 /* xid */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) 			io_parms->persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) 			io_parms->tcon->tid, io_parms->tcon->ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) 			io_parms->offset, io_parms->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) #ifdef CONFIG_CIFS_SMB_DIRECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) 	 * If we want to do a RDMA write, fill in and append
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) 	 * smbd_buffer_descriptor_v1 to the end of read request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) 	if (server->rdma && rdata && !server->sign &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) 		rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) 		struct smbd_buffer_descriptor_v1 *v1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) 		bool need_invalidate = server->dialect == SMB30_PROT_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) 		rdata->mr = smbd_register_mr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) 				server->smbd_conn, rdata->pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) 				rdata->nr_pages, rdata->page_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) 				rdata->tailsz, true, need_invalidate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) 		if (!rdata->mr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) 			return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) 		req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) 		if (need_invalidate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) 			req->Channel = SMB2_CHANNEL_RDMA_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) 		req->ReadChannelInfoOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) 			cpu_to_le16(offsetof(struct smb2_read_plain_req, Buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) 		req->ReadChannelInfoLength =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) 			cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) 		v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) 		v1->offset = cpu_to_le64(rdata->mr->mr->iova);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) 		v1->token = cpu_to_le32(rdata->mr->mr->rkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) 		v1->length = cpu_to_le32(rdata->mr->mr->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) 		*total_len += sizeof(*v1) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) 	if (request_type & CHAINED_REQUEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) 		if (!(request_type & END_OF_CHAIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) 			/* next 8-byte aligned request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) 			*total_len = DIV_ROUND_UP(*total_len, 8) * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) 			shdr->NextCommand = cpu_to_le32(*total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) 		} else /* END_OF_CHAIN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) 			shdr->NextCommand = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) 		if (request_type & RELATED_REQUEST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) 			shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) 			 * Related requests use info from previous read request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) 			 * in chain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) 			shdr->SessionId = 0xFFFFFFFFFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) 			shdr->TreeId = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) 			req->PersistentFileId = 0xFFFFFFFFFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) 			req->VolatileFileId = 0xFFFFFFFFFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) 	if (remaining_bytes > io_parms->length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) 		req->RemainingBytes = cpu_to_le32(remaining_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) 		req->RemainingBytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) 	*buf = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) smb2_readv_callback(struct mid_q_entry *mid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) 	struct cifs_readdata *rdata = mid->callback_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) 	struct TCP_Server_Info *server = rdata->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) 	struct smb2_sync_hdr *shdr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) 				(struct smb2_sync_hdr *)rdata->iov[0].iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) 	struct cifs_credits credits = { .value = 0, .instance = 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) 	struct smb_rqst rqst = { .rq_iov = &rdata->iov[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) 				 .rq_nvec = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) 				 .rq_pages = rdata->pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) 				 .rq_offset = rdata->page_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) 				 .rq_npages = rdata->nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) 				 .rq_pagesz = rdata->pagesz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) 				 .rq_tailsz = rdata->tailsz };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) 	WARN_ONCE(rdata->server != mid->server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) 		  "rdata server %p != mid server %p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) 		  rdata->server, mid->server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) 	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) 		 __func__, mid->mid, mid->mid_state, rdata->result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) 		 rdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) 	switch (mid->mid_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) 	case MID_RESPONSE_RECEIVED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) 		credits.value = le16_to_cpu(shdr->CreditRequest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) 		credits.instance = server->reconnect_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) 		/* result already set, check signature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) 		if (server->sign && !mid->decrypted) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) 			int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) 			rc = smb2_verify_signature(&rqst, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) 			if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) 				cifs_tcon_dbg(VFS, "SMB signature verification returned error = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) 					 rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) 		/* FIXME: should this be counted toward the initiating task? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) 		task_io_account_read(rdata->got_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) 		cifs_stats_bytes_read(tcon, rdata->got_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) 	case MID_REQUEST_SUBMITTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) 	case MID_RETRY_NEEDED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) 		rdata->result = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) 		if (server->sign && rdata->got_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) 			/* reset bytes number since we can not check a sign */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) 			rdata->got_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) 		/* FIXME: should this be counted toward the initiating task? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) 		task_io_account_read(rdata->got_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) 		cifs_stats_bytes_read(tcon, rdata->got_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) 	case MID_RESPONSE_MALFORMED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) 		credits.value = le16_to_cpu(shdr->CreditRequest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) 		credits.instance = server->reconnect_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) 		rdata->result = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) #ifdef CONFIG_CIFS_SMB_DIRECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) 	 * If this rdata has a memmory registered, the MR can be freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) 	 * MR needs to be freed as soon as I/O finishes to prevent deadlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) 	 * because they have limited number and are used for future I/Os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) 	if (rdata->mr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) 		smbd_deregister_mr(rdata->mr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) 		rdata->mr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) 	if (rdata->result && rdata->result != -ENODATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) 		cifs_stats_fail_inc(tcon, SMB2_READ_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) 		trace_smb3_read_err(0 /* xid */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) 				    rdata->cfile->fid.persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) 				    tcon->tid, tcon->ses->Suid, rdata->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) 				    rdata->bytes, rdata->result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) 		trace_smb3_read_done(0 /* xid */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) 				     rdata->cfile->fid.persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) 				     tcon->tid, tcon->ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) 				     rdata->offset, rdata->got_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) 	queue_work(cifsiod_wq, &rdata->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) 	DeleteMidQEntry(mid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) 	add_credits(server, &credits, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) /* smb2_async_readv - send an async read, and set up mid to handle result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) smb2_async_readv(struct cifs_readdata *rdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) 	int rc, flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) 	char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) 	struct smb2_sync_hdr *shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) 	struct cifs_io_parms io_parms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) 	struct smb_rqst rqst = { .rq_iov = rdata->iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) 				 .rq_nvec = 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) 	struct TCP_Server_Info *server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) 	cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) 		 __func__, rdata->offset, rdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) 	if (!rdata->server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) 		rdata->server = cifs_pick_channel(tcon->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) 	io_parms.tcon = tlink_tcon(rdata->cfile->tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) 	io_parms.server = server = rdata->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) 	io_parms.offset = rdata->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) 	io_parms.length = rdata->bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) 	io_parms.persistent_fid = rdata->cfile->fid.persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) 	io_parms.volatile_fid = rdata->cfile->fid.volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) 	io_parms.pid = rdata->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) 	rc = smb2_new_read_req(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) 		(void **) &buf, &total_len, &io_parms, rdata, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) 	if (smb3_encryption_required(io_parms.tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) 	rdata->iov[0].iov_base = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) 	rdata->iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) 	shdr = (struct smb2_sync_hdr *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) 	if (rdata->credits.value > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) 		shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) 						SMB2_MAX_BUFFER_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) 		shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) 		rc = adjust_credits(server, &rdata->credits, rdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) 			goto async_readv_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) 		flags |= CIFS_HAS_CREDITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) 	kref_get(&rdata->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) 	rc = cifs_call_async(server, &rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) 			     cifs_readv_receive, smb2_readv_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) 			     smb3_handle_read_data, rdata, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) 			     &rdata->credits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) 		kref_put(&rdata->refcount, cifs_readdata_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) 		cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) 		trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) 				    io_parms.tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) 				    io_parms.tcon->ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) 				    io_parms.offset, io_parms.length, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) async_readv_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) 	cifs_small_buf_release(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077) 	  unsigned int *nbytes, char **buf, int *buf_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) 	int resp_buftype, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) 	struct smb2_read_plain_req *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) 	struct smb2_read_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) 	int flags = CIFS_LOG_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) 	struct cifs_ses *ses = io_parms->tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) 	if (!io_parms->server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) 		io_parms->server = cifs_pick_channel(io_parms->tcon->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) 	*nbytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) 	rc = smb2_new_read_req((void **)&req, &total_len, io_parms, NULL, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) 	if (smb3_encryption_required(io_parms->tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) 	rc = cifs_send_recv(xid, ses, io_parms->server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) 	rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) 		if (rc != -ENODATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) 			cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) 			cifs_dbg(VFS, "Send error in read = %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) 			trace_smb3_read_err(xid, req->PersistentFileId,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) 					    io_parms->tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) 					    io_parms->offset, io_parms->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) 					    rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) 			trace_smb3_read_done(xid, req->PersistentFileId,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) 				    io_parms->tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) 				    io_parms->offset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) 		free_rsp_buf(resp_buftype, rsp_iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) 		cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) 		return rc == -ENODATA ? 0 : rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) 		trace_smb3_read_done(xid, req->PersistentFileId,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) 				    io_parms->tcon->tid, ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) 				    io_parms->offset, io_parms->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) 	*nbytes = le32_to_cpu(rsp->DataLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) 	if ((*nbytes > CIFS_MAX_MSGSIZE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) 	    (*nbytes > io_parms->length)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) 		cifs_dbg(FYI, "bad length %d for count %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) 			 *nbytes, io_parms->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) 		*nbytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) 	if (*buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) 		memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) 		free_rsp_buf(resp_buftype, rsp_iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) 	} else if (resp_buftype != CIFS_NO_BUFFER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) 		*buf = rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) 		if (resp_buftype == CIFS_SMALL_BUFFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) 			*buf_type = CIFS_SMALL_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149) 		else if (resp_buftype == CIFS_LARGE_BUFFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) 			*buf_type = CIFS_LARGE_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156)  * Check the mid_state and signature on received buffer (if any), and queue the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157)  * workqueue completion task.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) smb2_writev_callback(struct mid_q_entry *mid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) 	struct cifs_writedata *wdata = mid->callback_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) 	struct TCP_Server_Info *server = wdata->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) 	unsigned int written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) 	struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) 	struct cifs_credits credits = { .value = 0, .instance = 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) 	WARN_ONCE(wdata->server != mid->server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) 		  "wdata server %p != mid server %p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) 		  wdata->server, mid->server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) 	switch (mid->mid_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) 	case MID_RESPONSE_RECEIVED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) 		credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) 		credits.instance = server->reconnect_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) 		wdata->result = smb2_check_receive(mid, server, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) 		if (wdata->result != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) 		written = le32_to_cpu(rsp->DataLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) 		 * Mask off high 16 bits when bytes written as returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) 		 * by the server is greater than bytes requested by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) 		 * client. OS/2 servers are known to set incorrect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) 		 * CountHigh values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) 		if (written > wdata->bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) 			written &= 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) 		if (written < wdata->bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) 			wdata->result = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) 			wdata->bytes = written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196) 	case MID_REQUEST_SUBMITTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) 	case MID_RETRY_NEEDED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) 		wdata->result = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) 	case MID_RESPONSE_MALFORMED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) 		credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) 		credits.instance = server->reconnect_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) 		wdata->result = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) #ifdef CONFIG_CIFS_SMB_DIRECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) 	 * If this wdata has a memory registered, the MR can be freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) 	 * The number of MRs available is limited, it's important to recover
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) 	 * used MR as soon as I/O is finished. Hold MR longer in the later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) 	 * I/O process can possibly result in I/O deadlock due to lack of MR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) 	 * to send request on I/O retry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) 	if (wdata->mr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) 		smbd_deregister_mr(wdata->mr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) 		wdata->mr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) 	if (wdata->result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) 		cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) 		trace_smb3_write_err(0 /* no xid */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) 				     wdata->cfile->fid.persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) 				     tcon->tid, tcon->ses->Suid, wdata->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) 				     wdata->bytes, wdata->result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) 		if (wdata->result == -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228) 			pr_warn_once("Out of space writing to %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) 				     tcon->treeName);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) 		trace_smb3_write_done(0 /* no xid */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232) 				      wdata->cfile->fid.persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) 				      tcon->tid, tcon->ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) 				      wdata->offset, wdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236) 	queue_work(cifsiod_wq, &wdata->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) 	DeleteMidQEntry(mid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) 	add_credits(server, &credits, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) /* smb2_async_writev - send an async write, and set up mid to handle result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) smb2_async_writev(struct cifs_writedata *wdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) 		  void (*release)(struct kref *kref))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) 	int rc = -EACCES, flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) 	struct smb2_write_req *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) 	struct smb2_sync_hdr *shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) 	struct TCP_Server_Info *server = wdata->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) 	struct smb_rqst rqst = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) 	if (!wdata->server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) 		server = wdata->server = cifs_pick_channel(tcon->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) 	rc = smb2_plain_req_init(SMB2_WRITE, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266) 	shdr = (struct smb2_sync_hdr *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) 	shdr->ProcessId = cpu_to_le32(wdata->cfile->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) 	req->PersistentFileId = wdata->cfile->fid.persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270) 	req->VolatileFileId = wdata->cfile->fid.volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) 	req->WriteChannelInfoOffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) 	req->WriteChannelInfoLength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) 	req->Channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) 	req->Offset = cpu_to_le64(wdata->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) 	req->DataOffset = cpu_to_le16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) 				offsetof(struct smb2_write_req, Buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) 	req->RemainingBytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) 	trace_smb3_write_enter(0 /* xid */, wdata->cfile->fid.persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) 		tcon->tid, tcon->ses->Suid, wdata->offset, wdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) #ifdef CONFIG_CIFS_SMB_DIRECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) 	 * If we want to do a server RDMA read, fill in and append
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) 	 * smbd_buffer_descriptor_v1 to the end of write request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) 	if (server->rdma && !server->sign && wdata->bytes >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) 		server->smbd_conn->rdma_readwrite_threshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) 		struct smbd_buffer_descriptor_v1 *v1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) 		bool need_invalidate = server->dialect == SMB30_PROT_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292) 		wdata->mr = smbd_register_mr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) 				server->smbd_conn, wdata->pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) 				wdata->nr_pages, wdata->page_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) 				wdata->tailsz, false, need_invalidate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) 		if (!wdata->mr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) 			rc = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) 			goto async_writev_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) 		req->Length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) 		req->DataOffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) 		if (wdata->nr_pages > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) 			req->RemainingBytes =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304) 				cpu_to_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305) 					(wdata->nr_pages - 1) * wdata->pagesz -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) 					wdata->page_offset + wdata->tailsz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) 				);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) 			req->RemainingBytes = cpu_to_le32(wdata->tailsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) 		req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) 		if (need_invalidate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) 			req->Channel = SMB2_CHANNEL_RDMA_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) 		req->WriteChannelInfoOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) 			cpu_to_le16(offsetof(struct smb2_write_req, Buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315) 		req->WriteChannelInfoLength =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) 			cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317) 		v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) 		v1->offset = cpu_to_le64(wdata->mr->mr->iova);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319) 		v1->token = cpu_to_le32(wdata->mr->mr->rkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320) 		v1->length = cpu_to_le32(wdata->mr->mr->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323) 	iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) 	rqst.rq_pages = wdata->pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329) 	rqst.rq_offset = wdata->page_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330) 	rqst.rq_npages = wdata->nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331) 	rqst.rq_pagesz = wdata->pagesz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) 	rqst.rq_tailsz = wdata->tailsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333) #ifdef CONFIG_CIFS_SMB_DIRECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334) 	if (wdata->mr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335) 		iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) 		rqst.rq_npages = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339) 	cifs_dbg(FYI, "async write at %llu %u bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) 		 wdata->offset, wdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) #ifdef CONFIG_CIFS_SMB_DIRECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343) 	/* For RDMA read, I/O size is in RemainingBytes not in Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) 	if (!wdata->mr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345) 		req->Length = cpu_to_le32(wdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) 	req->Length = cpu_to_le32(wdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350) 	if (wdata->credits.value > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351) 		shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352) 						    SMB2_MAX_BUFFER_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353) 		shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) 		rc = adjust_credits(server, &wdata->credits, wdata->bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357) 			goto async_writev_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359) 		flags |= CIFS_HAS_CREDITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362) 	kref_get(&wdata->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363) 	rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364) 			     wdata, flags, &wdata->credits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367) 		trace_smb3_write_err(0 /* no xid */, req->PersistentFileId,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) 				     tcon->tid, tcon->ses->Suid, wdata->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369) 				     wdata->bytes, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370) 		kref_put(&wdata->refcount, release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371) 		cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374) async_writev_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380)  * SMB2_write function gets iov pointer to kvec array with n_vec as a length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381)  * The length field from io_parms must be at least 1 and indicates a number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382)  * elements with data to write that begins with position 1 in iov array. All
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383)  * data length is specified by count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387) 	   unsigned int *nbytes, struct kvec *iov, int n_vec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391) 	struct smb2_write_req *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392) 	struct smb2_write_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393) 	int resp_buftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) 	struct TCP_Server_Info *server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399) 	*nbytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401) 	if (n_vec < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404) 	if (!io_parms->server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405) 		io_parms->server = cifs_pick_channel(io_parms->tcon->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406) 	server = io_parms->server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407) 	if (server == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408) 		return -ECONNABORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410) 	rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415) 	if (smb3_encryption_required(io_parms->tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) 	req->sync_hdr.ProcessId = cpu_to_le32(io_parms->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) 	req->PersistentFileId = io_parms->persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) 	req->VolatileFileId = io_parms->volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422) 	req->WriteChannelInfoOffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423) 	req->WriteChannelInfoLength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) 	req->Channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425) 	req->Length = cpu_to_le32(io_parms->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426) 	req->Offset = cpu_to_le64(io_parms->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) 	req->DataOffset = cpu_to_le16(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428) 				offsetof(struct smb2_write_req, Buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429) 	req->RemainingBytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431) 	trace_smb3_write_enter(xid, io_parms->persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432) 		io_parms->tcon->tid, io_parms->tcon->ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433) 		io_parms->offset, io_parms->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) 	/* 1 for Buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437) 	iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) 	rqst.rq_nvec = n_vec + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443) 	rc = cifs_send_recv(xid, io_parms->tcon->ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444) 			    &rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445) 			    &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446) 	rsp = (struct smb2_write_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449) 		trace_smb3_write_err(xid, req->PersistentFileId,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450) 				     io_parms->tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451) 				     io_parms->tcon->ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452) 				     io_parms->offset, io_parms->length, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453) 		cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454) 		cifs_dbg(VFS, "Send error in write = %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456) 		*nbytes = le32_to_cpu(rsp->DataLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) 		trace_smb3_write_done(xid, req->PersistentFileId,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458) 				     io_parms->tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) 				     io_parms->tcon->ses->Suid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) 				     io_parms->offset, *nbytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468) int posix_info_sid_size(const void *beg, const void *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470) 	size_t subauth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471) 	int total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473) 	if (beg + 1 > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476) 	subauth = *(u8 *)(beg+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477) 	if (subauth < 1 || subauth > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480) 	total = 1 + 1 + 6 + 4*subauth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481) 	if (beg + total > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484) 	return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487) int posix_info_parse(const void *beg, const void *end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488) 		     struct smb2_posix_info_parsed *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491) 	int total_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492) 	int sid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) 	int name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494) 	const void *owner_sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495) 	const void *group_sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496) 	const void *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) 	/* if no end bound given, assume payload to be correct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499) 	if (!end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) 		const struct smb2_posix_info *p = beg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502) 		end = beg + le32_to_cpu(p->NextEntryOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503) 		/* last element will have a 0 offset, pick a sensible bound */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504) 		if (end == beg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505) 			end += 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508) 	/* check base buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) 	if (beg + sizeof(struct smb2_posix_info) > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511) 	total_len = sizeof(struct smb2_posix_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) 	/* check owner sid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514) 	owner_sid = beg + total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) 	sid_len = posix_info_sid_size(owner_sid, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) 	if (sid_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518) 	total_len += sid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520) 	/* check group sid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521) 	group_sid = beg + total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522) 	sid_len = posix_info_sid_size(group_sid, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) 	if (sid_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4525) 	total_len += sid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4527) 	/* check name len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4528) 	if (beg + total_len + 4 > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4529) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4530) 	name_len = le32_to_cpu(*(__le32 *)(beg + total_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4531) 	if (name_len < 1 || name_len > 0xFFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4532) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4533) 	total_len += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4535) 	/* check name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4536) 	name = beg + total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4537) 	if (name + name_len > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4538) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4539) 	total_len += name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4541) 	if (out) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4542) 		out->base = beg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4543) 		out->size = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4544) 		out->name_len = name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4545) 		out->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4546) 		memcpy(&out->owner, owner_sid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4547) 		       posix_info_sid_size(owner_sid, end));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4548) 		memcpy(&out->group, group_sid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4549) 		       posix_info_sid_size(group_sid, end));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4550) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4551) 	return total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4554) static int posix_info_extra_size(const void *beg, const void *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4556) 	int len = posix_info_parse(beg, end, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4558) 	if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4559) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4560) 	return len - sizeof(struct smb2_posix_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4563) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4564) num_entries(int infotype, char *bufstart, char *end_of_buf, char **lastentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4565) 	    size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4567) 	int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4568) 	unsigned int entrycount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4569) 	unsigned int next_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4570) 	char *entryptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4571) 	FILE_DIRECTORY_INFO *dir_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4573) 	if (bufstart == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4574) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4576) 	entryptr = bufstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4578) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4579) 		if (entryptr + next_offset < entryptr ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4580) 		    entryptr + next_offset > end_of_buf ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4581) 		    entryptr + next_offset + size > end_of_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4582) 			cifs_dbg(VFS, "malformed search entry would overflow\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4583) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4584) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4586) 		entryptr = entryptr + next_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4587) 		dir_info = (FILE_DIRECTORY_INFO *)entryptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4589) 		if (infotype == SMB_FIND_FILE_POSIX_INFO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4590) 			len = posix_info_extra_size(entryptr, end_of_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4591) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4592) 			len = le32_to_cpu(dir_info->FileNameLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4594) 		if (len < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4595) 		    entryptr + len < entryptr ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4596) 		    entryptr + len > end_of_buf ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4597) 		    entryptr + len + size > end_of_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4598) 			cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4599) 				 end_of_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4600) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4601) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4603) 		*lastentry = entryptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4604) 		entrycount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4606) 		next_offset = le32_to_cpu(dir_info->NextEntryOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4607) 		if (!next_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4608) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4609) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4611) 	return entrycount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4614) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4615)  * Readdir/FindFirst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4616)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4617) int SMB2_query_directory_init(const unsigned int xid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4618) 			      struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4619) 			      struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4620) 			      struct smb_rqst *rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4621) 			      u64 persistent_fid, u64 volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4622) 			      int index, int info_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4624) 	struct smb2_query_directory_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4625) 	unsigned char *bufptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4626) 	__le16 asteriks = cpu_to_le16('*');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4627) 	unsigned int output_size = CIFSMaxBufSize -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4628) 		MAX_SMB2_CREATE_RESPONSE_SIZE -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4629) 		MAX_SMB2_CLOSE_RESPONSE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4630) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4631) 	struct kvec *iov = rqst->rq_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4632) 	int len, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4634) 	rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4635) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4636) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4637) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4639) 	switch (info_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4640) 	case SMB_FIND_FILE_DIRECTORY_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4641) 		req->FileInformationClass = FILE_DIRECTORY_INFORMATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4642) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4643) 	case SMB_FIND_FILE_ID_FULL_DIR_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4644) 		req->FileInformationClass = FILEID_FULL_DIRECTORY_INFORMATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4645) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4646) 	case SMB_FIND_FILE_POSIX_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4647) 		req->FileInformationClass = SMB_FIND_FILE_POSIX_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4648) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4649) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4650) 		cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4651) 			info_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4652) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4653) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4655) 	req->FileIndex = cpu_to_le32(index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4656) 	req->PersistentFileId = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4657) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4659) 	len = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4660) 	bufptr = req->Buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4661) 	memcpy(bufptr, &asteriks, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4663) 	req->FileNameOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4664) 		cpu_to_le16(sizeof(struct smb2_query_directory_req) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4665) 	req->FileNameLength = cpu_to_le16(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4666) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4667) 	 * BB could be 30 bytes or so longer if we used SMB2 specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4668) 	 * buffer lengths, but this is safe and close enough.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4669) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4670) 	output_size = min_t(unsigned int, output_size, server->maxBuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4671) 	output_size = min_t(unsigned int, output_size, 2 << 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4672) 	req->OutputBufferLength = cpu_to_le32(output_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4674) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4675) 	/* 1 for Buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4676) 	iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4678) 	iov[1].iov_base = (char *)(req->Buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4679) 	iov[1].iov_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4681) 	trace_smb3_query_dir_enter(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4682) 			tcon->ses->Suid, index, output_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4684) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4687) void SMB2_query_directory_free(struct smb_rqst *rqst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4689) 	if (rqst && rqst->rq_iov) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4690) 		cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4691) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4694) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4695) smb2_parse_query_directory(struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4696) 			   struct kvec *rsp_iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4697) 			   int resp_buftype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4698) 			   struct cifs_search_info *srch_inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4700) 	struct smb2_query_directory_rsp *rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4701) 	size_t info_buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4702) 	char *end_of_smb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4703) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4705) 	rsp = (struct smb2_query_directory_rsp *)rsp_iov->iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4707) 	switch (srch_inf->info_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4708) 	case SMB_FIND_FILE_DIRECTORY_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4709) 		info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4710) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4711) 	case SMB_FIND_FILE_ID_FULL_DIR_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4712) 		info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4713) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4714) 	case SMB_FIND_FILE_POSIX_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4715) 		/* note that posix payload are variable size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4716) 		info_buf_size = sizeof(struct smb2_posix_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4717) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4718) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4719) 		cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4720) 			 srch_inf->info_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4721) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4722) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4724) 	rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4725) 			       le32_to_cpu(rsp->OutputBufferLength), rsp_iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4726) 			       info_buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4727) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4728) 		cifs_tcon_dbg(VFS, "bad info payload");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4729) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4730) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4732) 	srch_inf->unicode = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4734) 	if (srch_inf->ntwrk_buf_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4735) 		if (srch_inf->smallBuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4736) 			cifs_small_buf_release(srch_inf->ntwrk_buf_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4737) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4738) 			cifs_buf_release(srch_inf->ntwrk_buf_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4739) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4740) 	srch_inf->ntwrk_buf_start = (char *)rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4741) 	srch_inf->srch_entries_start = srch_inf->last_entry =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4742) 		(char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4743) 	end_of_smb = rsp_iov->iov_len + (char *)rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4745) 	srch_inf->entries_in_buffer = num_entries(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4746) 		srch_inf->info_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4747) 		srch_inf->srch_entries_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4748) 		end_of_smb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4749) 		&srch_inf->last_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4750) 		info_buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4752) 	srch_inf->index_of_last_entry += srch_inf->entries_in_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4753) 	cifs_dbg(FYI, "num entries %d last_index %lld srch start %p srch end %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4754) 		 srch_inf->entries_in_buffer, srch_inf->index_of_last_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4755) 		 srch_inf->srch_entries_start, srch_inf->last_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4756) 	if (resp_buftype == CIFS_LARGE_BUFFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4757) 		srch_inf->smallBuf = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4758) 	else if (resp_buftype == CIFS_SMALL_BUFFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4759) 		srch_inf->smallBuf = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4760) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4761) 		cifs_tcon_dbg(VFS, "Invalid search buffer type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4763) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4766) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4767) SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4768) 		     u64 persistent_fid, u64 volatile_fid, int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4769) 		     struct cifs_search_info *srch_inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4771) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4772) 	struct kvec iov[SMB2_QUERY_DIRECTORY_IOV_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4773) 	struct smb2_query_directory_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4774) 	int resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4775) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4776) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4777) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4778) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4779) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4781) 	if (!ses || !(ses->server))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4782) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4784) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4785) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4787) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4788) 	memset(&iov, 0, sizeof(iov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4789) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4790) 	rqst.rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4792) 	rc = SMB2_query_directory_init(xid, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4793) 				       &rqst, persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4794) 				       volatile_fid, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4795) 				       srch_inf->info_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4796) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4797) 		goto qdir_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4799) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4800) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4801) 	rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4803) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4804) 		if (rc == -ENODATA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4805) 		    rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4806) 			trace_smb3_query_dir_done(xid, persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4807) 				tcon->tid, tcon->ses->Suid, index, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4808) 			srch_inf->endOfSearch = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4809) 			rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4810) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4811) 			trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4812) 				tcon->ses->Suid, index, 0, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4813) 			cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4814) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4815) 		goto qdir_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4816) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4818) 	rc = smb2_parse_query_directory(tcon, &rsp_iov,	resp_buftype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4819) 					srch_inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4820) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4821) 		trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4822) 			tcon->ses->Suid, index, 0, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4823) 		goto qdir_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4824) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4825) 	resp_buftype = CIFS_NO_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4827) 	trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4828) 			tcon->ses->Suid, index, srch_inf->entries_in_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4830) qdir_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4831) 	SMB2_query_directory_free(&rqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4832) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4833) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4836) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4837) SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4838) 		   struct smb_rqst *rqst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4839) 		   u64 persistent_fid, u64 volatile_fid, u32 pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4840) 		   u8 info_class, u8 info_type, u32 additional_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4841) 		   void **data, unsigned int *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4843) 	struct smb2_set_info_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4844) 	struct kvec *iov = rqst->rq_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4845) 	unsigned int i, total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4846) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4848) 	rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4849) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4850) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4851) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4853) 	req->sync_hdr.ProcessId = cpu_to_le32(pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4854) 	req->InfoType = info_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4855) 	req->FileInfoClass = info_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4856) 	req->PersistentFileId = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4857) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4858) 	req->AdditionalInformation = cpu_to_le32(additional_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4860) 	req->BufferOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4861) 			cpu_to_le16(sizeof(struct smb2_set_info_req) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4862) 	req->BufferLength = cpu_to_le32(*size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4864) 	memcpy(req->Buffer, *data, *size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4865) 	total_len += *size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4867) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4868) 	/* 1 for Buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4869) 	iov[0].iov_len = total_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4871) 	for (i = 1; i < rqst->rq_nvec; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4872) 		le32_add_cpu(&req->BufferLength, size[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4873) 		iov[i].iov_base = (char *)data[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4874) 		iov[i].iov_len = size[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4875) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4877) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4880) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4881) SMB2_set_info_free(struct smb_rqst *rqst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4883) 	if (rqst && rqst->rq_iov)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4884) 		cifs_buf_release(rqst->rq_iov[0].iov_base); /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4887) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4888) send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4889) 	       u64 persistent_fid, u64 volatile_fid, u32 pid, u8 info_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4890) 	       u8 info_type, u32 additional_info, unsigned int num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4891) 		void **data, unsigned int *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4893) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4894) 	struct smb2_set_info_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4895) 	struct kvec *iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4896) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4897) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4898) 	int resp_buftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4899) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4900) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4901) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4903) 	if (!ses || !server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4904) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4906) 	if (!num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4907) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4909) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4910) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4912) 	iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4913) 	if (!iov)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4914) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4916) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4917) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4918) 	rqst.rq_nvec = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4920) 	rc = SMB2_set_info_init(tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4921) 				&rqst, persistent_fid, volatile_fid, pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4922) 				info_class, info_type, additional_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4923) 				data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4924) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4925) 		kfree(iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4926) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4927) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4930) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4931) 			    &rqst, &resp_buftype, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4932) 			    &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4933) 	SMB2_set_info_free(&rqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4934) 	rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4936) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4937) 		cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4938) 		trace_smb3_set_info_err(xid, persistent_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4939) 				ses->Suid, info_class, (__u32)info_type, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4940) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4942) 	free_rsp_buf(resp_buftype, rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4943) 	kfree(iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4944) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4947) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4948) SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4949) 	     u64 volatile_fid, u32 pid, __le64 *eof)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4950) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4951) 	struct smb2_file_eof_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4952) 	void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4953) 	unsigned int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4954) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4955) 	info.EndOfFile = *eof;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4956) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4957) 	data = &info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4958) 	size = sizeof(struct smb2_file_eof_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4960) 	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4961) 			pid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4962) 			0, 1, &data, &size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4964) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4965) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4966) SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4967) 		u64 persistent_fid, u64 volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4968) 		struct cifs_ntsd *pnntsd, int pacllen, int aclflag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4970) 	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4971) 			current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4972) 			1, (void **)&pnntsd, &pacllen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4975) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4976) SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4977) 	    u64 persistent_fid, u64 volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4978) 	    struct smb2_file_full_ea_info *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4979) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4980) 	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4981) 		current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4982) 		0, 1, (void **)&buf, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4985) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4986) SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4987) 		  const u64 persistent_fid, const u64 volatile_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4988) 		  __u8 oplock_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4990) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4991) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4992) 	struct smb2_oplock_break *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4993) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4994) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4995) 	int flags = CIFS_OBREAK_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4996) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4997) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4998) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4999) 	int resp_buf_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5000) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5001) 	cifs_dbg(FYI, "SMB2_oplock_break\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5002) 	rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5003) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5004) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5005) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5007) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5008) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5009) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5010) 	req->VolatileFid = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5011) 	req->PersistentFid = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5012) 	req->OplockLevel = oplock_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5013) 	req->sync_hdr.CreditRequest = cpu_to_le16(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5015) 	flags |= CIFS_NO_RSP_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5017) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5018) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5020) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5021) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5022) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5024) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5025) 			    &rqst, &resp_buf_type, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5026) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5027) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5028) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5029) 		cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5030) 		cifs_dbg(FYI, "Send error in Oplock Break = %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5031) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5033) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5036) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5037) smb2_copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5038) 			     struct kstatfs *kst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5039) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5040) 	kst->f_bsize = le32_to_cpu(pfs_inf->BytesPerSector) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5041) 			  le32_to_cpu(pfs_inf->SectorsPerAllocationUnit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5042) 	kst->f_blocks = le64_to_cpu(pfs_inf->TotalAllocationUnits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5043) 	kst->f_bfree  = kst->f_bavail =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5044) 			le64_to_cpu(pfs_inf->CallerAvailableAllocationUnits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5045) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5047) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5048) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5049) copy_posix_fs_info_to_kstatfs(FILE_SYSTEM_POSIX_INFO *response_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5050) 			struct kstatfs *kst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5051) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5052) 	kst->f_bsize = le32_to_cpu(response_data->BlockSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5053) 	kst->f_blocks = le64_to_cpu(response_data->TotalBlocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5054) 	kst->f_bfree =  le64_to_cpu(response_data->BlocksAvail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5055) 	if (response_data->UserBlocksAvail == cpu_to_le64(-1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5056) 		kst->f_bavail = kst->f_bfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5057) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5058) 		kst->f_bavail = le64_to_cpu(response_data->UserBlocksAvail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5059) 	if (response_data->TotalFileNodes != cpu_to_le64(-1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5060) 		kst->f_files = le64_to_cpu(response_data->TotalFileNodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5061) 	if (response_data->FreeFileNodes != cpu_to_le64(-1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5062) 		kst->f_ffree = le64_to_cpu(response_data->FreeFileNodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5063) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5064) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5066) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5067) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5068) build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5069) 		   struct TCP_Server_Info *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5070) 		   int level, int outbuf_len, u64 persistent_fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5071) 		   u64 volatile_fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5073) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5074) 	struct smb2_query_info_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5075) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5076) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5077) 	cifs_dbg(FYI, "Query FSInfo level %d\n", level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5078) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5079) 	if ((tcon->ses == NULL) || server == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5080) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5082) 	rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5083) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5084) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5085) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5087) 	req->InfoType = SMB2_O_INFO_FILESYSTEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5088) 	req->FileInfoClass = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5089) 	req->PersistentFileId = persistent_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5090) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5091) 	/* 1 for pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5092) 	req->InputBufferOffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5093) 			cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5094) 	req->OutputBufferLength = cpu_to_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5095) 		outbuf_len + sizeof(struct smb2_query_info_rsp) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5097) 	iov->iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5098) 	iov->iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5099) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5102) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5103) SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5104) 	      u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5106) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5107) 	struct smb2_query_info_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5108) 	struct kvec iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5109) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5110) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5111) 	int resp_buftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5112) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5113) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5114) 	FILE_SYSTEM_POSIX_INFO *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5115) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5117) 	rc = build_qfs_info_req(&iov, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5118) 				FS_POSIX_INFORMATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5119) 				sizeof(FILE_SYSTEM_POSIX_INFO),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5120) 				persistent_fid, volatile_fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5121) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5122) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5124) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5125) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5127) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5128) 	rqst.rq_iov = &iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5129) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5131) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5132) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5133) 	cifs_small_buf_release(iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5134) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5135) 		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5136) 		goto posix_qfsinf_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5137) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5138) 	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5140) 	info = (FILE_SYSTEM_POSIX_INFO *)(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5141) 		le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5142) 	rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5143) 			       le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5144) 			       sizeof(FILE_SYSTEM_POSIX_INFO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5145) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5146) 		copy_posix_fs_info_to_kstatfs(info, fsdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5148) posix_qfsinf_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5149) 	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5150) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5153) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5154) SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5155) 	      u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5157) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5158) 	struct smb2_query_info_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5159) 	struct kvec iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5160) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5161) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5162) 	int resp_buftype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5163) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5164) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5165) 	struct smb2_fs_full_size_info *info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5166) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5168) 	rc = build_qfs_info_req(&iov, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5169) 				FS_FULL_SIZE_INFORMATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5170) 				sizeof(struct smb2_fs_full_size_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5171) 				persistent_fid, volatile_fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5172) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5173) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5175) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5176) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5178) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5179) 	rqst.rq_iov = &iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5180) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5182) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5183) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5184) 	cifs_small_buf_release(iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5185) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5186) 		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5187) 		goto qfsinf_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5189) 	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5191) 	info = (struct smb2_fs_full_size_info *)(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5192) 		le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5193) 	rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5194) 			       le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5195) 			       sizeof(struct smb2_fs_full_size_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5196) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5197) 		smb2_copy_fs_info_to_kstatfs(info, fsdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5199) qfsinf_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5200) 	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5201) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5204) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5205) SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5206) 	      u64 persistent_fid, u64 volatile_fid, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5208) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5209) 	struct smb2_query_info_rsp *rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5210) 	struct kvec iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5211) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5212) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5213) 	int resp_buftype, max_len, min_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5214) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5215) 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5216) 	unsigned int rsp_len, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5217) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5219) 	if (level == FS_DEVICE_INFORMATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5220) 		max_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5221) 		min_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5222) 	} else if (level == FS_ATTRIBUTE_INFORMATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5223) 		max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5224) 		min_len = MIN_FS_ATTR_INFO_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5225) 	} else if (level == FS_SECTOR_SIZE_INFORMATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5226) 		max_len = sizeof(struct smb3_fs_ss_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5227) 		min_len = sizeof(struct smb3_fs_ss_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5228) 	} else if (level == FS_VOLUME_INFORMATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5229) 		max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5230) 		min_len = sizeof(struct smb3_fs_vol_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5231) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5232) 		cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5233) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5234) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5236) 	rc = build_qfs_info_req(&iov, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5237) 				level, max_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5238) 				persistent_fid, volatile_fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5239) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5240) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5242) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5243) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5245) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5246) 	rqst.rq_iov = &iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5247) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5249) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5250) 			    &rqst, &resp_buftype, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5251) 	cifs_small_buf_release(iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5252) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5253) 		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5254) 		goto qfsattr_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5255) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5256) 	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5258) 	rsp_len = le32_to_cpu(rsp->OutputBufferLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5259) 	offset = le16_to_cpu(rsp->OutputBufferOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5260) 	rc = smb2_validate_iov(offset, rsp_len, &rsp_iov, min_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5261) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5262) 		goto qfsattr_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5264) 	if (level == FS_ATTRIBUTE_INFORMATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5265) 		memcpy(&tcon->fsAttrInfo, offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5266) 			+ (char *)rsp, min_t(unsigned int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5267) 			rsp_len, max_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5268) 	else if (level == FS_DEVICE_INFORMATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5269) 		memcpy(&tcon->fsDevInfo, offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5270) 			+ (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5271) 	else if (level == FS_SECTOR_SIZE_INFORMATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5272) 		struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5273) 			(offset + (char *)rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5274) 		tcon->ss_flags = le32_to_cpu(ss_info->Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5275) 		tcon->perf_sector_size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5276) 			le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5277) 	} else if (level == FS_VOLUME_INFORMATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5278) 		struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5279) 			(offset + (char *)rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5280) 		tcon->vol_serial_number = vol_info->VolumeSerialNumber;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5281) 		tcon->vol_create_time = vol_info->VolumeCreationTime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5282) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5284) qfsattr_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5285) 	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5286) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5289) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5290) smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5291) 	   const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5292) 	   const __u32 num_lock, struct smb2_lock_element *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5294) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5295) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5296) 	struct smb2_lock_req *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5297) 	struct kvec iov[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5298) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5299) 	int resp_buf_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5300) 	unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5301) 	int flags = CIFS_NO_RSP_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5302) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5303) 	struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5305) 	cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5307) 	rc = smb2_plain_req_init(SMB2_LOCK, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5308) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5309) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5310) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5312) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5313) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5315) 	req->sync_hdr.ProcessId = cpu_to_le32(pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5316) 	req->LockCount = cpu_to_le16(num_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5318) 	req->PersistentFileId = persist_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5319) 	req->VolatileFileId = volatile_fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5321) 	count = num_lock * sizeof(struct smb2_lock_element);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5323) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5324) 	iov[0].iov_len = total_len - sizeof(struct smb2_lock_element);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5325) 	iov[1].iov_base = (char *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5326) 	iov[1].iov_len = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5328) 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5330) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5331) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5332) 	rqst.rq_nvec = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5334) 	rc = cifs_send_recv(xid, tcon->ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5335) 			    &rqst, &resp_buf_type, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5336) 			    &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5337) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5338) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5339) 		cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5340) 		cifs_stats_fail_inc(tcon, SMB2_LOCK_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5341) 		trace_smb3_lock_err(xid, persist_fid, tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5342) 				    tcon->ses->Suid, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5343) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5345) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5348) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5349) SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5350) 	  const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5351) 	  const __u64 length, const __u64 offset, const __u32 lock_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5352) 	  const bool wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5354) 	struct smb2_lock_element lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5356) 	lock.Offset = cpu_to_le64(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5357) 	lock.Length = cpu_to_le64(length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5358) 	lock.Flags = cpu_to_le32(lock_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5359) 	if (!wait && lock_flags != SMB2_LOCKFLAG_UNLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5360) 		lock.Flags |= cpu_to_le32(SMB2_LOCKFLAG_FAIL_IMMEDIATELY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5362) 	return smb2_lockv(xid, tcon, persist_fid, volatile_fid, pid, 1, &lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5365) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5366) SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5367) 		 __u8 *lease_key, const __le32 lease_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5369) 	struct smb_rqst rqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5370) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5371) 	struct smb2_lease_ack *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5372) 	struct cifs_ses *ses = tcon->ses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5373) 	int flags = CIFS_OBREAK_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5374) 	unsigned int total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5375) 	struct kvec iov[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5376) 	struct kvec rsp_iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5377) 	int resp_buf_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5378) 	__u64 *please_key_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5379) 	__u64 *please_key_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5380) 	struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5382) 	cifs_dbg(FYI, "SMB2_lease_break\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5383) 	rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5384) 				 (void **) &req, &total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5385) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5386) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5388) 	if (smb3_encryption_required(tcon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5389) 		flags |= CIFS_TRANSFORM_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5391) 	req->sync_hdr.CreditRequest = cpu_to_le16(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5392) 	req->StructureSize = cpu_to_le16(36);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5393) 	total_len += 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5395) 	memcpy(req->LeaseKey, lease_key, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5396) 	req->LeaseState = lease_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5398) 	flags |= CIFS_NO_RSP_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5400) 	iov[0].iov_base = (char *)req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5401) 	iov[0].iov_len = total_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5403) 	memset(&rqst, 0, sizeof(struct smb_rqst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5404) 	rqst.rq_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5405) 	rqst.rq_nvec = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5407) 	rc = cifs_send_recv(xid, ses, server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5408) 			    &rqst, &resp_buf_type, flags, &rsp_iov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5409) 	cifs_small_buf_release(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5411) 	please_key_low = (__u64 *)lease_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5412) 	please_key_high = (__u64 *)(lease_key+8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5413) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5414) 		cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5415) 		trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5416) 			ses->Suid, *please_key_low, *please_key_high, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5417) 		cifs_dbg(FYI, "Send error in Lease Break = %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5418) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5419) 		trace_smb3_lease_done(le32_to_cpu(lease_state), tcon->tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5420) 			ses->Suid, *please_key_low, *please_key_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5422) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5423) }