mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-04-18 06:10:40 +02:00
all: add static assertion for maximumg alloca() allocated buffer
Add a compile time check that the buffer that we allocate on the stack is reasonably small.
This commit is contained in:
parent
617bdbd8c2
commit
3263cab596
6 changed files with 58 additions and 39 deletions
|
|
@ -1409,7 +1409,8 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
|
|||
* If @str is longer then @trunc_at, the string is truncated and the closing
|
||||
* quote is instead '^' to indicate truncation.
|
||||
*
|
||||
* Thus, the maximum stack allocated buffer will be @trunc_at+3. */
|
||||
* Thus, the maximum stack allocated buffer will be @trunc_at+3. The maximum
|
||||
* buffer size must be a constant and not larger than 300. */
|
||||
#define nm_strquote_a(trunc_at, str) \
|
||||
({ \
|
||||
const char *const _str = (str); \
|
||||
|
|
@ -1420,6 +1421,8 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
|
|||
const gsize _strlen_trunc = NM_MIN (strlen (_str), _trunc_at); \
|
||||
char *_buf; \
|
||||
\
|
||||
G_STATIC_ASSERT_EXPR ((trunc_at) <= 300); \
|
||||
\
|
||||
_buf = g_alloca (_strlen_trunc + 3); \
|
||||
_buf[0] = '"'; \
|
||||
memcpy (&_buf[1], _str, _strlen_trunc); \
|
||||
|
|
@ -1444,19 +1447,30 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
|
|||
_buf; \
|
||||
})
|
||||
|
||||
#define nm_sprintf_bufa(n_elements, format, ...) \
|
||||
/* it is "unsafe" because @bufsize must not be a constant expression and
|
||||
* there is no check at compiletime. Regardless of that, the buffer size
|
||||
* must not be larger than 300 bytes, as this gets stack allocated. */
|
||||
#define nm_sprintf_buf_unsafe_a(bufsize, format, ...) \
|
||||
({ \
|
||||
char *_buf; \
|
||||
int _buf_len; \
|
||||
typeof (n_elements) _n_elements = (n_elements); \
|
||||
typeof (bufsize) _bufsize = (bufsize); \
|
||||
\
|
||||
_buf = g_alloca (_n_elements); \
|
||||
_buf_len = g_snprintf (_buf, _n_elements, \
|
||||
nm_assert (_bufsize <= 300); \
|
||||
\
|
||||
_buf = g_alloca (_bufsize); \
|
||||
_buf_len = g_snprintf (_buf, _bufsize, \
|
||||
""format"", ##__VA_ARGS__); \
|
||||
nm_assert (_buf_len < _n_elements); \
|
||||
nm_assert (_buf_len >= 0 && _buf_len < _bufsize); \
|
||||
_buf; \
|
||||
})
|
||||
|
||||
#define nm_sprintf_bufa(bufsize, format, ...) \
|
||||
({ \
|
||||
G_STATIC_ASSERT_EXPR ((bufsize) <= 300); \
|
||||
nm_sprintf_buf_unsafe_a ((bufsize), format, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
/* aims to alloca() a buffer and fill it with printf(format, name).
|
||||
* Note that format must not contain any format specifier except
|
||||
* "%s".
|
||||
|
|
@ -1470,9 +1484,9 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
|
|||
char *_buf2; \
|
||||
\
|
||||
nm_assert (_p_val_to_free && !*_p_val_to_free); \
|
||||
if ( NM_STRLEN (format) < 200 \
|
||||
&& _name_len < (gsize) (200 - NM_STRLEN (format))) \
|
||||
_buf2 = nm_sprintf_bufa (NM_STRLEN (format) + _name_len, format, _name); \
|
||||
if ( NM_STRLEN (format) <= 290 \
|
||||
&& _name_len < (gsize) (290 - NM_STRLEN (format))) \
|
||||
_buf2 = nm_sprintf_buf_unsafe_a (NM_STRLEN (format) + _name_len, format, _name); \
|
||||
else { \
|
||||
_buf2 = g_strdup_printf (format, _name); \
|
||||
*_p_val_to_free = _buf2; \
|
||||
|
|
|
|||
|
|
@ -278,6 +278,8 @@ _nm_strndup_a_step (char *s, const char *str, gsize len)
|
|||
char **const _out_str_free = (out_str_free); \
|
||||
char *_s; \
|
||||
\
|
||||
G_STATIC_ASSERT_EXPR ((alloca_maxlen) <= 300); \
|
||||
\
|
||||
if ( _out_str_free \
|
||||
&& _len >= _alloca_maxlen) { \
|
||||
_s = g_malloc (_len + 1); \
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ test_make_strv (void)
|
|||
|
||||
G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (NM_MAKE_STRV ("a", "b" )) == 3);
|
||||
G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (NM_MAKE_STRV ("a", "b", )) == 3);
|
||||
|
||||
nm_strquote_a (300, "");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -42,17 +42,6 @@
|
|||
#include "nm-utils/nm-time-utils.h"
|
||||
#include "nm-errors.h"
|
||||
|
||||
/* often we have some static string where we need to know the maximum length.
|
||||
* _MAX_LEN() returns @max but adds a debugging assertion that @str is indeed
|
||||
* shorter then @mac. */
|
||||
#define _MAX_LEN(max, str) \
|
||||
({ \
|
||||
const char *const _str = (str); \
|
||||
\
|
||||
nm_assert (_str && strlen (str) < (max)); \
|
||||
(max); \
|
||||
})
|
||||
|
||||
void (*_nm_logging_clear_platform_logging_cache) (void);
|
||||
|
||||
static void
|
||||
|
|
@ -592,14 +581,25 @@ _iovec_set_format (struct iovec *iov, gpointer *iov_free, const char *format, ..
|
|||
char *const _buf = g_alloca (_size); \
|
||||
int _len; \
|
||||
\
|
||||
G_STATIC_ASSERT_EXPR ((reserve_extra) + (NM_STRLEN (format) + 3) <= 96); \
|
||||
\
|
||||
_len = g_snprintf (_buf, _size, ""format"", ##__VA_ARGS__);\
|
||||
\
|
||||
nm_assert (_len >= 0); \
|
||||
nm_assert (_len <= _size); \
|
||||
nm_assert (_len < _size); \
|
||||
nm_assert (_len == strlen (_buf)); \
|
||||
\
|
||||
_iovec_set ((iov), _buf, _len); \
|
||||
} G_STMT_END
|
||||
|
||||
#define _iovec_set_format_str_a(iov, max_str_len, format, str_arg) \
|
||||
G_STMT_START { \
|
||||
const char *_str_arg = (str_arg); \
|
||||
\
|
||||
nm_assert (_str_arg && strlen (_str_arg) < (max_str_len)); \
|
||||
_iovec_set_format_a ((iov), (max_str_len), format, str_arg); \
|
||||
} G_STMT_END
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
|
|
@ -699,7 +699,7 @@ _nm_log_impl (const char *file,
|
|||
if (NM_FLAGS_ANY (dom, diter->num)) {
|
||||
if (i_domain > 0) {
|
||||
/* SYSLOG_FACILITY is specified multiple times for each domain that is actually enabled. */
|
||||
_iovec_set_format_a (iov++, _MAX_LEN (30, diter->name), "SYSLOG_FACILITY=%s", diter->name);
|
||||
_iovec_set_format_str_a (iov++, 30, "SYSLOG_FACILITY=%s", diter->name);
|
||||
i_domain--;
|
||||
}
|
||||
dom &= ~diter->num;
|
||||
|
|
@ -710,9 +710,9 @@ _nm_log_impl (const char *file,
|
|||
if (s_domain_all)
|
||||
_iovec_set (iov++, s_domain_all->str, s_domain_all->len);
|
||||
else
|
||||
_iovec_set_format_a (iov++, _MAX_LEN (30, s_domain_1), "NM_LOG_DOMAINS=%s", s_domain_1);
|
||||
_iovec_set_format_str_a (iov++, 30, "NM_LOG_DOMAINS=%s", s_domain_1);
|
||||
}
|
||||
_iovec_set_format_a (iov++, _MAX_LEN (15, global.level_desc[level].name), "NM_LOG_LEVEL=%s", global.level_desc[level].name);
|
||||
_iovec_set_format_str_a (iov++, 15, "NM_LOG_LEVEL=%s", global.level_desc[level].name);
|
||||
if (func)
|
||||
_iovec_set_format (iov++, iov_free++, "CODE_FUNC=%s", func);
|
||||
_iovec_set_format (iov++, iov_free++, "CODE_FILE=%s", file ?: "");
|
||||
|
|
|
|||
|
|
@ -2293,9 +2293,10 @@ link_set_option (NMPlatform *self, int ifindex, const char *category, const char
|
|||
if (dirfd < 0)
|
||||
return FALSE;
|
||||
|
||||
path = nm_sprintf_bufa (strlen (category) + strlen (option) + 2,
|
||||
"%s/%s",
|
||||
category, option);
|
||||
path = nm_sprintf_buf_unsafe_a (strlen (category) + strlen (option) + 2,
|
||||
"%s/%s",
|
||||
category,
|
||||
option);
|
||||
return nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_NETDIR_unsafe (dirfd, ifname_verified, path), value);
|
||||
}
|
||||
|
||||
|
|
@ -2313,9 +2314,9 @@ link_get_option (NMPlatform *self, int ifindex, const char *category, const char
|
|||
if (dirfd < 0)
|
||||
return NULL;
|
||||
|
||||
path = nm_sprintf_bufa (strlen (category) + strlen (option) + 2,
|
||||
"%s/%s",
|
||||
category, option);
|
||||
path = nm_sprintf_buf_unsafe_a (strlen (category) + strlen (option) + 2,
|
||||
"%s/%s",
|
||||
category, option);
|
||||
return nm_platform_sysctl_get (self, NMP_SYSCTL_PATHID_NETDIR_unsafe (dirfd, ifname_verified, path));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1087,15 +1087,15 @@ const char *nm_link_type_to_string (NMLinkType link_type);
|
|||
((const char *) NULL), -1, (path)
|
||||
|
||||
#define NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname, path) \
|
||||
nm_sprintf_bufa ( NM_STRLEN ("net:/sys/class/net//\0") \
|
||||
+ NMP_IFNAMSIZ \
|
||||
+ ({ \
|
||||
const gsize _l = strlen (path); \
|
||||
\
|
||||
nm_assert (_l < 200); \
|
||||
_l; \
|
||||
}), \
|
||||
"net:/sys/class/net/%s/%s", (ifname), (path)), \
|
||||
nm_sprintf_buf_unsafe_a ( NM_STRLEN ("net:/sys/class/net//\0") \
|
||||
+ NMP_IFNAMSIZ \
|
||||
+ ({ \
|
||||
const gsize _l = strlen (path); \
|
||||
\
|
||||
nm_assert (_l < 200); \
|
||||
_l; \
|
||||
}), \
|
||||
"net:/sys/class/net/%s/%s", (ifname), (path)), \
|
||||
(dirfd), (path)
|
||||
|
||||
#define NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, path) \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue