diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2021-10-26 07:38:41 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-10-26 07:38:41 -0700 |
commit | 931ce30859176f0f7daac6bac255dae5eb21284e (patch) | |
tree | a50f7407af869380f76876606ba80cb41d95a5ee | |
parent | c5b2f559814104f4145f8bc310f4d33c7ead8f49 (diff) | |
parent | 555a76e5e5dc2cd3c84c5e1bc060be17d5b32584 (diff) | |
download | qemu-931ce30859176f0f7daac6bac255dae5eb21284e.zip qemu-931ce30859176f0f7daac6bac255dae5eb21284e.tar.gz qemu-931ce30859176f0f7daac6bac255dae5eb21284e.tar.bz2 |
Merge remote-tracking branch 'remotes/dagrh/tags/pull-virtiofs-20211026' into staging
Virtiofsd pull 2021-10-26
New 'unsupported' feature for xattr mapping
Good for hiding selinux
Plus some tidy ups and error handling.
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
# gpg: Signature made Tue 26 Oct 2021 03:28:44 AM PDT
# gpg: using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full]
* remotes/dagrh/tags/pull-virtiofs-20211026:
virtiofsd: Error on bad socket group name
virtiofsd: Add a helper to stop all queues
virtiofsd: Add a helper to send element on virtqueue
virtiofsd: Remove unused virtio_fs_config definition
virtiofsd: xattr mapping add a new type "unsupported"
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | docs/tools/virtiofsd.rst | 6 | ||||
-rw-r--r-- | tools/virtiofsd/fuse_virtio.c | 80 | ||||
-rw-r--r-- | tools/virtiofsd/passthrough_ll.c | 17 |
3 files changed, 58 insertions, 45 deletions
diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst index b208f2a..cc31402 100644 --- a/docs/tools/virtiofsd.rst +++ b/docs/tools/virtiofsd.rst @@ -183,6 +183,12 @@ Using ':' as the separator a rule is of the form: 'ok' as either an explicit terminator or for special handling of certain patterns. +- 'unsupported' - If a client tries to use a name matching 'key' it's + denied using ENOTSUP; when the server passes an attribute + name matching 'prepend' it's hidden. In many ways it's use is very like + 'ok' as either an explicit terminator or for special handling of certain + patterns. + **key** is a string tested as a prefix on an attribute name originating on the client. It maybe empty in which case a 'client' rule will always match on client names. diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c index 8f4fd16..60b9647 100644 --- a/tools/virtiofsd/fuse_virtio.c +++ b/tools/virtiofsd/fuse_virtio.c @@ -82,12 +82,6 @@ struct fv_VuDev { struct fv_QueueInfo **qi; }; -/* From spec */ -struct virtio_fs_config { - char tag[36]; - uint32_t num_queues; -}; - /* Callback from libvhost-user */ static uint64_t fv_get_features(VuDev *dev) { @@ -249,6 +243,21 @@ static void vu_dispatch_unlock(struct fv_VuDev *vud) assert(ret == 0); } +static void vq_send_element(struct fv_QueueInfo *qi, VuVirtqElement *elem, + ssize_t len) +{ + struct fuse_session *se = qi->virtio_dev->se; + VuDev *dev = &se->virtio_dev->dev; + VuVirtq *q = vu_get_queue(dev, qi->qidx); + + vu_dispatch_rdlock(qi->virtio_dev); + pthread_mutex_lock(&qi->vq_lock); + vu_queue_push(dev, q, elem, len); + vu_queue_notify(dev, q); + pthread_mutex_unlock(&qi->vq_lock); + vu_dispatch_unlock(qi->virtio_dev); +} + /* * Called back by ll whenever it wants to send a reply/message back * The 1st element of the iov starts with the fuse_out_header @@ -259,8 +268,6 @@ int virtio_send_msg(struct fuse_session *se, struct fuse_chan *ch, { FVRequest *req = container_of(ch, FVRequest, ch); struct fv_QueueInfo *qi = ch->qi; - VuDev *dev = &se->virtio_dev->dev; - VuVirtq *q = vu_get_queue(dev, qi->qidx); VuVirtqElement *elem = &req->elem; int ret = 0; @@ -302,13 +309,7 @@ int virtio_send_msg(struct fuse_session *se, struct fuse_chan *ch, copy_iov(iov, count, in_sg, in_num, tosend_len); - vu_dispatch_rdlock(qi->virtio_dev); - pthread_mutex_lock(&qi->vq_lock); - vu_queue_push(dev, q, elem, tosend_len); - vu_queue_notify(dev, q); - pthread_mutex_unlock(&qi->vq_lock); - vu_dispatch_unlock(qi->virtio_dev); - + vq_send_element(qi, elem, tosend_len); req->reply_sent = true; err: @@ -327,8 +328,6 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, { FVRequest *req = container_of(ch, FVRequest, ch); struct fv_QueueInfo *qi = ch->qi; - VuDev *dev = &se->virtio_dev->dev; - VuVirtq *q = vu_get_queue(dev, qi->qidx); VuVirtqElement *elem = &req->elem; int ret = 0; g_autofree struct iovec *in_sg_cpy = NULL; @@ -436,12 +435,7 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, out_sg->len = tosend_len; } - vu_dispatch_rdlock(qi->virtio_dev); - pthread_mutex_lock(&qi->vq_lock); - vu_queue_push(dev, q, elem, tosend_len); - vu_queue_notify(dev, q); - pthread_mutex_unlock(&qi->vq_lock); - vu_dispatch_unlock(qi->virtio_dev); + vq_send_element(qi, elem, tosend_len); req->reply_sent = true; return 0; } @@ -453,7 +447,6 @@ static void fv_queue_worker(gpointer data, gpointer user_data) { struct fv_QueueInfo *qi = user_data; struct fuse_session *se = qi->virtio_dev->se; - struct VuDev *dev = &qi->virtio_dev->dev; FVRequest *req = data; VuVirtqElement *elem = &req->elem; struct fuse_buf fbuf = {}; @@ -595,17 +588,9 @@ out: /* If the request has no reply, still recycle the virtqueue element */ if (!req->reply_sent) { - struct VuVirtq *q = vu_get_queue(dev, qi->qidx); - fuse_log(FUSE_LOG_DEBUG, "%s: elem %d no reply sent\n", __func__, elem->index); - - vu_dispatch_rdlock(qi->virtio_dev); - pthread_mutex_lock(&qi->vq_lock); - vu_queue_push(dev, q, elem, 0); - vu_queue_notify(dev, q); - pthread_mutex_unlock(&qi->vq_lock); - vu_dispatch_unlock(qi->virtio_dev); + vq_send_element(qi, elem, 0); } pthread_mutex_destroy(&req->ch.lock); @@ -755,6 +740,18 @@ static void fv_queue_cleanup_thread(struct fv_VuDev *vud, int qidx) vud->qi[qidx] = NULL; } +static void stop_all_queues(struct fv_VuDev *vud) +{ + for (int i = 0; i < vud->nqueues; i++) { + if (!vud->qi[i]) { + continue; + } + + fuse_log(FUSE_LOG_INFO, "%s: Stopping queue %d thread\n", __func__, i); + fv_queue_cleanup_thread(vud, i); + } +} + /* Callback from libvhost-user on start or stop of a queue */ static void fv_queue_set_started(VuDev *dev, int qidx, bool started) { @@ -885,15 +882,7 @@ int virtio_loop(struct fuse_session *se) * Make sure all fv_queue_thread()s quit on exit, as we're about to * free virtio dev and fuse session, no one should access them anymore. */ - for (int i = 0; i < se->virtio_dev->nqueues; i++) { - if (!se->virtio_dev->qi[i]) { - continue; - } - - fuse_log(FUSE_LOG_INFO, "%s: Stopping queue %d thread\n", __func__, i); - fv_queue_cleanup_thread(se->virtio_dev, i); - } - + stop_all_queues(se->virtio_dev); fuse_log(FUSE_LOG_INFO, "%s: Exit\n", __func__); return 0; @@ -999,6 +988,13 @@ static int fv_create_listen_socket(struct fuse_session *se) "vhost socket failed to set group to %s (%d): %m\n", se->vu_socket_group, g->gr_gid); } + } else { + fuse_log(FUSE_LOG_ERR, + "vhost socket: unable to find group '%s'\n", + se->vu_socket_group); + close(listen_sock); + umask(old_umask); + return -1; } } umask(old_umask); diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 38b2af8..64b5b4f 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -2465,6 +2465,11 @@ static void lo_flock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, * Automatically reversed on read */ #define XATTR_MAP_FLAG_PREFIX (1 << 2) +/* + * The attribute is unsupported; + * ENOTSUP on write, hidden on read. + */ +#define XATTR_MAP_FLAG_UNSUPPORTED (1 << 3) /* scopes */ /* Apply rule to get/set/remove */ @@ -2636,6 +2641,8 @@ static void parse_xattrmap(struct lo_data *lo) tmp_entry.flags |= XATTR_MAP_FLAG_OK; } else if (strstart(map, "bad", &map)) { tmp_entry.flags |= XATTR_MAP_FLAG_BAD; + } else if (strstart(map, "unsupported", &map)) { + tmp_entry.flags |= XATTR_MAP_FLAG_UNSUPPORTED; } else if (strstart(map, "map", &map)) { /* * map is sugar that adds a number of rules, and must be @@ -2646,8 +2653,8 @@ static void parse_xattrmap(struct lo_data *lo) } else { fuse_log(FUSE_LOG_ERR, "%s: Unexpected type;" - "Expecting 'prefix', 'ok', 'bad' or 'map' in rule %zu\n", - __func__, lo->xattr_map_nentries); + "Expecting 'prefix', 'ok', 'bad', 'unsupported' or 'map'" + " in rule %zu\n", __func__, lo->xattr_map_nentries); exit(1); } @@ -2749,6 +2756,9 @@ static int xattr_map_client(const struct lo_data *lo, const char *client_name, if (cur_entry->flags & XATTR_MAP_FLAG_BAD) { return -EPERM; } + if (cur_entry->flags & XATTR_MAP_FLAG_UNSUPPORTED) { + return -ENOTSUP; + } if (cur_entry->flags & XATTR_MAP_FLAG_OK) { /* Unmodified name */ return 0; @@ -2788,7 +2798,8 @@ static int xattr_map_server(const struct lo_data *lo, const char *server_name, if ((cur_entry->flags & XATTR_MAP_FLAG_SERVER) && (strstart(server_name, cur_entry->prepend, &end))) { - if (cur_entry->flags & XATTR_MAP_FLAG_BAD) { + if (cur_entry->flags & XATTR_MAP_FLAG_BAD || + cur_entry->flags & XATTR_MAP_FLAG_UNSUPPORTED) { return -ENODATA; } if (cur_entry->flags & XATTR_MAP_FLAG_OK) { |