^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include "fuse_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/fuse.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/uio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define PASSTHROUGH_IOCB_MASK \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) (IOCB_APPEND | IOCB_DSYNC | IOCB_HIPRI | IOCB_NOWAIT | IOCB_SYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) struct fuse_aio_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct kiocb iocb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct kiocb *iocb_fuse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static void fuse_file_accessed(struct file *dst_file, struct file *src_file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct inode *dst_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct inode *src_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) if (dst_file->f_flags & O_NOATIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) dst_inode = file_inode(dst_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) src_inode = file_inode(src_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if ((!timespec64_equal(&dst_inode->i_mtime, &src_inode->i_mtime) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) !timespec64_equal(&dst_inode->i_ctime, &src_inode->i_ctime))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) dst_inode->i_mtime = src_inode->i_mtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) dst_inode->i_ctime = src_inode->i_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) touch_atime(&dst_file->f_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void fuse_copyattr(struct file *dst_file, struct file *src_file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct inode *dst = file_inode(dst_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct inode *src = file_inode(src_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) dst->i_atime = src->i_atime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) dst->i_mtime = src->i_mtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) dst->i_ctime = src->i_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) i_size_write(dst, i_size_read(src));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static void fuse_aio_cleanup_handler(struct fuse_aio_req *aio_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct kiocb *iocb = &aio_req->iocb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct kiocb *iocb_fuse = aio_req->iocb_fuse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (iocb->ki_flags & IOCB_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) __sb_writers_acquired(file_inode(iocb->ki_filp)->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) SB_FREEZE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) file_end_write(iocb->ki_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) fuse_copyattr(iocb_fuse->ki_filp, iocb->ki_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) iocb_fuse->ki_pos = iocb->ki_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) kfree(aio_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static void fuse_aio_rw_complete(struct kiocb *iocb, long res, long res2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct fuse_aio_req *aio_req =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) container_of(iocb, struct fuse_aio_req, iocb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct kiocb *iocb_fuse = aio_req->iocb_fuse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) fuse_aio_cleanup_handler(aio_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) iocb_fuse->ki_complete(iocb_fuse, res, res2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct iov_iter *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) const struct cred *old_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct file *fuse_filp = iocb_fuse->ki_filp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct fuse_file *ff = fuse_filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct file *passthrough_filp = ff->passthrough.filp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!iov_iter_count(iter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) old_cred = override_creds(ff->passthrough.cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (is_sync_kiocb(iocb_fuse)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) iocb_to_rw_flags(iocb_fuse->ki_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) PASSTHROUGH_IOCB_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct fuse_aio_req *aio_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) aio_req = kmalloc(sizeof(struct fuse_aio_req), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!aio_req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) aio_req->iocb_fuse = iocb_fuse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) kiocb_clone(&aio_req->iocb, iocb_fuse, passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) aio_req->iocb.ki_complete = fuse_aio_rw_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ret = call_read_iter(passthrough_filp, &aio_req->iocb, iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (ret != -EIOCBQUEUED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) fuse_aio_cleanup_handler(aio_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) revert_creds(old_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) fuse_file_accessed(fuse_filp, passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct iov_iter *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const struct cred *old_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct file *fuse_filp = iocb_fuse->ki_filp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct fuse_file *ff = fuse_filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct inode *fuse_inode = file_inode(fuse_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct file *passthrough_filp = ff->passthrough.filp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct inode *passthrough_inode = file_inode(passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (!iov_iter_count(iter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) inode_lock(fuse_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) fuse_copyattr(fuse_filp, passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) old_cred = override_creds(ff->passthrough.cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (is_sync_kiocb(iocb_fuse)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) file_start_write(passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) iocb_to_rw_flags(iocb_fuse->ki_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) PASSTHROUGH_IOCB_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) file_end_write(passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) fuse_copyattr(fuse_filp, passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct fuse_aio_req *aio_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) aio_req = kmalloc(sizeof(struct fuse_aio_req), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (!aio_req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) file_start_write(passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) __sb_writers_release(passthrough_inode->i_sb, SB_FREEZE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) aio_req->iocb_fuse = iocb_fuse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) kiocb_clone(&aio_req->iocb, iocb_fuse, passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) aio_req->iocb.ki_complete = fuse_aio_rw_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ret = call_write_iter(passthrough_filp, &aio_req->iocb, iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (ret != -EIOCBQUEUED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) fuse_aio_cleanup_handler(aio_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) revert_creds(old_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) inode_unlock(fuse_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) const struct cred *old_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct fuse_file *ff = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct file *passthrough_filp = ff->passthrough.filp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!passthrough_filp->f_op->mmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (WARN_ON(file != vma->vm_file))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) vma->vm_file = get_file(passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) old_cred = override_creds(ff->passthrough.cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ret = call_mmap(vma->vm_file, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) revert_creds(old_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) fput(passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) fput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) fuse_file_accessed(file, passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int fuse_passthrough_open(struct fuse_dev *fud, u32 lower_fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct file *passthrough_filp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct fuse_conn *fc = fud->fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct inode *passthrough_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct super_block *passthrough_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct fuse_passthrough *passthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (!fc->passthrough)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) passthrough_filp = fget(lower_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!passthrough_filp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) pr_err("FUSE: invalid file descriptor for passthrough.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (!passthrough_filp->f_op->read_iter ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) !passthrough_filp->f_op->write_iter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) pr_err("FUSE: passthrough file misses file operations.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) res = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) goto err_free_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) passthrough_inode = file_inode(passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) passthrough_sb = passthrough_inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (passthrough_sb->s_stack_depth >= FILESYSTEM_MAX_STACK_DEPTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) pr_err("FUSE: fs stacking depth exceeded for passthrough\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) res = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) goto err_free_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) passthrough = kmalloc(sizeof(struct fuse_passthrough), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (!passthrough) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) res = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto err_free_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) passthrough->filp = passthrough_filp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) passthrough->cred = prepare_creds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) idr_preload(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) spin_lock(&fc->passthrough_req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) res = idr_alloc(&fc->passthrough_req, passthrough, 1, 0, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) spin_unlock(&fc->passthrough_req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) idr_preload_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (res > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) fuse_passthrough_release(passthrough);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) kfree(passthrough);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) err_free_file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) fput(passthrough_filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct fuse_open_out *openarg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct fuse_passthrough *passthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int passthrough_fh = openarg->passthrough_fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!fc->passthrough)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* Default case, passthrough is not requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (passthrough_fh <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) spin_lock(&fc->passthrough_req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) passthrough = idr_remove(&fc->passthrough_req, passthrough_fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) spin_unlock(&fc->passthrough_req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!passthrough)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) ff->passthrough = *passthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) kfree(passthrough);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) void fuse_passthrough_release(struct fuse_passthrough *passthrough)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (passthrough->filp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) fput(passthrough->filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) passthrough->filp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (passthrough->cred) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) put_cred(passthrough->cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) passthrough->cred = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }