• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2017 Red Hat, Inc.
4  */
5 
6 #include <linux/cred.h>
7 #include <linux/file.h>
8 #include <linux/mount.h>
9 #include <linux/xattr.h>
10 #include <linux/uio.h>
11 #include <linux/uaccess.h>
12 #include <linux/splice.h>
13 #include <linux/mm.h>
14 #include <linux/fs.h>
15 #include "overlayfs.h"
16 
ovl_whatisit(struct inode * inode,struct inode * realinode)17 static char ovl_whatisit(struct inode *inode, struct inode *realinode)
18 {
19 	if (realinode != ovl_inode_upper(inode))
20 		return 'l';
21 	if (ovl_has_upperdata(inode))
22 		return 'u';
23 	else
24 		return 'm';
25 }
26 
27 /* No atime modificaton nor notify on underlying */
28 #define OVL_OPEN_FLAGS (O_NOATIME | FMODE_NONOTIFY)
29 
ovl_open_realfile(const struct file * file,struct inode * realinode)30 static struct file *ovl_open_realfile(const struct file *file,
31 				      struct inode *realinode)
32 {
33 	struct inode *inode = file_inode(file);
34 	struct file *realfile;
35 	const struct cred *old_cred;
36 	int flags = file->f_flags | OVL_OPEN_FLAGS;
37 
38 	old_cred = ovl_override_creds(inode->i_sb);
39 	realfile = open_with_fake_path(&file->f_path, flags, realinode,
40 				       current_cred());
41 	ovl_revert_creds(inode->i_sb, old_cred);
42 
43 	pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
44 		 file, file, ovl_whatisit(inode, realinode), file->f_flags,
45 		 realfile, IS_ERR(realfile) ? 0 : realfile->f_flags);
46 
47 	return realfile;
48 }
49 
50 #define OVL_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
51 
ovl_change_flags(struct file * file,unsigned int flags)52 static int ovl_change_flags(struct file *file, unsigned int flags)
53 {
54 	struct inode *inode = file_inode(file);
55 	int err;
56 
57 	flags |= OVL_OPEN_FLAGS;
58 
59 	/* If some flag changed that cannot be changed then something's amiss */
60 	if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK))
61 		return -EIO;
62 
63 	flags &= OVL_SETFL_MASK;
64 
65 	if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))
66 		return -EPERM;
67 
68 	if (flags & O_DIRECT) {
69 		if (!file->f_mapping->a_ops ||
70 		    !file->f_mapping->a_ops->direct_IO)
71 			return -EINVAL;
72 	}
73 
74 	if (file->f_op->check_flags) {
75 		err = file->f_op->check_flags(flags);
76 		if (err)
77 			return err;
78 	}
79 
80 	spin_lock(&file->f_lock);
81 	file->f_flags = (file->f_flags & ~OVL_SETFL_MASK) | flags;
82 	spin_unlock(&file->f_lock);
83 
84 	return 0;
85 }
86 
ovl_real_fdget_meta(const struct file * file,struct fd * real,bool allow_meta)87 static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
88 			       bool allow_meta)
89 {
90 	struct inode *inode = file_inode(file);
91 	struct inode *realinode;
92 
93 	real->flags = 0;
94 	real->file = file->private_data;
95 
96 	if (allow_meta)
97 		realinode = ovl_inode_real(inode);
98 	else
99 		realinode = ovl_inode_realdata(inode);
100 
101 	/* Has it been copied up since we'd opened it? */
102 	if (unlikely(file_inode(real->file) != realinode)) {
103 		real->flags = FDPUT_FPUT;
104 		real->file = ovl_open_realfile(file, realinode);
105 
106 		return PTR_ERR_OR_ZERO(real->file);
107 	}
108 
109 	/* Did the flags change since open? */
110 	if (unlikely((file->f_flags ^ real->file->f_flags) & ~OVL_OPEN_FLAGS))
111 		return ovl_change_flags(real->file, file->f_flags);
112 
113 	return 0;
114 }
115 
ovl_real_fdget(const struct file * file,struct fd * real)116 static int ovl_real_fdget(const struct file *file, struct fd *real)
117 {
118 	return ovl_real_fdget_meta(file, real, false);
119 }
120 
ovl_open(struct inode * inode,struct file * file)121 static int ovl_open(struct inode *inode, struct file *file)
122 {
123 	struct file *realfile;
124 	int err;
125 
126 	err = ovl_maybe_copy_up(file_dentry(file), file->f_flags);
127 	if (err)
128 		return err;
129 
130 	/* No longer need these flags, so don't pass them on to underlying fs */
131 	file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
132 
133 	realfile = ovl_open_realfile(file, ovl_inode_realdata(inode));
134 	if (IS_ERR(realfile))
135 		return PTR_ERR(realfile);
136 
137 	file->private_data = realfile;
138 
139 	return 0;
140 }
141 
ovl_release(struct inode * inode,struct file * file)142 static int ovl_release(struct inode *inode, struct file *file)
143 {
144 	fput(file->private_data);
145 
146 	return 0;
147 }
148 
ovl_llseek(struct file * file,loff_t offset,int whence)149 static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
150 {
151 	struct inode *inode = file_inode(file);
152 	struct fd real;
153 	const struct cred *old_cred;
154 	loff_t ret;
155 
156 	/*
157 	 * The two special cases below do not need to involve real fs,
158 	 * so we can optimizing concurrent callers.
159 	 */
160 	if (offset == 0) {
161 		if (whence == SEEK_CUR)
162 			return file->f_pos;
163 
164 		if (whence == SEEK_SET)
165 			return vfs_setpos(file, 0, 0);
166 	}
167 
168 	ret = ovl_real_fdget(file, &real);
169 	if (ret)
170 		return ret;
171 
172 	/*
173 	 * Overlay file f_pos is the master copy that is preserved
174 	 * through copy up and modified on read/write, but only real
175 	 * fs knows how to SEEK_HOLE/SEEK_DATA and real fs may impose
176 	 * limitations that are more strict than ->s_maxbytes for specific
177 	 * files, so we use the real file to perform seeks.
178 	 */
179 	inode_lock(inode);
180 	real.file->f_pos = file->f_pos;
181 
182 	old_cred = ovl_override_creds(inode->i_sb);
183 	ret = vfs_llseek(real.file, offset, whence);
184 	ovl_revert_creds(inode->i_sb, old_cred);
185 
186 	file->f_pos = real.file->f_pos;
187 	inode_unlock(inode);
188 
189 	fdput(real);
190 
191 	return ret;
192 }
193 
ovl_file_accessed(struct file * file)194 static void ovl_file_accessed(struct file *file)
195 {
196 	struct inode *inode, *upperinode;
197 
198 	if (file->f_flags & O_NOATIME)
199 		return;
200 
201 	inode = file_inode(file);
202 	upperinode = ovl_inode_upper(inode);
203 
204 	if (!upperinode)
205 		return;
206 
207 	if ((!timespec64_equal(&inode->i_mtime, &upperinode->i_mtime) ||
208 	     !timespec64_equal(&inode->i_ctime, &upperinode->i_ctime))) {
209 		inode->i_mtime = upperinode->i_mtime;
210 		inode->i_ctime = upperinode->i_ctime;
211 	}
212 
213 	touch_atime(&file->f_path);
214 }
215 
ovl_iocb_to_rwf(struct kiocb * iocb)216 static rwf_t ovl_iocb_to_rwf(struct kiocb *iocb)
217 {
218 	int ifl = iocb->ki_flags;
219 	rwf_t flags = 0;
220 
221 	if (ifl & IOCB_NOWAIT)
222 		flags |= RWF_NOWAIT;
223 	if (ifl & IOCB_HIPRI)
224 		flags |= RWF_HIPRI;
225 	if (ifl & IOCB_DSYNC)
226 		flags |= RWF_DSYNC;
227 	if (ifl & IOCB_SYNC)
228 		flags |= RWF_SYNC;
229 
230 	return flags;
231 }
232 
ovl_read_iter(struct kiocb * iocb,struct iov_iter * iter)233 static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
234 {
235 	struct file *file = iocb->ki_filp;
236 	struct fd real;
237 	const struct cred *old_cred;
238 	ssize_t ret;
239 
240 	if (!iov_iter_count(iter))
241 		return 0;
242 
243 	ret = ovl_real_fdget(file, &real);
244 	if (ret)
245 		return ret;
246 
247 	old_cred = ovl_override_creds(file_inode(file)->i_sb);
248 	ret = vfs_iter_read(real.file, iter, &iocb->ki_pos,
249 			    ovl_iocb_to_rwf(iocb));
250 	ovl_revert_creds(file_inode(file)->i_sb, old_cred);
251 
252 	ovl_file_accessed(file);
253 
254 	fdput(real);
255 
256 	return ret;
257 }
258 
ovl_write_iter(struct kiocb * iocb,struct iov_iter * iter)259 static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
260 {
261 	struct file *file = iocb->ki_filp;
262 	struct inode *inode = file_inode(file);
263 	struct fd real;
264 	const struct cred *old_cred;
265 	ssize_t ret;
266 
267 	if (!iov_iter_count(iter))
268 		return 0;
269 
270 	inode_lock(inode);
271 	/* Update mode */
272 	ovl_copyattr(ovl_inode_real(inode), inode);
273 	ret = file_remove_privs(file);
274 	if (ret)
275 		goto out_unlock;
276 
277 	ret = ovl_real_fdget(file, &real);
278 	if (ret)
279 		goto out_unlock;
280 
281 	old_cred = ovl_override_creds(file_inode(file)->i_sb);
282 	file_start_write(real.file);
283 	ret = vfs_iter_write(real.file, iter, &iocb->ki_pos,
284 			     ovl_iocb_to_rwf(iocb));
285 	file_end_write(real.file);
286 	ovl_revert_creds(file_inode(file)->i_sb, old_cred);
287 
288 	/* Update size */
289 	ovl_copyattr(ovl_inode_real(inode), inode);
290 
291 	fdput(real);
292 
293 out_unlock:
294 	inode_unlock(inode);
295 
296 	return ret;
297 }
298 
299 /*
300  * Calling iter_file_splice_write() directly from overlay's f_op may deadlock
301  * due to lock order inversion between pipe->mutex in iter_file_splice_write()
302  * and file_start_write(real.file) in ovl_write_iter().
303  *
304  * So do everything ovl_write_iter() does and call iter_file_splice_write() on
305  * the real file.
306  */
ovl_splice_write(struct pipe_inode_info * pipe,struct file * out,loff_t * ppos,size_t len,unsigned int flags)307 static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
308 				loff_t *ppos, size_t len, unsigned int flags)
309 {
310 	struct fd real;
311 	const struct cred *old_cred;
312 	struct inode *inode = file_inode(out);
313 	struct inode *realinode = ovl_inode_real(inode);
314 	ssize_t ret;
315 
316 	inode_lock(inode);
317 	/* Update mode */
318 	ovl_copyattr(realinode, inode);
319 	ret = file_remove_privs(out);
320 	if (ret)
321 		goto out_unlock;
322 
323 	ret = ovl_real_fdget(out, &real);
324 	if (ret)
325 		goto out_unlock;
326 
327 	old_cred = ovl_override_creds(inode->i_sb);
328 	file_start_write(real.file);
329 
330 	ret = iter_file_splice_write(pipe, real.file, ppos, len, flags);
331 
332 	file_end_write(real.file);
333 	/* Update size */
334 	ovl_copyattr(realinode, inode);
335 	revert_creds(old_cred);
336 	fdput(real);
337 
338 out_unlock:
339 	inode_unlock(inode);
340 
341 	return ret;
342 }
343 
ovl_fsync(struct file * file,loff_t start,loff_t end,int datasync)344 static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
345 {
346 	struct fd real;
347 	const struct cred *old_cred;
348 	int ret;
349 
350 	ret = ovl_real_fdget_meta(file, &real, !datasync);
351 	if (ret)
352 		return ret;
353 
354 	/* Don't sync lower file for fear of receiving EROFS error */
355 	if (file_inode(real.file) == ovl_inode_upper(file_inode(file))) {
356 		old_cred = ovl_override_creds(file_inode(file)->i_sb);
357 		ret = vfs_fsync_range(real.file, start, end, datasync);
358 		ovl_revert_creds(file_inode(file)->i_sb, old_cred);
359 	}
360 
361 	fdput(real);
362 
363 	return ret;
364 }
365 
ovl_mmap(struct file * file,struct vm_area_struct * vma)366 static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
367 {
368 	struct file *realfile = file->private_data;
369 	const struct cred *old_cred;
370 	int ret;
371 
372 	if (!realfile->f_op->mmap)
373 		return -ENODEV;
374 
375 	if (WARN_ON(file != vma->vm_file))
376 		return -EIO;
377 
378 	vma->vm_file = get_file(realfile);
379 
380 	old_cred = ovl_override_creds(file_inode(file)->i_sb);
381 	ret = call_mmap(vma->vm_file, vma);
382 	ovl_revert_creds(file_inode(file)->i_sb, old_cred);
383 
384 	if (ret) {
385 		/* Drop reference count from new vm_file value */
386 		fput(realfile);
387 	} else {
388 		/* Drop reference count from previous vm_file value */
389 		fput(file);
390 	}
391 
392 	ovl_file_accessed(file);
393 
394 	return ret;
395 }
396 
ovl_fallocate(struct file * file,int mode,loff_t offset,loff_t len)397 static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
398 {
399 	struct inode *inode = file_inode(file);
400 	struct fd real;
401 	const struct cred *old_cred;
402 	int ret;
403 
404 	ret = ovl_real_fdget(file, &real);
405 	if (ret)
406 		return ret;
407 
408 	old_cred = ovl_override_creds(file_inode(file)->i_sb);
409 	ret = vfs_fallocate(real.file, mode, offset, len);
410 	ovl_revert_creds(file_inode(file)->i_sb, old_cred);
411 
412 	/* Update size */
413 	ovl_copyattr(ovl_inode_real(inode), inode);
414 
415 	fdput(real);
416 
417 	return ret;
418 }
419 
ovl_fadvise(struct file * file,loff_t offset,loff_t len,int advice)420 static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
421 {
422 	struct fd real;
423 	const struct cred *old_cred;
424 	int ret;
425 
426 	ret = ovl_real_fdget(file, &real);
427 	if (ret)
428 		return ret;
429 
430 	old_cred = ovl_override_creds(file_inode(file)->i_sb);
431 	ret = vfs_fadvise(real.file, offset, len, advice);
432 	ovl_revert_creds(file_inode(file)->i_sb, old_cred);
433 
434 	fdput(real);
435 
436 	return ret;
437 }
438 
ovl_real_ioctl(struct file * file,unsigned int cmd,unsigned long arg)439 static long ovl_real_ioctl(struct file *file, unsigned int cmd,
440 			   unsigned long arg)
441 {
442 	struct fd real;
443 	const struct cred *old_cred;
444 	long ret;
445 
446 	ret = ovl_real_fdget(file, &real);
447 	if (ret)
448 		return ret;
449 
450 	old_cred = ovl_override_creds(file_inode(file)->i_sb);
451 	ret = vfs_ioctl(real.file, cmd, arg);
452 	ovl_revert_creds(file_inode(file)->i_sb, old_cred);
453 
454 	fdput(real);
455 
456 	return ret;
457 }
458 
ovl_ioctl_set_flags(struct file * file,unsigned int cmd,unsigned long arg,unsigned int iflags)459 static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
460 				unsigned long arg, unsigned int iflags)
461 {
462 	long ret;
463 	struct inode *inode = file_inode(file);
464 	unsigned int old_iflags;
465 
466 	if (!inode_owner_or_capable(inode))
467 		return -EACCES;
468 
469 	ret = mnt_want_write_file(file);
470 	if (ret)
471 		return ret;
472 
473 	inode_lock(inode);
474 
475 	/* Check the capability before cred override */
476 	ret = -EPERM;
477 	old_iflags = READ_ONCE(inode->i_flags);
478 	if (((iflags ^ old_iflags) & (S_APPEND | S_IMMUTABLE)) &&
479 	    !capable(CAP_LINUX_IMMUTABLE))
480 		goto unlock;
481 
482 	ret = ovl_maybe_copy_up(file_dentry(file), O_WRONLY);
483 	if (ret)
484 		goto unlock;
485 
486 	ret = ovl_real_ioctl(file, cmd, arg);
487 
488 	ovl_copyflags(ovl_inode_real(inode), inode);
489 unlock:
490 	inode_unlock(inode);
491 
492 	mnt_drop_write_file(file);
493 
494 	return ret;
495 
496 }
497 
ovl_fsflags_to_iflags(unsigned int flags)498 static unsigned int ovl_fsflags_to_iflags(unsigned int flags)
499 {
500 	unsigned int iflags = 0;
501 
502 	if (flags & FS_SYNC_FL)
503 		iflags |= S_SYNC;
504 	if (flags & FS_APPEND_FL)
505 		iflags |= S_APPEND;
506 	if (flags & FS_IMMUTABLE_FL)
507 		iflags |= S_IMMUTABLE;
508 	if (flags & FS_NOATIME_FL)
509 		iflags |= S_NOATIME;
510 
511 	return iflags;
512 }
513 
ovl_ioctl_set_fsflags(struct file * file,unsigned int cmd,unsigned long arg)514 static long ovl_ioctl_set_fsflags(struct file *file, unsigned int cmd,
515 				  unsigned long arg)
516 {
517 	unsigned int flags;
518 
519 	if (get_user(flags, (int __user *) arg))
520 		return -EFAULT;
521 
522 	return ovl_ioctl_set_flags(file, cmd, arg,
523 				   ovl_fsflags_to_iflags(flags));
524 }
525 
ovl_fsxflags_to_iflags(unsigned int xflags)526 static unsigned int ovl_fsxflags_to_iflags(unsigned int xflags)
527 {
528 	unsigned int iflags = 0;
529 
530 	if (xflags & FS_XFLAG_SYNC)
531 		iflags |= S_SYNC;
532 	if (xflags & FS_XFLAG_APPEND)
533 		iflags |= S_APPEND;
534 	if (xflags & FS_XFLAG_IMMUTABLE)
535 		iflags |= S_IMMUTABLE;
536 	if (xflags & FS_XFLAG_NOATIME)
537 		iflags |= S_NOATIME;
538 
539 	return iflags;
540 }
541 
ovl_ioctl_set_fsxflags(struct file * file,unsigned int cmd,unsigned long arg)542 static long ovl_ioctl_set_fsxflags(struct file *file, unsigned int cmd,
543 				   unsigned long arg)
544 {
545 	struct fsxattr fa;
546 
547 	memset(&fa, 0, sizeof(fa));
548 	if (copy_from_user(&fa, (void __user *) arg, sizeof(fa)))
549 		return -EFAULT;
550 
551 	return ovl_ioctl_set_flags(file, cmd, arg,
552 				   ovl_fsxflags_to_iflags(fa.fsx_xflags));
553 }
554 
ovl_ioctl(struct file * file,unsigned int cmd,unsigned long arg)555 static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
556 {
557 	long ret;
558 
559 	switch (cmd) {
560 	case FS_IOC_GETFLAGS:
561 	case FS_IOC_FSGETXATTR:
562 		ret = ovl_real_ioctl(file, cmd, arg);
563 		break;
564 
565 	case FS_IOC_SETFLAGS:
566 		ret = ovl_ioctl_set_fsflags(file, cmd, arg);
567 		break;
568 
569 	case FS_IOC_FSSETXATTR:
570 		ret = ovl_ioctl_set_fsxflags(file, cmd, arg);
571 		break;
572 
573 	default:
574 		ret = -ENOTTY;
575 	}
576 
577 	return ret;
578 }
579 
ovl_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)580 static long ovl_compat_ioctl(struct file *file, unsigned int cmd,
581 			     unsigned long arg)
582 {
583 	switch (cmd) {
584 	case FS_IOC32_GETFLAGS:
585 		cmd = FS_IOC_GETFLAGS;
586 		break;
587 
588 	case FS_IOC32_SETFLAGS:
589 		cmd = FS_IOC_SETFLAGS;
590 		break;
591 
592 	default:
593 		return -ENOIOCTLCMD;
594 	}
595 
596 	return ovl_ioctl(file, cmd, arg);
597 }
598 
599 enum ovl_copyop {
600 	OVL_COPY,
601 	OVL_CLONE,
602 	OVL_DEDUPE,
603 };
604 
ovl_copyfile(struct file * file_in,loff_t pos_in,struct file * file_out,loff_t pos_out,loff_t len,unsigned int flags,enum ovl_copyop op)605 static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
606 			    struct file *file_out, loff_t pos_out,
607 			    loff_t len, unsigned int flags, enum ovl_copyop op)
608 {
609 	struct inode *inode_out = file_inode(file_out);
610 	struct fd real_in, real_out;
611 	const struct cred *old_cred;
612 	loff_t ret;
613 
614 	ret = ovl_real_fdget(file_out, &real_out);
615 	if (ret)
616 		return ret;
617 
618 	ret = ovl_real_fdget(file_in, &real_in);
619 	if (ret) {
620 		fdput(real_out);
621 		return ret;
622 	}
623 
624 	old_cred = ovl_override_creds(file_inode(file_out)->i_sb);
625 	switch (op) {
626 	case OVL_COPY:
627 		ret = vfs_copy_file_range(real_in.file, pos_in,
628 					  real_out.file, pos_out, len, flags);
629 		break;
630 
631 	case OVL_CLONE:
632 		ret = vfs_clone_file_range(real_in.file, pos_in,
633 					   real_out.file, pos_out, len, flags);
634 		break;
635 
636 	case OVL_DEDUPE:
637 		ret = vfs_dedupe_file_range_one(real_in.file, pos_in,
638 						real_out.file, pos_out, len,
639 						flags);
640 		break;
641 	}
642 	ovl_revert_creds(file_inode(file_out)->i_sb, old_cred);
643 
644 	/* Update size */
645 	ovl_copyattr(ovl_inode_real(inode_out), inode_out);
646 
647 	fdput(real_in);
648 	fdput(real_out);
649 
650 	return ret;
651 }
652 
ovl_copy_file_range(struct file * file_in,loff_t pos_in,struct file * file_out,loff_t pos_out,size_t len,unsigned int flags)653 static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in,
654 				   struct file *file_out, loff_t pos_out,
655 				   size_t len, unsigned int flags)
656 {
657 	return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags,
658 			    OVL_COPY);
659 }
660 
ovl_remap_file_range(struct file * file_in,loff_t pos_in,struct file * file_out,loff_t pos_out,loff_t len,unsigned int remap_flags)661 static loff_t ovl_remap_file_range(struct file *file_in, loff_t pos_in,
662 				   struct file *file_out, loff_t pos_out,
663 				   loff_t len, unsigned int remap_flags)
664 {
665 	enum ovl_copyop op;
666 
667 	if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
668 		return -EINVAL;
669 
670 	if (remap_flags & REMAP_FILE_DEDUP)
671 		op = OVL_DEDUPE;
672 	else
673 		op = OVL_CLONE;
674 
675 	/*
676 	 * Don't copy up because of a dedupe request, this wouldn't make sense
677 	 * most of the time (data would be duplicated instead of deduplicated).
678 	 */
679 	if (op == OVL_DEDUPE &&
680 	    (!ovl_inode_upper(file_inode(file_in)) ||
681 	     !ovl_inode_upper(file_inode(file_out))))
682 		return -EPERM;
683 
684 	return ovl_copyfile(file_in, pos_in, file_out, pos_out, len,
685 			    remap_flags, op);
686 }
687 
688 const struct file_operations ovl_file_operations = {
689 	.open		= ovl_open,
690 	.release	= ovl_release,
691 	.llseek		= ovl_llseek,
692 	.read_iter	= ovl_read_iter,
693 	.write_iter	= ovl_write_iter,
694 	.fsync		= ovl_fsync,
695 	.mmap		= ovl_mmap,
696 	.fallocate	= ovl_fallocate,
697 	.fadvise	= ovl_fadvise,
698 	.unlocked_ioctl	= ovl_ioctl,
699 	.compat_ioctl	= ovl_compat_ioctl,
700 	.splice_read    = generic_file_splice_read,
701 	.splice_write   = ovl_splice_write,
702 
703 	.copy_file_range	= ovl_copy_file_range,
704 	.remap_file_range	= ovl_remap_file_range,
705 };
706