]> git.ipfire.org Git - people/ms/linux.git/blame - fs/cifsd/vfs.c
cifsd: check return value of ksmbd_vfs_getcasexattr() correctly
[people/ms/linux.git] / fs / cifsd / vfs.c
CommitLineData
f4415848
NJ
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
4 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
5 */
6
7#include <linux/kernel.h>
8#include <linux/fs.h>
9#include <linux/uaccess.h>
10#include <linux/backing-dev.h>
11#include <linux/writeback.h>
f4415848
NJ
12#include <linux/xattr.h>
13#include <linux/falloc.h>
14#include <linux/genhd.h>
15#include <linux/blkdev.h>
16#include <linux/fsnotify.h>
17#include <linux/dcache.h>
18#include <linux/slab.h>
19#include <linux/vmalloc.h>
20#include <linux/sched/xacct.h>
21#include <linux/crc32c.h>
22
23#include "glob.h"
24#include "oplock.h"
25#include "connection.h"
26#include "buffer_pool.h"
27#include "vfs.h"
28#include "vfs_cache.h"
29#include "smbacl.h"
30#include "ndr.h"
31#include "auth.h"
5626518e 32#include "misc.h"
f4415848 33
f4415848
NJ
34#include "smb_common.h"
35#include "mgmt/share_config.h"
36#include "mgmt/tree_connect.h"
37#include "mgmt/user_session.h"
38#include "mgmt/user_config.h"
39
40static char *extract_last_component(char *path)
41{
42 char *p = strrchr(path, '/');
43
44 if (p && p[1] != '\0') {
45 *p = '\0';
46 p++;
47 } else {
48 p = NULL;
49 ksmbd_err("Invalid path %s\n", path);
50 }
51 return p;
52}
53
f4415848 54static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
070fb21e
NJ
55 struct inode *parent_inode,
56 struct inode *inode)
f4415848
NJ
57{
58 if (!test_share_config_flag(work->tcon->share_conf,
64b39f4a 59 KSMBD_SHARE_FLAG_INHERIT_OWNER))
f4415848
NJ
60 return;
61
62 i_uid_write(inode, i_uid_read(parent_inode));
63}
64
f4415848
NJ
65int ksmbd_vfs_inode_permission(struct dentry *dentry, int acc_mode, bool delete)
66{
ff1d5727 67 int mask, ret = 0;
f4415848
NJ
68
69 mask = 0;
70 acc_mode &= O_ACCMODE;
71
72 if (acc_mode == O_RDONLY)
73 mask = MAY_READ;
74 else if (acc_mode == O_WRONLY)
75 mask = MAY_WRITE;
76 else if (acc_mode == O_RDWR)
77 mask = MAY_READ | MAY_WRITE;
78
79 if (inode_permission(&init_user_ns, d_inode(dentry), mask | MAY_OPEN))
80 return -EACCES;
81
82 if (delete) {
ff1d5727 83 struct dentry *child, *parent;
f4415848
NJ
84
85 parent = dget_parent(dentry);
ff1d5727
NJ
86 inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
87 child = lookup_one_len(dentry->d_name.name, parent,
070fb21e 88 dentry->d_name.len);
ff1d5727
NJ
89 if (IS_ERR(child)) {
90 ret = PTR_ERR(child);
91 goto out_lock;
92 }
93
94 if (child != dentry) {
95 ret = -ESTALE;
96 dput(child);
97 goto out_lock;
98 }
99 dput(child);
f4415848
NJ
100
101 if (inode_permission(&init_user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE)) {
ff1d5727
NJ
102 ret = -EACCES;
103 goto out_lock;
f4415848 104 }
ff1d5727
NJ
105out_lock:
106 inode_unlock(d_inode(parent));
f4415848
NJ
107 dput(parent);
108 }
ff1d5727 109 return ret;
f4415848
NJ
110}
111
112int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess)
113{
ff1d5727
NJ
114 struct dentry *parent, *child;
115 int ret = 0;
f4415848
NJ
116
117 *daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL);
118
119 if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_WRITE))
120 *daccess |= cpu_to_le32(WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
121 FILE_WRITE_DATA | FILE_APPEND_DATA |
122 FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES |
123 FILE_DELETE_CHILD);
124
125 if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_READ))
126 *daccess |= FILE_READ_DATA_LE | FILE_READ_EA_LE;
127
128 if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_EXEC))
129 *daccess |= FILE_EXECUTE_LE;
130
131 parent = dget_parent(dentry);
ff1d5727
NJ
132 inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
133 child = lookup_one_len(dentry->d_name.name, parent,
070fb21e 134 dentry->d_name.len);
ff1d5727
NJ
135 if (IS_ERR(child)) {
136 ret = PTR_ERR(child);
137 goto out_lock;
138 }
139
140 if (child != dentry) {
141 ret = -ESTALE;
142 dput(child);
143 goto out_lock;
144 }
145 dput(child);
f4415848
NJ
146
147 if (!inode_permission(&init_user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE))
148 *daccess |= FILE_DELETE_LE;
ff1d5727
NJ
149
150out_lock:
151 inode_unlock(d_inode(parent));
f4415848 152 dput(parent);
ff1d5727 153 return ret;
f4415848
NJ
154}
155
f4415848
NJ
156/**
157 * ksmbd_vfs_create() - vfs helper for smb create file
158 * @work: work
159 * @name: file name
160 * @mode: file create mode
161 *
162 * Return: 0 on success, otherwise error
163 */
64b39f4a 164int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
f4415848
NJ
165{
166 struct path path;
167 struct dentry *dentry;
168 int err;
169
170 dentry = kern_path_create(AT_FDCWD, name, &path, 0);
171 if (IS_ERR(dentry)) {
172 err = PTR_ERR(dentry);
173 if (err != -ENOENT)
174 ksmbd_err("path create failed for %s, err %d\n",
070fb21e 175 name, err);
f4415848
NJ
176 return err;
177 }
178
179 mode |= S_IFREG;
180 err = vfs_create(&init_user_ns, d_inode(path.dentry), dentry, mode, true);
181 if (!err) {
182 ksmbd_vfs_inherit_owner(work, d_inode(path.dentry),
070fb21e 183 d_inode(dentry));
f4415848
NJ
184 } else {
185 ksmbd_err("File(%s): creation failed (err:%d)\n", name, err);
186 }
187 done_path_create(&path, dentry);
188 return err;
189}
190
191/**
192 * ksmbd_vfs_mkdir() - vfs helper for smb create directory
193 * @work: work
194 * @name: directory name
195 * @mode: directory create mode
196 *
197 * Return: 0 on success, otherwise error
198 */
64b39f4a 199int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
f4415848
NJ
200{
201 struct path path;
202 struct dentry *dentry;
203 int err;
204
205 dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
206 if (IS_ERR(dentry)) {
207 err = PTR_ERR(dentry);
208 if (err != -EEXIST)
209 ksmbd_debug(VFS, "path create failed for %s, err %d\n",
070fb21e 210 name, err);
f4415848
NJ
211 return err;
212 }
213
214 mode |= S_IFDIR;
215 err = vfs_mkdir(&init_user_ns, d_inode(path.dentry), dentry, mode);
a2d6321b 216 if (err) {
16370235 217 goto out;
a2d6321b 218 } else if (d_unhashed(dentry)) {
16370235
HL
219 struct dentry *d;
220
070fb21e
NJ
221 d = lookup_one_len(dentry->d_name.name, dentry->d_parent,
222 dentry->d_name.len);
16370235
HL
223 if (IS_ERR(d)) {
224 err = PTR_ERR(d);
225 goto out;
226 }
227 if (unlikely(d_is_negative(d))) {
228 dput(d);
229 err = -ENOENT;
230 goto out;
231 }
232
070fb21e 233 ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(d));
16370235 234 dput(d);
64b39f4a 235 }
16370235 236out:
f4415848 237 done_path_create(&path, dentry);
16370235
HL
238 if (err)
239 ksmbd_err("mkdir(%s): creation failed (err:%d)\n", name, err);
f4415848
NJ
240 return err;
241}
242
64b39f4a 243static ssize_t ksmbd_vfs_getcasexattr(struct dentry *dentry, char *attr_name,
070fb21e 244 int attr_name_len, char **attr_value)
f4415848
NJ
245{
246 char *name, *xattr_list = NULL;
247 ssize_t value_len = -ENOENT, xattr_list_len;
248
249 xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
250 if (xattr_list_len <= 0)
251 goto out;
252
253 for (name = xattr_list; name - xattr_list < xattr_list_len;
254 name += strlen(name) + 1) {
255 ksmbd_debug(VFS, "%s, len %zd\n", name, strlen(name));
256 if (strncasecmp(attr_name, name, attr_name_len))
257 continue;
258
259 value_len = ksmbd_vfs_getxattr(dentry,
260 name,
261 attr_value);
262 if (value_len < 0)
263 ksmbd_err("failed to get xattr in file\n");
264 break;
265 }
266
267out:
79f6b11a 268 kvfree(xattr_list);
f4415848
NJ
269 return value_len;
270}
271
272static int ksmbd_vfs_stream_read(struct ksmbd_file *fp, char *buf, loff_t *pos,
070fb21e 273 size_t count)
f4415848
NJ
274{
275 ssize_t v_len;
276 char *stream_buf = NULL;
f4415848
NJ
277
278 ksmbd_debug(VFS, "read stream data pos : %llu, count : %zd\n",
070fb21e 279 *pos, count);
f4415848
NJ
280
281 v_len = ksmbd_vfs_getcasexattr(fp->filp->f_path.dentry,
282 fp->stream.name,
283 fp->stream.size,
284 &stream_buf);
fd6de099
YY
285 if ((int)v_len <= 0)
286 return (int)v_len;
f4415848
NJ
287
288 memcpy(buf, &stream_buf[*pos], count);
673b9ba7 289 kvfree(stream_buf);
f4415848
NJ
290 return v_len > count ? count : v_len;
291}
292
293/**
294 * check_lock_range() - vfs helper for smb byte range file locking
295 * @filp: the file to apply the lock to
296 * @start: lock start byte offset
297 * @end: lock end byte offset
298 * @type: byte range type read/write
299 *
300 * Return: 0 on success, otherwise error
301 */
64b39f4a 302static int check_lock_range(struct file *filp, loff_t start, loff_t end,
070fb21e 303 unsigned char type)
f4415848
NJ
304{
305 struct file_lock *flock;
306 struct file_lock_context *ctx = file_inode(filp)->i_flctx;
307 int error = 0;
308
309 if (!ctx || list_empty_careful(&ctx->flc_posix))
310 return 0;
311
312 spin_lock(&ctx->flc_lock);
313 list_for_each_entry(flock, &ctx->flc_posix, fl_list) {
314 /* check conflict locks */
315 if (flock->fl_end >= start && end >= flock->fl_start) {
316 if (flock->fl_type == F_RDLCK) {
317 if (type == WRITE) {
318 ksmbd_err("not allow write by shared lock\n");
319 error = 1;
320 goto out;
321 }
322 } else if (flock->fl_type == F_WRLCK) {
323 /* check owner in lock */
324 if (flock->fl_file != filp) {
325 error = 1;
326 ksmbd_err("not allow rw access by exclusive lock from other opens\n");
327 goto out;
328 }
329 }
330 }
331 }
332out:
333 spin_unlock(&ctx->flc_lock);
334 return error;
335}
336
337/**
338 * ksmbd_vfs_read() - vfs helper for smb file read
339 * @work: smb work
340 * @fid: file id of open file
341 * @count: read byte count
342 * @pos: file pos
343 *
344 * Return: number of read bytes on success, otherwise error
345 */
64b39f4a 346int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
070fb21e 347 loff_t *pos)
f4415848
NJ
348{
349 struct file *filp;
350 ssize_t nbytes = 0;
96a34377 351 char *rbuf;
f4415848 352 struct inode *inode;
f4415848 353
e5066499 354 rbuf = work->aux_payload_buf;
f4415848 355 filp = fp->filp;
d2f72ed8 356 inode = file_inode(filp);
f4415848
NJ
357 if (S_ISDIR(inode->i_mode))
358 return -EISDIR;
359
360 if (unlikely(count == 0))
361 return 0;
362
363 if (work->conn->connection_type) {
364 if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
365 ksmbd_err("no right to read(%s)\n", FP_FILENAME(fp));
366 return -EACCES;
367 }
368 }
369
370 if (ksmbd_stream_fd(fp))
371 return ksmbd_vfs_stream_read(fp, rbuf, pos, count);
372
c36fca86
NJ
373 if (!work->tcon->posix_extensions) {
374 int ret;
375
070fb21e 376 ret = check_lock_range(filp, *pos, *pos + count - 1, READ);
c36fca86
NJ
377 if (ret) {
378 ksmbd_err("unable to read due to lock\n");
379 return -EAGAIN;
380 }
f4415848
NJ
381 }
382
383 nbytes = kernel_read(filp, rbuf, count, pos);
384 if (nbytes < 0) {
f4415848 385 ksmbd_err("smb read failed for (%s), err = %zd\n",
070fb21e 386 fp->filename, nbytes);
f4415848
NJ
387 return nbytes;
388 }
389
390 filp->f_pos = *pos;
391 return nbytes;
392}
393
394static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
070fb21e 395 size_t count)
f4415848
NJ
396{
397 char *stream_buf = NULL, *wbuf;
398 size_t size, v_len;
399 int err = 0;
400
401 ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n",
070fb21e 402 *pos, count);
f4415848
NJ
403
404 size = *pos + count;
405 if (size > XATTR_SIZE_MAX) {
406 size = XATTR_SIZE_MAX;
407 count = (*pos + count) - XATTR_SIZE_MAX;
408 }
409
410 v_len = ksmbd_vfs_getcasexattr(fp->filp->f_path.dentry,
411 fp->stream.name,
412 fp->stream.size,
413 &stream_buf);
fd6de099 414 if ((int)v_len < 0) {
f4415848 415 ksmbd_err("not found stream in xattr : %zd\n", v_len);
fd6de099 416 err = (int)v_len;
f4415848
NJ
417 goto out;
418 }
419
420 if (v_len < size) {
79f6b11a 421 wbuf = kvmalloc(size, GFP_KERNEL | __GFP_ZERO);
f4415848
NJ
422 if (!wbuf) {
423 err = -ENOMEM;
424 goto out;
425 }
426
427 if (v_len > 0)
428 memcpy(wbuf, stream_buf, v_len);
113ef68d 429 kvfree(stream_buf);
f4415848
NJ
430 stream_buf = wbuf;
431 }
432
433 memcpy(&stream_buf[*pos], buf, count);
434
435 err = ksmbd_vfs_setxattr(fp->filp->f_path.dentry,
436 fp->stream.name,
437 (void *)stream_buf,
438 size,
439 0);
440 if (err < 0)
441 goto out;
442
443 fp->filp->f_pos = *pos;
444 err = 0;
445out:
79f6b11a 446 kvfree(stream_buf);
f4415848
NJ
447 return err;
448}
449
450/**
451 * ksmbd_vfs_write() - vfs helper for smb file write
452 * @work: work
453 * @fid: file id of open file
454 * @buf: buf containing data for writing
455 * @count: read byte count
456 * @pos: file pos
457 * @sync: fsync after write
458 * @written: number of bytes written
459 *
460 * Return: 0 on success, otherwise error
461 */
462int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e
NJ
463 char *buf, size_t count, loff_t *pos, bool sync,
464 ssize_t *written)
f4415848
NJ
465{
466 struct ksmbd_session *sess = work->sess;
467 struct file *filp;
468 loff_t offset = *pos;
469 int err = 0;
470
471 if (sess->conn->connection_type) {
472 if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
473 ksmbd_err("no right to write(%s)\n", FP_FILENAME(fp));
474 err = -EACCES;
475 goto out;
476 }
477 }
478
479 filp = fp->filp;
480
481 if (ksmbd_stream_fd(fp)) {
482 err = ksmbd_vfs_stream_write(fp, buf, pos, count);
483 if (!err)
484 *written = count;
485 goto out;
486 }
487
c36fca86
NJ
488 if (!work->tcon->posix_extensions) {
489 err = check_lock_range(filp, *pos, *pos + count - 1, WRITE);
490 if (err) {
491 ksmbd_err("unable to write due to lock\n");
492 err = -EAGAIN;
493 goto out;
494 }
f4415848
NJ
495 }
496
497 /* Do we need to break any of a levelII oplock? */
498 smb_break_all_levII_oplock(work, fp, 1);
499
500 err = kernel_write(filp, buf, count, pos);
501 if (err < 0) {
502 ksmbd_debug(VFS, "smb write failed, err = %d\n", err);
503 goto out;
504 }
505
506 filp->f_pos = *pos;
507 *written = err;
508 err = 0;
509 if (sync) {
510 err = vfs_fsync_range(filp, offset, offset + *written, 0);
511 if (err < 0)
512 ksmbd_err("fsync failed for filename = %s, err = %d\n",
070fb21e 513 FP_FILENAME(fp), err);
f4415848
NJ
514 }
515
516out:
517 return err;
518}
519
520/**
521 * ksmbd_vfs_getattr() - vfs helper for smb getattr
522 * @work: work
523 * @fid: file id of open file
524 * @attrs: inode attributes
525 *
526 * Return: 0 on success, otherwise error
527 */
528int ksmbd_vfs_getattr(struct path *path, struct kstat *stat)
529{
530 int err;
531
532 err = vfs_getattr(path, stat, STATX_BTIME, AT_STATX_SYNC_AS_STAT);
533 if (err)
534 ksmbd_err("getattr failed, err %d\n", err);
535 return err;
536}
537
538/**
539 * ksmbd_vfs_fsync() - vfs helper for smb fsync
540 * @work: work
541 * @fid: file id of open file
542 *
543 * Return: 0 on success, otherwise error
544 */
64b39f4a 545int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
f4415848
NJ
546{
547 struct ksmbd_file *fp;
548 int err;
549
550 fp = ksmbd_lookup_fd_slow(work, fid, p_id);
551 if (!fp) {
552 ksmbd_err("failed to get filp for fid %llu\n", fid);
553 return -ENOENT;
554 }
555 err = vfs_fsync(fp->filp, 0);
556 if (err < 0)
557 ksmbd_err("smb fsync failed, err = %d\n", err);
558 ksmbd_fd_put(work, fp);
559 return err;
560}
561
562/**
563 * ksmbd_vfs_remove_file() - vfs helper for smb rmdir or unlink
564 * @name: absolute directory or file name
565 *
566 * Return: 0 on success, otherwise error
567 */
568int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
569{
7c3d3e99
NJ
570 struct path path;
571 struct dentry *dentry, *parent;
3161ad3a 572 int err;
a6a5fa77 573 int flags = 0;
f4415848 574
f4415848
NJ
575 if (ksmbd_override_fsids(work))
576 return -ENOMEM;
577
a6a5fa77
HL
578 if (test_share_config_flag(work->tcon->share_conf,
579 KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS))
580 flags = LOOKUP_FOLLOW;
581
582 err = kern_path(name, flags, &path);
f4415848
NJ
583 if (err) {
584 ksmbd_debug(VFS, "can't get %s, err %d\n", name, err);
585 ksmbd_revert_fsids(work);
f4415848
NJ
586 return err;
587 }
588
7c3d3e99
NJ
589 parent = dget_parent(path.dentry);
590 inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
591 dentry = lookup_one_len(path.dentry->d_name.name, parent,
070fb21e 592 strlen(path.dentry->d_name.name));
f4415848
NJ
593 if (IS_ERR(dentry)) {
594 err = PTR_ERR(dentry);
7c3d3e99 595 ksmbd_debug(VFS, "%s: lookup failed, err %d\n",
070fb21e 596 path.dentry->d_name.name, err);
f4415848
NJ
597 goto out_err;
598 }
599
600 if (!d_inode(dentry) || !d_inode(dentry)->i_nlink) {
601 dput(dentry);
602 err = -ENOENT;
603 goto out_err;
604 }
605
606 if (S_ISDIR(d_inode(dentry)->i_mode)) {
7c3d3e99 607 err = vfs_rmdir(&init_user_ns, d_inode(parent), dentry);
f4415848
NJ
608 if (err && err != -ENOTEMPTY)
609 ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
070fb21e 610 err);
f4415848 611 } else {
7c3d3e99 612 err = vfs_unlink(&init_user_ns, d_inode(parent), dentry, NULL);
f4415848
NJ
613 if (err)
614 ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
070fb21e 615 err);
f4415848
NJ
616 }
617
618 dput(dentry);
619out_err:
7c3d3e99
NJ
620 inode_unlock(d_inode(parent));
621 dput(parent);
622 path_put(&path);
f4415848
NJ
623 ksmbd_revert_fsids(work);
624 return err;
625}
626
627/**
628 * ksmbd_vfs_link() - vfs helper for creating smb hardlink
629 * @oldname: source file name
630 * @newname: hardlink name
631 *
632 * Return: 0 on success, otherwise error
633 */
64b39f4a 634int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
070fb21e 635 const char *newname)
f4415848
NJ
636{
637 struct path oldpath, newpath;
638 struct dentry *dentry;
639 int err;
a6a5fa77 640 int flags = 0;
f4415848
NJ
641
642 if (ksmbd_override_fsids(work))
643 return -ENOMEM;
644
a6a5fa77
HL
645 if (test_share_config_flag(work->tcon->share_conf,
646 KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS))
647 flags = LOOKUP_FOLLOW;
648
649 err = kern_path(oldname, flags, &oldpath);
f4415848
NJ
650 if (err) {
651 ksmbd_err("cannot get linux path for %s, err = %d\n",
070fb21e 652 oldname, err);
f4415848
NJ
653 goto out1;
654 }
655
656 dentry = kern_path_create(AT_FDCWD, newname, &newpath,
a6a5fa77 657 flags | LOOKUP_REVAL);
f4415848
NJ
658 if (IS_ERR(dentry)) {
659 err = PTR_ERR(dentry);
660 ksmbd_err("path create err for %s, err %d\n", newname, err);
661 goto out2;
662 }
663
664 err = -EXDEV;
665 if (oldpath.mnt != newpath.mnt) {
666 ksmbd_err("vfs_link failed err %d\n", err);
667 goto out3;
668 }
669
670 err = vfs_link(oldpath.dentry, &init_user_ns, d_inode(newpath.dentry),
070fb21e 671 dentry, NULL);
f4415848
NJ
672 if (err)
673 ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
674
675out3:
676 done_path_create(&newpath, dentry);
677out2:
678 path_put(&oldpath);
679out1:
680 ksmbd_revert_fsids(work);
681 return err;
682}
683
684static int __ksmbd_vfs_rename(struct ksmbd_work *work,
070fb21e
NJ
685 struct dentry *src_dent_parent,
686 struct dentry *src_dent,
687 struct dentry *dst_dent_parent,
688 struct dentry *trap_dent,
689 char *dst_name)
f4415848
NJ
690{
691 struct dentry *dst_dent;
692 int err;
693
c36fca86
NJ
694 if (!work->tcon->posix_extensions) {
695 spin_lock(&src_dent->d_lock);
696 list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) {
697 struct ksmbd_file *child_fp;
f4415848 698
c36fca86
NJ
699 if (d_really_is_negative(dst_dent))
700 continue;
f4415848 701
c36fca86
NJ
702 child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent));
703 if (child_fp) {
704 spin_unlock(&src_dent->d_lock);
705 ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n");
706 return -EACCES;
707 }
f4415848 708 }
c36fca86 709 spin_unlock(&src_dent->d_lock);
f4415848 710 }
f4415848
NJ
711
712 if (d_really_is_negative(src_dent_parent))
713 return -ENOENT;
714 if (d_really_is_negative(dst_dent_parent))
715 return -ENOENT;
716 if (d_really_is_negative(src_dent))
717 return -ENOENT;
718 if (src_dent == trap_dent)
719 return -EINVAL;
720
721 if (ksmbd_override_fsids(work))
722 return -ENOMEM;
723
724 dst_dent = lookup_one_len(dst_name, dst_dent_parent, strlen(dst_name));
725 err = PTR_ERR(dst_dent);
726 if (IS_ERR(dst_dent)) {
727 ksmbd_err("lookup failed %s [%d]\n", dst_name, err);
728 goto out;
729 }
730
731 err = -ENOTEMPTY;
732 if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
733 struct renamedata rd = {
734 .old_mnt_userns = &init_user_ns,
735 .old_dir = d_inode(src_dent_parent),
736 .old_dentry = src_dent,
737 .new_mnt_userns = &init_user_ns,
738 .new_dir = d_inode(dst_dent_parent),
739 .new_dentry = dst_dent,
740 };
741 err = vfs_rename(&rd);
742 }
743 if (err)
744 ksmbd_err("vfs_rename failed err %d\n", err);
745 if (dst_dent)
746 dput(dst_dent);
747out:
748 ksmbd_revert_fsids(work);
749 return err;
750}
751
752int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e 753 char *newname)
f4415848
NJ
754{
755 struct path dst_path;
756 struct dentry *src_dent_parent, *dst_dent_parent;
ff1d5727 757 struct dentry *src_dent, *trap_dent, *src_child;
f4415848
NJ
758 char *dst_name;
759 int err;
a6a5fa77 760 int flags;
f4415848
NJ
761
762 dst_name = extract_last_component(newname);
763 if (!dst_name)
764 return -EINVAL;
765
766 src_dent_parent = dget_parent(fp->filp->f_path.dentry);
f4415848 767 src_dent = fp->filp->f_path.dentry;
f4415848 768
a6a5fa77
HL
769 flags = LOOKUP_DIRECTORY;
770 if (test_share_config_flag(work->tcon->share_conf,
771 KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS))
772 flags |= LOOKUP_FOLLOW;
773
774 err = kern_path(newname, flags, &dst_path);
f4415848
NJ
775 if (err) {
776 ksmbd_debug(VFS, "Cannot get path for %s [%d]\n", newname, err);
777 goto out;
778 }
779 dst_dent_parent = dst_path.dentry;
f4415848
NJ
780
781 trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
ff1d5727
NJ
782 dget(src_dent);
783 dget(dst_dent_parent);
784 src_child = lookup_one_len(src_dent->d_name.name, src_dent_parent,
070fb21e 785 src_dent->d_name.len);
ff1d5727
NJ
786 if (IS_ERR(src_child)) {
787 err = PTR_ERR(src_child);
788 goto out_lock;
789 }
790
791 if (src_child != src_dent) {
792 err = -ESTALE;
793 dput(src_child);
794 goto out_lock;
795 }
796 dput(src_child);
797
f4415848
NJ
798 err = __ksmbd_vfs_rename(work,
799 src_dent_parent,
800 src_dent,
801 dst_dent_parent,
802 trap_dent,
803 dst_name);
ff1d5727
NJ
804out_lock:
805 dput(src_dent);
f4415848 806 dput(dst_dent_parent);
ff1d5727 807 unlock_rename(src_dent_parent, dst_dent_parent);
f4415848
NJ
808 path_put(&dst_path);
809out:
f4415848
NJ
810 dput(src_dent_parent);
811 return err;
812}
813
814/**
815 * ksmbd_vfs_truncate() - vfs helper for smb file truncate
816 * @work: work
817 * @name: old filename
818 * @fid: file id of old file
819 * @size: truncate to given size
820 *
821 * Return: 0 on success, otherwise error
822 */
823int ksmbd_vfs_truncate(struct ksmbd_work *work, const char *name,
070fb21e 824 struct ksmbd_file *fp, loff_t size)
f4415848
NJ
825{
826 struct path path;
827 int err = 0;
f4415848
NJ
828
829 if (name) {
830 err = kern_path(name, 0, &path);
831 if (err) {
832 ksmbd_err("cannot get linux path for %s, err %d\n",
070fb21e 833 name, err);
f4415848
NJ
834 return err;
835 }
836 err = vfs_truncate(&path, size);
837 if (err)
838 ksmbd_err("truncate failed for %s err %d\n",
070fb21e 839 name, err);
f4415848
NJ
840 path_put(&path);
841 } else {
842 struct file *filp;
843
844 filp = fp->filp;
845
846 /* Do we need to break any of a levelII oplock? */
847 smb_break_all_levII_oplock(work, fp, 1);
848
c36fca86
NJ
849 if (!work->tcon->posix_extensions) {
850 struct inode *inode = file_inode(filp);
f4415848 851
c36fca86
NJ
852 if (size < inode->i_size) {
853 err = check_lock_range(filp, size,
070fb21e 854 inode->i_size - 1, WRITE);
c36fca86
NJ
855 } else {
856 err = check_lock_range(filp, inode->i_size,
070fb21e 857 size - 1, WRITE);
c36fca86
NJ
858 }
859
860 if (err) {
861 ksmbd_err("failed due to lock\n");
862 return -EAGAIN;
863 }
f4415848
NJ
864 }
865
866 err = vfs_truncate(&filp->f_path, size);
867 if (err)
868 ksmbd_err("truncate failed for filename : %s err %d\n",
070fb21e 869 fp->filename, err);
f4415848
NJ
870 }
871
872 return err;
873}
874
875/**
876 * ksmbd_vfs_listxattr() - vfs helper for smb list extended attributes
877 * @dentry: dentry of file for listing xattrs
878 * @list: destination buffer
879 * @size: destination buffer length
880 *
881 * Return: xattr list length on success, otherwise error
882 */
883ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list)
884{
885 ssize_t size;
886 char *vlist = NULL;
887
888 size = vfs_listxattr(dentry, NULL, 0);
889 if (size <= 0)
890 return size;
891
79f6b11a 892 vlist = kvmalloc(size, GFP_KERNEL | __GFP_ZERO);
f4415848
NJ
893 if (!vlist)
894 return -ENOMEM;
895
896 *list = vlist;
897 size = vfs_listxattr(dentry, vlist, size);
898 if (size < 0) {
899 ksmbd_debug(VFS, "listxattr failed\n");
79f6b11a 900 kvfree(vlist);
f4415848
NJ
901 *list = NULL;
902 }
903
904 return size;
905}
906
64b39f4a 907static ssize_t ksmbd_vfs_xattr_len(struct dentry *dentry, char *xattr_name)
f4415848
NJ
908{
909 return vfs_getxattr(&init_user_ns, dentry, xattr_name, NULL, 0);
910}
911
912/**
913 * ksmbd_vfs_getxattr() - vfs helper for smb get extended attributes value
914 * @dentry: dentry of file for getting xattrs
915 * @xattr_name: name of xattr name to query
916 * @xattr_buf: destination buffer xattr value
917 *
918 * Return: read xattr value length on success, otherwise error
919 */
64b39f4a 920ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name,
070fb21e 921 char **xattr_buf)
f4415848
NJ
922{
923 ssize_t xattr_len;
924 char *buf;
925
926 *xattr_buf = NULL;
927 xattr_len = ksmbd_vfs_xattr_len(dentry, xattr_name);
928 if (xattr_len < 0)
929 return xattr_len;
930
931 buf = kmalloc(xattr_len + 1, GFP_KERNEL);
932 if (!buf)
933 return -ENOMEM;
934
d7e5852b
HL
935 xattr_len = vfs_getxattr(&init_user_ns, dentry, xattr_name,
936 (void *)buf, xattr_len);
f4415848
NJ
937 if (xattr_len > 0)
938 *xattr_buf = buf;
939 else
940 kfree(buf);
941 return xattr_len;
942}
943
944/**
945 * ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value
946 * @dentry: dentry to set XATTR at
947 * @name: xattr name for setxattr
948 * @value: xattr value to set
949 * @size: size of xattr value
950 * @flags: destination buffer length
951 *
952 * Return: 0 on success, otherwise error
953 */
64b39f4a 954int ksmbd_vfs_setxattr(struct dentry *dentry, const char *attr_name,
070fb21e 955 const void *attr_value, size_t attr_size, int flags)
f4415848
NJ
956{
957 int err;
958
959 err = vfs_setxattr(&init_user_ns, dentry,
960 attr_name,
961 attr_value,
962 attr_size,
963 flags);
964 if (err)
965 ksmbd_debug(VFS, "setxattr failed, err %d\n", err);
966 return err;
967}
968
969/**
970 * ksmbd_vfs_set_fadvise() - convert smb IO caching options to linux options
971 * @filp: file pointer for IO
972 * @options: smb IO options
973 */
974void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option)
975{
976 struct address_space *mapping;
977
978 mapping = filp->f_mapping;
979
980 if (!option || !mapping)
981 return;
982
64b39f4a 983 if (option & FILE_WRITE_THROUGH_LE) {
f4415848 984 filp->f_flags |= O_SYNC;
64b39f4a 985 } else if (option & FILE_SEQUENTIAL_ONLY_LE) {
f4415848
NJ
986 filp->f_ra.ra_pages = inode_to_bdi(mapping->host)->ra_pages * 2;
987 spin_lock(&filp->f_lock);
988 filp->f_mode &= ~FMODE_RANDOM;
989 spin_unlock(&filp->f_lock);
990 } else if (option & FILE_RANDOM_ACCESS_LE) {
991 spin_lock(&filp->f_lock);
992 filp->f_mode |= FMODE_RANDOM;
993 spin_unlock(&filp->f_lock);
994 }
995}
996
997/**
998 * ksmbd_vfs_lock() - vfs helper for smb file locking
999 * @filp: the file to apply the lock to
1000 * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.)
1001 * @flock: The lock to be applied
1002 *
1003 * Return: 0 on success, otherwise error
1004 */
070fb21e 1005int ksmbd_vfs_lock(struct file *filp, int cmd, struct file_lock *flock)
f4415848
NJ
1006{
1007 ksmbd_debug(VFS, "calling vfs_lock_file\n");
1008 return vfs_lock_file(filp, cmd, flock, NULL);
1009}
1010
1011int ksmbd_vfs_readdir(struct file *file, struct ksmbd_readdir_data *rdata)
1012{
1013 return iterate_dir(file, &rdata->ctx);
1014}
1015
64b39f4a 1016int ksmbd_vfs_alloc_size(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e 1017 loff_t len)
f4415848
NJ
1018{
1019 smb_break_all_levII_oplock(work, fp, 1);
1020 return vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0, len);
1021}
1022
64b39f4a 1023int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
070fb21e 1024 loff_t off, loff_t len)
f4415848
NJ
1025{
1026 smb_break_all_levII_oplock(work, fp, 1);
1027 if (fp->f_ci->m_fattr & ATTR_SPARSE_FILE_LE)
1028 return vfs_fallocate(fp->filp,
070fb21e
NJ
1029 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
1030 off, len);
f4415848
NJ
1031
1032 return vfs_fallocate(fp->filp, FALLOC_FL_ZERO_RANGE, off, len);
1033}
1034
1035int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
070fb21e
NJ
1036 struct file_allocated_range_buffer *ranges,
1037 int in_count, int *out_count)
f4415848
NJ
1038{
1039 struct file *f = fp->filp;
1040 struct inode *inode = FP_INODE(fp);
1041 loff_t maxbytes = (u64)inode->i_sb->s_maxbytes, end;
1042 loff_t extent_start, extent_end;
1043 int ret = 0;
1044
1045 if (start > maxbytes)
1046 return -EFBIG;
1047
1048 if (!in_count)
1049 return 0;
1050
1051 /*
1052 * Shrink request scope to what the fs can actually handle.
1053 */
1054 if (length > maxbytes || (maxbytes - length) < start)
1055 length = maxbytes - start;
1056
1057 if (start + length > inode->i_size)
1058 length = inode->i_size - start;
1059
1060 *out_count = 0;
1061 end = start + length;
1062 while (start < end && *out_count < in_count) {
1063 extent_start = f->f_op->llseek(f, start, SEEK_DATA);
1064 if (extent_start < 0) {
1065 if (extent_start != -ENXIO)
1066 ret = (int)extent_start;
1067 break;
1068 }
1069
1070 if (extent_start >= end)
1071 break;
1072
1073 extent_end = f->f_op->llseek(f, extent_start, SEEK_HOLE);
1074 if (extent_end < 0) {
1075 if (extent_end != -ENXIO)
1076 ret = (int)extent_end;
1077 break;
64b39f4a 1078 } else if (extent_start >= extent_end) {
f4415848 1079 break;
64b39f4a 1080 }
f4415848
NJ
1081
1082 ranges[*out_count].file_offset = cpu_to_le64(extent_start);
1083 ranges[(*out_count)++].length =
1084 cpu_to_le64(min(extent_end, end) - extent_start);
1085
1086 start = extent_end;
1087 }
1088
1089 return ret;
1090}
1091
1092int ksmbd_vfs_remove_xattr(struct dentry *dentry, char *attr_name)
1093{
1094 return vfs_removexattr(&init_user_ns, dentry, attr_name);
1095}
1096
f4415848
NJ
1097int ksmbd_vfs_unlink(struct dentry *dir, struct dentry *dentry)
1098{
ff1d5727 1099 struct dentry *child;
f4415848
NJ
1100 int err = 0;
1101
f4415848 1102 inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
ff1d5727 1103 dget(dentry);
070fb21e 1104 child = lookup_one_len(dentry->d_name.name, dir, dentry->d_name.len);
ff1d5727
NJ
1105 if (IS_ERR(child)) {
1106 err = PTR_ERR(child);
1107 goto out;
1108 }
1109
1110 if (child != dentry) {
1111 err = -ESTALE;
1112 dput(child);
f4415848
NJ
1113 goto out;
1114 }
ff1d5727 1115 dput(child);
f4415848
NJ
1116
1117 if (S_ISDIR(d_inode(dentry)->i_mode))
1118 err = vfs_rmdir(&init_user_ns, d_inode(dir), dentry);
1119 else
1120 err = vfs_unlink(&init_user_ns, d_inode(dir), dentry, NULL);
1121
1122out:
f4415848 1123 dput(dentry);
ff1d5727 1124 inode_unlock(d_inode(dir));
f4415848
NJ
1125 if (err)
1126 ksmbd_debug(VFS, "failed to delete, err %d\n", err);
1127
1128 return err;
1129}
1130
1131/*
1132 * ksmbd_vfs_get_logical_sector_size() - get logical sector size from inode
1133 * @inode: inode
1134 *
1135 * Return: logical sector size
1136 */
1137unsigned short ksmbd_vfs_logical_sector_size(struct inode *inode)
1138{
1139 struct request_queue *q;
1140 unsigned short ret_val = 512;
1141
1142 if (!inode->i_sb->s_bdev)
1143 return ret_val;
1144
1145 q = inode->i_sb->s_bdev->bd_disk->queue;
1146
1147 if (q && q->limits.logical_block_size)
1148 ret_val = q->limits.logical_block_size;
1149
1150 return ret_val;
1151}
1152
1153/*
1154 * ksmbd_vfs_get_smb2_sector_size() - get fs sector sizes
1155 * @inode: inode
1156 * @fs_ss: fs sector size struct
1157 */
1158void ksmbd_vfs_smb2_sector_size(struct inode *inode,
070fb21e 1159 struct ksmbd_fs_sector_size *fs_ss)
f4415848
NJ
1160{
1161 struct request_queue *q;
1162
1163 fs_ss->logical_sector_size = 512;
1164 fs_ss->physical_sector_size = 512;
1165 fs_ss->optimal_io_size = 512;
1166
1167 if (!inode->i_sb->s_bdev)
1168 return;
1169
1170 q = inode->i_sb->s_bdev->bd_disk->queue;
1171
1172 if (q) {
1173 if (q->limits.logical_block_size)
1174 fs_ss->logical_sector_size =
1175 q->limits.logical_block_size;
1176 if (q->limits.physical_block_size)
1177 fs_ss->physical_sector_size =
1178 q->limits.physical_block_size;
1179 if (q->limits.io_opt)
1180 fs_ss->optimal_io_size = q->limits.io_opt;
1181 }
1182}
1183
64b39f4a 1184static int __dir_empty(struct dir_context *ctx, const char *name, int namlen,
070fb21e 1185 loff_t offset, u64 ino, unsigned int d_type)
f4415848
NJ
1186{
1187 struct ksmbd_readdir_data *buf;
1188
1189 buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
1190 buf->dirent_count++;
1191
1192 if (buf->dirent_count > 2)
1193 return -ENOTEMPTY;
1194 return 0;
1195}
1196
1197/**
1198 * ksmbd_vfs_empty_dir() - check for empty directory
1199 * @fp: ksmbd file pointer
1200 *
1201 * Return: true if directory empty, otherwise false
1202 */
1203int ksmbd_vfs_empty_dir(struct ksmbd_file *fp)
1204{
1205 int err;
1206 struct ksmbd_readdir_data readdir_data;
1207
1208 memset(&readdir_data, 0, sizeof(struct ksmbd_readdir_data));
1209
1210 set_ctx_actor(&readdir_data.ctx, __dir_empty);
1211 readdir_data.dirent_count = 0;
1212
1213 err = ksmbd_vfs_readdir(fp->filp, &readdir_data);
1214 if (readdir_data.dirent_count > 2)
1215 err = -ENOTEMPTY;
1216 else
1217 err = 0;
1218 return err;
1219}
1220
64b39f4a 1221static int __caseless_lookup(struct dir_context *ctx, const char *name,
070fb21e
NJ
1222 int namlen, loff_t offset, u64 ino,
1223 unsigned int d_type)
f4415848
NJ
1224{
1225 struct ksmbd_readdir_data *buf;
1226
1227 buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
1228
1229 if (buf->used != namlen)
1230 return 0;
1231 if (!strncasecmp((char *)buf->private, name, namlen)) {
1232 memcpy((char *)buf->private, name, namlen);
1233 buf->dirent_count = 1;
1234 return -EEXIST;
1235 }
1236 return 0;
1237}
1238
1239/**
1240 * ksmbd_vfs_lookup_in_dir() - lookup a file in a directory
3c203783
HL
1241 * @dir: path info
1242 * @name: filename to lookup
1243 * @namelen: filename length
f4415848
NJ
1244 *
1245 * Return: 0 on success, otherwise error
1246 */
3c203783 1247static int ksmbd_vfs_lookup_in_dir(struct path *dir, char *name, size_t namelen)
f4415848 1248{
f4415848
NJ
1249 int ret;
1250 struct file *dfilp;
64b39f4a 1251 int flags = O_RDONLY | O_LARGEFILE;
f4415848
NJ
1252 struct ksmbd_readdir_data readdir_data = {
1253 .ctx.actor = __caseless_lookup,
3c203783
HL
1254 .private = name,
1255 .used = namelen,
1256 .dirent_count = 0,
f4415848
NJ
1257 };
1258
3c203783
HL
1259 dfilp = dentry_open(dir, flags, current_cred());
1260 if (IS_ERR(dfilp))
1261 return PTR_ERR(dfilp);
f4415848
NJ
1262
1263 ret = ksmbd_vfs_readdir(dfilp, &readdir_data);
1264 if (readdir_data.dirent_count > 0)
1265 ret = 0;
f4415848 1266 fput(dfilp);
f4415848
NJ
1267 return ret;
1268}
1269
1270/**
1271 * ksmbd_vfs_kern_path() - lookup a file and get path info
1272 * @name: name of file for lookup
1273 * @flags: lookup flags
1274 * @path: if lookup succeed, return path info
1275 * @caseless: caseless filename lookup
1276 *
1277 * Return: 0 on success, otherwise error
1278 */
1279int ksmbd_vfs_kern_path(char *name, unsigned int flags, struct path *path,
070fb21e 1280 bool caseless)
f4415848 1281{
f4415848
NJ
1282 int err;
1283
3c203783
HL
1284 if (name[0] != '/')
1285 return -EINVAL;
1286
f4415848
NJ
1287 err = kern_path(name, flags, path);
1288 if (!err)
3c203783 1289 return 0;
f4415848
NJ
1290
1291 if (caseless) {
3c203783
HL
1292 char *filepath;
1293 struct path parent;
1294 size_t path_len, remain_len;
f4415848 1295
3c203783
HL
1296 filepath = kstrdup(name, GFP_KERNEL);
1297 if (!filepath)
1298 return -ENOMEM;
1299
1300 path_len = strlen(filepath);
1301 remain_len = path_len - 1;
f4415848 1302
3c203783 1303 err = kern_path("/", flags, &parent);
f4415848
NJ
1304 if (err)
1305 goto out;
f4415848 1306
3c203783
HL
1307 while (d_can_lookup(parent.dentry)) {
1308 char *filename = filepath + path_len - remain_len;
1309 char *next = strchrnul(filename, '/');
1310 size_t filename_len = next - filename;
1311 bool is_last = !next[0];
1312
1313 if (filename_len == 0)
1314 break;
1315
1316 err = ksmbd_vfs_lookup_in_dir(&parent, filename,
1317 filename_len);
1318 if (err) {
1319 path_put(&parent);
1320 goto out;
1321 }
1322
1323 path_put(&parent);
1324 next[0] = '\0';
1325
1326 err = kern_path(filepath, flags, &parent);
1327 if (err)
1328 goto out;
1329
1330 if (is_last) {
1331 path->mnt = parent.mnt;
1332 path->dentry = parent.dentry;
1333 goto out;
1334 }
1335
1336 next[0] = '/';
1337 remain_len -= filename_len + 1;
1338 }
1339
1340 path_put(&parent);
1341 err = -EINVAL;
f4415848 1342out:
3c203783
HL
1343 kfree(filepath);
1344 }
f4415848
NJ
1345 return err;
1346}
1347
1348int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry)
1349{
1350 char *name, *xattr_list = NULL;
1351 ssize_t xattr_list_len;
1352 int err = 0;
1353
1354 xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
1355 if (xattr_list_len < 0) {
1356 goto out;
1357 } else if (!xattr_list_len) {
1358 ksmbd_debug(SMB, "empty xattr in the file\n");
1359 goto out;
1360 }
1361
1362 for (name = xattr_list; name - xattr_list < xattr_list_len;
070fb21e 1363 name += strlen(name) + 1) {
f4415848
NJ
1364 ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
1365
1366 if (!strncmp(name, XATTR_NAME_POSIX_ACL_ACCESS,
64b39f4a 1367 sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) ||
f4415848 1368 !strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
64b39f4a 1369 sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) {
f4415848
NJ
1370 err = ksmbd_vfs_remove_xattr(dentry, name);
1371 if (err)
1372 ksmbd_debug(SMB,
070fb21e 1373 "remove acl xattr failed : %s\n", name);
f4415848
NJ
1374 }
1375 }
1376out:
79f6b11a 1377 kvfree(xattr_list);
f4415848
NJ
1378 return err;
1379}
1380
1381int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry)
1382{
1383 char *name, *xattr_list = NULL;
1384 ssize_t xattr_list_len;
1385 int err = 0;
1386
1387 xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
1388 if (xattr_list_len < 0) {
1389 goto out;
1390 } else if (!xattr_list_len) {
1391 ksmbd_debug(SMB, "empty xattr in the file\n");
1392 goto out;
1393 }
1394
1395 for (name = xattr_list; name - xattr_list < xattr_list_len;
1396 name += strlen(name) + 1) {
1397 ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
1398
1399 if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) {
1400 err = ksmbd_vfs_remove_xattr(dentry, name);
1401 if (err)
1402 ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
1403 }
1404 }
1405out:
79f6b11a 1406 kvfree(xattr_list);
f4415848
NJ
1407 return err;
1408}
1409
1410static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct inode *inode,
070fb21e 1411 int acl_type)
f4415848
NJ
1412{
1413 struct xattr_smb_acl *smb_acl = NULL;
1414 struct posix_acl *posix_acls;
1415 struct posix_acl_entry *pa_entry;
1416 struct xattr_acl_entry *xa_entry;
1417 int i;
1418
1419 posix_acls = ksmbd_vfs_get_acl(inode, acl_type);
1420 if (!posix_acls)
1421 return NULL;
1422
1423 smb_acl = kzalloc(sizeof(struct xattr_smb_acl) +
1424 sizeof(struct xattr_acl_entry) * posix_acls->a_count,
1425 GFP_KERNEL);
1426 if (!smb_acl)
1427 goto out;
1428
1429 smb_acl->count = posix_acls->a_count;
1430 pa_entry = posix_acls->a_entries;
1431 xa_entry = smb_acl->entries;
1432 for (i = 0; i < posix_acls->a_count; i++, pa_entry++, xa_entry++) {
1433 switch (pa_entry->e_tag) {
1434 case ACL_USER:
1435 xa_entry->type = SMB_ACL_USER;
1436 xa_entry->uid = from_kuid(&init_user_ns, pa_entry->e_uid);
1437 break;
1438 case ACL_USER_OBJ:
1439 xa_entry->type = SMB_ACL_USER_OBJ;
1440 break;
1441 case ACL_GROUP:
1442 xa_entry->type = SMB_ACL_GROUP;
1443 xa_entry->gid = from_kgid(&init_user_ns, pa_entry->e_gid);
1444 break;
1445 case ACL_GROUP_OBJ:
1446 xa_entry->type = SMB_ACL_GROUP_OBJ;
1447 break;
1448 case ACL_OTHER:
1449 xa_entry->type = SMB_ACL_OTHER;
1450 break;
1451 case ACL_MASK:
1452 xa_entry->type = SMB_ACL_MASK;
1453 break;
1454 default:
1455 ksmbd_err("unknown type : 0x%x\n", pa_entry->e_tag);
1456 goto out;
1457 }
1458
1459 if (pa_entry->e_perm & ACL_READ)
1460 xa_entry->perm |= SMB_ACL_READ;
1461 if (pa_entry->e_perm & ACL_WRITE)
1462 xa_entry->perm |= SMB_ACL_WRITE;
1463 if (pa_entry->e_perm & ACL_EXECUTE)
1464 xa_entry->perm |= SMB_ACL_EXECUTE;
1465 }
1466out:
1467 posix_acl_release(posix_acls);
1468 return smb_acl;
1469}
1470
1471int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
070fb21e 1472 struct smb_ntsd *pntsd, int len)
f4415848
NJ
1473{
1474 int rc;
1475 struct ndr sd_ndr = {0}, acl_ndr = {0};
1476 struct xattr_ntacl acl = {0};
1477 struct xattr_smb_acl *smb_acl, *def_smb_acl = NULL;
fba08fa0 1478 struct inode *inode = d_inode(dentry);
f4415848
NJ
1479
1480 acl.version = 4;
1481 acl.hash_type = XATTR_SD_HASH_TYPE_SHA256;
fba08fa0 1482 acl.current_time = ksmbd_UnixTimeToNT(current_time(inode));
f4415848
NJ
1483
1484 memcpy(acl.desc, "posix_acl", 9);
1485 acl.desc_len = 10;
1486
1487 pntsd->osidoffset =
1488 cpu_to_le32(le32_to_cpu(pntsd->osidoffset) + NDR_NTSD_OFFSETOF);
1489 pntsd->gsidoffset =
1490 cpu_to_le32(le32_to_cpu(pntsd->gsidoffset) + NDR_NTSD_OFFSETOF);
1491 pntsd->dacloffset =
1492 cpu_to_le32(le32_to_cpu(pntsd->dacloffset) + NDR_NTSD_OFFSETOF);
1493
1494 acl.sd_buf = (char *)pntsd;
1495 acl.sd_size = len;
1496
1497 rc = ksmbd_gen_sd_hash(conn, acl.sd_buf, acl.sd_size, acl.hash);
1498 if (rc) {
1499 ksmbd_err("failed to generate hash for ndr acl\n");
1500 return rc;
1501 }
1502
fba08fa0 1503 smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode, ACL_TYPE_ACCESS);
f4415848 1504 if (S_ISDIR(inode->i_mode))
fba08fa0 1505 def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode,
070fb21e 1506 ACL_TYPE_DEFAULT);
f4415848
NJ
1507
1508 rc = ndr_encode_posix_acl(&acl_ndr, inode, smb_acl, def_smb_acl);
1509 if (rc) {
1510 ksmbd_err("failed to encode ndr to posix acl\n");
1511 goto out;
1512 }
1513
1514 rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset,
070fb21e 1515 acl.posix_acl_hash);
f4415848
NJ
1516 if (rc) {
1517 ksmbd_err("failed to generate hash for ndr acl\n");
1518 goto out;
1519 }
1520
1521 rc = ndr_encode_v4_ntacl(&sd_ndr, &acl);
1522 if (rc) {
1523 ksmbd_err("failed to encode ndr to posix acl\n");
1524 goto out;
1525 }
1526
1527 rc = ksmbd_vfs_setxattr(dentry, XATTR_NAME_SD, sd_ndr.data,
070fb21e 1528 sd_ndr.offset, 0);
f4415848
NJ
1529 if (rc < 0)
1530 ksmbd_err("Failed to store XATTR ntacl :%d\n", rc);
1531
1532 kfree(sd_ndr.data);
1533out:
1534 kfree(acl_ndr.data);
1535 kfree(smb_acl);
1536 kfree(def_smb_acl);
1537 return rc;
1538}
1539
1540int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
070fb21e 1541 struct smb_ntsd **pntsd)
f4415848
NJ
1542{
1543 int rc;
1544 struct ndr n;
1545
1546 rc = ksmbd_vfs_getxattr(dentry, XATTR_NAME_SD, &n.data);
1547 if (rc > 0) {
fba08fa0 1548 struct inode *inode = d_inode(dentry);
f4415848
NJ
1549 struct ndr acl_ndr = {0};
1550 struct xattr_ntacl acl;
1551 struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL;
1552 __u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0};
1553
1554 n.length = rc;
1555 rc = ndr_decode_v4_ntacl(&n, &acl);
1556 if (rc)
1557 return rc;
1558
1559 smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode,
070fb21e 1560 ACL_TYPE_ACCESS);
f4415848
NJ
1561 if (S_ISDIR(inode->i_mode))
1562 def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode,
070fb21e 1563 ACL_TYPE_DEFAULT);
f4415848
NJ
1564
1565 rc = ndr_encode_posix_acl(&acl_ndr, inode, smb_acl, def_smb_acl);
1566 if (rc) {
1567 ksmbd_err("failed to encode ndr to posix acl\n");
1568 goto out;
1569 }
1570
1571 rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset,
070fb21e 1572 cmp_hash);
f4415848
NJ
1573 if (rc) {
1574 ksmbd_err("failed to generate hash for ndr acl\n");
1575 goto out;
1576 }
1577
1578 if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
1579 ksmbd_err("hash value diff\n");
1580 rc = -EINVAL;
1581 goto out;
1582 }
1583
1584 *pntsd = acl.sd_buf;
1585 (*pntsd)->osidoffset =
1586 cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) - NDR_NTSD_OFFSETOF);
1587 (*pntsd)->gsidoffset =
1588 cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) - NDR_NTSD_OFFSETOF);
1589 (*pntsd)->dacloffset =
1590 cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) - NDR_NTSD_OFFSETOF);
1591
1592 rc = acl.sd_size;
1593out:
1594 kfree(n.data);
1595 kfree(acl_ndr.data);
1596 kfree(smb_acl);
1597 kfree(def_smb_acl);
1598 }
1599
1600 return rc;
1601}
1602
1603int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry,
070fb21e 1604 struct xattr_dos_attrib *da)
f4415848
NJ
1605{
1606 struct ndr n;
1607 int err;
1608
1609 err = ndr_encode_dos_attr(&n, da);
1610 if (err)
1611 return err;
1612
070fb21e
NJ
1613 err = ksmbd_vfs_setxattr(dentry, XATTR_NAME_DOS_ATTRIBUTE,
1614 (void *)n.data, n.offset, 0);
f4415848
NJ
1615 if (err)
1616 ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
1617 kfree(n.data);
1618
1619 return err;
1620}
1621
1622int ksmbd_vfs_get_dos_attrib_xattr(struct dentry *dentry,
070fb21e 1623 struct xattr_dos_attrib *da)
f4415848
NJ
1624{
1625 struct ndr n;
1626 int err;
1627
070fb21e
NJ
1628 err = ksmbd_vfs_getxattr(dentry, XATTR_NAME_DOS_ATTRIBUTE,
1629 (char **)&n.data);
f4415848
NJ
1630 if (err > 0) {
1631 n.length = err;
1632 if (ndr_decode_dos_attr(&n, da))
1633 err = -EINVAL;
79f6b11a 1634 kfree(n.data);
64b39f4a 1635 } else {
f4415848 1636 ksmbd_debug(SMB, "failed to load dos attribute in xattr\n");
64b39f4a 1637 }
f4415848
NJ
1638
1639 return err;
1640}
1641
1642struct posix_acl *ksmbd_vfs_posix_acl_alloc(int count, gfp_t flags)
1643{
1644#if IS_ENABLED(CONFIG_FS_POSIX_ACL)
1645 return posix_acl_alloc(count, flags);
1646#else
1647 return NULL;
1648#endif
1649}
1650
1651struct posix_acl *ksmbd_vfs_get_acl(struct inode *inode, int type)
1652{
1653#if IS_ENABLED(CONFIG_FS_POSIX_ACL)
1654 return get_acl(inode, type);
1655#else
1656 return NULL;
1657#endif
1658}
1659
1660int ksmbd_vfs_set_posix_acl(struct inode *inode, int type,
070fb21e 1661 struct posix_acl *acl)
f4415848
NJ
1662{
1663#if IS_ENABLED(CONFIG_FS_POSIX_ACL)
1664 return set_posix_acl(&init_user_ns, inode, type, acl);
1665#else
1666 return -EOPNOTSUPP;
1667#endif
1668}
1669
1670/**
1671 * ksmbd_vfs_init_kstat() - convert unix stat information to smb stat format
1672 * @p: destination buffer
1673 * @ksmbd_kstat: ksmbd kstat wrapper
1674 */
1675void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat)
1676{
1677 struct file_directory_info *info = (struct file_directory_info *)(*p);
1678 struct kstat *kstat = ksmbd_kstat->kstat;
1679 u64 time;
1680
1681 info->FileIndex = 0;
1682 info->CreationTime = cpu_to_le64(ksmbd_kstat->create_time);
1683 time = ksmbd_UnixTimeToNT(kstat->atime);
1684 info->LastAccessTime = cpu_to_le64(time);
1685 time = ksmbd_UnixTimeToNT(kstat->mtime);
1686 info->LastWriteTime = cpu_to_le64(time);
1687 time = ksmbd_UnixTimeToNT(kstat->ctime);
1688 info->ChangeTime = cpu_to_le64(time);
1689
1690 if (ksmbd_kstat->file_attributes & ATTR_DIRECTORY_LE) {
1691 info->EndOfFile = 0;
1692 info->AllocationSize = 0;
1693 } else {
1694 info->EndOfFile = cpu_to_le64(kstat->size);
1695 info->AllocationSize = cpu_to_le64(kstat->blocks << 9);
1696 }
1697 info->ExtFileAttributes = ksmbd_kstat->file_attributes;
1698
1699 return info;
1700}
1701
64b39f4a 1702int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry,
070fb21e 1703 struct ksmbd_kstat *ksmbd_kstat)
f4415848
NJ
1704{
1705 u64 time;
1706 int rc;
1707
1708 generic_fillattr(&init_user_ns, d_inode(dentry), ksmbd_kstat->kstat);
1709
1710 time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
1711 ksmbd_kstat->create_time = time;
1712
1713 /*
1714 * set default value for the case that store dos attributes is not yes
1715 * or that acl is disable in server's filesystem and the config is yes.
1716 */
1717 if (S_ISDIR(ksmbd_kstat->kstat->mode))
1718 ksmbd_kstat->file_attributes = ATTR_DIRECTORY_LE;
1719 else
1720 ksmbd_kstat->file_attributes = ATTR_ARCHIVE_LE;
1721
1722 if (test_share_config_flag(work->tcon->share_conf,
64b39f4a 1723 KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
f4415848
NJ
1724 struct xattr_dos_attrib da;
1725
1726 rc = ksmbd_vfs_get_dos_attrib_xattr(dentry, &da);
1727 if (rc > 0) {
1728 ksmbd_kstat->file_attributes = cpu_to_le32(da.attr);
1729 ksmbd_kstat->create_time = da.create_time;
64b39f4a 1730 } else {
f4415848 1731 ksmbd_debug(VFS, "fail to load dos attribute.\n");
64b39f4a 1732 }
f4415848
NJ
1733 }
1734
1735 return 0;
1736}
1737
64b39f4a 1738ssize_t ksmbd_vfs_casexattr_len(struct dentry *dentry, char *attr_name,
070fb21e 1739 int attr_name_len)
f4415848
NJ
1740{
1741 char *name, *xattr_list = NULL;
1742 ssize_t value_len = -ENOENT, xattr_list_len;
1743
1744 xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
1745 if (xattr_list_len <= 0)
1746 goto out;
1747
1748 for (name = xattr_list; name - xattr_list < xattr_list_len;
1749 name += strlen(name) + 1) {
1750 ksmbd_debug(VFS, "%s, len %zd\n", name, strlen(name));
1751 if (strncasecmp(attr_name, name, attr_name_len))
1752 continue;
1753
1754 value_len = ksmbd_vfs_xattr_len(dentry, name);
1755 break;
1756 }
1757
1758out:
79f6b11a 1759 kvfree(xattr_list);
f4415848
NJ
1760 return value_len;
1761}
1762
64b39f4a 1763int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
070fb21e 1764 size_t *xattr_stream_name_size, int s_type)
f4415848
NJ
1765{
1766 int stream_name_size;
1767 char *xattr_stream_name_buf;
1768 char *type;
1769 int type_len;
1770
1771 if (s_type == DIR_STREAM)
1772 type = ":$INDEX_ALLOCATION";
1773 else
1774 type = ":$DATA";
1775
1776 type_len = strlen(type);
1777 stream_name_size = strlen(stream_name);
1778 *xattr_stream_name_size = stream_name_size + XATTR_NAME_STREAM_LEN + 1;
1779 xattr_stream_name_buf = kmalloc(*xattr_stream_name_size + type_len,
070fb21e 1780 GFP_KERNEL);
f4415848
NJ
1781 if (!xattr_stream_name_buf)
1782 return -ENOMEM;
1783
070fb21e 1784 memcpy(xattr_stream_name_buf, XATTR_NAME_STREAM, XATTR_NAME_STREAM_LEN);
f4415848
NJ
1785
1786 if (stream_name_size) {
1787 memcpy(&xattr_stream_name_buf[XATTR_NAME_STREAM_LEN],
070fb21e 1788 stream_name, stream_name_size);
f4415848
NJ
1789 }
1790 memcpy(&xattr_stream_name_buf[*xattr_stream_name_size - 1], type, type_len);
1791 *xattr_stream_name_size += type_len;
1792
1793 xattr_stream_name_buf[*xattr_stream_name_size - 1] = '\0';
1794 *xattr_stream_name = xattr_stream_name_buf;
1795
1796 return 0;
1797}
1798
eb817368 1799int ksmbd_vfs_copy_file_range(struct file *file_in, loff_t pos_in,
070fb21e 1800 struct file *file_out, loff_t pos_out, size_t len)
f4415848
NJ
1801{
1802 struct inode *inode_in = file_inode(file_in);
1803 struct inode *inode_out = file_inode(file_out);
1804 int ret;
1805
1806 ret = vfs_copy_file_range(file_in, pos_in, file_out, pos_out, len, 0);
1807 /* do splice for the copy between different file systems */
1808 if (ret != -EXDEV)
1809 return ret;
1810
1811 if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
1812 return -EISDIR;
1813 if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
1814 return -EINVAL;
1815
1816 if (!(file_in->f_mode & FMODE_READ) ||
1817 !(file_out->f_mode & FMODE_WRITE))
1818 return -EBADF;
1819
1820 if (len == 0)
1821 return 0;
1822
1823 file_start_write(file_out);
1824
1825 /*
1826 * skip the verification of the range of data. it will be done
1827 * in do_splice_direct
1828 */
1829 ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out,
070fb21e 1830 len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
f4415848
NJ
1831 if (ret > 0) {
1832 fsnotify_access(file_in);
1833 add_rchar(current, ret);
1834 fsnotify_modify(file_out);
1835 add_wchar(current, ret);
1836 }
1837
1838 inc_syscr(current);
1839 inc_syscw(current);
1840
1841 file_end_write(file_out);
1842 return ret;
1843}
1844
1845int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
070fb21e
NJ
1846 struct ksmbd_file *src_fp,
1847 struct ksmbd_file *dst_fp,
1848 struct srv_copychunk *chunks,
1849 unsigned int chunk_count,
1850 unsigned int *chunk_count_written,
1851 unsigned int *chunk_size_written,
1852 loff_t *total_size_written)
f4415848
NJ
1853{
1854 unsigned int i;
1855 loff_t src_off, dst_off, src_file_size;
1856 size_t len;
1857 int ret;
1858
1859 *chunk_count_written = 0;
1860 *chunk_size_written = 0;
1861 *total_size_written = 0;
1862
1863 if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
1864 ksmbd_err("no right to read(%s)\n", FP_FILENAME(src_fp));
1865 return -EACCES;
1866 }
1867 if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
1868 ksmbd_err("no right to write(%s)\n", FP_FILENAME(dst_fp));
1869 return -EACCES;
1870 }
1871
1872 if (ksmbd_stream_fd(src_fp) || ksmbd_stream_fd(dst_fp))
1873 return -EBADF;
1874
1875 smb_break_all_levII_oplock(work, dst_fp, 1);
1876
c36fca86
NJ
1877 if (!work->tcon->posix_extensions) {
1878 for (i = 0; i < chunk_count; i++) {
1879 src_off = le64_to_cpu(chunks[i].SourceOffset);
1880 dst_off = le64_to_cpu(chunks[i].TargetOffset);
1881 len = le32_to_cpu(chunks[i].Length);
1882
1883 if (check_lock_range(src_fp->filp, src_off,
64b39f4a 1884 src_off + len - 1, READ))
c36fca86
NJ
1885 return -EAGAIN;
1886 if (check_lock_range(dst_fp->filp, dst_off,
64b39f4a 1887 dst_off + len - 1, WRITE))
c36fca86
NJ
1888 return -EAGAIN;
1889 }
f4415848
NJ
1890 }
1891
1892 src_file_size = i_size_read(file_inode(src_fp->filp));
1893
1894 for (i = 0; i < chunk_count; i++) {
1895 src_off = le64_to_cpu(chunks[i].SourceOffset);
1896 dst_off = le64_to_cpu(chunks[i].TargetOffset);
1897 len = le32_to_cpu(chunks[i].Length);
1898
1899 if (src_off + len > src_file_size)
1900 return -E2BIG;
1901
1902 ret = ksmbd_vfs_copy_file_range(src_fp->filp, src_off,
070fb21e 1903 dst_fp->filp, dst_off, len);
f4415848
NJ
1904 if (ret < 0)
1905 return ret;
1906
1907 *chunk_count_written += 1;
1908 *total_size_written += ret;
1909 }
1910 return 0;
1911}
1912
1913int ksmbd_vfs_posix_lock_wait(struct file_lock *flock)
1914{
1915 return wait_event_interruptible(flock->fl_wait, !flock->fl_blocker);
1916}
1917
1918int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout)
1919{
1920 return wait_event_interruptible_timeout(flock->fl_wait,
1921 !flock->fl_blocker,
1922 timeout);
1923}
1924
1925void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock)
1926{
1927 locks_delete_block(flock);
1928}
1929
1930int ksmbd_vfs_set_init_posix_acl(struct inode *inode)
1931{
1932 struct posix_acl_state acl_state;
1933 struct posix_acl *acls;
1934 int rc;
1935
1936 ksmbd_debug(SMB, "Set posix acls\n");
1937 rc = init_acl_state(&acl_state, 1);
1938 if (rc)
1939 return rc;
1940
1941 /* Set default owner group */
1942 acl_state.owner.allow = (inode->i_mode & 0700) >> 6;
1943 acl_state.group.allow = (inode->i_mode & 0070) >> 3;
1944 acl_state.other.allow = inode->i_mode & 0007;
1945 acl_state.users->aces[acl_state.users->n].uid = inode->i_uid;
1946 acl_state.users->aces[acl_state.users->n++].perms.allow =
1947 acl_state.owner.allow;
1948 acl_state.groups->aces[acl_state.groups->n].gid = inode->i_gid;
1949 acl_state.groups->aces[acl_state.groups->n++].perms.allow =
1950 acl_state.group.allow;
1951 acl_state.mask.allow = 0x07;
1952
1953 acls = ksmbd_vfs_posix_acl_alloc(6, GFP_KERNEL);
1954 if (!acls) {
1955 free_acl_state(&acl_state);
1956 return -ENOMEM;
1957 }
1958 posix_state_to_acl(&acl_state, acls->a_entries);
1959 rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_ACCESS, acls);
1960 if (rc < 0)
1961 ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
070fb21e 1962 rc);
f4415848
NJ
1963 else if (S_ISDIR(inode->i_mode)) {
1964 posix_state_to_acl(&acl_state, acls->a_entries);
1965 rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_DEFAULT, acls);
1966 if (rc < 0)
1967 ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
070fb21e 1968 rc);
f4415848
NJ
1969 }
1970 free_acl_state(&acl_state);
1971 posix_acl_release(acls);
1972 return rc;
1973}
1974
1975int ksmbd_vfs_inherit_posix_acl(struct inode *inode, struct inode *parent_inode)
1976{
1977 struct posix_acl *acls;
1978 struct posix_acl_entry *pace;
1979 int rc, i;
1980
1981 acls = ksmbd_vfs_get_acl(parent_inode, ACL_TYPE_DEFAULT);
1982 if (!acls)
1983 return -ENOENT;
1984 pace = acls->a_entries;
1985
1986 for (i = 0; i < acls->a_count; i++, pace++) {
1987 if (pace->e_tag == ACL_MASK) {
1988 pace->e_perm = 0x07;
1989 break;
1990 }
1991 }
1992
1993 rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_ACCESS, acls);
1994 if (rc < 0)
1995 ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
070fb21e 1996 rc);
f4415848
NJ
1997 if (S_ISDIR(inode->i_mode)) {
1998 rc = ksmbd_vfs_set_posix_acl(inode, ACL_TYPE_DEFAULT, acls);
1999 if (rc < 0)
2000 ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
070fb21e 2001 rc);
f4415848
NJ
2002 }
2003 posix_acl_release(acls);
2004 return rc;
2005}