1 // SPDX-License-Identifier: LGPL-2.1
4 * Copyright (C) International Business Machines Corp., 2002, 2011
5 * Author(s): Steve French (sfrench@us.ibm.com),
6 * Pavel Shilovsky ((pshilovsky@samba.org) 2012
10 #include <linux/filelock.h>
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"
23 #include "smb2proto.h"
24 #include "smb2status.h"
26 static struct smb2_symlink_err_rsp
*symlink_data(const struct kvec
*iov
)
28 struct smb2_err_rsp
*err
= iov
->iov_base
;
29 struct smb2_symlink_err_rsp
*sym
= ERR_PTR(-EINVAL
);
32 if (err
->ErrorContextCount
) {
33 struct smb2_error_context_rsp
*p
, *end
;
35 len
= (u32
)err
->ErrorContextCount
* (offsetof(struct smb2_error_context_rsp
,
37 sizeof(struct smb2_symlink_err_rsp
));
38 if (le32_to_cpu(err
->ByteCount
) < len
|| iov
->iov_len
< len
+ sizeof(*err
) + 1)
39 return ERR_PTR(-EINVAL
);
41 p
= (struct smb2_error_context_rsp
*)err
->ErrorData
;
42 end
= (struct smb2_error_context_rsp
*)((u8
*)err
+ iov
->iov_len
);
44 if (le32_to_cpu(p
->ErrorId
) == SMB2_ERROR_ID_DEFAULT
) {
45 sym
= (struct smb2_symlink_err_rsp
*)&p
->ErrorContextData
;
48 cifs_dbg(FYI
, "%s: skipping unhandled error context: 0x%x\n",
49 __func__
, le32_to_cpu(p
->ErrorId
));
51 len
= ALIGN(le32_to_cpu(p
->ErrorDataLength
), 8);
52 p
= (struct smb2_error_context_rsp
*)((u8
*)&p
->ErrorContextData
+ len
);
54 } else if (le32_to_cpu(err
->ByteCount
) >= sizeof(*sym
) &&
55 iov
->iov_len
>= SMB2_SYMLINK_STRUCT_SIZE
) {
56 sym
= (struct smb2_symlink_err_rsp
*)err
->ErrorData
;
59 if (!IS_ERR(sym
) && (le32_to_cpu(sym
->SymLinkErrorTag
) != SYMLINK_ERROR_TAG
||
60 le32_to_cpu(sym
->ReparseTag
) != IO_REPARSE_TAG_SYMLINK
))
61 sym
= ERR_PTR(-EINVAL
);
66 int smb2_parse_symlink_response(struct cifs_sb_info
*cifs_sb
, const struct kvec
*iov
, char **path
)
68 struct smb2_symlink_err_rsp
*sym
;
69 unsigned int sub_offs
, sub_len
;
70 unsigned int print_offs
, print_len
;
73 if (!cifs_sb
|| !iov
|| !iov
->iov_base
|| !iov
->iov_len
|| !path
)
76 sym
= symlink_data(iov
);
80 sub_len
= le16_to_cpu(sym
->SubstituteNameLength
);
81 sub_offs
= le16_to_cpu(sym
->SubstituteNameOffset
);
82 print_len
= le16_to_cpu(sym
->PrintNameLength
);
83 print_offs
= le16_to_cpu(sym
->PrintNameOffset
);
85 if (iov
->iov_len
< SMB2_SYMLINK_STRUCT_SIZE
+ sub_offs
+ sub_len
||
86 iov
->iov_len
< SMB2_SYMLINK_STRUCT_SIZE
+ print_offs
+ print_len
)
89 s
= cifs_strndup_from_utf16((char *)sym
->PathBuffer
+ sub_offs
, sub_len
, true,
93 convert_delimiter(s
, '/');
94 cifs_dbg(FYI
, "%s: symlink target: %s\n", __func__
, s
);
100 int smb2_open_file(const unsigned int xid
, struct cifs_open_parms
*oparms
, __u32
*oplock
, void *buf
)
105 struct cifs_open_info_data
*data
= buf
;
106 struct smb2_file_all_info file_info
= {};
107 struct smb2_file_all_info
*smb2_data
= data
? &file_info
: NULL
;
108 struct kvec err_iov
= {};
109 int err_buftype
= CIFS_NO_BUFFER
;
110 struct cifs_fid
*fid
= oparms
->fid
;
111 struct network_resiliency_req nr_ioctl_req
;
113 smb2_path
= cifs_convert_path_to_utf16(oparms
->path
, oparms
->cifs_sb
);
114 if (smb2_path
== NULL
)
117 oparms
->desired_access
|= FILE_READ_ATTRIBUTES
;
118 smb2_oplock
= SMB2_OPLOCK_LEVEL_BATCH
;
120 rc
= SMB2_open(xid
, oparms
, smb2_path
, &smb2_oplock
, smb2_data
, NULL
, &err_iov
,
123 struct smb2_hdr
*hdr
= err_iov
.iov_base
;
125 if (unlikely(!err_iov
.iov_base
|| err_buftype
== CIFS_NO_BUFFER
))
127 if (hdr
->Status
== STATUS_STOPPED_ON_SYMLINK
) {
128 rc
= smb2_parse_symlink_response(oparms
->cifs_sb
, &err_iov
,
129 &data
->symlink_target
);
131 memset(smb2_data
, 0, sizeof(*smb2_data
));
132 oparms
->create_options
|= OPEN_REPARSE_POINT
;
133 rc
= SMB2_open(xid
, oparms
, smb2_path
, &smb2_oplock
, smb2_data
,
135 oparms
->create_options
&= ~OPEN_REPARSE_POINT
;
143 if (oparms
->tcon
->use_resilient
) {
144 /* default timeout is 0, servers pick default (120 seconds) */
145 nr_ioctl_req
.Timeout
=
146 cpu_to_le32(oparms
->tcon
->handle_timeout
);
147 nr_ioctl_req
.Reserved
= 0;
148 rc
= SMB2_ioctl(xid
, oparms
->tcon
, fid
->persistent_fid
,
149 fid
->volatile_fid
, FSCTL_LMR_REQUEST_RESILIENCY
,
150 (char *)&nr_ioctl_req
, sizeof(nr_ioctl_req
),
151 CIFSMaxBufSize
, NULL
, NULL
/* no return info */);
152 if (rc
== -EOPNOTSUPP
) {
154 "resiliency not supported by server, disabling\n");
155 oparms
->tcon
->use_resilient
= false;
157 cifs_dbg(FYI
, "error %d setting resiliency\n", rc
);
163 /* if open response does not have IndexNumber field - get it */
164 if (smb2_data
->IndexNumber
== 0) {
165 rc
= SMB2_get_srv_num(xid
, oparms
->tcon
,
168 &smb2_data
->IndexNumber
);
171 * let get_inode_info disable server inode
174 smb2_data
->IndexNumber
= 0;
178 memcpy(&data
->fi
, smb2_data
, sizeof(data
->fi
));
181 *oplock
= smb2_oplock
;
183 free_rsp_buf(err_buftype
, err_iov
.iov_base
);
189 smb2_unlock_range(struct cifsFileInfo
*cfile
, struct file_lock
*flock
,
190 const unsigned int xid
)
192 int rc
= 0, stored_rc
;
193 unsigned int max_num
, num
= 0, max_buf
;
194 struct smb2_lock_element
*buf
, *cur
;
195 struct cifs_tcon
*tcon
= tlink_tcon(cfile
->tlink
);
196 struct cifsInodeInfo
*cinode
= CIFS_I(d_inode(cfile
->dentry
));
197 struct cifsLockInfo
*li
, *tmp
;
198 __u64 length
= 1 + flock
->fl_end
- flock
->fl_start
;
199 struct list_head tmp_llist
;
201 INIT_LIST_HEAD(&tmp_llist
);
204 * Accessing maxBuf is racy with cifs_reconnect - need to store value
205 * and check it before using.
207 max_buf
= tcon
->ses
->server
->maxBuf
;
208 if (max_buf
< sizeof(struct smb2_lock_element
))
211 BUILD_BUG_ON(sizeof(struct smb2_lock_element
) > PAGE_SIZE
);
212 max_buf
= min_t(unsigned int, max_buf
, PAGE_SIZE
);
213 max_num
= max_buf
/ sizeof(struct smb2_lock_element
);
214 buf
= kcalloc(max_num
, sizeof(struct smb2_lock_element
), GFP_KERNEL
);
220 cifs_down_write(&cinode
->lock_sem
);
221 list_for_each_entry_safe(li
, tmp
, &cfile
->llist
->locks
, llist
) {
222 if (flock
->fl_start
> li
->offset
||
223 (flock
->fl_start
+ length
) <
224 (li
->offset
+ li
->length
))
226 if (current
->tgid
!= li
->pid
)
228 * flock and OFD lock are associated with an open
229 * file description, not the process.
231 if (!(flock
->c
.flc_flags
& (FL_FLOCK
| FL_OFDLCK
)))
233 if (cinode
->can_cache_brlcks
) {
235 * We can cache brlock requests - simply remove a lock
236 * from the file's list.
238 list_del(&li
->llist
);
239 cifs_del_lock_waiters(li
);
243 cur
->Length
= cpu_to_le64(li
->length
);
244 cur
->Offset
= cpu_to_le64(li
->offset
);
245 cur
->Flags
= cpu_to_le32(SMB2_LOCKFLAG_UNLOCK
);
247 * We need to save a lock here to let us add it again to the
248 * file's list if the unlock range request fails on the server.
250 list_move(&li
->llist
, &tmp_llist
);
251 if (++num
== max_num
) {
252 stored_rc
= smb2_lockv(xid
, tcon
,
253 cfile
->fid
.persistent_fid
,
254 cfile
->fid
.volatile_fid
,
255 current
->tgid
, num
, buf
);
258 * We failed on the unlock range request - add
259 * all locks from the tmp list to the head of
262 cifs_move_llist(&tmp_llist
,
263 &cfile
->llist
->locks
);
267 * The unlock range request succeed - free the
270 cifs_free_llist(&tmp_llist
);
277 stored_rc
= smb2_lockv(xid
, tcon
, cfile
->fid
.persistent_fid
,
278 cfile
->fid
.volatile_fid
, current
->tgid
,
281 cifs_move_llist(&tmp_llist
, &cfile
->llist
->locks
);
284 cifs_free_llist(&tmp_llist
);
286 up_write(&cinode
->lock_sem
);
293 smb2_push_mand_fdlocks(struct cifs_fid_locks
*fdlocks
, const unsigned int xid
,
294 struct smb2_lock_element
*buf
, unsigned int max_num
)
296 int rc
= 0, stored_rc
;
297 struct cifsFileInfo
*cfile
= fdlocks
->cfile
;
298 struct cifsLockInfo
*li
;
299 unsigned int num
= 0;
300 struct smb2_lock_element
*cur
= buf
;
301 struct cifs_tcon
*tcon
= tlink_tcon(cfile
->tlink
);
303 list_for_each_entry(li
, &fdlocks
->locks
, llist
) {
304 cur
->Length
= cpu_to_le64(li
->length
);
305 cur
->Offset
= cpu_to_le64(li
->offset
);
306 cur
->Flags
= cpu_to_le32(li
->type
|
307 SMB2_LOCKFLAG_FAIL_IMMEDIATELY
);
308 if (++num
== max_num
) {
309 stored_rc
= smb2_lockv(xid
, tcon
,
310 cfile
->fid
.persistent_fid
,
311 cfile
->fid
.volatile_fid
,
312 current
->tgid
, num
, buf
);
321 stored_rc
= smb2_lockv(xid
, tcon
,
322 cfile
->fid
.persistent_fid
,
323 cfile
->fid
.volatile_fid
,
324 current
->tgid
, num
, buf
);
333 smb2_push_mandatory_locks(struct cifsFileInfo
*cfile
)
335 int rc
= 0, stored_rc
;
337 unsigned int max_num
, max_buf
;
338 struct smb2_lock_element
*buf
;
339 struct cifsInodeInfo
*cinode
= CIFS_I(d_inode(cfile
->dentry
));
340 struct cifs_fid_locks
*fdlocks
;
345 * Accessing maxBuf is racy with cifs_reconnect - need to store value
346 * and check it for zero before using.
348 max_buf
= tlink_tcon(cfile
->tlink
)->ses
->server
->maxBuf
;
349 if (max_buf
< sizeof(struct smb2_lock_element
)) {
354 BUILD_BUG_ON(sizeof(struct smb2_lock_element
) > PAGE_SIZE
);
355 max_buf
= min_t(unsigned int, max_buf
, PAGE_SIZE
);
356 max_num
= max_buf
/ sizeof(struct smb2_lock_element
);
357 buf
= kcalloc(max_num
, sizeof(struct smb2_lock_element
), GFP_KERNEL
);
363 list_for_each_entry(fdlocks
, &cinode
->llist
, llist
) {
364 stored_rc
= smb2_push_mand_fdlocks(fdlocks
, xid
, buf
, max_num
);