]> Git Repo - qemu.git/blob - tools/virtiofsd/passthrough_ll.c
virtiofsd: set maximum RLIMIT_NOFILE limit
[qemu.git] / tools / virtiofsd / passthrough_ll.c
1 /*
2  * FUSE: Filesystem in Userspace
3  * Copyright (C) 2001-2007  Miklos Szeredi <[email protected]>
4  *
5  * This program can be distributed under the terms of the GNU GPLv2.
6  * See the file COPYING.
7  */
8
9 /*
10  *
11  * This file system mirrors the existing file system hierarchy of the
12  * system, starting at the root file system. This is implemented by
13  * just "passing through" all requests to the corresponding user-space
14  * libc functions. In contrast to passthrough.c and passthrough_fh.c,
15  * this implementation uses the low-level API. Its performance should
16  * be the least bad among the three, but many operations are not
17  * implemented. In particular, it is not possible to remove files (or
18  * directories) because the code necessary to defer actual removal
19  * until the file is not opened anymore would make the example much
20  * more complicated.
21  *
22  * When writeback caching is enabled (-o writeback mount option), it
23  * is only possible to write to files for which the mounting user has
24  * read permissions. This is because the writeback cache requires the
25  * kernel to be able to issue read requests for all files (which the
26  * passthrough filesystem cannot satisfy if it can't read the file in
27  * the underlying filesystem).
28  *
29  * Compile with:
30  *
31  *     gcc -Wall passthrough_ll.c `pkg-config fuse3 --cflags --libs` -o
32  * passthrough_ll
33  *
34  * ## Source code ##
35  * \include passthrough_ll.c
36  */
37
38 #include "qemu/osdep.h"
39 #include "fuse_virtio.h"
40 #include "fuse_lowlevel.h"
41 #include <assert.h>
42 #include <cap-ng.h>
43 #include <dirent.h>
44 #include <errno.h>
45 #include <inttypes.h>
46 #include <limits.h>
47 #include <pthread.h>
48 #include <stdbool.h>
49 #include <stddef.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <sys/file.h>
54 #include <sys/mount.h>
55 #include <sys/prctl.h>
56 #include <sys/resource.h>
57 #include <sys/syscall.h>
58 #include <sys/types.h>
59 #include <sys/wait.h>
60 #include <sys/xattr.h>
61 #include <unistd.h>
62
63 #include "passthrough_helpers.h"
64 #include "seccomp.h"
65
66 struct lo_map_elem {
67     union {
68         struct lo_inode *inode;
69         struct lo_dirp *dirp;
70         int fd;
71         ssize_t freelist;
72     };
73     bool in_use;
74 };
75
76 /* Maps FUSE fh or ino values to internal objects */
77 struct lo_map {
78     struct lo_map_elem *elems;
79     size_t nelems;
80     ssize_t freelist;
81 };
82
83 struct lo_inode {
84     struct lo_inode *next; /* protected by lo->mutex */
85     struct lo_inode *prev; /* protected by lo->mutex */
86     int fd;
87     bool is_symlink;
88     ino_t ino;
89     dev_t dev;
90     uint64_t refcount; /* protected by lo->mutex */
91     fuse_ino_t fuse_ino;
92 };
93
94 struct lo_cred {
95     uid_t euid;
96     gid_t egid;
97 };
98
99 enum {
100     CACHE_NEVER,
101     CACHE_NORMAL,
102     CACHE_ALWAYS,
103 };
104
105 struct lo_data {
106     pthread_mutex_t mutex;
107     int debug;
108     int norace;
109     int writeback;
110     int flock;
111     int xattr;
112     const char *source;
113     double timeout;
114     int cache;
115     int timeout_set;
116     struct lo_inode root; /* protected by lo->mutex */
117     struct lo_map ino_map; /* protected by lo->mutex */
118     struct lo_map dirp_map; /* protected by lo->mutex */
119     struct lo_map fd_map; /* protected by lo->mutex */
120
121     /* An O_PATH file descriptor to /proc/self/fd/ */
122     int proc_self_fd;
123 };
124
125 static const struct fuse_opt lo_opts[] = {
126     { "writeback", offsetof(struct lo_data, writeback), 1 },
127     { "no_writeback", offsetof(struct lo_data, writeback), 0 },
128     { "source=%s", offsetof(struct lo_data, source), 0 },
129     { "flock", offsetof(struct lo_data, flock), 1 },
130     { "no_flock", offsetof(struct lo_data, flock), 0 },
131     { "xattr", offsetof(struct lo_data, xattr), 1 },
132     { "no_xattr", offsetof(struct lo_data, xattr), 0 },
133     { "timeout=%lf", offsetof(struct lo_data, timeout), 0 },
134     { "timeout=", offsetof(struct lo_data, timeout_set), 1 },
135     { "cache=never", offsetof(struct lo_data, cache), CACHE_NEVER },
136     { "cache=auto", offsetof(struct lo_data, cache), CACHE_NORMAL },
137     { "cache=always", offsetof(struct lo_data, cache), CACHE_ALWAYS },
138     { "norace", offsetof(struct lo_data, norace), 1 },
139     FUSE_OPT_END
140 };
141
142 static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64_t n);
143
144 static struct {
145     pthread_mutex_t mutex;
146     void *saved;
147 } cap;
148 /* That we loaded cap-ng in the current thread from the saved */
149 static __thread bool cap_loaded = 0;
150
151 static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st);
152
153 static int is_dot_or_dotdot(const char *name)
154 {
155     return name[0] == '.' &&
156            (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
157 }
158
159 /* Is `path` a single path component that is not "." or ".."? */
160 static int is_safe_path_component(const char *path)
161 {
162     if (strchr(path, '/')) {
163         return 0;
164     }
165
166     return !is_dot_or_dotdot(path);
167 }
168
169 static struct lo_data *lo_data(fuse_req_t req)
170 {
171     return (struct lo_data *)fuse_req_userdata(req);
172 }
173
174 /*
175  * Load capng's state from our saved state if the current thread
176  * hadn't previously been loaded.
177  * returns 0 on success
178  */
179 static int load_capng(void)
180 {
181     if (!cap_loaded) {
182         pthread_mutex_lock(&cap.mutex);
183         capng_restore_state(&cap.saved);
184         /*
185          * restore_state free's the saved copy
186          * so make another.
187          */
188         cap.saved = capng_save_state();
189         if (!cap.saved) {
190             fuse_log(FUSE_LOG_ERR, "capng_save_state (thread)\n");
191             return -EINVAL;
192         }
193         pthread_mutex_unlock(&cap.mutex);
194
195         /*
196          * We want to use the loaded state for our pid,
197          * not the original
198          */
199         capng_setpid(syscall(SYS_gettid));
200         cap_loaded = true;
201     }
202     return 0;
203 }
204
205 /*
206  * Helpers for dropping and regaining effective capabilities. Returns 0
207  * on success, error otherwise
208  */
209 static int drop_effective_cap(const char *cap_name, bool *cap_dropped)
210 {
211     int cap, ret;
212
213     cap = capng_name_to_capability(cap_name);
214     if (cap < 0) {
215         ret = errno;
216         fuse_log(FUSE_LOG_ERR, "capng_name_to_capability(%s) failed:%s\n",
217                  cap_name, strerror(errno));
218         goto out;
219     }
220
221     if (load_capng()) {
222         ret = errno;
223         fuse_log(FUSE_LOG_ERR, "load_capng() failed\n");
224         goto out;
225     }
226
227     /* We dont have this capability in effective set already. */
228     if (!capng_have_capability(CAPNG_EFFECTIVE, cap)) {
229         ret = 0;
230         goto out;
231     }
232
233     if (capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, cap)) {
234         ret = errno;
235         fuse_log(FUSE_LOG_ERR, "capng_update(DROP,) failed\n");
236         goto out;
237     }
238
239     if (capng_apply(CAPNG_SELECT_CAPS)) {
240         ret = errno;
241         fuse_log(FUSE_LOG_ERR, "drop:capng_apply() failed\n");
242         goto out;
243     }
244
245     ret = 0;
246     if (cap_dropped) {
247         *cap_dropped = true;
248     }
249
250 out:
251     return ret;
252 }
253
254 static int gain_effective_cap(const char *cap_name)
255 {
256     int cap;
257     int ret = 0;
258
259     cap = capng_name_to_capability(cap_name);
260     if (cap < 0) {
261         ret = errno;
262         fuse_log(FUSE_LOG_ERR, "capng_name_to_capability(%s) failed:%s\n",
263                  cap_name, strerror(errno));
264         goto out;
265     }
266
267     if (load_capng()) {
268         ret = errno;
269         fuse_log(FUSE_LOG_ERR, "load_capng() failed\n");
270         goto out;
271     }
272
273     if (capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, cap)) {
274         ret = errno;
275         fuse_log(FUSE_LOG_ERR, "capng_update(ADD,) failed\n");
276         goto out;
277     }
278
279     if (capng_apply(CAPNG_SELECT_CAPS)) {
280         ret = errno;
281         fuse_log(FUSE_LOG_ERR, "gain:capng_apply() failed\n");
282         goto out;
283     }
284     ret = 0;
285
286 out:
287     return ret;
288 }
289
290 static void lo_map_init(struct lo_map *map)
291 {
292     map->elems = NULL;
293     map->nelems = 0;
294     map->freelist = -1;
295 }
296
297 static void lo_map_destroy(struct lo_map *map)
298 {
299     free(map->elems);
300 }
301
302 static int lo_map_grow(struct lo_map *map, size_t new_nelems)
303 {
304     struct lo_map_elem *new_elems;
305     size_t i;
306
307     if (new_nelems <= map->nelems) {
308         return 1;
309     }
310
311     new_elems = realloc(map->elems, sizeof(map->elems[0]) * new_nelems);
312     if (!new_elems) {
313         return 0;
314     }
315
316     for (i = map->nelems; i < new_nelems; i++) {
317         new_elems[i].freelist = i + 1;
318         new_elems[i].in_use = false;
319     }
320     new_elems[new_nelems - 1].freelist = -1;
321
322     map->elems = new_elems;
323     map->freelist = map->nelems;
324     map->nelems = new_nelems;
325     return 1;
326 }
327
328 static struct lo_map_elem *lo_map_alloc_elem(struct lo_map *map)
329 {
330     struct lo_map_elem *elem;
331
332     if (map->freelist == -1 && !lo_map_grow(map, map->nelems + 256)) {
333         return NULL;
334     }
335
336     elem = &map->elems[map->freelist];
337     map->freelist = elem->freelist;
338
339     elem->in_use = true;
340
341     return elem;
342 }
343
344 static struct lo_map_elem *lo_map_reserve(struct lo_map *map, size_t key)
345 {
346     ssize_t *prev;
347
348     if (!lo_map_grow(map, key + 1)) {
349         return NULL;
350     }
351
352     for (prev = &map->freelist; *prev != -1;
353          prev = &map->elems[*prev].freelist) {
354         if (*prev == key) {
355             struct lo_map_elem *elem = &map->elems[key];
356
357             *prev = elem->freelist;
358             elem->in_use = true;
359             return elem;
360         }
361     }
362     return NULL;
363 }
364
365 static struct lo_map_elem *lo_map_get(struct lo_map *map, size_t key)
366 {
367     if (key >= map->nelems) {
368         return NULL;
369     }
370     if (!map->elems[key].in_use) {
371         return NULL;
372     }
373     return &map->elems[key];
374 }
375
376 static void lo_map_remove(struct lo_map *map, size_t key)
377 {
378     struct lo_map_elem *elem;
379
380     if (key >= map->nelems) {
381         return;
382     }
383
384     elem = &map->elems[key];
385     if (!elem->in_use) {
386         return;
387     }
388
389     elem->in_use = false;
390
391     elem->freelist = map->freelist;
392     map->freelist = key;
393 }
394
395 /* Assumes lo->mutex is held */
396 static ssize_t lo_add_fd_mapping(fuse_req_t req, int fd)
397 {
398     struct lo_map_elem *elem;
399
400     elem = lo_map_alloc_elem(&lo_data(req)->fd_map);
401     if (!elem) {
402         return -1;
403     }
404
405     elem->fd = fd;
406     return elem - lo_data(req)->fd_map.elems;
407 }
408
409 /* Assumes lo->mutex is held */
410 static ssize_t lo_add_dirp_mapping(fuse_req_t req, struct lo_dirp *dirp)
411 {
412     struct lo_map_elem *elem;
413
414     elem = lo_map_alloc_elem(&lo_data(req)->dirp_map);
415     if (!elem) {
416         return -1;
417     }
418
419     elem->dirp = dirp;
420     return elem - lo_data(req)->dirp_map.elems;
421 }
422
423 /* Assumes lo->mutex is held */
424 static ssize_t lo_add_inode_mapping(fuse_req_t req, struct lo_inode *inode)
425 {
426     struct lo_map_elem *elem;
427
428     elem = lo_map_alloc_elem(&lo_data(req)->ino_map);
429     if (!elem) {
430         return -1;
431     }
432
433     elem->inode = inode;
434     return elem - lo_data(req)->ino_map.elems;
435 }
436
437 static struct lo_inode *lo_inode(fuse_req_t req, fuse_ino_t ino)
438 {
439     struct lo_data *lo = lo_data(req);
440     struct lo_map_elem *elem;
441
442     pthread_mutex_lock(&lo->mutex);
443     elem = lo_map_get(&lo->ino_map, ino);
444     pthread_mutex_unlock(&lo->mutex);
445
446     if (!elem) {
447         return NULL;
448     }
449
450     return elem->inode;
451 }
452
453 static int lo_fd(fuse_req_t req, fuse_ino_t ino)
454 {
455     struct lo_inode *inode = lo_inode(req, ino);
456     return inode ? inode->fd : -1;
457 }
458
459 static bool lo_debug(fuse_req_t req)
460 {
461     return lo_data(req)->debug != 0;
462 }
463
464 static void lo_init(void *userdata, struct fuse_conn_info *conn)
465 {
466     struct lo_data *lo = (struct lo_data *)userdata;
467
468     if (conn->capable & FUSE_CAP_EXPORT_SUPPORT) {
469         conn->want |= FUSE_CAP_EXPORT_SUPPORT;
470     }
471
472     if (lo->writeback && conn->capable & FUSE_CAP_WRITEBACK_CACHE) {
473         if (lo->debug) {
474             fuse_log(FUSE_LOG_DEBUG, "lo_init: activating writeback\n");
475         }
476         conn->want |= FUSE_CAP_WRITEBACK_CACHE;
477     }
478     if (lo->flock && conn->capable & FUSE_CAP_FLOCK_LOCKS) {
479         if (lo->debug) {
480             fuse_log(FUSE_LOG_DEBUG, "lo_init: activating flock locks\n");
481         }
482         conn->want |= FUSE_CAP_FLOCK_LOCKS;
483     }
484 }
485
486 static void lo_getattr(fuse_req_t req, fuse_ino_t ino,
487                        struct fuse_file_info *fi)
488 {
489     int res;
490     struct stat buf;
491     struct lo_data *lo = lo_data(req);
492
493     (void)fi;
494
495     res =
496         fstatat(lo_fd(req, ino), "", &buf, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
497     if (res == -1) {
498         return (void)fuse_reply_err(req, errno);
499     }
500
501     fuse_reply_attr(req, &buf, lo->timeout);
502 }
503
504 static int lo_parent_and_name(struct lo_data *lo, struct lo_inode *inode,
505                               char path[PATH_MAX], struct lo_inode **parent)
506 {
507     char procname[64];
508     char *last;
509     struct stat stat;
510     struct lo_inode *p;
511     int retries = 2;
512     int res;
513
514 retry:
515     sprintf(procname, "%i", inode->fd);
516
517     res = readlinkat(lo->proc_self_fd, procname, path, PATH_MAX);
518     if (res < 0) {
519         fuse_log(FUSE_LOG_WARNING, "%s: readlink failed: %m\n", __func__);
520         goto fail_noretry;
521     }
522
523     if (res >= PATH_MAX) {
524         fuse_log(FUSE_LOG_WARNING, "%s: readlink overflowed\n", __func__);
525         goto fail_noretry;
526     }
527     path[res] = '\0';
528
529     last = strrchr(path, '/');
530     if (last == NULL) {
531         /* Shouldn't happen */
532         fuse_log(
533             FUSE_LOG_WARNING,
534             "%s: INTERNAL ERROR: bad path read from proc\n", __func__);
535         goto fail_noretry;
536     }
537     if (last == path) {
538         p = &lo->root;
539         pthread_mutex_lock(&lo->mutex);
540         p->refcount++;
541         pthread_mutex_unlock(&lo->mutex);
542     } else {
543         *last = '\0';
544         res = fstatat(AT_FDCWD, last == path ? "/" : path, &stat, 0);
545         if (res == -1) {
546             if (!retries) {
547                 fuse_log(FUSE_LOG_WARNING,
548                          "%s: failed to stat parent: %m\n", __func__);
549             }
550             goto fail;
551         }
552         p = lo_find(lo, &stat);
553         if (p == NULL) {
554             if (!retries) {
555                 fuse_log(FUSE_LOG_WARNING,
556                          "%s: failed to find parent\n", __func__);
557             }
558             goto fail;
559         }
560     }
561     last++;
562     res = fstatat(p->fd, last, &stat, AT_SYMLINK_NOFOLLOW);
563     if (res == -1) {
564         if (!retries) {
565             fuse_log(FUSE_LOG_WARNING,
566                      "%s: failed to stat last\n", __func__);
567         }
568         goto fail_unref;
569     }
570     if (stat.st_dev != inode->dev || stat.st_ino != inode->ino) {
571         if (!retries) {
572             fuse_log(FUSE_LOG_WARNING,
573                      "%s: failed to match last\n", __func__);
574         }
575         goto fail_unref;
576     }
577     *parent = p;
578     memmove(path, last, strlen(last) + 1);
579
580     return 0;
581
582 fail_unref:
583     unref_inode(lo, p, 1);
584 fail:
585     if (retries) {
586         retries--;
587         goto retry;
588     }
589 fail_noretry:
590     errno = EIO;
591     return -1;
592 }
593
594 static int utimensat_empty(struct lo_data *lo, struct lo_inode *inode,
595                            const struct timespec *tv)
596 {
597     int res;
598     struct lo_inode *parent;
599     char path[PATH_MAX];
600
601     if (inode->is_symlink) {
602         res = utimensat(inode->fd, "", tv, AT_EMPTY_PATH);
603         if (res == -1 && errno == EINVAL) {
604             /* Sorry, no race free way to set times on symlink. */
605             if (lo->norace) {
606                 errno = EPERM;
607             } else {
608                 goto fallback;
609             }
610         }
611         return res;
612     }
613     sprintf(path, "%i", inode->fd);
614
615     return utimensat(lo->proc_self_fd, path, tv, 0);
616
617 fallback:
618     res = lo_parent_and_name(lo, inode, path, &parent);
619     if (res != -1) {
620         res = utimensat(parent->fd, path, tv, AT_SYMLINK_NOFOLLOW);
621         unref_inode(lo, parent, 1);
622     }
623
624     return res;
625 }
626
627 static int lo_fi_fd(fuse_req_t req, struct fuse_file_info *fi)
628 {
629     struct lo_data *lo = lo_data(req);
630     struct lo_map_elem *elem;
631
632     pthread_mutex_lock(&lo->mutex);
633     elem = lo_map_get(&lo->fd_map, fi->fh);
634     pthread_mutex_unlock(&lo->mutex);
635
636     if (!elem) {
637         return -1;
638     }
639
640     return elem->fd;
641 }
642
643 static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
644                        int valid, struct fuse_file_info *fi)
645 {
646     int saverr;
647     char procname[64];
648     struct lo_data *lo = lo_data(req);
649     struct lo_inode *inode;
650     int ifd;
651     int res;
652     int fd;
653
654     inode = lo_inode(req, ino);
655     if (!inode) {
656         fuse_reply_err(req, EBADF);
657         return;
658     }
659
660     ifd = inode->fd;
661
662     /* If fi->fh is invalid we'll report EBADF later */
663     if (fi) {
664         fd = lo_fi_fd(req, fi);
665     }
666
667     if (valid & FUSE_SET_ATTR_MODE) {
668         if (fi) {
669             res = fchmod(fd, attr->st_mode);
670         } else {
671             sprintf(procname, "%i", ifd);
672             res = fchmodat(lo->proc_self_fd, procname, attr->st_mode, 0);
673         }
674         if (res == -1) {
675             goto out_err;
676         }
677     }
678     if (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
679         uid_t uid = (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t)-1;
680         gid_t gid = (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t)-1;
681
682         res = fchownat(ifd, "", uid, gid, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
683         if (res == -1) {
684             goto out_err;
685         }
686     }
687     if (valid & FUSE_SET_ATTR_SIZE) {
688         int truncfd;
689
690         if (fi) {
691             truncfd = fd;
692         } else {
693             sprintf(procname, "%i", ifd);
694             truncfd = openat(lo->proc_self_fd, procname, O_RDWR);
695             if (truncfd < 0) {
696                 goto out_err;
697             }
698         }
699
700         res = ftruncate(truncfd, attr->st_size);
701         if (!fi) {
702             saverr = errno;
703             close(truncfd);
704             errno = saverr;
705         }
706         if (res == -1) {
707             goto out_err;
708         }
709     }
710     if (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
711         struct timespec tv[2];
712
713         tv[0].tv_sec = 0;
714         tv[1].tv_sec = 0;
715         tv[0].tv_nsec = UTIME_OMIT;
716         tv[1].tv_nsec = UTIME_OMIT;
717
718         if (valid & FUSE_SET_ATTR_ATIME_NOW) {
719             tv[0].tv_nsec = UTIME_NOW;
720         } else if (valid & FUSE_SET_ATTR_ATIME) {
721             tv[0] = attr->st_atim;
722         }
723
724         if (valid & FUSE_SET_ATTR_MTIME_NOW) {
725             tv[1].tv_nsec = UTIME_NOW;
726         } else if (valid & FUSE_SET_ATTR_MTIME) {
727             tv[1] = attr->st_mtim;
728         }
729
730         if (fi) {
731             res = futimens(fd, tv);
732         } else {
733             res = utimensat_empty(lo, inode, tv);
734         }
735         if (res == -1) {
736             goto out_err;
737         }
738     }
739
740     return lo_getattr(req, ino, fi);
741
742 out_err:
743     saverr = errno;
744     fuse_reply_err(req, saverr);
745 }
746
747 static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st)
748 {
749     struct lo_inode *p;
750     struct lo_inode *ret = NULL;
751
752     pthread_mutex_lock(&lo->mutex);
753     for (p = lo->root.next; p != &lo->root; p = p->next) {
754         if (p->ino == st->st_ino && p->dev == st->st_dev) {
755             assert(p->refcount > 0);
756             ret = p;
757             ret->refcount++;
758             break;
759         }
760     }
761     pthread_mutex_unlock(&lo->mutex);
762     return ret;
763 }
764
765 static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
766                         struct fuse_entry_param *e)
767 {
768     int newfd;
769     int res;
770     int saverr;
771     struct lo_data *lo = lo_data(req);
772     struct lo_inode *inode, *dir = lo_inode(req, parent);
773
774     memset(e, 0, sizeof(*e));
775     e->attr_timeout = lo->timeout;
776     e->entry_timeout = lo->timeout;
777
778     /* Do not allow escaping root directory */
779     if (dir == &lo->root && strcmp(name, "..") == 0) {
780         name = ".";
781     }
782
783     newfd = openat(lo_fd(req, parent), name, O_PATH | O_NOFOLLOW);
784     if (newfd == -1) {
785         goto out_err;
786     }
787
788     res = fstatat(newfd, "", &e->attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
789     if (res == -1) {
790         goto out_err;
791     }
792
793     inode = lo_find(lo_data(req), &e->attr);
794     if (inode) {
795         close(newfd);
796         newfd = -1;
797     } else {
798         struct lo_inode *prev, *next;
799
800         saverr = ENOMEM;
801         inode = calloc(1, sizeof(struct lo_inode));
802         if (!inode) {
803             goto out_err;
804         }
805
806         inode->is_symlink = S_ISLNK(e->attr.st_mode);
807         inode->refcount = 1;
808         inode->fd = newfd;
809         inode->ino = e->attr.st_ino;
810         inode->dev = e->attr.st_dev;
811
812         pthread_mutex_lock(&lo->mutex);
813         inode->fuse_ino = lo_add_inode_mapping(req, inode);
814         prev = &lo->root;
815         next = prev->next;
816         next->prev = inode;
817         inode->next = next;
818         inode->prev = prev;
819         prev->next = inode;
820         pthread_mutex_unlock(&lo->mutex);
821     }
822     e->ino = inode->fuse_ino;
823
824     if (lo_debug(req)) {
825         fuse_log(FUSE_LOG_DEBUG, "  %lli/%s -> %lli\n",
826                  (unsigned long long)parent, name, (unsigned long long)e->ino);
827     }
828
829     return 0;
830
831 out_err:
832     saverr = errno;
833     if (newfd != -1) {
834         close(newfd);
835     }
836     return saverr;
837 }
838
839 static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
840 {
841     struct fuse_entry_param e;
842     int err;
843
844     if (lo_debug(req)) {
845         fuse_log(FUSE_LOG_DEBUG, "lo_lookup(parent=%" PRIu64 ", name=%s)\n",
846                  parent, name);
847     }
848
849     /*
850      * Don't use is_safe_path_component(), allow "." and ".." for NFS export
851      * support.
852      */
853     if (strchr(name, '/')) {
854         fuse_reply_err(req, EINVAL);
855         return;
856     }
857
858     err = lo_do_lookup(req, parent, name, &e);
859     if (err) {
860         fuse_reply_err(req, err);
861     } else {
862         fuse_reply_entry(req, &e);
863     }
864 }
865
866 /*
867  * On some archs, setres*id is limited to 2^16 but they
868  * provide setres*id32 variants that allow 2^32.
869  * Others just let setres*id do 2^32 anyway.
870  */
871 #ifdef SYS_setresgid32
872 #define OURSYS_setresgid SYS_setresgid32
873 #else
874 #define OURSYS_setresgid SYS_setresgid
875 #endif
876
877 #ifdef SYS_setresuid32
878 #define OURSYS_setresuid SYS_setresuid32
879 #else
880 #define OURSYS_setresuid SYS_setresuid
881 #endif
882
883 /*
884  * Change to uid/gid of caller so that file is created with
885  * ownership of caller.
886  * TODO: What about selinux context?
887  */
888 static int lo_change_cred(fuse_req_t req, struct lo_cred *old)
889 {
890     int res;
891
892     old->euid = geteuid();
893     old->egid = getegid();
894
895     res = syscall(OURSYS_setresgid, -1, fuse_req_ctx(req)->gid, -1);
896     if (res == -1) {
897         return errno;
898     }
899
900     res = syscall(OURSYS_setresuid, -1, fuse_req_ctx(req)->uid, -1);
901     if (res == -1) {
902         int errno_save = errno;
903
904         syscall(OURSYS_setresgid, -1, old->egid, -1);
905         return errno_save;
906     }
907
908     return 0;
909 }
910
911 /* Regain Privileges */
912 static void lo_restore_cred(struct lo_cred *old)
913 {
914     int res;
915
916     res = syscall(OURSYS_setresuid, -1, old->euid, -1);
917     if (res == -1) {
918         fuse_log(FUSE_LOG_ERR, "seteuid(%u): %m\n", old->euid);
919         exit(1);
920     }
921
922     res = syscall(OURSYS_setresgid, -1, old->egid, -1);
923     if (res == -1) {
924         fuse_log(FUSE_LOG_ERR, "setegid(%u): %m\n", old->egid);
925         exit(1);
926     }
927 }
928
929 static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
930                              const char *name, mode_t mode, dev_t rdev,
931                              const char *link)
932 {
933     int res;
934     int saverr;
935     struct lo_inode *dir;
936     struct fuse_entry_param e;
937     struct lo_cred old = {};
938
939     if (!is_safe_path_component(name)) {
940         fuse_reply_err(req, EINVAL);
941         return;
942     }
943
944     dir = lo_inode(req, parent);
945     if (!dir) {
946         fuse_reply_err(req, EBADF);
947         return;
948     }
949
950     saverr = ENOMEM;
951
952     saverr = lo_change_cred(req, &old);
953     if (saverr) {
954         goto out;
955     }
956
957     res = mknod_wrapper(dir->fd, name, link, mode, rdev);
958
959     saverr = errno;
960
961     lo_restore_cred(&old);
962
963     if (res == -1) {
964         goto out;
965     }
966
967     saverr = lo_do_lookup(req, parent, name, &e);
968     if (saverr) {
969         goto out;
970     }
971
972     if (lo_debug(req)) {
973         fuse_log(FUSE_LOG_DEBUG, "  %lli/%s -> %lli\n",
974                  (unsigned long long)parent, name, (unsigned long long)e.ino);
975     }
976
977     fuse_reply_entry(req, &e);
978     return;
979
980 out:
981     fuse_reply_err(req, saverr);
982 }
983
984 static void lo_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
985                      mode_t mode, dev_t rdev)
986 {
987     lo_mknod_symlink(req, parent, name, mode, rdev, NULL);
988 }
989
990 static void lo_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
991                      mode_t mode)
992 {
993     lo_mknod_symlink(req, parent, name, S_IFDIR | mode, 0, NULL);
994 }
995
996 static void lo_symlink(fuse_req_t req, const char *link, fuse_ino_t parent,
997                        const char *name)
998 {
999     lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link);
1000 }
1001
1002 static int linkat_empty_nofollow(struct lo_data *lo, struct lo_inode *inode,
1003                                  int dfd, const char *name)
1004 {
1005     int res;
1006     struct lo_inode *parent;
1007     char path[PATH_MAX];
1008
1009     if (inode->is_symlink) {
1010         res = linkat(inode->fd, "", dfd, name, AT_EMPTY_PATH);
1011         if (res == -1 && (errno == ENOENT || errno == EINVAL)) {
1012             /* Sorry, no race free way to hard-link a symlink. */
1013             if (lo->norace) {
1014                 errno = EPERM;
1015             } else {
1016                 goto fallback;
1017             }
1018         }
1019         return res;
1020     }
1021
1022     sprintf(path, "%i", inode->fd);
1023
1024     return linkat(lo->proc_self_fd, path, dfd, name, AT_SYMLINK_FOLLOW);
1025
1026 fallback:
1027     res = lo_parent_and_name(lo, inode, path, &parent);
1028     if (res != -1) {
1029         res = linkat(parent->fd, path, dfd, name, 0);
1030         unref_inode(lo, parent, 1);
1031     }
1032
1033     return res;
1034 }
1035
1036 static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent,
1037                     const char *name)
1038 {
1039     int res;
1040     struct lo_data *lo = lo_data(req);
1041     struct lo_inode *inode;
1042     struct fuse_entry_param e;
1043     int saverr;
1044
1045     if (!is_safe_path_component(name)) {
1046         fuse_reply_err(req, EINVAL);
1047         return;
1048     }
1049
1050     inode = lo_inode(req, ino);
1051     if (!inode) {
1052         fuse_reply_err(req, EBADF);
1053         return;
1054     }
1055
1056     memset(&e, 0, sizeof(struct fuse_entry_param));
1057     e.attr_timeout = lo->timeout;
1058     e.entry_timeout = lo->timeout;
1059
1060     res = linkat_empty_nofollow(lo, inode, lo_fd(req, parent), name);
1061     if (res == -1) {
1062         goto out_err;
1063     }
1064
1065     res = fstatat(inode->fd, "", &e.attr, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW);
1066     if (res == -1) {
1067         goto out_err;
1068     }
1069
1070     pthread_mutex_lock(&lo->mutex);
1071     inode->refcount++;
1072     pthread_mutex_unlock(&lo->mutex);
1073     e.ino = inode->fuse_ino;
1074
1075     if (lo_debug(req)) {
1076         fuse_log(FUSE_LOG_DEBUG, "  %lli/%s -> %lli\n",
1077                  (unsigned long long)parent, name, (unsigned long long)e.ino);
1078     }
1079
1080     fuse_reply_entry(req, &e);
1081     return;
1082
1083 out_err:
1084     saverr = errno;
1085     fuse_reply_err(req, saverr);
1086 }
1087
1088 static void lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
1089 {
1090     int res;
1091     if (!is_safe_path_component(name)) {
1092         fuse_reply_err(req, EINVAL);
1093         return;
1094     }
1095
1096     res = unlinkat(lo_fd(req, parent), name, AT_REMOVEDIR);
1097
1098     fuse_reply_err(req, res == -1 ? errno : 0);
1099 }
1100
1101 static void lo_rename(fuse_req_t req, fuse_ino_t parent, const char *name,
1102                       fuse_ino_t newparent, const char *newname,
1103                       unsigned int flags)
1104 {
1105     int res;
1106
1107     if (!is_safe_path_component(name) || !is_safe_path_component(newname)) {
1108         fuse_reply_err(req, EINVAL);
1109         return;
1110     }
1111
1112     if (flags) {
1113         fuse_reply_err(req, EINVAL);
1114         return;
1115     }
1116
1117     res = renameat(lo_fd(req, parent), name, lo_fd(req, newparent), newname);
1118
1119     fuse_reply_err(req, res == -1 ? errno : 0);
1120 }
1121
1122 static void lo_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
1123 {
1124     int res;
1125
1126     if (!is_safe_path_component(name)) {
1127         fuse_reply_err(req, EINVAL);
1128         return;
1129     }
1130
1131     res = unlinkat(lo_fd(req, parent), name, 0);
1132
1133     fuse_reply_err(req, res == -1 ? errno : 0);
1134 }
1135
1136 static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64_t n)
1137 {
1138     if (!inode) {
1139         return;
1140     }
1141
1142     pthread_mutex_lock(&lo->mutex);
1143     assert(inode->refcount >= n);
1144     inode->refcount -= n;
1145     if (!inode->refcount) {
1146         struct lo_inode *prev, *next;
1147
1148         prev = inode->prev;
1149         next = inode->next;
1150         next->prev = prev;
1151         prev->next = next;
1152
1153         lo_map_remove(&lo->ino_map, inode->fuse_ino);
1154         pthread_mutex_unlock(&lo->mutex);
1155         close(inode->fd);
1156         free(inode);
1157     } else {
1158         pthread_mutex_unlock(&lo->mutex);
1159     }
1160 }
1161
1162 static void lo_forget_one(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
1163 {
1164     struct lo_data *lo = lo_data(req);
1165     struct lo_inode *inode;
1166
1167     inode = lo_inode(req, ino);
1168     if (!inode) {
1169         return;
1170     }
1171
1172     if (lo_debug(req)) {
1173         fuse_log(FUSE_LOG_DEBUG, "  forget %lli %lli -%lli\n",
1174                  (unsigned long long)ino, (unsigned long long)inode->refcount,
1175                  (unsigned long long)nlookup);
1176     }
1177
1178     unref_inode(lo, inode, nlookup);
1179 }
1180
1181 static void lo_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
1182 {
1183     lo_forget_one(req, ino, nlookup);
1184     fuse_reply_none(req);
1185 }
1186
1187 static void lo_forget_multi(fuse_req_t req, size_t count,
1188                             struct fuse_forget_data *forgets)
1189 {
1190     int i;
1191
1192     for (i = 0; i < count; i++) {
1193         lo_forget_one(req, forgets[i].ino, forgets[i].nlookup);
1194     }
1195     fuse_reply_none(req);
1196 }
1197
1198 static void lo_readlink(fuse_req_t req, fuse_ino_t ino)
1199 {
1200     char buf[PATH_MAX + 1];
1201     int res;
1202
1203     res = readlinkat(lo_fd(req, ino), "", buf, sizeof(buf));
1204     if (res == -1) {
1205         return (void)fuse_reply_err(req, errno);
1206     }
1207
1208     if (res == sizeof(buf)) {
1209         return (void)fuse_reply_err(req, ENAMETOOLONG);
1210     }
1211
1212     buf[res] = '\0';
1213
1214     fuse_reply_readlink(req, buf);
1215 }
1216
1217 struct lo_dirp {
1218     DIR *dp;
1219     struct dirent *entry;
1220     off_t offset;
1221 };
1222
1223 static struct lo_dirp *lo_dirp(fuse_req_t req, struct fuse_file_info *fi)
1224 {
1225     struct lo_data *lo = lo_data(req);
1226     struct lo_map_elem *elem;
1227
1228     pthread_mutex_lock(&lo->mutex);
1229     elem = lo_map_get(&lo->dirp_map, fi->fh);
1230     pthread_mutex_unlock(&lo->mutex);
1231     if (!elem) {
1232         return NULL;
1233     }
1234
1235     return elem->dirp;
1236 }
1237
1238 static void lo_opendir(fuse_req_t req, fuse_ino_t ino,
1239                        struct fuse_file_info *fi)
1240 {
1241     int error = ENOMEM;
1242     struct lo_data *lo = lo_data(req);
1243     struct lo_dirp *d;
1244     int fd;
1245     ssize_t fh;
1246
1247     d = calloc(1, sizeof(struct lo_dirp));
1248     if (d == NULL) {
1249         goto out_err;
1250     }
1251
1252     fd = openat(lo_fd(req, ino), ".", O_RDONLY);
1253     if (fd == -1) {
1254         goto out_errno;
1255     }
1256
1257     d->dp = fdopendir(fd);
1258     if (d->dp == NULL) {
1259         goto out_errno;
1260     }
1261
1262     d->offset = 0;
1263     d->entry = NULL;
1264
1265     pthread_mutex_lock(&lo->mutex);
1266     fh = lo_add_dirp_mapping(req, d);
1267     pthread_mutex_unlock(&lo->mutex);
1268     if (fh == -1) {
1269         goto out_err;
1270     }
1271
1272     fi->fh = fh;
1273     if (lo->cache == CACHE_ALWAYS) {
1274         fi->keep_cache = 1;
1275     }
1276     fuse_reply_open(req, fi);
1277     return;
1278
1279 out_errno:
1280     error = errno;
1281 out_err:
1282     if (d) {
1283         if (d->dp) {
1284             closedir(d->dp);
1285         }
1286         if (fd != -1) {
1287             close(fd);
1288         }
1289         free(d);
1290     }
1291     fuse_reply_err(req, error);
1292 }
1293
1294 static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
1295                           off_t offset, struct fuse_file_info *fi, int plus)
1296 {
1297     struct lo_data *lo = lo_data(req);
1298     struct lo_dirp *d;
1299     struct lo_inode *dinode;
1300     char *buf = NULL;
1301     char *p;
1302     size_t rem = size;
1303     int err = EBADF;
1304
1305     dinode = lo_inode(req, ino);
1306     if (!dinode) {
1307         goto error;
1308     }
1309
1310     d = lo_dirp(req, fi);
1311     if (!d) {
1312         goto error;
1313     }
1314
1315     err = ENOMEM;
1316     buf = calloc(1, size);
1317     if (!buf) {
1318         goto error;
1319     }
1320     p = buf;
1321
1322     if (offset != d->offset) {
1323         seekdir(d->dp, offset);
1324         d->entry = NULL;
1325         d->offset = offset;
1326     }
1327     while (1) {
1328         size_t entsize;
1329         off_t nextoff;
1330         const char *name;
1331
1332         if (!d->entry) {
1333             errno = 0;
1334             d->entry = readdir(d->dp);
1335             if (!d->entry) {
1336                 if (errno) { /* Error */
1337                     err = errno;
1338                     goto error;
1339                 } else { /* End of stream */
1340                     break;
1341                 }
1342             }
1343         }
1344         nextoff = d->entry->d_off;
1345         name = d->entry->d_name;
1346
1347         fuse_ino_t entry_ino = 0;
1348         struct fuse_entry_param e = (struct fuse_entry_param){
1349             .attr.st_ino = d->entry->d_ino,
1350             .attr.st_mode = d->entry->d_type << 12,
1351         };
1352
1353         /* Hide root's parent directory */
1354         if (dinode == &lo->root && strcmp(name, "..") == 0) {
1355             e.attr.st_ino = lo->root.ino;
1356             e.attr.st_mode = DT_DIR << 12;
1357         }
1358
1359         if (plus) {
1360             if (!is_dot_or_dotdot(name)) {
1361                 err = lo_do_lookup(req, ino, name, &e);
1362                 if (err) {
1363                     goto error;
1364                 }
1365                 entry_ino = e.ino;
1366             }
1367
1368             entsize = fuse_add_direntry_plus(req, p, rem, name, &e, nextoff);
1369         } else {
1370             entsize = fuse_add_direntry(req, p, rem, name, &e.attr, nextoff);
1371         }
1372         if (entsize > rem) {
1373             if (entry_ino != 0) {
1374                 lo_forget_one(req, entry_ino, 1);
1375             }
1376             break;
1377         }
1378
1379         p += entsize;
1380         rem -= entsize;
1381
1382         d->entry = NULL;
1383         d->offset = nextoff;
1384     }
1385
1386     err = 0;
1387 error:
1388     /*
1389      * If there's an error, we can only signal it if we haven't stored
1390      * any entries yet - otherwise we'd end up with wrong lookup
1391      * counts for the entries that are already in the buffer. So we
1392      * return what we've collected until that point.
1393      */
1394     if (err && rem == size) {
1395         fuse_reply_err(req, err);
1396     } else {
1397         fuse_reply_buf(req, buf, size - rem);
1398     }
1399     free(buf);
1400 }
1401
1402 static void lo_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
1403                        off_t offset, struct fuse_file_info *fi)
1404 {
1405     lo_do_readdir(req, ino, size, offset, fi, 0);
1406 }
1407
1408 static void lo_readdirplus(fuse_req_t req, fuse_ino_t ino, size_t size,
1409                            off_t offset, struct fuse_file_info *fi)
1410 {
1411     lo_do_readdir(req, ino, size, offset, fi, 1);
1412 }
1413
1414 static void lo_releasedir(fuse_req_t req, fuse_ino_t ino,
1415                           struct fuse_file_info *fi)
1416 {
1417     struct lo_data *lo = lo_data(req);
1418     struct lo_dirp *d;
1419
1420     (void)ino;
1421
1422     d = lo_dirp(req, fi);
1423     if (!d) {
1424         fuse_reply_err(req, EBADF);
1425         return;
1426     }
1427
1428     pthread_mutex_lock(&lo->mutex);
1429     lo_map_remove(&lo->dirp_map, fi->fh);
1430     pthread_mutex_unlock(&lo->mutex);
1431
1432     closedir(d->dp);
1433     free(d);
1434     fuse_reply_err(req, 0);
1435 }
1436
1437 static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
1438                       mode_t mode, struct fuse_file_info *fi)
1439 {
1440     int fd;
1441     struct lo_data *lo = lo_data(req);
1442     struct fuse_entry_param e;
1443     int err;
1444     struct lo_cred old = {};
1445
1446     if (lo_debug(req)) {
1447         fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=%" PRIu64 ", name=%s)\n",
1448                  parent, name);
1449     }
1450
1451     if (!is_safe_path_component(name)) {
1452         fuse_reply_err(req, EINVAL);
1453         return;
1454     }
1455
1456     err = lo_change_cred(req, &old);
1457     if (err) {
1458         goto out;
1459     }
1460
1461     fd = openat(lo_fd(req, parent), name, (fi->flags | O_CREAT) & ~O_NOFOLLOW,
1462                 mode);
1463     err = fd == -1 ? errno : 0;
1464     lo_restore_cred(&old);
1465
1466     if (!err) {
1467         ssize_t fh;
1468
1469         pthread_mutex_lock(&lo->mutex);
1470         fh = lo_add_fd_mapping(req, fd);
1471         pthread_mutex_unlock(&lo->mutex);
1472         if (fh == -1) {
1473             close(fd);
1474             fuse_reply_err(req, ENOMEM);
1475             return;
1476         }
1477
1478         fi->fh = fh;
1479         err = lo_do_lookup(req, parent, name, &e);
1480     }
1481     if (lo->cache == CACHE_NEVER) {
1482         fi->direct_io = 1;
1483     } else if (lo->cache == CACHE_ALWAYS) {
1484         fi->keep_cache = 1;
1485     }
1486
1487 out:
1488     if (err) {
1489         fuse_reply_err(req, err);
1490     } else {
1491         fuse_reply_create(req, &e, fi);
1492     }
1493 }
1494
1495 static void lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
1496                         struct fuse_file_info *fi)
1497 {
1498     int res;
1499     struct lo_dirp *d;
1500     int fd;
1501
1502     (void)ino;
1503
1504     d = lo_dirp(req, fi);
1505     if (!d) {
1506         fuse_reply_err(req, EBADF);
1507         return;
1508     }
1509
1510     fd = dirfd(d->dp);
1511     if (datasync) {
1512         res = fdatasync(fd);
1513     } else {
1514         res = fsync(fd);
1515     }
1516     fuse_reply_err(req, res == -1 ? errno : 0);
1517 }
1518
1519 static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
1520 {
1521     int fd;
1522     ssize_t fh;
1523     char buf[64];
1524     struct lo_data *lo = lo_data(req);
1525
1526     if (lo_debug(req)) {
1527         fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=%" PRIu64 ", flags=%d)\n", ino,
1528                  fi->flags);
1529     }
1530
1531     /*
1532      * With writeback cache, kernel may send read requests even
1533      * when userspace opened write-only
1534      */
1535     if (lo->writeback && (fi->flags & O_ACCMODE) == O_WRONLY) {
1536         fi->flags &= ~O_ACCMODE;
1537         fi->flags |= O_RDWR;
1538     }
1539
1540     /*
1541      * With writeback cache, O_APPEND is handled by the kernel.
1542      * This breaks atomicity (since the file may change in the
1543      * underlying filesystem, so that the kernel's idea of the
1544      * end of the file isn't accurate anymore). In this example,
1545      * we just accept that. A more rigorous filesystem may want
1546      * to return an error here
1547      */
1548     if (lo->writeback && (fi->flags & O_APPEND)) {
1549         fi->flags &= ~O_APPEND;
1550     }
1551
1552     sprintf(buf, "%i", lo_fd(req, ino));
1553     fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW);
1554     if (fd == -1) {
1555         return (void)fuse_reply_err(req, errno);
1556     }
1557
1558     pthread_mutex_lock(&lo->mutex);
1559     fh = lo_add_fd_mapping(req, fd);
1560     pthread_mutex_unlock(&lo->mutex);
1561     if (fh == -1) {
1562         close(fd);
1563         fuse_reply_err(req, ENOMEM);
1564         return;
1565     }
1566
1567     fi->fh = fh;
1568     if (lo->cache == CACHE_NEVER) {
1569         fi->direct_io = 1;
1570     } else if (lo->cache == CACHE_ALWAYS) {
1571         fi->keep_cache = 1;
1572     }
1573     fuse_reply_open(req, fi);
1574 }
1575
1576 static void lo_release(fuse_req_t req, fuse_ino_t ino,
1577                        struct fuse_file_info *fi)
1578 {
1579     struct lo_data *lo = lo_data(req);
1580     int fd;
1581
1582     (void)ino;
1583
1584     fd = lo_fi_fd(req, fi);
1585
1586     pthread_mutex_lock(&lo->mutex);
1587     lo_map_remove(&lo->fd_map, fi->fh);
1588     pthread_mutex_unlock(&lo->mutex);
1589
1590     close(fd);
1591     fuse_reply_err(req, 0);
1592 }
1593
1594 static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
1595 {
1596     int res;
1597     (void)ino;
1598     res = close(dup(lo_fi_fd(req, fi)));
1599     fuse_reply_err(req, res == -1 ? errno : 0);
1600 }
1601
1602 static void lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
1603                      struct fuse_file_info *fi)
1604 {
1605     int res;
1606     int fd;
1607     char *buf;
1608
1609     fuse_log(FUSE_LOG_DEBUG, "lo_fsync(ino=%" PRIu64 ", fi=0x%p)\n", ino,
1610              (void *)fi);
1611
1612     if (!fi) {
1613         struct lo_data *lo = lo_data(req);
1614
1615         res = asprintf(&buf, "%i", lo_fd(req, ino));
1616         if (res == -1) {
1617             return (void)fuse_reply_err(req, errno);
1618         }
1619
1620         fd = openat(lo->proc_self_fd, buf, O_RDWR);
1621         free(buf);
1622         if (fd == -1) {
1623             return (void)fuse_reply_err(req, errno);
1624         }
1625     } else {
1626         fd = lo_fi_fd(req, fi);
1627     }
1628
1629     if (datasync) {
1630         res = fdatasync(fd);
1631     } else {
1632         res = fsync(fd);
1633     }
1634     if (!fi) {
1635         close(fd);
1636     }
1637     fuse_reply_err(req, res == -1 ? errno : 0);
1638 }
1639
1640 static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset,
1641                     struct fuse_file_info *fi)
1642 {
1643     struct fuse_bufvec buf = FUSE_BUFVEC_INIT(size);
1644
1645     if (lo_debug(req)) {
1646         fuse_log(FUSE_LOG_DEBUG,
1647                  "lo_read(ino=%" PRIu64 ", size=%zd, "
1648                  "off=%lu)\n",
1649                  ino, size, (unsigned long)offset);
1650     }
1651
1652     buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
1653     buf.buf[0].fd = lo_fi_fd(req, fi);
1654     buf.buf[0].pos = offset;
1655
1656     fuse_reply_data(req, &buf);
1657 }
1658
1659 static void lo_write_buf(fuse_req_t req, fuse_ino_t ino,
1660                          struct fuse_bufvec *in_buf, off_t off,
1661                          struct fuse_file_info *fi)
1662 {
1663     (void)ino;
1664     ssize_t res;
1665     struct fuse_bufvec out_buf = FUSE_BUFVEC_INIT(fuse_buf_size(in_buf));
1666     bool cap_fsetid_dropped = false;
1667
1668     out_buf.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
1669     out_buf.buf[0].fd = lo_fi_fd(req, fi);
1670     out_buf.buf[0].pos = off;
1671
1672     if (lo_debug(req)) {
1673         fuse_log(FUSE_LOG_DEBUG,
1674                  "lo_write(ino=%" PRIu64 ", size=%zd, off=%lu)\n", ino,
1675                  out_buf.buf[0].size, (unsigned long)off);
1676     }
1677
1678     /*
1679      * If kill_priv is set, drop CAP_FSETID which should lead to kernel
1680      * clearing setuid/setgid on file.
1681      */
1682     if (fi->kill_priv) {
1683         res = drop_effective_cap("FSETID", &cap_fsetid_dropped);
1684         if (res != 0) {
1685             fuse_reply_err(req, res);
1686             return;
1687         }
1688     }
1689
1690     res = fuse_buf_copy(&out_buf, in_buf);
1691     if (res < 0) {
1692         fuse_reply_err(req, -res);
1693     } else {
1694         fuse_reply_write(req, (size_t)res);
1695     }
1696
1697     if (cap_fsetid_dropped) {
1698         res = gain_effective_cap("FSETID");
1699         if (res) {
1700             fuse_log(FUSE_LOG_ERR, "Failed to gain CAP_FSETID\n");
1701         }
1702     }
1703 }
1704
1705 static void lo_statfs(fuse_req_t req, fuse_ino_t ino)
1706 {
1707     int res;
1708     struct statvfs stbuf;
1709
1710     res = fstatvfs(lo_fd(req, ino), &stbuf);
1711     if (res == -1) {
1712         fuse_reply_err(req, errno);
1713     } else {
1714         fuse_reply_statfs(req, &stbuf);
1715     }
1716 }
1717
1718 static void lo_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, off_t offset,
1719                          off_t length, struct fuse_file_info *fi)
1720 {
1721     int err = EOPNOTSUPP;
1722     (void)ino;
1723
1724 #ifdef CONFIG_FALLOCATE
1725     err = fallocate(lo_fi_fd(req, fi), mode, offset, length);
1726     if (err < 0) {
1727         err = errno;
1728     }
1729
1730 #elif defined(CONFIG_POSIX_FALLOCATE)
1731     if (mode) {
1732         fuse_reply_err(req, EOPNOTSUPP);
1733         return;
1734     }
1735
1736     err = posix_fallocate(lo_fi_fd(req, fi), offset, length);
1737 #endif
1738
1739     fuse_reply_err(req, err);
1740 }
1741
1742 static void lo_flock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi,
1743                      int op)
1744 {
1745     int res;
1746     (void)ino;
1747
1748     res = flock(lo_fi_fd(req, fi), op);
1749
1750     fuse_reply_err(req, res == -1 ? errno : 0);
1751 }
1752
1753 static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
1754                         size_t size)
1755 {
1756     struct lo_data *lo = lo_data(req);
1757     char *value = NULL;
1758     char procname[64];
1759     struct lo_inode *inode;
1760     ssize_t ret;
1761     int saverr;
1762     int fd = -1;
1763
1764     inode = lo_inode(req, ino);
1765     if (!inode) {
1766         fuse_reply_err(req, EBADF);
1767         return;
1768     }
1769
1770     saverr = ENOSYS;
1771     if (!lo_data(req)->xattr) {
1772         goto out;
1773     }
1774
1775     if (lo_debug(req)) {
1776         fuse_log(FUSE_LOG_DEBUG,
1777                  "lo_getxattr(ino=%" PRIu64 ", name=%s size=%zd)\n", ino, name,
1778                  size);
1779     }
1780
1781     if (inode->is_symlink) {
1782         /* Sorry, no race free way to getxattr on symlink. */
1783         saverr = EPERM;
1784         goto out;
1785     }
1786
1787     sprintf(procname, "%i", inode->fd);
1788     fd = openat(lo->proc_self_fd, procname, O_RDONLY);
1789     if (fd < 0) {
1790         goto out_err;
1791     }
1792
1793     if (size) {
1794         value = malloc(size);
1795         if (!value) {
1796             goto out_err;
1797         }
1798
1799         ret = fgetxattr(fd, name, value, size);
1800         if (ret == -1) {
1801             goto out_err;
1802         }
1803         saverr = 0;
1804         if (ret == 0) {
1805             goto out;
1806         }
1807
1808         fuse_reply_buf(req, value, ret);
1809     } else {
1810         ret = fgetxattr(fd, name, NULL, 0);
1811         if (ret == -1) {
1812             goto out_err;
1813         }
1814
1815         fuse_reply_xattr(req, ret);
1816     }
1817 out_free:
1818     free(value);
1819
1820     if (fd >= 0) {
1821         close(fd);
1822     }
1823     return;
1824
1825 out_err:
1826     saverr = errno;
1827 out:
1828     fuse_reply_err(req, saverr);
1829     goto out_free;
1830 }
1831
1832 static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
1833 {
1834     struct lo_data *lo = lo_data(req);
1835     char *value = NULL;
1836     char procname[64];
1837     struct lo_inode *inode;
1838     ssize_t ret;
1839     int saverr;
1840     int fd = -1;
1841
1842     inode = lo_inode(req, ino);
1843     if (!inode) {
1844         fuse_reply_err(req, EBADF);
1845         return;
1846     }
1847
1848     saverr = ENOSYS;
1849     if (!lo_data(req)->xattr) {
1850         goto out;
1851     }
1852
1853     if (lo_debug(req)) {
1854         fuse_log(FUSE_LOG_DEBUG, "lo_listxattr(ino=%" PRIu64 ", size=%zd)\n",
1855                  ino, size);
1856     }
1857
1858     if (inode->is_symlink) {
1859         /* Sorry, no race free way to listxattr on symlink. */
1860         saverr = EPERM;
1861         goto out;
1862     }
1863
1864     sprintf(procname, "%i", inode->fd);
1865     fd = openat(lo->proc_self_fd, procname, O_RDONLY);
1866     if (fd < 0) {
1867         goto out_err;
1868     }
1869
1870     if (size) {
1871         value = malloc(size);
1872         if (!value) {
1873             goto out_err;
1874         }
1875
1876         ret = flistxattr(fd, value, size);
1877         if (ret == -1) {
1878             goto out_err;
1879         }
1880         saverr = 0;
1881         if (ret == 0) {
1882             goto out;
1883         }
1884
1885         fuse_reply_buf(req, value, ret);
1886     } else {
1887         ret = flistxattr(fd, NULL, 0);
1888         if (ret == -1) {
1889             goto out_err;
1890         }
1891
1892         fuse_reply_xattr(req, ret);
1893     }
1894 out_free:
1895     free(value);
1896
1897     if (fd >= 0) {
1898         close(fd);
1899     }
1900     return;
1901
1902 out_err:
1903     saverr = errno;
1904 out:
1905     fuse_reply_err(req, saverr);
1906     goto out_free;
1907 }
1908
1909 static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
1910                         const char *value, size_t size, int flags)
1911 {
1912     char procname[64];
1913     struct lo_data *lo = lo_data(req);
1914     struct lo_inode *inode;
1915     ssize_t ret;
1916     int saverr;
1917     int fd = -1;
1918
1919     inode = lo_inode(req, ino);
1920     if (!inode) {
1921         fuse_reply_err(req, EBADF);
1922         return;
1923     }
1924
1925     saverr = ENOSYS;
1926     if (!lo_data(req)->xattr) {
1927         goto out;
1928     }
1929
1930     if (lo_debug(req)) {
1931         fuse_log(FUSE_LOG_DEBUG,
1932                  "lo_setxattr(ino=%" PRIu64 ", name=%s value=%s size=%zd)\n",
1933                  ino, name, value, size);
1934     }
1935
1936     if (inode->is_symlink) {
1937         /* Sorry, no race free way to setxattr on symlink. */
1938         saverr = EPERM;
1939         goto out;
1940     }
1941
1942     sprintf(procname, "%i", inode->fd);
1943     fd = openat(lo->proc_self_fd, procname, O_RDWR);
1944     if (fd < 0) {
1945         saverr = errno;
1946         goto out;
1947     }
1948
1949     ret = fsetxattr(fd, name, value, size, flags);
1950     saverr = ret == -1 ? errno : 0;
1951
1952 out:
1953     if (fd >= 0) {
1954         close(fd);
1955     }
1956     fuse_reply_err(req, saverr);
1957 }
1958
1959 static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *name)
1960 {
1961     char procname[64];
1962     struct lo_data *lo = lo_data(req);
1963     struct lo_inode *inode;
1964     ssize_t ret;
1965     int saverr;
1966     int fd = -1;
1967
1968     inode = lo_inode(req, ino);
1969     if (!inode) {
1970         fuse_reply_err(req, EBADF);
1971         return;
1972     }
1973
1974     saverr = ENOSYS;
1975     if (!lo_data(req)->xattr) {
1976         goto out;
1977     }
1978
1979     if (lo_debug(req)) {
1980         fuse_log(FUSE_LOG_DEBUG, "lo_removexattr(ino=%" PRIu64 ", name=%s)\n",
1981                  ino, name);
1982     }
1983
1984     if (inode->is_symlink) {
1985         /* Sorry, no race free way to setxattr on symlink. */
1986         saverr = EPERM;
1987         goto out;
1988     }
1989
1990     sprintf(procname, "%i", inode->fd);
1991     fd = openat(lo->proc_self_fd, procname, O_RDWR);
1992     if (fd < 0) {
1993         saverr = errno;
1994         goto out;
1995     }
1996
1997     ret = fremovexattr(fd, name);
1998     saverr = ret == -1 ? errno : 0;
1999
2000 out:
2001     if (fd >= 0) {
2002         close(fd);
2003     }
2004     fuse_reply_err(req, saverr);
2005 }
2006
2007 #ifdef HAVE_COPY_FILE_RANGE
2008 static void lo_copy_file_range(fuse_req_t req, fuse_ino_t ino_in, off_t off_in,
2009                                struct fuse_file_info *fi_in, fuse_ino_t ino_out,
2010                                off_t off_out, struct fuse_file_info *fi_out,
2011                                size_t len, int flags)
2012 {
2013     int in_fd, out_fd;
2014     ssize_t res;
2015
2016     in_fd = lo_fi_fd(req, fi_in);
2017     out_fd = lo_fi_fd(req, fi_out);
2018
2019     fuse_log(FUSE_LOG_DEBUG,
2020              "lo_copy_file_range(ino=%" PRIu64 "/fd=%d, "
2021              "off=%lu, ino=%" PRIu64 "/fd=%d, "
2022              "off=%lu, size=%zd, flags=0x%x)\n",
2023              ino_in, in_fd, off_in, ino_out, out_fd, off_out, len, flags);
2024
2025     res = copy_file_range(in_fd, &off_in, out_fd, &off_out, len, flags);
2026     if (res < 0) {
2027         fuse_reply_err(req, -errno);
2028     } else {
2029         fuse_reply_write(req, res);
2030     }
2031 }
2032 #endif
2033
2034 static void lo_lseek(fuse_req_t req, fuse_ino_t ino, off_t off, int whence,
2035                      struct fuse_file_info *fi)
2036 {
2037     off_t res;
2038
2039     (void)ino;
2040     res = lseek(lo_fi_fd(req, fi), off, whence);
2041     if (res != -1) {
2042         fuse_reply_lseek(req, res);
2043     } else {
2044         fuse_reply_err(req, errno);
2045     }
2046 }
2047
2048 static struct fuse_lowlevel_ops lo_oper = {
2049     .init = lo_init,
2050     .lookup = lo_lookup,
2051     .mkdir = lo_mkdir,
2052     .mknod = lo_mknod,
2053     .symlink = lo_symlink,
2054     .link = lo_link,
2055     .unlink = lo_unlink,
2056     .rmdir = lo_rmdir,
2057     .rename = lo_rename,
2058     .forget = lo_forget,
2059     .forget_multi = lo_forget_multi,
2060     .getattr = lo_getattr,
2061     .setattr = lo_setattr,
2062     .readlink = lo_readlink,
2063     .opendir = lo_opendir,
2064     .readdir = lo_readdir,
2065     .readdirplus = lo_readdirplus,
2066     .releasedir = lo_releasedir,
2067     .fsyncdir = lo_fsyncdir,
2068     .create = lo_create,
2069     .open = lo_open,
2070     .release = lo_release,
2071     .flush = lo_flush,
2072     .fsync = lo_fsync,
2073     .read = lo_read,
2074     .write_buf = lo_write_buf,
2075     .statfs = lo_statfs,
2076     .fallocate = lo_fallocate,
2077     .flock = lo_flock,
2078     .getxattr = lo_getxattr,
2079     .listxattr = lo_listxattr,
2080     .setxattr = lo_setxattr,
2081     .removexattr = lo_removexattr,
2082 #ifdef HAVE_COPY_FILE_RANGE
2083     .copy_file_range = lo_copy_file_range,
2084 #endif
2085     .lseek = lo_lseek,
2086 };
2087
2088 /* Print vhost-user.json backend program capabilities */
2089 static void print_capabilities(void)
2090 {
2091     printf("{\n");
2092     printf("  \"type\": \"fs\"\n");
2093     printf("}\n");
2094 }
2095
2096 /*
2097  * Move to a new mount, net, and pid namespaces to isolate this process.
2098  */
2099 static void setup_namespaces(struct lo_data *lo, struct fuse_session *se)
2100 {
2101     pid_t child;
2102
2103     /*
2104      * Create a new pid namespace for *child* processes.  We'll have to
2105      * fork in order to enter the new pid namespace.  A new mount namespace
2106      * is also needed so that we can remount /proc for the new pid
2107      * namespace.
2108      *
2109      * Our UNIX domain sockets have been created.  Now we can move to
2110      * an empty network namespace to prevent TCP/IP and other network
2111      * activity in case this process is compromised.
2112      */
2113     if (unshare(CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET) != 0) {
2114         fuse_log(FUSE_LOG_ERR, "unshare(CLONE_NEWPID | CLONE_NEWNS): %m\n");
2115         exit(1);
2116     }
2117
2118     child = fork();
2119     if (child < 0) {
2120         fuse_log(FUSE_LOG_ERR, "fork() failed: %m\n");
2121         exit(1);
2122     }
2123     if (child > 0) {
2124         pid_t waited;
2125         int wstatus;
2126
2127         /* The parent waits for the child */
2128         do {
2129             waited = waitpid(child, &wstatus, 0);
2130         } while (waited < 0 && errno == EINTR && !se->exited);
2131
2132         /* We were terminated by a signal, see fuse_signals.c */
2133         if (se->exited) {
2134             exit(0);
2135         }
2136
2137         if (WIFEXITED(wstatus)) {
2138             exit(WEXITSTATUS(wstatus));
2139         }
2140
2141         exit(1);
2142     }
2143
2144     /* Send us SIGTERM when the parent thread terminates, see prctl(2) */
2145     prctl(PR_SET_PDEATHSIG, SIGTERM);
2146
2147     /*
2148      * If the mounts have shared propagation then we want to opt out so our
2149      * mount changes don't affect the parent mount namespace.
2150      */
2151     if (mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL) < 0) {
2152         fuse_log(FUSE_LOG_ERR, "mount(/, MS_REC|MS_SLAVE): %m\n");
2153         exit(1);
2154     }
2155
2156     /* The child must remount /proc to use the new pid namespace */
2157     if (mount("proc", "/proc", "proc",
2158               MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RELATIME, NULL) < 0) {
2159         fuse_log(FUSE_LOG_ERR, "mount(/proc): %m\n");
2160         exit(1);
2161     }
2162
2163     /* Now we can get our /proc/self/fd directory file descriptor */
2164     lo->proc_self_fd = open("/proc/self/fd", O_PATH);
2165     if (lo->proc_self_fd == -1) {
2166         fuse_log(FUSE_LOG_ERR, "open(/proc/self/fd, O_PATH): %m\n");
2167         exit(1);
2168     }
2169 }
2170
2171 /*
2172  * Capture the capability state, we'll need to restore this for individual
2173  * threads later; see load_capng.
2174  */
2175 static void setup_capng(void)
2176 {
2177     /* Note this accesses /proc so has to happen before the sandbox */
2178     if (capng_get_caps_process()) {
2179         fuse_log(FUSE_LOG_ERR, "capng_get_caps_process\n");
2180         exit(1);
2181     }
2182     pthread_mutex_init(&cap.mutex, NULL);
2183     pthread_mutex_lock(&cap.mutex);
2184     cap.saved = capng_save_state();
2185     if (!cap.saved) {
2186         fuse_log(FUSE_LOG_ERR, "capng_save_state\n");
2187         exit(1);
2188     }
2189     pthread_mutex_unlock(&cap.mutex);
2190 }
2191
2192 static void cleanup_capng(void)
2193 {
2194     free(cap.saved);
2195     cap.saved = NULL;
2196     pthread_mutex_destroy(&cap.mutex);
2197 }
2198
2199
2200 /*
2201  * Make the source directory our root so symlinks cannot escape and no other
2202  * files are accessible.  Assumes unshare(CLONE_NEWNS) was already called.
2203  */
2204 static void setup_mounts(const char *source)
2205 {
2206     int oldroot;
2207     int newroot;
2208
2209     if (mount(source, source, NULL, MS_BIND, NULL) < 0) {
2210         fuse_log(FUSE_LOG_ERR, "mount(%s, %s, MS_BIND): %m\n", source, source);
2211         exit(1);
2212     }
2213
2214     /* This magic is based on lxc's lxc_pivot_root() */
2215     oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
2216     if (oldroot < 0) {
2217         fuse_log(FUSE_LOG_ERR, "open(/): %m\n");
2218         exit(1);
2219     }
2220
2221     newroot = open(source, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
2222     if (newroot < 0) {
2223         fuse_log(FUSE_LOG_ERR, "open(%s): %m\n", source);
2224         exit(1);
2225     }
2226
2227     if (fchdir(newroot) < 0) {
2228         fuse_log(FUSE_LOG_ERR, "fchdir(newroot): %m\n");
2229         exit(1);
2230     }
2231
2232     if (syscall(__NR_pivot_root, ".", ".") < 0) {
2233         fuse_log(FUSE_LOG_ERR, "pivot_root(., .): %m\n");
2234         exit(1);
2235     }
2236
2237     if (fchdir(oldroot) < 0) {
2238         fuse_log(FUSE_LOG_ERR, "fchdir(oldroot): %m\n");
2239         exit(1);
2240     }
2241
2242     if (mount("", ".", "", MS_SLAVE | MS_REC, NULL) < 0) {
2243         fuse_log(FUSE_LOG_ERR, "mount(., MS_SLAVE | MS_REC): %m\n");
2244         exit(1);
2245     }
2246
2247     if (umount2(".", MNT_DETACH) < 0) {
2248         fuse_log(FUSE_LOG_ERR, "umount2(., MNT_DETACH): %m\n");
2249         exit(1);
2250     }
2251
2252     if (fchdir(newroot) < 0) {
2253         fuse_log(FUSE_LOG_ERR, "fchdir(newroot): %m\n");
2254         exit(1);
2255     }
2256
2257     close(newroot);
2258     close(oldroot);
2259 }
2260
2261 /*
2262  * Lock down this process to prevent access to other processes or files outside
2263  * source directory.  This reduces the impact of arbitrary code execution bugs.
2264  */
2265 static void setup_sandbox(struct lo_data *lo, struct fuse_session *se)
2266 {
2267     setup_namespaces(lo, se);
2268     setup_mounts(lo->source);
2269     setup_seccomp();
2270 }
2271
2272 /* Raise the maximum number of open file descriptors */
2273 static void setup_nofile_rlimit(void)
2274 {
2275     const rlim_t max_fds = 1000000;
2276     struct rlimit rlim;
2277
2278     if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
2279         fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n");
2280         exit(1);
2281     }
2282
2283     if (rlim.rlim_cur >= max_fds) {
2284         return; /* nothing to do */
2285     }
2286
2287     rlim.rlim_cur = max_fds;
2288     rlim.rlim_max = max_fds;
2289
2290     if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
2291         /* Ignore SELinux denials */
2292         if (errno == EPERM) {
2293             return;
2294         }
2295
2296         fuse_log(FUSE_LOG_ERR, "setrlimit(RLIMIT_NOFILE): %m\n");
2297         exit(1);
2298     }
2299 }
2300
2301 int main(int argc, char *argv[])
2302 {
2303     struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
2304     struct fuse_session *se;
2305     struct fuse_cmdline_opts opts;
2306     struct lo_data lo = {
2307         .debug = 0,
2308         .writeback = 0,
2309         .proc_self_fd = -1,
2310     };
2311     struct lo_map_elem *root_elem;
2312     int ret = -1;
2313
2314     /* Don't mask creation mode, kernel already did that */
2315     umask(0);
2316
2317     pthread_mutex_init(&lo.mutex, NULL);
2318     lo.root.next = lo.root.prev = &lo.root;
2319     lo.root.fd = -1;
2320     lo.root.fuse_ino = FUSE_ROOT_ID;
2321     lo.cache = CACHE_NORMAL;
2322
2323     /*
2324      * Set up the ino map like this:
2325      * [0] Reserved (will not be used)
2326      * [1] Root inode
2327      */
2328     lo_map_init(&lo.ino_map);
2329     lo_map_reserve(&lo.ino_map, 0)->in_use = false;
2330     root_elem = lo_map_reserve(&lo.ino_map, lo.root.fuse_ino);
2331     root_elem->inode = &lo.root;
2332
2333     lo_map_init(&lo.dirp_map);
2334     lo_map_init(&lo.fd_map);
2335
2336     if (fuse_parse_cmdline(&args, &opts) != 0) {
2337         return 1;
2338     }
2339     if (opts.show_help) {
2340         printf("usage: %s [options]\n\n", argv[0]);
2341         fuse_cmdline_help();
2342         printf("    -o source=PATH             shared directory tree\n");
2343         fuse_lowlevel_help();
2344         ret = 0;
2345         goto err_out1;
2346     } else if (opts.show_version) {
2347         fuse_lowlevel_version();
2348         ret = 0;
2349         goto err_out1;
2350     } else if (opts.print_capabilities) {
2351         print_capabilities();
2352         ret = 0;
2353         goto err_out1;
2354     }
2355
2356     if (fuse_opt_parse(&args, &lo, lo_opts, NULL) == -1) {
2357         return 1;
2358     }
2359
2360     lo.debug = opts.debug;
2361     lo.root.refcount = 2;
2362     if (lo.source) {
2363         struct stat stat;
2364         int res;
2365
2366         res = lstat(lo.source, &stat);
2367         if (res == -1) {
2368             fuse_log(FUSE_LOG_ERR, "failed to stat source (\"%s\"): %m\n",
2369                      lo.source);
2370             exit(1);
2371         }
2372         if (!S_ISDIR(stat.st_mode)) {
2373             fuse_log(FUSE_LOG_ERR, "source is not a directory\n");
2374             exit(1);
2375         }
2376
2377     } else {
2378         lo.source = "/";
2379     }
2380     lo.root.is_symlink = false;
2381     if (!lo.timeout_set) {
2382         switch (lo.cache) {
2383         case CACHE_NEVER:
2384             lo.timeout = 0.0;
2385             break;
2386
2387         case CACHE_NORMAL:
2388             lo.timeout = 1.0;
2389             break;
2390
2391         case CACHE_ALWAYS:
2392             lo.timeout = 86400.0;
2393             break;
2394         }
2395     } else if (lo.timeout < 0) {
2396         fuse_log(FUSE_LOG_ERR, "timeout is negative (%lf)\n", lo.timeout);
2397         exit(1);
2398     }
2399
2400     lo.root.fd = open(lo.source, O_PATH);
2401
2402     if (lo.root.fd == -1) {
2403         fuse_log(FUSE_LOG_ERR, "open(\"%s\", O_PATH): %m\n", lo.source);
2404         exit(1);
2405     }
2406
2407     se = fuse_session_new(&args, &lo_oper, sizeof(lo_oper), &lo);
2408     if (se == NULL) {
2409         goto err_out1;
2410     }
2411
2412     if (fuse_set_signal_handlers(se) != 0) {
2413         goto err_out2;
2414     }
2415
2416     if (fuse_session_mount(se) != 0) {
2417         goto err_out3;
2418     }
2419
2420     fuse_daemonize(opts.foreground);
2421
2422     setup_nofile_rlimit();
2423
2424     /* Must be before sandbox since it wants /proc */
2425     setup_capng();
2426
2427     setup_sandbox(&lo, se);
2428
2429     /* Block until ctrl+c or fusermount -u */
2430     ret = virtio_loop(se);
2431
2432     fuse_session_unmount(se);
2433     cleanup_capng();
2434 err_out3:
2435     fuse_remove_signal_handlers(se);
2436 err_out2:
2437     fuse_session_destroy(se);
2438 err_out1:
2439     fuse_opt_free_args(&args);
2440
2441     lo_map_destroy(&lo.fd_map);
2442     lo_map_destroy(&lo.dirp_map);
2443     lo_map_destroy(&lo.ino_map);
2444
2445     if (lo.proc_self_fd >= 0) {
2446         close(lo.proc_self_fd);
2447     }
2448
2449     if (lo.root.fd >= 0) {
2450         close(lo.root.fd);
2451     }
2452
2453     return ret ? 1 : 0;
2454 }
This page took 0.158852 seconds and 4 git commands to generate.