From 9f93ee041f814b683d3599aea69c5e92446e1fb6 Mon Sep 17 00:00:00 2001 From: Bernd Schubert Date: Thu, 18 Apr 2024 12:56:25 +0200 Subject: [PATCH] fuse_session_custom_io: Add a struct size field As in commit 73cd124d 'struct fuse_custom_io' might get extended and in order to stay ABI compatible libfuse has to zero all extended fields. In order to do so it has to know the size of the struct the application knows about. Signed-off-by: Bernd Schubert --- example/hello_ll_uds.c | 2 +- include/fuse_lowlevel.h | 9 +++++++-- lib/fuse_lowlevel.c | 20 +++++++++++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/example/hello_ll_uds.c b/example/hello_ll_uds.c index f291fed99..da8909175 100644 --- a/example/hello_ll_uds.c +++ b/example/hello_ll_uds.c @@ -341,7 +341,7 @@ int main(int argc, char *argv[]) if (cfd == -1) goto err_out3; - if (fuse_session_custom_io(se, &io, cfd) != 0) + if (fuse_session_custom_io(se, &io, sizeof(io), cfd) != 0) goto err_out3; /* Block until ctrl+c */ diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index 330d40e54..cc63f4446 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -2043,7 +2043,10 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, * @param se session object * @param io Custom io to use when retrieving/sending requests/responses * @param fd file descriptor for the session - * + * @param custom_io_size the size of the struct the callers knows about. + * The struct might be extended in higher libfuse versions and in order + * to stay ABI compatible extended fields are zeroed - libuse needs to know + * the size the caller knows about. * @return 0 on success * @return -EINVAL if `io`, `io->read` or `ìo->writev` are NULL * @return -EBADF if `fd` was smaller than 0 @@ -2051,7 +2054,9 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, * **/ int fuse_session_custom_io(struct fuse_session *se, - const struct fuse_custom_io *io, int fd); + const struct fuse_custom_io *io, + size_t custom_io_size, + int fd); /** * Mount a FUSE file system. diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 5129a3b21..d415c5702 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -3117,8 +3117,17 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, } int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io *io, - int fd) + size_t prog_custom_io_sz, int fd) { + size_t lib_custom_io_sz = sizeof(*se->io); + + if (prog_custom_io_sz > lib_custom_io_sz) { + fuse_log(FUSE_LOG_ERR, + "Provided 'fuse_custom_io_sz' (%zu) is larger than struct (%zu)\n", + prog_custom_io_sz, lib_custom_io_sz); + return -EINVAL; + } + if (fd < 0) { fuse_log(FUSE_LOG_ERR, "Invalid file descriptor value %d passed to " "fuse_session_custom_io()\n", fd); @@ -3138,7 +3147,7 @@ int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io return -EINVAL; } - se->io = malloc(sizeof(struct fuse_custom_io)); + se->io = calloc(1, lib_custom_io_sz); if (se->io == NULL) { fuse_log(FUSE_LOG_ERR, "Failed to allocate memory for custom io. " "Error: %s\n", strerror(errno)); @@ -3146,7 +3155,12 @@ int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io } se->fd = fd; - *se->io = *io; + + /* Above the struct was zeroed. For ABI compatibility we memcopy in + * what the caller knows about. + */ + memcpy(se->io, io, prog_custom_io_sz); + return 0; }