"Fossies" - the Fresh Open Source Software Archive

Member "libsafe-2.0-16/src/intercept.c" (31 May 2002, 42342 Bytes) of package /linux/misc/old/libsafe-2.0-16.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #ident "$Name: release2_0-16 $"
    2 #ident "$Id: intercept.c,v 1.40 2002/05/31 17:37:34 ttsai Exp $"
    3 
    4 
    5 /*
    6  * Copyright (C) 2002 Avaya Labs, Avaya Inc.
    7  * Copyright (C) 1999 Bell Labs, Lucent Technologies.
    8  * Copyright (C) Arash Baratloo, Timothy Tsai, Navjot Singh, and Hamilton Slye.
    9  *
   10  * This file is part of the Libsafe library.
   11  * Libsafe version 2.x: protecting against stack smashing attacks.
   12  *
   13  * This library is free software; you can redistribute it and/or
   14  * modify it under the terms of the GNU Lesser General Public
   15  * License as published by the Free Software Foundation; either
   16  * version 2.1 of the License, or (at your option) any later version.
   17  *
   18  * This library is distributed in the hope that it will be useful,
   19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   21  * Lesser General Public License for more details.
   22  *
   23  * You should have received a copy of the GNU Lesser General Public
   24  * License along with this library; if not, write to the Free Software
   25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   26  * For more information, 
   27  *
   28  *   visit http://www.research.avayalabs.com/project/libsafe/index.html
   29  *   or email libsafe@research.avayalabs.com
   30  */
   31 
   32 /* 
   33  * unsafe functions that are supported:
   34  *              strcpy(3), strcat(3), sprintf(3), vsprintf(3),
   35  *              getwd(3), gets(3), realpath(3),
   36  *              fscanf(3), scanf(3), sscanf(3)
   37  * safe but supported (as we must): 
   38  *              memcpy(3)
   39  * might be problematic, but I can't figure out why:
   40  *              getopt(3), getpass(3), index(3), streadd(?) 
   41  */
   42 
   43 #include <stdio.h>      /* defines stdin */
   44 #include <stdarg.h>     /* defines va_args */
   45 #define __NO_STRING_INLINES 1   /* stops the inline expansion of strcpy() */
   46 #define __USE_GNU 1     /* defines strnlen() */
   47 #include <string.h>     /* defines strncat() */
   48 #include <unistd.h>     /* defines getcwd(), readlink() */
   49 #include <sys/param.h>      /* MAXPATHLEN for realpath() */
   50 #include <limits.h>     /* PATH_MAX for getwd(); actually in */
   51                 /*     linux/limits.h */
   52 #include <pwd.h>        /* defines getpass() */
   53 #include <errno.h>      /* defines errno */
   54 #include <dlfcn.h>      /* defines dlsym() */
   55 #include <wchar.h>      /* for the wide-char functions */
   56 #include <ctype.h>      /* for the isdigit() */
   57 #include "util.h"
   58 #include "log.h"
   59 
   60 /*
   61  * -----------------------------------------------------------------
   62  * ----------------- system library protocols ----------------------
   63  */
   64 typedef void *(*memcpy_t) (void *dest, const void *src, size_t n);
   65 typedef char *(*strcpy_t) (char *dest, const char *src);
   66 typedef char *(*strncpy_t) (char *dest, const char *src, size_t n);
   67 typedef wchar_t *(*wcscpy_t) (wchar_t *dest, const wchar_t *src);
   68 typedef char *(*stpcpy_t) (char *dest, const char *src);
   69 typedef wchar_t *(*wcpcpy_t) (wchar_t *dest, const wchar_t *src);
   70 typedef char *(*strcat_t) (char *dest, const char *src);
   71 typedef char *(*strncat_t) (char *dest, const char *src, size_t n);
   72 typedef wchar_t *(*wcscat_t) (wchar_t *dest, const wchar_t *src);
   73 typedef int (*vsprintf_t) (char *str, const char *format, va_list ap);
   74 typedef int (*vsnprintf_t) (char *str, size_t size, const char *format, va_list
   75     ap);
   76 typedef int (*vprintf_t) (const char *format, va_list ap);
   77 typedef int (*vfprintf_t) (FILE *fp, const char *format, va_list ap);
   78 typedef char *(*getwd_t) (char *buf);
   79 typedef char *(*gets_t) (char *s);
   80 typedef char *(*realpath_t) (char *path, char resolved_path[]);
   81 typedef int (*_IO_vfscanf_t) (_IO_FILE *s, const char *format, _IO_va_list
   82     argptr, int *errp);
   83 
   84 
   85 
   86 /*
   87  * 0 = don't do any libsafe checking for this process
   88  * 1 = enable libsafe checking for this process
   89  */
   90 int _libsafe_exclude = 0;
   91 
   92 
   93 /*
   94  * -----------------------------------------------------------------
   95  * ------------------- utility functions ---------------------------
   96  */
   97 #ifndef __USE_GNU
   98 inline size_t strnlen(const char *s, size_t count)
   99 {
  100     register int __res;
  101     __asm__ __volatile__("movl %1,%0\n\t"
  102              "jmp 2f\n"
  103              "1:\tcmpb $0,(%0)\n\t"
  104              "je 3f\n\t"
  105              "incl %0\n"
  106              "2:\tdecl %2\n\t"
  107              "cmpl $-1,%2\n\t"
  108              "jne 1b\n" "3:\tsubl %1,%0":"=a"(__res)
  109              :"c"(s), "d"(count)
  110              :"dx");
  111     return __res;
  112 }
  113 #endif
  114 
  115 /*
  116  * returns a pointer to the implementation of 'funcName' in
  117  * the libc library.  If not found, terminates the program.
  118  */
  119 static void *getLibraryFunction(const char *funcName)
  120 {
  121     void *res;
  122 
  123     if ((res = dlsym(RTLD_NEXT, funcName)) == NULL) {
  124     fprintf(stderr, "dlsym %s error:%s\n", funcName, dlerror());
  125     _exit(1);
  126     }
  127     return res;
  128 }
  129 
  130 
  131 /* Starting with version 2.0, we keep a single global copy of the pointer to
  132  * the real memcpy() function.  This allows us to call
  133  * getLibraryFunction("memcpy") just once instead of multiple times, since
  134  * memcpy() is needed in four different functions below.
  135  */
  136 static memcpy_t real_memcpy = NULL;
  137 
  138 
  139 /*
  140  * -------------- system library implementations -------------------
  141  * Here is the story: if a C source file includes <string.h> and is
  142  * compiled with -O, then by default strcpy() is expanded (to several
  143  * memcpy()'s and a strcpy()) just like a macro.  Thus, it is wise to
  144  * bounds-check memcpy().  Furthermore, because the string "strcpy(,)"
  145  * gets expanded even when the function is being declared, this code
  146  * will not compile if optimized unless __NO_STRING_INLINES is defined
  147  * (see the end of /usr/include/string.h).  This is obviously a
  148  * compiler/header-file specific thing.  I am using gcc version
  149  * egcs-2.91.66.
  150  */
  151 char *strcpy(char *dest, const char *src)
  152 {
  153     static strcpy_t real_strcpy = NULL;
  154     size_t max_size, len;
  155 
  156     if (!real_memcpy)
  157     real_memcpy = (memcpy_t) getLibraryFunction("memcpy");
  158     if (!real_strcpy)
  159     real_strcpy = (strcpy_t) getLibraryFunction("strcpy");
  160 
  161     if (_libsafe_exclude)
  162     return real_strcpy(dest, src);
  163 
  164     if ((max_size = _libsafe_stackVariableP(dest)) == 0) {
  165     LOG(5, "strcpy(<heap var> , <src>)\n");
  166     return real_strcpy(dest, src);
  167     }
  168 
  169     LOG(4, "strcpy(<stack var> , <src>) stack limit=%d)\n", max_size);
  170     /*
  171      * Note: we can't use the standard strncpy()!  From the strncpy(3) manual
  172      * pages: In the case where the length of 'src' is less than that of
  173      * 'max_size', the remainder of 'dest' will be padded with nulls.  We do
  174      * not want null written all over the 'dest', hence, our own
  175      * implementation.
  176      */
  177     if ((len = strnlen(src, max_size)) == max_size)
  178     _libsafe_die("Overflow caused by strcpy()");
  179     real_memcpy(dest, src, len + 1);
  180     return dest;
  181 }
  182 
  183 char *strncpy(char *dest, const char *src, size_t n)
  184 {
  185     static strncpy_t real_strncpy = NULL;
  186     size_t max_size, len;
  187 
  188     if (!real_strncpy)
  189     real_strncpy = (strncpy_t) getLibraryFunction("strncpy");
  190 
  191     if (_libsafe_exclude)
  192     return real_strncpy(dest, src, n);
  193 
  194     if ((max_size = _libsafe_stackVariableP(dest)) == 0) {
  195     LOG(5, "strncpy(<heap var> , <src>)\n");
  196     return real_strncpy(dest, src, n);
  197     }
  198 
  199     LOG(4, "strncpy(<stack var> , <src>) stack limit=%d)\n", max_size);
  200 
  201     if (n > max_size && (len = strnlen(src, max_size)) == max_size)
  202     _libsafe_die("Overflow caused by strncpy()");
  203 
  204     return real_strncpy(dest, src, n);
  205 }
  206 
  207 char *stpcpy(char *dest, const char *src)
  208 {
  209     static stpcpy_t real_stpcpy = NULL;
  210     size_t max_size, len;
  211 
  212     if (!real_memcpy)
  213     real_memcpy = (memcpy_t) getLibraryFunction("memcpy");
  214     if (!real_stpcpy)
  215     real_stpcpy = (stpcpy_t) getLibraryFunction("stpcpy");
  216 
  217     if (_libsafe_exclude)
  218     return real_stpcpy(dest, src);
  219 
  220     if ((max_size = _libsafe_stackVariableP(dest)) == 0) {
  221     LOG(5, "stpcpy(<heap var> , <src>)\n");
  222     return real_stpcpy(dest, src);
  223     }
  224 
  225     LOG(4, "stpcpy(<stack var> , <src>) stack limit=%d)\n", max_size);
  226     /*
  227      * Note: we can't use the standard strncpy()!  From the strncpy(3) manual
  228      * pages: In the case where the length of 'src' is less than that of
  229      * 'max_size', the remainder of 'dest' will be padded with nulls.  We do
  230      * not want null written all over the 'dest', hence, our own
  231      * implementation.
  232      */
  233     if ((len = strnlen(src, max_size)) == max_size)
  234     _libsafe_die("Overflow caused by stpcpy()");
  235     real_memcpy(dest, src, len + 1);
  236     return dest + len;
  237 }
  238 
  239 #ifndef MISSING_WCSNLEN
  240 wchar_t *wcscpy(wchar_t *dest, const wchar_t *src)
  241 {
  242     static wcscpy_t real_wcscpy = NULL;
  243     size_t max_bytes, max_wchars, len;
  244 
  245     if (!real_wcscpy)
  246     real_wcscpy = (wcscpy_t) getLibraryFunction("wcscpy");
  247 
  248     if (_libsafe_exclude)
  249     return real_wcscpy(dest, src);
  250 
  251     if ((max_bytes = _libsafe_stackVariableP(dest)) == 0) {
  252     LOG(5, "strcpy(<heap var> , <src>)\n");
  253     return real_wcscpy(dest, src);
  254     }
  255 
  256     LOG(4, "wcscpy(<stack var> , <src>) stack limit=%d)\n", max_bytes);
  257     /*
  258      * Note: we can't use the standard wcsncpy()!  From the wcsncpy(3) manual
  259      * pages: "If the length wcslen(src) is smaller than n, the remaining wide
  260      * characters in the array pointed to by dest are filled with  L'\0'
  261      * characters."  We do not want null written all over the 'dest', hence,
  262      * our own implementation.
  263      */
  264     max_wchars = max_bytes / sizeof(wchar_t);
  265     if ((len = wcsnlen(src, max_wchars)) == max_wchars) {
  266     /*
  267      * If wcsnlen() returns max_wchars, it means that no L'\0' character was
  268      * found in the first max_wchars wide characters.  So, this
  269      * wide-character string won't fit in the stack frame.
  270      */
  271     _libsafe_die("Overflow caused by wcscpy()");
  272     }
  273 
  274     /*
  275      * Note that we can use wcscpy() directly since there is no memcpy()
  276      * optimization as in the case of strcpy().
  277      */
  278     return real_wcscpy(dest, src);
  279 }
  280 
  281 wchar_t *wcpcpy(wchar_t *dest, const wchar_t *src)
  282 {
  283     static wcpcpy_t real_wcpcpy = NULL;
  284     size_t max_bytes, max_wchars, len;
  285 
  286     if (!real_wcpcpy)
  287     real_wcpcpy = (wcpcpy_t) getLibraryFunction("wcpcpy");
  288 
  289     if (_libsafe_exclude)
  290     return real_wcpcpy(dest, src);
  291 
  292     if ((max_bytes = _libsafe_stackVariableP(dest)) == 0) {
  293     LOG(5, "strcpy(<heap var> , <src>)\n");
  294     return real_wcpcpy(dest, src);
  295     }
  296 
  297     LOG(4, "wcpcpy(<stack var> , <src>) stack limit=%d)\n", max_bytes);
  298     /*
  299      * Note: we can't use the standard wcsncpy()!  From the wcsncpy(3) manual
  300      * pages: "If the length wcslen(src) is smaller than n, the remaining wide
  301      * characters in the array pointed to by dest are filled with  L'\0'
  302      * characters."  We do not want null written all over the 'dest', hence,
  303      * our own implementation.
  304      */
  305     max_wchars = max_bytes / sizeof(wchar_t);
  306     if ((len = wcsnlen(src, max_wchars)) == max_wchars) {
  307     /*
  308      * If wcsnlen() returns max_wchars, it means that no L'\0' character was
  309      * found in the first max_wchars wide characters.  So, this
  310      * wide-character string won't fit in the stack frame.
  311      */
  312     _libsafe_die("Overflow caused by wcpcpy()");
  313     }
  314 
  315     /*
  316      * Note that we can use wcpcpy() directly since there is no memcpy()
  317      * optimization as in the case of strcpy().
  318      */
  319     return real_wcpcpy(dest, src);
  320 }
  321 #endif /* MISSING_WCSNLEN */
  322 
  323 /*
  324  * This is needed!  See the strcpy() for the reason. -ab.
  325  */
  326 void *memcpy(void *dest, const void *src, size_t n)
  327 {
  328     size_t max_size;
  329 
  330     if (!real_memcpy)
  331     real_memcpy = (memcpy_t) getLibraryFunction("memcpy");
  332 
  333     if (_libsafe_exclude)
  334     return real_memcpy(dest, src, n);
  335 
  336     if ((max_size = _libsafe_stackVariableP(dest)) == 0) {
  337     LOG(5, "memcpy(<heap var> , <src>, %d)\n", n);
  338     return real_memcpy(dest, src, n);
  339     }
  340 
  341     LOG(4, "memcpy(<stack var> , <src>, %d) stack limit=%d)\n", n, max_size);
  342     if (n > max_size)
  343     _libsafe_die("Overflow caused by memcpy()");
  344     return real_memcpy(dest, src, n);
  345 }
  346 
  347 
  348 char *strcat(char *dest, const char *src)
  349 {
  350     static strcat_t real_strcat = NULL;
  351     size_t max_size;
  352     uint dest_len, src_len;
  353 
  354     if (!real_memcpy)
  355     real_memcpy = (memcpy_t) getLibraryFunction("memcpy");
  356     if (!real_strcat)
  357     real_strcat = (strcat_t) getLibraryFunction("strcat");
  358 
  359     if (_libsafe_exclude)
  360     return real_strcat(dest, src);
  361 
  362     if ((max_size = _libsafe_stackVariableP(dest)) == 0) {
  363     LOG(5, "strcat(<heap var> , <src>)\n");
  364     return real_strcat(dest, src);
  365     }
  366 
  367     LOG(4, "strcat(<stack var> , <src>) stack limit=%d\n", max_size);
  368     dest_len = strnlen(dest, max_size);
  369     src_len = strnlen(src, max_size);
  370 
  371     if (dest_len + src_len >= max_size)
  372     _libsafe_die("Overflow caused by strcat()");
  373 
  374     real_memcpy(dest + dest_len, src, src_len + 1);
  375 
  376     return dest;
  377 }
  378 
  379 
  380 char *strncat(char *dest, const char *src, size_t n)
  381 {
  382     static strncat_t real_strncat = NULL;
  383     size_t max_size;
  384     uint dest_len, src_len;
  385 
  386     if (!real_strncat)
  387     real_strncat = (strncat_t) getLibraryFunction("strncat");
  388 
  389     if (_libsafe_exclude)
  390     return real_strncat(dest, src, n);
  391 
  392     if ((max_size = _libsafe_stackVariableP(dest)) == 0) {
  393     LOG(5, "strncat(<heap var> , <src>)\n");
  394     return real_strncat(dest, src, n);
  395     }
  396 
  397     LOG(4, "strncat(<stack var> , <src>) stack limit=%d\n", max_size);
  398     dest_len = strnlen(dest, max_size);
  399     src_len = strnlen(src, max_size);
  400 
  401     if (dest_len + n > max_size && dest_len + src_len >= max_size)
  402     _libsafe_die("Overflow caused by strncat()");
  403 
  404     return real_strncat(dest, src, n);
  405 }
  406 
  407 
  408 #ifndef MISSING_WCSNLEN
  409 wchar_t *wcscat(wchar_t *dest, const wchar_t *src)
  410 {
  411     static wcscat_t real_wcscat = NULL;
  412     size_t max_bytes;
  413     uint dest_len, src_len;
  414 
  415     if (!real_memcpy)
  416     real_memcpy = (memcpy_t) getLibraryFunction("memcpy");
  417     if (!real_wcscat)
  418     real_wcscat = (wcscat_t) getLibraryFunction("wcscat");
  419 
  420     if (_libsafe_exclude)
  421     return real_wcscat(dest, src);
  422 
  423     if ((max_bytes = _libsafe_stackVariableP(dest)) == 0) {
  424     LOG(5, "wcscat(<heap var> , <src>)\n");
  425     return real_wcscat(dest, src);
  426     }
  427 
  428     LOG(4, "wcscat(<stack var> , <src>) stack limit=%d\n", max_bytes);
  429     dest_len = wcsnlen(dest, max_bytes/sizeof(wchar_t));
  430     src_len = wcsnlen(src, max_bytes/sizeof(wchar_t));
  431 
  432     if (dest_len + src_len + 1 >= max_bytes/sizeof(wchar_t))
  433     _libsafe_die("Overflow caused by wcscat()");
  434 
  435     real_memcpy(dest + dest_len, src, src_len + 1);
  436 
  437     return dest;
  438 }
  439 #endif /* MISSING_WCSNLEN */
  440 
  441 
  442 /*
  443  * How deep can the stack be when _libsafe_save_ra_fp() is called?  We need to
  444  * save the return addresses and frame pointers for stack frame.  MAXLEVELS is
  445  * the size of the arrays to save these values, since we don't want to mess
  446  * around with malloc().
  447  */
  448 #define MAXLEVELS   1000
  449 
  450 
  451 /*
  452  * The following table is used in vfprintf() and _IO_vfprintf() to estimate how
  453  * many conversion specifiers exist.  A 1 means that the character is a valid
  454  * modifier for a conversion.
  455  */
  456 static char is_printf_flag[] = {
  457     0,  /* 00    NUL '\0'       */
  458     0,  /* 01    SOH            */
  459     0,  /* 02    STX            */
  460     0,  /* 03    ETX            */
  461     0,  /* 04    EOT            */
  462     0,  /* 05    ENQ            */
  463     0,  /* 06    ACK            */
  464     0,  /* 07    BEL '\a'       */
  465     0,  /* 08    BS  '\b'       */
  466     0,  /* 09    HT  '\t'       */
  467     0,  /* 0A    LF  '\n'       */
  468     0,  /* 0B    VT  '\v'       */
  469     0,  /* 0C    FF  '\f'       */
  470     0,  /* 0D    CR  '\r'       */
  471     0,  /* 0E    SO             */
  472     0,  /* 0F    SI             */
  473     0,  /* 10    DLE            */
  474     0,  /* 11    DC1            */
  475     0,  /* 12    DC2            */
  476     0,  /* 13    DC3            */
  477     0,  /* 14    DC4            */
  478     0,  /* 15    NAK            */
  479     0,  /* 16    SYN            */
  480     0,  /* 17    ETB            */
  481     0,  /* 18    CAN            */
  482     0,  /* 19    EM             */
  483     0,  /* 1A    SUB            */
  484     0,  /* 1B    ESC            */
  485     0,  /* 1C    FS             */
  486     0,  /* 1D    GS             */
  487     0,  /* 1E    RS             */
  488     0,  /* 1F    US             */
  489     1,  /* 20    SPACE          */
  490     0,  /* 21    !              */
  491     0,  /* 22    "              */
  492     1,  /* 23    #              */
  493     0,  /* 24    $              */
  494     0,  /* 25    %              */
  495     0,  /* 26    &              */
  496     1,  /* 27    '              */
  497     0,  /* 28    (              */
  498     0,  /* 29    )              */
  499     0,  /* 2A    *              */
  500     1,  /* 2B    +              */
  501     0,  /* 2C    ,              */
  502     1,  /* 2D    -              */
  503     0,  /* 2E    .              */
  504     0,  /* 2F    /              */
  505     1,  /* 30    0              */
  506     0,  /* 31    1              */
  507     0,  /* 32    2              */
  508     0,  /* 33    3              */
  509     0,  /* 34    4              */
  510     0,  /* 35    5              */
  511     0,  /* 36    6              */
  512     0,  /* 37    7              */
  513     0,  /* 38    8              */
  514     0,  /* 39    9              */
  515     0,  /* 3A    :              */
  516     0,  /* 3B    ;              */
  517     0,  /* 3C    <              */
  518     0,  /* 3D    =              */
  519     0,  /* 3E    >              */
  520     0,  /* 3F    ?      */
  521     0,  /* 40    @@     */
  522     0,  /* 41    A      */
  523     0,  /* 42    B      */
  524     0,  /* 43    C      */
  525     0,  /* 44    D      */
  526     0,  /* 45    E      */
  527     0,  /* 46    F      */
  528     0,  /* 47    G      */
  529     0,  /* 48    H      */
  530     1,  /* 49    I      */
  531     0,  /* 4A    J      */
  532     0,  /* 4B    K      */
  533     0,  /* 4C    L      */
  534     0,  /* 4D    M      */
  535     0,  /* 4E    N      */
  536     0,  /* 4F    O      */
  537     0,  /* 50    P      */
  538     0,  /* 51    Q      */
  539     0,  /* 52    R      */
  540     0,  /* 53    S      */
  541     0,  /* 54    T      */
  542     0,  /* 55    U      */
  543     0,  /* 56    V      */
  544     0,  /* 57    W      */
  545     0,  /* 58    X      */
  546     0,  /* 59    Y      */
  547     0,  /* 5A    Z      */
  548     0,  /* 5B    [      */
  549     0,  /* 5C    \   '\\'   */
  550     0,  /* 5D    ]      */
  551     0,  /* 5E    ^      */
  552     0,  /* 5F    _      */
  553     0,  /* 60    `      */
  554     0,  /* 61    a      */
  555     0,  /* 62    b      */
  556     0,  /* 63    c      */
  557     0,  /* 64    d      */
  558     0,  /* 65    e      */
  559     0,  /* 66    f      */
  560     0,  /* 67    g      */
  561     0,  /* 68    h      */
  562     0,  /* 69    i      */
  563     0,  /* 6A    j      */
  564     0,  /* 6B    k      */
  565     0,  /* 6C    l      */
  566     0,  /* 6D    m      */
  567     0,  /* 6E    n      */
  568     0,  /* 6F    o      */
  569     0,  /* 70    p      */
  570     0,  /* 71    q      */
  571     0,  /* 72    r      */
  572     0,  /* 73    s      */
  573     0,  /* 74    t      */
  574     0,  /* 75    u      */
  575     0,  /* 76    v      */
  576     0,  /* 77    w      */
  577     0,  /* 78    x      */
  578     0,  /* 79    y      */
  579     0,  /* 7A    z      */
  580     0,  /* 7B    {      */
  581     0,  /* 7C    |      */
  582     0,  /* 7D    }      */
  583     0,  /* 7E    ~      */
  584     0,  /* 7F    DEL        */
  585 };
  586 
  587 /*
  588  * The following table is used in vfprintf() and _IO_vfprintf() to estimate how
  589  * many conversion specifiers exist.  A 1 means that the character is a valid
  590  * modifier for a conversion.
  591  */
  592 static char is_printf_lengthmod[] = {
  593     0,  /* 00    NUL '\0'       */
  594     0,  /* 01    SOH            */
  595     0,  /* 02    STX            */
  596     0,  /* 03    ETX            */
  597     0,  /* 04    EOT            */
  598     0,  /* 05    ENQ            */
  599     0,  /* 06    ACK            */
  600     0,  /* 07    BEL '\a'       */
  601     0,  /* 08    BS  '\b'       */
  602     0,  /* 09    HT  '\t'       */
  603     0,  /* 0A    LF  '\n'       */
  604     0,  /* 0B    VT  '\v'       */
  605     0,  /* 0C    FF  '\f'       */
  606     0,  /* 0D    CR  '\r'       */
  607     0,  /* 0E    SO             */
  608     0,  /* 0F    SI             */
  609     0,  /* 10    DLE            */
  610     0,  /* 11    DC1            */
  611     0,  /* 12    DC2            */
  612     0,  /* 13    DC3            */
  613     0,  /* 14    DC4            */
  614     0,  /* 15    NAK            */
  615     0,  /* 16    SYN            */
  616     0,  /* 17    ETB            */
  617     0,  /* 18    CAN            */
  618     0,  /* 19    EM             */
  619     0,  /* 1A    SUB            */
  620     0,  /* 1B    ESC            */
  621     0,  /* 1C    FS             */
  622     0,  /* 1D    GS             */
  623     0,  /* 1E    RS             */
  624     0,  /* 1F    US             */
  625     0,  /* 20    SPACE          */
  626     0,  /* 21    !              */
  627     0,  /* 22    "              */
  628     0,  /* 23    #              */
  629     0,  /* 24    $              */
  630     0,  /* 25    %              */
  631     0,  /* 26    &              */
  632     0,  /* 27    '              */
  633     0,  /* 28    (              */
  634     0,  /* 29    )              */
  635     0,  /* 2A    *              */
  636     0,  /* 2B    +              */
  637     0,  /* 2C    ,              */
  638     0,  /* 2D    -              */
  639     0,  /* 2E    .              */
  640     0,  /* 2F    /              */
  641     0,  /* 30    0              */
  642     0,  /* 31    1              */
  643     0,  /* 32    2              */
  644     0,  /* 33    3              */
  645     0,  /* 34    4              */
  646     0,  /* 35    5              */
  647     0,  /* 36    6              */
  648     0,  /* 37    7              */
  649     0,  /* 38    8              */
  650     0,  /* 39    9              */
  651     0,  /* 3A    :              */
  652     0,  /* 3B    ;              */
  653     0,  /* 3C    <              */
  654     0,  /* 3D    =              */
  655     0,  /* 3E    >              */
  656     0,  /* 3F    ?      */
  657     0,  /* 40    @@     */
  658     0,  /* 41    A      */
  659     0,  /* 42    B      */
  660     0,  /* 43    C      */
  661     0,  /* 44    D      */
  662     0,  /* 45    E      */
  663     0,  /* 46    F      */
  664     0,  /* 47    G      */
  665     0,  /* 48    H      */
  666     0,  /* 49    I      */
  667     0,  /* 4A    J      */
  668     0,  /* 4B    K      */
  669     1,  /* 4C    L      */
  670     0,  /* 4D    M      */
  671     0,  /* 4E    N      */
  672     0,  /* 4F    O      */
  673     0,  /* 50    P      */
  674     0,  /* 51    Q      */
  675     0,  /* 52    R      */
  676     0,  /* 53    S      */
  677     0,  /* 54    T      */
  678     0,  /* 55    U      */
  679     0,  /* 56    V      */
  680     0,  /* 57    W      */
  681     0,  /* 58    X      */
  682     0,  /* 59    Y      */
  683     0,  /* 5A    Z      */
  684     0,  /* 5B    [      */
  685     0,  /* 5C    \   '\\'   */
  686     0,  /* 5D    ]      */
  687     0,  /* 5E    ^      */
  688     0,  /* 5F    _      */
  689     0,  /* 60    `      */
  690     0,  /* 61    a      */
  691     0,  /* 62    b      */
  692     0,  /* 63    c      */
  693     0,  /* 64    d      */
  694     0,  /* 65    e      */
  695     0,  /* 66    f      */
  696     0,  /* 67    g      */
  697     1,  /* 68    h      */
  698     0,  /* 69    i      */
  699     1,  /* 6A    j      */
  700     0,  /* 6B    k      */
  701     1,  /* 6C    l      */
  702     0,  /* 6D    m      */
  703     0,  /* 6E    n      */
  704     0,  /* 6F    o      */
  705     0,  /* 70    p      */
  706     1,  /* 71    q      */
  707     0,  /* 72    r      */
  708     0,  /* 73    s      */
  709     1,  /* 74    t      */
  710     0,  /* 75    u      */
  711     0,  /* 76    v      */
  712     0,  /* 77    w      */
  713     0,  /* 78    x      */
  714     0,  /* 79    y      */
  715     1,  /* 7A    z      */
  716     0,  /* 7B    {      */
  717     0,  /* 7C    |      */
  718     0,  /* 7D    }      */
  719     0,  /* 7E    ~      */
  720     0,  /* 7F    DEL        */
  721 };
  722 
  723 /*
  724  * The following table is used in vfprintf() and _IO_vfprintf() to estimate how
  725  * many conversion specifiers exist.  A 1 means that the character is a valid
  726  * modifier for a conversion.
  727  */
  728 static char is_printf_convspec[] = {
  729     0,  /* 00    NUL '\0'       */
  730     0,  /* 01    SOH            */
  731     0,  /* 02    STX            */
  732     0,  /* 03    ETX            */
  733     0,  /* 04    EOT            */
  734     0,  /* 05    ENQ            */
  735     0,  /* 06    ACK            */
  736     0,  /* 07    BEL '\a'       */
  737     0,  /* 08    BS  '\b'       */
  738     0,  /* 09    HT  '\t'       */
  739     0,  /* 0A    LF  '\n'       */
  740     0,  /* 0B    VT  '\v'       */
  741     0,  /* 0C    FF  '\f'       */
  742     0,  /* 0D    CR  '\r'       */
  743     0,  /* 0E    SO             */
  744     0,  /* 0F    SI             */
  745     0,  /* 10    DLE            */
  746     0,  /* 11    DC1            */
  747     0,  /* 12    DC2            */
  748     0,  /* 13    DC3            */
  749     0,  /* 14    DC4            */
  750     0,  /* 15    NAK            */
  751     0,  /* 16    SYN            */
  752     0,  /* 17    ETB            */
  753     0,  /* 18    CAN            */
  754     0,  /* 19    EM             */
  755     0,  /* 1A    SUB            */
  756     0,  /* 1B    ESC            */
  757     0,  /* 1C    FS             */
  758     0,  /* 1D    GS             */
  759     0,  /* 1E    RS             */
  760     0,  /* 1F    US             */
  761     0,  /* 20    SPACE          */
  762     0,  /* 21    !              */
  763     0,  /* 22    "              */
  764     0,  /* 23    #              */
  765     0,  /* 24    $              */
  766     1,  /* 25    %              */
  767     0,  /* 26    &              */
  768     0,  /* 27    '              */
  769     0,  /* 28    (              */
  770     0,  /* 29    )              */
  771     0,  /* 2A    *              */
  772     0,  /* 2B    +              */
  773     0,  /* 2C    ,              */
  774     0,  /* 2D    -              */
  775     0,  /* 2E    .              */
  776     0,  /* 2F    /              */
  777     0,  /* 30    0              */
  778     0,  /* 31    1              */
  779     0,  /* 32    2              */
  780     0,  /* 33    3              */
  781     0,  /* 34    4              */
  782     0,  /* 35    5              */
  783     0,  /* 36    6              */
  784     0,  /* 37    7              */
  785     0,  /* 38    8              */
  786     0,  /* 39    9              */
  787     0,  /* 3A    :              */
  788     0,  /* 3B    ;              */
  789     0,  /* 3C    <              */
  790     0,  /* 3D    =              */
  791     0,  /* 3E    >              */
  792     0,  /* 3F    ?      */
  793     0,  /* 40    @@     */
  794     1,  /* 41    A      */
  795     0,  /* 42    B      */
  796     1,  /* 43    C      */
  797     0,  /* 44    D      */
  798     1,  /* 45    E      */
  799     1,  /* 46    F      */
  800     1,  /* 47    G      */
  801     0,  /* 48    H      */
  802     0,  /* 49    I      */
  803     0,  /* 4A    J      */
  804     0,  /* 4B    K      */
  805     0,  /* 4C    L      */
  806     0,  /* 4D    M      */
  807     0,  /* 4E    N      */
  808     0,  /* 4F    O      */
  809     0,  /* 50    P      */
  810     0,  /* 51    Q      */
  811     0,  /* 52    R      */
  812     1,  /* 53    S      */
  813     0,  /* 54    T      */
  814     0,  /* 55    U      */
  815     0,  /* 56    V      */
  816     0,  /* 57    W      */
  817     1,  /* 58    X      */
  818     0,  /* 59    Y      */
  819     0,  /* 5A    Z      */
  820     0,  /* 5B    [      */
  821     0,  /* 5C    \   '\\'   */
  822     0,  /* 5D    ]      */
  823     0,  /* 5E    ^      */
  824     0,  /* 5F    _      */
  825     0,  /* 60    `      */
  826     1,  /* 61    a      */
  827     0,  /* 62    b      */
  828     1,  /* 63    c      */
  829     1,  /* 64    d      */
  830     1,  /* 65    e      */
  831     1,  /* 66    f      */
  832     1,  /* 67    g      */
  833     0,  /* 68    h      */
  834     1,  /* 69    i      */
  835     0,  /* 6A    j      */
  836     0,  /* 6B    k      */
  837     0,  /* 6C    l      */
  838     0,  /* 6D    m      */
  839     1,  /* 6E    n      */
  840     1,  /* 6F    o      */
  841     1,  /* 70    p      */
  842     0,  /* 71    q      */
  843     0,  /* 72    r      */
  844     1,  /* 73    s      */
  845     0,  /* 74    t      */
  846     1,  /* 75    u      */
  847     0,  /* 76    v      */
  848     0,  /* 77    w      */
  849     1,  /* 78    x      */
  850     0,  /* 79    y      */
  851     0,  /* 7A    z      */
  852     0,  /* 7B    {      */
  853     0,  /* 7C    |      */
  854     0,  /* 7D    }      */
  855     0,  /* 7E    ~      */
  856     0,  /* 7F    DEL        */
  857 };
  858 
  859 /*
  860  * No variant of printf() can be called here!!!
  861  */
  862 int vfprintf(FILE *fp, const char *format, va_list ap)
  863 {
  864     static vfprintf_t real_vfprintf = NULL;
  865     int res;
  866     char *p, *pnum;
  867     int c = -1;     /* Next var arg to be used */
  868     int in_mth;     /* Are we currently looking for an m-th argument? */
  869     int atoi(const char *nptr);
  870 
  871     if (!real_vfprintf)
  872     real_vfprintf = (vfprintf_t) getLibraryFunction("vfprintf");
  873 
  874     if (_libsafe_exclude) {
  875     res = real_vfprintf(fp, format, ap);
  876     return res;
  877     }
  878 
  879     /*
  880      * Now check to see if there are any %n specifiers.  If %n specifiers
  881      * exist, then check the destination pointer to make sure it isn't a return
  882      * address or frame pointer.
  883      */
  884 
  885     /*
  886      * %[<value>][<flags>][<fieldwidth>][.<precision>][<lengthmod>]<convspec>
  887      *
  888      * <value> = <pnum>$
  889      * <flags> = # | 0 | - | <space> | + | ' | I
  890      *          NOTE: <flags> can be in any order and can be repeated
  891      * <fieldwidth> = <num> | *[<pnum>$]
  892      * <precision> = <num> | *[<pnum>$]
  893      * <lengthmod> = hh | h | l | ll | L | q | j | z | t
  894      * <convspec> = d | i | o | u | x | X | e | E | f | F | g | G | a | A | c |
  895      *          s | C | S | p | n | %
  896      *
  897      * <num> = any integer, including negative and zero integers; can have any
  898      *          number of leading '0'
  899      * <pnum> = positive integer; can have any number of leading '0'
  900      */
  901     for (p=(char*)format; *p; p++) {
  902     if (*p == '%') {
  903         /*
  904          * Check for [<value>].
  905          */
  906         pnum = NULL;
  907         for (p++,in_mth=0; *p && isdigit((int)*p); p++) {
  908         if (in_mth == 0)
  909             pnum = p;
  910         in_mth = 1;
  911         }
  912         if (*p == (char)NULL) break;
  913         if (in_mth) {
  914         if (*p == '$') {
  915             p++;
  916         }
  917         else {
  918             c++;
  919             p--;
  920             continue;
  921         }
  922         }
  923 
  924         /*
  925          * Check for [<flags>].
  926          */
  927         for (; *p && is_printf_flag[(int)*p]; p++);
  928         if (*p == (char)NULL) break;
  929 
  930         /*
  931          * Check for [<fieldwidth>].  Note that '-' is consumed previously.
  932          */
  933         if (*p == '*') {
  934         for (p++,in_mth=0; *p && isdigit((int)*p); p++)
  935             in_mth = 1;
  936         if (*p == (char)NULL) break;
  937         if (in_mth) {
  938             if (*p == '$') {
  939             p++;
  940             }
  941             else {
  942             c++;
  943             p--;
  944             continue;
  945             }
  946         }
  947         else {
  948             c++;
  949         }
  950         }
  951         else {
  952         for (; *p && isdigit((int)*p); p++);
  953         if (*p == (char)NULL) break;
  954         }
  955 
  956         /*
  957          * Check for [<precision>].
  958          */
  959         if (*p == '.') {
  960         p++;
  961         if (*p == '*') {
  962             for (p++,in_mth=0; *p && isdigit((int)*p); p++)
  963             in_mth = 1;
  964             if (*p == (char)NULL) break;
  965             if (in_mth) {
  966             if (*p == '$') {
  967                 p++;
  968             }
  969             else {
  970                 c++;
  971                 p--;
  972                 continue;
  973             }
  974             }
  975             else {
  976             c++;
  977             }
  978         }
  979         else {
  980             for (; *p && isdigit((int)*p); p++);
  981             if (*p == (char)NULL) break;
  982         }
  983         }
  984 
  985         /*
  986          * Check for [<lengthmod>].
  987          */
  988         if (is_printf_lengthmod[(int)*p]) {
  989         p++;
  990         if (*p == (char)NULL) break;
  991         if ((*p == 'h' && *(p-1) == 'h') ||
  992             (*p == 'l' && *(p-1) == 'l'))
  993         {
  994             p++;
  995         }
  996         if (*p == (char)NULL) break;
  997         }
  998 
  999         /*
 1000          * Check for <convspec>.
 1001          */
 1002         if (is_printf_convspec[(int)*p]) {
 1003         caddr_t addr;
 1004         c++;
 1005         if (pnum) {
 1006             addr = *((caddr_t*)(ap + (atoi(pnum)-1)*sizeof(char*)));
 1007         }
 1008         else {
 1009             addr = *((caddr_t*)(ap + c*sizeof(char*)));
 1010         }
 1011         if (*p == 'n') {
 1012             if (_libsafe_raVariableP((void *)(addr))) {
 1013             _libsafe_die("printf(\"%%n\")");
 1014             }
 1015         }
 1016         }
 1017     }
 1018     }
 1019 
 1020     res = real_vfprintf(fp, format, ap);
 1021     return res;
 1022 }
 1023 
 1024 /*
 1025  * No variant of printf() can be called here!!!
 1026  */
 1027 int _IO_vfprintf(FILE *fp, const char *format, va_list ap)
 1028 {
 1029     static vfprintf_t real_vfprintf = NULL;
 1030     int res;
 1031     char *p, *pnum;
 1032     int c = -1;     /* Next var arg to be used */
 1033     int in_mth;     /* Are we currently looking for an m-th argument? */
 1034     int atoi(const char *nptr);
 1035 
 1036     if (!real_vfprintf)
 1037     real_vfprintf = (vfprintf_t) getLibraryFunction("vfprintf");
 1038 
 1039     if (_libsafe_exclude) {
 1040     res = real_vfprintf(fp, format, ap);
 1041     return res;
 1042     }
 1043 
 1044     /*
 1045      * Now check to see if there are any %n specifiers.  If %n specifiers
 1046      * exist, then check the destination pointer to make sure it isn't a return
 1047      * address or frame pointer.
 1048      */
 1049 
 1050     /*
 1051      * %[<value>][<flags>][<fieldwidth>][.<precision>][<lengthmod>]<convspec>
 1052      *
 1053      * <value> = <pnum>$
 1054      * <flags> = # | 0 | - | <space> | + | ' | I
 1055      *          NOTE: <flags> can be in any order and can be repeated
 1056      * <fieldwidth> = <num> | *[<pnum>$]
 1057      * <precision> = <num> | *[<pnum>$]
 1058      * <lengthmod> = hh | h | l | ll | L | q | j | z | t
 1059      * <convspec> = d | i | o | u | x | X | e | E | f | F | g | G | a | A | c |
 1060      *          s | C | S | p | n | %
 1061      *
 1062      * <num> = any integer, including negative and zero integers; can have any
 1063      *          number of leading '0'
 1064      * <pnum> = positive integer; can have any number of leading '0'
 1065      */
 1066     for (p=(char*)format; *p; p++) {
 1067     if (*p == '%') {
 1068         /*
 1069          * Check for [<value>].
 1070          */
 1071         pnum = NULL;
 1072         for (p++,in_mth=0; *p && isdigit((int)*p); p++) {
 1073         if (in_mth == 0)
 1074             pnum = p;
 1075         in_mth = 1;
 1076         }
 1077         if (*p == (char)NULL) break;
 1078         if (in_mth) {
 1079         if (*p == '$') {
 1080             p++;
 1081         }
 1082         else {
 1083             c++;
 1084             p--;
 1085             continue;
 1086         }
 1087         }
 1088 
 1089         /*
 1090          * Check for [<flags>].
 1091          */
 1092         for (; *p && is_printf_flag[(int)*p]; p++);
 1093         if (*p == (char)NULL) break;
 1094 
 1095         /*
 1096          * Check for [<fieldwidth>].  Note that '-' is consumed previously.
 1097          */
 1098         if (*p == '*') {
 1099         for (p++,in_mth=0; *p && isdigit((int)*p); p++)
 1100             in_mth = 1;
 1101         if (*p == (char)NULL) break;
 1102         if (in_mth) {
 1103             if (*p == '$') {
 1104             p++;
 1105             }
 1106             else {
 1107             c++;
 1108             p--;
 1109             continue;
 1110             }
 1111         }
 1112         else {
 1113             c++;
 1114         }
 1115         }
 1116         else {
 1117         for (; *p && isdigit((int)*p); p++);
 1118         if (*p == (char)NULL) break;
 1119         }
 1120 
 1121         /*
 1122          * Check for [<precision>].
 1123          */
 1124         if (*p == '.') {
 1125         p++;
 1126         if (*p == '*') {
 1127             for (p++,in_mth=0; *p && isdigit((int)*p); p++)
 1128             in_mth = 1;
 1129             if (*p == (char)NULL) break;
 1130             if (in_mth) {
 1131             if (*p == '$') {
 1132                 p++;
 1133             }
 1134             else {
 1135                 c++;
 1136                 p--;
 1137                 continue;
 1138             }
 1139             }
 1140             else {
 1141             c++;
 1142             }
 1143         }
 1144         else {
 1145             for (; *p && isdigit((int)*p); p++);
 1146             if (*p == (char)NULL) break;
 1147         }
 1148         }
 1149 
 1150         /*
 1151          * Check for [<lengthmod>].
 1152          */
 1153         if (is_printf_lengthmod[(int)*p]) {
 1154         p++;
 1155         if (*p == (char)NULL) break;
 1156         if ((*p == 'h' && *(p-1) == 'h') ||
 1157             (*p == 'l' && *(p-1) == 'l'))
 1158         {
 1159             p++;
 1160         }
 1161         if (*p == (char)NULL) break;
 1162         }
 1163 
 1164         /*
 1165          * Check for <convspec>.
 1166          */
 1167         if (is_printf_convspec[(int)*p]) {
 1168         caddr_t addr;
 1169         c++;
 1170         if (pnum) {
 1171             addr = *((caddr_t*)(ap + (atoi(pnum)-1)*sizeof(char*)));
 1172         }
 1173         else {
 1174             addr = *((caddr_t*)(ap + c*sizeof(char*)));
 1175         }
 1176         if (*p == 'n') {
 1177             if (_libsafe_raVariableP((void *)(addr))) {
 1178             _libsafe_die("printf(\"%%n\")");
 1179             }
 1180         }
 1181         }
 1182     }
 1183     }
 1184 
 1185     res = real_vfprintf(fp, format, ap);
 1186     return res;
 1187 }
 1188 
 1189 
 1190 int sprintf(char *str, const char *format, ...)
 1191 {
 1192     static vsprintf_t real_vsprintf = NULL;
 1193     static vsnprintf_t real_vsnprintf = NULL;
 1194     size_t max_size;
 1195     va_list ap;
 1196     int res;
 1197 
 1198     if (!real_vsprintf)
 1199     real_vsprintf = (vsprintf_t) getLibraryFunction("vsprintf");
 1200     if (!real_vsnprintf)
 1201     real_vsnprintf = (vsnprintf_t) getLibraryFunction("vsnprintf");
 1202 
 1203     if (_libsafe_exclude) {
 1204     va_start(ap, format);
 1205     res = real_vsprintf(str, format, ap);
 1206     va_end(ap);
 1207     return res;
 1208     }
 1209 
 1210     if ((max_size = _libsafe_stackVariableP(str)) == 0) {
 1211     LOG(5, "sprintf(<heap var>, <format>)\n");
 1212     va_start(ap, format);
 1213     res = real_vsprintf(str, format, ap);
 1214     va_end(ap);
 1215     return res;
 1216     }
 1217 
 1218     LOG(4, "sprintf(<stack var>, <format>) stack limit=%d\n", max_size);
 1219     va_start(ap, format);
 1220 
 1221     /*
 1222      * Some man pages say that -1 is returned if vsnprintf truncates the
 1223      * output.  However, some implementations actually return the number of
 1224      * chars that would have been output with a sufficiently large output
 1225      * buffer.  Hence, we check for both res==-1 and res>max_size-1.  The
 1226      * max_size-1 is to make sure that there is room for the string-terminating
 1227      * NULL.
 1228      */
 1229     res = real_vsnprintf(str, max_size, format, ap);
 1230     if (res == -1 || res > max_size-1)
 1231     {
 1232     _libsafe_die("overflow caused by sprintf()");
 1233     }
 1234     va_end(ap);
 1235 
 1236     return res;
 1237 }
 1238 
 1239 
 1240 int snprintf(char *str, size_t size, const char *format, ...)
 1241 {
 1242     static vsnprintf_t real_vsnprintf = NULL;
 1243     size_t max_size;
 1244     va_list ap;
 1245     int res;
 1246 
 1247     if (!real_vsnprintf)
 1248     real_vsnprintf = (vsnprintf_t) getLibraryFunction("vsnprintf");
 1249 
 1250     if (_libsafe_exclude) {
 1251     va_start(ap, format);
 1252     res = real_vsnprintf(str, size, format, ap);
 1253     va_end(ap);
 1254     return res;
 1255     }
 1256 
 1257     if ((max_size = _libsafe_stackVariableP(str)) == 0) {
 1258     LOG(5, "snprintf(<heap var>, <format>)\n");
 1259     va_start(ap, format);
 1260     res = real_vsnprintf(str, size, format, ap);
 1261     va_end(ap);
 1262     return res;
 1263     }
 1264 
 1265     LOG(4, "snprintf(<stack var>, <format>) stack limit=%d\n", max_size);
 1266     va_start(ap, format);
 1267 
 1268     /*
 1269      * Some man pages say that -1 is returned if vsnprintf truncates the
 1270      * output.  However, some implementations actually return the number of
 1271      * chars that would have been output with a sufficiently large output
 1272      * buffer.  Hence, we check for both res==-1 and res>max_size-1.  The
 1273      * max_size-1 is to make sure that there is room for the string-terminating
 1274      * NULL.
 1275      */
 1276     res = real_vsnprintf(str, size, format, ap);
 1277     if ((res == -1 || res > max_size-1) && (size > max_size))
 1278     {
 1279     _libsafe_die("overflow caused by snprintf()");
 1280     }
 1281     va_end(ap);
 1282 
 1283     return res;
 1284 }
 1285 
 1286 
 1287 int vsprintf(char *str, const char *format, va_list ap)
 1288 {
 1289     static vsprintf_t real_vsprintf = NULL;
 1290     static vsnprintf_t real_vsnprintf = NULL;
 1291     size_t max_size;
 1292     int res;
 1293 
 1294     if (!real_vsprintf)
 1295     real_vsprintf = (vsprintf_t) getLibraryFunction("vsprintf");
 1296     if (!real_vsnprintf)
 1297     real_vsnprintf = (vsnprintf_t) getLibraryFunction("vsnprintf");
 1298 
 1299     if (_libsafe_exclude)
 1300     return real_vsprintf(str, format, ap);
 1301 
 1302     if ((max_size = _libsafe_stackVariableP(str)) == 0) {
 1303     LOG(5, "vsprintf(<heap var>, <format>, <va_list>)\n");
 1304     return real_vsprintf(str, format, ap);
 1305     }
 1306 
 1307     LOG(4, "vsprintf(<stack var>, <format>, <va_list>)\n");
 1308 
 1309     /*
 1310      * Some man pages say that -1 is returned if vsnprintf truncates the
 1311      * output.  However, some implementations actually return the number of
 1312      * chars that would have been output with a sufficiently large output
 1313      * buffer.  Hence, we check for both res==-1 and res>max_size-1.  The
 1314      * max_size-1 is to make sure that there is room for the string-terminating
 1315      * NULL.
 1316      */
 1317     res = real_vsnprintf(str, max_size, format, ap);
 1318     if (res == -1 || res > max_size-1)
 1319     {
 1320     _libsafe_die("overflow caused by vsprintf()");
 1321     }
 1322     return res;
 1323 }
 1324 
 1325 
 1326 int vsnprintf(char *str, size_t size, const char *format, va_list ap)
 1327 {
 1328     static vsnprintf_t real_vsnprintf = NULL;
 1329     size_t max_size;
 1330     int res;
 1331 
 1332     if (!real_vsnprintf)
 1333     real_vsnprintf = (vsnprintf_t) getLibraryFunction("vsnprintf");
 1334 
 1335     if (_libsafe_exclude)
 1336     return real_vsnprintf(str, size, format, ap);
 1337 
 1338     if ((max_size = _libsafe_stackVariableP(str)) == 0) {
 1339     LOG(5, "vsnprintf(<heap var>, <format>, <va_list>)\n");
 1340     return real_vsnprintf(str, size, format, ap);
 1341     }
 1342 
 1343     LOG(4, "vsnprintf(<stack var>, <format>, <va_list>)\n");
 1344 
 1345     /*
 1346      * Some man pages say that -1 is returned if vsnprintf truncates the
 1347      * output.  However, some implementations actually return the number of
 1348      * chars that would have been output with a sufficiently large output
 1349      * buffer.  Hence, we check for both res==-1 and res>max_size-1.  The
 1350      * max_size-1 is to make sure that there is room for the string-terminating
 1351      * NULL.
 1352      */
 1353     res = real_vsnprintf(str, size, format, ap);
 1354     if ((res == -1 || res > max_size-1) && (size > max_size))
 1355     {
 1356     _libsafe_die("overflow caused by vsnprintf()");
 1357     }
 1358     return res;
 1359 }
 1360 
 1361 
 1362 char *getwd(char *buf)
 1363 {
 1364     static getwd_t real_getwd = NULL;
 1365     size_t max_size;
 1366     char *res;
 1367 
 1368     if (!real_getwd)
 1369     real_getwd = (getwd_t) getLibraryFunction("getwd");
 1370 
 1371     if (_libsafe_exclude)
 1372     return real_getwd(buf);
 1373 
 1374     if ((max_size = _libsafe_stackVariableP(buf)) == 0) {
 1375     LOG(5, "getwd(<heap var>)\n");
 1376     return real_getwd(buf);
 1377     }
 1378 
 1379     LOG(4, "getwd(<stack var>) stack limit=%d\n", max_size);
 1380     res = getcwd(buf, PATH_MAX);
 1381     if ((strlen(buf) + 1) > max_size)
 1382     _libsafe_die("Overflow caused by getwd()");
 1383     return res;
 1384 }
 1385 
 1386 
 1387 char *gets(char *s)
 1388 {
 1389     static gets_t real_gets = NULL;
 1390     size_t max_size, len;
 1391 
 1392     if (!real_gets)
 1393     real_gets = (gets_t) getLibraryFunction("gets");
 1394 
 1395     if (_libsafe_exclude)
 1396     return real_gets(s);
 1397 
 1398     if ((max_size = _libsafe_stackVariableP(s)) == 0) {
 1399     LOG(5, "gets(<heap var>)\n");
 1400     return real_gets(s);
 1401     }
 1402 
 1403     LOG(4, "gets(<stack var>) stack limit=%d\n", max_size);
 1404     fgets(s, max_size, stdin);
 1405     len = strlen(s);
 1406 
 1407     if(s[len - 1] == '\n')
 1408     s[len - 1] = '\0';
 1409     return s;
 1410 }
 1411 
 1412 
 1413 char *realpath(char *path, char resolved_path[])
 1414 {
 1415     static realpath_t real_realpath = NULL;
 1416     size_t max_size, len;
 1417     char *res;
 1418     char buf[MAXPATHLEN + 1];
 1419 
 1420     if (!real_memcpy)
 1421     real_memcpy = (memcpy_t) getLibraryFunction("memcpy");
 1422     if (!real_realpath)
 1423     real_realpath = (realpath_t) getLibraryFunction("realpath");
 1424 
 1425     if (_libsafe_exclude)
 1426     return real_realpath(path, resolved_path);
 1427 
 1428     if ((max_size = _libsafe_stackVariableP(resolved_path)) == 0) {
 1429     LOG(5, "realpath(<src>, <heap var>)\n");
 1430     return real_realpath(path, resolved_path);
 1431     }
 1432 
 1433     LOG(4, "realpath(<src>, <stack var>) stack limit=%d\n", max_size);
 1434     /*
 1435      * realpath(3) copies at most MAXNAMLEN characters
 1436      */
 1437     res = real_realpath(path, buf);
 1438     if ((len = strnlen(buf, max_size)) == max_size)
 1439     _libsafe_die("Overflow caused by realpath()");
 1440 
 1441     real_memcpy(resolved_path, buf, len + 1);
 1442     return (res == NULL) ? NULL : resolved_path;
 1443 }
 1444 
 1445 
 1446 int _IO_vfscanf (_IO_FILE *s, const char *format, _IO_va_list argptr, int *errp)
 1447 {
 1448     static _IO_vfscanf_t real_IO_vfscanf = NULL;
 1449     int res, save_count;
 1450     caddr_t ra_array[MAXLEVELS], fp_array[MAXLEVELS];
 1451 
 1452     if (!real_IO_vfscanf)
 1453     real_IO_vfscanf = (_IO_vfscanf_t) getLibraryFunction("_IO_vfscanf");
 1454 
 1455     if (_libsafe_exclude)
 1456     return real_IO_vfscanf(s, format, argptr, errp);
 1457 
 1458     save_count = _libsafe_save_ra_fp(sizeof(ra_array)/sizeof(caddr_t),
 1459         ra_array, fp_array);
 1460 
 1461     res = real_IO_vfscanf(s, format, argptr, errp);
 1462 
 1463     if (save_count >= 0 && _libsafe_verify_ra_fp(save_count, ra_array,
 1464         fp_array) == -1)
 1465     {
 1466     _libsafe_die("Overflow caused by *scanf()");
 1467     }
 1468 
 1469     return res;
 1470 }
 1471 
 1472 
 1473 
 1474 /*
 1475  * -----------------------------------------------------------------
 1476  * ------------- initializer and finalizer--------------------------
 1477  */
 1478 static void _intercept_init() __attribute__ ((constructor));
 1479 static void _intercept_fini() __attribute__ ((destructor));
 1480 
 1481 
 1482 static char *get_exename(char *exename, int size) {
 1483     int res;
 1484     
 1485     /*
 1486      * get the name of the current executable
 1487      */
 1488     if ((res = readlink("/proc/self/exe", exename, size - 1)) == -1)
 1489     exename[0] = '\0';
 1490     else
 1491     exename[res] = '\0';
 1492     return (exename);
 1493 }
 1494 
 1495 
 1496 static void _intercept_init(void)
 1497 {
 1498     char    exename[MAXPATHLEN];
 1499     char    omitfile[MAXPATHLEN];
 1500     FILE    *fp;
 1501 
 1502     LOG(4, "beginning of _intercept_init()\n");
 1503 
 1504     /*
 1505      * Is this process on the list of applications to ignore?  Note that
 1506      * programs listed in /etc/libsafe.exclude must be specified as absolute
 1507      * pathnames.
 1508      */
 1509     get_exename(exename, MAXPATHLEN);
 1510     if ((fp=fopen("/etc/libsafe.exclude", "r")) != NULL) {
 1511     while (fgets(omitfile, sizeof(omitfile), fp)) {
 1512         omitfile[strnlen(omitfile, sizeof(omitfile)) - 1] = (char)NULL;
 1513 
 1514         if (!strncmp(omitfile, exename, sizeof(omitfile))) {
 1515         _libsafe_exclude = 1;
 1516         }
 1517 
 1518         /*
 1519          * Is this process being run as a privileged process?  If so, and
 1520          * the LIBSAFE_PROTECT_ROOT is set, then only protect privileged
 1521          * processes.  By protecting only privileged processes, overall
 1522          * system performance can be improved.
 1523          */
 1524         if (!strncmp(omitfile, "LIBSAFE_PROTECT_ROOT", sizeof(omitfile))) {
 1525         if (geteuid() >= 100)
 1526             _libsafe_exclude = 1;
 1527         }
 1528     }
 1529     
 1530     fclose(fp);
 1531     }
 1532 }
 1533 
 1534 
 1535 static void _intercept_fini(void)
 1536 {
 1537     LOG(4, "end of _intercept_fini()\n");
 1538 }