Canonicalize Btrfs and Bcachefs snapshot paths with realpath in fssnapshot_inode
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-arm32 (push) Waiting to run
Build / build-win (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run

This commit is contained in:
Andrea Mazzoleni 2026-08-25 23:27:31 +02:00
parent 1748e4c06f
commit 9d376b1d66
2 changed files with 16 additions and 5 deletions

View file

@ -76,7 +76,7 @@ struct fssnapshot_struct {
/**
* Root directory of the volume/dataset mountpoint.
* It ALWAYS terminates with /
* - Btrfs/Bcachefs: subvolume root
* - Btrfs/Bcachefs: subvolume root (canonical path via realpath)
* - ZFS: dataset mountpoint (canonical path via realpath)
* - Windows: volume mountpoint (via GetVolumePathName)
*/
@ -97,8 +97,8 @@ struct fssnapshot_struct {
* It NEVER starts with '/'.
* It is empty if the configured data directory is exactly root_dir.
* If non-empty, it ALWAYS terminates with '/'.
* - ZFS: relative suffix computed from realpath() canonical representation
* - Btrfs/Bcachefs/Windows: relative suffix computed from configured path
* - Unix: relative suffix computed from the realpath() canonical representation
* - Windows: relative suffix computed from the configured path
*/
char sub_dir[PATH_MAX];

View file

@ -2144,9 +2144,14 @@ int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_har
#if HAVE_LINUX_DEVICE
static int fssnapshot_inode(const char* path, uint32_t magic, uint64_t root_inode, struct fssnapshot_struct* fss)
{
char resolved[PATH_MAX];
char current_path[PATH_MAX];
pathcpy(current_path, sizeof(current_path), path);
if (realpath(path, resolved) == 0)
return -1;
pathslash(resolved, sizeof(resolved));
pathcpy(current_path, sizeof(current_path), resolved);
/* walk up the directory tree to find the subvolume root (Inode 256) */
while (1) {
@ -2172,7 +2177,13 @@ static int fssnapshot_inode(const char* path, uint32_t magic, uint64_t root_inod
}
size_t root_len = strlen(fss->root_dir);
pathcpy(fss->sub_dir, sizeof(fss->sub_dir), path + root_len);
if (pathncmp(fss->root_dir, resolved, root_len) != 0) {
errno = EINVAL;
return -1;
}
pathcpy(fss->sub_dir, sizeof(fss->sub_dir), resolved + root_len);
fss->magic = magic;
return 0;