1 // SPDX-License-Identifier: LGPL-2.1
4 * Copyright (C) International Business Machines Corp., 2002, 2011
6 * Author(s): Pavel Shilovsky (pshilovsky@samba.org),
7 * Steve French (sfrench@us.ibm.com)
11 #include <linux/stat.h>
12 #include <linux/slab.h>
13 #include <linux/pagemap.h>
14 #include <asm/div64.h>
18 #include "cifsproto.h"
19 #include "cifs_debug.h"
20 #include "cifs_fs_sb.h"
21 #include "cifs_unicode.h"
25 #include "smb2proto.h"
26 #include "cached_dir.h"
27 #include "../common/smb2status.h"
29 static struct reparse_data_buffer
*reparse_buf_ptr(struct kvec
*iov
)
31 struct reparse_data_buffer
*buf
;
32 struct smb2_ioctl_rsp
*io
= iov
->iov_base
;
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
)
40 buf
= (struct reparse_data_buffer
*)((u8
*)io
+ off
);
42 if (count
< len
|| count
< le16_to_cpu(buf
->ReparseDataLength
) + len
)
47 static inline __u32
file_create_options(struct dentry
*dentry
)
49 struct cifsInodeInfo
*ci
;
52 ci
= CIFS_I(d_inode(dentry
));
53 if (ci
->cifsAttrs
& ATTR_REPARSE
)
54 return OPEN_REPARSE_POINT
;
59 /* Parse owner and group from SMB3.1.1 POSIX query info */
60 static int parse_posix_sids(struct cifs_open_info_data
*data
,
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
;
69 if (out_len
<= qi_len
)
72 sidsbuf
= (u8
*)qi
+ le16_to_cpu(qi
->OutputBufferOffset
) + qi_len
;
73 sidsbuf_end
= sidsbuf
+ out_len
- qi_len
;
75 owner_len
= posix_info_sid_size(sidsbuf
, sidsbuf_end
);
79 memcpy(&data
->posix_owner
, sidsbuf
, owner_len
);
80 group_len
= posix_info_sid_size(sidsbuf
+ owner_len
, sidsbuf_end
);
84 memcpy(&data
->posix_group
, sidsbuf
+ owner_len
, group_len
);
91 __u8 name
[SMB2_WSL_XATTR_NAME_LEN
+ 1];
94 #define NEXT_OFF cpu_to_le32(sizeof(struct wsl_query_ea))
96 static const struct wsl_query_ea wsl_query_eas
[] = {
97 { .next
= NEXT_OFF
, .name_len
= SMB2_WSL_XATTR_NAME_LEN
, .name
= SMB2_WSL_XATTR_UID
, },
98 { .next
= NEXT_OFF
, .name_len
= SMB2_WSL_XATTR_NAME_LEN
, .name
= SMB2_WSL_XATTR_GID
, },
99 { .next
= NEXT_OFF
, .name_len
= SMB2_WSL_XATTR_NAME_LEN
, .name
= SMB2_WSL_XATTR_MODE
, },
100 { .next
= 0, .name_len
= SMB2_WSL_XATTR_NAME_LEN
, .name
= SMB2_WSL_XATTR_DEV
, },
103 static int check_wsl_eas(struct kvec
*rsp_iov
)
105 struct smb2_file_full_ea_info
*ea
;
106 struct smb2_query_info_rsp
*rsp
= rsp_iov
->iov_base
;
113 outlen
= le32_to_cpu(rsp
->OutputBufferLength
);
114 if (outlen
< SMB2_WSL_MIN_QUERY_EA_RESP_SIZE
||
115 outlen
> SMB2_WSL_MAX_QUERY_EA_RESP_SIZE
)
118 ea
= (void *)((u8
*)rsp_iov
->iov_base
+
119 le16_to_cpu(rsp
->OutputBufferOffset
));
120 end
= (u8
*)rsp_iov
->iov_base
+ rsp_iov
->iov_len
;
122 if ((u8
*)ea
> end
- sizeof(*ea
))
125 nlen
= ea
->ea_name_length
;
126 vlen
= le16_to_cpu(ea
->ea_value_length
);
127 if (nlen
!= SMB2_WSL_XATTR_NAME_LEN
||
128 (u8
*)ea
+ nlen
+ 1 + vlen
> end
)
133 if (strncmp(ea
->ea_data
, SMB2_WSL_XATTR_UID
, nlen
) &&
134 strncmp(ea
->ea_data
, SMB2_WSL_XATTR_GID
, nlen
) &&
135 strncmp(ea
->ea_data
, SMB2_WSL_XATTR_MODE
, nlen
))
139 if (strncmp(ea
->ea_data
, SMB2_WSL_XATTR_DEV
, nlen
))
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 !strncmp(ea
->ea_data
, SMB2_WSL_XATTR_DEV
, nlen
))
153 next
= le32_to_cpu(ea
->next_entry_offset
);
156 if (!IS_ALIGNED(next
, 4) ||
157 check_add_overflow((unsigned long)ea
, next
, &addr
))
165 * note: If cfile is passed, the reference to it is dropped here.
166 * So make sure that you do not reuse cfile after return from this func.
168 * If passing @out_iov and @out_buftype, ensure to make them both large enough
169 * (>= 3) to hold all compounded responses. Caller is also responsible for
170 * freeing them up with free_rsp_buf().
172 static int smb2_compound_op(const unsigned int xid
, struct cifs_tcon
*tcon
,
173 struct cifs_sb_info
*cifs_sb
, const char *full_path
,
174 struct cifs_open_parms
*oparms
, struct kvec
*in_iov
,
175 int *cmds
, int num_cmds
, struct cifsFileInfo
*cfile
,
176 struct kvec
*out_iov
, int *out_buftype
, struct dentry
*dentry
)
179 struct reparse_data_buffer
*rbuf
;
180 struct smb2_compound_vars
*vars
= NULL
;
181 struct kvec
*rsp_iov
, *iov
;
182 struct smb_rqst
*rqst
;
184 __le16
*utf16_path
= NULL
;
185 __u8 oplock
= SMB2_OPLOCK_LEVEL_NONE
;
187 struct cifs_ses
*ses
= tcon
->ses
;
188 struct TCP_Server_Info
*server
;
190 int resp_buftype
[MAX_COMPOUND
];
191 struct smb2_query_info_rsp
*qi_rsp
= NULL
;
192 struct cifs_open_info_data
*idata
;
193 struct inode
*inode
= NULL
;
195 __u8 delete_pending
[8] = {1, 0, 0, 0, 0, 0, 0, 0};
196 unsigned int size
[2];
199 int retries
= 0, cur_sleep
= 1;
202 /* reinitialize for possible replay */
204 oplock
= SMB2_OPLOCK_LEVEL_NONE
;
206 server
= cifs_pick_channel(ses
);
208 vars
= kzalloc(sizeof(*vars
), GFP_ATOMIC
);
211 rqst
= &vars
->rqst
[0];
212 rsp_iov
= &vars
->rsp_iov
[0];
214 if (smb3_encryption_required(tcon
))
215 flags
|= CIFS_TRANSFORM_REQ
;
217 for (i
= 0; i
< ARRAY_SIZE(resp_buftype
); i
++)
218 resp_buftype
[i
] = CIFS_NO_BUFFER
;
220 /* We already have a handle so we can skip the open */
225 utf16_path
= cifs_convert_path_to_utf16(full_path
, cifs_sb
);
231 /* if there is an existing lease, reuse it */
234 * note: files with hardlinks cause unexpected behaviour. As per MS-SMB2,
235 * lease keys are associated with the filepath. We are maintaining lease keys
236 * with the inode on the client. If the file has hardlinks, it is possible
237 * that the lease for a file be reused for an operation on its hardlink or
239 * As a workaround, send request using an existing lease key and if the server
240 * returns STATUS_INVALID_PARAMETER, which maps to EINVAL, send the request
241 * again without the lease.
244 inode
= d_inode(dentry
);
245 if (CIFS_I(inode
)->lease_granted
&& server
->ops
->get_lease_key
) {
246 oplock
= SMB2_OPLOCK_LEVEL_LEASE
;
247 server
->ops
->get_lease_key(inode
, &fid
);
251 vars
->oparms
= *oparms
;
252 vars
->oparms
.fid
= &fid
;
254 rqst
[num_rqst
].rq_iov
= &vars
->open_iov
[0];
255 rqst
[num_rqst
].rq_nvec
= SMB2_CREATE_IOV_SIZE
;
256 rc
= SMB2_open_init(tcon
, server
,
257 &rqst
[num_rqst
], &oplock
, &vars
->oparms
,
263 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
268 for (i
= 0; i
< num_cmds
; i
++) {
271 case SMB2_OP_QUERY_INFO
:
272 rqst
[num_rqst
].rq_iov
= &vars
->qi_iov
;
273 rqst
[num_rqst
].rq_nvec
= 1;
276 rc
= SMB2_query_info_init(tcon
, server
,
278 cfile
->fid
.persistent_fid
,
279 cfile
->fid
.volatile_fid
,
280 FILE_ALL_INFORMATION
,
282 sizeof(struct smb2_file_all_info
) +
283 PATH_MAX
* 2, 0, NULL
);
285 rc
= SMB2_query_info_init(tcon
, server
,
289 FILE_ALL_INFORMATION
,
291 sizeof(struct smb2_file_all_info
) +
292 PATH_MAX
* 2, 0, NULL
);
294 if (!rc
&& (!cfile
|| num_rqst
> 1)) {
295 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
296 smb2_set_related(&rqst
[num_rqst
]);
301 trace_smb3_query_info_compound_enter(xid
, ses
->Suid
,
302 tcon
->tid
, full_path
);
304 case SMB2_OP_POSIX_QUERY_INFO
:
305 rqst
[num_rqst
].rq_iov
= &vars
->qi_iov
;
306 rqst
[num_rqst
].rq_nvec
= 1;
309 /* TBD: fix following to allow for longer SIDs */
310 rc
= SMB2_query_info_init(tcon
, server
,
312 cfile
->fid
.persistent_fid
,
313 cfile
->fid
.volatile_fid
,
314 SMB_FIND_FILE_POSIX_INFO
,
316 sizeof(struct smb311_posix_qinfo
*) +
318 (sizeof(struct smb_sid
) * 2), 0, NULL
);
320 rc
= SMB2_query_info_init(tcon
, server
,
324 SMB_FIND_FILE_POSIX_INFO
,
326 sizeof(struct smb311_posix_qinfo
*) +
328 (sizeof(struct smb_sid
) * 2), 0, NULL
);
330 if (!rc
&& (!cfile
|| num_rqst
> 1)) {
331 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
332 smb2_set_related(&rqst
[num_rqst
]);
337 trace_smb3_posix_query_info_compound_enter(xid
, ses
->Suid
,
338 tcon
->tid
, full_path
);
341 trace_smb3_delete_enter(xid
, ses
->Suid
, tcon
->tid
, full_path
);
345 * Directories are created through parameters in the
348 trace_smb3_mkdir_enter(xid
, ses
->Suid
, tcon
->tid
, full_path
);
351 rqst
[num_rqst
].rq_iov
= &vars
->si_iov
[0];
352 rqst
[num_rqst
].rq_nvec
= 1;
354 size
[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
355 data
[0] = &delete_pending
[0];
357 rc
= SMB2_set_info_init(tcon
, server
,
358 &rqst
[num_rqst
], COMPOUND_FID
,
359 COMPOUND_FID
, current
->tgid
,
360 FILE_DISPOSITION_INFORMATION
,
361 SMB2_O_INFO_FILE
, 0, data
, size
);
364 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
365 smb2_set_related(&rqst
[num_rqst
++]);
366 trace_smb3_rmdir_enter(xid
, ses
->Suid
, tcon
->tid
, full_path
);
368 case SMB2_OP_SET_EOF
:
369 rqst
[num_rqst
].rq_iov
= &vars
->si_iov
[0];
370 rqst
[num_rqst
].rq_nvec
= 1;
372 size
[0] = in_iov
[i
].iov_len
;
373 data
[0] = in_iov
[i
].iov_base
;
376 rc
= SMB2_set_info_init(tcon
, server
,
378 cfile
->fid
.persistent_fid
,
379 cfile
->fid
.volatile_fid
,
381 FILE_END_OF_FILE_INFORMATION
,
385 rc
= SMB2_set_info_init(tcon
, server
,
390 FILE_END_OF_FILE_INFORMATION
,
394 if (!rc
&& (!cfile
|| num_rqst
> 1)) {
395 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
396 smb2_set_related(&rqst
[num_rqst
]);
401 trace_smb3_set_eof_enter(xid
, ses
->Suid
, tcon
->tid
, full_path
);
403 case SMB2_OP_SET_INFO
:
404 rqst
[num_rqst
].rq_iov
= &vars
->si_iov
[0];
405 rqst
[num_rqst
].rq_nvec
= 1;
407 size
[0] = in_iov
[i
].iov_len
;
408 data
[0] = in_iov
[i
].iov_base
;
411 rc
= SMB2_set_info_init(tcon
, server
,
413 cfile
->fid
.persistent_fid
,
414 cfile
->fid
.volatile_fid
, current
->tgid
,
415 FILE_BASIC_INFORMATION
,
416 SMB2_O_INFO_FILE
, 0, data
, size
);
418 rc
= SMB2_set_info_init(tcon
, server
,
421 COMPOUND_FID
, current
->tgid
,
422 FILE_BASIC_INFORMATION
,
423 SMB2_O_INFO_FILE
, 0, data
, size
);
425 if (!rc
&& (!cfile
|| num_rqst
> 1)) {
426 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
427 smb2_set_related(&rqst
[num_rqst
]);
432 trace_smb3_set_info_compound_enter(xid
, ses
->Suid
,
433 tcon
->tid
, full_path
);
436 rqst
[num_rqst
].rq_iov
= &vars
->si_iov
[0];
437 rqst
[num_rqst
].rq_nvec
= 2;
439 len
= in_iov
[i
].iov_len
;
441 vars
->rename_info
.ReplaceIfExists
= 1;
442 vars
->rename_info
.RootDirectory
= 0;
443 vars
->rename_info
.FileNameLength
= cpu_to_le32(len
);
445 size
[0] = sizeof(struct smb2_file_rename_info
);
446 data
[0] = &vars
->rename_info
;
448 size
[1] = len
+ 2 /* null */;
449 data
[1] = in_iov
[i
].iov_base
;
452 rc
= SMB2_set_info_init(tcon
, server
,
454 cfile
->fid
.persistent_fid
,
455 cfile
->fid
.volatile_fid
,
456 current
->tgid
, FILE_RENAME_INFORMATION
,
457 SMB2_O_INFO_FILE
, 0, data
, size
);
459 rc
= SMB2_set_info_init(tcon
, server
,
461 COMPOUND_FID
, COMPOUND_FID
,
462 current
->tgid
, FILE_RENAME_INFORMATION
,
463 SMB2_O_INFO_FILE
, 0, data
, size
);
465 if (!rc
&& (!cfile
|| num_rqst
> 1)) {
466 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
467 smb2_set_related(&rqst
[num_rqst
]);
472 trace_smb3_rename_enter(xid
, ses
->Suid
, tcon
->tid
, full_path
);
474 case SMB2_OP_HARDLINK
:
475 rqst
[num_rqst
].rq_iov
= &vars
->si_iov
[0];
476 rqst
[num_rqst
].rq_nvec
= 2;
478 len
= in_iov
[i
].iov_len
;
480 vars
->link_info
.ReplaceIfExists
= 0;
481 vars
->link_info
.RootDirectory
= 0;
482 vars
->link_info
.FileNameLength
= cpu_to_le32(len
);
484 size
[0] = sizeof(struct smb2_file_link_info
);
485 data
[0] = &vars
->link_info
;
487 size
[1] = len
+ 2 /* null */;
488 data
[1] = in_iov
[i
].iov_base
;
490 rc
= SMB2_set_info_init(tcon
, server
,
491 &rqst
[num_rqst
], COMPOUND_FID
,
492 COMPOUND_FID
, current
->tgid
,
493 FILE_LINK_INFORMATION
,
494 SMB2_O_INFO_FILE
, 0, data
, size
);
497 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
498 smb2_set_related(&rqst
[num_rqst
++]);
499 trace_smb3_hardlink_enter(xid
, ses
->Suid
, tcon
->tid
, full_path
);
501 case SMB2_OP_SET_REPARSE
:
502 rqst
[num_rqst
].rq_iov
= vars
->io_iov
;
503 rqst
[num_rqst
].rq_nvec
= ARRAY_SIZE(vars
->io_iov
);
506 rc
= SMB2_ioctl_init(tcon
, server
, &rqst
[num_rqst
],
507 cfile
->fid
.persistent_fid
,
508 cfile
->fid
.volatile_fid
,
509 FSCTL_SET_REPARSE_POINT
,
511 in_iov
[i
].iov_len
, 0);
513 rc
= SMB2_ioctl_init(tcon
, server
, &rqst
[num_rqst
],
514 COMPOUND_FID
, COMPOUND_FID
,
515 FSCTL_SET_REPARSE_POINT
,
517 in_iov
[i
].iov_len
, 0);
519 if (!rc
&& (!cfile
|| num_rqst
> 1)) {
520 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
521 smb2_set_related(&rqst
[num_rqst
]);
526 trace_smb3_set_reparse_compound_enter(xid
, ses
->Suid
,
527 tcon
->tid
, full_path
);
529 case SMB2_OP_GET_REPARSE
:
530 rqst
[num_rqst
].rq_iov
= vars
->io_iov
;
531 rqst
[num_rqst
].rq_nvec
= ARRAY_SIZE(vars
->io_iov
);
534 rc
= SMB2_ioctl_init(tcon
, server
, &rqst
[num_rqst
],
535 cfile
->fid
.persistent_fid
,
536 cfile
->fid
.volatile_fid
,
537 FSCTL_GET_REPARSE_POINT
,
538 NULL
, 0, CIFSMaxBufSize
);
540 rc
= SMB2_ioctl_init(tcon
, server
, &rqst
[num_rqst
],
541 COMPOUND_FID
, COMPOUND_FID
,
542 FSCTL_GET_REPARSE_POINT
,
543 NULL
, 0, CIFSMaxBufSize
);
545 if (!rc
&& (!cfile
|| num_rqst
> 1)) {
546 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
547 smb2_set_related(&rqst
[num_rqst
]);
552 trace_smb3_get_reparse_compound_enter(xid
, ses
->Suid
,
553 tcon
->tid
, full_path
);
555 case SMB2_OP_QUERY_WSL_EA
:
556 rqst
[num_rqst
].rq_iov
= &vars
->ea_iov
;
557 rqst
[num_rqst
].rq_nvec
= 1;
560 rc
= SMB2_query_info_init(tcon
, server
,
562 cfile
->fid
.persistent_fid
,
563 cfile
->fid
.volatile_fid
,
564 FILE_FULL_EA_INFORMATION
,
566 SMB2_WSL_MAX_QUERY_EA_RESP_SIZE
,
567 sizeof(wsl_query_eas
),
568 (void *)wsl_query_eas
);
570 rc
= SMB2_query_info_init(tcon
, server
,
574 FILE_FULL_EA_INFORMATION
,
576 SMB2_WSL_MAX_QUERY_EA_RESP_SIZE
,
577 sizeof(wsl_query_eas
),
578 (void *)wsl_query_eas
);
580 if (!rc
&& (!cfile
|| num_rqst
> 1)) {
581 smb2_set_next_command(tcon
, &rqst
[num_rqst
]);
582 smb2_set_related(&rqst
[num_rqst
]);
589 cifs_dbg(VFS
, "Invalid command\n");
596 /* We already have a handle so we can skip the close */
600 flags
|= CIFS_CP_CREATE_CLOSE_OP
;
601 rqst
[num_rqst
].rq_iov
= &vars
->close_iov
;
602 rqst
[num_rqst
].rq_nvec
= 1;
603 rc
= SMB2_close_init(tcon
, server
,
604 &rqst
[num_rqst
], COMPOUND_FID
,
605 COMPOUND_FID
, false);
606 smb2_set_related(&rqst
[num_rqst
]);
614 for (i
= 1; i
< num_rqst
- 2; i
++)
615 smb2_set_replay(server
, &rqst
[i
]);
617 rc
= compound_send_recv(xid
, ses
, server
,
619 &rqst
[1], &resp_buftype
[1],
623 for (i
= 0; i
< num_rqst
; i
++)
624 smb2_set_replay(server
, &rqst
[i
]);
626 rc
= compound_send_recv(xid
, ses
, server
,
634 SMB2_open_free(&rqst
[num_rqst
++]);
635 if (rc
== -EREMCHG
) {
636 pr_warn_once("server share %s deleted\n", tcon
->tree_name
);
637 tcon
->need_reconnect
= true;
640 for (i
= 0; i
< num_cmds
; i
++) {
642 case SMB2_OP_QUERY_INFO
:
643 idata
= in_iov
[i
].iov_base
;
644 if (rc
== 0 && cfile
&& cfile
->symlink_target
) {
645 idata
->symlink_target
= kstrdup(cfile
->symlink_target
, GFP_KERNEL
);
646 if (!idata
->symlink_target
)
650 qi_rsp
= (struct smb2_query_info_rsp
*)
651 rsp_iov
[i
+ 1].iov_base
;
652 rc
= smb2_validate_and_copy_iov(
653 le16_to_cpu(qi_rsp
->OutputBufferOffset
),
654 le32_to_cpu(qi_rsp
->OutputBufferLength
),
655 &rsp_iov
[i
+ 1], sizeof(idata
->fi
), (char *)&idata
->fi
);
657 SMB2_query_info_free(&rqst
[num_rqst
++]);
659 trace_smb3_query_info_compound_err(xid
, ses
->Suid
,
662 trace_smb3_query_info_compound_done(xid
, ses
->Suid
,
665 case SMB2_OP_POSIX_QUERY_INFO
:
666 idata
= in_iov
[i
].iov_base
;
667 if (rc
== 0 && cfile
&& cfile
->symlink_target
) {
668 idata
->symlink_target
= kstrdup(cfile
->symlink_target
, GFP_KERNEL
);
669 if (!idata
->symlink_target
)
673 qi_rsp
= (struct smb2_query_info_rsp
*)
674 rsp_iov
[i
+ 1].iov_base
;
675 rc
= smb2_validate_and_copy_iov(
676 le16_to_cpu(qi_rsp
->OutputBufferOffset
),
677 le32_to_cpu(qi_rsp
->OutputBufferLength
),
678 &rsp_iov
[i
+ 1], sizeof(idata
->posix_fi
) /* add SIDs */,
679 (char *)&idata
->posix_fi
);
682 rc
= parse_posix_sids(idata
, &rsp_iov
[i
+ 1]);
684 SMB2_query_info_free(&rqst
[num_rqst
++]);
686 trace_smb3_posix_query_info_compound_err(xid
, ses
->Suid
,
689 trace_smb3_posix_query_info_compound_done(xid
, ses
->Suid
,
694 trace_smb3_delete_err(xid
, ses
->Suid
, tcon
->tid
, rc
);
697 * If dentry (hence, inode) is NULL, lease break is going to
698 * take care of degrading leases on handles for deleted files.
701 cifs_mark_open_handles_for_deleted_file(inode
, full_path
);
702 trace_smb3_delete_done(xid
, ses
->Suid
, tcon
->tid
);
707 trace_smb3_mkdir_err(xid
, ses
->Suid
, tcon
->tid
, rc
);
709 trace_smb3_mkdir_done(xid
, ses
->Suid
, tcon
->tid
);
711 case SMB2_OP_HARDLINK
:
713 trace_smb3_hardlink_err(xid
, ses
->Suid
, tcon
->tid
, rc
);
715 trace_smb3_hardlink_done(xid
, ses
->Suid
, tcon
->tid
);
716 SMB2_set_info_free(&rqst
[num_rqst
++]);
720 trace_smb3_rename_err(xid
, ses
->Suid
, tcon
->tid
, rc
);
722 trace_smb3_rename_done(xid
, ses
->Suid
, tcon
->tid
);
723 SMB2_set_info_free(&rqst
[num_rqst
++]);
727 trace_smb3_rmdir_err(xid
, ses
->Suid
, tcon
->tid
, rc
);
729 trace_smb3_rmdir_done(xid
, ses
->Suid
, tcon
->tid
);
730 SMB2_set_info_free(&rqst
[num_rqst
++]);
732 case SMB2_OP_SET_EOF
:
734 trace_smb3_set_eof_err(xid
, ses
->Suid
, tcon
->tid
, rc
);
736 trace_smb3_set_eof_done(xid
, ses
->Suid
, tcon
->tid
);
737 SMB2_set_info_free(&rqst
[num_rqst
++]);
739 case SMB2_OP_SET_INFO
:
741 trace_smb3_set_info_compound_err(xid
, ses
->Suid
,
744 trace_smb3_set_info_compound_done(xid
, ses
->Suid
,
746 SMB2_set_info_free(&rqst
[num_rqst
++]);
748 case SMB2_OP_SET_REPARSE
:
750 trace_smb3_set_reparse_compound_err(xid
, ses
->Suid
,
753 trace_smb3_set_reparse_compound_done(xid
, ses
->Suid
,
756 SMB2_ioctl_free(&rqst
[num_rqst
++]);
758 case SMB2_OP_GET_REPARSE
:
760 iov
= &rsp_iov
[i
+ 1];
761 idata
= in_iov
[i
].iov_base
;
762 idata
->reparse
.io
.iov
= *iov
;
763 idata
->reparse
.io
.buftype
= resp_buftype
[i
+ 1];
764 rbuf
= reparse_buf_ptr(iov
);
767 trace_smb3_set_reparse_compound_err(xid
, ses
->Suid
,
770 idata
->reparse
.tag
= le32_to_cpu(rbuf
->ReparseTag
);
771 trace_smb3_set_reparse_compound_done(xid
, ses
->Suid
,
774 memset(iov
, 0, sizeof(*iov
));
775 resp_buftype
[i
+ 1] = CIFS_NO_BUFFER
;
777 trace_smb3_set_reparse_compound_err(xid
, ses
->Suid
,
780 SMB2_ioctl_free(&rqst
[num_rqst
++]);
782 case SMB2_OP_QUERY_WSL_EA
:
784 idata
= in_iov
[i
].iov_base
;
785 qi_rsp
= rsp_iov
[i
+ 1].iov_base
;
786 data
[0] = (u8
*)qi_rsp
+ le16_to_cpu(qi_rsp
->OutputBufferOffset
);
787 size
[0] = le32_to_cpu(qi_rsp
->OutputBufferLength
);
788 rc
= check_wsl_eas(&rsp_iov
[i
+ 1]);
790 memcpy(idata
->wsl
.eas
, data
[0], size
[0]);
791 idata
->wsl
.eas_len
= size
[0];
795 trace_smb3_query_wsl_ea_compound_done(xid
, ses
->Suid
,
798 trace_smb3_query_wsl_ea_compound_err(xid
, ses
->Suid
,
801 SMB2_query_info_free(&rqst
[num_rqst
++]);
805 SMB2_close_free(&rqst
[num_rqst
]);
808 if (out_iov
&& out_buftype
) {
809 memcpy(out_iov
, rsp_iov
, num_cmds
* sizeof(*out_iov
));
810 memcpy(out_buftype
, resp_buftype
,
811 num_cmds
* sizeof(*out_buftype
));
813 for (i
= 0; i
< num_cmds
; i
++)
814 free_rsp_buf(resp_buftype
[i
], rsp_iov
[i
].iov_base
);
816 num_cmds
-= 2; /* correct num_cmds as there could be a retry */
819 if (is_replayable_error(rc
) &&
820 smb2_should_replay(tcon
, &retries
, &cur_sleep
))
824 cifsFileInfo_put(cfile
);
829 static int parse_create_response(struct cifs_open_info_data
*data
,
830 struct cifs_sb_info
*cifs_sb
,
831 const char *full_path
,
832 const struct kvec
*iov
)
834 struct smb2_create_rsp
*rsp
= iov
->iov_base
;
835 bool reparse_point
= false;
839 switch (rsp
->hdr
.Status
) {
840 case STATUS_IO_REPARSE_TAG_NOT_HANDLED
:
841 reparse_point
= true;
843 case STATUS_STOPPED_ON_SYMLINK
:
844 rc
= smb2_parse_symlink_response(cifs_sb
, iov
,
846 &data
->symlink_target
);
849 tag
= IO_REPARSE_TAG_SYMLINK
;
850 reparse_point
= true;
853 reparse_point
= !!(rsp
->Flags
& SMB2_CREATE_FLAG_REPARSEPOINT
);
856 data
->reparse_point
= reparse_point
;
857 data
->reparse
.tag
= tag
;
861 int smb2_query_path_info(const unsigned int xid
,
862 struct cifs_tcon
*tcon
,
863 struct cifs_sb_info
*cifs_sb
,
864 const char *full_path
,
865 struct cifs_open_info_data
*data
)
867 struct cifs_open_parms oparms
;
868 __u32 create_options
= 0;
869 struct cifsFileInfo
*cfile
;
870 struct cached_fid
*cfid
= NULL
;
871 struct smb2_hdr
*hdr
;
872 struct kvec in_iov
[3], out_iov
[3] = {};
873 int out_buftype
[3] = {};
879 data
->adjust_tz
= false;
880 data
->reparse_point
= false;
883 * BB TODO: Add support for using cached root handle in SMB3.1.1 POSIX.
884 * Create SMB2_query_posix_info worker function to do non-compounded
885 * query when we already have an open file handle for this. For now this
886 * is fast enough (always using the compounded version).
888 if (!tcon
->posix_extensions
) {
892 rc
= open_cached_dir(xid
, tcon
, full_path
,
893 cifs_sb
, false, &cfid
);
895 /* If it is a root and its handle is cached then use it */
897 if (cfid
->file_all_info_is_valid
) {
898 memcpy(&data
->fi
, &cfid
->file_all_info
,
901 rc
= SMB2_query_info(xid
, tcon
,
902 cfid
->fid
.persistent_fid
,
903 cfid
->fid
.volatile_fid
,
906 close_cached_dir(cfid
);
909 cmds
[num_cmds
++] = SMB2_OP_QUERY_INFO
;
911 cmds
[num_cmds
++] = SMB2_OP_POSIX_QUERY_INFO
;
914 in_iov
[0].iov_base
= data
;
915 in_iov
[0].iov_len
= sizeof(*data
);
916 in_iov
[1] = in_iov
[0];
917 in_iov
[2] = in_iov
[0];
919 cifs_get_readable_path(tcon
, full_path
, &cfile
);
920 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, full_path
, FILE_READ_ATTRIBUTES
,
921 FILE_OPEN
, create_options
, ACL_NO_MODE
);
922 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
, full_path
,
923 &oparms
, in_iov
, cmds
, num_cmds
,
924 cfile
, out_iov
, out_buftype
, NULL
);
925 hdr
= out_iov
[0].iov_base
;
927 * If first iov is unset, then SMB session was dropped or we've got a
928 * cached open file (@cfile).
930 if (!hdr
|| out_buftype
[0] == CIFS_NO_BUFFER
)
935 rc
= parse_create_response(data
, cifs_sb
, full_path
, &out_iov
[0]);
939 * BB TODO: When support for special files added to Samba
940 * re-verify this path.
942 rc
= parse_create_response(data
, cifs_sb
, full_path
, &out_iov
[0]);
943 if (rc
|| !data
->reparse_point
)
946 cmds
[num_cmds
++] = SMB2_OP_QUERY_WSL_EA
;
948 * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
951 if (data
->reparse
.tag
!= IO_REPARSE_TAG_SYMLINK
)
952 cmds
[num_cmds
++] = SMB2_OP_GET_REPARSE
;
954 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, full_path
,
955 FILE_READ_ATTRIBUTES
|
956 FILE_READ_EA
| SYNCHRONIZE
,
957 FILE_OPEN
, create_options
|
958 OPEN_REPARSE_POINT
, ACL_NO_MODE
);
959 cifs_get_readable_path(tcon
, full_path
, &cfile
);
960 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
, full_path
,
961 &oparms
, in_iov
, cmds
, num_cmds
,
962 cfile
, NULL
, NULL
, NULL
);
967 if (hdr
->Status
!= STATUS_OBJECT_NAME_INVALID
)
969 rc2
= cifs_inval_name_dfs_link_error(xid
, tcon
, cifs_sb
,
980 for (i
= 0; i
< ARRAY_SIZE(out_buftype
); i
++)
981 free_rsp_buf(out_buftype
[i
], out_iov
[i
].iov_base
);
986 smb2_mkdir(const unsigned int xid
, struct inode
*parent_inode
, umode_t mode
,
987 struct cifs_tcon
*tcon
, const char *name
,
988 struct cifs_sb_info
*cifs_sb
)
990 struct cifs_open_parms oparms
;
992 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, name
, FILE_WRITE_ATTRIBUTES
,
993 FILE_CREATE
, CREATE_NOT_FILE
, mode
);
994 return smb2_compound_op(xid
, tcon
, cifs_sb
,
996 &(int){SMB2_OP_MKDIR
}, 1,
997 NULL
, NULL
, NULL
, NULL
);
1001 smb2_mkdir_setinfo(struct inode
*inode
, const char *name
,
1002 struct cifs_sb_info
*cifs_sb
, struct cifs_tcon
*tcon
,
1003 const unsigned int xid
)
1005 struct cifs_open_parms oparms
;
1006 FILE_BASIC_INFO data
= {};
1007 struct cifsInodeInfo
*cifs_i
;
1008 struct cifsFileInfo
*cfile
;
1013 in_iov
.iov_base
= &data
;
1014 in_iov
.iov_len
= sizeof(data
);
1015 cifs_i
= CIFS_I(inode
);
1016 dosattrs
= cifs_i
->cifsAttrs
| ATTR_READONLY
;
1017 data
.Attributes
= cpu_to_le32(dosattrs
);
1018 cifs_get_writable_path(tcon
, name
, FIND_WR_ANY
, &cfile
);
1019 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, name
, FILE_WRITE_ATTRIBUTES
,
1020 FILE_CREATE
, CREATE_NOT_FILE
, ACL_NO_MODE
);
1021 tmprc
= smb2_compound_op(xid
, tcon
, cifs_sb
, name
,
1023 &(int){SMB2_OP_SET_INFO
}, 1,
1024 cfile
, NULL
, NULL
, NULL
);
1026 cifs_i
->cifsAttrs
= dosattrs
;
1030 smb2_rmdir(const unsigned int xid
, struct cifs_tcon
*tcon
, const char *name
,
1031 struct cifs_sb_info
*cifs_sb
)
1033 struct cifs_open_parms oparms
;
1035 drop_cached_dir_by_name(xid
, tcon
, name
, cifs_sb
);
1036 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, name
, DELETE
,
1037 FILE_OPEN
, CREATE_NOT_FILE
, ACL_NO_MODE
);
1038 return smb2_compound_op(xid
, tcon
, cifs_sb
,
1039 name
, &oparms
, NULL
,
1040 &(int){SMB2_OP_RMDIR
}, 1,
1041 NULL
, NULL
, NULL
, NULL
);
1045 smb2_unlink(const unsigned int xid
, struct cifs_tcon
*tcon
, const char *name
,
1046 struct cifs_sb_info
*cifs_sb
, struct dentry
*dentry
)
1048 struct cifs_open_parms oparms
;
1050 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, name
,
1052 CREATE_DELETE_ON_CLOSE
| OPEN_REPARSE_POINT
,
1054 int rc
= smb2_compound_op(xid
, tcon
, cifs_sb
, name
, &oparms
,
1055 NULL
, &(int){SMB2_OP_DELETE
}, 1,
1056 NULL
, NULL
, NULL
, dentry
);
1057 if (rc
== -EINVAL
) {
1058 cifs_dbg(FYI
, "invalid lease key, resending request without lease");
1059 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
, name
, &oparms
,
1060 NULL
, &(int){SMB2_OP_DELETE
}, 1,
1061 NULL
, NULL
, NULL
, NULL
);
1066 static int smb2_set_path_attr(const unsigned int xid
, struct cifs_tcon
*tcon
,
1067 const char *from_name
, const char *to_name
,
1068 struct cifs_sb_info
*cifs_sb
,
1069 __u32 create_options
, __u32 access
,
1070 int command
, struct cifsFileInfo
*cfile
,
1071 struct dentry
*dentry
)
1073 struct cifs_open_parms oparms
;
1075 __le16
*smb2_to_name
= NULL
;
1078 smb2_to_name
= cifs_convert_path_to_utf16(to_name
, cifs_sb
);
1079 if (smb2_to_name
== NULL
) {
1081 goto smb2_rename_path
;
1083 in_iov
.iov_base
= smb2_to_name
;
1084 in_iov
.iov_len
= 2 * UniStrnlen((wchar_t *)smb2_to_name
, PATH_MAX
);
1085 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, from_name
, access
, FILE_OPEN
,
1086 create_options
, ACL_NO_MODE
);
1087 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
, from_name
,
1088 &oparms
, &in_iov
, &command
, 1,
1089 cfile
, NULL
, NULL
, dentry
);
1091 kfree(smb2_to_name
);
1095 int smb2_rename_path(const unsigned int xid
,
1096 struct cifs_tcon
*tcon
,
1097 struct dentry
*source_dentry
,
1098 const char *from_name
, const char *to_name
,
1099 struct cifs_sb_info
*cifs_sb
)
1101 struct cifsFileInfo
*cfile
;
1102 __u32 co
= file_create_options(source_dentry
);
1104 drop_cached_dir_by_name(xid
, tcon
, from_name
, cifs_sb
);
1105 cifs_get_writable_path(tcon
, from_name
, FIND_WR_WITH_DELETE
, &cfile
);
1107 int rc
= smb2_set_path_attr(xid
, tcon
, from_name
, to_name
, cifs_sb
,
1108 co
, DELETE
, SMB2_OP_RENAME
, cfile
, source_dentry
);
1109 if (rc
== -EINVAL
) {
1110 cifs_dbg(FYI
, "invalid lease key, resending request without lease");
1111 cifs_get_writable_path(tcon
, from_name
,
1112 FIND_WR_WITH_DELETE
, &cfile
);
1113 rc
= smb2_set_path_attr(xid
, tcon
, from_name
, to_name
, cifs_sb
,
1114 co
, DELETE
, SMB2_OP_RENAME
, cfile
, NULL
);
1119 int smb2_create_hardlink(const unsigned int xid
,
1120 struct cifs_tcon
*tcon
,
1121 struct dentry
*source_dentry
,
1122 const char *from_name
, const char *to_name
,
1123 struct cifs_sb_info
*cifs_sb
)
1125 __u32 co
= file_create_options(source_dentry
);
1127 return smb2_set_path_attr(xid
, tcon
, from_name
, to_name
,
1128 cifs_sb
, co
, FILE_READ_ATTRIBUTES
,
1129 SMB2_OP_HARDLINK
, NULL
, NULL
);
1133 smb2_set_path_size(const unsigned int xid
, struct cifs_tcon
*tcon
,
1134 const char *full_path
, __u64 size
,
1135 struct cifs_sb_info
*cifs_sb
, bool set_alloc
,
1136 struct dentry
*dentry
)
1138 struct cifs_open_parms oparms
;
1139 struct cifsFileInfo
*cfile
;
1141 __le64 eof
= cpu_to_le64(size
);
1144 in_iov
.iov_base
= &eof
;
1145 in_iov
.iov_len
= sizeof(eof
);
1146 cifs_get_writable_path(tcon
, full_path
, FIND_WR_ANY
, &cfile
);
1148 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, full_path
, FILE_WRITE_DATA
,
1149 FILE_OPEN
, 0, ACL_NO_MODE
);
1150 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
,
1151 full_path
, &oparms
, &in_iov
,
1152 &(int){SMB2_OP_SET_EOF
}, 1,
1153 cfile
, NULL
, NULL
, dentry
);
1154 if (rc
== -EINVAL
) {
1155 cifs_dbg(FYI
, "invalid lease key, resending request without lease");
1156 cifs_get_writable_path(tcon
, full_path
, FIND_WR_ANY
, &cfile
);
1157 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
,
1158 full_path
, &oparms
, &in_iov
,
1159 &(int){SMB2_OP_SET_EOF
}, 1,
1160 cfile
, NULL
, NULL
, NULL
);
1166 smb2_set_file_info(struct inode
*inode
, const char *full_path
,
1167 FILE_BASIC_INFO
*buf
, const unsigned int xid
)
1169 struct cifs_open_parms oparms
;
1170 struct cifs_sb_info
*cifs_sb
= CIFS_SB(inode
->i_sb
);
1171 struct tcon_link
*tlink
;
1172 struct cifs_tcon
*tcon
;
1173 struct cifsFileInfo
*cfile
;
1174 struct kvec in_iov
= { .iov_base
= buf
, .iov_len
= sizeof(*buf
), };
1177 if ((buf
->CreationTime
== 0) && (buf
->LastAccessTime
== 0) &&
1178 (buf
->LastWriteTime
== 0) && (buf
->ChangeTime
== 0) &&
1179 (buf
->Attributes
== 0))
1180 return 0; /* would be a no op, no sense sending this */
1182 tlink
= cifs_sb_tlink(cifs_sb
);
1184 return PTR_ERR(tlink
);
1185 tcon
= tlink_tcon(tlink
);
1187 cifs_get_writable_path(tcon
, full_path
, FIND_WR_ANY
, &cfile
);
1188 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, full_path
, FILE_WRITE_ATTRIBUTES
,
1189 FILE_OPEN
, 0, ACL_NO_MODE
);
1190 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
,
1191 full_path
, &oparms
, &in_iov
,
1192 &(int){SMB2_OP_SET_INFO
}, 1,
1193 cfile
, NULL
, NULL
, NULL
);
1194 cifs_put_tlink(tlink
);
1198 struct inode
*smb2_get_reparse_inode(struct cifs_open_info_data
*data
,
1199 struct super_block
*sb
,
1200 const unsigned int xid
,
1201 struct cifs_tcon
*tcon
,
1202 const char *full_path
,
1204 struct kvec
*reparse_iov
,
1205 struct kvec
*xattr_iov
)
1207 struct cifs_open_parms oparms
;
1208 struct cifs_sb_info
*cifs_sb
= CIFS_SB(sb
);
1209 struct cifsFileInfo
*cfile
;
1210 struct inode
*new = NULL
;
1211 int out_buftype
[4] = {};
1212 struct kvec out_iov
[4] = {};
1213 struct kvec in_iov
[2];
1218 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, full_path
,
1219 SYNCHRONIZE
| DELETE
|
1220 FILE_READ_ATTRIBUTES
|
1221 FILE_WRITE_ATTRIBUTES
,
1223 (directory
? CREATE_NOT_FILE
: CREATE_NOT_DIR
) | OPEN_REPARSE_POINT
,
1226 oparms
.ea_cctx
= xattr_iov
;
1228 cmds
[0] = SMB2_OP_SET_REPARSE
;
1229 in_iov
[0] = *reparse_iov
;
1230 in_iov
[1].iov_base
= data
;
1231 in_iov
[1].iov_len
= sizeof(*data
);
1233 if (tcon
->posix_extensions
) {
1234 cmds
[1] = SMB2_OP_POSIX_QUERY_INFO
;
1235 cifs_get_writable_path(tcon
, full_path
, FIND_WR_ANY
, &cfile
);
1236 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
, full_path
, &oparms
,
1237 in_iov
, cmds
, 2, cfile
, out_iov
, out_buftype
, NULL
);
1239 rc
= smb311_posix_get_inode_info(&new, full_path
,
1243 cmds
[1] = SMB2_OP_QUERY_INFO
;
1244 cifs_get_writable_path(tcon
, full_path
, FIND_WR_ANY
, &cfile
);
1245 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
, full_path
, &oparms
,
1246 in_iov
, cmds
, 2, cfile
, out_iov
, out_buftype
, NULL
);
1248 rc
= cifs_get_inode_info(&new, full_path
,
1249 data
, sb
, xid
, NULL
);
1255 * If CREATE was successful but SMB2_OP_SET_REPARSE failed then
1256 * remove the intermediate object created by CREATE. Otherwise
1257 * empty object stay on the server when reparse call failed.
1260 out_iov
[0].iov_base
!= NULL
&& out_buftype
[0] != CIFS_NO_BUFFER
&&
1261 ((struct smb2_hdr
*)out_iov
[0].iov_base
)->Status
== STATUS_SUCCESS
&&
1262 (out_iov
[1].iov_base
== NULL
|| out_buftype
[1] == CIFS_NO_BUFFER
||
1263 ((struct smb2_hdr
*)out_iov
[1].iov_base
)->Status
!= STATUS_SUCCESS
))
1264 smb2_unlink(xid
, tcon
, full_path
, cifs_sb
, NULL
);
1266 for (i
= 0; i
< ARRAY_SIZE(out_buftype
); i
++)
1267 free_rsp_buf(out_buftype
[i
], out_iov
[i
].iov_base
);
1269 return rc
? ERR_PTR(rc
) : new;
1272 int smb2_query_reparse_point(const unsigned int xid
,
1273 struct cifs_tcon
*tcon
,
1274 struct cifs_sb_info
*cifs_sb
,
1275 const char *full_path
,
1276 u32
*tag
, struct kvec
*rsp
,
1279 struct cifs_open_parms oparms
;
1280 struct cifs_open_info_data data
= {};
1281 struct cifsFileInfo
*cfile
;
1282 struct kvec in_iov
= { .iov_base
= &data
, .iov_len
= sizeof(data
), };
1285 cifs_dbg(FYI
, "%s: path: %s\n", __func__
, full_path
);
1287 cifs_get_readable_path(tcon
, full_path
, &cfile
);
1288 oparms
= CIFS_OPARMS(cifs_sb
, tcon
, full_path
,
1289 FILE_READ_ATTRIBUTES
| FILE_READ_EA
| SYNCHRONIZE
,
1290 FILE_OPEN
, OPEN_REPARSE_POINT
, ACL_NO_MODE
);
1291 rc
= smb2_compound_op(xid
, tcon
, cifs_sb
,
1292 full_path
, &oparms
, &in_iov
,
1293 &(int){SMB2_OP_GET_REPARSE
}, 1,
1294 cfile
, NULL
, NULL
, NULL
);
1298 *tag
= data
.reparse
.tag
;
1299 *rsp
= data
.reparse
.io
.iov
;
1300 *rsp_buftype
= data
.reparse
.io
.buftype
;
1301 memset(&data
.reparse
.io
.iov
, 0, sizeof(data
.reparse
.io
.iov
));
1302 data
.reparse
.io
.buftype
= CIFS_NO_BUFFER
;
1304 cifs_free_open_info(&data
);