]> git.baikalelectronics.ru Git - kernel.git/commit
ioctx_alloc(): fix vma (and file) leak on failure
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 6 Apr 2015 21:57:44 +0000 (17:57 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 6 Apr 2015 21:57:44 +0000 (17:57 -0400)
commitbe48a5712cde9ccefa0956f290bb7b23b7e8cf2e
tree49786da6f302e84cf94e2af32e06b159432d26bc
parentd651dd1fe1bd63378e63761632d342db890a24e2
ioctx_alloc(): fix vma (and file) leak on failure

If we fail past the aio_setup_ring(), we need to destroy the
mapping.  We don't need to care about anybody having found ctx,
or added requests to it, since the last failure exit is exactly
the failure to make ctx visible to lookups.

Reproducer (based on one by Joe Mario <jmario@redhat.com>):

void count(char *p)
{
char s[80];
printf("%s: ", p);
fflush(stdout);
sprintf(s, "/bin/cat /proc/%d/maps|/bin/fgrep -c '/[aio] (deleted)'", getpid());
system(s);
}

int main()
{
io_context_t *ctx;
int created, limit, i, destroyed;
FILE *f;

count("before");
if ((f = fopen("/proc/sys/fs/aio-max-nr", "r")) == NULL)
perror("opening aio-max-nr");
else if (fscanf(f, "%d", &limit) != 1)
fprintf(stderr, "can't parse aio-max-nr\n");
else if ((ctx = calloc(limit, sizeof(io_context_t))) == NULL)
perror("allocating aio_context_t array");
else {
for (i = 0, created = 0; i < limit; i++) {
if (io_setup(1000, ctx + created) == 0)
created++;
}
for (i = 0, destroyed = 0; i < created; i++)
if (io_destroy(ctx[i]) == 0)
destroyed++;
printf("created %d, failed %d, destroyed %d\n",
created, limit - created, destroyed);
count("after");
}
}

Found-by: Joe Mario <jmario@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/aio.c