[PATCH 2/3] connection: Prevent integer overflow in DIV_ROUNDUP.
Pekka Paalanen
ppaalanen at gmail.com
Fri Aug 17 10:39:12 UTC 2018
On Tue, 14 Aug 2018 13:07:52 +0200
Michal Srb <msrb at suse.com> wrote:
> The DIV_ROUNDUP macro would overflow when trying to round values higher
> than MAX_UINT32 - (a - 1). The result is 0 after the division. This is
> potential security issue when demarshalling an array because the length
> check is performed with the overflowed value, but then the original huge
> value is stored for later use.
>
> The issue was present only on 32bit platforms. The use of size_t in the
> DIV_ROUNDUP macro already promoted everything to 64 bit size on 64 bit
> systems.
> ---
> src/connection.c | 23 ++++++++++++++---------
> 1 file changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/src/connection.c b/src/connection.c
> index 294c521..31396bc 100644
> --- a/src/connection.c
> +++ b/src/connection.c
> @@ -44,7 +44,12 @@
> #include "wayland-private.h"
> #include "wayland-os.h"
>
> -#define DIV_ROUNDUP(n, a) ( ((n) + ((a) - 1)) / (a) )
> +static inline uint32_t div_roundup(uint32_t n, size_t a) {
> + // The cast to uint64_t is necessary to prevent overflow when rounding
> + // values close to UINT32_MAX. After the division it is again safe to
> + // cast back to uint32_t.
> + return (uint32_t) (((uint64_t) n + (a - 1)) / a);
> +}
The above has a few style issues:
- div_roundup should start on a new line as it is a function now
- use /* */ comment style
- use tabs for indent
- missing Signed-off-by
But aside from those, this patch is:
Reviewed-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
>
> struct wl_buffer {
> char data[4096];
> @@ -734,7 +739,7 @@ wl_connection_demarshal(struct wl_connection *connection,
> break;
> }
>
> - next = p + DIV_ROUNDUP(length, sizeof *p);
> + next = p + div_roundup(length, sizeof *p);
> if (next > end) {
> wl_log("message too short, "
> "object (%d), message %s(%s)\n",
> @@ -793,7 +798,7 @@ wl_connection_demarshal(struct wl_connection *connection,
> case 'a':
> length = *p++;
>
> - next = p + DIV_ROUNDUP(length, sizeof *p);
> + next = p + div_roundup(length, sizeof *p);
> if (next > end) {
> wl_log("message too short, "
> "object (%d), message %s(%s)\n",
> @@ -1068,7 +1073,7 @@ buffer_size_for_closure(struct wl_closure *closure)
> }
>
> size = strlen(closure->args[i].s) + 1;
> - buffer_size += 1 + DIV_ROUNDUP(size, sizeof(uint32_t));
> + buffer_size += 1 + div_roundup(size, sizeof(uint32_t));
> break;
> case 'a':
> if (closure->args[i].a == NULL) {
> @@ -1077,7 +1082,7 @@ buffer_size_for_closure(struct wl_closure *closure)
> }
>
> size = closure->args[i].a->size;
> - buffer_size += (1 + DIV_ROUNDUP(size, sizeof(uint32_t)));
> + buffer_size += (1 + div_roundup(size, sizeof(uint32_t)));
> break;
> default:
> break;
> @@ -1139,11 +1144,11 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
> size = strlen(closure->args[i].s) + 1;
> *p++ = size;
>
> - if (p + DIV_ROUNDUP(size, sizeof *p) > end)
> + if (p + div_roundup(size, sizeof *p) > end)
> goto overflow;
>
> memcpy(p, closure->args[i].s, size);
> - p += DIV_ROUNDUP(size, sizeof *p);
> + p += div_roundup(size, sizeof *p);
> break;
> case 'a':
> if (closure->args[i].a == NULL) {
> @@ -1154,11 +1159,11 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
> size = closure->args[i].a->size;
> *p++ = size;
>
> - if (p + DIV_ROUNDUP(size, sizeof *p) > end)
> + if (p + div_roundup(size, sizeof *p) > end)
> goto overflow;
>
> memcpy(p, closure->args[i].a->data, size);
> - p += DIV_ROUNDUP(size, sizeof *p);
> + p += div_roundup(size, sizeof *p);
> break;
> default:
> break;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20180817/ce264b9b/attachment.sig>
More information about the wayland-devel
mailing list