File Index
Files and directories
Sign in
FILE

smb2inode.c

File preview with syntax highlighting.

linux-6.19.14/fs/smb/client/smb2inode.c C
   1// SPDX-License-Identifier: LGPL-2.1
   2/*
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2002, 2011
   5 *                 Etersoft, 2012
   6 *   Author(s): Pavel Shilovsky (pshilovsky@samba.org),
   7 *              Steve French (sfrench@us.ibm.com)
   8 *
   9 */
  10#include <linux/fs.h>
  11#include <linux/stat.h>
  12#include <linux/slab.h>
  13#include <linux/pagemap.h>
  14#include <asm/div64.h>
  15#include "cifsfs.h"
  16#include "cifspdu.h"
  17#include "cifsglob.h"
  18#include "cifsproto.h"
  19#include "cifs_debug.h"
  20#include "cifs_fs_sb.h"
  21#include "cifs_unicode.h"
  22#include "fscache.h"
  23#include "smb2glob.h"
  24#include "smb2proto.h"
  25#include "cached_dir.h"
  26#include "../common/smb2status.h"
  27
  28static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
  29{
  30	struct reparse_data_buffer *buf;
  31	struct smb2_ioctl_rsp *io = iov->iov_base;
  32	u32 off, count, len;
  33	u16 rdlen;
  34
  35	count = le32_to_cpu(io->OutputCount);
  36	off = le32_to_cpu(io->OutputOffset);
  37	if (check_add_overflow(off, count, &len) || len > iov->iov_len)
  38		return ERR_PTR(smb_EIO2(smb_eio_trace_reparse_overlong,
  39					off, count));
  40
  41	buf = (struct reparse_data_buffer *)((u8 *)io + off);
  42	len = sizeof(*buf);
  43	rdlen = le16_to_cpu(buf->ReparseDataLength);
  44
  45	if (count < len || count < rdlen + len)
  46		return ERR_PTR(smb_EIO2(smb_eio_trace_reparse_rdlen, count, rdlen));
  47	return buf;
  48}
  49
  50static inline __u32 file_create_options(struct dentry *dentry)
  51{
  52	struct cifsInodeInfo *ci;
  53
  54	if (dentry) {
  55		ci = CIFS_I(d_inode(dentry));
  56		if (ci->cifsAttrs & ATTR_REPARSE_POINT)
  57			return OPEN_REPARSE_POINT;
  58	}
  59	return 0;
  60}
  61
  62/* Parse owner and group from SMB3.1.1 POSIX query info */
  63static int parse_posix_sids(struct cifs_open_info_data *data,
  64			    struct kvec *rsp_iov)
  65{
  66	struct smb2_query_info_rsp *qi = rsp_iov->iov_base;
  67	unsigned int out_len = le32_to_cpu(qi->OutputBufferLength);
  68	unsigned int qi_len = sizeof(data->posix_fi);
  69	int owner_len, group_len;
  70	u8 *sidsbuf, *sidsbuf_end;
  71
  72	if (out_len <= qi_len)
  73		return -EINVAL;
  74
  75	sidsbuf = (u8 *)qi + le16_to_cpu(qi->OutputBufferOffset) + qi_len;
  76	sidsbuf_end = sidsbuf + out_len - qi_len;
  77
  78	owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
  79	if (owner_len == -1)
  80		return -EINVAL;
  81
  82	memcpy(&data->posix_owner, sidsbuf, owner_len);
  83	group_len = posix_info_sid_size(sidsbuf + owner_len, sidsbuf_end);
  84	if (group_len == -1)
  85		return -EINVAL;
  86
  87	memcpy(&data->posix_group, sidsbuf + owner_len, group_len);
  88	return 0;
  89}
  90
  91struct wsl_query_ea {
  92	__le32	next;
  93	__u8	name_len;
  94	__u8	name[SMB2_WSL_XATTR_NAME_LEN + 1];
  95} __packed;
  96
  97#define NEXT_OFF cpu_to_le32(sizeof(struct wsl_query_ea))
  98
  99static const struct wsl_query_ea wsl_query_eas[] = {
 100	{ .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_UID, },
 101	{ .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_GID, },
 102	{ .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_MODE, },
 103	{ .next = 0,        .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_DEV, },
 104};
 105
 106static int check_wsl_eas(struct kvec *rsp_iov)
 107{
 108	struct smb2_file_full_ea_info *ea;
 109	struct smb2_query_info_rsp *rsp = rsp_iov->iov_base;
 110	unsigned long addr;
 111	u32 outlen, next;
 112	u16 vlen;
 113	u8 nlen;
 114	u8 *end;
 115
 116	outlen = le32_to_cpu(rsp->OutputBufferLength);
 117	if (outlen < SMB2_WSL_MIN_QUERY_EA_RESP_SIZE ||
 118	    outlen > SMB2_WSL_MAX_QUERY_EA_RESP_SIZE)
 119		return -EINVAL;
 120
 121	ea = (void *)((u8 *)rsp_iov->iov_base +
 122		      le16_to_cpu(rsp->OutputBufferOffset));
 123	end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len;
 124	for (;;) {
 125		if ((u8 *)ea > end - sizeof(*ea))
 126			return -EINVAL;
 127
 128		nlen = ea->ea_name_length;
 129		vlen = le16_to_cpu(ea->ea_value_length);
 130		if (nlen != SMB2_WSL_XATTR_NAME_LEN ||
 131		    (u8 *)ea->ea_data + nlen + 1 + vlen > end)
 132			return -EINVAL;
 133
 134		switch (vlen) {
 135		case 4:
 136			if (strncmp(ea->ea_data, SMB2_WSL_XATTR_UID, nlen) &&
 137			    strncmp(ea->ea_data, SMB2_WSL_XATTR_GID, nlen) &&
 138			    strncmp(ea->ea_data, SMB2_WSL_XATTR_MODE, nlen))
 139				return -EINVAL;
 140			break;
 141		case 8:
 142			if (strncmp(ea->ea_data, SMB2_WSL_XATTR_DEV, nlen))
 143				return -EINVAL;
 144			break;
 145		case 0:
 146			if (!strncmp(ea->ea_data, SMB2_WSL_XATTR_UID, nlen) ||
 147			    !strncmp(ea->ea_data, SMB2_WSL_XATTR_GID, nlen) ||
 148			    !strncmp(ea->ea_data, SMB2_WSL_XATTR_MODE, nlen) ||
 149			    !strncmp(ea->ea_data, SMB2_WSL_XATTR_DEV, nlen))
 150				break;
 151			fallthrough;
 152		default:
 153			return -EINVAL;
 154		}
 155
 156		next = le32_to_cpu(ea->next_entry_offset);
 157		if (!next)
 158			break;
 159		if (!IS_ALIGNED(next, 4) ||
 160		    check_add_overflow((unsigned long)ea, next, &addr))
 161			return -EINVAL;
 162		ea = (void *)addr;
 163	}
 164	return 0;
 165}
 166
 167/*
 168 * note: If cfile is passed, the reference to it is dropped here.
 169 * So make sure that you do not reuse cfile after return from this func.
 170 *
 171 * If passing @out_iov and @out_buftype, ensure to make them both large enough
 172 * (>= 3) to hold all compounded responses.  Caller is also responsible for
 173 * freeing them up with free_rsp_buf().
 174 */
 175static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
 176			    struct cifs_sb_info *cifs_sb, const char *full_path,
 177			    struct cifs_open_parms *oparms, struct kvec *in_iov,
 178			    int *cmds, int num_cmds, struct cifsFileInfo *cfile,
 179			    struct kvec *out_iov, int *out_buftype, struct dentry *dentry)
 180{
 181
 182	struct smb2_create_rsp *create_rsp = NULL;
 183	struct smb2_query_info_rsp *qi_rsp = NULL;
 184	struct smb2_compound_vars *vars = NULL;
 185	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
 186	struct cifs_open_info_data *idata;
 187	struct cifs_ses *ses = tcon->ses;
 188	struct reparse_data_buffer *rbuf;
 189	struct TCP_Server_Info *server;
 190	int resp_buftype[MAX_COMPOUND];
 191	int retries = 0, cur_sleep = 1;
 192	__u8 delete_pending[8] = {1,};
 193	struct kvec *rsp_iov, *iov;
 194	struct inode *inode = NULL;
 195	__le16 *utf16_path = NULL;
 196	struct smb_rqst *rqst;
 197	unsigned int size[2];
 198	struct cifs_fid fid;
 199	int num_rqst = 0, i;
 200	unsigned int len;
 201	int tmp_rc, rc;
 202	int flags = 0;
 203	void *data[2];
 204
 205replay_again:
 206	/* reinitialize for possible replay */
 207	flags = 0;
 208	oplock = SMB2_OPLOCK_LEVEL_NONE;
 209	num_rqst = 0;
 210	server = cifs_pick_channel(ses);
 211
 212	vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
 213	if (vars == NULL) {
 214		rc = -ENOMEM;
 215		goto out;
 216	}
 217	rqst = &vars->rqst[0];
 218	rsp_iov = &vars->rsp_iov[0];
 219
 220	if (smb3_encryption_required(tcon))
 221		flags |= CIFS_TRANSFORM_REQ;
 222
 223	for (i = 0; i < ARRAY_SIZE(resp_buftype); i++)
 224		resp_buftype[i] = CIFS_NO_BUFFER;
 225
 226	/* We already have a handle so we can skip the open */
 227	if (cfile)
 228		goto after_open;
 229
 230	/* Open */
 231	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
 232	if (!utf16_path) {
 233		rc = -ENOMEM;
 234		goto finished;
 235	}
 236
 237	/* if there is an existing lease, reuse it */
 238
 239	/*
 240	 * note: files with hardlinks cause unexpected behaviour. As per MS-SMB2,
 241	 * lease keys are associated with the filepath. We are maintaining lease keys
 242	 * with the inode on the client. If the file has hardlinks, it is possible
 243	 * that the lease for a file be reused for an operation on its hardlink or
 244	 * vice versa.
 245	 * As a workaround, send request using an existing lease key and if the server
 246	 * returns STATUS_INVALID_PARAMETER, which maps to EINVAL, send the request
 247	 * again without the lease.
 248	 */
 249	if (dentry) {
 250		inode = d_inode(dentry);
 251		if (CIFS_I(inode)->lease_granted && server->ops->get_lease_key) {
 252			oplock = SMB2_OPLOCK_LEVEL_LEASE;
 253			server->ops->get_lease_key(inode, &fid);
 254		}
 255	}
 256
 257	vars->oparms = *oparms;
 258	vars->oparms.fid = &fid;
 259
 260	rqst[num_rqst].rq_iov = &vars->open_iov[0];
 261	rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE;
 262	rc = SMB2_open_init(tcon, server,
 263			    &rqst[num_rqst], &oplock, &vars->oparms,
 264			    utf16_path);
 265	kfree(utf16_path);
 266	if (rc)
 267		goto finished;
 268
 269	smb2_set_next_command(tcon, &rqst[num_rqst]);
 270 after_open:
 271	num_rqst++;
 272	rc = 0;
 273
 274	i = 0;
 275
 276	/* Skip the leading explicit OPEN operation */
 277	if (num_cmds > 0 && cmds[0] == SMB2_OP_OPEN_QUERY)
 278		i++;
 279
 280	for (; i < num_cmds; i++) {
 281		/* Operation */
 282		switch (cmds[i]) {
 283		case SMB2_OP_QUERY_INFO:
 284			rqst[num_rqst].rq_iov = &vars->qi_iov;
 285			rqst[num_rqst].rq_nvec = 1;
 286
 287			if (cfile) {
 288				rc = SMB2_query_info_init(tcon, server,
 289							  &rqst[num_rqst],
 290							  cfile->fid.persistent_fid,
 291							  cfile->fid.volatile_fid,
 292							  FILE_ALL_INFORMATION,
 293							  SMB2_O_INFO_FILE, 0,
 294							  sizeof(struct smb2_file_all_info) +
 295							  PATH_MAX * 2, 0, NULL);
 296			} else {
 297				rc = SMB2_query_info_init(tcon, server,
 298							  &rqst[num_rqst],
 299							  COMPOUND_FID,
 300							  COMPOUND_FID,
 301							  FILE_ALL_INFORMATION,
 302							  SMB2_O_INFO_FILE, 0,
 303							  sizeof(struct smb2_file_all_info) +
 304							  PATH_MAX * 2, 0, NULL);
 305			}
 306			if (!rc && (!cfile || num_rqst > 1)) {
 307				smb2_set_next_command(tcon, &rqst[num_rqst]);
 308				smb2_set_related(&rqst[num_rqst]);
 309			} else if (rc) {
 310				goto finished;
 311			}
 312			num_rqst++;
 313			trace_smb3_query_info_compound_enter(xid, tcon->tid,
 314							     ses->Suid, full_path);
 315			break;
 316		case SMB2_OP_POSIX_QUERY_INFO:
 317			rqst[num_rqst].rq_iov = &vars->qi_iov;
 318			rqst[num_rqst].rq_nvec = 1;
 319
 320			if (cfile) {
 321				/* TBD: fix following to allow for longer SIDs */
 322				rc = SMB2_query_info_init(tcon, server,
 323							  &rqst[num_rqst],
 324							  cfile->fid.persistent_fid,
 325							  cfile->fid.volatile_fid,
 326							  SMB_FIND_FILE_POSIX_INFO,
 327							  SMB2_O_INFO_FILE, 0,
 328							  sizeof(struct smb311_posix_qinfo) +
 329							  (PATH_MAX * 2) +
 330							  (sizeof(struct smb_sid) * 2), 0, NULL);
 331			} else {
 332				rc = SMB2_query_info_init(tcon, server,
 333							  &rqst[num_rqst],
 334							  COMPOUND_FID,
 335							  COMPOUND_FID,
 336							  SMB_FIND_FILE_POSIX_INFO,
 337							  SMB2_O_INFO_FILE, 0,
 338							  sizeof(struct smb311_posix_qinfo) +
 339							  (PATH_MAX * 2) +
 340							  (sizeof(struct smb_sid) * 2), 0, NULL);
 341			}
 342			if (!rc && (!cfile || num_rqst > 1)) {
 343				smb2_set_next_command(tcon, &rqst[num_rqst]);
 344				smb2_set_related(&rqst[num_rqst]);
 345			} else if (rc) {
 346				goto finished;
 347			}
 348			num_rqst++;
 349			trace_smb3_posix_query_info_compound_enter(xid, tcon->tid,
 350								   ses->Suid, full_path);
 351			break;
 352		case SMB2_OP_MKDIR:
 353			/*
 354			 * Directories are created through parameters in the
 355			 * SMB2_open() call.
 356			 */
 357			trace_smb3_mkdir_enter(xid, tcon->tid, ses->Suid, full_path);
 358			break;
 359		case SMB2_OP_UNLINK:
 360			rqst[num_rqst].rq_iov = vars->unlink_iov;
 361			rqst[num_rqst].rq_nvec = 1;
 362
 363			size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
 364			data[0] = &delete_pending[0];
 365
 366			if (cfile) {
 367				rc = SMB2_set_info_init(tcon, server,
 368							&rqst[num_rqst],
 369							cfile->fid.persistent_fid,
 370							cfile->fid.volatile_fid,
 371							current->tgid,
 372							FILE_DISPOSITION_INFORMATION,
 373							SMB2_O_INFO_FILE, 0,
 374							data, size);
 375			} else {
 376				rc = SMB2_set_info_init(tcon, server,
 377							&rqst[num_rqst],
 378							COMPOUND_FID,
 379							COMPOUND_FID,
 380							current->tgid,
 381							FILE_DISPOSITION_INFORMATION,
 382							SMB2_O_INFO_FILE, 0,
 383							data, size);
 384			}
 385			if (!rc && (!cfile || num_rqst > 1)) {
 386				smb2_set_next_command(tcon, &rqst[num_rqst]);
 387				smb2_set_related(&rqst[num_rqst]);
 388			} else if (rc) {
 389				goto finished;
 390			}
 391			num_rqst++;
 392			trace_smb3_unlink_enter(xid, tcon->tid, ses->Suid, full_path);
 393			break;
 394		case SMB2_OP_SET_EOF:
 395			rqst[num_rqst].rq_iov = &vars->si_iov[0];
 396			rqst[num_rqst].rq_nvec = 1;
 397
 398			size[0] = in_iov[i].iov_len;
 399			data[0] = in_iov[i].iov_base;
 400
 401			if (cfile) {
 402				rc = SMB2_set_info_init(tcon, server,
 403							&rqst[num_rqst],
 404							cfile->fid.persistent_fid,
 405							cfile->fid.volatile_fid,
 406							current->tgid,
 407							FILE_END_OF_FILE_INFORMATION,
 408							SMB2_O_INFO_FILE, 0,
 409							data, size);
 410			} else {
 411				rc = SMB2_set_info_init(tcon, server,
 412							&rqst[num_rqst],
 413							COMPOUND_FID,
 414							COMPOUND_FID,
 415							current->tgid,
 416							FILE_END_OF_FILE_INFORMATION,
 417							SMB2_O_INFO_FILE, 0,
 418							data, size);
 419			}
 420			if (!rc && (!cfile || num_rqst > 1)) {
 421				smb2_set_next_command(tcon, &rqst[num_rqst]);
 422				smb2_set_related(&rqst[num_rqst]);
 423			} else if (rc) {
 424				goto finished;
 425			}
 426			num_rqst++;
 427			trace_smb3_set_eof_enter(xid, tcon->tid, ses->Suid, full_path);
 428			break;
 429		case SMB2_OP_SET_INFO:
 430			rqst[num_rqst].rq_iov = &vars->si_iov[0];
 431			rqst[num_rqst].rq_nvec = 1;
 432
 433			size[0] = in_iov[i].iov_len;
 434			data[0] = in_iov[i].iov_base;
 435
 436			if (cfile) {
 437				rc = SMB2_set_info_init(tcon, server,
 438							&rqst[num_rqst],
 439							cfile->fid.persistent_fid,
 440							cfile->fid.volatile_fid, current->tgid,
 441							FILE_BASIC_INFORMATION,
 442							SMB2_O_INFO_FILE, 0, data, size);
 443			} else {
 444				rc = SMB2_set_info_init(tcon, server,
 445							&rqst[num_rqst],
 446							COMPOUND_FID,
 447							COMPOUND_FID, current->tgid,
 448							FILE_BASIC_INFORMATION,
 449							SMB2_O_INFO_FILE, 0, data, size);
 450			}
 451			if (!rc && (!cfile || num_rqst > 1)) {
 452				smb2_set_next_command(tcon, &rqst[num_rqst]);
 453				smb2_set_related(&rqst[num_rqst]);
 454			} else if (rc) {
 455				goto finished;
 456			}
 457			num_rqst++;
 458			trace_smb3_set_info_compound_enter(xid, tcon->tid,
 459							   ses->Suid, full_path);
 460			break;
 461		case SMB2_OP_RENAME:
 462			rqst[num_rqst].rq_iov = vars->rename_iov;
 463			rqst[num_rqst].rq_nvec = 2;
 464
 465			len = in_iov[i].iov_len;
 466
 467			vars->rename_info.ReplaceIfExists = 1;
 468			vars->rename_info.RootDirectory = 0;
 469			vars->rename_info.FileNameLength = cpu_to_le32(len);
 470
 471			size[0] = sizeof(struct smb2_file_rename_info);
 472			data[0] = &vars->rename_info;
 473
 474			size[1] = len + 2 /* null */;
 475			data[1] = in_iov[i].iov_base;
 476
 477			if (cfile) {
 478				rc = SMB2_set_info_init(tcon, server,
 479							&rqst[num_rqst],
 480							cfile->fid.persistent_fid,
 481							cfile->fid.volatile_fid,
 482							current->tgid, FILE_RENAME_INFORMATION,
 483							SMB2_O_INFO_FILE, 0, data, size);
 484			} else {
 485				rc = SMB2_set_info_init(tcon, server,
 486							&rqst[num_rqst],
 487							COMPOUND_FID, COMPOUND_FID,
 488							current->tgid, FILE_RENAME_INFORMATION,
 489							SMB2_O_INFO_FILE, 0, data, size);
 490			}
 491			if (!rc && (!cfile || num_rqst > 1)) {
 492				smb2_set_next_command(tcon, &rqst[num_rqst]);
 493				smb2_set_related(&rqst[num_rqst]);
 494			} else if (rc) {
 495				goto finished;
 496			}
 497			num_rqst++;
 498			trace_smb3_rename_enter(xid, tcon->tid, ses->Suid, full_path);
 499			break;
 500		case SMB2_OP_HARDLINK:
 501			rqst[num_rqst].rq_iov = &vars->si_iov[0];
 502			rqst[num_rqst].rq_nvec = 2;
 503
 504			len = in_iov[i].iov_len;
 505
 506			vars->link_info.ReplaceIfExists = 0;
 507			vars->link_info.RootDirectory = 0;
 508			vars->link_info.FileNameLength = cpu_to_le32(len);
 509
 510			size[0] = sizeof(struct smb2_file_link_info);
 511			data[0] = &vars->link_info;
 512
 513			size[1] = len + 2 /* null */;
 514			data[1] = in_iov[i].iov_base;
 515
 516			rc = SMB2_set_info_init(tcon, server,
 517						&rqst[num_rqst], COMPOUND_FID,
 518						COMPOUND_FID, current->tgid,
 519						FILE_LINK_INFORMATION,
 520						SMB2_O_INFO_FILE, 0, data, size);
 521			if (rc)
 522				goto finished;
 523			smb2_set_next_command(tcon, &rqst[num_rqst]);
 524			smb2_set_related(&rqst[num_rqst++]);
 525			trace_smb3_hardlink_enter(xid, tcon->tid, ses->Suid, full_path);
 526			break;
 527		case SMB2_OP_SET_REPARSE:
 528			rqst[num_rqst].rq_iov = vars->io_iov;
 529			rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
 530
 531			if (cfile) {
 532				rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
 533						     cfile->fid.persistent_fid,
 534						     cfile->fid.volatile_fid,
 535						     FSCTL_SET_REPARSE_POINT,
 536						     in_iov[i].iov_base,
 537						     in_iov[i].iov_len, 0);
 538			} else {
 539				rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
 540						     COMPOUND_FID, COMPOUND_FID,
 541						     FSCTL_SET_REPARSE_POINT,
 542						     in_iov[i].iov_base,
 543						     in_iov[i].iov_len, 0);
 544			}
 545			if (!rc && (!cfile || num_rqst > 1)) {
 546				smb2_set_next_command(tcon, &rqst[num_rqst]);
 547				smb2_set_related(&rqst[num_rqst]);
 548			} else if (rc) {
 549				goto finished;
 550			}
 551			num_rqst++;
 552			trace_smb3_set_reparse_compound_enter(xid, tcon->tid,
 553							      ses->Suid, full_path);
 554			break;
 555		case SMB2_OP_GET_REPARSE:
 556			rqst[num_rqst].rq_iov = vars->io_iov;
 557			rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
 558
 559			if (cfile) {
 560				rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
 561						     cfile->fid.persistent_fid,
 562						     cfile->fid.volatile_fid,
 563						     FSCTL_GET_REPARSE_POINT,
 564						     NULL, 0, CIFSMaxBufSize);
 565			} else {
 566				rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
 567						     COMPOUND_FID, COMPOUND_FID,
 568						     FSCTL_GET_REPARSE_POINT,
 569						     NULL, 0, CIFSMaxBufSize);
 570			}
 571			if (!rc && (!cfile || num_rqst > 1)) {
 572				smb2_set_next_command(tcon, &rqst[num_rqst]);
 573				smb2_set_related(&rqst[num_rqst]);
 574			} else if (rc) {
 575				goto finished;
 576			}
 577			num_rqst++;
 578			trace_smb3_get_reparse_compound_enter(xid, tcon->tid,
 579							      ses->Suid, full_path);
 580			break;
 581		case SMB2_OP_QUERY_WSL_EA:
 582			rqst[num_rqst].rq_iov = &vars->ea_iov;
 583			rqst[num_rqst].rq_nvec = 1;
 584
 585			if (cfile) {
 586				rc = SMB2_query_info_init(tcon, server,
 587							  &rqst[num_rqst],
 588							  cfile->fid.persistent_fid,
 589							  cfile->fid.volatile_fid,
 590							  FILE_FULL_EA_INFORMATION,
 591							  SMB2_O_INFO_FILE, 0,
 592							  SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,
 593							  sizeof(wsl_query_eas),
 594							  (void *)wsl_query_eas);
 595			} else {
 596				rc = SMB2_query_info_init(tcon, server,
 597							  &rqst[num_rqst],
 598							  COMPOUND_FID,
 599							  COMPOUND_FID,
 600							  FILE_FULL_EA_INFORMATION,
 601							  SMB2_O_INFO_FILE, 0,
 602							  SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,
 603							  sizeof(wsl_query_eas),
 604							  (void *)wsl_query_eas);
 605			}
 606			if (!rc && (!cfile || num_rqst > 1)) {
 607				smb2_set_next_command(tcon, &rqst[num_rqst]);
 608				smb2_set_related(&rqst[num_rqst]);
 609			} else if (rc) {
 610				goto finished;
 611			}
 612			num_rqst++;
 613			trace_smb3_query_wsl_ea_compound_enter(xid, tcon->tid,
 614							       ses->Suid, full_path);
 615			break;
 616		default:
 617			cifs_dbg(VFS, "Invalid command\n");
 618			rc = -EINVAL;
 619		}
 620	}
 621	if (rc)
 622		goto finished;
 623
 624	/* We already have a handle so we can skip the close */
 625	if (cfile)
 626		goto after_close;
 627	/* Close */
 628	flags |= CIFS_CP_CREATE_CLOSE_OP;
 629	rqst[num_rqst].rq_iov = &vars->close_iov;
 630	rqst[num_rqst].rq_nvec = 1;
 631	rc = SMB2_close_init(tcon, server,
 632			     &rqst[num_rqst], COMPOUND_FID,
 633			     COMPOUND_FID, false);
 634	smb2_set_related(&rqst[num_rqst]);
 635	if (rc)
 636		goto finished;
 637 after_close:
 638	num_rqst++;
 639
 640	if (cfile) {
 641		if (retries)
 642			for (i = 1; i < num_rqst - 2; i++)
 643				smb2_set_replay(server, &rqst[i]);
 644
 645		rc = compound_send_recv(xid, ses, server,
 646					flags, num_rqst - 2,
 647					&rqst[1], &resp_buftype[1],
 648					&rsp_iov[1]);
 649	} else {
 650		if (retries)
 651			for (i = 0; i < num_rqst; i++)
 652				smb2_set_replay(server, &rqst[i]);
 653
 654		rc = compound_send_recv(xid, ses, server,
 655					flags, num_rqst,
 656					rqst, resp_buftype,
 657					rsp_iov);
 658	}
 659
 660finished:
 661	num_rqst = 0;
 662	SMB2_open_free(&rqst[num_rqst++]);
 663	if (rc == -EREMCHG) {
 664		pr_warn_once("server share %s deleted\n", tcon->tree_name);
 665		tcon->need_reconnect = true;
 666	}
 667
 668	tmp_rc = rc;
 669
 670	if (rc == 0 && num_cmds > 0 && cmds[0] == SMB2_OP_OPEN_QUERY) {
 671		create_rsp = rsp_iov[0].iov_base;
 672		idata = in_iov[0].iov_base;
 673		idata->fi.CreationTime = create_rsp->CreationTime;
 674		idata->fi.LastAccessTime = create_rsp->LastAccessTime;
 675		idata->fi.LastWriteTime = create_rsp->LastWriteTime;
 676		idata->fi.ChangeTime = create_rsp->ChangeTime;
 677		idata->fi.Attributes = create_rsp->FileAttributes;
 678		idata->fi.AllocationSize = create_rsp->AllocationSize;
 679		idata->fi.EndOfFile = create_rsp->EndofFile;
 680		if (le32_to_cpu(idata->fi.NumberOfLinks) == 0)
 681			idata->fi.NumberOfLinks = cpu_to_le32(1); /* dummy value */
 682		idata->fi.DeletePending = 0; /* successful open = not delete pending */
 683		idata->fi.Directory = !!(le32_to_cpu(create_rsp->FileAttributes) & ATTR_DIRECTORY);
 684
 685		/* smb2_parse_contexts() fills idata->fi.IndexNumber */
 686		rc = smb2_parse_contexts(server, &rsp_iov[0], &oparms->fid->epoch,
 687					 oparms->fid->lease_key, &oplock, &idata->fi, NULL);
 688		if (rc)
 689			cifs_dbg(VFS, "rc: %d parsing context of compound op\n", rc);
 690	}
 691
 692	for (i = 0; i < num_cmds; i++) {
 693		char *buf = rsp_iov[i + 1].iov_base;
 694
 695		if (buf && resp_buftype[i + 1] != CIFS_NO_BUFFER)
 696			rc = server->ops->map_error(buf, false);
 697		else
 698			rc = tmp_rc;
 699		switch (cmds[i]) {
 700		case SMB2_OP_QUERY_INFO:
 701			idata = in_iov[i].iov_base;
 702			idata->contains_posix_file_info = false;
 703			if (rc == 0 && cfile && cfile->symlink_target) {
 704				idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
 705				if (!idata->symlink_target)
 706					rc = -ENOMEM;
 707			}
 708			if (rc == 0) {
 709				qi_rsp = (struct smb2_query_info_rsp *)
 710					rsp_iov[i + 1].iov_base;
 711				rc = smb2_validate_and_copy_iov(
 712					le16_to_cpu(qi_rsp->OutputBufferOffset),
 713					le32_to_cpu(qi_rsp->OutputBufferLength),
 714					&rsp_iov[i + 1], sizeof(idata->fi), (char *)&idata->fi);
 715			}
 716			SMB2_query_info_free(&rqst[num_rqst++]);
 717			if (rc)
 718				trace_smb3_query_info_compound_err(xid,  tcon->tid,
 719								   ses->Suid, rc);
 720			else
 721				trace_smb3_query_info_compound_done(xid, tcon->tid,
 722								    ses->Suid);
 723			break;
 724		case SMB2_OP_POSIX_QUERY_INFO:
 725			idata = in_iov[i].iov_base;
 726			idata->contains_posix_file_info = true;
 727			if (rc == 0 && cfile && cfile->symlink_target) {
 728				idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
 729				if (!idata->symlink_target)
 730					rc = -ENOMEM;
 731			}
 732			if (rc == 0) {
 733				qi_rsp = (struct smb2_query_info_rsp *)
 734					rsp_iov[i + 1].iov_base;
 735				rc = smb2_validate_and_copy_iov(
 736					le16_to_cpu(qi_rsp->OutputBufferOffset),
 737					le32_to_cpu(qi_rsp->OutputBufferLength),
 738					&rsp_iov[i + 1], sizeof(idata->posix_fi) /* add SIDs */,
 739					(char *)&idata->posix_fi);
 740			}
 741			if (rc == 0)
 742				rc = parse_posix_sids(idata, &rsp_iov[i + 1]);
 743
 744			SMB2_query_info_free(&rqst[num_rqst++]);
 745			if (rc)
 746				trace_smb3_posix_query_info_compound_err(xid,  tcon->tid,
 747									 ses->Suid, rc);
 748			else
 749				trace_smb3_posix_query_info_compound_done(xid, tcon->tid,
 750									  ses->Suid);
 751			break;
 752		case SMB2_OP_MKDIR:
 753			if (rc)
 754				trace_smb3_mkdir_err(xid, tcon->tid, ses->Suid, rc);
 755			else
 756				trace_smb3_mkdir_done(xid, tcon->tid, ses->Suid);
 757			break;
 758		case SMB2_OP_HARDLINK:
 759			if (rc)
 760				trace_smb3_hardlink_err(xid,  tcon->tid, ses->Suid, rc);
 761			else
 762				trace_smb3_hardlink_done(xid, tcon->tid, ses->Suid);
 763			SMB2_set_info_free(&rqst[num_rqst++]);
 764			break;
 765		case SMB2_OP_RENAME:
 766			if (rc)
 767				trace_smb3_rename_err(xid, tcon->tid, ses->Suid, rc);
 768			else
 769				trace_smb3_rename_done(xid, tcon->tid, ses->Suid);
 770			SMB2_set_info_free(&rqst[num_rqst++]);
 771			break;
 772		case SMB2_OP_UNLINK:
 773			if (!rc)
 774				trace_smb3_unlink_done(xid, tcon->tid, ses->Suid);
 775			else
 776				trace_smb3_unlink_err(xid, tcon->tid, ses->Suid, rc);
 777			SMB2_set_info_free(&rqst[num_rqst++]);
 778			break;
 779		case SMB2_OP_SET_EOF:
 780			if (rc)
 781				trace_smb3_set_eof_err(xid, tcon->tid, ses->Suid, rc);
 782			else
 783				trace_smb3_set_eof_done(xid, tcon->tid, ses->Suid);
 784			SMB2_set_info_free(&rqst[num_rqst++]);
 785			break;
 786		case SMB2_OP_SET_INFO:
 787			if (rc)
 788				trace_smb3_set_info_compound_err(xid,  tcon->tid,
 789								 ses->Suid, rc);
 790			else
 791				trace_smb3_set_info_compound_done(xid, tcon->tid,
 792								  ses->Suid);
 793			SMB2_set_info_free(&rqst[num_rqst++]);
 794			break;
 795		case SMB2_OP_SET_REPARSE:
 796			if (rc) {
 797				trace_smb3_set_reparse_compound_err(xid, tcon->tid,
 798								    ses->Suid, rc);
 799			} else {
 800				trace_smb3_set_reparse_compound_done(xid, tcon->tid,
 801								     ses->Suid);
 802			}
 803			SMB2_ioctl_free(&rqst[num_rqst++]);
 804			break;
 805		case SMB2_OP_GET_REPARSE:
 806			if (!rc) {
 807				iov = &rsp_iov[i + 1];
 808				idata = in_iov[i].iov_base;
 809				idata->reparse.io.iov = *iov;
 810				idata->reparse.io.buftype = resp_buftype[i + 1];
 811				idata->contains_posix_file_info = false; /* BB VERIFY */
 812				rbuf = reparse_buf_ptr(iov);
 813				if (IS_ERR(rbuf)) {
 814					rc = PTR_ERR(rbuf);
 815					trace_smb3_get_reparse_compound_err(xid, tcon->tid,
 816									    ses->Suid, rc);
 817				} else {
 818					idata->reparse.tag = le32_to_cpu(rbuf->ReparseTag);
 819					trace_smb3_get_reparse_compound_done(xid, tcon->tid,
 820									     ses->Suid);
 821				}
 822				memset(iov, 0, sizeof(*iov));
 823				resp_buftype[i + 1] = CIFS_NO_BUFFER;
 824			} else {
 825				trace_smb3_get_reparse_compound_err(xid, tcon->tid,
 826								    ses->Suid, rc);
 827			}
 828			SMB2_ioctl_free(&rqst[num_rqst++]);
 829			break;
 830		case SMB2_OP_QUERY_WSL_EA:
 831			if (!rc) {
 832				idata = in_iov[i].iov_base;
 833				idata->contains_posix_file_info = false;
 834				qi_rsp = rsp_iov[i + 1].iov_base;
 835				data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset);
 836				size[0] = le32_to_cpu(qi_rsp->OutputBufferLength);
 837				rc = check_wsl_eas(&rsp_iov[i + 1]);
 838				if (!rc) {
 839					memcpy(idata->wsl.eas, data[0], size[0]);
 840					idata->wsl.eas_len = size[0];
 841				}
 842			}
 843			if (!rc) {
 844				trace_smb3_query_wsl_ea_compound_done(xid, tcon->tid,
 845								      ses->Suid);
 846			} else {
 847				trace_smb3_query_wsl_ea_compound_err(xid, tcon->tid,
 848								     ses->Suid, rc);
 849			}
 850			SMB2_query_info_free(&rqst[num_rqst++]);
 851			break;
 852		}
 853	}
 854	SMB2_close_free(&rqst[num_rqst]);
 855	rc = tmp_rc;
 856
 857	num_cmds += 2;
 858	if (out_iov && out_buftype) {
 859		memcpy(out_iov, rsp_iov, num_cmds * sizeof(*out_iov));
 860		memcpy(out_buftype, resp_buftype,
 861		       num_cmds * sizeof(*out_buftype));
 862	} else {
 863		for (i = 0; i < num_cmds; i++)
 864			free_rsp_buf(resp_buftype[i], rsp_iov[i].iov_base);
 865	}
 866	num_cmds -= 2; /* correct num_cmds as there could be a retry */
 867	kfree(vars);
 868
 869	if (is_replayable_error(rc) &&
 870	    smb2_should_replay(tcon, &retries, &cur_sleep))
 871		goto replay_again;
 872
 873out:
 874	if (cfile)
 875		cifsFileInfo_put(cfile);
 876
 877	return rc;
 878}
 879
 880static int parse_create_response(struct cifs_open_info_data *data,
 881				 struct cifs_sb_info *cifs_sb,
 882				 const char *full_path,
 883				 const struct kvec *iov)
 884{
 885	struct smb2_create_rsp *rsp = iov->iov_base;
 886	bool reparse_point = false;
 887	u32 tag = 0;
 888	int rc = 0;
 889
 890	switch (rsp->hdr.Status) {
 891	case STATUS_IO_REPARSE_TAG_NOT_HANDLED:
 892		reparse_point = true;
 893		break;
 894	case STATUS_STOPPED_ON_SYMLINK:
 895		rc = smb2_parse_symlink_response(cifs_sb, iov,
 896						 full_path,
 897						 &data->symlink_target);
 898		if (rc)
 899			return rc;
 900		tag = IO_REPARSE_TAG_SYMLINK;
 901		reparse_point = true;
 902		break;
 903	case STATUS_SUCCESS:
 904		reparse_point = !!(rsp->Flags & SMB2_CREATE_FLAG_REPARSEPOINT);
 905		break;
 906	}
 907	data->reparse_point = reparse_point;
 908	data->reparse.tag = tag;
 909	return rc;
 910}
 911
 912/* Check only if SMB2_OP_QUERY_WSL_EA command failed in the compound chain */
 913static bool ea_unsupported(int *cmds, int num_cmds,
 914			   struct kvec *out_iov, int *out_buftype)
 915{
 916	int i;
 917
 918	if (cmds[num_cmds - 1] != SMB2_OP_QUERY_WSL_EA)
 919		return false;
 920
 921	for (i = 1; i < num_cmds - 1; i++) {
 922		struct smb2_hdr *hdr = out_iov[i].iov_base;
 923
 924		if (out_buftype[i] == CIFS_NO_BUFFER || !hdr ||
 925		    hdr->Status != STATUS_SUCCESS)
 926			return false;
 927	}
 928	return true;
 929}
 930
 931static inline void free_rsp_iov(struct kvec *iovs, int *buftype, int count)
 932{
 933	int i;
 934
 935	for (i = 0; i < count; i++) {
 936		free_rsp_buf(buftype[i], iovs[i].iov_base);
 937		memset(&iovs[i], 0, sizeof(*iovs));
 938		buftype[i] = CIFS_NO_BUFFER;
 939	}
 940}
 941
 942int smb2_query_path_info(const unsigned int xid,
 943			 struct cifs_tcon *tcon,
 944			 struct cifs_sb_info *cifs_sb,
 945			 const char *full_path,
 946			 struct cifs_open_info_data *data)
 947{
 948	struct kvec in_iov[3], out_iov[5] = {};
 949	struct cached_fid *cfid = NULL;
 950	struct cifs_open_parms oparms;
 951	struct cifsFileInfo *cfile;
 952	__u32 create_options = 0;
 953	int out_buftype[5] = {};
 954	struct smb2_hdr *hdr;
 955	int num_cmds = 0;
 956	int cmds[3];
 957	bool islink;
 958	int rc, rc2;
 959
 960	data->adjust_tz = false;
 961	data->reparse_point = false;
 962
 963	/*
 964	 * BB TODO: Add support for using cached root handle in SMB3.1.1 POSIX.
 965	 * Create SMB2_query_posix_info worker function to do non-compounded
 966	 * query when we already have an open file handle for this. For now this
 967	 * is fast enough (always using the compounded version).
 968	 */
 969	if (!tcon->posix_extensions) {
 970		if (*full_path) {
 971			rc = -ENOENT;
 972		} else {
 973			rc = open_cached_dir(xid, tcon, full_path,
 974					     cifs_sb, false, &cfid);
 975		}
 976		/* If it is a root and its handle is cached then use it */
 977		if (!rc) {
 978			if (cfid->file_all_info_is_valid) {
 979				memcpy(&data->fi, &cfid->file_all_info,
 980				       sizeof(data->fi));
 981			} else {
 982				rc = SMB2_query_info(xid, tcon,
 983						     cfid->fid.persistent_fid,
 984						     cfid->fid.volatile_fid,
 985						     &data->fi);
 986			}
 987			close_cached_dir(cfid);
 988			return rc;
 989		}
 990		cmds[num_cmds++] = SMB2_OP_QUERY_INFO;
 991	} else {
 992		cmds[num_cmds++] = SMB2_OP_POSIX_QUERY_INFO;
 993	}
 994
 995	in_iov[0].iov_base = data;
 996	in_iov[0].iov_len = sizeof(*data);
 997	in_iov[1] = in_iov[0];
 998	in_iov[2] = in_iov[0];
 999
1000	cifs_get_readable_path(tcon, full_path, &cfile);
1001	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_ATTRIBUTES,
1002			     FILE_OPEN, create_options, ACL_NO_MODE);
1003	rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
1004			      &oparms, in_iov, cmds, num_cmds,
1005			      cfile, out_iov, out_buftype, NULL);
1006	hdr = out_iov[0].iov_base;
1007	/*
1008	 * If first iov is unset, then SMB session was dropped or we've got a
1009	 * cached open file (@cfile).
1010	 */
1011	if (!hdr || out_buftype[0] == CIFS_NO_BUFFER)
1012		goto out;
1013
1014	switch (rc) {
1015	case 0:
1016		rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
1017		break;
1018	case -EACCES:
1019		/*
1020		 * If SMB2_OP_QUERY_INFO (called when POSIX extensions are not used) failed with
1021		 * STATUS_ACCESS_DENIED then it means that caller does not have permission to
1022		 * open the path with FILE_READ_ATTRIBUTES access and therefore cannot issue
1023		 * SMB2_OP_QUERY_INFO command.
1024		 *
1025		 * There is an alternative way how to query limited information about path but still
1026		 * suitable for stat() syscall. SMB2 OPEN/CREATE operation returns in its successful
1027		 * response subset of query information.
1028		 *
1029		 * So try to open the path without FILE_READ_ATTRIBUTES but with MAXIMUM_ALLOWED
1030		 * access which will grant the maximum possible access to the file and the response
1031		 * will contain required query information for stat() syscall.
1032		 */
1033
1034		if (tcon->posix_extensions)
1035			break;
1036
1037		num_cmds = 1;
1038		cmds[0] = SMB2_OP_OPEN_QUERY;
1039		in_iov[0].iov_base = data;
1040		in_iov[0].iov_len = sizeof(*data);
1041		oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, MAXIMUM_ALLOWED,
1042				     FILE_OPEN, create_options, ACL_NO_MODE);
1043		free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
1044		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
1045				      &oparms, in_iov, cmds, num_cmds,
1046				      cfile, out_iov, out_buftype, NULL);
1047
1048		hdr = out_iov[0].iov_base;
1049		if (!hdr || out_buftype[0] == CIFS_NO_BUFFER)
1050			goto out;
1051
1052		if (!rc)
1053			rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
1054		break;
1055	case -EOPNOTSUPP:
1056		/*
1057		 * BB TODO: When support for special files added to Samba
1058		 * re-verify this path.
1059		 */
1060		rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
1061		if (rc || !data->reparse_point)
1062			goto out;
1063
1064		/*
1065		 * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
1066		 * response.
1067		 */
1068		if (data->reparse.tag != IO_REPARSE_TAG_SYMLINK) {
1069			cmds[num_cmds++] = SMB2_OP_GET_REPARSE;
1070			if (!tcon->posix_extensions)
1071				cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
1072		}
1073
1074		oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1075				     FILE_READ_ATTRIBUTES |
1076				     FILE_READ_EA | SYNCHRONIZE,
1077				     FILE_OPEN, create_options |
1078				     OPEN_REPARSE_POINT, ACL_NO_MODE);
1079		cifs_get_readable_path(tcon, full_path, &cfile);
1080		free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
1081		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
1082				      &oparms, in_iov, cmds, num_cmds,
1083				      cfile, out_iov, out_buftype, NULL);
1084		if (rc && ea_unsupported(cmds, num_cmds,
1085					 out_iov, out_buftype)) {
1086			if (data->reparse.tag != IO_REPARSE_TAG_LX_BLK &&
1087			    data->reparse.tag != IO_REPARSE_TAG_LX_CHR)
1088				rc = 0;
1089			else
1090				rc = -EOPNOTSUPP;
1091		}
1092
1093		if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK && !rc) {
1094			bool directory = le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY;
1095			rc = smb2_fix_symlink_target_type(&data->symlink_target, directory, cifs_sb);
1096		}
1097		break;
1098	case -EREMOTE:
1099		break;
1100	default:
1101		if (hdr->Status != STATUS_OBJECT_NAME_INVALID)
1102			break;
1103		rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
1104						     full_path, &islink);
1105		if (rc2) {
1106			rc = rc2;
1107			goto out;
1108		}
1109		if (islink)
1110			rc = -EREMOTE;
1111	}
1112
1113out:
1114	free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
1115	return rc;
1116}
1117
1118int
1119smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
1120	   struct cifs_tcon *tcon, const char *name,
1121	   struct cifs_sb_info *cifs_sb)
1122{
1123	struct cifs_open_parms oparms;
1124
1125	oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
1126			     FILE_CREATE, CREATE_NOT_FILE, mode);
1127	return smb2_compound_op(xid, tcon, cifs_sb,
1128				name, &oparms, NULL,
1129				&(int){SMB2_OP_MKDIR}, 1,
1130				NULL, NULL, NULL, NULL);
1131}
1132
1133void
1134smb2_mkdir_setinfo(struct inode *inode, const char *name,
1135		   struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
1136		   const unsigned int xid)
1137{
1138	struct cifs_open_parms oparms;
1139	FILE_BASIC_INFO data = {};
1140	struct cifsInodeInfo *cifs_i;
1141	struct cifsFileInfo *cfile;
1142	struct kvec in_iov;
1143	u32 dosattrs;
1144	int tmprc;
1145
1146	in_iov.iov_base = &data;
1147	in_iov.iov_len = sizeof(data);
1148	cifs_i = CIFS_I(inode);
1149	dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
1150	data.Attributes = cpu_to_le32(dosattrs);
1151	cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
1152	oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
1153			     FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE);
1154	tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
1155				 &oparms, &in_iov,
1156				 &(int){SMB2_OP_SET_INFO}, 1,
1157				 cfile, NULL, NULL, NULL);
1158	if (tmprc == 0)
1159		cifs_i->cifsAttrs = dosattrs;
1160}
1161
1162int
1163smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
1164	   struct cifs_sb_info *cifs_sb)
1165{
1166	struct cifs_open_parms oparms;
1167
1168	drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
1169	oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE,
1170			     FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE);
1171	return smb2_compound_op(xid, tcon, cifs_sb,
1172				name, &oparms, NULL,
1173				&(int){SMB2_OP_UNLINK}, 1,
1174				NULL, NULL, NULL, NULL);
1175}
1176
1177int
1178smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
1179	    struct cifs_sb_info *cifs_sb, struct dentry *dentry)
1180{
1181	struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
1182	__le16 *utf16_path __free(kfree) = NULL;
1183	int retries = 0, cur_sleep = 1;
1184	struct TCP_Server_Info *server;
1185	struct cifs_open_parms oparms;
1186	struct smb2_create_req *creq;
1187	struct inode *inode = NULL;
1188	struct smb_rqst rqst[2];
1189	struct kvec rsp_iov[2];
1190	struct kvec close_iov;
1191	int resp_buftype[2];
1192	struct cifs_fid fid;
1193	int flags = 0;
1194	__u8 oplock;
1195	int rc;
1196
1197	utf16_path = cifs_convert_path_to_utf16(name, cifs_sb);
1198	if (!utf16_path)
1199		return -ENOMEM;
1200
1201	if (smb3_encryption_required(tcon))
1202		flags |= CIFS_TRANSFORM_REQ;
1203again:
1204	oplock = SMB2_OPLOCK_LEVEL_NONE;
1205	server = cifs_pick_channel(tcon->ses);
1206
1207	memset(rqst, 0, sizeof(rqst));
1208	memset(resp_buftype, 0, sizeof(resp_buftype));
1209	memset(rsp_iov, 0, sizeof(rsp_iov));
1210
1211	memset(open_iov, 0, sizeof(open_iov));
1212	rqst[0].rq_iov = open_iov;
1213	rqst[0].rq_nvec = ARRAY_SIZE(open_iov);
1214
1215	oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE | FILE_READ_ATTRIBUTES,
1216			     FILE_OPEN, CREATE_DELETE_ON_CLOSE |
1217			     OPEN_REPARSE_POINT, ACL_NO_MODE);
1218	oparms.fid = &fid;
1219
1220	if (dentry) {
1221		inode = d_inode(dentry);
1222		if (CIFS_I(inode)->lease_granted && server->ops->get_lease_key) {
1223			oplock = SMB2_OPLOCK_LEVEL_LEASE;
1224			server->ops->get_lease_key(inode, &fid);
1225		}
1226	}
1227
1228	rc = SMB2_open_init(tcon, server,
1229			    &rqst[0], &oplock, &oparms, utf16_path);
1230	if (rc)
1231		goto err_free;
1232	smb2_set_next_command(tcon, &rqst[0]);
1233	creq = rqst[0].rq_iov[0].iov_base;
1234	creq->ShareAccess = FILE_SHARE_DELETE_LE;
1235
1236	memset(&close_iov, 0, sizeof(close_iov));
1237	rqst[1].rq_iov = &close_iov;
1238	rqst[1].rq_nvec = 1;
1239
1240	rc = SMB2_close_init(tcon, server, &rqst[1],
1241			     COMPOUND_FID, COMPOUND_FID, false);
1242	if (rc)
1243		goto err_free;
1244	smb2_set_related(&rqst[1]);
1245
1246	if (retries) {
1247		for (int i = 0; i < ARRAY_SIZE(rqst);  i++)
1248			smb2_set_replay(server, &rqst[i]);
1249	}
1250
1251	rc = compound_send_recv(xid, tcon->ses, server, flags,
1252				ARRAY_SIZE(rqst), rqst,
1253				resp_buftype, rsp_iov);
1254	SMB2_open_free(&rqst[0]);
1255	SMB2_close_free(&rqst[1]);
1256	free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
1257	free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
1258
1259	if (is_replayable_error(rc) &&
1260	    smb2_should_replay(tcon, &retries, &cur_sleep))
1261		goto again;
1262
1263	/* Retry compound request without lease */
1264	if (rc == -EINVAL && dentry) {
1265		dentry = NULL;
1266		retries = 0;
1267		cur_sleep = 1;
1268		goto again;
1269	}
1270	/*
1271	 * If dentry (hence, inode) is NULL, lease break is going to
1272	 * take care of degrading leases on handles for deleted files.
1273	 */
1274	if (!rc && inode)
1275		cifs_mark_open_handles_for_deleted_file(inode, name);
1276
1277	return rc;
1278
1279err_free:
1280	SMB2_open_free(&rqst[0]);
1281	SMB2_close_free(&rqst[1]);
1282	free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
1283	free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
1284	return rc;
1285}
1286
1287static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
1288			      const char *from_name, const char *to_name,
1289			      struct cifs_sb_info *cifs_sb,
1290			      __u32 create_options, __u32 access,
1291			      int command, struct cifsFileInfo *cfile,
1292				  struct dentry *dentry)
1293{
1294	struct cifs_open_parms oparms;
1295	struct kvec in_iov;
1296	__le16 *smb2_to_name = NULL;
1297	int rc;
1298
1299	smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
1300	if (smb2_to_name == NULL) {
1301		rc = -ENOMEM;
1302		if (cfile)
1303			cifsFileInfo_put(cfile);
1304		goto smb2_rename_path;
1305	}
1306	in_iov.iov_base = smb2_to_name;
1307	in_iov.iov_len = 2 * UniStrnlen((wchar_t *)smb2_to_name, PATH_MAX);
1308	oparms = CIFS_OPARMS(cifs_sb, tcon, from_name, access, FILE_OPEN,
1309			     create_options, ACL_NO_MODE);
1310	rc = smb2_compound_op(xid, tcon, cifs_sb, from_name,
1311			      &oparms, &in_iov, &command, 1,
1312			      cfile, NULL, NULL, dentry);
1313smb2_rename_path:
1314	kfree(smb2_to_name);
1315	return rc;
1316}
1317
1318int smb2_rename_path(const unsigned int xid,
1319		     struct cifs_tcon *tcon,
1320		     struct dentry *source_dentry,
1321		     const char *from_name, const char *to_name,
1322		     struct cifs_sb_info *cifs_sb)
1323{
1324	struct cifsFileInfo *cfile;
1325	__u32 co = file_create_options(source_dentry);
1326
1327	drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
1328	cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
1329
1330	int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
1331				  co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
1332	if (rc == -EINVAL) {
1333		cifs_dbg(FYI, "invalid lease key, resending request without lease");
1334		cifs_get_writable_path(tcon, from_name,
1335				       FIND_WR_WITH_DELETE, &cfile);
1336		rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
1337				  co, DELETE, SMB2_OP_RENAME, cfile, NULL);
1338	}
1339	return rc;
1340}
1341
1342int smb2_create_hardlink(const unsigned int xid,
1343			 struct cifs_tcon *tcon,
1344			 struct dentry *source_dentry,
1345			 const char *from_name, const char *to_name,
1346			 struct cifs_sb_info *cifs_sb)
1347{
1348	__u32 co = file_create_options(source_dentry);
1349
1350	return smb2_set_path_attr(xid, tcon, from_name, to_name,
1351				  cifs_sb, co, FILE_READ_ATTRIBUTES,
1352				  SMB2_OP_HARDLINK, NULL, NULL);
1353}
1354
1355int
1356smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
1357		   const char *full_path, __u64 size,
1358		   struct cifs_sb_info *cifs_sb, bool set_alloc,
1359		   struct dentry *dentry)
1360{
1361	struct cifs_open_parms oparms;
1362	struct cifsFileInfo *cfile;
1363	struct kvec in_iov;
1364	__le64 eof = cpu_to_le64(size);
1365	int rc;
1366
1367	in_iov.iov_base = &eof;
1368	in_iov.iov_len = sizeof(eof);
1369	cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1370
1371	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,
1372			     FILE_OPEN, 0, ACL_NO_MODE);
1373	rc = smb2_compound_op(xid, tcon, cifs_sb,
1374			      full_path, &oparms, &in_iov,
1375			      &(int){SMB2_OP_SET_EOF}, 1,
1376			      cfile, NULL, NULL, dentry);
1377	if (rc == -EINVAL) {
1378		cifs_dbg(FYI, "invalid lease key, resending request without lease");
1379		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1380		rc = smb2_compound_op(xid, tcon, cifs_sb,
1381				      full_path, &oparms, &in_iov,
1382				      &(int){SMB2_OP_SET_EOF}, 1,
1383				      cfile, NULL, NULL, NULL);
1384	}
1385	return rc;
1386}
1387
1388int
1389smb2_set_file_info(struct inode *inode, const char *full_path,
1390		   FILE_BASIC_INFO *buf, const unsigned int xid)
1391{
1392	struct kvec in_iov = { .iov_base = buf, .iov_len = sizeof(*buf), };
1393	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1394	struct cifsFileInfo *cfile = NULL;
1395	struct cifs_open_parms oparms;
1396	struct tcon_link *tlink;
1397	struct cifs_tcon *tcon;
1398	int rc = 0;
1399
1400	tlink = cifs_sb_tlink(cifs_sb);
1401	if (IS_ERR(tlink))
1402		return PTR_ERR(tlink);
1403	tcon = tlink_tcon(tlink);
1404
1405	if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
1406	    (buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) {
1407		if (buf->Attributes == 0)
1408			goto out; /* would be a no op, no sense sending this */
1409		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1410	}
1411
1412	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES,
1413			     FILE_OPEN, 0, ACL_NO_MODE);
1414	rc = smb2_compound_op(xid, tcon, cifs_sb,
1415			      full_path, &oparms, &in_iov,
1416			      &(int){SMB2_OP_SET_INFO}, 1,
1417			      cfile, NULL, NULL, NULL);
1418out:
1419	cifs_put_tlink(tlink);
1420	return rc;
1421}
1422
1423struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
1424				     struct super_block *sb,
1425				     const unsigned int xid,
1426				     struct cifs_tcon *tcon,
1427				     const char *full_path,
1428				     bool directory,
1429				     struct kvec *reparse_iov,
1430				     struct kvec *xattr_iov)
1431{
1432	struct cifs_open_parms oparms;
1433	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1434	struct cifsFileInfo *cfile;
1435	struct inode *new = NULL;
1436	int out_buftype[4] = {};
1437	struct kvec out_iov[4] = {};
1438	struct kvec in_iov[2];
1439	int cmds[2];
1440	int rc;
1441	int i;
1442
1443	/*
1444	 * If server filesystem does not support reparse points then do not
1445	 * attempt to create reparse point. This will prevent creating unusable
1446	 * empty object on the server.
1447	 */
1448	if (!CIFS_REPARSE_SUPPORT(tcon))
1449		return ERR_PTR(-EOPNOTSUPP);
1450
1451	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1452			     SYNCHRONIZE | DELETE |
1453			     FILE_READ_ATTRIBUTES |
1454			     FILE_WRITE_ATTRIBUTES,
1455			     FILE_CREATE,
1456			     (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
1457			     ACL_NO_MODE);
1458	if (xattr_iov)
1459		oparms.ea_cctx = xattr_iov;
1460
1461	cmds[0] = SMB2_OP_SET_REPARSE;
1462	in_iov[0] = *reparse_iov;
1463	in_iov[1].iov_base = data;
1464	in_iov[1].iov_len = sizeof(*data);
1465
1466	if (tcon->posix_extensions) {
1467		cmds[1] = SMB2_OP_POSIX_QUERY_INFO;
1468		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1469		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
1470				      in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
1471		if (!rc) {
1472			rc = smb311_posix_get_inode_info(&new, full_path,
1473							 data, sb, xid);
1474		}
1475	} else {
1476		cmds[1] = SMB2_OP_QUERY_INFO;
1477		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1478		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
1479				      in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
1480		if (!rc) {
1481			rc = cifs_get_inode_info(&new, full_path,
1482						 data, sb, xid, NULL);
1483		}
1484	}
1485
1486
1487	/*
1488	 * If CREATE was successful but SMB2_OP_SET_REPARSE failed then
1489	 * remove the intermediate object created by CREATE. Otherwise
1490	 * empty object stay on the server when reparse call failed.
1491	 */
1492	if (rc &&
1493	    out_iov[0].iov_base != NULL && out_buftype[0] != CIFS_NO_BUFFER &&
1494	    ((struct smb2_hdr *)out_iov[0].iov_base)->Status == STATUS_SUCCESS &&
1495	    (out_iov[1].iov_base == NULL || out_buftype[1] == CIFS_NO_BUFFER ||
1496	     ((struct smb2_hdr *)out_iov[1].iov_base)->Status != STATUS_SUCCESS))
1497		smb2_unlink(xid, tcon, full_path, cifs_sb, NULL);
1498
1499	for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
1500		free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
1501
1502	return rc ? ERR_PTR(rc) : new;
1503}
1504
1505int smb2_query_reparse_point(const unsigned int xid,
1506			     struct cifs_tcon *tcon,
1507			     struct cifs_sb_info *cifs_sb,
1508			     const char *full_path,
1509			     u32 *tag, struct kvec *rsp,
1510			     int *rsp_buftype)
1511{
1512	struct cifs_open_parms oparms;
1513	struct cifs_open_info_data data = {};
1514	struct cifsFileInfo *cfile;
1515	struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), };
1516	int rc;
1517
1518	cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
1519
1520	cifs_get_readable_path(tcon, full_path, &cfile);
1521	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1522			     FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE,
1523			     FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE);
1524	rc = smb2_compound_op(xid, tcon, cifs_sb,
1525			      full_path, &oparms, &in_iov,
1526			      &(int){SMB2_OP_GET_REPARSE}, 1,
1527			      cfile, NULL, NULL, NULL);
1528	if (rc)
1529		goto out;
1530
1531	*tag = data.reparse.tag;
1532	*rsp = data.reparse.io.iov;
1533	*rsp_buftype = data.reparse.io.buftype;
1534	memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov));
1535	data.reparse.io.buftype = CIFS_NO_BUFFER;
1536out:
1537	cifs_free_open_info(&data);
1538	return rc;
1539}
1540
1541static inline __le16 *utf16_smb2_path(struct cifs_sb_info *cifs_sb,
1542				      const char *name, size_t namelen)
1543{
1544	int len;
1545
1546	if (*name == '\\' ||
1547	    (cifs_sb_master_tlink(cifs_sb) &&
1548	     cifs_sb_master_tcon(cifs_sb)->posix_extensions && *name == '/'))
1549		name++;
1550	return cifs_strndup_to_utf16(name, namelen, &len,
1551				     cifs_sb->local_nls,
1552				     cifs_remap(cifs_sb));
1553}
1554
1555int smb2_rename_pending_delete(const char *full_path,
1556			       struct dentry *dentry,
1557			       const unsigned int xid)
1558{
1559	struct cifs_sb_info *cifs_sb = CIFS_SB(d_inode(dentry)->i_sb);
1560	struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry));
1561	__le16 *utf16_path __free(kfree) = NULL;
1562	__u32 co = file_create_options(dentry);
1563	int cmds[] = {
1564		SMB2_OP_SET_INFO,
1565		SMB2_OP_RENAME,
1566		SMB2_OP_UNLINK,
1567	};
1568	const int num_cmds = ARRAY_SIZE(cmds);
1569	char *to_name __free(kfree) = NULL;
1570	__u32 attrs = cinode->cifsAttrs;
1571	struct cifs_open_parms oparms;
1572	static atomic_t sillycounter;
1573	struct cifsFileInfo *cfile;
1574	struct tcon_link *tlink;
1575	struct cifs_tcon *tcon;
1576	struct kvec iov[2];
1577	const char *ppath;
1578	void *page;
1579	size_t len;
1580	int rc;
1581
1582	tlink = cifs_sb_tlink(cifs_sb);
1583	if (IS_ERR(tlink))
1584		return PTR_ERR(tlink);
1585	tcon = tlink_tcon(tlink);
1586
1587	page = alloc_dentry_path();
1588
1589	ppath = build_path_from_dentry(dentry->d_parent, page);
1590	if (IS_ERR(ppath)) {
1591		rc = PTR_ERR(ppath);
1592		goto out;
1593	}
1594
1595	len = strlen(ppath) + strlen("/.__smb1234") + 1;
1596	to_name = kmalloc(len, GFP_KERNEL);
1597	if (!to_name) {
1598		rc = -ENOMEM;
1599		goto out;
1600	}
1601
1602	scnprintf(to_name, len, "%s%c.__smb%04X", ppath, CIFS_DIR_SEP(cifs_sb),
1603		  atomic_inc_return(&sillycounter) & 0xffff);
1604
1605	utf16_path = utf16_smb2_path(cifs_sb, to_name, len);
1606	if (!utf16_path) {
1607		rc = -ENOMEM;
1608		goto out;
1609	}
1610
1611	drop_cached_dir_by_name(xid, tcon, full_path, cifs_sb);
1612	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1613			     DELETE | FILE_WRITE_ATTRIBUTES,
1614			     FILE_OPEN, co, ACL_NO_MODE);
1615
1616	attrs &= ~ATTR_READONLY;
1617	if (!attrs)
1618		attrs = ATTR_NORMAL;
1619	if (d_inode(dentry)->i_nlink <= 1)
1620		attrs |= ATTR_HIDDEN;
1621	iov[0].iov_base = &(FILE_BASIC_INFO) {
1622		.Attributes = cpu_to_le32(attrs),
1623	};
1624	iov[0].iov_len = sizeof(FILE_BASIC_INFO);
1625	iov[1].iov_base = utf16_path;
1626	iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path);
1627
1628	cifs_get_writable_path(tcon, full_path, FIND_WR_WITH_DELETE, &cfile);
1629	rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,
1630			      cmds, num_cmds, cfile, NULL, NULL, dentry);
1631	if (rc == -EINVAL) {
1632		cifs_dbg(FYI, "invalid lease key, resending request without lease\n");
1633		cifs_get_writable_path(tcon, full_path,
1634				       FIND_WR_WITH_DELETE, &cfile);
1635		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,
1636				      cmds, num_cmds, cfile, NULL, NULL, NULL);
1637	}
1638	if (!rc) {
1639		set_bit(CIFS_INO_DELETE_PENDING, &cinode->flags);
1640	} else {
1641		cifs_tcon_dbg(FYI, "%s: failed to rename '%s' to '%s': %d\n",
1642			      __func__, full_path, to_name, rc);
1643		rc = smb_EIO1(smb_eio_trace_pend_del_fail, rc);
1644	}
1645out:
1646	cifs_put_tlink(tlink);
1647	free_dentry_path(page);
1648	return rc;
1649}
~/ Read-only file preview.