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 tmp_rc = rc;
604 }
605 }
606
607 for (i = 0; i < num_cmds; i++) {
608 char *buf = rsp_iov[i + 1].iov_base;
609
610 if (buf && resp_buftype[i + 1] != CIFS_NO_BUFFER)
611 rc = server->ops->map_error(buf, false);
612 else
613 rc = tmp_rc;
614 switch (cmds[i]) {
615 case SMB2_OP_QUERY_INFO:
616 idata = in_iov[i].iov_base;
617 if (rc == 0 && cfile && cfile->symlink_target) {
618 idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
619 if (!idata->symlink_target)
620 rc = -ENOMEM;
621 }
622 if (rc == 0) {
623 qi_rsp = (struct smb2_query_info_rsp *)
624 rsp_iov[i + 1].iov_base;
625 rc = smb2_validate_and_copy_iov(
626 le16_to_cpu(qi_rsp->OutputBufferOffset),
627 le32_to_cpu(qi_rsp->OutputBufferLength),
628 &rsp_iov[i + 1], sizeof(idata->fi), (char *)&idata->fi);
629 if (!rc)
630 idata->contains_posix_file_info = false;
631 }
632 SMB2_query_info_free(&rqst[num_rqst++]);
633 if (rc)
634 trace_smb3_query_info_compound_err(xid, tcon->tid,
635 ses->Suid, rc);
636 else
637 trace_smb3_query_info_compound_done(xid, tcon->tid,
638 ses->Suid);
639 break;
640 case SMB2_OP_POSIX_QUERY_INFO:
641 idata = in_iov[i].iov_base;
642 if (rc == 0 && cfile && cfile->symlink_target) {
643 idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
644 if (!idata->symlink_target)
645 rc = -ENOMEM;
646 }
647 if (rc == 0) {
648 qi_rsp = (struct smb2_query_info_rsp *)
649 rsp_iov[i + 1].iov_base;
650 rc = smb2_validate_and_copy_iov(
651 le16_to_cpu(qi_rsp->OutputBufferOffset),
652 le32_to_cpu(qi_rsp->OutputBufferLength),
653 &rsp_iov[i + 1], sizeof(idata->posix_fi) /* add SIDs */,
654 (char *)&idata->posix_fi);
655 if (!rc)
656 idata->contains_posix_file_info = true;
657 }
658 if (rc == 0)
659 rc = parse_posix_sids(idata, &rsp_iov[i + 1]);
660
661 SMB2_query_info_free(&rqst[num_rqst++]);
662 if (rc)
663 trace_smb3_posix_query_info_compound_err(xid, tcon->tid,
664 ses->Suid, rc);
665 else
666 trace_smb3_posix_query_info_compound_done(xid, tcon->tid,
667 ses->Suid);
668 break;
669 case SMB2_OP_MKDIR:
670 if (rc)
671 trace_smb3_mkdir_err(xid, tcon->tid, ses->Suid, rc);
672 else
673 trace_smb3_mkdir_done(xid, tcon->tid, ses->Suid);
674 break;
675 case SMB2_OP_HARDLINK:
676 if (rc)
677 trace_smb3_hardlink_err(xid, tcon->tid, ses->Suid, rc);
678 else
679 trace_smb3_hardlink_done(xid, tcon->tid, ses->Suid);
680 SMB2_set_info_free(&rqst[num_rqst++]);
681 break;
682 case SMB2_OP_RENAME:
683 if (rc)
684 trace_smb3_rename_err(xid, tcon->tid, ses->Suid, rc);
685 else
686 trace_smb3_rename_done(xid, tcon->tid, ses->Suid);
687 SMB2_set_info_free(&rqst[num_rqst++]);
688 break;
689 case SMB2_OP_UNLINK:
690 if (!rc)
691 trace_smb3_unlink_done(xid, tcon->tid, ses->Suid);
692 else
693 trace_smb3_unlink_err(xid, tcon->tid, ses->Suid, rc);
694 SMB2_set_info_free(&rqst[num_rqst++]);
695 break;
696 case SMB2_OP_SET_EOF:
697 if (rc)
698 trace_smb3_set_eof_err(xid, tcon->tid, ses->Suid, rc);
699 else
700 trace_smb3_set_eof_done(xid, tcon->tid, ses->Suid);
701 SMB2_set_info_free(&rqst[num_rqst++]);
702 break;
703 case SMB2_OP_SET_INFO:
704 if (rc)
705 trace_smb3_set_info_compound_err(xid, tcon->tid,
706 ses->Suid, rc);
707 else
708 trace_smb3_set_info_compound_done(xid, tcon->tid,
709 ses->Suid);
710 SMB2_set_info_free(&rqst[num_rqst++]);
711 break;
712 case SMB2_OP_SET_REPARSE:
713 if (rc) {
714 trace_smb3_set_reparse_compound_err(xid, tcon->tid,
715 ses->Suid, rc);
716 } else {
717 trace_smb3_set_reparse_compound_done(xid, tcon->tid,
718 ses->Suid);
719 }
720 SMB2_ioctl_free(&rqst[num_rqst++]);
721 break;
722 case SMB2_OP_GET_REPARSE:
723 if (!rc) {
724 iov = &rsp_iov[i + 1];
725 idata = in_iov[i].iov_base;
726 idata->reparse.io.iov = *iov;
727 idata->reparse.io.buftype = resp_buftype[i + 1];
728 rbuf = reparse_buf_ptr(iov);
729 if (IS_ERR(rbuf)) {
730 rc = PTR_ERR(rbuf);
731 trace_smb3_get_reparse_compound_err(xid, tcon->tid,
732 ses->Suid, rc);
733 } else {
734 idata->reparse.tag = le32_to_cpu(rbuf->ReparseTag);
735 trace_smb3_get_reparse_compound_done(xid, tcon->tid,
736 ses->Suid);
737 }
738 memset(iov, 0, sizeof(*iov));
739 resp_buftype[i + 1] = CIFS_NO_BUFFER;
740 } else {
741 trace_smb3_get_reparse_compound_err(xid, tcon->tid,
742 ses->Suid, rc);
743 }
744 SMB2_ioctl_free(&rqst[num_rqst++]);
745 break;
746 case SMB2_OP_QUERY_WSL_EA:
747 if (!rc) {
748 idata = in_iov[i].iov_base;
749 qi_rsp = rsp_iov[i + 1].iov_base;
750 data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset);
751 size[0] = le32_to_cpu(qi_rsp->OutputBufferLength);
752 rc = check_wsl_eas(&rsp_iov[i + 1]);
753 if (!rc) {
754 memcpy(idata->wsl.eas, data[0], size[0]);
755 idata->wsl.eas_len = size[0];
756 }
757 }
758 if (!rc) {
759 trace_smb3_query_wsl_ea_compound_done(xid, tcon->tid,
760 ses->Suid);
761 } else {
762 trace_smb3_query_wsl_ea_compound_err(xid, tcon->tid,
763 ses->Suid, rc);
764 }
765 SMB2_query_info_free(&rqst[num_rqst++]);
766 break;
767 }
768 }
769 SMB2_close_free(&rqst[num_rqst]);
770 rc = tmp_rc;
771
772 num_cmds += 2;
773 if (out_iov && out_buftype) {
774 memcpy(out_iov, rsp_iov, num_cmds * sizeof(*out_iov));
775 memcpy(out_buftype, resp_buftype,
776 num_cmds * sizeof(*out_buftype));
777 } else {
778 for (i = 0; i < num_cmds; i++)
779 free_rsp_buf(resp_buftype[i], rsp_iov[i].iov_base);
780 }
781 num_cmds -= 2; /* correct num_cmds as there could be a retry */
782 kfree(vars);
783
784 if (is_replayable_error(rc) &&
785 smb2_should_replay(tcon, &retries, &cur_sleep))
786 goto replay_again;
787
788 out:
789 if (cfile)
790 cifsFileInfo_put(cfile);
791
792 return rc;
793 }
794
parse_create_response(struct cifs_open_info_data * data,struct cifs_sb_info * cifs_sb,const char * full_path,const struct kvec * iov)795 static int parse_create_response(struct cifs_open_info_data *data,
796 struct cifs_sb_info *cifs_sb,
797 const char *full_path,
798 const struct kvec *iov)
799 {
800 struct smb2_create_rsp *rsp = iov->iov_base;
801 bool reparse_point = false;
802 u32 tag = 0;
803 int rc = 0;
804
805 switch (rsp->hdr.Status) {
806 case STATUS_IO_REPARSE_TAG_NOT_HANDLED:
807 reparse_point = true;
808 break;
809 case STATUS_STOPPED_ON_SYMLINK:
810 rc = smb2_parse_symlink_response(cifs_sb, iov,
811 full_path,
812 &data->symlink_target);
813 if (rc != 0 && rc != -ENODATA)
814 return rc;
815 /*
816 * -ENODATA means that the response was parsed but did not contain
817 * the symlink target at all (see symlink_data()). Treat it like
818 * STATUS_IO_REPARSE_TAG_NOT_HANDLED, which does not contain it
819 * either: leave the tag unset and clear rc, so that the caller
820 * retrieves the target with SMB2_OP_GET_REPARSE.
821 */
822 if (rc == -ENODATA)
823 rc = 0;
824 else
825 tag = IO_REPARSE_TAG_SYMLINK;
826 reparse_point = true;
827 break;
828 case STATUS_SUCCESS:
829 reparse_point = !!(rsp->Flags & SMB2_CREATE_FLAG_REPARSEPOINT);
830 break;
831 }
832 data->reparse_point = reparse_point;
833 data->reparse.tag = tag;
834 return rc;
835 }
836
837 /* 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)838 static bool ea_unsupported(int *cmds, int num_cmds,
839 struct kvec *out_iov, int *out_buftype)
840 {
841 int i;
842
843 if (cmds[num_cmds - 1] != SMB2_OP_QUERY_WSL_EA)
844 return false;
845
846 for (i = 1; i < num_cmds - 1; i++) {
847 struct smb2_hdr *hdr = out_iov[i].iov_base;
848
849 if (out_buftype[i] == CIFS_NO_BUFFER || !hdr ||
850 hdr->Status != STATUS_SUCCESS)
851 return false;
852 }
853 return true;
854 }
855
free_rsp_iov(struct kvec * iovs,int * buftype,int count)856 static inline void free_rsp_iov(struct kvec *iovs, int *buftype, int count)
857 {
858 int i;
859
860 for (i = 0; i < count; i++) {
861 free_rsp_buf(buftype[i], iovs[i].iov_base);
862 memset(&iovs[i], 0, sizeof(*iovs));
863 buftype[i] = CIFS_NO_BUFFER;
864 }
865 }
866
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)867 int smb2_query_path_info(const unsigned int xid,
868 struct cifs_tcon *tcon,
869 struct cifs_sb_info *cifs_sb,
870 const char *full_path,
871 struct cifs_open_info_data *data)
872 {
873 struct kvec in_iov[3], out_iov[5] = {};
874 struct cached_fid *cfid = NULL;
875 struct cifs_open_parms oparms;
876 struct cifsFileInfo *cfile;
877 __u32 create_options = 0;
878 int out_buftype[5] = {};
879 struct smb2_hdr *hdr;
880 int num_cmds = 0;
881 int cmds[3];
882 bool islink;
883 int rc, rc2;
884
885 data->adjust_tz = false;
886 data->reparse_point = false;
887
888 /*
889 * BB TODO: Add support for using cached root handle in SMB3.1.1 POSIX.
890 * Create SMB2_query_posix_info worker function to do non-compounded
891 * query when we already have an open file handle for this. For now this
892 * is fast enough (always using the compounded version).
893 */
894 if (!tcon->posix_extensions) {
895 if (*full_path) {
896 rc = -ENOENT;
897 } else {
898 rc = open_cached_dir(xid, tcon, full_path,
899 cifs_sb, false, &cfid);
900 }
901 /* If it is a root and its handle is cached then use it */
902 if (!rc) {
903 if (cfid->file_all_info_is_valid) {
904 memcpy(&data->fi, &cfid->file_all_info,
905 sizeof(data->fi));
906 } else {
907 rc = SMB2_query_info(xid, tcon,
908 cfid->fid.persistent_fid,
909 cfid->fid.volatile_fid,
910 &data->fi);
911 }
912 close_cached_dir(cfid);
913 return rc;
914 }
915 cmds[num_cmds++] = SMB2_OP_QUERY_INFO;
916 } else {
917 cmds[num_cmds++] = SMB2_OP_POSIX_QUERY_INFO;
918 }
919
920 in_iov[0].iov_base = data;
921 in_iov[0].iov_len = sizeof(*data);
922 in_iov[1] = in_iov[0];
923 in_iov[2] = in_iov[0];
924
925 cifs_get_readable_path(tcon, full_path, &cfile);
926 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_ATTRIBUTES,
927 FILE_OPEN, create_options, ACL_NO_MODE);
928 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
929 &oparms, in_iov, cmds, num_cmds,
930 cfile, out_iov, out_buftype, NULL);
931 hdr = out_iov[0].iov_base;
932 /*
933 * If first iov is unset, then SMB session was dropped or we've got a
934 * cached open file (@cfile).
935 */
936 if (!hdr || out_buftype[0] == CIFS_NO_BUFFER)
937 goto out;
938
939 switch (rc) {
940 case 0:
941 rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
942 break;
943 case -EACCES:
944 /*
945 * If SMB2_OP_QUERY_INFO (called when POSIX extensions are not used) failed with
946 * STATUS_ACCESS_DENIED then it means that caller does not have permission to
947 * open the path with FILE_READ_ATTRIBUTES access and therefore cannot issue
948 * SMB2_OP_QUERY_INFO command.
949 *
950 * There is an alternative way how to query limited information about path but still
951 * suitable for stat() syscall. SMB2 OPEN/CREATE operation returns in its successful
952 * response subset of query information.
953 *
954 * So try to open the path without FILE_READ_ATTRIBUTES but with MAXIMUM_ALLOWED
955 * access which will grant the maximum possible access to the file and the response
956 * will contain required query information for stat() syscall.
957 */
958
959 if (tcon->posix_extensions)
960 break;
961
962 num_cmds = 1;
963 cmds[0] = SMB2_OP_OPEN_QUERY;
964 in_iov[0].iov_base = data;
965 in_iov[0].iov_len = sizeof(*data);
966 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, MAXIMUM_ALLOWED,
967 FILE_OPEN, create_options, ACL_NO_MODE);
968 free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
969 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
970 &oparms, in_iov, cmds, num_cmds,
971 cfile, out_iov, out_buftype, NULL);
972
973 hdr = out_iov[0].iov_base;
974 if (!hdr || out_buftype[0] == CIFS_NO_BUFFER)
975 goto out;
976
977 if (!rc)
978 rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
979 break;
980 case -EOPNOTSUPP:
981 /*
982 * BB TODO: When support for special files added to Samba
983 * re-verify this path.
984 */
985 rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
986 if (rc || !data->reparse_point)
987 goto out;
988
989 /*
990 * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
991 * response.
992 */
993 if (data->reparse.tag != IO_REPARSE_TAG_SYMLINK) {
994 cmds[num_cmds++] = SMB2_OP_GET_REPARSE;
995 if (!tcon->posix_extensions)
996 cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
997 }
998
999 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1000 FILE_READ_ATTRIBUTES |
1001 FILE_READ_EA | SYNCHRONIZE,
1002 FILE_OPEN, create_options |
1003 OPEN_REPARSE_POINT, ACL_NO_MODE);
1004 cifs_get_readable_path(tcon, full_path, &cfile);
1005 free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
1006 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
1007 &oparms, in_iov, cmds, num_cmds,
1008 cfile, out_iov, out_buftype, NULL);
1009 if (rc && ea_unsupported(cmds, num_cmds,
1010 out_iov, out_buftype)) {
1011 if (data->reparse.tag != IO_REPARSE_TAG_LX_BLK &&
1012 data->reparse.tag != IO_REPARSE_TAG_LX_CHR)
1013 rc = 0;
1014 else
1015 rc = -EOPNOTSUPP;
1016 }
1017
1018 /*
1019 * If the symlink was already parsed in create response then it is needed to fix
1020 * its type now (after the second call with OPEN_REPARSE_POINT which filled the
1021 * metadata attributes). If the symlink was not parsed in create response then
1022 * the data->symlink_target was not filled yet and then the type will be fixed
1023 * later after data->symlink_target is filled.
1024 */
1025 if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK && !rc && data->symlink_target) {
1026 bool directory = cifs_open_data_attrs(data) & ATTR_DIRECTORY;
1027
1028 rc = smb2_fix_symlink_target_type(&data->symlink_target, directory, cifs_sb);
1029 }
1030 break;
1031 case -EREMOTE:
1032 break;
1033 default:
1034 if (hdr->Status != STATUS_OBJECT_NAME_INVALID)
1035 break;
1036 rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
1037 full_path, &islink);
1038 if (rc2) {
1039 rc = rc2;
1040 goto out;
1041 }
1042 if (islink)
1043 rc = -EREMOTE;
1044 }
1045
1046 out:
1047 free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
1048 return rc;
1049 }
1050
1051 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)1052 smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
1053 struct cifs_tcon *tcon, const char *name,
1054 struct cifs_sb_info *cifs_sb)
1055 {
1056 struct cifs_open_parms oparms;
1057
1058 oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
1059 FILE_CREATE, CREATE_NOT_FILE, mode);
1060 return smb2_compound_op(xid, tcon, cifs_sb,
1061 name, &oparms, NULL,
1062 &(int){SMB2_OP_MKDIR}, 1,
1063 NULL, NULL, NULL, NULL);
1064 }
1065
1066 void
smb2_mkdir_setinfo(struct inode * inode,const char * name,struct cifs_sb_info * cifs_sb,struct cifs_tcon * tcon,const unsigned int xid)1067 smb2_mkdir_setinfo(struct inode *inode, const char *name,
1068 struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
1069 const unsigned int xid)
1070 {
1071 struct cifs_open_parms oparms;
1072 FILE_BASIC_INFO data = {};
1073 struct cifsInodeInfo *cifs_i;
1074 struct cifsFileInfo *cfile;
1075 struct kvec in_iov;
1076 u32 dosattrs;
1077 int tmprc;
1078
1079 in_iov.iov_base = &data;
1080 in_iov.iov_len = sizeof(data);
1081 cifs_i = CIFS_I(inode);
1082 dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
1083 data.Attributes = cpu_to_le32(dosattrs);
1084 cifs_get_writable_path(tcon, name, inode, FIND_ANY, &cfile);
1085 oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
1086 FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE);
1087 tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
1088 &oparms, &in_iov,
1089 &(int){SMB2_OP_SET_INFO}, 1,
1090 cfile, NULL, NULL, NULL);
1091 if (tmprc == 0)
1092 cifs_i->cifsAttrs = dosattrs;
1093 }
1094
1095 int
smb2_rmdir(const unsigned int xid,struct cifs_tcon * tcon,const char * name,struct cifs_sb_info * cifs_sb)1096 smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
1097 struct cifs_sb_info *cifs_sb)
1098 {
1099 struct cifs_open_parms oparms;
1100
1101 drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
1102 oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE,
1103 FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE);
1104 return smb2_compound_op(xid, tcon, cifs_sb,
1105 name, &oparms, NULL,
1106 &(int){SMB2_OP_UNLINK}, 1,
1107 NULL, NULL, NULL, NULL);
1108 }
1109
1110 int
smb2_unlink(const unsigned int xid,struct cifs_tcon * tcon,const char * name,struct cifs_sb_info * cifs_sb,struct dentry * dentry)1111 smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
1112 struct cifs_sb_info *cifs_sb, struct dentry *dentry)
1113 {
1114 struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
1115 __le16 *utf16_path __free(kfree) = NULL;
1116 int retries = 0, cur_sleep = 0;
1117 struct TCP_Server_Info *server;
1118 struct cifs_open_parms oparms;
1119 struct smb2_create_req *creq;
1120 struct inode *inode = NULL;
1121 struct smb_rqst rqst[2];
1122 struct kvec rsp_iov[2];
1123 struct kvec close_iov;
1124 int resp_buftype[2];
1125 struct cifs_fid fid;
1126 int flags = CIFS_CP_CREATE_CLOSE_OP;
1127 __u8 oplock;
1128 int rc;
1129
1130 utf16_path = cifs_convert_path_to_utf16(name, cifs_sb);
1131 if (!utf16_path)
1132 return -ENOMEM;
1133
1134 if (smb3_encryption_required(tcon))
1135 flags |= CIFS_TRANSFORM_REQ;
1136 again:
1137 oplock = SMB2_OPLOCK_LEVEL_NONE;
1138 server = cifs_pick_channel(tcon->ses);
1139
1140 memset(rqst, 0, sizeof(rqst));
1141 memset(resp_buftype, 0, sizeof(resp_buftype));
1142 memset(rsp_iov, 0, sizeof(rsp_iov));
1143
1144 memset(open_iov, 0, sizeof(open_iov));
1145 rqst[0].rq_iov = open_iov;
1146 rqst[0].rq_nvec = ARRAY_SIZE(open_iov);
1147
1148 oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE | FILE_READ_ATTRIBUTES,
1149 FILE_OPEN, CREATE_DELETE_ON_CLOSE |
1150 OPEN_REPARSE_POINT, ACL_NO_MODE);
1151 oparms.fid = &fid;
1152
1153 if (dentry) {
1154 inode = d_inode(dentry);
1155 if (CIFS_I(inode)->lease_granted && server->ops->get_lease_key) {
1156 oplock = SMB2_OPLOCK_LEVEL_LEASE;
1157 server->ops->get_lease_key(inode, &fid);
1158 }
1159 }
1160
1161 rc = SMB2_open_init(tcon, server,
1162 &rqst[0], &oplock, &oparms, utf16_path);
1163 if (rc)
1164 goto err_free;
1165 smb2_set_next_command(tcon, &rqst[0]);
1166 creq = rqst[0].rq_iov[0].iov_base;
1167 creq->ShareAccess = FILE_SHARE_DELETE_LE;
1168
1169 memset(&close_iov, 0, sizeof(close_iov));
1170 rqst[1].rq_iov = &close_iov;
1171 rqst[1].rq_nvec = 1;
1172
1173 rc = SMB2_close_init(tcon, server, &rqst[1],
1174 COMPOUND_FID, COMPOUND_FID, false);
1175 if (rc)
1176 goto err_free;
1177 smb2_set_related(&rqst[1]);
1178
1179 if (retries) {
1180 /* Back-off before retry */
1181 if (cur_sleep)
1182 msleep(cur_sleep);
1183 for (int i = 0; i < ARRAY_SIZE(rqst); i++)
1184 smb2_set_replay(server, &rqst[i]);
1185 }
1186
1187 rc = compound_send_recv(xid, tcon->ses, server, flags,
1188 ARRAY_SIZE(rqst), rqst,
1189 resp_buftype, rsp_iov);
1190 SMB2_open_free(&rqst[0]);
1191 SMB2_close_free(&rqst[1]);
1192 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
1193 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
1194
1195 if (is_replayable_error(rc) &&
1196 smb2_should_replay(tcon, &retries, &cur_sleep))
1197 goto again;
1198
1199 /* Retry compound request without lease */
1200 if (rc == -EINVAL && dentry) {
1201 dentry = NULL;
1202 retries = 0;
1203 cur_sleep = 0;
1204 goto again;
1205 }
1206 /*
1207 * If dentry (hence, inode) is NULL, lease break is going to
1208 * take care of degrading leases on handles for deleted files.
1209 */
1210 if (!rc && inode)
1211 cifs_mark_open_handles_for_deleted_file(inode, name);
1212
1213 return rc;
1214
1215 err_free:
1216 SMB2_open_free(&rqst[0]);
1217 SMB2_close_free(&rqst[1]);
1218 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
1219 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
1220 return rc;
1221 }
1222
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)1223 static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
1224 const char *from_name, const char *to_name,
1225 struct cifs_sb_info *cifs_sb,
1226 __u32 create_options, __u32 access,
1227 int command, struct cifsFileInfo *cfile,
1228 struct dentry *dentry)
1229 {
1230 struct cifs_open_parms oparms;
1231 struct kvec in_iov;
1232 __le16 *smb2_to_name = NULL;
1233 int rc;
1234
1235 smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
1236 if (smb2_to_name == NULL) {
1237 rc = -ENOMEM;
1238 if (cfile)
1239 cifsFileInfo_put(cfile);
1240 goto smb2_rename_path;
1241 }
1242 in_iov.iov_base = smb2_to_name;
1243 in_iov.iov_len = 2 * UniStrnlen((wchar_t *)smb2_to_name, PATH_MAX);
1244 oparms = CIFS_OPARMS(cifs_sb, tcon, from_name, access, FILE_OPEN,
1245 create_options, ACL_NO_MODE);
1246 rc = smb2_compound_op(xid, tcon, cifs_sb, from_name,
1247 &oparms, &in_iov, &command, 1,
1248 cfile, NULL, NULL, dentry);
1249 smb2_rename_path:
1250 kfree(smb2_to_name);
1251 return rc;
1252 }
1253
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)1254 int smb2_rename_path(const unsigned int xid,
1255 struct cifs_tcon *tcon,
1256 struct dentry *source_dentry,
1257 const char *from_name, const char *to_name,
1258 struct cifs_sb_info *cifs_sb)
1259 {
1260 struct inode *inode = source_dentry ? d_inode(source_dentry) : NULL;
1261 struct cifsFileInfo *cfile;
1262 __u32 co = file_create_options(source_dentry);
1263
1264 drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
1265 cifs_get_writable_path(tcon, from_name, inode,
1266 FIND_WITH_DELETE, &cfile);
1267
1268 int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
1269 co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
1270 if (rc == -EINVAL) {
1271 cifs_dbg(FYI, "invalid lease key, resending request without lease");
1272 cifs_get_writable_path(tcon, from_name, inode,
1273 FIND_WITH_DELETE, &cfile);
1274 rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
1275 co, DELETE, SMB2_OP_RENAME, cfile, NULL);
1276 }
1277 return rc;
1278 }
1279
clear_tmpfile_attr(const unsigned int xid,struct cifs_tcon * tcon,struct inode * inode,const char * full_path)1280 static int clear_tmpfile_attr(const unsigned int xid, struct cifs_tcon *tcon,
1281 struct inode *inode, const char *full_path)
1282 {
1283 struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
1284 struct cifsInodeInfo *cinode = CIFS_I(inode);
1285 FILE_BASIC_INFO fi;
1286
1287 cinode->cifsAttrs &= ~(ATTR_TEMPORARY | ATTR_HIDDEN);
1288 fi = (FILE_BASIC_INFO) {
1289 .Attributes = cpu_to_le32(cinode->cifsAttrs),
1290 };
1291 return server->ops->set_file_info(inode, full_path, &fi, xid);
1292 }
1293
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)1294 int smb2_create_hardlink(const unsigned int xid,
1295 struct cifs_tcon *tcon,
1296 struct dentry *source_dentry,
1297 const char *from_name, const char *to_name,
1298 struct cifs_sb_info *cifs_sb)
1299 {
1300 struct inode *inode = source_dentry ? d_inode(source_dentry) : NULL;
1301 __u32 co = file_create_options(source_dentry);
1302 struct cifsFileInfo *cfile;
1303 int rc;
1304
1305 if (inode && test_bit(CIFS_INO_TMPFILE, &CIFS_I(inode)->flags)) {
1306 rc = clear_tmpfile_attr(xid, tcon, inode, from_name);
1307 if (rc)
1308 return rc;
1309 }
1310
1311 cifs_get_writable_path(tcon, from_name, inode,
1312 FIND_WITH_DELETE, &cfile);
1313 return smb2_set_path_attr(xid, tcon, from_name, to_name,
1314 cifs_sb, co, FILE_READ_ATTRIBUTES,
1315 SMB2_OP_HARDLINK, cfile, NULL);
1316 }
1317
1318 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)1319 smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
1320 const char *full_path, __u64 size,
1321 struct cifs_sb_info *cifs_sb, bool set_alloc,
1322 struct dentry *dentry)
1323 {
1324 struct inode *inode = dentry ? d_inode(dentry) : NULL;
1325 __le64 eof = cpu_to_le64(size);
1326 struct cifs_open_parms oparms;
1327 struct cifsFileInfo *cfile;
1328 struct kvec in_iov;
1329 int rc;
1330
1331 in_iov.iov_base = &eof;
1332 in_iov.iov_len = sizeof(eof);
1333 cifs_get_writable_path(tcon, full_path, inode, FIND_ANY, &cfile);
1334
1335 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,
1336 FILE_OPEN, 0, ACL_NO_MODE);
1337 rc = smb2_compound_op(xid, tcon, cifs_sb,
1338 full_path, &oparms, &in_iov,
1339 &(int){SMB2_OP_SET_EOF}, 1,
1340 cfile, NULL, NULL, dentry);
1341 if (rc == -EINVAL) {
1342 cifs_dbg(FYI, "invalid lease key, resending request without lease");
1343 cifs_get_writable_path(tcon, full_path,
1344 inode, FIND_ANY, &cfile);
1345 rc = smb2_compound_op(xid, tcon, cifs_sb,
1346 full_path, &oparms, &in_iov,
1347 &(int){SMB2_OP_SET_EOF}, 1,
1348 cfile, NULL, NULL, NULL);
1349 }
1350 return rc;
1351 }
1352
1353 int
smb2_set_file_info(struct inode * inode,const char * full_path,FILE_BASIC_INFO * buf,const unsigned int xid)1354 smb2_set_file_info(struct inode *inode, const char *full_path,
1355 FILE_BASIC_INFO *buf, const unsigned int xid)
1356 {
1357 struct kvec in_iov = { .iov_base = buf, .iov_len = sizeof(*buf), };
1358 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1359 struct cifsFileInfo *cfile = NULL;
1360 struct cifs_open_parms oparms;
1361 struct tcon_link *tlink;
1362 struct cifs_tcon *tcon;
1363 int rc = 0;
1364
1365 tlink = cifs_sb_tlink(cifs_sb);
1366 if (IS_ERR(tlink))
1367 return PTR_ERR(tlink);
1368 tcon = tlink_tcon(tlink);
1369
1370 if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
1371 (buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) {
1372 if (buf->Attributes == 0)
1373 goto out; /* would be a no op, no sense sending this */
1374 cifs_get_writable_path(tcon, full_path,
1375 inode, FIND_ANY, &cfile);
1376 }
1377
1378 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES,
1379 FILE_OPEN, 0, ACL_NO_MODE);
1380 rc = smb2_compound_op(xid, tcon, cifs_sb,
1381 full_path, &oparms, &in_iov,
1382 &(int){SMB2_OP_SET_INFO}, 1,
1383 cfile, NULL, NULL, NULL);
1384 out:
1385 cifs_put_tlink(tlink);
1386 return rc;
1387 }
1388
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)1389 struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
1390 struct super_block *sb,
1391 const unsigned int xid,
1392 struct cifs_tcon *tcon,
1393 const char *full_path,
1394 bool directory,
1395 struct kvec *reparse_iov,
1396 struct kvec *xattr_iov)
1397 {
1398 struct cifs_open_parms oparms;
1399 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1400 struct cifsFileInfo *cfile;
1401 struct inode *new = NULL;
1402 int out_buftype[4] = {};
1403 struct kvec out_iov[4] = {};
1404 struct kvec in_iov[2];
1405 int cmds[2];
1406 int rc;
1407 int i;
1408
1409 /*
1410 * If server filesystem does not support reparse points then do not
1411 * attempt to create reparse point. This will prevent creating unusable
1412 * empty object on the server.
1413 */
1414 if (!CIFS_REPARSE_SUPPORT(tcon))
1415 return ERR_PTR(-EOPNOTSUPP);
1416
1417 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1418 SYNCHRONIZE | DELETE |
1419 FILE_READ_ATTRIBUTES |
1420 FILE_WRITE_ATTRIBUTES,
1421 FILE_CREATE,
1422 (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
1423 ACL_NO_MODE);
1424 if (xattr_iov)
1425 oparms.ea_cctx = xattr_iov;
1426
1427 cmds[0] = SMB2_OP_SET_REPARSE;
1428 in_iov[0] = *reparse_iov;
1429 in_iov[1].iov_base = data;
1430 in_iov[1].iov_len = sizeof(*data);
1431
1432 if (tcon->posix_extensions) {
1433 cmds[1] = SMB2_OP_POSIX_QUERY_INFO;
1434 cifs_get_writable_path(tcon, full_path, NULL, FIND_ANY, &cfile);
1435 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
1436 in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
1437 if (!rc) {
1438 rc = smb311_posix_get_inode_info(&new, full_path,
1439 data, sb, xid);
1440 }
1441 } else {
1442 cmds[1] = SMB2_OP_QUERY_INFO;
1443 cifs_get_writable_path(tcon, full_path, NULL, FIND_ANY, &cfile);
1444 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
1445 in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
1446 if (!rc) {
1447 rc = cifs_get_inode_info(&new, full_path,
1448 data, sb, xid, NULL);
1449 }
1450 }
1451
1452
1453 /*
1454 * If CREATE was successful but SMB2_OP_SET_REPARSE failed then
1455 * remove the intermediate object created by CREATE. Otherwise
1456 * empty object stay on the server when reparse call failed.
1457 */
1458 if (rc &&
1459 out_iov[0].iov_base != NULL && out_buftype[0] != CIFS_NO_BUFFER &&
1460 ((struct smb2_hdr *)out_iov[0].iov_base)->Status == STATUS_SUCCESS &&
1461 (out_iov[1].iov_base == NULL || out_buftype[1] == CIFS_NO_BUFFER ||
1462 ((struct smb2_hdr *)out_iov[1].iov_base)->Status != STATUS_SUCCESS))
1463 smb2_unlink(xid, tcon, full_path, cifs_sb, NULL);
1464
1465 for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
1466 free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
1467
1468 return rc ? ERR_PTR(rc) : new;
1469 }
1470
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)1471 int smb2_query_reparse_point(const unsigned int xid,
1472 struct cifs_tcon *tcon,
1473 struct cifs_sb_info *cifs_sb,
1474 const char *full_path,
1475 u32 *tag, struct kvec *rsp,
1476 int *rsp_buftype)
1477 {
1478 struct cifs_open_parms oparms;
1479 struct cifs_open_info_data data = {};
1480 struct cifsFileInfo *cfile;
1481 struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), };
1482 int rc;
1483
1484 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
1485
1486 cifs_get_readable_path(tcon, full_path, &cfile);
1487 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1488 FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE,
1489 FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE);
1490 rc = smb2_compound_op(xid, tcon, cifs_sb,
1491 full_path, &oparms, &in_iov,
1492 &(int){SMB2_OP_GET_REPARSE}, 1,
1493 cfile, NULL, NULL, NULL);
1494 if (rc)
1495 goto out;
1496
1497 *tag = data.reparse.tag;
1498 *rsp = data.reparse.io.iov;
1499 *rsp_buftype = data.reparse.io.buftype;
1500 memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov));
1501 data.reparse.io.buftype = CIFS_NO_BUFFER;
1502 out:
1503 cifs_free_open_info(&data);
1504 return rc;
1505 }
1506
utf16_smb2_path(struct cifs_sb_info * cifs_sb,const char * name,size_t namelen)1507 static inline __le16 *utf16_smb2_path(struct cifs_sb_info *cifs_sb,
1508 const char *name, size_t namelen)
1509 {
1510 int len;
1511
1512 if (*name == '\\' ||
1513 (cifs_sb_master_tlink(cifs_sb) &&
1514 cifs_sb_master_tcon(cifs_sb)->posix_extensions && *name == '/'))
1515 name++;
1516 return cifs_strndup_to_utf16(name, namelen, &len,
1517 cifs_sb->local_nls,
1518 cifs_remap(cifs_sb));
1519 }
1520
smb2_rename_pending_delete(const char * full_path,struct dentry * dentry,const unsigned int xid)1521 int smb2_rename_pending_delete(const char *full_path,
1522 struct dentry *dentry,
1523 const unsigned int xid)
1524 {
1525 struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry));
1526 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry);
1527 __le16 *utf16_path __free(kfree) = NULL;
1528 __u32 co = file_create_options(dentry);
1529 int cmds[] = {
1530 SMB2_OP_SET_INFO,
1531 SMB2_OP_RENAME,
1532 SMB2_OP_UNLINK,
1533 };
1534 const int num_cmds = ARRAY_SIZE(cmds);
1535 char *to_name __free(kfree) = NULL;
1536 __u32 attrs = cinode->cifsAttrs;
1537 struct cifs_open_parms oparms;
1538 struct cifsFileInfo *cfile;
1539 struct tcon_link *tlink;
1540 struct cifs_tcon *tcon;
1541 struct kvec iov[2];
1542 int rc;
1543
1544 tlink = cifs_sb_tlink(cifs_sb);
1545 if (IS_ERR(tlink))
1546 return PTR_ERR(tlink);
1547 tcon = tlink_tcon(tlink);
1548
1549 to_name = cifs_silly_fullpath(dentry);
1550 if (IS_ERR(to_name)) {
1551 rc = PTR_ERR(to_name);
1552 to_name = NULL;
1553 goto out;
1554 }
1555
1556 utf16_path = utf16_smb2_path(cifs_sb, to_name, strlen(to_name));
1557 if (!utf16_path) {
1558 rc = -ENOMEM;
1559 goto out;
1560 }
1561
1562 drop_cached_dir_by_name(xid, tcon, full_path, cifs_sb);
1563 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
1564 DELETE | FILE_WRITE_ATTRIBUTES,
1565 FILE_OPEN, co, ACL_NO_MODE);
1566
1567 attrs &= ~ATTR_READONLY;
1568 if (!attrs)
1569 attrs = ATTR_NORMAL;
1570 if (d_inode(dentry)->i_nlink <= 1)
1571 attrs |= ATTR_HIDDEN;
1572 iov[0].iov_base = &(FILE_BASIC_INFO) {
1573 .Attributes = cpu_to_le32(attrs),
1574 };
1575 iov[0].iov_len = sizeof(FILE_BASIC_INFO);
1576 iov[1].iov_base = utf16_path;
1577 iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path);
1578
1579 cifs_get_writable_path(tcon, full_path, d_inode(dentry),
1580 FIND_WITH_DELETE, &cfile);
1581 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,
1582 cmds, num_cmds, cfile, NULL, NULL, dentry);
1583 if (rc == -EINVAL) {
1584 cifs_dbg(FYI, "invalid lease key, resending request without lease\n");
1585 cifs_get_writable_path(tcon, full_path, d_inode(dentry),
1586 FIND_WITH_DELETE, &cfile);
1587 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,
1588 cmds, num_cmds, cfile, NULL, NULL, NULL);
1589 }
1590 if (!rc) {
1591 set_bit(CIFS_INO_DELETE_PENDING, &cinode->flags);
1592 } else {
1593 cifs_tcon_dbg(FYI, "%s: failed to rename '%s' to '%s': %d\n",
1594 __func__, full_path, to_name, rc);
1595 rc = smb_EIO1(smb_eio_trace_pend_del_fail, rc);
1596 }
1597 out:
1598 cifs_put_tlink(tlink);
1599 return rc;
1600 }
1601