From: Goffredo Baroncelli <kreijack@libero.it>
To: Jan Schmidt <list.btrfs@jan-o-sch.net>
Cc: linux-btrfs <linux-btrfs@vger.kernel.org>,
Hugo Mills <hugo@carfax.org.uk>
Subject: [btrfs-progs] [bug][patch] Leaking file handle in scrub_fs_info()
Date: Tue, 24 Apr 2012 20:43:23 +0200 [thread overview]
Message-ID: <4F96F44B.8000400@libero.it> (raw)
Hi Jan,
I was giving a look to the function scrub_fs_info( ), and to me it seems
that could be a potential file handle leaking problem.
In fact:
static int scrub_fs_info(int fd, char *path,
struct btrfs_ioctl_fs_info_args *fi_args,
struct btrfs_ioctl_dev_info_args **di_ret)
{
[...]
ret = ioctl(fd, BTRFS_IOC_FS_INFO, fi_args);
if (ret && errno == EINVAL) {
/* path is no mounted btrfs. try if it's a device */
[...]
close(fd); <--- Here the
file handle is
closed
fd = open_file_or_dir(mp); <--- then it is
re-opened
if (fd < 0)
return -errno;
} else if (ret) {
return -errno;
}
[...]
But in the rest of the function:
a) the file handle is not closed
b) the (new) file handle isn't returned
The function "scrub_fs_info()" is called from the functions
1) cmd_scrub_status(), which doesn't use the file handle after the call
to the cmd_scrub_status() [except for a close()]. So no problem at all.
2) scrub_start(), which uses the file handle after the call to the
cmd_scrub_status() functions.
My suggestions is to change scrub_fs_info() to accept only the path.
Then it open (and closes) its own (and private) the file descriptor.
Instead scrub_start(), opens a file descriptor after the call to the
scrub_fs_info() function.
What do you think ?
BR
G.Baroncelli
You can pull the patch below from
http://cassiopea.homelinux.net/git/btrfs-progs-unstable.git
branch
fd-leaking
-----
diff --git a/cmds-scrub.c b/cmds-scrub.c
index c4503f4..486768c 100644
--- a/cmds-scrub.c
+++ b/cmds-scrub.c
@@ -979,19 +979,26 @@ static int scrub_device_info(int fd, u64 devid,
return ret ? -errno : 0;
}
-static int scrub_fs_info(int fd, char *path,
+static int scrub_fs_info( char *path,
struct btrfs_ioctl_fs_info_args *fi_args,
struct btrfs_ioctl_dev_info_args **di_ret)
{
int ret = 0;
int ndevs = 0;
int i = 1;
+ int fd;
struct btrfs_fs_devices *fs_devices_mnt = NULL;
struct btrfs_ioctl_dev_info_args *di_args;
char mp[BTRFS_PATH_NAME_MAX + 1];
memset(fi_args, 0, sizeof(*fi_args));
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return -1;
+ }
+
ret = ioctl(fd, BTRFS_IOC_FS_INFO, fi_args);
if (ret && errno == EINVAL) {
/* path is no mounted btrfs. try if it's a device */
@@ -1010,28 +1017,36 @@ static int scrub_fs_info(int fd, char *path,
if (fd < 0)
return -errno;
} else if (ret) {
+ close(fd);
return -errno;
}
- if (!fi_args->num_devices)
+ if (!fi_args->num_devices){
+ close(fd);
return 0;
+ }
di_args = *di_ret = malloc(fi_args->num_devices * sizeof(*di_args));
- if (!di_args)
+ if (!di_args){
+ close(fd);
return -errno;
+ }
for (; i <= fi_args->max_id; ++i) {
BUG_ON(ndevs >= fi_args->num_devices);
ret = scrub_device_info(fd, i, &di_args[ndevs]);
if (ret == -ENODEV)
continue;
- if (ret)
+ if (ret){
+ close(fd);
return ret;
+ }
++ndevs;
}
BUG_ON(ndevs == 0);
+ close(fd);
return 0;
}
@@ -1155,7 +1170,7 @@ static int scrub_start(int argc, char **argv, int
resume)
return 12;
}
- ret = scrub_fs_info(fdmnt, path, &fi_args, &di_args);
+ ret = scrub_fs_info(path, &fi_args, &di_args);
if (ret) {
ERR(!do_quiet, "ERROR: getting dev info for scrub failed: "
"%s\n", strerror(-ret));
@@ -1586,7 +1601,6 @@ static int cmd_scrub_status(int argc, char **argv)
.sun_family = AF_UNIX,
};
int ret;
- int fdmnt;
int i;
int print_raw = 0;
int do_stats_per_dev = 0;
@@ -1615,13 +1629,7 @@ static int cmd_scrub_status(int argc, char **argv)
path = argv[optind];
- fdmnt = open_file_or_dir(path);
- if (fdmnt < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
-
- ret = scrub_fs_info(fdmnt, path, &fi_args, &di_args);
+ ret = scrub_fs_info(path, &fi_args, &di_args);
if (ret) {
fprintf(stderr, "ERROR: getting dev info for scrub failed: "
"%s\n", strerror(-ret));
@@ -1698,7 +1706,6 @@ static int cmd_scrub_status(int argc, char **argv)
out:
free_history(past_scrubs);
free(di_args);
- close(fdmnt);
if (fdres > -1)
close(fdres);
next reply other threads:[~2012-04-24 18:43 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-24 18:43 Goffredo Baroncelli [this message]
2012-04-25 9:39 ` [btrfs-progs] [bug][patch] Leaking file handle in scrub_fs_info() Jan Schmidt
2012-04-25 19:07 ` Goffredo Baroncelli
2012-06-05 11:01 ` Hugo Mills
2012-06-05 17:26 ` [btrfs-progs] [bug][patch V2] " Goffredo Baroncelli
2012-06-05 18:19 ` Hugo Mills
2012-06-05 20:12 ` Goffredo Baroncelli
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F96F44B.8000400@libero.it \
--to=kreijack@libero.it \
--cc=hugo@carfax.org.uk \
--cc=kreijack@inwind.it \
--cc=linux-btrfs@vger.kernel.org \
--cc=list.btrfs@jan-o-sch.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.