1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2017 Red Hat, Inc.
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 "overlayfs.h"
14 static char ovl_whatisit(struct inode
*inode
, struct inode
*realinode
)
16 if (realinode
!= ovl_inode_upper(inode
))
18 if (ovl_has_upperdata(inode
))
24 /* No atime modificaton nor notify on underlying */
25 #define OVL_OPEN_FLAGS (O_NOATIME | FMODE_NONOTIFY)
27 static struct file
*ovl_open_realfile(const struct file
*file
,
28 struct inode
*realinode
)
30 struct inode
*inode
= file_inode(file
);
31 struct file
*realfile
;
32 const struct cred
*old_cred
;
33 int flags
= file
->f_flags
| OVL_OPEN_FLAGS
;
35 old_cred
= ovl_override_creds(inode
->i_sb
);
36 realfile
= open_with_fake_path(&file
->f_path
, flags
, realinode
,
38 revert_creds(old_cred
);
40 pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
41 file
, file
, ovl_whatisit(inode
, realinode
), file
->f_flags
,
42 realfile
, IS_ERR(realfile
) ? 0 : realfile
->f_flags
);
47 #define OVL_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
49 static int ovl_change_flags(struct file
*file
, unsigned int flags
)
51 struct inode
*inode
= file_inode(file
);
54 flags
|= OVL_OPEN_FLAGS
;
56 /* If some flag changed that cannot be changed then something's amiss */
57 if (WARN_ON((file
->f_flags
^ flags
) & ~OVL_SETFL_MASK
))
60 flags
&= OVL_SETFL_MASK
;
62 if (((flags
^ file
->f_flags
) & O_APPEND
) && IS_APPEND(inode
))
65 if (flags
& O_DIRECT
) {
66 if (!file
->f_mapping
->a_ops
||
67 !file
->f_mapping
->a_ops
->direct_IO
)
71 if (file
->f_op
->check_flags
) {
72 err
= file
->f_op
->check_flags(flags
);
77 spin_lock(&file
->f_lock
);
78 file
->f_flags
= (file
->f_flags
& ~OVL_SETFL_MASK
) | flags
;
79 spin_unlock(&file
->f_lock
);
84 static int ovl_real_fdget_meta(const struct file
*file
, struct fd
*real
,
87 struct inode
*inode
= file_inode(file
);
88 struct inode
*realinode
;
91 real
->file
= file
->private_data
;
94 realinode
= ovl_inode_real(inode
);
96 realinode
= ovl_inode_realdata(inode
);
98 /* Has it been copied up since we'd opened it? */
99 if (unlikely(file_inode(real
->file
) != realinode
)) {
100 real
->flags
= FDPUT_FPUT
;
101 real
->file
= ovl_open_realfile(file
, realinode
);
103 return PTR_ERR_OR_ZERO(real
->file
);
106 /* Did the flags change since open? */
107 if (unlikely((file
->f_flags
^ real
->file
->f_flags
) & ~OVL_OPEN_FLAGS
))
108 return ovl_change_flags(real
->file
, file
->f_flags
);
113 static int ovl_real_fdget(const struct file
*file
, struct fd
*real
)
115 return ovl_real_fdget_meta(file
, real
, false);
118 static int ovl_open(struct inode
*inode
, struct file
*file
)
120 struct file
*realfile
;
123 err
= ovl_maybe_copy_up(file_dentry(file
), file
->f_flags
);
127 /* No longer need these flags, so don't pass them on to underlying fs */
128 file
->f_flags
&= ~(O_CREAT
| O_EXCL
| O_NOCTTY
| O_TRUNC
);
130 realfile
= ovl_open_realfile(file
, ovl_inode_realdata(inode
));
131 if (IS_ERR(realfile
))
132 return PTR_ERR(realfile
);
134 file
->private_data
= realfile
;
139 static int ovl_release(struct inode
*inode
, struct file
*file
)
141 fput(file
->private_data
);
146 static loff_t
ovl_llseek(struct file
*file
, loff_t offset
, int whence
)
148 struct inode
*inode
= file_inode(file
);
150 const struct cred
*old_cred
;
154 * The two special cases below do not need to involve real fs,
155 * so we can optimizing concurrent callers.
158 if (whence
== SEEK_CUR
)
161 if (whence
== SEEK_SET
)
162 return vfs_setpos(file
, 0, 0);
165 ret
= ovl_real_fdget(file
, &real
);
170 * Overlay file f_pos is the master copy that is preserved
171 * through copy up and modified on read/write, but only real
172 * fs knows how to SEEK_HOLE/SEEK_DATA and real fs may impose
173 * limitations that are more strict than ->s_maxbytes for specific
174 * files, so we use the real file to perform seeks.
177 real
.file
->f_pos
= file
->f_pos
;
179 old_cred
= ovl_override_creds(inode
->i_sb
);
180 ret
= vfs_llseek(real
.file
, offset
, whence
);
181 revert_creds(old_cred
);
183 file
->f_pos
= real
.file
->f_pos
;
191 static void ovl_file_accessed(struct file
*file
)
193 struct inode
*inode
, *upperinode
;
195 if (file
->f_flags
& O_NOATIME
)
198 inode
= file_inode(file
);
199 upperinode
= ovl_inode_upper(inode
);
204 if ((!timespec64_equal(&inode
->i_mtime
, &upperinode
->i_mtime
) ||
205 !timespec64_equal(&inode
->i_ctime
, &upperinode
->i_ctime
))) {
206 inode
->i_mtime
= upperinode
->i_mtime
;
207 inode
->i_ctime
= upperinode
->i_ctime
;
210 touch_atime(&file
->f_path
);
213 static rwf_t
ovl_iocb_to_rwf(struct kiocb
*iocb
)
215 int ifl
= iocb
->ki_flags
;
218 if (ifl
& IOCB_NOWAIT
)
220 if (ifl
& IOCB_HIPRI
)
222 if (ifl
& IOCB_DSYNC
)
230 static ssize_t
ovl_read_iter(struct kiocb
*iocb
, struct iov_iter
*iter
)
232 struct file
*file
= iocb
->ki_filp
;
234 const struct cred
*old_cred
;
237 if (!iov_iter_count(iter
))
240 ret
= ovl_real_fdget(file
, &real
);
244 old_cred
= ovl_override_creds(file_inode(file
)->i_sb
);
245 ret
= vfs_iter_read(real
.file
, iter
, &iocb
->ki_pos
,
246 ovl_iocb_to_rwf(iocb
));
247 revert_creds(old_cred
);
249 ovl_file_accessed(file
);
256 static ssize_t
ovl_write_iter(struct kiocb
*iocb
, struct iov_iter
*iter
)
258 struct file
*file
= iocb
->ki_filp
;
259 struct inode
*inode
= file_inode(file
);
261 const struct cred
*old_cred
;
264 if (!iov_iter_count(iter
))
269 ovl_copyattr(ovl_inode_real(inode
), inode
);
270 ret
= file_remove_privs(file
);
274 ret
= ovl_real_fdget(file
, &real
);
278 old_cred
= ovl_override_creds(file_inode(file
)->i_sb
);
279 file_start_write(real
.file
);
280 ret
= vfs_iter_write(real
.file
, iter
, &iocb
->ki_pos
,
281 ovl_iocb_to_rwf(iocb
));
282 file_end_write(real
.file
);
283 revert_creds(old_cred
);
286 ovl_copyattr(ovl_inode_real(inode
), inode
);
296 static int ovl_fsync(struct file
*file
, loff_t start
, loff_t end
, int datasync
)
299 const struct cred
*old_cred
;
302 ret
= ovl_real_fdget_meta(file
, &real
, !datasync
);
306 /* Don't sync lower file for fear of receiving EROFS error */
307 if (file_inode(real
.file
) == ovl_inode_upper(file_inode(file
))) {
308 old_cred
= ovl_override_creds(file_inode(file
)->i_sb
);
309 ret
= vfs_fsync_range(real
.file
, start
, end
, datasync
);
310 revert_creds(old_cred
);
318 static int ovl_mmap(struct file
*file
, struct vm_area_struct
*vma
)
320 struct file
*realfile
= file
->private_data
;
321 const struct cred
*old_cred
;
324 if (!realfile
->f_op
->mmap
)
327 if (WARN_ON(file
!= vma
->vm_file
))
330 vma
->vm_file
= get_file(realfile
);
332 old_cred
= ovl_override_creds(file_inode(file
)->i_sb
);
333 ret
= call_mmap(vma
->vm_file
, vma
);
334 revert_creds(old_cred
);
337 /* Drop reference count from new vm_file value */
340 /* Drop reference count from previous vm_file value */
344 ovl_file_accessed(file
);
349 static long ovl_fallocate(struct file
*file
, int mode
, loff_t offset
, loff_t len
)
351 struct inode
*inode
= file_inode(file
);
353 const struct cred
*old_cred
;
356 ret
= ovl_real_fdget(file
, &real
);
360 old_cred
= ovl_override_creds(file_inode(file
)->i_sb
);
361 ret
= vfs_fallocate(real
.file
, mode
, offset
, len
);
362 revert_creds(old_cred
);
365 ovl_copyattr(ovl_inode_real(inode
), inode
);
372 static int ovl_fadvise(struct file
*file
, loff_t offset
, loff_t len
, int advice
)
375 const struct cred
*old_cred
;
378 ret
= ovl_real_fdget(file
, &real
);
382 old_cred
= ovl_override_creds(file_inode(file
)->i_sb
);
383 ret
= vfs_fadvise(real
.file
, offset
, len
, advice
);
384 revert_creds(old_cred
);
391 static long ovl_real_ioctl(struct file
*file
, unsigned int cmd
,
395 const struct cred
*old_cred
;
398 ret
= ovl_real_fdget(file
, &real
);
402 old_cred
= ovl_override_creds(file_inode(file
)->i_sb
);
403 ret
= vfs_ioctl(real
.file
, cmd
, arg
);
404 revert_creds(old_cred
);
411 static long ovl_ioctl_set_flags(struct file
*file
, unsigned int cmd
,
412 unsigned long arg
, unsigned int iflags
)
415 struct inode
*inode
= file_inode(file
);
416 unsigned int old_iflags
;
418 if (!inode_owner_or_capable(inode
))
421 ret
= mnt_want_write_file(file
);
427 /* Check the capability before cred override */
429 old_iflags
= READ_ONCE(inode
->i_flags
);
430 if (((iflags
^ old_iflags
) & (S_APPEND
| S_IMMUTABLE
)) &&
431 !capable(CAP_LINUX_IMMUTABLE
))
434 ret
= ovl_maybe_copy_up(file_dentry(file
), O_WRONLY
);
438 ret
= ovl_real_ioctl(file
, cmd
, arg
);
440 ovl_copyflags(ovl_inode_real(inode
), inode
);
444 mnt_drop_write_file(file
);
450 static unsigned int ovl_fsflags_to_iflags(unsigned int flags
)
452 unsigned int iflags
= 0;
454 if (flags
& FS_SYNC_FL
)
456 if (flags
& FS_APPEND_FL
)
458 if (flags
& FS_IMMUTABLE_FL
)
459 iflags
|= S_IMMUTABLE
;
460 if (flags
& FS_NOATIME_FL
)
466 static long ovl_ioctl_set_fsflags(struct file
*file
, unsigned int cmd
,
471 if (get_user(flags
, (int __user
*) arg
))
474 return ovl_ioctl_set_flags(file
, cmd
, arg
,
475 ovl_fsflags_to_iflags(flags
));
478 static unsigned int ovl_fsxflags_to_iflags(unsigned int xflags
)
480 unsigned int iflags
= 0;
482 if (xflags
& FS_XFLAG_SYNC
)
484 if (xflags
& FS_XFLAG_APPEND
)
486 if (xflags
& FS_XFLAG_IMMUTABLE
)
487 iflags
|= S_IMMUTABLE
;
488 if (xflags
& FS_XFLAG_NOATIME
)
494 static long ovl_ioctl_set_fsxflags(struct file
*file
, unsigned int cmd
,
499 memset(&fa
, 0, sizeof(fa
));
500 if (copy_from_user(&fa
, (void __user
*) arg
, sizeof(fa
)))
503 return ovl_ioctl_set_flags(file
, cmd
, arg
,
504 ovl_fsxflags_to_iflags(fa
.fsx_xflags
));
507 static long ovl_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
512 case FS_IOC_GETFLAGS
:
513 case FS_IOC_FSGETXATTR
:
514 ret
= ovl_real_ioctl(file
, cmd
, arg
);
517 case FS_IOC_SETFLAGS
:
518 ret
= ovl_ioctl_set_fsflags(file
, cmd
, arg
);
521 case FS_IOC_FSSETXATTR
:
522 ret
= ovl_ioctl_set_fsxflags(file
, cmd
, arg
);
532 static long ovl_compat_ioctl(struct file
*file
, unsigned int cmd
,
536 case FS_IOC32_GETFLAGS
:
537 cmd
= FS_IOC_GETFLAGS
;
540 case FS_IOC32_SETFLAGS
:
541 cmd
= FS_IOC_SETFLAGS
;
548 return ovl_ioctl(file
, cmd
, arg
);
557 static loff_t
ovl_copyfile(struct file
*file_in
, loff_t pos_in
,
558 struct file
*file_out
, loff_t pos_out
,
559 loff_t len
, unsigned int flags
, enum ovl_copyop op
)
561 struct inode
*inode_out
= file_inode(file_out
);
562 struct fd real_in
, real_out
;
563 const struct cred
*old_cred
;
566 ret
= ovl_real_fdget(file_out
, &real_out
);
570 ret
= ovl_real_fdget(file_in
, &real_in
);
576 old_cred
= ovl_override_creds(file_inode(file_out
)->i_sb
);
579 ret
= vfs_copy_file_range(real_in
.file
, pos_in
,
580 real_out
.file
, pos_out
, len
, flags
);
584 ret
= vfs_clone_file_range(real_in
.file
, pos_in
,
585 real_out
.file
, pos_out
, len
, flags
);
589 ret
= vfs_dedupe_file_range_one(real_in
.file
, pos_in
,
590 real_out
.file
, pos_out
, len
,
594 revert_creds(old_cred
);
597 ovl_copyattr(ovl_inode_real(inode_out
), inode_out
);
605 static ssize_t
ovl_copy_file_range(struct file
*file_in
, loff_t pos_in
,
606 struct file
*file_out
, loff_t pos_out
,
607 size_t len
, unsigned int flags
)
609 return ovl_copyfile(file_in
, pos_in
, file_out
, pos_out
, len
, flags
,
613 static loff_t
ovl_remap_file_range(struct file
*file_in
, loff_t pos_in
,
614 struct file
*file_out
, loff_t pos_out
,
615 loff_t len
, unsigned int remap_flags
)
619 if (remap_flags
& ~(REMAP_FILE_DEDUP
| REMAP_FILE_ADVISORY
))
622 if (remap_flags
& REMAP_FILE_DEDUP
)
628 * Don't copy up because of a dedupe request, this wouldn't make sense
629 * most of the time (data would be duplicated instead of deduplicated).
631 if (op
== OVL_DEDUPE
&&
632 (!ovl_inode_upper(file_inode(file_in
)) ||
633 !ovl_inode_upper(file_inode(file_out
))))
636 return ovl_copyfile(file_in
, pos_in
, file_out
, pos_out
, len
,
640 const struct file_operations ovl_file_operations
= {
642 .release
= ovl_release
,
643 .llseek
= ovl_llseek
,
644 .read_iter
= ovl_read_iter
,
645 .write_iter
= ovl_write_iter
,
648 .fallocate
= ovl_fallocate
,
649 .fadvise
= ovl_fadvise
,
650 .unlocked_ioctl
= ovl_ioctl
,
651 .compat_ioctl
= ovl_compat_ioctl
,
653 .copy_file_range
= ovl_copy_file_range
,
654 .remap_file_range
= ovl_remap_file_range
,