Discussion:
af_alg: Fix a resource leak
Bruno Haible
2018-05-06 13:34:38 UTC
Permalink
When the function returns -EINVAL, a socket is not closed.


2018-05-06 Bruno Haible <***@clisp.org>

af_alg: Fix a resource leak.
* lib/af_alg.c (afalg_stream): Close socket before returning -EINVAL.
New local variable 'result'.

diff --git a/lib/af_alg.c b/lib/af_alg.c
index 79e2195..0319459 100644
--- a/lib/af_alg.c
+++ b/lib/af_alg.c
@@ -43,6 +43,7 @@ afalg_stream (FILE *stream, const char *alg, void *resblock, ssize_t hashlen)
if (cfd < 0)
return -EAFNOSUPPORT;

+ int result;
struct sockaddr_alg salg = {
.salg_family = AF_ALG,
.salg_type = "hash",
@@ -50,19 +51,22 @@ afalg_stream (FILE *stream, const char *alg, void *resblock, ssize_t hashlen)
/* Avoid calling both strcpy and strlen. */
for (int i = 0; (salg.salg_name[i] = alg[i]); i++)
if (i == sizeof salg.salg_name - 1)
- return -EINVAL;
+ {
+ result = -EINVAL;
+ goto out_cfd;
+ }

int ret = bind (cfd, (struct sockaddr *) &salg, sizeof salg);
if (ret != 0)
{
- ret = -EAFNOSUPPORT;
+ result = -EAFNOSUPPORT;
goto out_cfd;
}

int ofd = accept (cfd, NULL, 0);
if (ofd < 0)
{
- ret = -EAFNOSUPPORT;
+ result = -EAFNOSUPPORT;
goto out_cfd;
}

@@ -80,9 +84,9 @@ afalg_stream (FILE *stream, const char *alg, void *resblock, ssize_t hashlen)
if (fflush (stream))
{
#if defined _WIN32 && ! defined __CYGWIN__
- ret = -EIO;
+ result = -EIO;
#else
- ret = -errno;
+ result = -errno;
#endif
goto out_cfd;
}
@@ -92,12 +96,12 @@ afalg_stream (FILE *stream, const char *alg, void *resblock, ssize_t hashlen)
See <https://patchwork.kernel.org/patch/9434741/>. */
if (nbytes <= 0)
{
- ret = -EAFNOSUPPORT;
+ result = -EAFNOSUPPORT;
goto out_ofd;
}
if (sendfile (ofd, fd, NULL, nbytes) != nbytes)
{
- ret = -EIO;
+ result = -EIO;
goto out_ofd;
}
}
@@ -112,34 +116,34 @@ afalg_stream (FILE *stream, const char *alg, void *resblock, ssize_t hashlen)
non_empty = 1;
if (send (ofd, buf, size, MSG_MORE) != size)
{
- ret = -EIO;
+ result = -EIO;
goto out_ofd;
}
}
if (ferror (stream))
{
- ret = -EIO;
+ result = -EIO;
goto out_ofd;
}
/* On Linux < 4.9, the value for an empty stream is wrong (all zeroes).
See <https://patchwork.kernel.org/patch/9434741/>. */
if (!non_empty)
{
- ret = -EAFNOSUPPORT;
+ result = -EAFNOSUPPORT;
goto out_ofd;
}
}

if (read (ofd, resblock, hashlen) != hashlen)
- ret = -EIO;
+ result = -EIO;
else
- ret = 0;
+ result = 0;

out_ofd:
close (ofd);
out_cfd:
close (cfd);
- return ret;
+ return result;
}

#endif

Loading...