diff mbox

[04/14] btrfs-progs: don't leak fd in get_fs_info

Message ID 1362436804-16766-5-git-send-email-sandeen@redhat.com (mailing list archive)
State Under Review, archived
Headers show

Commit Message

Eric Sandeen March 4, 2013, 10:39 p.m. UTC
If we discover that a passed-in fd is not a mountpoint,
we determine whether it is a device, and issue another
open() against the device's mount point if it is mounted.

If we do so, ensure this 2nd fd gets closed before we return
so that it does not leak, by consolidating error returns.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
 utils.c |   21 ++++++++++++++-------
 1 files changed, 14 insertions(+), 7 deletions(-)

Comments

Eric Sandeen March 5, 2013, 11:41 p.m. UTC | #1
On 3/4/13 4:39 PM, Eric Sandeen wrote:
> If we discover that a passed-in fd is not a mountpoint,
> we determine whether it is a device, and issue another
> open() against the device's mount point if it is mounted.
> 
> If we do so, ensure this 2nd fd gets closed before we return
> so that it does not leak, by consolidating error returns.
> 
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>

Gah, self-nak on this for now, I started trying to make a
regression test for scrub, and this makes it fail.

Don't know why yet.

-Eric

> ---
>  utils.c |   21 ++++++++++++++-------
>  1 files changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/utils.c b/utils.c
> index 1813dda..54d577c 100644
> --- a/utils.c
> +++ b/utils.c
> @@ -1462,6 +1462,7 @@ int get_fs_info(int fd, char *path, struct btrfs_ioctl_fs_info_args *fi_args,
>  		struct btrfs_ioctl_dev_info_args **di_ret)
>  {
>  	int ret = 0;
> +	int fd2 = -1;
>  	int ndevs = 0;
>  	int i = 1;
>  	struct btrfs_fs_devices *fs_devices_mnt = NULL;
> @@ -1484,19 +1485,22 @@ int get_fs_info(int fd, char *path, struct btrfs_ioctl_fs_info_args *fi_args,
>  		i = fs_devices_mnt->latest_devid;
>  		memcpy(fi_args->fsid, fs_devices_mnt->fsid, BTRFS_FSID_SIZE);
>  		close(fd);
> -		fd = open_file_or_dir(mp);
> -		if (fd < 0)
> +		fd2 = open_file_or_dir(mp);
> +		if (fd2 < 0)
>  			return -errno;
> +		fd = fd2;
>  	} else if (ret) {
>  		return -errno;
>  	}
>  
>  	if (!fi_args->num_devices)
> -		return 0;
> +		goto out;
>  
>  	di_args = *di_ret = malloc(fi_args->num_devices * sizeof(*di_args));
> -	if (!di_args)
> -		return -errno;
> +	if (!di_args) {
> +		ret = -errno;
> +		goto out;
> +	}
>  
>  	for (; i <= fi_args->max_id; ++i) {
>  		BUG_ON(ndevs >= fi_args->num_devices);
> @@ -1504,13 +1508,16 @@ int get_fs_info(int fd, char *path, struct btrfs_ioctl_fs_info_args *fi_args,
>  		if (ret == -ENODEV)
>  			continue;
>  		if (ret)
> -			return ret;
> +			goto out;
>  		ndevs++;
>  	}
>  
>  	BUG_ON(ndevs == 0);
>  
> -	return 0;
> +out:
> +	if (fd2 != -1)
> +		close(fd2);
> +	return ret;
>  }
>  
>  #define isoctal(c)	(((c) & ~7) == '0')
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric Sandeen March 8, 2013, 3:27 p.m. UTC | #2
On 3/5/13 5:41 PM, Eric Sandeen wrote:
> On 3/4/13 4:39 PM, Eric Sandeen wrote:
>> If we discover that a passed-in fd is not a mountpoint,
>> we determine whether it is a device, and issue another
>> open() against the device's mount point if it is mounted.
>>
>> If we do so, ensure this 2nd fd gets closed before we return
>> so that it does not leak, by consolidating error returns.
>>
>> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
> 
> Gah, self-nak on this for now, I started trying to make a
> regression test for scrub, and this makes it fail.
> 
> Don't know why yet.
> 
> -Eric

For posterity, it's because this function is actually
doing kind of a nasty thing - it closes the caller's
filehandle & re-opens it on a different path.

Usually the caller is none the wiser, but ick!  So permanent
NAK on this patch, I'm working on a different solution.

-Eric
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/utils.c b/utils.c
index 1813dda..54d577c 100644
--- a/utils.c
+++ b/utils.c
@@ -1462,6 +1462,7 @@  int get_fs_info(int fd, char *path, struct btrfs_ioctl_fs_info_args *fi_args,
 		struct btrfs_ioctl_dev_info_args **di_ret)
 {
 	int ret = 0;
+	int fd2 = -1;
 	int ndevs = 0;
 	int i = 1;
 	struct btrfs_fs_devices *fs_devices_mnt = NULL;
@@ -1484,19 +1485,22 @@  int get_fs_info(int fd, char *path, struct btrfs_ioctl_fs_info_args *fi_args,
 		i = fs_devices_mnt->latest_devid;
 		memcpy(fi_args->fsid, fs_devices_mnt->fsid, BTRFS_FSID_SIZE);
 		close(fd);
-		fd = open_file_or_dir(mp);
-		if (fd < 0)
+		fd2 = open_file_or_dir(mp);
+		if (fd2 < 0)
 			return -errno;
+		fd = fd2;
 	} else if (ret) {
 		return -errno;
 	}
 
 	if (!fi_args->num_devices)
-		return 0;
+		goto out;
 
 	di_args = *di_ret = malloc(fi_args->num_devices * sizeof(*di_args));
-	if (!di_args)
-		return -errno;
+	if (!di_args) {
+		ret = -errno;
+		goto out;
+	}
 
 	for (; i <= fi_args->max_id; ++i) {
 		BUG_ON(ndevs >= fi_args->num_devices);
@@ -1504,13 +1508,16 @@  int get_fs_info(int fd, char *path, struct btrfs_ioctl_fs_info_args *fi_args,
 		if (ret == -ENODEV)
 			continue;
 		if (ret)
-			return ret;
+			goto out;
 		ndevs++;
 	}
 
 	BUG_ON(ndevs == 0);
 
-	return 0;
+out:
+	if (fd2 != -1)
+		close(fd2);
+	return ret;
 }
 
 #define isoctal(c)	(((c) & ~7) == '0')