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; }