xref: /linux/fs/smb/client/smb2inode.c (revision 3be042cf46feeedf664152d063376b5c17026d1d)
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 "smb2pdu.h"
25 #include "smb2proto.h"
26 #include "cached_dir.h"
27 #include "smb2status.h"
28 
29 static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
30 {
31 	struct reparse_data_buffer *buf;
32 	struct smb2_ioctl_rsp *io = iov->iov_base;
33 	u32 off, count, len;
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(-EIO);
39 
40 	buf = (struct reparse_data_buffer *)((u8 *)io + off);
41 	len = sizeof(*buf);
42 	if (count < len || count < le16_to_cpu(buf->ReparseDataLength) + len)
43 		return ERR_PTR(-EIO);
44 	return buf;
45 }
46 
47 static inline __u32 file_create_options(struct dentry *dentry)
48 {
49 	struct cifsInodeInfo *ci;
50 
51 	if (dentry) {
52 		ci = CIFS_I(d_inode(dentry));
53 		if (ci->cifsAttrs & ATTR_REPARSE)
54 			return OPEN_REPARSE_POINT;
55 	}
56 	return 0;
57 }
58 
59 /* Parse owner and group from SMB3.1.1 POSIX query info */
60 static int parse_posix_sids(struct cifs_open_info_data *data,
61 			    struct kvec *rsp_iov)
62 {
63 	struct smb2_query_info_rsp *qi = rsp_iov->iov_base;
64 	unsigned int out_len = le32_to_cpu(qi->OutputBufferLength);
65 	unsigned int qi_len = sizeof(data->posix_fi);
66 	int owner_len, group_len;
67 	u8 *sidsbuf, *sidsbuf_end;
68 
69 	if (out_len <= qi_len)
70 		return -EINVAL;
71 
72 	sidsbuf = (u8 *)qi + le16_to_cpu(qi->OutputBufferOffset) + qi_len;
73 	sidsbuf_end = sidsbuf + out_len - qi_len;
74 
75 	owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
76 	if (owner_len == -1)
77 		return -EINVAL;
78 
79 	memcpy(&data->posix_owner, sidsbuf, owner_len);
80 	group_len = posix_info_sid_size(sidsbuf + owner_len, sidsbuf_end);
81 	if (group_len == -1)
82 		return -EINVAL;
83 
84 	memcpy(&data->posix_group, sidsbuf + owner_len, group_len);
85 	return 0;
86 }
87 
88 /*
89  * note: If cfile is passed, the reference to it is dropped here.
90  * So make sure that you do not reuse cfile after return from this func.
91  *
92  * If passing @out_iov and @out_buftype, ensure to make them both large enough
93  * (>= 3) to hold all compounded responses.  Caller is also responsible for
94  * freeing them up with free_rsp_buf().
95  */
96 static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
97 			    struct cifs_sb_info *cifs_sb, const char *full_path,
98 			    __u32 desired_access, __u32 create_disposition,
99 			    __u32 create_options, umode_t mode, struct kvec *in_iov,
100 			    int *cmds, int num_cmds, struct cifsFileInfo *cfile,
101 			    struct kvec *out_iov, int *out_buftype)
102 {
103 
104 	struct reparse_data_buffer *rbuf;
105 	struct smb2_compound_vars *vars = NULL;
106 	struct kvec *rsp_iov, *iov;
107 	struct smb_rqst *rqst;
108 	int rc;
109 	__le16 *utf16_path = NULL;
110 	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
111 	struct cifs_fid fid;
112 	struct cifs_ses *ses = tcon->ses;
113 	struct TCP_Server_Info *server;
114 	int num_rqst = 0, i;
115 	int resp_buftype[MAX_COMPOUND];
116 	struct smb2_query_info_rsp *qi_rsp = NULL;
117 	struct cifs_open_info_data *idata;
118 	int flags = 0;
119 	__u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0};
120 	unsigned int size[2];
121 	void *data[2];
122 	int len;
123 	int retries = 0, cur_sleep = 1;
124 
125 replay_again:
126 	/* reinitialize for possible replay */
127 	flags = 0;
128 	oplock = SMB2_OPLOCK_LEVEL_NONE;
129 	num_rqst = 0;
130 	server = cifs_pick_channel(ses);
131 
132 	vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
133 	if (vars == NULL)
134 		return -ENOMEM;
135 	rqst = &vars->rqst[0];
136 	rsp_iov = &vars->rsp_iov[0];
137 
138 	if (smb3_encryption_required(tcon))
139 		flags |= CIFS_TRANSFORM_REQ;
140 
141 	for (i = 0; i < ARRAY_SIZE(resp_buftype); i++)
142 		resp_buftype[i] = CIFS_NO_BUFFER;
143 
144 	/* We already have a handle so we can skip the open */
145 	if (cfile)
146 		goto after_open;
147 
148 	/* Open */
149 	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
150 	if (!utf16_path) {
151 		rc = -ENOMEM;
152 		goto finished;
153 	}
154 
155 	vars->oparms = (struct cifs_open_parms) {
156 		.tcon = tcon,
157 		.path = full_path,
158 		.desired_access = desired_access,
159 		.disposition = create_disposition,
160 		.create_options = cifs_create_options(cifs_sb, create_options),
161 		.fid = &fid,
162 		.mode = mode,
163 		.cifs_sb = cifs_sb,
164 	};
165 
166 	rqst[num_rqst].rq_iov = &vars->open_iov[0];
167 	rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE;
168 	rc = SMB2_open_init(tcon, server,
169 			    &rqst[num_rqst], &oplock, &vars->oparms,
170 			    utf16_path);
171 	kfree(utf16_path);
172 	if (rc)
173 		goto finished;
174 
175 	smb2_set_next_command(tcon, &rqst[num_rqst]);
176  after_open:
177 	num_rqst++;
178 	rc = 0;
179 
180 	for (i = 0; i < num_cmds; i++) {
181 		/* Operation */
182 		switch (cmds[i]) {
183 		case SMB2_OP_QUERY_INFO:
184 			rqst[num_rqst].rq_iov = &vars->qi_iov;
185 			rqst[num_rqst].rq_nvec = 1;
186 
187 			if (cfile) {
188 				rc = SMB2_query_info_init(tcon, server,
189 							  &rqst[num_rqst],
190 							  cfile->fid.persistent_fid,
191 							  cfile->fid.volatile_fid,
192 							  FILE_ALL_INFORMATION,
193 							  SMB2_O_INFO_FILE, 0,
194 							  sizeof(struct smb2_file_all_info) +
195 							  PATH_MAX * 2, 0, NULL);
196 			} else {
197 				rc = SMB2_query_info_init(tcon, server,
198 							  &rqst[num_rqst],
199 							  COMPOUND_FID,
200 							  COMPOUND_FID,
201 							  FILE_ALL_INFORMATION,
202 							  SMB2_O_INFO_FILE, 0,
203 							  sizeof(struct smb2_file_all_info) +
204 							  PATH_MAX * 2, 0, NULL);
205 				if (!rc) {
206 					smb2_set_next_command(tcon, &rqst[num_rqst]);
207 					smb2_set_related(&rqst[num_rqst]);
208 				}
209 			}
210 
211 			if (rc)
212 				goto finished;
213 			num_rqst++;
214 			trace_smb3_query_info_compound_enter(xid, ses->Suid,
215 							     tcon->tid, full_path);
216 			break;
217 		case SMB2_OP_POSIX_QUERY_INFO:
218 			rqst[num_rqst].rq_iov = &vars->qi_iov;
219 			rqst[num_rqst].rq_nvec = 1;
220 
221 			if (cfile) {
222 				/* TBD: fix following to allow for longer SIDs */
223 				rc = SMB2_query_info_init(tcon, server,
224 							  &rqst[num_rqst],
225 							  cfile->fid.persistent_fid,
226 							  cfile->fid.volatile_fid,
227 							  SMB_FIND_FILE_POSIX_INFO,
228 							  SMB2_O_INFO_FILE, 0,
229 							  sizeof(struct smb311_posix_qinfo *) +
230 							  (PATH_MAX * 2) +
231 							  (sizeof(struct cifs_sid) * 2), 0, NULL);
232 			} else {
233 				rc = SMB2_query_info_init(tcon, server,
234 							  &rqst[num_rqst],
235 							  COMPOUND_FID,
236 							  COMPOUND_FID,
237 							  SMB_FIND_FILE_POSIX_INFO,
238 							  SMB2_O_INFO_FILE, 0,
239 							  sizeof(struct smb311_posix_qinfo *) +
240 							  (PATH_MAX * 2) +
241 							  (sizeof(struct cifs_sid) * 2), 0, NULL);
242 				if (!rc) {
243 					smb2_set_next_command(tcon, &rqst[num_rqst]);
244 					smb2_set_related(&rqst[num_rqst]);
245 				}
246 			}
247 
248 			if (rc)
249 				goto finished;
250 			num_rqst++;
251 			trace_smb3_posix_query_info_compound_enter(xid, ses->Suid,
252 								   tcon->tid, full_path);
253 			break;
254 		case SMB2_OP_DELETE:
255 			trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
256 			break;
257 		case SMB2_OP_MKDIR:
258 			/*
259 			 * Directories are created through parameters in the
260 			 * SMB2_open() call.
261 			 */
262 			trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path);
263 			break;
264 		case SMB2_OP_RMDIR:
265 			rqst[num_rqst].rq_iov = &vars->si_iov[0];
266 			rqst[num_rqst].rq_nvec = 1;
267 
268 			size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
269 			data[0] = &delete_pending[0];
270 
271 			rc = SMB2_set_info_init(tcon, server,
272 						&rqst[num_rqst], COMPOUND_FID,
273 						COMPOUND_FID, current->tgid,
274 						FILE_DISPOSITION_INFORMATION,
275 						SMB2_O_INFO_FILE, 0, data, size);
276 			if (rc)
277 				goto finished;
278 			smb2_set_next_command(tcon, &rqst[num_rqst]);
279 			smb2_set_related(&rqst[num_rqst++]);
280 			trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
281 			break;
282 		case SMB2_OP_SET_EOF:
283 			rqst[num_rqst].rq_iov = &vars->si_iov[0];
284 			rqst[num_rqst].rq_nvec = 1;
285 
286 			size[0] = in_iov[i].iov_len;
287 			data[0] = in_iov[i].iov_base;
288 
289 			if (cfile) {
290 				rc = SMB2_set_info_init(tcon, server,
291 							&rqst[num_rqst],
292 							cfile->fid.persistent_fid,
293 							cfile->fid.volatile_fid,
294 							current->tgid,
295 							FILE_END_OF_FILE_INFORMATION,
296 							SMB2_O_INFO_FILE, 0,
297 							data, size);
298 			} else {
299 				rc = SMB2_set_info_init(tcon, server,
300 							&rqst[num_rqst],
301 							COMPOUND_FID,
302 							COMPOUND_FID,
303 							current->tgid,
304 							FILE_END_OF_FILE_INFORMATION,
305 							SMB2_O_INFO_FILE, 0,
306 							data, size);
307 				if (!rc) {
308 					smb2_set_next_command(tcon, &rqst[num_rqst]);
309 					smb2_set_related(&rqst[num_rqst]);
310 				}
311 			}
312 			if (rc)
313 				goto finished;
314 			num_rqst++;
315 			trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
316 			break;
317 		case SMB2_OP_SET_INFO:
318 			rqst[num_rqst].rq_iov = &vars->si_iov[0];
319 			rqst[num_rqst].rq_nvec = 1;
320 
321 			size[0] = in_iov[i].iov_len;
322 			data[0] = in_iov[i].iov_base;
323 
324 			if (cfile) {
325 				rc = SMB2_set_info_init(tcon, server,
326 							&rqst[num_rqst],
327 							cfile->fid.persistent_fid,
328 							cfile->fid.volatile_fid, current->tgid,
329 							FILE_BASIC_INFORMATION,
330 							SMB2_O_INFO_FILE, 0, data, size);
331 			} else {
332 				rc = SMB2_set_info_init(tcon, server,
333 							&rqst[num_rqst],
334 							COMPOUND_FID,
335 							COMPOUND_FID, current->tgid,
336 							FILE_BASIC_INFORMATION,
337 							SMB2_O_INFO_FILE, 0, data, size);
338 				if (!rc) {
339 					smb2_set_next_command(tcon, &rqst[num_rqst]);
340 					smb2_set_related(&rqst[num_rqst]);
341 				}
342 			}
343 
344 			if (rc)
345 				goto finished;
346 			num_rqst++;
347 			trace_smb3_set_info_compound_enter(xid, ses->Suid,
348 							   tcon->tid, full_path);
349 			break;
350 		case SMB2_OP_RENAME:
351 			rqst[num_rqst].rq_iov = &vars->si_iov[0];
352 			rqst[num_rqst].rq_nvec = 2;
353 
354 			len = in_iov[i].iov_len;
355 
356 			vars->rename_info.ReplaceIfExists = 1;
357 			vars->rename_info.RootDirectory = 0;
358 			vars->rename_info.FileNameLength = cpu_to_le32(len);
359 
360 			size[0] = sizeof(struct smb2_file_rename_info);
361 			data[0] = &vars->rename_info;
362 
363 			size[1] = len + 2 /* null */;
364 			data[1] = in_iov[i].iov_base;
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, FILE_RENAME_INFORMATION,
372 							SMB2_O_INFO_FILE, 0, data, size);
373 			} else {
374 				rc = SMB2_set_info_init(tcon, server,
375 							&rqst[num_rqst],
376 							COMPOUND_FID, COMPOUND_FID,
377 							current->tgid, FILE_RENAME_INFORMATION,
378 							SMB2_O_INFO_FILE, 0, data, size);
379 				if (!rc) {
380 					smb2_set_next_command(tcon, &rqst[num_rqst]);
381 					smb2_set_related(&rqst[num_rqst]);
382 				}
383 			}
384 			if (rc)
385 				goto finished;
386 			num_rqst++;
387 			trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
388 			break;
389 		case SMB2_OP_HARDLINK:
390 			rqst[num_rqst].rq_iov = &vars->si_iov[0];
391 			rqst[num_rqst].rq_nvec = 2;
392 
393 			len = in_iov[i].iov_len;
394 
395 			vars->link_info.ReplaceIfExists = 0;
396 			vars->link_info.RootDirectory = 0;
397 			vars->link_info.FileNameLength = cpu_to_le32(len);
398 
399 			size[0] = sizeof(struct smb2_file_link_info);
400 			data[0] = &vars->link_info;
401 
402 			size[1] = len + 2 /* null */;
403 			data[1] = in_iov[i].iov_base;
404 
405 			rc = SMB2_set_info_init(tcon, server,
406 						&rqst[num_rqst], COMPOUND_FID,
407 						COMPOUND_FID, current->tgid,
408 						FILE_LINK_INFORMATION,
409 						SMB2_O_INFO_FILE, 0, data, size);
410 			if (rc)
411 				goto finished;
412 			smb2_set_next_command(tcon, &rqst[num_rqst]);
413 			smb2_set_related(&rqst[num_rqst++]);
414 			trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
415 			break;
416 		case SMB2_OP_SET_REPARSE:
417 			rqst[num_rqst].rq_iov = vars->io_iov;
418 			rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
419 
420 			rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
421 					     COMPOUND_FID, COMPOUND_FID,
422 					     FSCTL_SET_REPARSE_POINT,
423 					     in_iov[i].iov_base,
424 					     in_iov[i].iov_len, 0);
425 			if (rc)
426 				goto finished;
427 			smb2_set_next_command(tcon, &rqst[num_rqst]);
428 			smb2_set_related(&rqst[num_rqst++]);
429 			trace_smb3_set_reparse_compound_enter(xid, ses->Suid,
430 							      tcon->tid, full_path);
431 			break;
432 		case SMB2_OP_GET_REPARSE:
433 			rqst[num_rqst].rq_iov = vars->io_iov;
434 			rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);
435 
436 			rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],
437 					     COMPOUND_FID, COMPOUND_FID,
438 					     FSCTL_GET_REPARSE_POINT,
439 					     NULL, 0, CIFSMaxBufSize);
440 			if (rc)
441 				goto finished;
442 			smb2_set_next_command(tcon, &rqst[num_rqst]);
443 			smb2_set_related(&rqst[num_rqst++]);
444 			trace_smb3_get_reparse_compound_enter(xid, ses->Suid,
445 							      tcon->tid, full_path);
446 			break;
447 		default:
448 			cifs_dbg(VFS, "Invalid command\n");
449 			rc = -EINVAL;
450 		}
451 	}
452 	if (rc)
453 		goto finished;
454 
455 	/* We already have a handle so we can skip the close */
456 	if (cfile)
457 		goto after_close;
458 	/* Close */
459 	flags |= CIFS_CP_CREATE_CLOSE_OP;
460 	rqst[num_rqst].rq_iov = &vars->close_iov;
461 	rqst[num_rqst].rq_nvec = 1;
462 	rc = SMB2_close_init(tcon, server,
463 			     &rqst[num_rqst], COMPOUND_FID,
464 			     COMPOUND_FID, false);
465 	smb2_set_related(&rqst[num_rqst]);
466 	if (rc)
467 		goto finished;
468  after_close:
469 	num_rqst++;
470 
471 	if (cfile) {
472 		if (retries)
473 			for (i = 1; i < num_rqst - 2; i++)
474 				smb2_set_replay(server, &rqst[i]);
475 
476 		rc = compound_send_recv(xid, ses, server,
477 					flags, num_rqst - 2,
478 					&rqst[1], &resp_buftype[1],
479 					&rsp_iov[1]);
480 	} else {
481 		if (retries)
482 			for (i = 0; i < num_rqst; i++)
483 				smb2_set_replay(server, &rqst[i]);
484 
485 		rc = compound_send_recv(xid, ses, server,
486 					flags, num_rqst,
487 					rqst, resp_buftype,
488 					rsp_iov);
489 	}
490 
491 finished:
492 	num_rqst = 0;
493 	SMB2_open_free(&rqst[num_rqst++]);
494 	if (rc == -EREMCHG) {
495 		pr_warn_once("server share %s deleted\n", tcon->tree_name);
496 		tcon->need_reconnect = true;
497 	}
498 
499 	for (i = 0; i < num_cmds; i++) {
500 		switch (cmds[i]) {
501 		case SMB2_OP_QUERY_INFO:
502 			idata = in_iov[i].iov_base;
503 			if (rc == 0 && cfile && cfile->symlink_target) {
504 				idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
505 				if (!idata->symlink_target)
506 					rc = -ENOMEM;
507 			}
508 			if (rc == 0) {
509 				qi_rsp = (struct smb2_query_info_rsp *)
510 					rsp_iov[i + 1].iov_base;
511 				rc = smb2_validate_and_copy_iov(
512 					le16_to_cpu(qi_rsp->OutputBufferOffset),
513 					le32_to_cpu(qi_rsp->OutputBufferLength),
514 					&rsp_iov[i + 1], sizeof(idata->fi), (char *)&idata->fi);
515 			}
516 			SMB2_query_info_free(&rqst[num_rqst++]);
517 			if (rc)
518 				trace_smb3_query_info_compound_err(xid,  ses->Suid,
519 								   tcon->tid, rc);
520 			else
521 				trace_smb3_query_info_compound_done(xid, ses->Suid,
522 								    tcon->tid);
523 			break;
524 		case SMB2_OP_POSIX_QUERY_INFO:
525 			idata = in_iov[i].iov_base;
526 			if (rc == 0 && cfile && cfile->symlink_target) {
527 				idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
528 				if (!idata->symlink_target)
529 					rc = -ENOMEM;
530 			}
531 			if (rc == 0) {
532 				qi_rsp = (struct smb2_query_info_rsp *)
533 					rsp_iov[i + 1].iov_base;
534 				rc = smb2_validate_and_copy_iov(
535 					le16_to_cpu(qi_rsp->OutputBufferOffset),
536 					le32_to_cpu(qi_rsp->OutputBufferLength),
537 					&rsp_iov[i + 1], sizeof(idata->posix_fi) /* add SIDs */,
538 					(char *)&idata->posix_fi);
539 			}
540 			if (rc == 0)
541 				rc = parse_posix_sids(idata, &rsp_iov[i + 1]);
542 
543 			SMB2_query_info_free(&rqst[num_rqst++]);
544 			if (rc)
545 				trace_smb3_posix_query_info_compound_err(xid,  ses->Suid,
546 									 tcon->tid, rc);
547 			else
548 				trace_smb3_posix_query_info_compound_done(xid, ses->Suid,
549 									  tcon->tid);
550 			break;
551 		case SMB2_OP_DELETE:
552 			if (rc)
553 				trace_smb3_delete_err(xid,  ses->Suid, tcon->tid, rc);
554 			else
555 				trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
556 			break;
557 		case SMB2_OP_MKDIR:
558 			if (rc)
559 				trace_smb3_mkdir_err(xid,  ses->Suid, tcon->tid, rc);
560 			else
561 				trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid);
562 			break;
563 		case SMB2_OP_HARDLINK:
564 			if (rc)
565 				trace_smb3_hardlink_err(xid,  ses->Suid, tcon->tid, rc);
566 			else
567 				trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid);
568 			SMB2_set_info_free(&rqst[num_rqst++]);
569 			break;
570 		case SMB2_OP_RENAME:
571 			if (rc)
572 				trace_smb3_rename_err(xid,  ses->Suid, tcon->tid, rc);
573 			else
574 				trace_smb3_rename_done(xid, ses->Suid, tcon->tid);
575 			SMB2_set_info_free(&rqst[num_rqst++]);
576 			break;
577 		case SMB2_OP_RMDIR:
578 			if (rc)
579 				trace_smb3_rmdir_err(xid,  ses->Suid, tcon->tid, rc);
580 			else
581 				trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid);
582 			SMB2_set_info_free(&rqst[num_rqst++]);
583 			break;
584 		case SMB2_OP_SET_EOF:
585 			if (rc)
586 				trace_smb3_set_eof_err(xid,  ses->Suid, tcon->tid, rc);
587 			else
588 				trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
589 			SMB2_set_info_free(&rqst[num_rqst++]);
590 			break;
591 		case SMB2_OP_SET_INFO:
592 			if (rc)
593 				trace_smb3_set_info_compound_err(xid,  ses->Suid,
594 								 tcon->tid, rc);
595 			else
596 				trace_smb3_set_info_compound_done(xid, ses->Suid,
597 								  tcon->tid);
598 			SMB2_set_info_free(&rqst[num_rqst++]);
599 			break;
600 		case SMB2_OP_SET_REPARSE:
601 			if (rc) {
602 				trace_smb3_set_reparse_compound_err(xid,  ses->Suid,
603 								    tcon->tid, rc);
604 			} else {
605 				trace_smb3_set_reparse_compound_done(xid, ses->Suid,
606 								     tcon->tid);
607 			}
608 			SMB2_ioctl_free(&rqst[num_rqst++]);
609 			break;
610 		case SMB2_OP_GET_REPARSE:
611 			if (!rc) {
612 				iov = &rsp_iov[i + 1];
613 				idata = in_iov[i].iov_base;
614 				idata->reparse.io.iov = *iov;
615 				idata->reparse.io.buftype = resp_buftype[i + 1];
616 				rbuf = reparse_buf_ptr(iov);
617 				if (IS_ERR(rbuf)) {
618 					rc = PTR_ERR(rbuf);
619 					trace_smb3_set_reparse_compound_err(xid,  ses->Suid,
620 									    tcon->tid, rc);
621 				} else {
622 					idata->reparse.tag = le32_to_cpu(rbuf->ReparseTag);
623 					trace_smb3_set_reparse_compound_done(xid, ses->Suid,
624 									     tcon->tid);
625 				}
626 				memset(iov, 0, sizeof(*iov));
627 				resp_buftype[i + 1] = CIFS_NO_BUFFER;
628 			} else {
629 				trace_smb3_set_reparse_compound_err(xid,  ses->Suid,
630 								    tcon->tid, rc);
631 			}
632 			SMB2_ioctl_free(&rqst[num_rqst++]);
633 			break;
634 		}
635 	}
636 	SMB2_close_free(&rqst[num_rqst]);
637 
638 	num_cmds += 2;
639 	if (out_iov && out_buftype) {
640 		memcpy(out_iov, rsp_iov, num_cmds * sizeof(*out_iov));
641 		memcpy(out_buftype, resp_buftype,
642 		       num_cmds * sizeof(*out_buftype));
643 	} else {
644 		for (i = 0; i < num_cmds; i++)
645 			free_rsp_buf(resp_buftype[i], rsp_iov[i].iov_base);
646 	}
647 	num_cmds -= 2; /* correct num_cmds as there could be a retry */
648 	kfree(vars);
649 
650 	if (is_replayable_error(rc) &&
651 	    smb2_should_replay(tcon, &retries, &cur_sleep))
652 		goto replay_again;
653 
654 	if (cfile)
655 		cifsFileInfo_put(cfile);
656 
657 	return rc;
658 }
659 
660 static int parse_create_response(struct cifs_open_info_data *data,
661 				 struct cifs_sb_info *cifs_sb,
662 				 const struct kvec *iov)
663 {
664 	struct smb2_create_rsp *rsp = iov->iov_base;
665 	bool reparse_point = false;
666 	u32 tag = 0;
667 	int rc = 0;
668 
669 	switch (rsp->hdr.Status) {
670 	case STATUS_IO_REPARSE_TAG_NOT_HANDLED:
671 		reparse_point = true;
672 		break;
673 	case STATUS_STOPPED_ON_SYMLINK:
674 		rc = smb2_parse_symlink_response(cifs_sb, iov,
675 						 &data->symlink_target);
676 		if (rc)
677 			return rc;
678 		tag = IO_REPARSE_TAG_SYMLINK;
679 		reparse_point = true;
680 		break;
681 	case STATUS_SUCCESS:
682 		reparse_point = !!(rsp->Flags & SMB2_CREATE_FLAG_REPARSEPOINT);
683 		break;
684 	}
685 	data->reparse_point = reparse_point;
686 	data->reparse.tag = tag;
687 	return rc;
688 }
689 
690 int smb2_query_path_info(const unsigned int xid,
691 			 struct cifs_tcon *tcon,
692 			 struct cifs_sb_info *cifs_sb,
693 			 const char *full_path,
694 			 struct cifs_open_info_data *data)
695 {
696 	__u32 create_options = 0;
697 	struct cifsFileInfo *cfile;
698 	struct cached_fid *cfid = NULL;
699 	struct smb2_hdr *hdr;
700 	struct kvec in_iov[2], out_iov[3] = {};
701 	int out_buftype[3] = {};
702 	int cmds[2];
703 	bool islink;
704 	int i, num_cmds;
705 	int rc, rc2;
706 
707 	data->adjust_tz = false;
708 	data->reparse_point = false;
709 
710 	/*
711 	 * BB TODO: Add support for using cached root handle in SMB3.1.1 POSIX.
712 	 * Create SMB2_query_posix_info worker function to do non-compounded
713 	 * query when we already have an open file handle for this. For now this
714 	 * is fast enough (always using the compounded version).
715 	 */
716 	if (!tcon->posix_extensions) {
717 		if (*full_path) {
718 			rc = -ENOENT;
719 		} else {
720 			rc = open_cached_dir(xid, tcon, full_path,
721 					     cifs_sb, false, &cfid);
722 		}
723 		/* If it is a root and its handle is cached then use it */
724 		if (!rc) {
725 			if (cfid->file_all_info_is_valid) {
726 				memcpy(&data->fi, &cfid->file_all_info,
727 				       sizeof(data->fi));
728 			} else {
729 				rc = SMB2_query_info(xid, tcon,
730 						     cfid->fid.persistent_fid,
731 						     cfid->fid.volatile_fid,
732 						     &data->fi);
733 			}
734 			close_cached_dir(cfid);
735 			return rc;
736 		}
737 		cmds[0] = SMB2_OP_QUERY_INFO;
738 	} else {
739 		cmds[0] = SMB2_OP_POSIX_QUERY_INFO;
740 	}
741 
742 	in_iov[0].iov_base = data;
743 	in_iov[0].iov_len = sizeof(*data);
744 	in_iov[1] = in_iov[0];
745 
746 	cifs_get_readable_path(tcon, full_path, &cfile);
747 	rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
748 			      FILE_READ_ATTRIBUTES, FILE_OPEN,
749 			      create_options, ACL_NO_MODE, in_iov,
750 			      cmds, 1, cfile, out_iov, out_buftype);
751 	hdr = out_iov[0].iov_base;
752 	/*
753 	 * If first iov is unset, then SMB session was dropped or we've got a
754 	 * cached open file (@cfile).
755 	 */
756 	if (!hdr || out_buftype[0] == CIFS_NO_BUFFER)
757 		goto out;
758 
759 	switch (rc) {
760 	case 0:
761 	case -EOPNOTSUPP:
762 		/*
763 		 * BB TODO: When support for special files added to Samba
764 		 * re-verify this path.
765 		 */
766 		rc = parse_create_response(data, cifs_sb, &out_iov[0]);
767 		if (rc || !data->reparse_point)
768 			goto out;
769 
770 		if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK) {
771 			/* symlink already parsed in create response */
772 			num_cmds = 1;
773 		} else {
774 			cmds[1] = SMB2_OP_GET_REPARSE;
775 			num_cmds = 2;
776 		}
777 		create_options |= OPEN_REPARSE_POINT;
778 		cifs_get_readable_path(tcon, full_path, &cfile);
779 		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
780 				      FILE_READ_ATTRIBUTES, FILE_OPEN,
781 				      create_options, ACL_NO_MODE, in_iov,
782 				      cmds, num_cmds, cfile, NULL, NULL);
783 		break;
784 	case -EREMOTE:
785 		break;
786 	default:
787 		if (hdr->Status != STATUS_OBJECT_NAME_INVALID)
788 			break;
789 		rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
790 						     full_path, &islink);
791 		if (rc2) {
792 			rc = rc2;
793 			goto out;
794 		}
795 		if (islink)
796 			rc = -EREMOTE;
797 	}
798 
799 out:
800 	for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
801 		free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
802 	return rc;
803 }
804 
805 int
806 smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
807 	   struct cifs_tcon *tcon, const char *name,
808 	   struct cifs_sb_info *cifs_sb)
809 {
810 	return smb2_compound_op(xid, tcon, cifs_sb, name,
811 				FILE_WRITE_ATTRIBUTES, FILE_CREATE,
812 				CREATE_NOT_FILE, mode,
813 				NULL, &(int){SMB2_OP_MKDIR}, 1,
814 				NULL, NULL, NULL);
815 }
816 
817 void
818 smb2_mkdir_setinfo(struct inode *inode, const char *name,
819 		   struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
820 		   const unsigned int xid)
821 {
822 	FILE_BASIC_INFO data = {};
823 	struct cifsInodeInfo *cifs_i;
824 	struct cifsFileInfo *cfile;
825 	struct kvec in_iov;
826 	u32 dosattrs;
827 	int tmprc;
828 
829 	in_iov.iov_base = &data;
830 	in_iov.iov_len = sizeof(data);
831 	cifs_i = CIFS_I(inode);
832 	dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
833 	data.Attributes = cpu_to_le32(dosattrs);
834 	cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
835 	tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
836 				 FILE_WRITE_ATTRIBUTES, FILE_CREATE,
837 				 CREATE_NOT_FILE, ACL_NO_MODE, &in_iov,
838 				 &(int){SMB2_OP_SET_INFO}, 1,
839 				 cfile, NULL, NULL);
840 	if (tmprc == 0)
841 		cifs_i->cifsAttrs = dosattrs;
842 }
843 
844 int
845 smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
846 	   struct cifs_sb_info *cifs_sb)
847 {
848 	drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
849 	return smb2_compound_op(xid, tcon, cifs_sb, name,
850 				DELETE, FILE_OPEN, CREATE_NOT_FILE,
851 				ACL_NO_MODE, NULL,
852 				&(int){SMB2_OP_RMDIR}, 1,
853 				NULL, NULL, NULL);
854 }
855 
856 int
857 smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
858 	    struct cifs_sb_info *cifs_sb)
859 {
860 	return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
861 				CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
862 				ACL_NO_MODE, NULL,
863 				&(int){SMB2_OP_DELETE}, 1,
864 				NULL, NULL, NULL);
865 }
866 
867 static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
868 			      const char *from_name, const char *to_name,
869 			      struct cifs_sb_info *cifs_sb,
870 			      __u32 create_options, __u32 access,
871 			      int command, struct cifsFileInfo *cfile)
872 {
873 	struct kvec in_iov;
874 	__le16 *smb2_to_name = NULL;
875 	int rc;
876 
877 	smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
878 	if (smb2_to_name == NULL) {
879 		rc = -ENOMEM;
880 		goto smb2_rename_path;
881 	}
882 	in_iov.iov_base = smb2_to_name;
883 	in_iov.iov_len = 2 * UniStrnlen((wchar_t *)smb2_to_name, PATH_MAX);
884 	rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
885 			      FILE_OPEN, create_options, ACL_NO_MODE,
886 			      &in_iov, &command, 1, cfile, NULL, NULL);
887 smb2_rename_path:
888 	kfree(smb2_to_name);
889 	return rc;
890 }
891 
892 int smb2_rename_path(const unsigned int xid,
893 		     struct cifs_tcon *tcon,
894 		     struct dentry *source_dentry,
895 		     const char *from_name, const char *to_name,
896 		     struct cifs_sb_info *cifs_sb)
897 {
898 	struct cifsFileInfo *cfile;
899 	__u32 co = file_create_options(source_dentry);
900 
901 	drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
902 	cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
903 
904 	return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
905 				  co, DELETE, SMB2_OP_RENAME, cfile);
906 }
907 
908 int smb2_create_hardlink(const unsigned int xid,
909 			 struct cifs_tcon *tcon,
910 			 struct dentry *source_dentry,
911 			 const char *from_name, const char *to_name,
912 			 struct cifs_sb_info *cifs_sb)
913 {
914 	__u32 co = file_create_options(source_dentry);
915 
916 	return smb2_set_path_attr(xid, tcon, from_name, to_name,
917 				  cifs_sb, co, FILE_READ_ATTRIBUTES,
918 				  SMB2_OP_HARDLINK, NULL);
919 }
920 
921 int
922 smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
923 		   const char *full_path, __u64 size,
924 		   struct cifs_sb_info *cifs_sb, bool set_alloc)
925 {
926 	struct cifsFileInfo *cfile;
927 	struct kvec in_iov;
928 	__le64 eof = cpu_to_le64(size);
929 
930 	in_iov.iov_base = &eof;
931 	in_iov.iov_len = sizeof(eof);
932 	cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
933 	return smb2_compound_op(xid, tcon, cifs_sb, full_path,
934 				FILE_WRITE_DATA, FILE_OPEN,
935 				0, ACL_NO_MODE, &in_iov,
936 				&(int){SMB2_OP_SET_EOF}, 1,
937 				cfile, NULL, NULL);
938 }
939 
940 int
941 smb2_set_file_info(struct inode *inode, const char *full_path,
942 		   FILE_BASIC_INFO *buf, const unsigned int xid)
943 {
944 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
945 	struct tcon_link *tlink;
946 	struct cifs_tcon *tcon;
947 	struct cifsFileInfo *cfile;
948 	struct kvec in_iov = { .iov_base = buf, .iov_len = sizeof(*buf), };
949 	int rc;
950 
951 	if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
952 	    (buf->LastWriteTime == 0) && (buf->ChangeTime == 0) &&
953 	    (buf->Attributes == 0))
954 		return 0; /* would be a no op, no sense sending this */
955 
956 	tlink = cifs_sb_tlink(cifs_sb);
957 	if (IS_ERR(tlink))
958 		return PTR_ERR(tlink);
959 	tcon = tlink_tcon(tlink);
960 
961 	cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
962 	rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
963 			      FILE_WRITE_ATTRIBUTES, FILE_OPEN,
964 			      0, ACL_NO_MODE, &in_iov,
965 			      &(int){SMB2_OP_SET_INFO}, 1,
966 			      cfile, NULL, NULL);
967 	cifs_put_tlink(tlink);
968 	return rc;
969 }
970 
971 struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
972 				     struct super_block *sb,
973 				     const unsigned int xid,
974 				     struct cifs_tcon *tcon,
975 				     const char *full_path,
976 				     struct kvec *iov)
977 {
978 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
979 	struct cifsFileInfo *cfile;
980 	struct inode *new = NULL;
981 	struct kvec in_iov[2];
982 	int cmds[2];
983 	int da, co, cd;
984 	int rc;
985 
986 	da = SYNCHRONIZE | DELETE |
987 		FILE_READ_ATTRIBUTES |
988 		FILE_WRITE_ATTRIBUTES;
989 	co = CREATE_NOT_DIR | OPEN_REPARSE_POINT;
990 	cd = FILE_CREATE;
991 	cmds[0] = SMB2_OP_SET_REPARSE;
992 	in_iov[0] = *iov;
993 	in_iov[1].iov_base = data;
994 	in_iov[1].iov_len = sizeof(*data);
995 
996 	if (tcon->posix_extensions) {
997 		cmds[1] = SMB2_OP_POSIX_QUERY_INFO;
998 		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
999 		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
1000 				      da, cd, co, ACL_NO_MODE, in_iov,
1001 				      cmds, 2, cfile, NULL, NULL);
1002 		if (!rc) {
1003 			rc = smb311_posix_get_inode_info(&new, full_path,
1004 							 data, sb, xid);
1005 		}
1006 	} else {
1007 		cmds[1] = SMB2_OP_QUERY_INFO;
1008 		cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
1009 		rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
1010 				      da, cd, co, ACL_NO_MODE, in_iov,
1011 				      cmds, 2, cfile, NULL, NULL);
1012 		if (!rc) {
1013 			rc = cifs_get_inode_info(&new, full_path,
1014 						 data, sb, xid, NULL);
1015 		}
1016 	}
1017 	return rc ? ERR_PTR(rc) : new;
1018 }
1019 
1020 int smb2_query_reparse_point(const unsigned int xid,
1021 			     struct cifs_tcon *tcon,
1022 			     struct cifs_sb_info *cifs_sb,
1023 			     const char *full_path,
1024 			     u32 *tag, struct kvec *rsp,
1025 			     int *rsp_buftype)
1026 {
1027 	struct cifs_open_info_data data = {};
1028 	struct cifsFileInfo *cfile;
1029 	struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), };
1030 	int rc;
1031 
1032 	cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
1033 
1034 	cifs_get_readable_path(tcon, full_path, &cfile);
1035 	rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
1036 			      FILE_READ_ATTRIBUTES, FILE_OPEN,
1037 			      OPEN_REPARSE_POINT, ACL_NO_MODE, &in_iov,
1038 			      &(int){SMB2_OP_GET_REPARSE}, 1,
1039 			      cfile, NULL, NULL);
1040 	if (rc)
1041 		goto out;
1042 
1043 	*tag = data.reparse.tag;
1044 	*rsp = data.reparse.io.iov;
1045 	*rsp_buftype = data.reparse.io.buftype;
1046 	memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov));
1047 	data.reparse.io.buftype = CIFS_NO_BUFFER;
1048 out:
1049 	cifs_free_open_info(&data);
1050 	return rc;
1051 }
1052