Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
379 changes: 379 additions & 0 deletions SPECS/keepalived/CVE-2024-41184.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,379 @@
From f3a32e3557520dccb298b36b4952eff3e236fb86 Mon Sep 17 00:00:00 2001
From: Quentin Armitage <quentin@armitage.org.uk>
Date: Fri, 12 Jul 2024 15:11:13 +0100
Subject: [PATCH 1/5] lib: don't return subtracted addresses for rb_find()
compare function

If sizeof(int) < sizeof(void *) returning the difference between two
addresses in an int can cause an overflow.

Use less_equal_greater_than() for comparing addresses.

Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
---
lib/memory.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/memory.c b/lib/memory.c
index c7217fdd..4b250ac9 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -200,7 +200,7 @@ static unsigned free_list_size;
static inline int
memcheck_ptr_cmp(const void *key, const struct rb_node *a)
{
- return (const char *)key - (char *)rb_entry_const(a, MEMCHECK, t)->ptr;
+ return less_equal_greater_than((const char *)key, (char *)rb_entry_const(a, MEMCHECK, t)->ptr);
}

static inline bool
--
2.34.1


From e78513fe0ce5d83c226ea2c0bd222f375c2438e7 Mon Sep 17 00:00:00 2001
From: Quentin Armitage <quentin@armitage.org.uk>
Date: Fri, 12 Jul 2024 15:16:47 +0100
Subject: [PATCH 2/5] vrrp: Handle empty ipset names with vrrp_ipsets keyword

We now handle empty ipset names and return a config error.

Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
---
keepalived/core/global_parser.c | 40 ++++++++++++++++++---------------
1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/keepalived/core/global_parser.c b/keepalived/core/global_parser.c
index ed76b5cb..8935e502 100644
--- a/keepalived/core/global_parser.c
+++ b/keepalived/core/global_parser.c
@@ -1099,6 +1099,22 @@ vrrp_iptables_handler(const vector_t *strvec)
}
}
#ifdef _HAVE_LIBIPSET_
+static bool
+check_valid_ipset_name(const vector_t *strvec, unsigned entry, const char *log_name)
+{
+ if (strlen(strvec_slot(strvec, entry)) >= IPSET_MAXNAMELEN - 1) {
+ report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset %s name too long - ignored", log_name);
+ return false;
+ }
+
+ if (strlen(strvec_slot(strvec, entry)) == 0) {
+ report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset %s name empty - ignored", log_name);
+ return false;
+ }
+
+ return true;
+}
+
static void
vrrp_ipsets_handler(const vector_t *strvec)
{
@@ -1119,17 +1135,13 @@ vrrp_ipsets_handler(const vector_t *strvec)
return;
}

- if (strlen(strvec_slot(strvec,1)) >= IPSET_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset address name too long - ignored");
+ if (!check_valid_ipset_name(strvec, 1, "address"))
return;
- }
global_data->vrrp_ipset_address = STRDUP(strvec_slot(strvec,1));

if (vector_size(strvec) >= 3) {
- if (strlen(strvec_slot(strvec,2)) >= IPSET_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset IPv6 address name too long - ignored");
+ if (!check_valid_ipset_name(strvec, 2, "IPv6 address"))
return;
- }
global_data->vrrp_ipset_address6 = STRDUP(strvec_slot(strvec,2));
} else {
/* No second set specified, copy first name and add "6" */
@@ -1140,10 +1152,8 @@ vrrp_ipsets_handler(const vector_t *strvec)
}

if (vector_size(strvec) >= 4) {
- if (strlen(strvec_slot(strvec,3)) >= IPSET_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset IPv6 address_iface name too long - ignored");
+ if (!check_valid_ipset_name(strvec, 3, "IPv6 address_iface"))
return;
- }
global_data->vrrp_ipset_address_iface6 = STRDUP(strvec_slot(strvec,3));
} else {
/* No third set specified, copy second name and add "_if6" */
@@ -1157,10 +1167,8 @@ vrrp_ipsets_handler(const vector_t *strvec)
}

if (vector_size(strvec) >= 5) {
- if (strlen(strvec_slot(strvec,4)) >= IPSET_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset IGMP name too long - ignored");
+ if (!check_valid_ipset_name(strvec, 4, "IGMP"))
return;
- }
global_data->vrrp_ipset_igmp = STRDUP(strvec_slot(strvec,4));
} else {
/* No second set specified, copy first name and add "_igmp" */
@@ -1171,10 +1179,8 @@ vrrp_ipsets_handler(const vector_t *strvec)
}

if (vector_size(strvec) >= 6) {
- if (strlen(strvec_slot(strvec,5)) >= IPSET_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset MLD name too long - ignored");
+ if (!check_valid_ipset_name(strvec, 5, "MLD"))
return;
- }
global_data->vrrp_ipset_mld = STRDUP(strvec_slot(strvec,5));
} else {
/* No second set specified, copy first name and add "_mld" */
@@ -1186,10 +1192,8 @@ vrrp_ipsets_handler(const vector_t *strvec)

#ifdef _HAVE_VRRP_VMAC_
if (vector_size(strvec) >= 7) {
- if (strlen(strvec_slot(strvec,6)) >= IPSET_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset ND name too long - ignored");
+ if (!check_valid_ipset_name(strvec, 6, "ND"))
return;
- }
global_data->vrrp_ipset_vmac_nd = STRDUP(strvec_slot(strvec,6));
} else {
/* No second set specified, copy first name and add "_nd" */
--
2.34.1


From 281de3aa8a0990fa3cd694a9addc0bf28953da0b Mon Sep 17 00:00:00 2001
From: Quentin Armitage <quentin@armitage.org.uk>
Date: Fri, 12 Jul 2024 15:18:20 +0100
Subject: [PATCH 3/5] vrrp: handle empty iptables chain names - vrrp_iptables
keyword

We now return an error if a chain name is empty.

Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
---
keepalived/core/global_parser.c | 42 ++++++++++++++++++++-------------
1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/keepalived/core/global_parser.c b/keepalived/core/global_parser.c
index 8935e502..3d436e49 100644
--- a/keepalived/core/global_parser.c
+++ b/keepalived/core/global_parser.c
@@ -1072,6 +1072,28 @@ vrrp_higher_prio_send_advert_handler(const vector_t *strvec)
global_data->vrrp_higher_prio_send_advert = true;
}
#ifdef _WITH_IPTABLES_
+static bool
+check_valid_iptables_ipset_name(const vector_t *strvec, unsigned entry, unsigned max_len, const char *type_name, const char *log_name)
+{
+ if (strlen(strvec_slot(strvec, entry)) >= max_len - 1) {
+ report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : %s %s name too long - ignored", type_name, log_name);
+ return false;
+ }
+
+ if (strlen(strvec_slot(strvec, entry)) == 0) {
+ report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : %s %s name empty - ignored", type_name, log_name);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+check_valid_iptables_chain_name(const vector_t *strvec, unsigned entry, const char *log_name)
+{
+ return check_valid_iptables_ipset_name(strvec, entry, XT_EXTENSION_MAXNAMELEN, "iptables", log_name);
+}
+
static void
vrrp_iptables_handler(const vector_t *strvec)
{
@@ -1081,16 +1103,12 @@ vrrp_iptables_handler(const vector_t *strvec)
}

if (vector_size(strvec) >= 2) {
- if (strlen(strvec_slot(strvec,1)) >= XT_EXTENSION_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : iptables in chain name too long - ignored");
+ if (!check_valid_iptables_chain_name(strvec, 1, "in chain"))
return;
- }
global_data->vrrp_iptables_inchain = STRDUP(strvec_slot(strvec,1));
if (vector_size(strvec) >= 3) {
- if (strlen(strvec_slot(strvec,2)) >= XT_EXTENSION_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : iptables out chain name too long - ignored");
+ if (!check_valid_iptables_chain_name(strvec, 2, "out chain"))
return;
- }
global_data->vrrp_iptables_outchain = STRDUP(strvec_slot(strvec,2));
}
} else {
@@ -1102,17 +1120,7 @@ vrrp_iptables_handler(const vector_t *strvec)
static bool
check_valid_ipset_name(const vector_t *strvec, unsigned entry, const char *log_name)
{
- if (strlen(strvec_slot(strvec, entry)) >= IPSET_MAXNAMELEN - 1) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset %s name too long - ignored", log_name);
- return false;
- }
-
- if (strlen(strvec_slot(strvec, entry)) == 0) {
- report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : ipset %s name empty - ignored", log_name);
- return false;
- }
-
- return true;
+ return check_valid_iptables_ipset_name(strvec, entry, IPSET_MAXNAMELEN, "ipset", log_name);
}

static void
--
2.34.1


From 1e5902c4793ac01b810f0faa3b5cf47b41ae95c1 Mon Sep 17 00:00:00 2001
From: Quentin Armitage <quentin@armitage.org.uk>
Date: Fri, 12 Jul 2024 15:32:35 +0100
Subject: [PATCH 4/5] vrrp and ipvs: handle empty nftables chain names

We now return an error if a chain name is empty.

Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
---
keepalived/core/global_parser.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/keepalived/core/global_parser.c b/keepalived/core/global_parser.c
index 3d436e49..0a8f53ac 100644
--- a/keepalived/core/global_parser.c
+++ b/keepalived/core/global_parser.c
@@ -1071,9 +1071,10 @@ vrrp_higher_prio_send_advert_handler(const vector_t *strvec)
else
global_data->vrrp_higher_prio_send_advert = true;
}
-#ifdef _WITH_IPTABLES_
+
+#if defined _WITH_IPTABLES_ || defined _WITH_NFTABLES_
static bool
-check_valid_iptables_ipset_name(const vector_t *strvec, unsigned entry, unsigned max_len, const char *type_name, const char *log_name)
+check_valid_iptables_ipset_nftables_name(const vector_t *strvec, unsigned entry, unsigned max_len, const char *type_name, const char *log_name)
{
if (strlen(strvec_slot(strvec, entry)) >= max_len - 1) {
report_config_error(CONFIG_GENERAL_ERROR, "VRRP Error : %s %s name too long - ignored", type_name, log_name);
@@ -1087,11 +1088,13 @@ check_valid_iptables_ipset_name(const vector_t *strvec, unsigned entry, unsigned

return true;
}
+#endif

+#ifdef _WITH_IPTABLES_
static bool
check_valid_iptables_chain_name(const vector_t *strvec, unsigned entry, const char *log_name)
{
- return check_valid_iptables_ipset_name(strvec, entry, XT_EXTENSION_MAXNAMELEN, "iptables", log_name);
+ return check_valid_iptables_ipset_nftables_name(strvec, entry, XT_EXTENSION_MAXNAMELEN, "iptables", log_name);
}

static void
@@ -1120,7 +1123,7 @@ vrrp_iptables_handler(const vector_t *strvec)
static bool
check_valid_ipset_name(const vector_t *strvec, unsigned entry, const char *log_name)
{
- return check_valid_iptables_ipset_name(strvec, entry, IPSET_MAXNAMELEN, "ipset", log_name);
+ return check_valid_iptables_ipset_nftables_name(strvec, entry, IPSET_MAXNAMELEN, "ipset", log_name);
}

static void
@@ -1229,6 +1232,12 @@ vrrp_iptables_handler(__attribute__((unused)) const vector_t *strvec)

#ifdef _WITH_NFTABLES_
#ifdef _WITH_VRRP_
+static bool
+check_valid_nftables_chain_name(const vector_t *strvec, unsigned entry, const char *log_name)
+{
+ return check_valid_iptables_ipset_nftables_name(strvec, entry, NFT_TABLE_MAXNAMELEN, "nftables", log_name);
+}
+
static void
vrrp_nftables_handler(__attribute__((unused)) const vector_t *strvec)
{
@@ -1240,10 +1249,8 @@ vrrp_nftables_handler(__attribute__((unused)) const vector_t *strvec)
}

if (vector_size(strvec) >= 2) {
- if (strlen(strvec_slot(strvec, 1)) >= NFT_TABLE_MAXNAMELEN) {
- report_config_error(CONFIG_GENERAL_ERROR, "nftables table name too long - ignoring");
+ if (!check_valid_nftables_chain_name(strvec, 1, "chain"))
return;
- }
name = strvec_slot(strvec, 1);
}
else {
@@ -1283,10 +1290,8 @@ ipvs_nftables_handler(__attribute__((unused)) const vector_t *strvec)
}

if (vector_size(strvec) >= 2) {
- if (strlen(strvec_slot(strvec, 1)) >= NFT_TABLE_MAXNAMELEN) {
- report_config_error(CONFIG_GENERAL_ERROR, "ipvs nftables table name too long - ignoring");
+ if (!check_valid_nftables_chain_name(strvec, 1, "ipvs chain"))
return;
- }
name = strvec_slot(strvec, 1);
}
else {
--
2.34.1


From 7e2cabdb1391f9378fbb76513c2ee9c88b15dba8 Mon Sep 17 00:00:00 2001
From: Quentin Armitage <quentin@armitage.org.uk>
Date: Fri, 12 Jul 2024 15:34:54 +0100
Subject: [PATCH 5/5] configure: add --enable-sanitize-address option

Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
---
configure.ac | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/configure.ac b/configure.ac
index 180beb6f..1ba691b6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -263,6 +263,8 @@ AC_ARG_ENABLE(stacktrace,
[AS_HELP_STRING([--enable-stacktrace], [compile with stacktrace support])])
AC_ARG_ENABLE(perf,
[AS_HELP_STRING([--enable-perf], [compile with perf performance data recording support for vrrp process])])
+AC_ARG_ENABLE(sanitize-address,
+ [AS_HELP_STRING([--enable-sanitize-address], [compile with sanitize=address (ASAN) support])])
AC_ARG_ENABLE(log-file,
[AS_HELP_STRING([--enable-log-file], [enable logging to file (-g)])])
AC_ARG_ENABLE(dump-threads,
@@ -2848,6 +2850,16 @@ else
ENABLE_PERF=No
fi

+dnl ----[ sanitize=address testing or not? ]----
+if test "${enable_sanitize_address}" = yes; then
+# AC_DEFINE([_WITH_SANITIZE_ADDRESS_], [ 1 ], [Define to 1 to build with sanitize=address support])
+ ENABLE_SANITIZE_ADDRESS=Yes
+ add_config_opt([SANITIZE_ADDRESS])
+ add_to_var([KA_CFLAGS], [-fsanitize=address -g])
+else
+ ENABLE_SANITIZE_ADDRESS=No
+fi
+
if test "${enable_log_file}" = yes; then
AC_DEFINE([ENABLE_LOG_TO_FILE], [ 1 ], [Define if enabling logging to files])
ENABLE_LOG_FILE_APPEND=Yes
@@ -3271,6 +3283,9 @@ fi
if test ${ENABLE_PERF} = Yes; then
echo "Perf support : Yes"
fi
+if test ${ENABLE_SANITIZE_ADDRESS} = Yes; then
+ echo "sanitize=address testing : Yes"
+fi
if test ${MEM_CHECK} = Yes; then
echo "Memory alloc check : Yes"
echo "Memory alloc check log : ${MEM_CHECK_LOG}"
--
2.34.1

4 changes: 2 additions & 2 deletions SPECS/keepalived/keepalived.signatures.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"Signatures": {
"keepalived-2.2.7.tar.gz": "c61940d874154a560a54627ecf7ef47adebdf832164368d10bf242a4d9b7d49d",
"keepalived-2.3.1.tar.gz": "92f4b69bfd998e2306d1995ad16fdad1b59e70be694c883385c5f55e02c62aa3",
"keepalived.service": "533fac0ed629192f87b42f5fa2ba4443bccc3ac383e9495be97369616b95d6bd"
}
}
}
Loading