This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v1.1] Preload infrastructure.
- From: OndÅej BÃlka <neleai at seznam dot cz>
- To: libc-alpha at sourceware dot org
- Date: Mon, 21 Oct 2013 23:26:55 +0200
- Subject: [PATCH v1.1] Preload infrastructure.
- Authentication-results: sourceware.org; auth=none
- References: <20131021193617 dot GA29829 at domone dot podge>
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