Changeset d5eac12 in rtems-libbsd


Ignore:
Timestamp:
10/09/14 12:34:13 (8 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, 5, 5-freebsd-12, 6-freebsd-12, freebsd-9.3, master
Children:
43dc972
Parents:
403d0b8
git-author:
Sebastian Huber <sebastian.huber@…> (10/09/14 12:34:13)
git-committer:
Sebastian Huber <sebastian.huber@…> (10/09/14 12:56:29)
Message:

SYSLOG(3): Replace implementation

Avoid potential buffer overflows on the stack. Expand the %m in the
format string.

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • rtemsbsd/rtems/syslog.c

    r403d0b8 rd5eac12  
    1 /*
    2  * RTEMS version of syslog and associated routines
     1/**
     2 * @file
     3 *
     4 * @ingroup rtems_bsd_rtems
     5 *
     6 * @brief TODO.
    37 */
    48
    5 #ifdef HAVE_CONFIG_H
    6 #include "config.h"
    7 #endif
     9/*
     10 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
     11 *
     12 *  embedded brains GmbH
     13 *  Dornierstr. 4
     14 *  82178 Puchheim
     15 *  Germany
     16 *  <rtems@embedded-brains.de>
     17 *
     18 * Redistribution and use in source and binary forms, with or without
     19 * modification, are permitted provided that the following conditions
     20 * are met:
     21 * 1. Redistributions of source code must retain the above copyright
     22 *    notice, this list of conditions and the following disclaimer.
     23 * 2. Redistributions in binary form must reproduce the above copyright
     24 *    notice, this list of conditions and the following disclaimer in the
     25 *    documentation and/or other materials provided with the distribution.
     26 *
     27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     37 * SUCH DAMAGE.
     38 */
    839
    9 #include <rtems.h>
     40#include <machine/rtems-bsd-user-space.h>
     41#include <machine/rtems-bsd-program.h>
     42
     43#include <syslog.h>
     44#include <errno.h>
    1045#include <stdio.h>
    11 #include <stdarg.h>
    12 #include <errno.h>
    13 #include <syslog.h>
    14 #include <rtems/bsd/sys/types.h>
    15 #include <sys/socket.h>
    16 #include <netinet/in.h>
    1746#include <string.h>
    1847
    19 #include <unistd.h>
     48typedef struct {
     49  int mask;
     50} rtems_bsd_syslog_context;
    2051
    21 #include <machine/rtems-bsd-printf-to-iprintf.h>
     52/* FIXME: This should be thread specific */
     53static rtems_bsd_syslog_context rtems_bsd_syslog_instance = {
     54        .mask = LOG_UPTO(LOG_DEBUG)
     55};
    2256
    23 static int LogStatus = LOG_CONS;
    24 static const char *LogTag = "syslog";
    25 static int LogFacility = LOG_USER;
    26 static int LogMask = 0xff;
     57static const char * const rtems_bsd_syslog_priorities[] = {
     58        [LOG_EMERG] = "emerg",
     59        [LOG_ALERT] = "alert",
     60        [LOG_CRIT] = "crit",
     61        [LOG_ERR] = "err",
     62        [LOG_WARNING] = "warning",
     63        [LOG_NOTICE] = "notice",
     64        [LOG_INFO] = "info",
     65        [LOG_DEBUG] = "debug"
     66};
    2767
    28 static int LogFd = -1;
    29 static rtems_id LogSemaphore;
    30 extern struct in_addr rtems_bsdnet_log_host_address;
     68static rtems_bsd_syslog_context *
     69rtems_bsd_syslog_get_context(void)
     70{
     71        return &rtems_bsd_syslog_instance;
     72}
    3173
    32 #define SYSLOG_PORT     514
     74static void
     75rtems_bsd_syslog_format_buffer_overflow(void)
     76{
     77        fputs("err: syslog: format buffer overflow\n", stderr);
     78}
    3379
    3480void
    35 syslog (int pri, const char *fmt, ...)
     81syslog(int priority, const char *format, ...)
    3682{
    3783        va_list ap;
    3884
    39         va_start (ap, fmt);
    40         vsyslog (pri, fmt, ap);
    41         va_end (ap);
    42 }
    43 
    44 /*
    45  * FIXME: Should cbuf be static?  It could be if we put the mutex
    46  *        around the entire body of this routine.  Then we wouldn't
    47  *        have to worry about blowing stacks with a local variable
    48  *        that large.  Could make cbuf bigger, too.
    49  */
    50 void
    51 vsyslog (int pri, const char *fmt, va_list ap)
    52 {
    53         int cnt;
    54         char *cp;
    55         char *msgp, cbuf[200];
    56         int sent;
    57 
    58         if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
    59                 syslog (LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID,
    60                                                                 "syslog: unknown facility/priority: %#x", pri);
    61                 pri &= LOG_PRIMASK|LOG_FACMASK;
    62         }
    63 
    64         if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
    65                 return;
    66 
    67         if ((pri & LOG_FACMASK) == 0)
    68                 pri |= LogFacility;
    69 
    70         cnt = sprintf (cbuf, "<%d>", pri);
    71         cp = msgp = cbuf + cnt;
    72         if (LogTag) {
    73                 const char *lp = LogTag;
    74                 while ((*cp = *lp++) != '\0')
    75                         cp++;
    76         }
    77         if (LogStatus & LOG_PID) {
    78                 rtems_id tid;
    79                 rtems_task_ident (RTEMS_SELF, 0, &tid);
    80                 cnt = sprintf (cp, "[%#lx]", (unsigned long)tid);
    81                 cp += cnt;
    82         }
    83         if (LogTag) {
    84                 *cp++ = ':';
    85                 *cp++ = ' ';
    86         }
    87         cnt = vsprintf (cp, fmt, ap);
    88         cnt += cp - cbuf;
    89         if (cbuf[cnt-1] == '\n')
    90                 cbuf[--cnt] = '\0';
    91 
    92         if (LogStatus & LOG_PERROR)
    93                 printf ("%s\n", cbuf);
    94 
    95         /*
    96          * Grab the mutex
    97          */
    98         sent = 0;
    99         if ((rtems_bsdnet_log_host_address.s_addr != INADDR_ANY)
    100          && (LogFd >= 0)
    101          && (rtems_semaphore_obtain (LogSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL)) {
    102                 /*
    103                  * Set the destination address/port
    104                  */
    105                 struct sockaddr_in farAddress;
    106                 farAddress.sin_family = AF_INET;
    107                 farAddress.sin_port = htons (SYSLOG_PORT);
    108                 farAddress.sin_addr = rtems_bsdnet_log_host_address;
    109                 memset (farAddress.sin_zero, '\0', sizeof farAddress.sin_zero);
    110 
    111                 /*
    112                  * Send the message
    113                  */
    114                 if (sendto (LogFd, cbuf, cnt, 0, (struct sockaddr *)&farAddress, sizeof farAddress) >= 0)
    115                         sent = 1;
    116                 rtems_semaphore_release (LogSemaphore);
    117         }
    118         if (!sent && (LogStatus & LOG_CONS) && !(LogStatus & LOG_PERROR))
    119                 printf ("%s\n", msgp);
     85        va_start(ap, format);
     86        vsyslog(priority, format, ap);
     87        va_end(ap);
    12088}
    12189
    12290void
    123 openlog (const char *ident, int logstat, int logfac)
     91vsyslog(int priority, const char *format, va_list ap)
    12492{
    125         rtems_status_code sc;
    126         struct sockaddr_in myAddress;
     93        rtems_bsd_syslog_context *ctx = rtems_bsd_syslog_get_context();
     94        int pri = LOG_PRI(priority);
     95        char fmt[128];
     96        char buf[128];
     97        const char *src;
     98        char *dst;
     99        size_t rem;
     100        char *m;
     101        int n;
     102        size_t len;
    127103
    128         if (ident != NULL)
    129                 LogTag = ident;
    130         LogStatus = logstat;
    131         if (logfac != 0 && (logfac & ~LOG_FACMASK) == 0)
    132                 LogFacility = logfac;
    133 
    134         /*
    135          * Create the socket
    136          */
    137         if ((LogFd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
    138                 printf ("Can't create syslog socket: %d\n", errno);
     104        if ((LOG_MASK(pri) & ctx->mask) == 0) {
    139105                return;
    140106        }
    141107
    142         /*
    143          * Bind socket to name
    144          */
    145         myAddress.sin_family = AF_INET;
    146         myAddress.sin_addr.s_addr = INADDR_ANY;
    147         myAddress.sin_port = 0;
    148         memset (myAddress.sin_zero, '\0', sizeof myAddress.sin_zero);
    149         if (bind (LogFd, (struct sockaddr *)&myAddress, sizeof (myAddress)) < 0) {
    150                 close (LogFd);
    151                 LogFd = -1;
    152                 printf ("Can't bind syslog socket: %d\n", errno);
     108        /* Expand the %m in the format string and add a newline character */
     109
     110        src = format;
     111        dst = &fmt[0];
     112        rem = sizeof(fmt) - 2;
     113
     114        while ((m = strstr(src, "%m")) != NULL) {
     115                size_t c = m - src;
     116
     117                if (c > rem) {
     118                        rtems_bsd_syslog_format_buffer_overflow();
     119                        return;
     120                }
     121
     122                memcpy(dst, src, c);
     123                dst += c;
     124                src += c + 2;
     125                rem -= c;
     126
     127                n = sniprintf(dst, rem, "%s", strerror(errno));
     128                if (n > rem || n < 0) {
     129                        rtems_bsd_syslog_format_buffer_overflow();
     130                        return;
     131                }
     132
     133                dst += (size_t) n;
     134                rem -= (size_t) n;
     135        }
     136
     137        len = strlen(src);
     138        if (len > rem) {
     139                rtems_bsd_syslog_format_buffer_overflow();
    153140                return;
    154141        }
    155142
    156         /*
    157          * Create the mutex
    158          */
    159         sc = rtems_semaphore_create (rtems_build_name('s', 'L', 'o', 'g'),
    160                                         1,
    161                                         RTEMS_PRIORITY |
    162                                                 RTEMS_BINARY_SEMAPHORE |
    163                                                 RTEMS_INHERIT_PRIORITY |
    164                                                 RTEMS_NO_PRIORITY_CEILING |
    165                                                 RTEMS_LOCAL,
    166                                         0,
    167                                         &LogSemaphore);
    168         if (sc != RTEMS_SUCCESSFUL) {
    169                 printf ("Can't create syslog semaphore: %d\n", sc);
    170                 close (LogFd);
    171                 LogFd = -1;
     143        memcpy(dst, src, len);
     144        dst += len;
     145        dst[0] = '\n';
     146        dst[1] = '\0';
     147
     148        /* Print into buffer */
     149
     150        dst = &buf[0];
     151        rem = sizeof(buf) - 1;
     152
     153        n = sniprintf(dst, rem, "%s: ", rtems_bsd_syslog_priorities[pri]);
     154        if (n <= rem) {
     155                dst += (size_t) n;
     156                rem -= (size_t) n;
    172157        }
     158
     159        n = sniprintf(dst, rem, "%s: ", rtems_bsd_program_get_name());
     160        if (n <= rem) {
     161                dst += (size_t) n;
     162                rem -= (size_t) n;
     163        }
     164
     165        vsniprintf(dst, rem, &fmt[0], ap);
     166
     167        /* Write in one rush */
     168
     169        fputs(&buf[0], stderr);
     170}
     171
     172void
     173openlog(const char *ident, int option, int facility)
     174{
     175        /* TODO */
    173176}
    174177
     
    176179closelog(void)
    177180{
    178         if (LogFd >= 0) {
    179                 close (LogFd);
    180                 LogFd = -1;
    181                 rtems_semaphore_delete (LogSemaphore);
    182         }
     181        /* TODO */
    183182}
    184183
    185184int
    186 setlogmask (int pmask)
     185setlogmask(int mask)
    187186{
    188         int omask;
     187        rtems_bsd_syslog_context *ctx = rtems_bsd_syslog_get_context();
     188        int cur = ctx->mask;
    189189
    190         omask = LogMask;
    191         if (pmask != 0)
    192                 LogMask = pmask;
    193         return (omask);
     190        ctx->mask = mask & LOG_UPTO(LOG_DEBUG);
     191
     192        return cur;
    194193}
  • testsuite/syscalls01/test_main.c

    r403d0b8 rd5eac12  
    5151#include <string.h>
    5252#include <unistd.h>
     53#include <syslog.h>
    5354
    5455#define RTEMS_BSD_PROGRAM_NO_EXIT_WRAP
     
    16931694
    16941695static void
     1696test_syslog(void)
     1697{
     1698        puts("test syslog");
     1699
     1700        errno = 0;
     1701        syslog(LOG_ERR, "%m");
     1702        syslog(LOG_ERR, "b%m");
     1703        syslog(LOG_ERR, "%me");
     1704        errno = ENXIO;
     1705        syslog(LOG_ERR, "<%m><%m><%m>");
     1706        syslog(LOG_INFO, "%m%m%m%m%m%m%m%m%m%m%m%m%m%m");
     1707        syslog(LOG_EMERG, "emerg");
     1708        syslog(LOG_ALERT, "alert");
     1709        syslog(LOG_CRIT, "crit");
     1710        syslog(LOG_ERR, "err");
     1711        syslog(LOG_WARNING, "warning");
     1712        syslog(LOG_NOTICE, "notice");
     1713        syslog(LOG_INFO, "info");
     1714        syslog(LOG_DEBUG, "debug");
     1715}
     1716
     1717static void
    16951718test_main(void)
    16961719{
     
    17211744        test_warn();
    17221745        test_err();
     1746        test_syslog();
    17231747
    17241748        exit(0);
Note: See TracChangeset for help on using the changeset viewer.