LCOV - code coverage report
Current view: top level - lib - strnlen_user.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 19 28 67.9 %
Date: 2015-04-12 14:34:49 Functions: 1 2 50.0 %

          Line data    Source code
       1             : #include <linux/kernel.h>
       2             : #include <linux/export.h>
       3             : #include <linux/uaccess.h>
       4             : 
       5             : #include <asm/word-at-a-time.h>
       6             : 
       7             : /* Set bits in the first 'n' bytes when loaded from memory */
       8             : #ifdef __LITTLE_ENDIAN
       9             : #  define aligned_byte_mask(n) ((1ul << 8*(n))-1)
      10             : #else
      11             : #  define aligned_byte_mask(n) (~0xfful << (BITS_PER_LONG - 8 - 8*(n)))
      12             : #endif
      13             : 
      14             : /*
      15             :  * Do a strnlen, return length of string *with* final '\0'.
      16             :  * 'count' is the user-supplied count, while 'max' is the
      17             :  * address space maximum.
      18             :  *
      19             :  * Return 0 for exceptions (which includes hitting the address
      20             :  * space maximum), or 'count+1' if hitting the user-supplied
      21             :  * maximum count.
      22             :  *
      23             :  * NOTE! We can sometimes overshoot the user-supplied maximum
      24             :  * if it fits in a aligned 'long'. The caller needs to check
      25             :  * the return value against "> max".
      26             :  */
      27             : static inline long do_strnlen_user(const char __user *src, unsigned long count, unsigned long max)
      28             : {
      29             :         const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
      30             :         long align, res = 0;
      31             :         unsigned long c;
      32             : 
      33             :         /*
      34             :          * Truncate 'max' to the user-specified limit, so that
      35             :          * we only have one limit we need to check in the loop
      36             :          */
      37       77071 :         if (max > count)
      38             :                 max = count;
      39             : 
      40             :         /*
      41             :          * Do everything aligned. But that means that we
      42             :          * need to also expand the maximum..
      43             :          */
      44       77071 :         align = (sizeof(long) - 1) & (unsigned long)src;
      45       77071 :         src -= align;
      46       77071 :         max += align;
      47             : 
      48       77071 :         if (unlikely(__get_user(c,(unsigned long __user *)src)))
      49             :                 return 0;
      50       77071 :         c |= aligned_byte_mask(align);
      51             : 
      52             :         for (;;) {
      53             :                 unsigned long data;
      54      472826 :                 if (has_zero(c, &data, &constants)) {
      55             :                         data = prep_zero_mask(c, data, &constants);
      56             :                         data = create_zero_mask(data);
      57       77071 :                         return res + find_zero(data) + 1 - align;
      58             :                 }
      59      395755 :                 res += sizeof(unsigned long);
      60      395755 :                 if (unlikely(max < sizeof(unsigned long)))
      61             :                         break;
      62      395755 :                 max -= sizeof(unsigned long);
      63      395755 :                 if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
      64             :                         return 0;
      65             :         }
      66           0 :         res -= align;
      67             : 
      68             :         /*
      69             :          * Uhhuh. We hit 'max'. But was that the user-specified maximum
      70             :          * too? If so, return the marker for "too long".
      71             :          */
      72           0 :         if (res >= count)
      73           0 :                 return count+1;
      74             : 
      75             :         /*
      76             :          * Nope: we hit the address space limit, and we still had more
      77             :          * characters the caller would have wanted. That's 0.
      78             :          */
      79             :         return 0;
      80             : }
      81             : 
      82             : /**
      83             :  * strnlen_user: - Get the size of a user string INCLUDING final NUL.
      84             :  * @str: The string to measure.
      85             :  * @count: Maximum count (including NUL character)
      86             :  *
      87             :  * Context: User context only.  This function may sleep.
      88             :  *
      89             :  * Get the size of a NUL-terminated string in user space.
      90             :  *
      91             :  * Returns the size of the string INCLUDING the terminating NUL.
      92             :  * If the string is too long, returns 'count+1'.
      93             :  * On exception (or invalid count), returns 0.
      94             :  */
      95       77071 : long strnlen_user(const char __user *str, long count)
      96             : {
      97             :         unsigned long max_addr, src_addr;
      98             : 
      99       77071 :         if (unlikely(count <= 0))
     100             :                 return 0;
     101             : 
     102       77071 :         max_addr = user_addr_max();
     103       77071 :         src_addr = (unsigned long)str;
     104       77071 :         if (likely(src_addr < max_addr)) {
     105       77071 :                 unsigned long max = max_addr - src_addr;
     106      154142 :                 return do_strnlen_user(str, count, max);
     107             :         }
     108             :         return 0;
     109             : }
     110             : EXPORT_SYMBOL(strnlen_user);
     111             : 
     112             : /**
     113             :  * strlen_user: - Get the size of a user string INCLUDING final NUL.
     114             :  * @str: The string to measure.
     115             :  *
     116             :  * Context: User context only.  This function may sleep.
     117             :  *
     118             :  * Get the size of a NUL-terminated string in user space.
     119             :  *
     120             :  * Returns the size of the string INCLUDING the terminating NUL.
     121             :  * On exception, returns 0.
     122             :  *
     123             :  * If there is a limit on the length of a valid string, you may wish to
     124             :  * consider using strnlen_user() instead.
     125             :  */
     126           0 : long strlen_user(const char __user *str)
     127             : {
     128             :         unsigned long max_addr, src_addr;
     129             : 
     130           0 :         max_addr = user_addr_max();
     131           0 :         src_addr = (unsigned long)str;
     132           0 :         if (likely(src_addr < max_addr)) {
     133           0 :                 unsigned long max = max_addr - src_addr;
     134           0 :                 return do_strnlen_user(str, ~0ul, max);
     135             :         }
     136             :         return 0;
     137             : }
     138             : EXPORT_SYMBOL(strlen_user);

Generated by: LCOV version 1.11