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