Module: xenomai-forge
Branch: master
Commit: 2793e2ee4767966406eead401d984595d1ebb17d
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=2793e2ee4767966406eead401d984595d1ebb17d

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Tue Apr 16 01:12:27 2013 +0200

lib/cobalt: allow compiling applications with _FORTIFY_SOURCE

When _FORTIFY_SOURCE is set, some services are replaced at compilation
time with versions performing additional checks on their
arguments. This is a problem if the same services need to be wrapped
by Xenomai: the checked versions are not wrapped, causing switches to
secondary mode.

This commit provides wrappers for the checked services.

The wrappers simply call the non checked version wrapper: calling
glibc checked services directly would break compilation with libcs
without this option, meaning old glibcs and alternative libcs.

In order to enable the checks provided by _FORTIFY_SOURCE, the Xenomai
binaries should be compiled with this option.

We attempt to auto-detect whether the underlying *libc supports
_FORTIFY_SOURCE at configuration time. --enable-fortify is introduced
to enable or disable the corresponding support in Xenomai libs.

If the support is enabled, checked versions of the Cobalt services are
redirected to checked versions of the *libc services. Otherwise, if a
checked version of a Cobalt service ends up being called, a fatal
error is raised.

---

 configure.in               |   19 +++++
 include/cobalt/stdio.h     |    6 ++
 include/cobalt/syslog.h    |    7 ++
 include/rtdk.h             |    5 ++
 lib/cobalt/cobalt.wrappers |    6 ++
 lib/cobalt/printf.c        |  170 +++++++++++++++++++++++++++++++++++++-------
 lib/cobalt/wrappers.c      |   18 +++++
 7 files changed, 205 insertions(+), 26 deletions(-)

diff --git a/configure.in b/configure.in
index 10cf78d..0786039 100644
--- a/configure.in
+++ b/configure.in
@@ -745,6 +745,25 @@ dnl in-tree executables which require POSIX symbol 
wrapping.
    AC_CONFIG_LINKS([lib/include/$base/xenomai:$srcdir/include/$base])
 fi
 
+unset want_fortify
+AC_MSG_CHECKING(for fortify support)
+AC_ARG_ENABLE([fortify], 
+             AC_HELP_STRING([--enable-fortify],
+                            [Enable support for applications compiled
+                            with _FORTIFY_SOURCE]),
+             [case "$enableval" in
+              y | yes) want_fortify=yes;;
+             *) want_fortify=no;;
+             esac])
+AC_MSG_RESULT(${want_fortify:-autodetect})
+if test x"$want_fortify" != xno; then
+   AC_CHECK_FUNC(__vfprintf_chk,
+             [AC_DEFINE(CONFIG_XENO_FORTIFY, 1 ,[config])],
+             [if test x"$want_fortify" = "xyes"; then
+             AC_MSG_ERROR([Fortify support enabled but not available in *libc])
+              fi])
+fi
+
 dnl
 dnl Build the Makefiles
 dnl
diff --git a/include/cobalt/stdio.h b/include/cobalt/stdio.h
index 4a88778..9f3fd4d 100644
--- a/include/cobalt/stdio.h
+++ b/include/cobalt/stdio.h
@@ -7,6 +7,7 @@
 
 #include <stddef.h>
 #include <stdarg.h>
+#include <xeno_config.h>
 #include <cobalt/wrappers.h>
 
 #ifdef __cplusplus
@@ -15,6 +16,11 @@ extern "C" {
 
 COBALT_DECL(int, vfprintf(FILE *stream, const char *fmt, va_list args));
 
+#ifdef CONFIG_XENO_FORTIFY
+COBALT_DECL(int, __vfprintf_chk(FILE *stream, int level,
+                               const char *fmt, va_list ap));
+#endif
+
 COBALT_DECL(int, vprintf(const char *fmt, va_list args));
 
 COBALT_DECL(int, fprintf(FILE *stream, const char *fmt, ...));
diff --git a/include/cobalt/syslog.h b/include/cobalt/syslog.h
index d446f45..701ec22 100644
--- a/include/cobalt/syslog.h
+++ b/include/cobalt/syslog.h
@@ -3,6 +3,7 @@
 
 #include <stdarg.h>
 #include_next <syslog.h>
+#include <xeno_config.h>
 #include <cobalt/wrappers.h>
 
 #ifdef __cplusplus
@@ -13,6 +14,12 @@ COBALT_DECL(void, syslog(int priority, const char *fmt, 
...));
 
 COBALT_DECL(void, vsyslog(int priority,
                          const char *fmt, va_list ap));
+
+#ifdef CONFIG_XENO_FORTIFY
+COBALT_DECL(void, __vsyslog_chk(int priority, int level,
+                               const char *fmt, va_list ap));
+#endif
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/include/rtdk.h b/include/rtdk.h
index 1b5f218..ecebbff 100644
--- a/include/rtdk.h
+++ b/include/rtdk.h
@@ -43,6 +43,7 @@ static inline const char *rt_print_buffer_name(void)
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <xeno_config.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -65,6 +66,10 @@ void rt_print_cleanup(void);
 void rt_print_auto_init(int enable);
 const char *rt_print_buffer_name(void);
 void rt_print_flush_buffers(void);
+#ifdef CONFIG_XENO_FORTIFY
+int __rt_vfprintf_chk(FILE *stream, int level, const char *fmt, va_list args);
+void __rt_vsyslog_chk(int priority, int level, const char *fmt, va_list args);
+#endif
 
 void assert_nrt(void);
 
diff --git a/lib/cobalt/cobalt.wrappers b/lib/cobalt/cobalt.wrappers
index 4ed9188..3d5d16b 100644
--- a/lib/cobalt/cobalt.wrappers
+++ b/lib/cobalt/cobalt.wrappers
@@ -98,3 +98,9 @@
 --wrap malloc
 --wrap free
 --wrap gettimeofday
+--wrap __vfprintf_chk
+--wrap __vprintf_chk
+--wrap __fprintf_chk
+--wrap __printf_chk
+--wrap __vsyslog_chk
+--wrap __syslog_chk
diff --git a/lib/cobalt/printf.c b/lib/cobalt/printf.c
index 99e4b90..eb1b31b 100644
--- a/lib/cobalt/printf.c
+++ b/lib/cobalt/printf.c
@@ -95,8 +95,9 @@ static void print_buffers(void);
 
 /* *** rt_print API *** */
 
-static int vprint_to_buffer(FILE *stream, int priority, unsigned int mode,
-                           size_t sz, const char *format, va_list args)
+static int 
+vprint_to_buffer(FILE *stream, int fortify_level, int priority, 
+                unsigned int mode, size_t sz, const char *format, va_list args)
 {
        struct print_buffer *buffer = pthread_getspecific(buffer_key);
        off_t write_pos, read_pos;
@@ -158,6 +159,16 @@ static int vprint_to_buffer(FILE *stream, int priority, 
unsigned int mode,
        if (mode == RT_PRINT_MODE_FORMAT) {
                if (stream != RT_PRINT_SYSLOG_STREAM) {
                        /* We do not need the terminating \0 */
+#ifdef CONFIG_XENO_FORTIFY
+                       if (fortify_level > 0)
+                               res = __vsnprintf_chk(head->data, len,
+                                                     fortify_level - 1,
+                                                     len > 0 ? len : 0, 
+                                                     format, args);
+                       else
+#else
+                               (void)fortify_level;
+#endif
                        res = vsnprintf(head->data, len, format, args);
 
                        if (res < len) {
@@ -170,7 +181,15 @@ static int vprint_to_buffer(FILE *stream, int priority, 
unsigned int mode,
                        }
                } else {
                        /* We DO need the terminating \0 */
-                       res = vsnprintf(head->data, len, format, args);
+#ifdef CONFIG_XENO_FORTIFY
+                       if (fortify_level > 0)
+                               res = __vsnprintf_chk(head->data, len,
+                                                     fortify_level - 1,
+                                                     len > 0 ? len : 0, 
+                                                     format, args);
+                       else
+#endif
+                               res = vsnprintf(head->data, len, format, args);
 
                        if (res < len) {
                                /* Text was written completely, res contains its
@@ -226,7 +245,7 @@ static int print_to_buffer(FILE *stream, int priority, 
unsigned int mode,
        int ret;
 
        va_start(args, format);
-       ret = vprint_to_buffer(stream, priority, mode, sz, format, args);
+       ret = vprint_to_buffer(stream, 0, priority, mode, sz, format, args);
        va_end(args);
 
        return ret;
@@ -234,10 +253,20 @@ static int print_to_buffer(FILE *stream, int priority, 
unsigned int mode,
 
 int rt_vfprintf(FILE *stream, const char *format, va_list args)
 {
-       return vprint_to_buffer(stream, 0,
+       return vprint_to_buffer(stream, 0, 0,
                                RT_PRINT_MODE_FORMAT, 0, format, args);
 }
 
+#ifdef CONFIG_XENO_FORTIFY
+
+int __rt_vfprintf_chk(FILE *stream, int level, const char *fmt, va_list args)
+{
+       return vprint_to_buffer(stream, level + 1, 0,
+                               RT_PRINT_MODE_FORMAT, 0, fmt, args);
+}
+
+#endif
+
 int rt_vprintf(const char *format, va_list args)
 {
        return rt_vfprintf(stdout, format, args);
@@ -312,17 +341,27 @@ void rt_syslog(int priority, const char *format, ...)
        va_list args;
 
        va_start(args, format);
-       vprint_to_buffer(RT_PRINT_SYSLOG_STREAM, priority,
+       vprint_to_buffer(RT_PRINT_SYSLOG_STREAM, 0, priority,
                         RT_PRINT_MODE_FORMAT, 0, format, args);
        va_end(args);
 }
 
 void rt_vsyslog(int priority, const char *format, va_list args)
 {
-       vprint_to_buffer(RT_PRINT_SYSLOG_STREAM, priority,
+       vprint_to_buffer(RT_PRINT_SYSLOG_STREAM, 0, priority,
                         RT_PRINT_MODE_FORMAT, 0, format, args);
 }
 
+#ifdef CONFIG_XENO_FORTIFY
+
+void __rt_vsyslog_chk(int priority, int level, const char *fmt, va_list args)
+{
+       vprint_to_buffer(RT_PRINT_SYSLOG_STREAM, level + 1, priority,
+                        RT_PRINT_MODE_FORMAT, 0, fmt, args);
+}
+
+#endif
+
 static void set_buffer_name(struct print_buffer *buffer, const char *name)
 {
        int n;
@@ -681,7 +720,7 @@ void cobalt_print_init(void)
                errno = 0;
                default_buffer_size = strtol(value_str, NULL, 10);
                if (errno || default_buffer_size < RT_PRINT_LINE_BREAK) {
-                       __real_fprintf(stderr, "Invalid %s\n", 
RT_PRINT_BUFFER_ENV);
+                       __STD(fprintf(stderr, "Invalid %s\n", 
RT_PRINT_BUFFER_ENV));
                        exit(1);
                }
        }
@@ -692,7 +731,7 @@ void cobalt_print_init(void)
                errno = 0;
                period = strtoll(value_str, NULL, 10);
                if (errno) {
-                       __real_fprintf(stderr, "Invalid %s\n", 
RT_PRINT_PERIOD_ENV);
+                       __STD(fprintf(stderr, "Invalid %s\n", 
RT_PRINT_PERIOD_ENV));
                        exit(1);
                }
        }
@@ -710,8 +749,8 @@ void cobalt_print_init(void)
                        errno = 0;
                        buffers_count = strtoul(value_str, NULL, 0);
                        if (errno) {
-                               __real_fprintf(stderr, "Invalid %s\n",
-                                              RT_PRINT_BUFFERS_COUNT_ENV);
+                               __STD(fprintf(stderr, "Invalid %s\n",
+                                             RT_PRINT_BUFFERS_COUNT_ENV));
                                exit(1);
                        }
                }
@@ -723,8 +762,8 @@ void cobalt_print_init(void)
 
                pool_bitmap = malloc(pool_bitmap_len * sizeof(*pool_bitmap));
                if (!pool_bitmap) {
-                       __real_fprintf(stderr, "Error allocating rt_printf "
-                               "buffers\n");
+                       __STD(fprintf(stderr, "Error allocating rt_printf "
+                                     "buffers\n"));
                        exit(1);
                }
 
@@ -732,8 +771,8 @@ void cobalt_print_init(void)
                pool_len = buffers_count * pool_buf_size;
                pool_start = (unsigned long)malloc(pool_len);
                if (!pool_start) {
-                       __real_fprintf(stderr, "Error allocating rt_printf "
-                                      "buffers\n");
+                       __STD(fprintf(stderr, "Error allocating rt_printf "
+                                     "buffers\n"));
                        exit(1);
                }
 
@@ -783,13 +822,13 @@ COBALT_IMPL(int, vfprintf, (FILE *stream, const char 
*fmt, va_list args))
                return rt_vfprintf(stream, fmt, args);
        else {
                rt_print_flush_buffers();
-               return __real_vfprintf(stream, fmt, args);
+               return __STD(vfprintf(stream, fmt, args));
        }
 }
 
 COBALT_IMPL(int, vprintf, (const char *fmt, va_list args))
 {
-       return __wrap_vfprintf(stdout, fmt, args);
+       return __COBALT(vfprintf(stdout, fmt, args));
 }
 
 COBALT_IMPL(int, fprintf, (FILE *stream, const char *fmt, ...))
@@ -798,7 +837,7 @@ COBALT_IMPL(int, fprintf, (FILE *stream, const char *fmt, 
...))
        int rc;
 
        va_start(args, fmt);
-       rc = __wrap_vfprintf(stream, fmt, args);
+       rc = __COBALT(vfprintf(stream, fmt, args));
        va_end(args);
 
        return rc;
@@ -810,7 +849,7 @@ COBALT_IMPL(int, printf, (const char *fmt, ...))
        int rc;
 
        va_start(args, fmt);
-       rc = __wrap_vfprintf(stdout, fmt, args);
+       rc = __COBALT(vfprintf(stdout, fmt, args));
        va_end(args);
 
        return rc;
@@ -823,7 +862,7 @@ COBALT_IMPL(int, fputs, (const char *s, FILE *stream))
                return rt_fputs(s, stream);
        else {
                rt_print_flush_buffers();
-               return __real_fputs(s, stream);
+               return __STD(fputs(s, stream));
        }
 }
 
@@ -834,7 +873,7 @@ COBALT_IMPL(int, puts, (const char *s))
                return rt_puts(s);
        else {
                rt_print_flush_buffers();
-               return __real_puts(s);
+               return __STD(puts(s));
        }
 }
 
@@ -847,7 +886,7 @@ COBALT_IMPL(int, fputc, (int c, FILE *stream))
                return rt_fputc(c, stream);
        else {
                rt_print_flush_buffers();
-               return __real_fputc(c, stream);
+               return __STD(fputc(c, stream));
        }
 }
 
@@ -858,7 +897,7 @@ COBALT_IMPL(int, putchar, (int c))
                return rt_putchar(c);
        else {
                rt_print_flush_buffers();
-               return __real_putchar(c);
+               return __STD(putchar(c));
        }
 }
 
@@ -883,7 +922,7 @@ COBALT_IMPL(size_t, fwrite, (const void *ptr, size_t size, 
size_t nmemb, FILE *s
                return rt_fwrite(ptr, size, nmemb, stream);
        else {
                rt_print_flush_buffers();
-               return __real_fwrite(ptr, size, nmemb, stream);
+               return __STD(fwrite(ptr, size, nmemb, stream));
        }
 
 }
@@ -895,7 +934,7 @@ COBALT_IMPL(void, vsyslog, (int priority, const char *fmt, 
va_list ap))
                return rt_vsyslog(priority, fmt, ap);
        else {
                rt_print_flush_buffers();
-               __real_vsyslog(priority, fmt, ap);
+               __STD(vsyslog(priority, fmt, ap));
        }
 }
 
@@ -904,6 +943,85 @@ COBALT_IMPL(void, syslog, (int priority, const char *fmt, 
...))
        va_list args;
 
        va_start(args, fmt);
-       __wrap_vsyslog(priority, fmt, args);
+       __COBALT(vsyslog(priority, fmt, args));
+       va_end(args);
+}
+
+/* 
+ * Checked versions for -D_FORTIFY_SOURCE
+ */
+COBALT_IMPL(int, __vfprintf_chk, (FILE *f, int flag, const char *fmt, va_list 
ap))
+{
+#ifdef CONFIG_XENO_FORTIFY
+       if (xeno_get_current() != XN_NO_HANDLE &&
+           !(xeno_get_current_mode() & XNRELAX))
+               return __rt_vfprintf_chk(f, flag, fmt, ap);
+       else {
+               rt_print_flush_buffers();
+               return __STD(__vfprintf_chk(f, flag, fmt, ap));
+       }
+#else
+       __STD(fprintf(stderr, 
+                     "Xenomai has to be compiled with --enable-fortify "
+                     "to support applications\ncompiled with "
+                     "-D_FORTIFY_SOURCE\n"));
+       exit(EXIT_FAILURE);
+#endif
+}
+
+COBALT_IMPL(int, __vprintf_chk, (int flag, const char *fmt, va_list ap))
+{
+       return __COBALT(__vfprintf_chk(stdout, flag, fmt, ap));
+}
+
+COBALT_IMPL(int, __fprintf_chk, (FILE *f, int flag, const char *fmt, ...))
+{
+       va_list args;
+       int ret;
+
+       va_start(args, fmt);
+       ret = __COBALT(__vfprintf_chk(f, flag, fmt, args));
+       va_end(args);
+
+       return ret;
+}
+
+COBALT_IMPL(int, __printf_chk, (int flag, const char *fmt, ...))
+{
+       va_list args;
+       int ret;
+
+       va_start(args, fmt);
+       ret = __COBALT(__vprintf_chk(flag, fmt, args));
+       va_end(args);
+
+       return ret;
+}
+
+COBALT_IMPL(void, __vsyslog_chk, (int pri, int flag, const char *fmt, va_list 
ap))
+{
+#ifdef CONFIG_XENO_FORTIFY
+       if (xeno_get_current() != XN_NO_HANDLE &&
+            !(xeno_get_current_mode() & XNRELAX))
+               return __rt_vsyslog_chk(pri, flag, fmt, ap);
+       else {
+               rt_print_flush_buffers();
+               __STD(__vsyslog_chk(pri, flag, fmt, ap));
+       }
+#else
+       __STD(fprintf(stderr, 
+                     "Xenomai needs to be compiled with --enable-fortify "
+                     "to support applications\ncompiled with "
+                     "-D_FORTIFY_SOURCE\n"));
+       exit(EXIT_FAILURE);
+#endif
+}
+
+COBALT_IMPL(void, __syslog_chk, (int pri, int flag, const char *fmt, ...))
+{
+       va_list args;
+
+       va_start(args, fmt);
+       __COBALT(__vsyslog_chk(pri, flag, fmt, args));
        va_end(args);
 }
diff --git a/lib/cobalt/wrappers.c b/lib/cobalt/wrappers.c
index d8dfacd..d322068 100644
--- a/lib/cobalt/wrappers.c
+++ b/lib/cobalt/wrappers.c
@@ -308,6 +308,24 @@ int __real_printf(const char *fmt, ...)
        return rc;
 }
 
+#ifdef CONFIG_XENO_FORTIFY
+
+__attribute__ ((weak))
+int __real___vfprintf_chk(FILE *stream, int level, const char *fmt, va_list ap)
+{
+       return __vfprintf_chk(stream, level, fmt, ap);
+}
+
+__attribute__ ((weak))
+void __real___vsyslog_chk(int priority, int level, const char *fmt, va_list ap)
+{
+       extern void __vsyslog_chk(int, int, const char *, va_list);
+
+       __vsyslog_chk(priority, level, fmt, ap);
+}
+
+#endif
+
 __attribute__ ((weak))
 int __real_puts(const char *s)
 {


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to