bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 6/6] Add test for explicit_bzero


From: Bruno Haible
Subject: Re: [PATCH 6/6] Add test for explicit_bzero
Date: Sun, 12 Apr 2020 21:07:57 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-174-generic; KDE/5.18.0; x86_64; ; )

Hi Bastien,

> But I will prefer that you push first the test (I have not written
> myself and it need comments that are outside my english language
> skills).
> 
> So could you push a test ?

I'm pushing the test as shown below.

It confirms my suspicion that with just a plain memset instead of
explicit_bzero, the compiler optimizes memset away only in the stack-allocated
case. (This is with gcc -O2.)

Now, your turn. With this test, please test your changes on some relevant
platforms. I can cover those platforms to which you don't have access to.

Bruno

========================= tests/test-explicit_bzero.c =========================
/* Test of explicit_bzero() function.
   Copyright (C) 2020 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

/* Written by Bruno Haible <address@hidden>, 2020.  */

#include <config.h>

/* Specification.  */
#include <string.h>

#include "signature.h"
SIGNATURE_CHECK (explicit_bzero, void, (void *, size_t));

#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#include "vma-iter.h"
#include "macros.h"

#define SECRET "xyzzy1729"
#define SECRET_SIZE 9

static char zero[SECRET_SIZE] = { 0 };

/* Enable this to verify that the test is effective.  */
#if 0
# define explicit_bzero(a, n)  memset (a, '\0', n)
#endif

/* =================== Verify operation on static memory =================== */

static char stbuf[SECRET_SIZE];

static void
test_static (void)
{
  memcpy (stbuf, SECRET, SECRET_SIZE);
  explicit_bzero (stbuf, SECRET_SIZE);
  ASSERT (memcmp (zero, stbuf, SECRET_SIZE) == 0);
}

/* =============== Verify operation on heap-allocated memory =============== */

/* Test whether an address range is mapped in memory.  */
#if VMA_ITERATE_SUPPORTED

struct locals
{
  uintptr_t range_start;
  uintptr_t range_end;
};

static int
vma_iterate_callback (void *data, uintptr_t start, uintptr_t end,
                      unsigned int flags)
{
  struct locals *lp = (struct locals *) data;

  /* Remove from [range_start, range_end) the part at the beginning or at the
     end that is covered by [start, end).  */
  if (start <= lp->range_start && end > lp->range_start)
    lp->range_start = (end < lp->range_end ? end : lp->range_end);
  if (start < lp->range_end && end >= lp->range_end)
    lp->range_end = (start > lp->range_start ? start : lp->range_start);

  return 0;
}

static bool
is_range_mapped (uintptr_t range_start, uintptr_t range_end)
{
  struct locals l;

  l.range_start = range_start;
  l.range_end = range_end;
  vma_iterate (vma_iterate_callback, &l);
  return l.range_start == l.range_end;
}

#else

static bool
is_range_mapped (uintptr_t range_start, uintptr_t range_end)
{
  return true;
}

#endif

static void
test_heap (void)
{
  char *heapbuf = (char *) malloc (SECRET_SIZE);
  uintptr_t addr = (uintptr_t) heapbuf;
  memcpy (heapbuf, SECRET, SECRET_SIZE);
  explicit_bzero (heapbuf, SECRET_SIZE);
  free (heapbuf);
  if (is_range_mapped (addr, addr + SECRET_SIZE))
    {
      ASSERT (memcmp (zero, heapbuf, SECRET_SIZE) == 0);
      printf ("test_heap: address range is still mapped after free().\n");
    }
  else
    printf ("test_heap: address range is unmapped after free().\n");
}

/* =============== Verify operation on stack-allocated memory =============== */

/* There are two passes:
     1. Put a secret in memory and invoke explicit_bzero on it.
     2. Verify that the memory has been erased.
   Implement them in the same function, so that they access the same memory
   range on the stack.  */
int
do_secret_stuff (volatile int pass)
{
  char stackbuf[SECRET_SIZE];
  if (pass == 1)
    {
      memcpy (stackbuf, SECRET, SECRET_SIZE);
      explicit_bzero (stackbuf, SECRET_SIZE);
      return 0;
    }
  else /* pass == 2 */
    {
      return memcmp (zero, stackbuf, SECRET_SIZE) != 0;
    }
}

void
test_stack (void)
{
  int count = 0;
  int repeat;

  for (repeat = 1000; repeat > 0; repeat--)
    {
      do_secret_stuff (1);
      count += do_secret_stuff (2);
    }
  /* If explicit_bzero works, count is near 0.  (It may be > 0 if there were
     some asynchronous signal invocations between the two calls of
     do_secret_stuff.)
     If explicit_bzero is optimized away by the compiler, count comes out as
     approximately 1000.  */
  printf ("test_stack: count = %d\n", count);
  ASSERT (count < 50);
}

/* ========================================================================== */

int
main ()
{
  test_static ();
  test_heap ();
  test_stack ();

  return 0;
}
========================= modules/explicit_bzero-tests ========================
Files:
tests/test-explicit_bzero.c
tests/signature.h
tests/macros.h

Depends-on:
stdint
vma-iter

configure.ac:

Makefile.am:
TESTS += test-explicit_bzero
check_PROGRAMS += test-explicit_bzero




reply via email to

[Prev in Thread] Current Thread [Next in Thread]