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