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