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