Many error paths in shiftfs_btrfs_ioctl_fd_replace() do not free memory
allocated near the top of the function. Fix up these error paths to free
the memory.
Additionally, the addresses for the allocated memory are assigned to
return parameters early in the function, before we know whether or not
the function as a whole will return success. Wait to assign these values
until we know the function was successful, and for good measure
initialize the return parameters to NULL at the start.
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
CVE-2021-3492
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Marcelo Cerri <marcelo.cerri@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
struct btrfs_ioctl_vol_args *v1 = NULL;
struct btrfs_ioctl_vol_args_v2 *v2 = NULL;
+ *b1 = NULL;
+ *b2 = NULL;
+
if (!is_btrfs_snap_ioctl(cmd))
return 0;
if (IS_ERR(v1))
return PTR_ERR(v1);
oldfd = v1->fd;
- *b1 = v1;
} else {
v2 = memdup_user(arg, sizeof(*v2));
if (IS_ERR(v2))
return PTR_ERR(v2);
oldfd = v2->fd;
- *b2 = v2;
}
src = fdget(oldfd);
- if (!src.file)
- return -EINVAL;
+ if (!src.file) {
+ ret = -EINVAL;
+ goto err_free;
+ }
ret = shiftfs_real_fdget(src.file, &lfd);
if (ret) {
fdput(src);
- return ret;
+ goto err_free;
}
/*
*newfd = get_unused_fd_flags(lfd.file->f_flags);
if (*newfd < 0) {
fdput(lfd);
- return *newfd;
+ ret = *newfd;
+ goto err_free;
}
fd_install(*newfd, lfd.file);
v2->fd = oldfd;
}
- if (ret)
+ if (!ret) {
+ *b1 = v1;
+ *b2 = v2;
+ } else {
shiftfs_btrfs_ioctl_fd_restore(cmd, *newfd, arg, v1, v2);
+ }
+
+ return ret;
+
+err_free:
+ kfree(v1);
+ kfree(v2);
return ret;
}