diff options
author | Bernd Schubert <bschubert@ddn.com> | 2025-04-07 11:50:19 +0200 |
---|---|---|
committer | Bernd Schubert <bernd@bsbernd.com> | 2025-04-07 15:32:04 +0200 |
commit | 12507408c311601b9e933645b10d8f801f32452c (patch) | |
tree | 160278ecc08fe14fec0ec3c87487bac64852d24f /lib/fuse_lowlevel.c | |
parent | ead0a13d57dcbc5ac7b5396722a61cc99cd0c9dc (diff) | |
download | libfuse-12507408c311601b9e933645b10d8f801f32452c.tar.gz |
fuse_lowlevel: Set bufsize if HAVE_SPLICE is not define and avoid race
These are several buf size fixes
1) Set bufsize when HAVE_SPLICE is not defined. Addresses
https://github.com/libfuse/libfuse/issues/1184
2) Check in the read retry condition for bufsize, i.e. the value
passed to read and not for the buf->mem_size. Using buf->mem_size
can be startup racy. Additionally we now also set bufsize on
allocation to avoid these races.
3) Allocation and value assigned needs to follow the pattern
bufsize = se->bufsize;
buf_alloc(bufsize, internal)
buf->mem_size = bufsize;
I.e. bufsize has to be retrieved first, as se->bufsize might
change at anytime - the value used for allocation and
must not differ from the value actually used.
This also tries to set large sizes in passthrough_hp, to catch
issues in xfstests - though requires to set
/proc/sys/fs/fuse/max_pages_limit
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
Diffstat (limited to 'lib/fuse_lowlevel.c')
-rw-r--r-- | lib/fuse_lowlevel.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index ff7a73b..cf8a7b0 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -3159,16 +3159,16 @@ pipe_retry: struct fuse_bufvec dst = { .count = 1 }; if (!buf->mem) { - buf->mem = buf_alloc(se->bufsize, internal); + buf->mem = buf_alloc(bufsize, internal); if (!buf->mem) { fuse_log( FUSE_LOG_ERR, "fuse: failed to allocate read buffer\n"); return -ENOMEM; } - buf->mem_size = se->bufsize; + buf->mem_size = bufsize; } - buf->size = se->bufsize; + buf->size = bufsize; buf->flags = 0; dst.buf[0] = *buf; @@ -3198,14 +3198,18 @@ pipe_retry: fallback: #endif + bufsize = internal ? buf->mem_size : se->bufsize; if (!buf->mem) { - buf->mem = buf_alloc(se->bufsize, internal); + bufsize = se->bufsize; /* might have changed */ + buf->mem = buf_alloc(bufsize, internal); if (!buf->mem) { fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate read buffer\n"); return -ENOMEM; } - buf->mem_size = se->bufsize; + + if (internal) + buf->mem_size = bufsize; } restart: @@ -3223,7 +3227,7 @@ restart: if (fuse_session_exited(se)) return 0; if (res == -1) { - if (err == EINVAL && internal && se->bufsize > buf->mem_size) { + if (err == EINVAL && internal && se->bufsize > bufsize) { /* FUSE_INIT might have increased the required bufsize */ bufsize = se->bufsize; void *newbuf = buf_alloc(bufsize, internal); |