2 * FUSE: Filesystem in Userspace
3 * Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 * This program can be distributed under the terms of the GNU GPLv2.
6 * See the file COPYING.
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
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).
31 * gcc -Wall passthrough_ll.c `pkg-config fuse3 --cflags --libs` -o
35 * \include passthrough_ll.c
38 #include "qemu/osdep.h"
39 #include "qemu/timer.h"
40 #include "fuse_virtio.h"
42 #include "fuse_lowlevel.h"
57 #include <sys/mount.h>
58 #include <sys/prctl.h>
59 #include <sys/resource.h>
60 #include <sys/syscall.h>
61 #include <sys/types.h>
63 #include <sys/xattr.h>
67 #include "passthrough_helpers.h"
70 /* Keep track of inode posix locks for each owner. */
71 struct lo_inode_plock
{
73 int fd
; /* fd for OFD locks */
78 struct lo_inode
*inode
;
86 /* Maps FUSE fh or ino values to internal objects */
88 struct lo_map_elem
*elems
;
102 * Atomic reference count for this object. The nlookup field holds a
103 * reference and release it when nlookup reaches 0.
110 * This counter keeps the inode alive during the FUSE session.
111 * Incremented when the FUSE inode number is sent in a reply
112 * (FUSE_LOOKUP, FUSE_READDIRPLUS, etc). Decremented when an inode is
113 * released by requests like FUSE_FORGET, FUSE_RMDIR, FUSE_RENAME, etc.
115 * Note that this value is untrusted because the client can manipulate
116 * it arbitrarily using FUSE_FORGET requests.
118 * Protected by lo->mutex.
123 pthread_mutex_t plock_mutex
;
124 GHashTable
*posix_locks
; /* protected by lo_inode->plock_mutex */
141 pthread_mutex_t mutex
;
153 int readdirplus_clear
;
154 struct lo_inode root
;
155 GHashTable
*inodes
; /* protected by lo->mutex */
156 struct lo_map ino_map
; /* protected by lo->mutex */
157 struct lo_map dirp_map
; /* protected by lo->mutex */
158 struct lo_map fd_map
; /* protected by lo->mutex */
160 /* An O_PATH file descriptor to /proc/self/fd/ */
164 static const struct fuse_opt lo_opts
[] = {
165 { "writeback", offsetof(struct lo_data
, writeback
), 1 },
166 { "no_writeback", offsetof(struct lo_data
, writeback
), 0 },
167 { "source=%s", offsetof(struct lo_data
, source
), 0 },
168 { "flock", offsetof(struct lo_data
, flock
), 1 },
169 { "no_flock", offsetof(struct lo_data
, flock
), 0 },
170 { "posix_lock", offsetof(struct lo_data
, posix_lock
), 1 },
171 { "no_posix_lock", offsetof(struct lo_data
, posix_lock
), 0 },
172 { "xattr", offsetof(struct lo_data
, xattr
), 1 },
173 { "no_xattr", offsetof(struct lo_data
, xattr
), 0 },
174 { "timeout=%lf", offsetof(struct lo_data
, timeout
), 0 },
175 { "timeout=", offsetof(struct lo_data
, timeout_set
), 1 },
176 { "cache=none", offsetof(struct lo_data
, cache
), CACHE_NONE
},
177 { "cache=auto", offsetof(struct lo_data
, cache
), CACHE_AUTO
},
178 { "cache=always", offsetof(struct lo_data
, cache
), CACHE_ALWAYS
},
179 { "norace", offsetof(struct lo_data
, norace
), 1 },
180 { "readdirplus", offsetof(struct lo_data
, readdirplus_set
), 1 },
181 { "no_readdirplus", offsetof(struct lo_data
, readdirplus_clear
), 1 },
184 static bool use_syslog
= false;
185 static int current_log_level
;
186 static void unref_inode_lolocked(struct lo_data
*lo
, struct lo_inode
*inode
,
190 pthread_mutex_t mutex
;
193 /* That we loaded cap-ng in the current thread from the saved */
194 static __thread
bool cap_loaded
= 0;
196 static struct lo_inode
*lo_find(struct lo_data
*lo
, struct stat
*st
);
198 static int is_dot_or_dotdot(const char *name
)
200 return name
[0] == '.' &&
201 (name
[1] == '\0' || (name
[1] == '.' && name
[2] == '\0'));
204 /* Is `path` a single path component that is not "." or ".."? */
205 static int is_safe_path_component(const char *path
)
207 if (strchr(path
, '/')) {
211 return !is_dot_or_dotdot(path
);
214 static struct lo_data
*lo_data(fuse_req_t req
)
216 return (struct lo_data
*)fuse_req_userdata(req
);
220 * Load capng's state from our saved state if the current thread
221 * hadn't previously been loaded.
222 * returns 0 on success
224 static int load_capng(void)
227 pthread_mutex_lock(&cap
.mutex
);
228 capng_restore_state(&cap
.saved
);
230 * restore_state free's the saved copy
233 cap
.saved
= capng_save_state();
235 pthread_mutex_unlock(&cap
.mutex
);
236 fuse_log(FUSE_LOG_ERR
, "capng_save_state (thread)\n");
239 pthread_mutex_unlock(&cap
.mutex
);
242 * We want to use the loaded state for our pid,
245 capng_setpid(syscall(SYS_gettid
));
252 * Helpers for dropping and regaining effective capabilities. Returns 0
253 * on success, error otherwise
255 static int drop_effective_cap(const char *cap_name
, bool *cap_dropped
)
259 cap
= capng_name_to_capability(cap_name
);
262 fuse_log(FUSE_LOG_ERR
, "capng_name_to_capability(%s) failed:%s\n",
263 cap_name
, strerror(errno
));
269 fuse_log(FUSE_LOG_ERR
, "load_capng() failed\n");
273 /* We dont have this capability in effective set already. */
274 if (!capng_have_capability(CAPNG_EFFECTIVE
, cap
)) {
279 if (capng_update(CAPNG_DROP
, CAPNG_EFFECTIVE
, cap
)) {
281 fuse_log(FUSE_LOG_ERR
, "capng_update(DROP,) failed\n");
285 if (capng_apply(CAPNG_SELECT_CAPS
)) {
287 fuse_log(FUSE_LOG_ERR
, "drop:capng_apply() failed\n");
300 static int gain_effective_cap(const char *cap_name
)
305 cap
= capng_name_to_capability(cap_name
);
308 fuse_log(FUSE_LOG_ERR
, "capng_name_to_capability(%s) failed:%s\n",
309 cap_name
, strerror(errno
));
315 fuse_log(FUSE_LOG_ERR
, "load_capng() failed\n");
319 if (capng_update(CAPNG_ADD
, CAPNG_EFFECTIVE
, cap
)) {
321 fuse_log(FUSE_LOG_ERR
, "capng_update(ADD,) failed\n");
325 if (capng_apply(CAPNG_SELECT_CAPS
)) {
327 fuse_log(FUSE_LOG_ERR
, "gain:capng_apply() failed\n");
336 static void lo_map_init(struct lo_map
*map
)
343 static void lo_map_destroy(struct lo_map
*map
)
348 static int lo_map_grow(struct lo_map
*map
, size_t new_nelems
)
350 struct lo_map_elem
*new_elems
;
353 if (new_nelems
<= map
->nelems
) {
357 new_elems
= realloc(map
->elems
, sizeof(map
->elems
[0]) * new_nelems
);
362 for (i
= map
->nelems
; i
< new_nelems
; i
++) {
363 new_elems
[i
].freelist
= i
+ 1;
364 new_elems
[i
].in_use
= false;
366 new_elems
[new_nelems
- 1].freelist
= -1;
368 map
->elems
= new_elems
;
369 map
->freelist
= map
->nelems
;
370 map
->nelems
= new_nelems
;
374 static struct lo_map_elem
*lo_map_alloc_elem(struct lo_map
*map
)
376 struct lo_map_elem
*elem
;
378 if (map
->freelist
== -1 && !lo_map_grow(map
, map
->nelems
+ 256)) {
382 elem
= &map
->elems
[map
->freelist
];
383 map
->freelist
= elem
->freelist
;
390 static struct lo_map_elem
*lo_map_reserve(struct lo_map
*map
, size_t key
)
394 if (!lo_map_grow(map
, key
+ 1)) {
398 for (prev
= &map
->freelist
; *prev
!= -1;
399 prev
= &map
->elems
[*prev
].freelist
) {
401 struct lo_map_elem
*elem
= &map
->elems
[key
];
403 *prev
= elem
->freelist
;
411 static struct lo_map_elem
*lo_map_get(struct lo_map
*map
, size_t key
)
413 if (key
>= map
->nelems
) {
416 if (!map
->elems
[key
].in_use
) {
419 return &map
->elems
[key
];
422 static void lo_map_remove(struct lo_map
*map
, size_t key
)
424 struct lo_map_elem
*elem
;
426 if (key
>= map
->nelems
) {
430 elem
= &map
->elems
[key
];
435 elem
->in_use
= false;
437 elem
->freelist
= map
->freelist
;
441 /* Assumes lo->mutex is held */
442 static ssize_t
lo_add_fd_mapping(fuse_req_t req
, int fd
)
444 struct lo_map_elem
*elem
;
446 elem
= lo_map_alloc_elem(&lo_data(req
)->fd_map
);
452 return elem
- lo_data(req
)->fd_map
.elems
;
455 /* Assumes lo->mutex is held */
456 static ssize_t
lo_add_dirp_mapping(fuse_req_t req
, struct lo_dirp
*dirp
)
458 struct lo_map_elem
*elem
;
460 elem
= lo_map_alloc_elem(&lo_data(req
)->dirp_map
);
466 return elem
- lo_data(req
)->dirp_map
.elems
;
469 /* Assumes lo->mutex is held */
470 static ssize_t
lo_add_inode_mapping(fuse_req_t req
, struct lo_inode
*inode
)
472 struct lo_map_elem
*elem
;
474 elem
= lo_map_alloc_elem(&lo_data(req
)->ino_map
);
480 return elem
- lo_data(req
)->ino_map
.elems
;
483 static void lo_inode_put(struct lo_data
*lo
, struct lo_inode
**inodep
)
485 struct lo_inode
*inode
= *inodep
;
493 if (g_atomic_int_dec_and_test(&inode
->refcount
)) {
499 /* Caller must release refcount using lo_inode_put() */
500 static struct lo_inode
*lo_inode(fuse_req_t req
, fuse_ino_t ino
)
502 struct lo_data
*lo
= lo_data(req
);
503 struct lo_map_elem
*elem
;
505 pthread_mutex_lock(&lo
->mutex
);
506 elem
= lo_map_get(&lo
->ino_map
, ino
);
508 g_atomic_int_inc(&elem
->inode
->refcount
);
510 pthread_mutex_unlock(&lo
->mutex
);
520 * TODO Remove this helper and force callers to hold an inode refcount until
521 * they are done with the fd. This will be done in a later patch to make
524 static int lo_fd(fuse_req_t req
, fuse_ino_t ino
)
526 struct lo_inode
*inode
= lo_inode(req
, ino
);
534 lo_inode_put(lo_data(req
), &inode
);
538 static void lo_init(void *userdata
, struct fuse_conn_info
*conn
)
540 struct lo_data
*lo
= (struct lo_data
*)userdata
;
542 if (conn
->capable
& FUSE_CAP_EXPORT_SUPPORT
) {
543 conn
->want
|= FUSE_CAP_EXPORT_SUPPORT
;
546 if (lo
->writeback
&& conn
->capable
& FUSE_CAP_WRITEBACK_CACHE
) {
547 fuse_log(FUSE_LOG_DEBUG
, "lo_init: activating writeback\n");
548 conn
->want
|= FUSE_CAP_WRITEBACK_CACHE
;
550 if (conn
->capable
& FUSE_CAP_FLOCK_LOCKS
) {
552 fuse_log(FUSE_LOG_DEBUG
, "lo_init: activating flock locks\n");
553 conn
->want
|= FUSE_CAP_FLOCK_LOCKS
;
555 fuse_log(FUSE_LOG_DEBUG
, "lo_init: disabling flock locks\n");
556 conn
->want
&= ~FUSE_CAP_FLOCK_LOCKS
;
560 if (conn
->capable
& FUSE_CAP_POSIX_LOCKS
) {
561 if (lo
->posix_lock
) {
562 fuse_log(FUSE_LOG_DEBUG
, "lo_init: activating posix locks\n");
563 conn
->want
|= FUSE_CAP_POSIX_LOCKS
;
565 fuse_log(FUSE_LOG_DEBUG
, "lo_init: disabling posix locks\n");
566 conn
->want
&= ~FUSE_CAP_POSIX_LOCKS
;
570 if ((lo
->cache
== CACHE_NONE
&& !lo
->readdirplus_set
) ||
571 lo
->readdirplus_clear
) {
572 fuse_log(FUSE_LOG_DEBUG
, "lo_init: disabling readdirplus\n");
573 conn
->want
&= ~FUSE_CAP_READDIRPLUS
;
577 static void lo_getattr(fuse_req_t req
, fuse_ino_t ino
,
578 struct fuse_file_info
*fi
)
582 struct lo_data
*lo
= lo_data(req
);
587 fstatat(lo_fd(req
, ino
), "", &buf
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
589 return (void)fuse_reply_err(req
, errno
);
592 fuse_reply_attr(req
, &buf
, lo
->timeout
);
596 * Increments parent->nlookup and caller must release refcount using
597 * lo_inode_put(&parent).
599 static int lo_parent_and_name(struct lo_data
*lo
, struct lo_inode
*inode
,
600 char path
[PATH_MAX
], struct lo_inode
**parent
)
610 sprintf(procname
, "%i", inode
->fd
);
612 res
= readlinkat(lo
->proc_self_fd
, procname
, path
, PATH_MAX
);
614 fuse_log(FUSE_LOG_WARNING
, "%s: readlink failed: %m\n", __func__
);
618 if (res
>= PATH_MAX
) {
619 fuse_log(FUSE_LOG_WARNING
, "%s: readlink overflowed\n", __func__
);
624 last
= strrchr(path
, '/');
626 /* Shouldn't happen */
629 "%s: INTERNAL ERROR: bad path read from proc\n", __func__
);
634 pthread_mutex_lock(&lo
->mutex
);
636 g_atomic_int_inc(&p
->refcount
);
637 pthread_mutex_unlock(&lo
->mutex
);
640 res
= fstatat(AT_FDCWD
, last
== path
? "/" : path
, &stat
, 0);
643 fuse_log(FUSE_LOG_WARNING
,
644 "%s: failed to stat parent: %m\n", __func__
);
648 p
= lo_find(lo
, &stat
);
651 fuse_log(FUSE_LOG_WARNING
,
652 "%s: failed to find parent\n", __func__
);
658 res
= fstatat(p
->fd
, last
, &stat
, AT_SYMLINK_NOFOLLOW
);
661 fuse_log(FUSE_LOG_WARNING
,
662 "%s: failed to stat last\n", __func__
);
666 if (stat
.st_dev
!= inode
->key
.dev
|| stat
.st_ino
!= inode
->key
.ino
) {
668 fuse_log(FUSE_LOG_WARNING
,
669 "%s: failed to match last\n", __func__
);
674 memmove(path
, last
, strlen(last
) + 1);
679 unref_inode_lolocked(lo
, p
, 1);
680 lo_inode_put(lo
, &p
);
691 static int utimensat_empty(struct lo_data
*lo
, struct lo_inode
*inode
,
692 const struct timespec
*tv
)
695 struct lo_inode
*parent
;
698 if (S_ISLNK(inode
->filetype
)) {
699 res
= utimensat(inode
->fd
, "", tv
, AT_EMPTY_PATH
);
700 if (res
== -1 && errno
== EINVAL
) {
701 /* Sorry, no race free way to set times on symlink. */
710 sprintf(path
, "%i", inode
->fd
);
712 return utimensat(lo
->proc_self_fd
, path
, tv
, 0);
715 res
= lo_parent_and_name(lo
, inode
, path
, &parent
);
717 res
= utimensat(parent
->fd
, path
, tv
, AT_SYMLINK_NOFOLLOW
);
718 unref_inode_lolocked(lo
, parent
, 1);
719 lo_inode_put(lo
, &parent
);
725 static int lo_fi_fd(fuse_req_t req
, struct fuse_file_info
*fi
)
727 struct lo_data
*lo
= lo_data(req
);
728 struct lo_map_elem
*elem
;
730 pthread_mutex_lock(&lo
->mutex
);
731 elem
= lo_map_get(&lo
->fd_map
, fi
->fh
);
732 pthread_mutex_unlock(&lo
->mutex
);
741 static void lo_setattr(fuse_req_t req
, fuse_ino_t ino
, struct stat
*attr
,
742 int valid
, struct fuse_file_info
*fi
)
746 struct lo_data
*lo
= lo_data(req
);
747 struct lo_inode
*inode
;
752 inode
= lo_inode(req
, ino
);
754 fuse_reply_err(req
, EBADF
);
760 /* If fi->fh is invalid we'll report EBADF later */
762 fd
= lo_fi_fd(req
, fi
);
765 if (valid
& FUSE_SET_ATTR_MODE
) {
767 res
= fchmod(fd
, attr
->st_mode
);
769 sprintf(procname
, "%i", ifd
);
770 res
= fchmodat(lo
->proc_self_fd
, procname
, attr
->st_mode
, 0);
776 if (valid
& (FUSE_SET_ATTR_UID
| FUSE_SET_ATTR_GID
)) {
777 uid_t uid
= (valid
& FUSE_SET_ATTR_UID
) ? attr
->st_uid
: (uid_t
)-1;
778 gid_t gid
= (valid
& FUSE_SET_ATTR_GID
) ? attr
->st_gid
: (gid_t
)-1;
780 res
= fchownat(ifd
, "", uid
, gid
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
785 if (valid
& FUSE_SET_ATTR_SIZE
) {
791 sprintf(procname
, "%i", ifd
);
792 truncfd
= openat(lo
->proc_self_fd
, procname
, O_RDWR
);
798 res
= ftruncate(truncfd
, attr
->st_size
);
808 if (valid
& (FUSE_SET_ATTR_ATIME
| FUSE_SET_ATTR_MTIME
)) {
809 struct timespec tv
[2];
813 tv
[0].tv_nsec
= UTIME_OMIT
;
814 tv
[1].tv_nsec
= UTIME_OMIT
;
816 if (valid
& FUSE_SET_ATTR_ATIME_NOW
) {
817 tv
[0].tv_nsec
= UTIME_NOW
;
818 } else if (valid
& FUSE_SET_ATTR_ATIME
) {
819 tv
[0] = attr
->st_atim
;
822 if (valid
& FUSE_SET_ATTR_MTIME_NOW
) {
823 tv
[1].tv_nsec
= UTIME_NOW
;
824 } else if (valid
& FUSE_SET_ATTR_MTIME
) {
825 tv
[1] = attr
->st_mtim
;
829 res
= futimens(fd
, tv
);
831 res
= utimensat_empty(lo
, inode
, tv
);
837 lo_inode_put(lo
, &inode
);
839 return lo_getattr(req
, ino
, fi
);
843 lo_inode_put(lo
, &inode
);
844 fuse_reply_err(req
, saverr
);
847 static struct lo_inode
*lo_find(struct lo_data
*lo
, struct stat
*st
)
850 struct lo_key key
= {
855 pthread_mutex_lock(&lo
->mutex
);
856 p
= g_hash_table_lookup(lo
->inodes
, &key
);
858 assert(p
->nlookup
> 0);
860 g_atomic_int_inc(&p
->refcount
);
862 pthread_mutex_unlock(&lo
->mutex
);
867 /* value_destroy_func for posix_locks GHashTable */
868 static void posix_locks_value_destroy(gpointer data
)
870 struct lo_inode_plock
*plock
= data
;
873 * We had used open() for locks and had only one fd. So
874 * closing this fd should release all OFD locks.
881 * Increments nlookup and caller must release refcount using
882 * lo_inode_put(&parent).
884 static int lo_do_lookup(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
885 struct fuse_entry_param
*e
)
890 struct lo_data
*lo
= lo_data(req
);
891 struct lo_inode
*inode
= NULL
;
892 struct lo_inode
*dir
= lo_inode(req
, parent
);
895 * name_to_handle_at() and open_by_handle_at() can reach here with fuse
896 * mount point in guest, but we don't have its inode info in the
903 memset(e
, 0, sizeof(*e
));
904 e
->attr_timeout
= lo
->timeout
;
905 e
->entry_timeout
= lo
->timeout
;
907 /* Do not allow escaping root directory */
908 if (dir
== &lo
->root
&& strcmp(name
, "..") == 0) {
912 newfd
= openat(dir
->fd
, name
, O_PATH
| O_NOFOLLOW
);
917 res
= fstatat(newfd
, "", &e
->attr
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
922 inode
= lo_find(lo
, &e
->attr
);
926 inode
= calloc(1, sizeof(struct lo_inode
));
931 /* cache only filetype */
932 inode
->filetype
= (e
->attr
.st_mode
& S_IFMT
);
935 * One for the caller and one for nlookup (released in
936 * unref_inode_lolocked())
938 g_atomic_int_set(&inode
->refcount
, 2);
942 inode
->key
.ino
= e
->attr
.st_ino
;
943 inode
->key
.dev
= e
->attr
.st_dev
;
944 pthread_mutex_init(&inode
->plock_mutex
, NULL
);
945 inode
->posix_locks
= g_hash_table_new_full(
946 g_direct_hash
, g_direct_equal
, NULL
, posix_locks_value_destroy
);
948 pthread_mutex_lock(&lo
->mutex
);
949 inode
->fuse_ino
= lo_add_inode_mapping(req
, inode
);
950 g_hash_table_insert(lo
->inodes
, &inode
->key
, inode
);
951 pthread_mutex_unlock(&lo
->mutex
);
953 e
->ino
= inode
->fuse_ino
;
954 lo_inode_put(lo
, &inode
);
955 lo_inode_put(lo
, &dir
);
957 fuse_log(FUSE_LOG_DEBUG
, " %lli/%s -> %lli\n", (unsigned long long)parent
,
958 name
, (unsigned long long)e
->ino
);
967 lo_inode_put(lo
, &inode
);
968 lo_inode_put(lo
, &dir
);
972 static void lo_lookup(fuse_req_t req
, fuse_ino_t parent
, const char *name
)
974 struct fuse_entry_param e
;
977 fuse_log(FUSE_LOG_DEBUG
, "lo_lookup(parent=%" PRIu64
", name=%s)\n", parent
,
981 * Don't use is_safe_path_component(), allow "." and ".." for NFS export
984 if (strchr(name
, '/')) {
985 fuse_reply_err(req
, EINVAL
);
989 err
= lo_do_lookup(req
, parent
, name
, &e
);
991 fuse_reply_err(req
, err
);
993 fuse_reply_entry(req
, &e
);
998 * On some archs, setres*id is limited to 2^16 but they
999 * provide setres*id32 variants that allow 2^32.
1000 * Others just let setres*id do 2^32 anyway.
1002 #ifdef SYS_setresgid32
1003 #define OURSYS_setresgid SYS_setresgid32
1005 #define OURSYS_setresgid SYS_setresgid
1008 #ifdef SYS_setresuid32
1009 #define OURSYS_setresuid SYS_setresuid32
1011 #define OURSYS_setresuid SYS_setresuid
1015 * Change to uid/gid of caller so that file is created with
1016 * ownership of caller.
1017 * TODO: What about selinux context?
1019 static int lo_change_cred(fuse_req_t req
, struct lo_cred
*old
)
1023 old
->euid
= geteuid();
1024 old
->egid
= getegid();
1026 res
= syscall(OURSYS_setresgid
, -1, fuse_req_ctx(req
)->gid
, -1);
1031 res
= syscall(OURSYS_setresuid
, -1, fuse_req_ctx(req
)->uid
, -1);
1033 int errno_save
= errno
;
1035 syscall(OURSYS_setresgid
, -1, old
->egid
, -1);
1042 /* Regain Privileges */
1043 static void lo_restore_cred(struct lo_cred
*old
)
1047 res
= syscall(OURSYS_setresuid
, -1, old
->euid
, -1);
1049 fuse_log(FUSE_LOG_ERR
, "seteuid(%u): %m\n", old
->euid
);
1053 res
= syscall(OURSYS_setresgid
, -1, old
->egid
, -1);
1055 fuse_log(FUSE_LOG_ERR
, "setegid(%u): %m\n", old
->egid
);
1060 static void lo_mknod_symlink(fuse_req_t req
, fuse_ino_t parent
,
1061 const char *name
, mode_t mode
, dev_t rdev
,
1066 struct lo_data
*lo
= lo_data(req
);
1067 struct lo_inode
*dir
;
1068 struct fuse_entry_param e
;
1069 struct lo_cred old
= {};
1071 if (!is_safe_path_component(name
)) {
1072 fuse_reply_err(req
, EINVAL
);
1076 dir
= lo_inode(req
, parent
);
1078 fuse_reply_err(req
, EBADF
);
1082 saverr
= lo_change_cred(req
, &old
);
1087 res
= mknod_wrapper(dir
->fd
, name
, link
, mode
, rdev
);
1091 lo_restore_cred(&old
);
1097 saverr
= lo_do_lookup(req
, parent
, name
, &e
);
1102 fuse_log(FUSE_LOG_DEBUG
, " %lli/%s -> %lli\n", (unsigned long long)parent
,
1103 name
, (unsigned long long)e
.ino
);
1105 fuse_reply_entry(req
, &e
);
1106 lo_inode_put(lo
, &dir
);
1110 lo_inode_put(lo
, &dir
);
1111 fuse_reply_err(req
, saverr
);
1114 static void lo_mknod(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
1115 mode_t mode
, dev_t rdev
)
1117 lo_mknod_symlink(req
, parent
, name
, mode
, rdev
, NULL
);
1120 static void lo_mkdir(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
1123 lo_mknod_symlink(req
, parent
, name
, S_IFDIR
| mode
, 0, NULL
);
1126 static void lo_symlink(fuse_req_t req
, const char *link
, fuse_ino_t parent
,
1129 lo_mknod_symlink(req
, parent
, name
, S_IFLNK
, 0, link
);
1132 static int linkat_empty_nofollow(struct lo_data
*lo
, struct lo_inode
*inode
,
1133 int dfd
, const char *name
)
1136 struct lo_inode
*parent
;
1137 char path
[PATH_MAX
];
1139 if (S_ISLNK(inode
->filetype
)) {
1140 res
= linkat(inode
->fd
, "", dfd
, name
, AT_EMPTY_PATH
);
1141 if (res
== -1 && (errno
== ENOENT
|| errno
== EINVAL
)) {
1142 /* Sorry, no race free way to hard-link a symlink. */
1152 sprintf(path
, "%i", inode
->fd
);
1154 return linkat(lo
->proc_self_fd
, path
, dfd
, name
, AT_SYMLINK_FOLLOW
);
1157 res
= lo_parent_and_name(lo
, inode
, path
, &parent
);
1159 res
= linkat(parent
->fd
, path
, dfd
, name
, 0);
1160 unref_inode_lolocked(lo
, parent
, 1);
1161 lo_inode_put(lo
, &parent
);
1167 static void lo_link(fuse_req_t req
, fuse_ino_t ino
, fuse_ino_t parent
,
1171 struct lo_data
*lo
= lo_data(req
);
1172 struct lo_inode
*parent_inode
;
1173 struct lo_inode
*inode
;
1174 struct fuse_entry_param e
;
1177 if (!is_safe_path_component(name
)) {
1178 fuse_reply_err(req
, EINVAL
);
1182 parent_inode
= lo_inode(req
, parent
);
1183 inode
= lo_inode(req
, ino
);
1184 if (!parent_inode
|| !inode
) {
1189 memset(&e
, 0, sizeof(struct fuse_entry_param
));
1190 e
.attr_timeout
= lo
->timeout
;
1191 e
.entry_timeout
= lo
->timeout
;
1193 res
= linkat_empty_nofollow(lo
, inode
, parent_inode
->fd
, name
);
1198 res
= fstatat(inode
->fd
, "", &e
.attr
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
1203 pthread_mutex_lock(&lo
->mutex
);
1205 pthread_mutex_unlock(&lo
->mutex
);
1206 e
.ino
= inode
->fuse_ino
;
1208 fuse_log(FUSE_LOG_DEBUG
, " %lli/%s -> %lli\n", (unsigned long long)parent
,
1209 name
, (unsigned long long)e
.ino
);
1211 fuse_reply_entry(req
, &e
);
1212 lo_inode_put(lo
, &parent_inode
);
1213 lo_inode_put(lo
, &inode
);
1218 lo_inode_put(lo
, &parent_inode
);
1219 lo_inode_put(lo
, &inode
);
1220 fuse_reply_err(req
, saverr
);
1223 /* Increments nlookup and caller must release refcount using lo_inode_put() */
1224 static struct lo_inode
*lookup_name(fuse_req_t req
, fuse_ino_t parent
,
1230 res
= fstatat(lo_fd(req
, parent
), name
, &attr
,
1231 AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
1236 return lo_find(lo_data(req
), &attr
);
1239 static void lo_rmdir(fuse_req_t req
, fuse_ino_t parent
, const char *name
)
1242 struct lo_inode
*inode
;
1243 struct lo_data
*lo
= lo_data(req
);
1245 if (!is_safe_path_component(name
)) {
1246 fuse_reply_err(req
, EINVAL
);
1250 inode
= lookup_name(req
, parent
, name
);
1252 fuse_reply_err(req
, EIO
);
1256 res
= unlinkat(lo_fd(req
, parent
), name
, AT_REMOVEDIR
);
1258 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1259 unref_inode_lolocked(lo
, inode
, 1);
1260 lo_inode_put(lo
, &inode
);
1263 static void lo_rename(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
1264 fuse_ino_t newparent
, const char *newname
,
1268 struct lo_inode
*parent_inode
;
1269 struct lo_inode
*newparent_inode
;
1270 struct lo_inode
*oldinode
= NULL
;
1271 struct lo_inode
*newinode
= NULL
;
1272 struct lo_data
*lo
= lo_data(req
);
1274 if (!is_safe_path_component(name
) || !is_safe_path_component(newname
)) {
1275 fuse_reply_err(req
, EINVAL
);
1279 parent_inode
= lo_inode(req
, parent
);
1280 newparent_inode
= lo_inode(req
, newparent
);
1281 if (!parent_inode
|| !newparent_inode
) {
1282 fuse_reply_err(req
, EBADF
);
1286 oldinode
= lookup_name(req
, parent
, name
);
1287 newinode
= lookup_name(req
, newparent
, newname
);
1290 fuse_reply_err(req
, EIO
);
1295 #ifndef SYS_renameat2
1296 fuse_reply_err(req
, EINVAL
);
1298 res
= syscall(SYS_renameat2
, parent_inode
->fd
, name
,
1299 newparent_inode
->fd
, newname
, flags
);
1300 if (res
== -1 && errno
== ENOSYS
) {
1301 fuse_reply_err(req
, EINVAL
);
1303 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1309 res
= renameat(parent_inode
->fd
, name
, newparent_inode
->fd
, newname
);
1311 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1313 unref_inode_lolocked(lo
, oldinode
, 1);
1314 unref_inode_lolocked(lo
, newinode
, 1);
1315 lo_inode_put(lo
, &oldinode
);
1316 lo_inode_put(lo
, &newinode
);
1317 lo_inode_put(lo
, &parent_inode
);
1318 lo_inode_put(lo
, &newparent_inode
);
1321 static void lo_unlink(fuse_req_t req
, fuse_ino_t parent
, const char *name
)
1324 struct lo_inode
*inode
;
1325 struct lo_data
*lo
= lo_data(req
);
1327 if (!is_safe_path_component(name
)) {
1328 fuse_reply_err(req
, EINVAL
);
1332 inode
= lookup_name(req
, parent
, name
);
1334 fuse_reply_err(req
, EIO
);
1338 res
= unlinkat(lo_fd(req
, parent
), name
, 0);
1340 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1341 unref_inode_lolocked(lo
, inode
, 1);
1342 lo_inode_put(lo
, &inode
);
1345 /* To be called with lo->mutex held */
1346 static void unref_inode(struct lo_data
*lo
, struct lo_inode
*inode
, uint64_t n
)
1352 assert(inode
->nlookup
>= n
);
1353 inode
->nlookup
-= n
;
1354 if (!inode
->nlookup
) {
1355 lo_map_remove(&lo
->ino_map
, inode
->fuse_ino
);
1356 g_hash_table_remove(lo
->inodes
, &inode
->key
);
1357 if (g_hash_table_size(inode
->posix_locks
)) {
1358 fuse_log(FUSE_LOG_WARNING
, "Hash table is not empty\n");
1360 g_hash_table_destroy(inode
->posix_locks
);
1361 pthread_mutex_destroy(&inode
->plock_mutex
);
1363 /* Drop our refcount from lo_do_lookup() */
1364 lo_inode_put(lo
, &inode
);
1368 static void unref_inode_lolocked(struct lo_data
*lo
, struct lo_inode
*inode
,
1375 pthread_mutex_lock(&lo
->mutex
);
1376 unref_inode(lo
, inode
, n
);
1377 pthread_mutex_unlock(&lo
->mutex
);
1380 static void lo_forget_one(fuse_req_t req
, fuse_ino_t ino
, uint64_t nlookup
)
1382 struct lo_data
*lo
= lo_data(req
);
1383 struct lo_inode
*inode
;
1385 inode
= lo_inode(req
, ino
);
1390 fuse_log(FUSE_LOG_DEBUG
, " forget %lli %lli -%lli\n",
1391 (unsigned long long)ino
, (unsigned long long)inode
->nlookup
,
1392 (unsigned long long)nlookup
);
1394 unref_inode_lolocked(lo
, inode
, nlookup
);
1395 lo_inode_put(lo
, &inode
);
1398 static void lo_forget(fuse_req_t req
, fuse_ino_t ino
, uint64_t nlookup
)
1400 lo_forget_one(req
, ino
, nlookup
);
1401 fuse_reply_none(req
);
1404 static void lo_forget_multi(fuse_req_t req
, size_t count
,
1405 struct fuse_forget_data
*forgets
)
1409 for (i
= 0; i
< count
; i
++) {
1410 lo_forget_one(req
, forgets
[i
].ino
, forgets
[i
].nlookup
);
1412 fuse_reply_none(req
);
1415 static void lo_readlink(fuse_req_t req
, fuse_ino_t ino
)
1417 char buf
[PATH_MAX
+ 1];
1420 res
= readlinkat(lo_fd(req
, ino
), "", buf
, sizeof(buf
));
1422 return (void)fuse_reply_err(req
, errno
);
1425 if (res
== sizeof(buf
)) {
1426 return (void)fuse_reply_err(req
, ENAMETOOLONG
);
1431 fuse_reply_readlink(req
, buf
);
1437 struct dirent
*entry
;
1441 static void lo_dirp_put(struct lo_dirp
**dp
)
1443 struct lo_dirp
*d
= *dp
;
1450 if (g_atomic_int_dec_and_test(&d
->refcount
)) {
1456 /* Call lo_dirp_put() on the return value when no longer needed */
1457 static struct lo_dirp
*lo_dirp(fuse_req_t req
, struct fuse_file_info
*fi
)
1459 struct lo_data
*lo
= lo_data(req
);
1460 struct lo_map_elem
*elem
;
1462 pthread_mutex_lock(&lo
->mutex
);
1463 elem
= lo_map_get(&lo
->dirp_map
, fi
->fh
);
1465 g_atomic_int_inc(&elem
->dirp
->refcount
);
1467 pthread_mutex_unlock(&lo
->mutex
);
1475 static void lo_opendir(fuse_req_t req
, fuse_ino_t ino
,
1476 struct fuse_file_info
*fi
)
1479 struct lo_data
*lo
= lo_data(req
);
1484 d
= calloc(1, sizeof(struct lo_dirp
));
1489 fd
= openat(lo_fd(req
, ino
), ".", O_RDONLY
);
1494 d
->dp
= fdopendir(fd
);
1495 if (d
->dp
== NULL
) {
1502 g_atomic_int_set(&d
->refcount
, 1); /* paired with lo_releasedir() */
1503 pthread_mutex_lock(&lo
->mutex
);
1504 fh
= lo_add_dirp_mapping(req
, d
);
1505 pthread_mutex_unlock(&lo
->mutex
);
1511 if (lo
->cache
== CACHE_ALWAYS
) {
1512 fi
->cache_readdir
= 1;
1514 fuse_reply_open(req
, fi
);
1523 } else if (fd
!= -1) {
1528 fuse_reply_err(req
, error
);
1531 static void lo_do_readdir(fuse_req_t req
, fuse_ino_t ino
, size_t size
,
1532 off_t offset
, struct fuse_file_info
*fi
, int plus
)
1534 struct lo_data
*lo
= lo_data(req
);
1535 struct lo_dirp
*d
= NULL
;
1536 struct lo_inode
*dinode
;
1542 dinode
= lo_inode(req
, ino
);
1547 d
= lo_dirp(req
, fi
);
1553 buf
= calloc(1, size
);
1559 if (offset
!= d
->offset
) {
1560 seekdir(d
->dp
, offset
);
1571 d
->entry
= readdir(d
->dp
);
1573 if (errno
) { /* Error */
1576 } else { /* End of stream */
1581 nextoff
= d
->entry
->d_off
;
1582 name
= d
->entry
->d_name
;
1584 fuse_ino_t entry_ino
= 0;
1585 struct fuse_entry_param e
= (struct fuse_entry_param
){
1586 .attr
.st_ino
= d
->entry
->d_ino
,
1587 .attr
.st_mode
= d
->entry
->d_type
<< 12,
1590 /* Hide root's parent directory */
1591 if (dinode
== &lo
->root
&& strcmp(name
, "..") == 0) {
1592 e
.attr
.st_ino
= lo
->root
.key
.ino
;
1593 e
.attr
.st_mode
= DT_DIR
<< 12;
1597 if (!is_dot_or_dotdot(name
)) {
1598 err
= lo_do_lookup(req
, ino
, name
, &e
);
1605 entsize
= fuse_add_direntry_plus(req
, p
, rem
, name
, &e
, nextoff
);
1607 entsize
= fuse_add_direntry(req
, p
, rem
, name
, &e
.attr
, nextoff
);
1609 if (entsize
> rem
) {
1610 if (entry_ino
!= 0) {
1611 lo_forget_one(req
, entry_ino
, 1);
1620 d
->offset
= nextoff
;
1626 lo_inode_put(lo
, &dinode
);
1629 * If there's an error, we can only signal it if we haven't stored
1630 * any entries yet - otherwise we'd end up with wrong lookup
1631 * counts for the entries that are already in the buffer. So we
1632 * return what we've collected until that point.
1634 if (err
&& rem
== size
) {
1635 fuse_reply_err(req
, err
);
1637 fuse_reply_buf(req
, buf
, size
- rem
);
1642 static void lo_readdir(fuse_req_t req
, fuse_ino_t ino
, size_t size
,
1643 off_t offset
, struct fuse_file_info
*fi
)
1645 lo_do_readdir(req
, ino
, size
, offset
, fi
, 0);
1648 static void lo_readdirplus(fuse_req_t req
, fuse_ino_t ino
, size_t size
,
1649 off_t offset
, struct fuse_file_info
*fi
)
1651 lo_do_readdir(req
, ino
, size
, offset
, fi
, 1);
1654 static void lo_releasedir(fuse_req_t req
, fuse_ino_t ino
,
1655 struct fuse_file_info
*fi
)
1657 struct lo_data
*lo
= lo_data(req
);
1658 struct lo_map_elem
*elem
;
1663 pthread_mutex_lock(&lo
->mutex
);
1664 elem
= lo_map_get(&lo
->dirp_map
, fi
->fh
);
1666 pthread_mutex_unlock(&lo
->mutex
);
1667 fuse_reply_err(req
, EBADF
);
1672 lo_map_remove(&lo
->dirp_map
, fi
->fh
);
1673 pthread_mutex_unlock(&lo
->mutex
);
1675 lo_dirp_put(&d
); /* paired with lo_opendir() */
1677 fuse_reply_err(req
, 0);
1680 static void update_open_flags(int writeback
, struct fuse_file_info
*fi
)
1683 * With writeback cache, kernel may send read requests even
1684 * when userspace opened write-only
1686 if (writeback
&& (fi
->flags
& O_ACCMODE
) == O_WRONLY
) {
1687 fi
->flags
&= ~O_ACCMODE
;
1688 fi
->flags
|= O_RDWR
;
1692 * With writeback cache, O_APPEND is handled by the kernel.
1693 * This breaks atomicity (since the file may change in the
1694 * underlying filesystem, so that the kernel's idea of the
1695 * end of the file isn't accurate anymore). In this example,
1696 * we just accept that. A more rigorous filesystem may want
1697 * to return an error here
1699 if (writeback
&& (fi
->flags
& O_APPEND
)) {
1700 fi
->flags
&= ~O_APPEND
;
1704 * O_DIRECT in guest should not necessarily mean bypassing page
1705 * cache on host as well. If somebody needs that behavior, it
1706 * probably should be a configuration knob in daemon.
1708 fi
->flags
&= ~O_DIRECT
;
1711 static void lo_create(fuse_req_t req
, fuse_ino_t parent
, const char *name
,
1712 mode_t mode
, struct fuse_file_info
*fi
)
1715 struct lo_data
*lo
= lo_data(req
);
1716 struct lo_inode
*parent_inode
;
1717 struct fuse_entry_param e
;
1719 struct lo_cred old
= {};
1721 fuse_log(FUSE_LOG_DEBUG
, "lo_create(parent=%" PRIu64
", name=%s)\n", parent
,
1724 if (!is_safe_path_component(name
)) {
1725 fuse_reply_err(req
, EINVAL
);
1729 parent_inode
= lo_inode(req
, parent
);
1730 if (!parent_inode
) {
1731 fuse_reply_err(req
, EBADF
);
1735 err
= lo_change_cred(req
, &old
);
1740 update_open_flags(lo
->writeback
, fi
);
1742 fd
= openat(parent_inode
->fd
, name
, (fi
->flags
| O_CREAT
) & ~O_NOFOLLOW
,
1744 err
= fd
== -1 ? errno
: 0;
1745 lo_restore_cred(&old
);
1750 pthread_mutex_lock(&lo
->mutex
);
1751 fh
= lo_add_fd_mapping(req
, fd
);
1752 pthread_mutex_unlock(&lo
->mutex
);
1760 err
= lo_do_lookup(req
, parent
, name
, &e
);
1762 if (lo
->cache
== CACHE_NONE
) {
1764 } else if (lo
->cache
== CACHE_ALWAYS
) {
1769 lo_inode_put(lo
, &parent_inode
);
1772 fuse_reply_err(req
, err
);
1774 fuse_reply_create(req
, &e
, fi
);
1778 /* Should be called with inode->plock_mutex held */
1779 static struct lo_inode_plock
*lookup_create_plock_ctx(struct lo_data
*lo
,
1780 struct lo_inode
*inode
,
1781 uint64_t lock_owner
,
1782 pid_t pid
, int *err
)
1784 struct lo_inode_plock
*plock
;
1789 g_hash_table_lookup(inode
->posix_locks
, GUINT_TO_POINTER(lock_owner
));
1795 plock
= malloc(sizeof(struct lo_inode_plock
));
1801 /* Open another instance of file which can be used for ofd locks. */
1802 sprintf(procname
, "%i", inode
->fd
);
1804 /* TODO: What if file is not writable? */
1805 fd
= openat(lo
->proc_self_fd
, procname
, O_RDWR
);
1812 plock
->lock_owner
= lock_owner
;
1814 g_hash_table_insert(inode
->posix_locks
, GUINT_TO_POINTER(plock
->lock_owner
),
1819 static void lo_getlk(fuse_req_t req
, fuse_ino_t ino
, struct fuse_file_info
*fi
,
1822 struct lo_data
*lo
= lo_data(req
);
1823 struct lo_inode
*inode
;
1824 struct lo_inode_plock
*plock
;
1825 int ret
, saverr
= 0;
1827 fuse_log(FUSE_LOG_DEBUG
,
1828 "lo_getlk(ino=%" PRIu64
", flags=%d)"
1829 " owner=0x%lx, l_type=%d l_start=0x%lx"
1831 ino
, fi
->flags
, fi
->lock_owner
, lock
->l_type
, lock
->l_start
,
1834 inode
= lo_inode(req
, ino
);
1836 fuse_reply_err(req
, EBADF
);
1840 pthread_mutex_lock(&inode
->plock_mutex
);
1842 lookup_create_plock_ctx(lo
, inode
, fi
->lock_owner
, lock
->l_pid
, &ret
);
1848 ret
= fcntl(plock
->fd
, F_OFD_GETLK
, lock
);
1854 pthread_mutex_unlock(&inode
->plock_mutex
);
1855 lo_inode_put(lo
, &inode
);
1858 fuse_reply_err(req
, saverr
);
1860 fuse_reply_lock(req
, lock
);
1864 static void lo_setlk(fuse_req_t req
, fuse_ino_t ino
, struct fuse_file_info
*fi
,
1865 struct flock
*lock
, int sleep
)
1867 struct lo_data
*lo
= lo_data(req
);
1868 struct lo_inode
*inode
;
1869 struct lo_inode_plock
*plock
;
1870 int ret
, saverr
= 0;
1872 fuse_log(FUSE_LOG_DEBUG
,
1873 "lo_setlk(ino=%" PRIu64
", flags=%d)"
1874 " cmd=%d pid=%d owner=0x%lx sleep=%d l_whence=%d"
1875 " l_start=0x%lx l_len=0x%lx\n",
1876 ino
, fi
->flags
, lock
->l_type
, lock
->l_pid
, fi
->lock_owner
, sleep
,
1877 lock
->l_whence
, lock
->l_start
, lock
->l_len
);
1880 fuse_reply_err(req
, EOPNOTSUPP
);
1884 inode
= lo_inode(req
, ino
);
1886 fuse_reply_err(req
, EBADF
);
1890 pthread_mutex_lock(&inode
->plock_mutex
);
1892 lookup_create_plock_ctx(lo
, inode
, fi
->lock_owner
, lock
->l_pid
, &ret
);
1899 /* TODO: Is it alright to modify flock? */
1901 ret
= fcntl(plock
->fd
, F_OFD_SETLK
, lock
);
1907 pthread_mutex_unlock(&inode
->plock_mutex
);
1908 lo_inode_put(lo
, &inode
);
1910 fuse_reply_err(req
, saverr
);
1913 static void lo_fsyncdir(fuse_req_t req
, fuse_ino_t ino
, int datasync
,
1914 struct fuse_file_info
*fi
)
1922 d
= lo_dirp(req
, fi
);
1924 fuse_reply_err(req
, EBADF
);
1930 res
= fdatasync(fd
);
1937 fuse_reply_err(req
, res
== -1 ? errno
: 0);
1940 static void lo_open(fuse_req_t req
, fuse_ino_t ino
, struct fuse_file_info
*fi
)
1945 struct lo_data
*lo
= lo_data(req
);
1947 fuse_log(FUSE_LOG_DEBUG
, "lo_open(ino=%" PRIu64
", flags=%d)\n", ino
,
1950 update_open_flags(lo
->writeback
, fi
);
1952 sprintf(buf
, "%i", lo_fd(req
, ino
));
1953 fd
= openat(lo
->proc_self_fd
, buf
, fi
->flags
& ~O_NOFOLLOW
);
1955 return (void)fuse_reply_err(req
, errno
);
1958 pthread_mutex_lock(&lo
->mutex
);
1959 fh
= lo_add_fd_mapping(req
, fd
);
1960 pthread_mutex_unlock(&lo
->mutex
);
1963 fuse_reply_err(req
, ENOMEM
);
1968 if (lo
->cache
== CACHE_NONE
) {
1970 } else if (lo
->cache
== CACHE_ALWAYS
) {
1973 fuse_reply_open(req
, fi
);
1976 static void lo_release(fuse_req_t req
, fuse_ino_t ino
,
1977 struct fuse_file_info
*fi
)
1979 struct lo_data
*lo
= lo_data(req
);
1980 struct lo_map_elem
*elem
;
1985 pthread_mutex_lock(&lo
->mutex
);
1986 elem
= lo_map_get(&lo
->fd_map
, fi
->fh
);
1990 lo_map_remove(&lo
->fd_map
, fi
->fh
);
1992 pthread_mutex_unlock(&lo
->mutex
);
1995 fuse_reply_err(req
, 0);
1998 static void lo_flush(fuse_req_t req
, fuse_ino_t ino
, struct fuse_file_info
*fi
)
2002 struct lo_inode
*inode
;
2004 inode
= lo_inode(req
, ino
);
2006 fuse_reply_err(req
, EBADF
);
2010 /* An fd is going away. Cleanup associated posix locks */
2011 pthread_mutex_lock(&inode
->plock_mutex
);
2012 g_hash_table_remove(inode
->posix_locks
, GUINT_TO_POINTER(fi
->lock_owner
));
2013 pthread_mutex_unlock(&inode
->plock_mutex
);
2015 res
= close(dup(lo_fi_fd(req
, fi
)));
2016 lo_inode_put(lo_data(req
), &inode
);
2017 fuse_reply_err(req
, res
== -1 ? errno
: 0);
2020 static void lo_fsync(fuse_req_t req
, fuse_ino_t ino
, int datasync
,
2021 struct fuse_file_info
*fi
)
2027 fuse_log(FUSE_LOG_DEBUG
, "lo_fsync(ino=%" PRIu64
", fi=0x%p)\n", ino
,
2031 struct lo_data
*lo
= lo_data(req
);
2033 res
= asprintf(&buf
, "%i", lo_fd(req
, ino
));
2035 return (void)fuse_reply_err(req
, errno
);
2038 fd
= openat(lo
->proc_self_fd
, buf
, O_RDWR
);
2041 return (void)fuse_reply_err(req
, errno
);
2044 fd
= lo_fi_fd(req
, fi
);
2048 res
= fdatasync(fd
);
2055 fuse_reply_err(req
, res
== -1 ? errno
: 0);
2058 static void lo_read(fuse_req_t req
, fuse_ino_t ino
, size_t size
, off_t offset
,
2059 struct fuse_file_info
*fi
)
2061 struct fuse_bufvec buf
= FUSE_BUFVEC_INIT(size
);
2063 fuse_log(FUSE_LOG_DEBUG
,
2064 "lo_read(ino=%" PRIu64
", size=%zd, "
2066 ino
, size
, (unsigned long)offset
);
2068 buf
.buf
[0].flags
= FUSE_BUF_IS_FD
| FUSE_BUF_FD_SEEK
;
2069 buf
.buf
[0].fd
= lo_fi_fd(req
, fi
);
2070 buf
.buf
[0].pos
= offset
;
2072 fuse_reply_data(req
, &buf
);
2075 static void lo_write_buf(fuse_req_t req
, fuse_ino_t ino
,
2076 struct fuse_bufvec
*in_buf
, off_t off
,
2077 struct fuse_file_info
*fi
)
2081 struct fuse_bufvec out_buf
= FUSE_BUFVEC_INIT(fuse_buf_size(in_buf
));
2082 bool cap_fsetid_dropped
= false;
2084 out_buf
.buf
[0].flags
= FUSE_BUF_IS_FD
| FUSE_BUF_FD_SEEK
;
2085 out_buf
.buf
[0].fd
= lo_fi_fd(req
, fi
);
2086 out_buf
.buf
[0].pos
= off
;
2088 fuse_log(FUSE_LOG_DEBUG
,
2089 "lo_write_buf(ino=%" PRIu64
", size=%zd, off=%lu)\n", ino
,
2090 out_buf
.buf
[0].size
, (unsigned long)off
);
2093 * If kill_priv is set, drop CAP_FSETID which should lead to kernel
2094 * clearing setuid/setgid on file.
2096 if (fi
->kill_priv
) {
2097 res
= drop_effective_cap("FSETID", &cap_fsetid_dropped
);
2099 fuse_reply_err(req
, res
);
2104 res
= fuse_buf_copy(&out_buf
, in_buf
);
2106 fuse_reply_err(req
, -res
);
2108 fuse_reply_write(req
, (size_t)res
);
2111 if (cap_fsetid_dropped
) {
2112 res
= gain_effective_cap("FSETID");
2114 fuse_log(FUSE_LOG_ERR
, "Failed to gain CAP_FSETID\n");
2119 static void lo_statfs(fuse_req_t req
, fuse_ino_t ino
)
2122 struct statvfs stbuf
;
2124 res
= fstatvfs(lo_fd(req
, ino
), &stbuf
);
2126 fuse_reply_err(req
, errno
);
2128 fuse_reply_statfs(req
, &stbuf
);
2132 static void lo_fallocate(fuse_req_t req
, fuse_ino_t ino
, int mode
, off_t offset
,
2133 off_t length
, struct fuse_file_info
*fi
)
2135 int err
= EOPNOTSUPP
;
2138 #ifdef CONFIG_FALLOCATE
2139 err
= fallocate(lo_fi_fd(req
, fi
), mode
, offset
, length
);
2144 #elif defined(CONFIG_POSIX_FALLOCATE)
2146 fuse_reply_err(req
, EOPNOTSUPP
);
2150 err
= posix_fallocate(lo_fi_fd(req
, fi
), offset
, length
);
2153 fuse_reply_err(req
, err
);
2156 static void lo_flock(fuse_req_t req
, fuse_ino_t ino
, struct fuse_file_info
*fi
,
2162 res
= flock(lo_fi_fd(req
, fi
), op
);
2164 fuse_reply_err(req
, res
== -1 ? errno
: 0);
2167 static void lo_getxattr(fuse_req_t req
, fuse_ino_t ino
, const char *name
,
2170 struct lo_data
*lo
= lo_data(req
);
2173 struct lo_inode
*inode
;
2178 inode
= lo_inode(req
, ino
);
2180 fuse_reply_err(req
, EBADF
);
2185 if (!lo_data(req
)->xattr
) {
2189 fuse_log(FUSE_LOG_DEBUG
, "lo_getxattr(ino=%" PRIu64
", name=%s size=%zd)\n",
2193 value
= malloc(size
);
2199 sprintf(procname
, "%i", inode
->fd
);
2201 * It is not safe to open() non-regular/non-dir files in file server
2202 * unless O_PATH is used, so use that method for regular files/dir
2203 * only (as it seems giving less performance overhead).
2204 * Otherwise, call fchdir() to avoid open().
2206 if (S_ISREG(inode
->filetype
) || S_ISDIR(inode
->filetype
)) {
2207 fd
= openat(lo
->proc_self_fd
, procname
, O_RDONLY
);
2211 ret
= fgetxattr(fd
, name
, value
, size
);
2213 /* fchdir should not fail here */
2214 assert(fchdir(lo
->proc_self_fd
) == 0);
2215 ret
= getxattr(procname
, name
, value
, size
);
2216 assert(fchdir(lo
->root
.fd
) == 0);
2227 fuse_reply_buf(req
, value
, ret
);
2229 fuse_reply_xattr(req
, ret
);
2238 lo_inode_put(lo
, &inode
);
2244 fuse_reply_err(req
, saverr
);
2248 static void lo_listxattr(fuse_req_t req
, fuse_ino_t ino
, size_t size
)
2250 struct lo_data
*lo
= lo_data(req
);
2253 struct lo_inode
*inode
;
2258 inode
= lo_inode(req
, ino
);
2260 fuse_reply_err(req
, EBADF
);
2265 if (!lo_data(req
)->xattr
) {
2269 fuse_log(FUSE_LOG_DEBUG
, "lo_listxattr(ino=%" PRIu64
", size=%zd)\n", ino
,
2273 value
= malloc(size
);
2279 sprintf(procname
, "%i", inode
->fd
);
2280 if (S_ISREG(inode
->filetype
) || S_ISDIR(inode
->filetype
)) {
2281 fd
= openat(lo
->proc_self_fd
, procname
, O_RDONLY
);
2285 ret
= flistxattr(fd
, value
, size
);
2287 /* fchdir should not fail here */
2288 assert(fchdir(lo
->proc_self_fd
) == 0);
2289 ret
= listxattr(procname
, value
, size
);
2290 assert(fchdir(lo
->root
.fd
) == 0);
2301 fuse_reply_buf(req
, value
, ret
);
2303 fuse_reply_xattr(req
, ret
);
2312 lo_inode_put(lo
, &inode
);
2318 fuse_reply_err(req
, saverr
);
2322 static void lo_setxattr(fuse_req_t req
, fuse_ino_t ino
, const char *name
,
2323 const char *value
, size_t size
, int flags
)
2326 struct lo_data
*lo
= lo_data(req
);
2327 struct lo_inode
*inode
;
2332 inode
= lo_inode(req
, ino
);
2334 fuse_reply_err(req
, EBADF
);
2339 if (!lo_data(req
)->xattr
) {
2343 fuse_log(FUSE_LOG_DEBUG
, "lo_setxattr(ino=%" PRIu64
2344 ", name=%s value=%s size=%zd)\n", ino
, name
, value
, size
);
2346 sprintf(procname
, "%i", inode
->fd
);
2347 if (S_ISREG(inode
->filetype
) || S_ISDIR(inode
->filetype
)) {
2348 fd
= openat(lo
->proc_self_fd
, procname
, O_RDONLY
);
2353 ret
= fsetxattr(fd
, name
, value
, size
, flags
);
2355 /* fchdir should not fail here */
2356 assert(fchdir(lo
->proc_self_fd
) == 0);
2357 ret
= setxattr(procname
, name
, value
, size
, flags
);
2358 assert(fchdir(lo
->root
.fd
) == 0);
2361 saverr
= ret
== -1 ? errno
: 0;
2368 lo_inode_put(lo
, &inode
);
2369 fuse_reply_err(req
, saverr
);
2372 static void lo_removexattr(fuse_req_t req
, fuse_ino_t ino
, const char *name
)
2375 struct lo_data
*lo
= lo_data(req
);
2376 struct lo_inode
*inode
;
2381 inode
= lo_inode(req
, ino
);
2383 fuse_reply_err(req
, EBADF
);
2388 if (!lo_data(req
)->xattr
) {
2392 fuse_log(FUSE_LOG_DEBUG
, "lo_removexattr(ino=%" PRIu64
", name=%s)\n", ino
,
2395 sprintf(procname
, "%i", inode
->fd
);
2396 if (S_ISREG(inode
->filetype
) || S_ISDIR(inode
->filetype
)) {
2397 fd
= openat(lo
->proc_self_fd
, procname
, O_RDONLY
);
2402 ret
= fremovexattr(fd
, name
);
2404 /* fchdir should not fail here */
2405 assert(fchdir(lo
->proc_self_fd
) == 0);
2406 ret
= removexattr(procname
, name
);
2407 assert(fchdir(lo
->root
.fd
) == 0);
2410 saverr
= ret
== -1 ? errno
: 0;
2417 lo_inode_put(lo
, &inode
);
2418 fuse_reply_err(req
, saverr
);
2421 #ifdef HAVE_COPY_FILE_RANGE
2422 static void lo_copy_file_range(fuse_req_t req
, fuse_ino_t ino_in
, off_t off_in
,
2423 struct fuse_file_info
*fi_in
, fuse_ino_t ino_out
,
2424 off_t off_out
, struct fuse_file_info
*fi_out
,
2425 size_t len
, int flags
)
2430 in_fd
= lo_fi_fd(req
, fi_in
);
2431 out_fd
= lo_fi_fd(req
, fi_out
);
2433 fuse_log(FUSE_LOG_DEBUG
,
2434 "lo_copy_file_range(ino=%" PRIu64
"/fd=%d, "
2435 "off=%lu, ino=%" PRIu64
"/fd=%d, "
2436 "off=%lu, size=%zd, flags=0x%x)\n",
2437 ino_in
, in_fd
, off_in
, ino_out
, out_fd
, off_out
, len
, flags
);
2439 res
= copy_file_range(in_fd
, &off_in
, out_fd
, &off_out
, len
, flags
);
2441 fuse_reply_err(req
, errno
);
2443 fuse_reply_write(req
, res
);
2448 static void lo_lseek(fuse_req_t req
, fuse_ino_t ino
, off_t off
, int whence
,
2449 struct fuse_file_info
*fi
)
2454 res
= lseek(lo_fi_fd(req
, fi
), off
, whence
);
2456 fuse_reply_lseek(req
, res
);
2458 fuse_reply_err(req
, errno
);
2462 static void lo_destroy(void *userdata
)
2464 struct lo_data
*lo
= (struct lo_data
*)userdata
;
2466 pthread_mutex_lock(&lo
->mutex
);
2468 GHashTableIter iter
;
2469 gpointer key
, value
;
2471 g_hash_table_iter_init(&iter
, lo
->inodes
);
2472 if (!g_hash_table_iter_next(&iter
, &key
, &value
)) {
2476 struct lo_inode
*inode
= value
;
2477 unref_inode(lo
, inode
, inode
->nlookup
);
2479 pthread_mutex_unlock(&lo
->mutex
);
2482 static struct fuse_lowlevel_ops lo_oper
= {
2484 .lookup
= lo_lookup
,
2487 .symlink
= lo_symlink
,
2489 .unlink
= lo_unlink
,
2491 .rename
= lo_rename
,
2492 .forget
= lo_forget
,
2493 .forget_multi
= lo_forget_multi
,
2494 .getattr
= lo_getattr
,
2495 .setattr
= lo_setattr
,
2496 .readlink
= lo_readlink
,
2497 .opendir
= lo_opendir
,
2498 .readdir
= lo_readdir
,
2499 .readdirplus
= lo_readdirplus
,
2500 .releasedir
= lo_releasedir
,
2501 .fsyncdir
= lo_fsyncdir
,
2502 .create
= lo_create
,
2506 .release
= lo_release
,
2510 .write_buf
= lo_write_buf
,
2511 .statfs
= lo_statfs
,
2512 .fallocate
= lo_fallocate
,
2514 .getxattr
= lo_getxattr
,
2515 .listxattr
= lo_listxattr
,
2516 .setxattr
= lo_setxattr
,
2517 .removexattr
= lo_removexattr
,
2518 #ifdef HAVE_COPY_FILE_RANGE
2519 .copy_file_range
= lo_copy_file_range
,
2522 .destroy
= lo_destroy
,
2525 /* Print vhost-user.json backend program capabilities */
2526 static void print_capabilities(void)
2529 printf(" \"type\": \"fs\"\n");
2534 * Drop all Linux capabilities because the wait parent process only needs to
2535 * sit in waitpid(2) and terminate.
2537 static void setup_wait_parent_capabilities(void)
2539 capng_setpid(syscall(SYS_gettid
));
2540 capng_clear(CAPNG_SELECT_BOTH
);
2541 capng_apply(CAPNG_SELECT_BOTH
);
2545 * Move to a new mount, net, and pid namespaces to isolate this process.
2547 static void setup_namespaces(struct lo_data
*lo
, struct fuse_session
*se
)
2550 char template[] = "virtiofsd-XXXXXX";
2554 * Create a new pid namespace for *child* processes. We'll have to
2555 * fork in order to enter the new pid namespace. A new mount namespace
2556 * is also needed so that we can remount /proc for the new pid
2559 * Our UNIX domain sockets have been created. Now we can move to
2560 * an empty network namespace to prevent TCP/IP and other network
2561 * activity in case this process is compromised.
2563 if (unshare(CLONE_NEWPID
| CLONE_NEWNS
| CLONE_NEWNET
) != 0) {
2564 fuse_log(FUSE_LOG_ERR
, "unshare(CLONE_NEWPID | CLONE_NEWNS): %m\n");
2570 fuse_log(FUSE_LOG_ERR
, "fork() failed: %m\n");
2577 setup_wait_parent_capabilities();
2579 /* The parent waits for the child */
2581 waited
= waitpid(child
, &wstatus
, 0);
2582 } while (waited
< 0 && errno
== EINTR
&& !se
->exited
);
2584 /* We were terminated by a signal, see fuse_signals.c */
2589 if (WIFEXITED(wstatus
)) {
2590 exit(WEXITSTATUS(wstatus
));
2596 /* Send us SIGTERM when the parent thread terminates, see prctl(2) */
2597 prctl(PR_SET_PDEATHSIG
, SIGTERM
);
2600 * If the mounts have shared propagation then we want to opt out so our
2601 * mount changes don't affect the parent mount namespace.
2603 if (mount(NULL
, "/", NULL
, MS_REC
| MS_SLAVE
, NULL
) < 0) {
2604 fuse_log(FUSE_LOG_ERR
, "mount(/, MS_REC|MS_SLAVE): %m\n");
2608 /* The child must remount /proc to use the new pid namespace */
2609 if (mount("proc", "/proc", "proc",
2610 MS_NODEV
| MS_NOEXEC
| MS_NOSUID
| MS_RELATIME
, NULL
) < 0) {
2611 fuse_log(FUSE_LOG_ERR
, "mount(/proc): %m\n");
2615 tmpdir
= mkdtemp(template);
2617 fuse_log(FUSE_LOG_ERR
, "tmpdir(%s): %m\n", template);
2621 if (mount("/proc/self/fd", tmpdir
, NULL
, MS_BIND
, NULL
) < 0) {
2622 fuse_log(FUSE_LOG_ERR
, "mount(/proc/self/fd, %s, MS_BIND): %m\n",
2627 /* Now we can get our /proc/self/fd directory file descriptor */
2628 lo
->proc_self_fd
= open(tmpdir
, O_PATH
);
2629 if (lo
->proc_self_fd
== -1) {
2630 fuse_log(FUSE_LOG_ERR
, "open(%s, O_PATH): %m\n", tmpdir
);
2634 if (umount2(tmpdir
, MNT_DETACH
) < 0) {
2635 fuse_log(FUSE_LOG_ERR
, "umount2(%s, MNT_DETACH): %m\n", tmpdir
);
2639 if (rmdir(tmpdir
) < 0) {
2640 fuse_log(FUSE_LOG_ERR
, "rmdir(%s): %m\n", tmpdir
);
2645 * Capture the capability state, we'll need to restore this for individual
2646 * threads later; see load_capng.
2648 static void setup_capng(void)
2650 /* Note this accesses /proc so has to happen before the sandbox */
2651 if (capng_get_caps_process()) {
2652 fuse_log(FUSE_LOG_ERR
, "capng_get_caps_process\n");
2655 pthread_mutex_init(&cap
.mutex
, NULL
);
2656 pthread_mutex_lock(&cap
.mutex
);
2657 cap
.saved
= capng_save_state();
2659 fuse_log(FUSE_LOG_ERR
, "capng_save_state\n");
2662 pthread_mutex_unlock(&cap
.mutex
);
2665 static void cleanup_capng(void)
2669 pthread_mutex_destroy(&cap
.mutex
);
2674 * Make the source directory our root so symlinks cannot escape and no other
2675 * files are accessible. Assumes unshare(CLONE_NEWNS) was already called.
2677 static void setup_mounts(const char *source
)
2682 if (mount(source
, source
, NULL
, MS_BIND
| MS_REC
, NULL
) < 0) {
2683 fuse_log(FUSE_LOG_ERR
, "mount(%s, %s, MS_BIND): %m\n", source
, source
);
2687 /* This magic is based on lxc's lxc_pivot_root() */
2688 oldroot
= open("/", O_DIRECTORY
| O_RDONLY
| O_CLOEXEC
);
2690 fuse_log(FUSE_LOG_ERR
, "open(/): %m\n");
2694 newroot
= open(source
, O_DIRECTORY
| O_RDONLY
| O_CLOEXEC
);
2696 fuse_log(FUSE_LOG_ERR
, "open(%s): %m\n", source
);
2700 if (fchdir(newroot
) < 0) {
2701 fuse_log(FUSE_LOG_ERR
, "fchdir(newroot): %m\n");
2705 if (syscall(__NR_pivot_root
, ".", ".") < 0) {
2706 fuse_log(FUSE_LOG_ERR
, "pivot_root(., .): %m\n");
2710 if (fchdir(oldroot
) < 0) {
2711 fuse_log(FUSE_LOG_ERR
, "fchdir(oldroot): %m\n");
2715 if (mount("", ".", "", MS_SLAVE
| MS_REC
, NULL
) < 0) {
2716 fuse_log(FUSE_LOG_ERR
, "mount(., MS_SLAVE | MS_REC): %m\n");
2720 if (umount2(".", MNT_DETACH
) < 0) {
2721 fuse_log(FUSE_LOG_ERR
, "umount2(., MNT_DETACH): %m\n");
2725 if (fchdir(newroot
) < 0) {
2726 fuse_log(FUSE_LOG_ERR
, "fchdir(newroot): %m\n");
2735 * Only keep whitelisted capabilities that are needed for file system operation
2737 static void setup_capabilities(void)
2739 pthread_mutex_lock(&cap
.mutex
);
2740 capng_restore_state(&cap
.saved
);
2743 * Whitelist file system-related capabilities that are needed for a file
2744 * server to act like root. Drop everything else like networking and
2745 * sysadmin capabilities.
2748 * 1. CAP_LINUX_IMMUTABLE is not included because it's only used via ioctl
2749 * and we don't support that.
2750 * 2. CAP_MAC_OVERRIDE is not included because it only seems to be
2751 * used by the Smack LSM. Omit it until there is demand for it.
2753 capng_setpid(syscall(SYS_gettid
));
2754 capng_clear(CAPNG_SELECT_BOTH
);
2755 capng_updatev(CAPNG_ADD
, CAPNG_PERMITTED
| CAPNG_EFFECTIVE
,
2758 CAP_DAC_READ_SEARCH
,
2765 capng_apply(CAPNG_SELECT_BOTH
);
2767 cap
.saved
= capng_save_state();
2768 pthread_mutex_unlock(&cap
.mutex
);
2772 * Lock down this process to prevent access to other processes or files outside
2773 * source directory. This reduces the impact of arbitrary code execution bugs.
2775 static void setup_sandbox(struct lo_data
*lo
, struct fuse_session
*se
,
2778 setup_namespaces(lo
, se
);
2779 setup_mounts(lo
->source
);
2780 setup_seccomp(enable_syslog
);
2781 setup_capabilities();
2784 /* Set the maximum number of open file descriptors */
2785 static void setup_nofile_rlimit(unsigned long rlimit_nofile
)
2787 struct rlimit rlim
= {
2788 .rlim_cur
= rlimit_nofile
,
2789 .rlim_max
= rlimit_nofile
,
2792 if (rlimit_nofile
== 0) {
2793 return; /* nothing to do */
2796 if (setrlimit(RLIMIT_NOFILE
, &rlim
) < 0) {
2797 /* Ignore SELinux denials */
2798 if (errno
== EPERM
) {
2802 fuse_log(FUSE_LOG_ERR
, "setrlimit(RLIMIT_NOFILE): %m\n");
2807 static void log_func(enum fuse_log_level level
, const char *fmt
, va_list ap
)
2809 g_autofree
char *localfmt
= NULL
;
2811 if (current_log_level
< level
) {
2815 if (current_log_level
== FUSE_LOG_DEBUG
) {
2817 localfmt
= g_strdup_printf("[%" PRId64
"] [ID: %08ld] %s",
2818 get_clock(), syscall(__NR_gettid
), fmt
);
2820 localfmt
= g_strdup_printf("[ID: %08ld] %s", syscall(__NR_gettid
),
2827 int priority
= LOG_ERR
;
2829 case FUSE_LOG_EMERG
:
2830 priority
= LOG_EMERG
;
2832 case FUSE_LOG_ALERT
:
2833 priority
= LOG_ALERT
;
2836 priority
= LOG_CRIT
;
2841 case FUSE_LOG_WARNING
:
2842 priority
= LOG_WARNING
;
2844 case FUSE_LOG_NOTICE
:
2845 priority
= LOG_NOTICE
;
2848 priority
= LOG_INFO
;
2850 case FUSE_LOG_DEBUG
:
2851 priority
= LOG_DEBUG
;
2854 vsyslog(priority
, fmt
, ap
);
2856 vfprintf(stderr
, fmt
, ap
);
2860 static void setup_root(struct lo_data
*lo
, struct lo_inode
*root
)
2865 fd
= open("/", O_PATH
);
2867 fuse_log(FUSE_LOG_ERR
, "open(%s, O_PATH): %m\n", lo
->source
);
2871 res
= fstatat(fd
, "", &stat
, AT_EMPTY_PATH
| AT_SYMLINK_NOFOLLOW
);
2873 fuse_log(FUSE_LOG_ERR
, "fstatat(%s): %m\n", lo
->source
);
2877 root
->filetype
= S_IFDIR
;
2879 root
->key
.ino
= stat
.st_ino
;
2880 root
->key
.dev
= stat
.st_dev
;
2882 g_atomic_int_set(&root
->refcount
, 2);
2885 static guint
lo_key_hash(gconstpointer key
)
2887 const struct lo_key
*lkey
= key
;
2889 return (guint
)lkey
->ino
+ (guint
)lkey
->dev
;
2892 static gboolean
lo_key_equal(gconstpointer a
, gconstpointer b
)
2894 const struct lo_key
*la
= a
;
2895 const struct lo_key
*lb
= b
;
2897 return la
->ino
== lb
->ino
&& la
->dev
== lb
->dev
;
2900 static void fuse_lo_data_cleanup(struct lo_data
*lo
)
2903 g_hash_table_destroy(lo
->inodes
);
2905 lo_map_destroy(&lo
->fd_map
);
2906 lo_map_destroy(&lo
->dirp_map
);
2907 lo_map_destroy(&lo
->ino_map
);
2909 if (lo
->proc_self_fd
>= 0) {
2910 close(lo
->proc_self_fd
);
2913 if (lo
->root
.fd
>= 0) {
2920 int main(int argc
, char *argv
[])
2922 struct fuse_args args
= FUSE_ARGS_INIT(argc
, argv
);
2923 struct fuse_session
*se
;
2924 struct fuse_cmdline_opts opts
;
2925 struct lo_data lo
= {
2931 struct lo_map_elem
*root_elem
;
2934 /* Don't mask creation mode, kernel already did that */
2937 pthread_mutex_init(&lo
.mutex
, NULL
);
2938 lo
.inodes
= g_hash_table_new(lo_key_hash
, lo_key_equal
);
2940 lo
.root
.fuse_ino
= FUSE_ROOT_ID
;
2941 lo
.cache
= CACHE_AUTO
;
2944 * Set up the ino map like this:
2945 * [0] Reserved (will not be used)
2948 lo_map_init(&lo
.ino_map
);
2949 lo_map_reserve(&lo
.ino_map
, 0)->in_use
= false;
2950 root_elem
= lo_map_reserve(&lo
.ino_map
, lo
.root
.fuse_ino
);
2951 root_elem
->inode
= &lo
.root
;
2953 lo_map_init(&lo
.dirp_map
);
2954 lo_map_init(&lo
.fd_map
);
2956 if (fuse_parse_cmdline(&args
, &opts
) != 0) {
2959 fuse_set_log_func(log_func
);
2960 use_syslog
= opts
.syslog
;
2962 openlog("virtiofsd", LOG_PID
, LOG_DAEMON
);
2965 if (opts
.show_help
) {
2966 printf("usage: %s [options]\n\n", argv
[0]);
2967 fuse_cmdline_help();
2968 printf(" -o source=PATH shared directory tree\n");
2969 fuse_lowlevel_help();
2972 } else if (opts
.show_version
) {
2973 fuse_lowlevel_version();
2976 } else if (opts
.print_capabilities
) {
2977 print_capabilities();
2982 if (fuse_opt_parse(&args
, &lo
, lo_opts
, NULL
) == -1) {
2987 * log_level is 0 if not configured via cmd options (0 is LOG_EMERG,
2988 * and we don't use this log level).
2990 if (opts
.log_level
!= 0) {
2991 current_log_level
= opts
.log_level
;
2993 lo
.debug
= opts
.debug
;
2995 current_log_level
= FUSE_LOG_DEBUG
;
3001 res
= lstat(lo
.source
, &stat
);
3003 fuse_log(FUSE_LOG_ERR
, "failed to stat source (\"%s\"): %m\n",
3007 if (!S_ISDIR(stat
.st_mode
)) {
3008 fuse_log(FUSE_LOG_ERR
, "source is not a directory\n");
3012 lo
.source
= strdup("/");
3014 if (!lo
.timeout_set
) {
3025 lo
.timeout
= 86400.0;
3028 } else if (lo
.timeout
< 0) {
3029 fuse_log(FUSE_LOG_ERR
, "timeout is negative (%lf)\n", lo
.timeout
);
3033 se
= fuse_session_new(&args
, &lo_oper
, sizeof(lo_oper
), &lo
);
3038 if (fuse_set_signal_handlers(se
) != 0) {
3042 if (fuse_session_mount(se
) != 0) {
3046 fuse_daemonize(opts
.foreground
);
3048 setup_nofile_rlimit(opts
.rlimit_nofile
);
3050 /* Must be before sandbox since it wants /proc */
3053 setup_sandbox(&lo
, se
, opts
.syslog
);
3055 setup_root(&lo
, &lo
.root
);
3056 /* Block until ctrl+c or fusermount -u */
3057 ret
= virtio_loop(se
);
3059 fuse_session_unmount(se
);
3062 fuse_remove_signal_handlers(se
);
3064 fuse_session_destroy(se
);
3066 fuse_opt_free_args(&args
);
3068 fuse_lo_data_cleanup(&lo
);