Add missing strdup() return value checks
PATCH 1/1 Add missing strdup() return value checks
As reported by Bill Parker in trac #600, strdup() return values are not always correctly checked for failed allocations. This patch adds missing checks.
Note that in misc.c and options.c, the check is after the dirname() or basename() call, because these can deal with NULL params and we need to keep MSVC happy with its ancient no-declaration-after-statement policy.
--- src/openvpn/cryptoapi.c | 1 + src/openvpn/init.c | 1 + src/openvpn/misc.c | 1 + src/openvpn/options.c | 1 + src/openvpn/ssl_polarssl.c | 1 + 5 files changed, 5 insertions(+)
src/openvpn/cryptoapi.c +1 -0
@@ -127,6 +127,7 @@ static char *ms_error_text(DWORD ms_err)break ; } } +check_malloc_return (rv);return rv; }
src/openvpn/init.c +1 -0
@@ -817,6 +817,7 @@ init_options_dev (struct options *options) {if (!options->dev && options->dev_node) {char *dev_node =strdup (options->dev_node);/* POSIX basename() implementaions may modify its arguments */ +check_malloc_return (dev_node); options->dev =basename (dev_node); } }
src/openvpn/misc.c +1 -0
@@ -1608,6 +1608,7 @@ argv_extract_cmd_name (const char *path) {char *path_cp =strdup (path);/* POSIX basename() implementaions may modify its arguments */ const char *bn =basename (path_cp); +check_malloc_return (path_cp);if (bn) {char *ret =string_alloc (bn,NULL );
src/openvpn/options.c +1 -0
@@ -2588,6 +2588,7 @@ check_file_access(const int type, const char *file, const int mode, const char * {char *fullpath =strdup (file);/* POSIX dirname() implementaion may modify its arguments */ char *dirpath =dirname (fullpath); +check_malloc_return (fullpath);if (platform_access (dirpath, mode|X_OK ) !=0 ) errcode = errno;
src/openvpn/ssl_polarssl.c +1 -0
@@ -198,6 +198,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)/* Parse allowed ciphers, getting IDs */ i =0 ; tmp_ciphers_orig = tmp_ciphers =strdup (ciphers); +check_malloc_return (tmp_ciphers); token =strtok (tmp_ciphers,":" );while (token)
Signature · 1 line
2.1.4
Am 26.08.15 um 00:29 schrieb Steffan Karger:
Quoted 9 lines
As reported by Bill Parker in trac #600,
strdup()return values are not always correctly checked for failed allocations. This patch adds missing checks.Note that in
misc.candoptions.c, the check is after thedirname()orbasename()call, because these can deal with NULL params and we need to keep MSVC happy with its ancient no-declaration-after-statement policy.
ACK from me.
Arne
Hi,
Quoted 7 lines · Steffan Karger
As reported by Bill Parker in trac #600,
strdup()return values are not always correctly checked for failed allocations. This patch adds missing checks.Note that in
misc.candoptions.c, the check is after thedirname()orbasename()call, because these can deal with NULL params and we need to keep MSVC happy with its ancient no-declaration-after-statement policy.
Even though Arne has already ACKed it, I'm not merging it - I started merging it today, but the more I stare at the code, the more I'm convinced that we should just get rid of strdup() instead and/or the code is not needed.
Why...? Let me comment...
src/openvpn/cryptoapi.c static char *ms_error_text(DWORD ms_err) · line 132
Quoted 11 lines
src/openvpn/cryptoapi.c +1
-0@@ -127,6 +127,7 @@ static char *ms_error_text(DWORD ms_err)break ; } } +check_malloc_return (rv);return rv; }
This is not needed, as the code does
rv = strdup(lpMsgBuf);
LocalFree(lpMsgBuf);
/* trim to the left */
if (rv)
for (p = rv + strlen(rv) - 1; p >= rv; p--) {
if (isspace(*p))
*p = '\0';
else
break;
}
}
return rv;... so if the strdup() fails, the function falls into "return NULL", which is the same return value as for "if (!lpMsgBuf)", so I assume the caller expects this - with the extra check, a failure in FormatMessage() would be flagged as memory allocation failure (because rv is set to NULL at start), which it isn't.
So, just not needed.
src/openvpn/init.c init_options_dev (struct options *options) · line 823
Quoted 12 lines
src/openvpn/init.c +1
-0@@ -817,6 +817,7 @@ init_options_dev (struct options *options) {if (!options->dev && options->dev_node) {char *dev_node =strdup (options->dev_node);/* POSIX basename() implementaions may modify its arguments */ +check_malloc_return (dev_node); options->dev =basename (dev_node); } }
I'd need to look into this in more detail, but I think we never modify options->dev_node afterward - so a simple strrchr() to find the "/" and point options->dev there might be sufficient... but if it actually needs to be a true copy, we should just use
char *dev_node = string_alloc(options->dev_node, NULL)
instead - string_alloc() is OpenVPN's strdup(), and "NULL" tells it "do not use gc, use calloc" (side note: someone seriously overengineered the "we really want clean memory!" bit here - allocating <n> bytes and immediately overwriting with a n-byte memcpy() should be good enough, no?) - *and* string_alloc() actually does...
if (gc) {
...
} else {
ret = calloc(1, n);
check_malloc_return(ret);
}
memcpy (ret, str, n);... so the check_malloc_return() is built-in.
src/openvpn/misc.c argv_extract_cmd_name (const char *path) · line 1614
Quoted 12 lines
src/openvpn/misc.c +1
-0@@ -1608,6 +1608,7 @@ argv_extract_cmd_name (const char *path) {char *path_cp =strdup (path);/* POSIX basename() implementaions may modify its arguments */ const char *bn =basename (path_cp); +check_malloc_return (path_cp);if (bn) {char *ret =string_alloc (bn,NULL );
This is totally weird code, using strdup() first, and then string_alloc() later, inside an "if (bn)" check on a variable that will never be NULL anyway, since basename(NULL) is documented to return "." - and it very much looks like two different persons wrote this part :-)
Dunno, this really smells like refactor the function to use strrchr() on the original path, and then use string_alloc($ptr, NULL) to make a copy of that... throw out the if(bn) block, and be done... or just change the strdup() to string_alloc() as well.
src/openvpn/options.c check_file_access(const int type, const char *file, const int mode, const char * · line 2594
Quoted 12 lines
src/openvpn/options.c +1
-0@@ -2588,6 +2588,7 @@ check_file_access(const int type, const char *file, const int mode, const char * {char *fullpath =strdup (file);/* POSIX dirname() implementaion may modify its arguments */ char *dirpath =dirname (fullpath); +check_malloc_return (fullpath);if (platform_access (dirpath, mode|X_OK ) !=0 ) errcode = errno;
string_alloc() (pity we do not have a gc around here :-) )
src/openvpn/ssl_polarssl.c tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) · line 204
Quoted 12 lines
src/openvpn/ssl_polarssl.c +1
-0@@ -198,6 +198,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)/* Parse allowed ciphers, getting IDs */ i =0 ; tmp_ciphers_orig = tmp_ciphers =strdup (ciphers); +check_malloc_return (tmp_ciphers); token =strtok (tmp_ciphers,":" );while (token)
I could mention string_alloc() again, but I'm sure interested readers already recognize the pattern :-))
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Quoted 27 lines · Gert Doering
src/openvpn/cryptoapi.c static char *ms_error_text(DWORD ms_err) · line 132
Quoted 11 lines
src/openvpn/cryptoapi.c +1
-0@@ -127,6 +127,7 @@ static char *ms_error_text(DWORD ms_err)break ; } } +check_malloc_return (rv);return rv; }This is not needed, as the code does
rv = strdup(lpMsgBuf); LocalFree(lpMsgBuf); /* trim to the left */ if (rv) for (p = rv + strlen(rv) - 1; p >= rv; p--) { if (isspace(*p)) *p = '\0'; else break; } } return rv;
Quoted 7 lines
... so if the
strdup()fails, the function falls into "return NULL", which is the same return value as for "if (!lpMsgBuf)", so I assume the caller expects this - with the extra check, a failure inFormatMessage()would be flagged as memory allocation failure (because rv is set to NULL at start), which it isn't.So, just not needed.
This is what I thought at first too. But when I tried to verify that returning NULL could do no harm, I simply couldn't. The NULL is passed as a 'char *' to openssl, which stores it in some kind of error string storage. I could not trivially see that this can not do harm when actual error occur, so I decided to fix that as part of the patch.
Quoted 34 lines
src/openvpn/init.c init_options_dev (struct options *options) · line 823
Quoted 12 lines
src/openvpn/init.c +1
-0@@ -817,6 +817,7 @@ init_options_dev (struct options *options) {if (!options->dev && options->dev_node) {char *dev_node =strdup (options->dev_node);/* POSIX basename() implementaions may modify its arguments */ +check_malloc_return (dev_node); options->dev =basename (dev_node); } }I'd need to look into this in more detail, but I think we never modify
options->dev_nodeafterward - so a simplestrrchr()to find the "/" and pointoptions->devthere might be sufficient... but if it actually needs to be a true copy, we should just usechar *dev_node = string_alloc(options->dev_node, NULL)instead -
string_alloc()is OpenVPN'sstrdup(), and "NULL" tells it "do not use gc, use calloc" (side note: someone seriously overengineered the "we really want clean memory!" bit here - allocating <n> bytes and immediately overwriting with a n-bytememcpy()should be good enough, no?) - *and*string_alloc()actually does...if (gc) { ... } else { ret = calloc(1, n); check_malloc_return(ret); } memcpy (ret, str, n);
Quoted 1 line
... so the
check_malloc_return()is built-in.
You are absolutely right, I forgot about string_alloc(). I updated the patch to use string_alloc() instead.
So, attached two patches.
0001 replaces strdup() calls with string_alloc() to automatically check the return values.
0002 adds a return value check for the result of ms_error_text()
I ran our test suite on linux and did some smoke tests on Windows, but since this is cornercase-code, it is hard to really test.
-Steffan
From b748ddef2a779a7fa6999cb4c7bba3acf2c38f6f Mon Sep 17 00:00:00 2001
From: Steffan Karger <[email protected]...>
Date: Mon, 21 Sep 2015 22:04:19 +0200
Subject: [PATCH 2/2] Check return value of ms_error_text()
ms_error_text() may return NULL, and it is unclear (or, at least undocumented) whether the OpenSSL ERR code (and our code using the ERR code) can deal with esd->string being NULL. So, just to be sure, check that ms_error_text() succeeded before passing the result to ERR_load_strings().
--- src/openvpn/cryptoapi.c | 1 + 1 file changed, 1 insertion(+)
src/openvpn/cryptoapi.c +1 -0
@@ -164,6 +164,7 @@ static void err_put_ms_error(DWORD ms_err, int func, const char *file, int line) err_map[i].ms_err = ms_err; err_map[i].err = esd->error = i +100 ; esd->string =ms_error_text (ms_err); +check_malloc_return (esd->string);ERR_load_strings (ERR_LIB_CRYPTOAPI , esd);ERR_PUT_error (ERR_LIB_CRYPTOAPI , func, err_map[i].err, file, line);break ;
Signature · 1 line
2.1.4
From 00a71fa221f2265ad525d1b490a8fbfd009c9f23 Mon Sep 17 00:00:00 2001
From: Steffan Karger <[email protected]...>
Date: Mon, 21 Sep 2015 20:48:33 +0200
Subject: [PATCH 1/2] Replace strdup() calls for string_alloc() calls
As reported by Bill Parker in trac #600, strdup() return values are not always correctly checked for failed allocations. This patch adds missing checks by using string_alloc(), which performs the required checks.
--- src/openvpn/buffer.h | 2 +- src/openvpn/cryptoapi.c | 4 +++- src/openvpn/init.c | 2 +- src/openvpn/misc.c | 2 +- src/openvpn/options.c | 2 +- src/openvpn/ssl_polarssl.c | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-)
src/openvpn/buffer.h +1 -1
@@ -898,7 +898,7 @@ gc_reset (struct gc_arena *a) }static inline void -check_malloc_return (void *p) +check_malloc_return (const void *p) {if (!p)out_of_memory ();
src/openvpn/cryptoapi.c +3 -1
@@ -46,6 +46,8 @@#include <ctype.h> #include <assert.h> +#include "buffer.h" +/* MinGW w32api 3.17 is still incomplete when it comes to CryptoAPI while * MinGW32-w64 defines all macros used. This is a hack around that problem. */
@@ -116,7 +118,7 @@ static char *ms_error_text(DWORD ms_err) (LPTSTR) &lpMsgBuf, 0, NULL);if (lpMsgBuf) {char *p; - rv =strdup (lpMsgBuf); + rv =string_alloc (lpMsgBuf,NULL );LocalFree (lpMsgBuf);/* trim to the left */ if (rv)
src/openvpn/init.c +1 -1
@@ -822,7 +822,7 @@ void init_options_dev (struct options *options) {if (!options->dev && options->dev_node) { -char *dev_node =strdup (options->dev_node);/* POSIX basename() implementaions may modify its arguments */ +char *dev_node =string_alloc (options->dev_node,NULL );/* POSIX basename() implementaions may modify its arguments */ options->dev =basename (dev_node); } }
src/openvpn/misc.c +1 -1
@@ -1615,7 +1615,7 @@ argv_extract_cmd_name (const char *path) {if (path) { -char *path_cp =strdup (path);/* POSIX basename() implementaions may modify its arguments */ +char *path_cp =string_alloc (path,NULL );/* POSIX basename() implementaions may modify its arguments */ const char *bn =basename (path_cp);if (bn) {
src/openvpn/options.c +1 -1
@@ -2578,7 +2578,7 @@ check_file_access(const int type, const char *file, const int mode, const char */* Is the directory path leading to the given file accessible? */ if (type &CHKACC_DIRPATH ) { -char *fullpath =strdup (file);/* POSIX dirname() implementaion may modify its arguments */ +char *fullpath =string_alloc (file,NULL );/* POSIX dirname() implementaion may modify its arguments */ char *dirpath =dirname (fullpath);if (platform_access (dirpath, mode|X_OK ) !=0 )
src/openvpn/ssl_polarssl.c +1 -1
@@ -197,7 +197,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)/* Parse allowed ciphers, getting IDs */ i =0 ; - tmp_ciphers_orig = tmp_ciphers =strdup (ciphers); + tmp_ciphers_orig = tmp_ciphers =string_alloc (ciphers,NULL ); token =strtok (tmp_ciphers,":" );while (token)
Signature · 1 line
2.1.4
[Openvpn-devel] [PATCH applied] Re: Replace strdup() calls for string_alloc() calls
ACK.
Your patches have been applied to the master and release/2.3 branch.
commit ddc7692d245017c71adc40ad5cc195617e39fce0 (master) commit 6d4920e9d36675ff515da17c1eb301d22d07b489 (release/2.3)
Author: Steffan Karger Date: Mon Sep 21 20:48:33 2015 +0200
Replace strdup() calls for string_alloc() calls
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Gert Doering <[email protected]...>
Message-Id: <[email protected]...>
URL: http://article.gmane.org/gmane.network.openvpn.devel/10176
Signed-off-by: Gert Doering <[email protected]...>commit 5584b738a332d0abc740d9303c275764c2ca13f1 (master) commit ad71fe5f79ffbd4c86afa79d4559b08617b41dfb (release/2.3)
Author: Steffan Karger Date: Mon Sep 21 22:04:19 2015 +0200
Check return value of ms_error_text()
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Gert Doering <[email protected]...>
Message-Id: <[email protected]...>
URL: http://article.gmane.org/gmane.network.openvpn.devel/10176
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering