diff options
author | Timo Rothenpieler <timo@rothenpieler.org> | 2022-09-26 00:36:24 +0200 |
---|---|---|
committer | Timo Rothenpieler <timo@rothenpieler.org> | 2022-09-26 14:59:49 +0200 |
commit | e648f720d3f9d6ecc8b335f5e7aa15f15b62317a (patch) | |
tree | 4664dc9bbaa015f53291418eb7084a927e0a90e1 /src/libutil/addr.c | |
parent | 0eaa19a09a573ac9e1a77290b57557cd39860eff (diff) | |
download | rspamd-e648f720d3f9d6ecc8b335f5e7aa15f15b62317a.tar.gz rspamd-e648f720d3f9d6ecc8b335f5e7aa15f15b62317a.zip |
[Fix] Fix copying of sockaddr_un addresses
They can be very tiny (hence the adjustment of the size assert)
and the path can contain intermittent null bytes, so the only choice
is to trust the input slen and copy the whole struct.
An autobound unix socket uses an abstract address, which starts with a
null byte, hence this change is neccesary for such an address getting
copied properly.
Diffstat (limited to 'src/libutil/addr.c')
-rw-r--r-- | src/libutil/addr.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/src/libutil/addr.c b/src/libutil/addr.c index 4c3de70cf..71879e357 100644 --- a/src/libutil/addr.c +++ b/src/libutil/addr.c @@ -1680,7 +1680,8 @@ rspamd_inet_address_from_sa (const struct sockaddr *sa, socklen_t slen) rspamd_inet_addr_t *addr; g_assert (sa != NULL); - g_assert (slen >= sizeof (struct sockaddr)); + /* Address of an AF_UNIX socket can be tiny */ + g_assert (slen >= sizeof (sa_family_t) + 1); addr = rspamd_inet_addr_create (sa->sa_family, NULL); @@ -1689,12 +1690,13 @@ rspamd_inet_address_from_sa (const struct sockaddr *sa, socklen_t slen) const struct sockaddr_un *un = (const struct sockaddr_un *)sa; g_assert (slen >= SUN_LEN (un)); + g_assert (slen <= sizeof (addr->u.un->addr)); - rspamd_strlcpy (addr->u.un->addr.sun_path, un->sun_path, - sizeof (addr->u.un->addr.sun_path)); -#if defined(FREEBSD) || defined(__APPLE__) - addr->u.un->addr.sun_len = un->sun_len; -#endif + /* sun_path can legally contain intermittent NULL bytes */ + memcpy (&addr->u.un->addr, un, slen); + + /* length of AF_UNIX addresses is variable */ + addr->slen = slen; } else if (sa->sa_family == AF_INET) { g_assert (slen >= sizeof (struct sockaddr_in)); |