libfuse: small safety and portability fixes across opt/cpu/fusermount/maintenance_thread

- fuse_opt: reformat process_opt_param to project style; return the
  rv from sscanf through a named local so the error branch prints
  the failing option cleanly.

- cpu.cpp: when parsing /sys/devices/system/cpu/*/topology/core_id,
  bail out cleanly on stream read failure rather than recording an
  uninitialized core_id.

- fusermount: free(copy) on the success path of parsing the mount
  option (previously leaked on every mount), and replace the fixed-
  buffer sprintf into procfile with snprintf bounded by the buffer
  size.

- maintenance_thread: widen the iteration count from int to u64
  so a long-lived daemon doesn't wrap after ~68 years of ticks
  (real effect: silence signed-overflow warnings under UBSan).
This commit is contained in:
Antonio S. Musumeci 2026-04-18 01:00:51 -04:00
parent a5043d801a
commit 861d52ceb3
4 changed files with 37 additions and 12 deletions

View file

@ -136,6 +136,12 @@ CPU::cpu2core()
ifs >> core_id;
if(!ifs)
{
ifs.close();
continue;
}
c2c[i] = core_id;
ifs.close();
@ -169,6 +175,12 @@ CPU::core2cpus()
ifs >> core_id;
if(!ifs)
{
ifs.close();
continue;
}
c2c[core_id].insert(i);
ifs.close();

View file

@ -214,23 +214,35 @@ int fuse_opt_match(const struct fuse_opt *opts, const char *opt)
return find_opt(opts, opt, &dummy) ? 1 : 0;
}
static int process_opt_param(void *var, const char *format, const char *param,
const char *arg)
static
int
process_opt_param(void *var,
const char *format,
const char *param,
const char *arg)
{
assert(format[0] == '%');
if (format[1] == 's')
if(format[1] == 's')
{
char *copy = strdup(param);
if (!copy)
if(!copy)
return alloc_failed();
*static_cast<char**>(var) = copy;
} else {
if (sscanf(param, format, static_cast<int*>(var)) != 1) {
fprintf(stderr, "fuse: invalid parameter in option `%s'\n", arg);
return -1;
}
}
else
{
int rv;
rv = sscanf(param, format, static_cast<int*>(var));
if(rv != 1)
{
fprintf(stderr,"mergerfs: invalid parameter in option `%s'\n",arg);
return -1;
}
}
return 0;
}

View file

@ -16,7 +16,7 @@ static
void*
_thread_loop(void *)
{
int count;
u64 count;
pthread_setname_np(pthread_self(),"fuse.maint");

View file

@ -445,6 +445,7 @@ static int unmount_fuse_locked(const char *mnt, int quiet, int lazy)
}
out:
free(copy);
if (res == -1)
return -1;
@ -688,7 +689,7 @@ static int get_mnt_opts(int flags, char *opts, char **mnt_optsp)
if (add_option(mnt_optsp, "user=", strlen(user)) == -1)
return -1;
strcat(*mnt_optsp, user);
strcat(*mnt_optsp,user);
}
return 0;
}
@ -992,7 +993,7 @@ static int check_perm(const char **mntp, struct stat *stbuf, int *mountpoint_fd)
return -1;
}
sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd);
snprintf(procfile,sizeof(procfile),"/proc/self/fd/%i",*mountpoint_fd);
*mntp = procfile;
} else {
fprintf(stderr,