Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fuse: allow synchronous FUSE_INIT

FUSE_INIT has always been asynchronous with mount. That means that the
server processed this request after the mount syscall returned.

This means that FUSE_INIT can't supply the root inode's ID, hence it
currently has a hardcoded value. There are other limitations such as not
being able to perform getxattr during mount, which is needed by selinux.

To remove these limitations allow server to process FUSE_INIT while
initializing the in-core super block for the fuse filesystem. This can
only be done if the server is prepared to handle this, so add
FUSE_DEV_IOC_SYNC_INIT ioctl, which

a) lets the server know whether this feature is supported, returning
ENOTTY othewrwise.

b) lets the kernel know to perform a synchronous initialization

The implementation is slightly tricky, since fuse_dev/fuse_conn are set up
only during super block creation. This is solved by setting the private
data of the fuse device file to a special value ((struct fuse_dev *) 1) and
waiting for this to be turned into a proper fuse_dev before commecing with
operations on the device file.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>

+114 -34
+2 -1
fs/fuse/cuse.c
··· 52 52 #include <linux/user_namespace.h> 53 53 54 54 #include "fuse_i.h" 55 + #include "fuse_dev_i.h" 55 56 56 57 #define CUSE_CONNTBL_LEN 64 57 58 ··· 548 547 */ 549 548 static int cuse_channel_release(struct inode *inode, struct file *file) 550 549 { 551 - struct fuse_dev *fud = file->private_data; 550 + struct fuse_dev *fud = __fuse_get_dev(file); 552 551 struct cuse_conn *cc = fc_to_cc(fud->fc); 553 552 554 553 /* remove from the conntbl, no more access from this point on */
+53 -18
fs/fuse/dev.c
··· 1530 1530 return 0; 1531 1531 } 1532 1532 1533 + struct fuse_dev *fuse_get_dev(struct file *file) 1534 + { 1535 + struct fuse_dev *fud = __fuse_get_dev(file); 1536 + int err; 1537 + 1538 + if (likely(fud)) 1539 + return fud; 1540 + 1541 + err = wait_event_interruptible(fuse_dev_waitq, 1542 + READ_ONCE(file->private_data) != FUSE_DEV_SYNC_INIT); 1543 + if (err) 1544 + return ERR_PTR(err); 1545 + 1546 + fud = __fuse_get_dev(file); 1547 + if (!fud) 1548 + return ERR_PTR(-EPERM); 1549 + 1550 + return fud; 1551 + } 1552 + 1533 1553 static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to) 1534 1554 { 1535 1555 struct fuse_copy_state cs; 1536 1556 struct file *file = iocb->ki_filp; 1537 1557 struct fuse_dev *fud = fuse_get_dev(file); 1538 1558 1539 - if (!fud) 1540 - return -EPERM; 1559 + if (IS_ERR(fud)) 1560 + return PTR_ERR(fud); 1541 1561 1542 1562 if (!user_backed_iter(to)) 1543 1563 return -EINVAL; ··· 1577 1557 struct fuse_copy_state cs; 1578 1558 struct fuse_dev *fud = fuse_get_dev(in); 1579 1559 1580 - if (!fud) 1581 - return -EPERM; 1560 + if (IS_ERR(fud)) 1561 + return PTR_ERR(fud); 1582 1562 1583 1563 bufs = kvmalloc_array(pipe->max_usage, sizeof(struct pipe_buffer), 1584 1564 GFP_KERNEL); ··· 2251 2231 static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from) 2252 2232 { 2253 2233 struct fuse_copy_state cs; 2254 - struct fuse_dev *fud = fuse_get_dev(iocb->ki_filp); 2234 + struct fuse_dev *fud = __fuse_get_dev(iocb->ki_filp); 2255 2235 2256 2236 if (!fud) 2257 2237 return -EPERM; ··· 2273 2253 unsigned idx; 2274 2254 struct pipe_buffer *bufs; 2275 2255 struct fuse_copy_state cs; 2276 - struct fuse_dev *fud; 2256 + struct fuse_dev *fud = __fuse_get_dev(out); 2277 2257 size_t rem; 2278 2258 ssize_t ret; 2279 2259 2280 - fud = fuse_get_dev(out); 2281 2260 if (!fud) 2282 2261 return -EPERM; 2283 2262 ··· 2362 2343 struct fuse_iqueue *fiq; 2363 2344 struct fuse_dev *fud = fuse_get_dev(file); 2364 2345 2365 - if (!fud) 2346 + if (IS_ERR(fud)) 2366 2347 return EPOLLERR; 2367 2348 2368 2349 fiq = &fud->fc->iq; ··· 2509 2490 2510 2491 int fuse_dev_release(struct inode *inode, struct file *file) 2511 2492 { 2512 - struct fuse_dev *fud = fuse_get_dev(file); 2493 + struct fuse_dev *fud = __fuse_get_dev(file); 2513 2494 2514 2495 if (fud) { 2515 2496 struct fuse_conn *fc = fud->fc; ··· 2540 2521 { 2541 2522 struct fuse_dev *fud = fuse_get_dev(file); 2542 2523 2543 - if (!fud) 2544 - return -EPERM; 2524 + if (IS_ERR(fud)) 2525 + return PTR_ERR(fud); 2545 2526 2546 2527 /* No locking - fasync_helper does its own locking */ 2547 2528 return fasync_helper(fd, file, on, &fud->fc->iq.fasync); ··· 2551 2532 { 2552 2533 struct fuse_dev *fud; 2553 2534 2554 - if (new->private_data) 2535 + if (__fuse_get_dev(new)) 2555 2536 return -EINVAL; 2556 2537 2557 2538 fud = fuse_dev_alloc_install(fc); ··· 2582 2563 * uses the same ioctl handler. 2583 2564 */ 2584 2565 if (fd_file(f)->f_op == file->f_op) 2585 - fud = fuse_get_dev(fd_file(f)); 2566 + fud = __fuse_get_dev(fd_file(f)); 2586 2567 2587 2568 res = -EINVAL; 2588 2569 if (fud) { ··· 2600 2581 struct fuse_dev *fud = fuse_get_dev(file); 2601 2582 struct fuse_backing_map map; 2602 2583 2603 - if (!fud) 2604 - return -EPERM; 2584 + if (IS_ERR(fud)) 2585 + return PTR_ERR(fud); 2605 2586 2606 2587 if (!IS_ENABLED(CONFIG_FUSE_PASSTHROUGH)) 2607 2588 return -EOPNOTSUPP; ··· 2617 2598 struct fuse_dev *fud = fuse_get_dev(file); 2618 2599 int backing_id; 2619 2600 2620 - if (!fud) 2621 - return -EPERM; 2601 + if (IS_ERR(fud)) 2602 + return PTR_ERR(fud); 2622 2603 2623 2604 if (!IS_ENABLED(CONFIG_FUSE_PASSTHROUGH)) 2624 2605 return -EOPNOTSUPP; ··· 2627 2608 return -EFAULT; 2628 2609 2629 2610 return fuse_backing_close(fud->fc, backing_id); 2611 + } 2612 + 2613 + static long fuse_dev_ioctl_sync_init(struct file *file) 2614 + { 2615 + int err = -EINVAL; 2616 + 2617 + mutex_lock(&fuse_mutex); 2618 + if (!__fuse_get_dev(file)) { 2619 + WRITE_ONCE(file->private_data, FUSE_DEV_SYNC_INIT); 2620 + err = 0; 2621 + } 2622 + mutex_unlock(&fuse_mutex); 2623 + return err; 2630 2624 } 2631 2625 2632 2626 static long fuse_dev_ioctl(struct file *file, unsigned int cmd, ··· 2657 2625 case FUSE_DEV_IOC_BACKING_CLOSE: 2658 2626 return fuse_dev_ioctl_backing_close(file, argp); 2659 2627 2628 + case FUSE_DEV_IOC_SYNC_INIT: 2629 + return fuse_dev_ioctl_sync_init(file); 2630 + 2660 2631 default: 2661 2632 return -ENOTTY; 2662 2633 } ··· 2668 2633 #ifdef CONFIG_PROC_FS 2669 2634 static void fuse_dev_show_fdinfo(struct seq_file *seq, struct file *file) 2670 2635 { 2671 - struct fuse_dev *fud = fuse_get_dev(file); 2636 + struct fuse_dev *fud = __fuse_get_dev(file); 2672 2637 if (!fud) 2673 2638 return; 2674 2639
+2 -2
fs/fuse/dev_uring.c
··· 1139 1139 return -EINVAL; 1140 1140 1141 1141 fud = fuse_get_dev(cmd->file); 1142 - if (!fud) { 1142 + if (IS_ERR(fud)) { 1143 1143 pr_info_ratelimited("No fuse device found\n"); 1144 - return -ENOTCONN; 1144 + return PTR_ERR(fud); 1145 1145 } 1146 1146 fc = fud->fc; 1147 1147
+11 -2
fs/fuse/fuse_dev_i.h
··· 12 12 #define FUSE_INT_REQ_BIT (1ULL << 0) 13 13 #define FUSE_REQ_ID_STEP (1ULL << 1) 14 14 15 + extern struct wait_queue_head fuse_dev_waitq; 16 + 15 17 struct fuse_arg; 16 18 struct fuse_args; 17 19 struct fuse_pqueue; ··· 39 37 } ring; 40 38 }; 41 39 42 - static inline struct fuse_dev *fuse_get_dev(struct file *file) 40 + #define FUSE_DEV_SYNC_INIT ((struct fuse_dev *) 1) 41 + #define FUSE_DEV_PTR_MASK (~1UL) 42 + 43 + static inline struct fuse_dev *__fuse_get_dev(struct file *file) 43 44 { 44 45 /* 45 46 * Lockless access is OK, because file->private data is set 46 47 * once during mount and is valid until the file is released. 47 48 */ 48 - return READ_ONCE(file->private_data); 49 + struct fuse_dev *fud = READ_ONCE(file->private_data); 50 + 51 + return (typeof(fud)) ((unsigned long) fud & FUSE_DEV_PTR_MASK); 49 52 } 53 + 54 + struct fuse_dev *fuse_get_dev(struct file *file); 50 55 51 56 unsigned int fuse_req_hash(u64 unique); 52 57 struct fuse_req *fuse_request_find(struct fuse_pqueue *fpq, u64 unique);
+4 -1
fs/fuse/fuse_i.h
··· 904 904 /* Is link not implemented by fs? */ 905 905 unsigned int no_link:1; 906 906 907 + /* Is synchronous FUSE_INIT allowed? */ 908 + unsigned int sync_init:1; 909 + 907 910 /* Use io_uring for communication */ 908 911 unsigned int io_uring; 909 912 ··· 1321 1318 struct fuse_dev *fuse_dev_alloc(void); 1322 1319 void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc); 1323 1320 void fuse_dev_free(struct fuse_dev *fud); 1324 - void fuse_send_init(struct fuse_mount *fm); 1321 + int fuse_send_init(struct fuse_mount *fm); 1325 1322 1326 1323 /** 1327 1324 * Fill in superblock and initialize fuse connection
+41 -10
fs/fuse/inode.c
··· 7 7 */ 8 8 9 9 #include "fuse_i.h" 10 + #include "fuse_dev_i.h" 10 11 #include "dev_uring_i.h" 11 12 12 13 #include <linux/dax.h> ··· 35 34 static struct kmem_cache *fuse_inode_cachep; 36 35 struct list_head fuse_conn_list; 37 36 DEFINE_MUTEX(fuse_mutex); 37 + DECLARE_WAIT_QUEUE_HEAD(fuse_dev_waitq); 38 38 39 39 static int set_global_limit(const char *val, const struct kernel_param *kp); 40 40 ··· 1468 1466 wake_up_all(&fc->blocked_waitq); 1469 1467 } 1470 1468 1471 - void fuse_send_init(struct fuse_mount *fm) 1469 + static struct fuse_init_args *fuse_new_init(struct fuse_mount *fm) 1472 1470 { 1473 1471 struct fuse_init_args *ia; 1474 1472 u64 flags; ··· 1527 1525 ia->args.out_args[0].value = &ia->out; 1528 1526 ia->args.force = true; 1529 1527 ia->args.nocreds = true; 1530 - ia->args.end = process_init_reply; 1531 1528 1532 - if (fuse_simple_background(fm, &ia->args, GFP_KERNEL) != 0) 1533 - process_init_reply(fm, &ia->args, -ENOTCONN); 1529 + return ia; 1530 + } 1531 + 1532 + int fuse_send_init(struct fuse_mount *fm) 1533 + { 1534 + struct fuse_init_args *ia = fuse_new_init(fm); 1535 + int err; 1536 + 1537 + if (fm->fc->sync_init) { 1538 + err = fuse_simple_request(fm, &ia->args); 1539 + /* Ignore size of init reply */ 1540 + if (err > 0) 1541 + err = 0; 1542 + } else { 1543 + ia->args.end = process_init_reply; 1544 + err = fuse_simple_background(fm, &ia->args, GFP_KERNEL); 1545 + if (!err) 1546 + return 0; 1547 + } 1548 + process_init_reply(fm, &ia->args, err); 1549 + if (fm->fc->conn_error) 1550 + return -ENOTCONN; 1551 + return 0; 1534 1552 } 1535 1553 EXPORT_SYMBOL_GPL(fuse_send_init); 1536 1554 ··· 1889 1867 1890 1868 mutex_lock(&fuse_mutex); 1891 1869 err = -EINVAL; 1892 - if (ctx->fudptr && *ctx->fudptr) 1893 - goto err_unlock; 1870 + if (ctx->fudptr && *ctx->fudptr) { 1871 + if (*ctx->fudptr == FUSE_DEV_SYNC_INIT) 1872 + fc->sync_init = 1; 1873 + else 1874 + goto err_unlock; 1875 + } 1894 1876 1895 1877 err = fuse_ctl_add_conn(fc); 1896 1878 if (err) ··· 1902 1876 1903 1877 list_add_tail(&fc->entry, &fuse_conn_list); 1904 1878 sb->s_root = root_dentry; 1905 - if (ctx->fudptr) 1879 + if (ctx->fudptr) { 1906 1880 *ctx->fudptr = fud; 1881 + wake_up_all(&fuse_dev_waitq); 1882 + } 1907 1883 mutex_unlock(&fuse_mutex); 1908 1884 return 0; 1909 1885 ··· 1926 1898 static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc) 1927 1899 { 1928 1900 struct fuse_fs_context *ctx = fsc->fs_private; 1901 + struct fuse_mount *fm; 1929 1902 int err; 1930 1903 1931 1904 if (!ctx->file || !ctx->rootmode_present || ··· 1947 1918 return err; 1948 1919 /* file->private_data shall be visible on all CPUs after this */ 1949 1920 smp_mb(); 1950 - fuse_send_init(get_fuse_mount_super(sb)); 1951 - return 0; 1921 + 1922 + fm = get_fuse_mount_super(sb); 1923 + 1924 + return fuse_send_init(fm); 1952 1925 } 1953 1926 1954 1927 /* ··· 2011 1980 * Allow creating a fuse mount with an already initialized fuse 2012 1981 * connection 2013 1982 */ 2014 - fud = READ_ONCE(ctx->file->private_data); 1983 + fud = __fuse_get_dev(ctx->file); 2015 1984 if (ctx->file->f_op == &fuse_dev_operations && fud) { 2016 1985 fsc->sget_key = fud->fc; 2017 1986 sb = sget_fc(fsc, fuse_test_super, fuse_set_no_super);
+1
include/uapi/linux/fuse.h
··· 1131 1131 #define FUSE_DEV_IOC_BACKING_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 1, \ 1132 1132 struct fuse_backing_map) 1133 1133 #define FUSE_DEV_IOC_BACKING_CLOSE _IOW(FUSE_DEV_IOC_MAGIC, 2, uint32_t) 1134 + #define FUSE_DEV_IOC_SYNC_INIT _IO(FUSE_DEV_IOC_MAGIC, 3) 1134 1135 1135 1136 struct fuse_lseek_in { 1136 1137 uint64_t fh;