This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v1.1] Preload infrastructure.


On Mon, Oct 21, 2013 at 09:36:17PM +0200, OndÅej BÃlka wrote:
> Hi, to continue idea from
> http://www.sourceware.org/ml/libc-alpha/2013-10/msg00303.html
> I wrote a simple custom library to detect undefined behaviour and
> performance problems.
> 
> A first implementation does:
>  - overflow checks for string routines.
>  - detection of strcat usage that leads to quadratic behaviour
>  - detection passing long unaligned strings to memcpy
>  - detection of passing closed file descriptor to freopen (bug 15701)
> 
> OK to commit?
>
That was bit older version that I wanted to send, this one is correct,
as there was bug in strcat and use_preload was not fully converted.
 
 	* preload: New directory.
 	* preload/Makefile: New file.
 	* preload/common.c: Likewise.
 	* preload/common.h: Likewise.
 	* preload/freopen.c: Likewise.
 	* preload/string.c: Likewise.
 	* preload/use_preload: Likewise.

---
 preload/Makefile    |   2 +
 preload/common.c    |  22 +++++++++
 preload/common.h    |  19 ++++++++
 preload/freopen.c   |  10 ++++
 preload/string.c    | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 preload/use_preload |   7 +++
 6 files changed, 194 insertions(+)
 create mode 100644 preload/Makefile
 create mode 100644 preload/common.c
 create mode 100644 preload/common.h
 create mode 100644 preload/freopen.c
 create mode 100644 preload/string.c
 create mode 100755 preload/use_preload

diff --git a/preload/Makefile b/preload/Makefile
new file mode 100644
index 0000000..29d80fb
--- /dev/null
+++ b/preload/Makefile
@@ -0,0 +1,2 @@
+all:
+	gcc *.c -fPIC -ldl -g -lpthread -shared -o libc_preload.so
diff --git a/preload/common.c b/preload/common.c
new file mode 100644
index 0000000..098d307
--- /dev/null
+++ b/preload/common.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <dlfcn.h>
+FILE *__preload_log;
+void *__libc_handle;
+long __preload_counter = 0;
+static void __attribute__ ((constructor))
+init ()
+{
+  __preload_log = fopen ("/tmp/preload_log", "a");
+  __libc_handle = dlopen ("libc.so.6", RTLD_NOW);
+}
+static void __attribute__ ((destructor))
+fini ()
+{
+  fclose (__preload_log);
+}
+
+void
+__add_counter ()
+{
+  __preload_counter++;
+}
diff --git a/preload/common.h b/preload/common.h
new file mode 100644
index 0000000..847eb2f
--- /dev/null
+++ b/preload/common.h
@@ -0,0 +1,19 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <dlfcn.h>
+extern FILE *__preload_log;
+extern long __preload_counter;
+extern void *__libc_handle;
+
+#define validate_fd(x) \
+do {\
+  if (fcntl(x, F_GETFD) == -1) \
+  { \
+    log ("invalid file descriptor %i\n", x); \
+    abort (); \
+  } \
+} while (0)
+
+#define validate_file(x) validate_fd (fileno (x))
+
+#define log(...) fprintf(__preload_log,__VA_ARGS__)
diff --git a/preload/freopen.c b/preload/freopen.c
new file mode 100644
index 0000000..2ace5aa
--- /dev/null
+++ b/preload/freopen.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include "common.h"
+FILE *freopen(const char *path, const char *mode, FILE *stream)
+{
+  validate_file (stream);
+  FILE *(*fp)(const char *, const char *, FILE *) = dlsym (__libc_handle, "freopen");
+  return fp (path, mode, stream);
+}
+
diff --git a/preload/string.c b/preload/string.c
new file mode 100644
index 0000000..6782414
--- /dev/null
+++ b/preload/string.c
@@ -0,0 +1,134 @@
+#include <stdlib.h>
+#include <string.h>
+#include "common.h"
+#undef memcpy
+void *
+memcpy (void *dest, const void *src, size_t n)
+{
+  static int misaligned = 0;
+  size_t i;
+  if (n > 4096 && (dest - src) % 16 && !misaligned)
+    {
+      log ("memcpy %i: Misaligned copy of size %i\n", __preload_counter, n);
+      if (getenv ("ABORT_MISALIGNED"))
+	abort ();
+      misaligned = 1;
+    }
+  if (src - n < dest && dest < src + n)
+    {
+      fprintf (stderr, "memcpy %i - overlapping areas\n", __preload_counter);
+      abort ();
+    }
+  __add_counter ();
+
+  memmove (dest, src, n); /* memmove is not overloaded */
+  return dest;
+}
+void *
+mempcpy (void *dest, const void *src, size_t n)
+{
+  return memcpy (dest, src, n) + n;
+}
+char *
+strcpy (char *dest, const char *src)
+{
+  size_t n = strlen (src) + 1;
+  return memcpy (dest, src, n);
+}
+char *
+stpcpy (char *dest, const char *src)
+{
+  size_t n = strlen (src) + 1;
+  return memcpy (dest, src, n) + n - 1;
+}
+
+char *
+strncpy (char *dest, const char *src, size_t n)
+{
+  if (src - n < dest && dest < src + n)
+    {
+      fprintf (stderr, "strncpy %i - overlapping areas", __preload_counter);
+      abort ();
+    }
+  size_t len = strnlen (src, n);
+  memcpy (dest, src, len);
+  memset (dest + len, 0, n - len);
+  return dest;
+}
+
+char *
+stpncpy (char *dest, const char *src, size_t n)
+{
+  if (src - n < dest && dest < src + n)
+    {
+      fprintf (stderr, "stpncpy %i - overlapping areas", __preload_counter);
+      abort ();
+    }
+  size_t len = strnlen (src, n);
+  memcpy (dest, src, len);
+  memset (dest + len, 0, n - len);
+  return dest + len;
+}
+
+
+char *
+strncat (char *dest, const char *src, size_t n)
+{
+  static char *last; static int cnt; static int lastsize;
+  size_t len = strnlen (src, n);
+  char *p = dest + strlen (dest);
+
+  if (dest == last && len >= lastsize)
+    {
+      cnt++;
+    }
+  else
+    {
+      cnt = 0;
+    }
+  lastsize = len;
+
+  static int quad = 0;
+  if (cnt > 10 && !quad)
+    {
+      log ("str(n)cat %i: Detected likely quadratic loop.\n", __preload_counter);
+      if (getenv ("ABORT_LOOP"))
+	abort ();
+      quad = 1;
+    }
+
+
+  if (dest - len < src && src < p)
+    {
+      fprintf (stderr, "strcat %i - overlapping areas", __preload_counter);
+      abort ();
+    }
+
+  memcpy (p, src, len);
+  p[len] = 0;
+  return dest;
+}
+
+char *
+strcat (char *dest, const char *src)
+{
+  return strncat (dest, src, strlen (src));
+}
+
+void *
+memccpy (void *dest, const void *src, int c, size_t n)
+{
+  if (src - n < dest && dest < src + n)
+    {
+      fprintf (stderr, "memccpy %i - overlapping areas", __preload_counter);
+      abort ();
+    }
+
+  void *p = memchr (src, c, n);
+
+  if (p != NULL)
+    return mempcpy (dest, src, p - src + 1);
+
+  memcpy (dest, src, n);
+  return NULL;
+}
diff --git a/preload/use_preload b/preload/use_preload
new file mode 100755
index 0000000..bfdbe6d
--- /dev/null
+++ b/preload/use_preload
@@ -0,0 +1,7 @@
+#!/bin/bash
+rm /tmp/preload_log
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+LD_PRELOAD=$DIR/libc_preload.so $*
+echo
+echo "Checking warnings:"
+cat /tmp/preload_log
-- 
1.8.4.rc3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]