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 "../common/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
,
67 const char *full_path
, char **path
)
69 struct smb2_symlink_err_rsp
*sym
;
70 unsigned int sub_offs
, sub_len
;
71 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 return smb2_parse_native_symlink(path
,
90 (char *)sym
->PathBuffer
+ sub_offs
,
93 le32_to_cpu(sym
->Flags
) & SYMLINK_FLAG_RELATIVE
,
98 int smb2_open_file(const unsigned int xid
, struct cifs_open_parms
*oparms
, __u32
*oplock
, void *buf
)
103 struct cifs_open_info_data
*data
= buf
;
104 struct smb2_file_all_info file_info
= {};
105 struct smb2_file_all_info
*smb2_data
= data
? &file_info
: NULL
;
106 struct kvec err_iov
= {};
107 int err_buftype
= CIFS_NO_BUFFER
;
108 struct cifs_fid
*fid
= oparms
->fid
;
109 struct network_resiliency_req nr_ioctl_req
;
111 smb2_path
= cifs_convert_path_to_utf16(oparms
->path
, oparms
->cifs_sb
);
112 if (smb2_path
== NULL
)
115 oparms
->desired_access
|= FILE_READ_ATTRIBUTES
;
116 smb2_oplock
= SMB2_OPLOCK_LEVEL_BATCH
;
118 rc
= SMB2_open(xid
, oparms
, smb2_path
, &smb2_oplock
, smb2_data
, NULL
, &err_iov
,
121 struct smb2_hdr
*hdr
= err_iov
.iov_base
;
123 if (unlikely(!err_iov
.iov_base
|| err_buftype
== CIFS_NO_BUFFER
))
125 if (hdr
->Status
== STATUS_STOPPED_ON_SYMLINK
) {
126 rc
= smb2_parse_symlink_response(oparms
->cifs_sb
, &err_iov
,
128 &data
->symlink_target
);
130 memset(smb2_data
, 0, sizeof(*smb2_data
));
131 oparms
->create_options
|= OPEN_REPARSE_POINT
;
132 rc
= SMB2_open(xid
, oparms
, smb2_path
, &smb2_oplock
, smb2_data
,
134 oparms
->create_options
&= ~OPEN_REPARSE_POINT
;
142 if (oparms
->tcon
->use_resilient
) {
143 /* default timeout is 0, servers pick default (120 seconds) */
144 nr_ioctl_req
.Timeout
=
145 cpu_to_le32(oparms
->tcon
->handle_timeout
);
146 nr_ioctl_req
.Reserved
= 0;
147 rc
= SMB2_ioctl(xid
, oparms
->tcon
, fid
->persistent_fid
,
148 fid
->volatile_fid
, FSCTL_LMR_REQUEST_RESILIENCY
,
149 (char *)&nr_ioctl_req
, sizeof(nr_ioctl_req
),
150 CIFSMaxBufSize
, NULL
, NULL
/* no return info */);
151 if (rc
== -EOPNOTSUPP
) {
153 "resiliency not supported by server, disabling\n");
154 oparms
->tcon
->use_resilient
= false;
156 cifs_dbg(FYI
, "error %d setting resiliency\n", rc
);
162 /* if open response does not have IndexNumber field - get it */
163 if (smb2_data
->IndexNumber
== 0) {
164 rc
= SMB2_get_srv_num(xid
, oparms
->tcon
,
167 &smb2_data
->IndexNumber
);
170 * let get_inode_info disable server inode
173 smb2_data
->IndexNumber
= 0;
177 memcpy(&data
->fi
, smb2_data
, sizeof(data
->fi
));
180 *oplock
= smb2_oplock
;
182 free_rsp_buf(err_buftype
, err_iov
.iov_base
);
188 smb2_unlock_range(struct cifsFileInfo
*cfile
, struct file_lock
*flock
,
189 const unsigned int xid
)
191 int rc
= 0, stored_rc
;
192 unsigned int max_num
, num
= 0, max_buf
;
193 struct smb2_lock_element
*buf
, *cur
;
194 struct cifs_tcon
*tcon
= tlink_tcon(cfile
->tlink
);
195 struct cifsInodeInfo
*cinode
= CIFS_I(d_inode(cfile
->dentry
));
196 struct cifsLockInfo
*li
, *tmp
;
197 __u64 length
= 1 + flock
->fl_end
- flock
->fl_start
;
198 LIST_HEAD(tmp_llist
);
201 * Accessing maxBuf is racy with cifs_reconnect - need to store value
202 * and check it before using.
204 max_buf
= tcon
->ses
->server
->maxBuf
;
205 if (max_buf
< sizeof(struct smb2_lock_element
))
208 BUILD_BUG_ON(sizeof(struct smb2_lock_element
) > PAGE_SIZE
);
209 max_buf
= min_t(unsigned int, max_buf
, PAGE_SIZE
);
210 max_num
= max_buf
/ sizeof(struct smb2_lock_element
);
211 buf
= kcalloc(max_num
, sizeof(struct smb2_lock_element
), GFP_KERNEL
);
217 cifs_down_write(&cinode
->lock_sem
);
218 list_for_each_entry_safe(li
, tmp
, &cfile
->llist
->locks
, llist
) {
219 if (flock
->fl_start
> li
->offset
||
220 (flock
->fl_start
+ length
) <
221 (li
->offset
+ li
->length
))
223 if (current
->tgid
!= li
->pid
)
225 * flock and OFD lock are associated with an open
226 * file description, not the process.
228 if (!(flock
->c
.flc_flags
& (FL_FLOCK
| FL_OFDLCK
)))
230 if (cinode
->can_cache_brlcks
) {
232 * We can cache brlock requests - simply remove a lock
233 * from the file's list.
235 list_del(&li
->llist
);
236 cifs_del_lock_waiters(li
);
240 cur
->Length
= cpu_to_le64(li
->length
);
241 cur
->Offset
= cpu_to_le64(li
->offset
);
242 cur
->Flags
= cpu_to_le32(SMB2_LOCKFLAG_UNLOCK
);
244 * We need to save a lock here to let us add it again to the
245 * file's list if the unlock range request fails on the server.
247 list_move(&li
->llist
, &tmp_llist
);
248 if (++num
== max_num
) {
249 stored_rc
= smb2_lockv(xid
, tcon
,
250 cfile
->fid
.persistent_fid
,
251 cfile
->fid
.volatile_fid
,
252 current
->tgid
, num
, buf
);
255 * We failed on the unlock range request - add
256 * all locks from the tmp list to the head of
259 cifs_move_llist(&tmp_llist
,
260 &cfile
->llist
->locks
);
264 * The unlock range request succeed - free the
267 cifs_free_llist(&tmp_llist
);
274 stored_rc
= smb2_lockv(xid
, tcon
, cfile
->fid
.persistent_fid
,
275 cfile
->fid
.volatile_fid
, current
->tgid
,
278 cifs_move_llist(&tmp_llist
, &cfile
->llist
->locks
);
281 cifs_free_llist(&tmp_llist
);
283 up_write(&cinode
->lock_sem
);
290 smb2_push_mand_fdlocks(struct cifs_fid_locks
*fdlocks
, const unsigned int xid
,
291 struct smb2_lock_element
*buf
, unsigned int max_num
)
293 int rc
= 0, stored_rc
;
294 struct cifsFileInfo
*cfile
= fdlocks
->cfile
;
295 struct cifsLockInfo
*li
;
296 unsigned int num
= 0;
297 struct smb2_lock_element
*cur
= buf
;
298 struct cifs_tcon
*tcon
= tlink_tcon(cfile
->tlink
);
300 list_for_each_entry(li
, &fdlocks
->locks
, llist
) {
301 cur
->Length
= cpu_to_le64(li
->length
);
302 cur
->Offset
= cpu_to_le64(li
->offset
);
303 cur
->Flags
= cpu_to_le32(li
->type
|
304 SMB2_LOCKFLAG_FAIL_IMMEDIATELY
);
305 if (++num
== max_num
) {
306 stored_rc
= smb2_lockv(xid
, tcon
,
307 cfile
->fid
.persistent_fid
,
308 cfile
->fid
.volatile_fid
,
309 current
->tgid
, num
, buf
);
318 stored_rc
= smb2_lockv(xid
, tcon
,
319 cfile
->fid
.persistent_fid
,
320 cfile
->fid
.volatile_fid
,
321 current
->tgid
, num
, buf
);
330 smb2_push_mandatory_locks(struct cifsFileInfo
*cfile
)
332 int rc
= 0, stored_rc
;
334 unsigned int max_num
, max_buf
;
335 struct smb2_lock_element
*buf
;
336 struct cifsInodeInfo
*cinode
= CIFS_I(d_inode(cfile
->dentry
));
337 struct cifs_fid_locks
*fdlocks
;
342 * Accessing maxBuf is racy with cifs_reconnect - need to store value
343 * and check it for zero before using.
345 max_buf
= tlink_tcon(cfile
->tlink
)->ses
->server
->maxBuf
;
346 if (max_buf
< sizeof(struct smb2_lock_element
)) {
351 BUILD_BUG_ON(sizeof(struct smb2_lock_element
) > PAGE_SIZE
);
352 max_buf
= min_t(unsigned int, max_buf
, PAGE_SIZE
);
353 max_num
= max_buf
/ sizeof(struct smb2_lock_element
);
354 buf
= kcalloc(max_num
, sizeof(struct smb2_lock_element
), GFP_KERNEL
);
360 list_for_each_entry(fdlocks
, &cinode
->llist
, llist
) {
361 stored_rc
= smb2_push_mand_fdlocks(fdlocks
, xid
, buf
, max_num
);