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