diff mbox series

[v3,2/2] libselinux: introduce reallocarray(3)

Message ID 20231101165636.184983-2-cgzones@googlemail.com (mailing list archive)
State Accepted
Commit cb8289c2b237
Delegated to: Petr Lautrbach
Headers show
Series [v3,1/2] libselinux: cast to unsigned char for character handling function | expand

Commit Message

Christian Göttsche Nov. 1, 2023, 4:56 p.m. UTC
Introduce reallocarray(3), a realloc(3) wrapper incorporating a
multiplication overflow check.

Add private implementation in case the function is not provided by the
standard C library.

Use in appropriate locations.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
v3:
  - use SIZE_MAX and NULL instead of -1 and 0
  - fix indentation
  - drop RFC and split from original patch set
---
 libselinux/src/Makefile             |  6 ++++++
 libselinux/src/get_context_list.c   |  2 +-
 libselinux/src/matchpathcon.c       |  4 ++--
 libselinux/src/selinux_internal.c   | 16 ++++++++++++++++
 libselinux/src/selinux_internal.h   |  4 ++++
 libselinux/src/selinux_restorecon.c |  3 +--
 6 files changed, 30 insertions(+), 5 deletions(-)

Comments

James Carter Nov. 6, 2023, 6:28 p.m. UTC | #1
On Wed, Nov 1, 2023 at 12:57 PM Christian Göttsche
<cgzones@googlemail.com> wrote:
>
> Introduce reallocarray(3), a realloc(3) wrapper incorporating a
> multiplication overflow check.
>
> Add private implementation in case the function is not provided by the
> standard C library.
>
> Use in appropriate locations.
>
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Acked-by: James Carter <jwcart2@gmail.com>

> ---
> v3:
>   - use SIZE_MAX and NULL instead of -1 and 0
>   - fix indentation
>   - drop RFC and split from original patch set
> ---
>  libselinux/src/Makefile             |  6 ++++++
>  libselinux/src/get_context_list.c   |  2 +-
>  libselinux/src/matchpathcon.c       |  4 ++--
>  libselinux/src/selinux_internal.c   | 16 ++++++++++++++++
>  libselinux/src/selinux_internal.h   |  4 ++++
>  libselinux/src/selinux_restorecon.c |  3 +--
>  6 files changed, 30 insertions(+), 5 deletions(-)
>
> diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
> index cf830046..7aadb822 100644
> --- a/libselinux/src/Makefile
> +++ b/libselinux/src/Makefile
> @@ -108,6 +108,12 @@ ifeq (yes,$(shell printf '${H}include <string.h>\nint main(void){char*d,*s;strlc
>  override CFLAGS += -DHAVE_STRLCPY
>  endif
>
> +# check for reallocarray(3) availability
> +H := \#
> +ifeq (yes,$(shell printf '${H}include <stdlib.h>\nint main(void){reallocarray(NULL, 0, 0);return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes))
> +override CFLAGS += -DHAVE_REALLOCARRAY
> +endif
> +
>  SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \
>                 -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations \
>                 -Wno-deprecated-declarations
> diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c
> index 0342823c..9dafa519 100644
> --- a/libselinux/src/get_context_list.c
> +++ b/libselinux/src/get_context_list.c
> @@ -272,7 +272,7 @@ static int get_context_user(FILE * fp,
>                         continue;
>                 }
>                 if (security_check_context(usercon_str2) == 0) {
> -                       new_reachable = realloc(*reachable, (*nreachable + 2) * sizeof(char *));
> +                       new_reachable = reallocarray(*reachable, *nreachable + 2, sizeof(char *));
>                         if (!new_reachable) {
>                                 context_free(usercon);
>                                 rc = -1;
> diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
> index b98849d9..e44734c3 100644
> --- a/libselinux/src/matchpathcon.c
> +++ b/libselinux/src/matchpathcon.c
> @@ -96,8 +96,8 @@ static int add_array_elt(char *con)
>         if (con_array_size) {
>                 while (con_array_used >= con_array_size) {
>                         con_array_size *= 2;
> -                       tmp = (char **)realloc(con_array, sizeof(char*) *
> -                                                    con_array_size);
> +                       tmp = (char **)reallocarray(con_array, con_array_size,
> +                                                   sizeof(char*));
>                         if (!tmp) {
>                                 free_array_elts();
>                                 return -1;
> diff --git a/libselinux/src/selinux_internal.c b/libselinux/src/selinux_internal.c
> index c2be7c0a..678bd99c 100644
> --- a/libselinux/src/selinux_internal.c
> +++ b/libselinux/src/selinux_internal.c
> @@ -1,5 +1,7 @@
>  #include "selinux_internal.h"
>
> +#include <errno.h>
> +#include <stdlib.h>
>  #include <string.h>
>
>
> @@ -16,3 +18,17 @@ size_t strlcpy(char *dest, const char *src, size_t size)
>         return ret;
>  }
>  #endif /* HAVE_STRLCPY */
> +
> +#ifndef HAVE_REALLOCARRAY
> +void *reallocarray(void *ptr, size_t nmemb, size_t size)
> +{
> +
> +       if (size && nmemb > SIZE_MAX / size) {
> +               errno = ENOMEM;
> +               return NULL;
> +       }
> +
> +       return realloc(ptr, nmemb * size);
> +
> +}
> +#endif /* HAVE_REALLOCARRAY */
> diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
> index 06f2c038..af69ff04 100644
> --- a/libselinux/src/selinux_internal.h
> +++ b/libselinux/src/selinux_internal.h
> @@ -98,4 +98,8 @@ extern int has_selinux_config ;
>  size_t strlcpy(char *dest, const char *src, size_t size);
>  #endif
>
> +#ifndef HAVE_REALLOCARRAY
> +void *reallocarray(void *ptr, size_t nmemb, size_t size);
> +#endif
> +
>  #endif /* SELINUX_INTERNAL_H_ */
> diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
> index 7ef2d45d..38f10f1c 100644
> --- a/libselinux/src/selinux_restorecon.c
> +++ b/libselinux/src/selinux_restorecon.c
> @@ -175,8 +175,7 @@ static int add_exclude(const char *directory, bool who)
>                 return -1;
>         }
>
> -       tmp_list = realloc(exclude_lst,
> -                          sizeof(struct edir) * (exclude_count + 1));
> +       tmp_list = reallocarray(exclude_lst, exclude_count + 1, sizeof(struct edir));
>         if (!tmp_list)
>                 goto oom;
>
> --
> 2.42.0
>
diff mbox series

Patch

diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index cf830046..7aadb822 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -108,6 +108,12 @@  ifeq (yes,$(shell printf '${H}include <string.h>\nint main(void){char*d,*s;strlc
 override CFLAGS += -DHAVE_STRLCPY
 endif
 
+# check for reallocarray(3) availability
+H := \#
+ifeq (yes,$(shell printf '${H}include <stdlib.h>\nint main(void){reallocarray(NULL, 0, 0);return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes))
+override CFLAGS += -DHAVE_REALLOCARRAY
+endif
+
 SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \
 		-Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations \
 		-Wno-deprecated-declarations
diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c
index 0342823c..9dafa519 100644
--- a/libselinux/src/get_context_list.c
+++ b/libselinux/src/get_context_list.c
@@ -272,7 +272,7 @@  static int get_context_user(FILE * fp,
 			continue;
 		}
 		if (security_check_context(usercon_str2) == 0) {
-			new_reachable = realloc(*reachable, (*nreachable + 2) * sizeof(char *));
+			new_reachable = reallocarray(*reachable, *nreachable + 2, sizeof(char *));
 			if (!new_reachable) {
 				context_free(usercon);
 				rc = -1;
diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
index b98849d9..e44734c3 100644
--- a/libselinux/src/matchpathcon.c
+++ b/libselinux/src/matchpathcon.c
@@ -96,8 +96,8 @@  static int add_array_elt(char *con)
 	if (con_array_size) {
 		while (con_array_used >= con_array_size) {
 			con_array_size *= 2;
-			tmp = (char **)realloc(con_array, sizeof(char*) *
-						     con_array_size);
+			tmp = (char **)reallocarray(con_array, con_array_size,
+						    sizeof(char*));
 			if (!tmp) {
 				free_array_elts();
 				return -1;
diff --git a/libselinux/src/selinux_internal.c b/libselinux/src/selinux_internal.c
index c2be7c0a..678bd99c 100644
--- a/libselinux/src/selinux_internal.c
+++ b/libselinux/src/selinux_internal.c
@@ -1,5 +1,7 @@ 
 #include "selinux_internal.h"
 
+#include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 
 
@@ -16,3 +18,17 @@  size_t strlcpy(char *dest, const char *src, size_t size)
 	return ret;
 }
 #endif /* HAVE_STRLCPY */
+
+#ifndef HAVE_REALLOCARRAY
+void *reallocarray(void *ptr, size_t nmemb, size_t size)
+{
+	
+	if (size && nmemb > SIZE_MAX / size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	return realloc(ptr, nmemb * size);
+
+}
+#endif /* HAVE_REALLOCARRAY */
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
index 06f2c038..af69ff04 100644
--- a/libselinux/src/selinux_internal.h
+++ b/libselinux/src/selinux_internal.h
@@ -98,4 +98,8 @@  extern int has_selinux_config ;
 size_t strlcpy(char *dest, const char *src, size_t size);
 #endif
 
+#ifndef HAVE_REALLOCARRAY
+void *reallocarray(void *ptr, size_t nmemb, size_t size);
+#endif
+
 #endif /* SELINUX_INTERNAL_H_ */
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 7ef2d45d..38f10f1c 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -175,8 +175,7 @@  static int add_exclude(const char *directory, bool who)
 		return -1;
 	}
 
-	tmp_list = realloc(exclude_lst,
-			   sizeof(struct edir) * (exclude_count + 1));
+	tmp_list = reallocarray(exclude_lst, exclude_count + 1, sizeof(struct edir));
 	if (!tmp_list)
 		goto oom;