LCOV - code coverage report
Current view: top level - lib - strncpy_from_user.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 22 23 95.7 %
Date: 2014-02-18 Functions: 1 1 100.0 %
Branches: 19 21 90.5 %

           Branch data     Line data    Source code
       1                 :            : #include <linux/module.h>
       2                 :            : #include <linux/uaccess.h>
       3                 :            : #include <linux/kernel.h>
       4                 :            : #include <linux/errno.h>
       5                 :            : 
       6                 :            : #include <asm/byteorder.h>
       7                 :            : #include <asm/word-at-a-time.h>
       8                 :            : 
       9                 :            : #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
      10                 :            : #define IS_UNALIGNED(src, dst)  0
      11                 :            : #else
      12                 :            : #define IS_UNALIGNED(src, dst)  \
      13                 :            :         (((long) dst | (long) src) & (sizeof(long) - 1))
      14                 :            : #endif
      15                 :            : 
      16                 :            : /*
      17                 :            :  * Do a strncpy, return length of string without final '\0'.
      18                 :            :  * 'count' is the user-supplied count (return 'count' if we
      19                 :            :  * hit it), 'max' is the address space maximum (and we return
      20                 :            :  * -EFAULT if we hit it).
      21                 :            :  */
      22                 :            : static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max)
      23                 :            : {
      24                 :            :         const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
      25                 :            :         long res = 0;
      26                 :            : 
      27                 :            :         /*
      28                 :            :          * Truncate 'max' to the user-specified limit, so that
      29                 :            :          * we only have one limit we need to check in the loop
      30                 :            :          */
      31         [ +  + ]:   20967086 :         if (max > count)
      32                 :            :                 max = count;
      33                 :            : 
      34         [ +  + ]:   20967086 :         if (IS_UNALIGNED(src, dst))
      35                 :            :                 goto byte_at_a_time;
      36                 :            : 
      37         [ +  + ]:   67662662 :         while (max >= sizeof(unsigned long)) {
      38                 :            :                 unsigned long c, data;
      39                 :            : 
      40                 :            :                 /* Fall back to byte-at-a-time if we get a page fault */
      41            [ + ]:   78514917 :                 if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
      42                 :            :                         break;
      43                 :   78145712 :                 *(unsigned long *)(dst+res) = c;
      44         [ +  + ]:   78145712 :                 if (has_zero(c, &data, &constants)) {
      45                 :            :                         data = prep_zero_mask(c, data, &constants);
      46                 :            :                         data = create_zero_mask(data);
      47                 :   10114310 :                         return res + find_zero(data);
      48                 :            :                 }
      49                 :   57547831 :                 res += sizeof(unsigned long);
      50                 :   57547831 :                 max -= sizeof(unsigned long);
      51                 :            :         }
      52                 :            : 
      53                 :            : byte_at_a_time:
      54         [ +  + ]:   11192816 :         while (max) {
      55                 :            :                 char c;
      56                 :            : 
      57         [ +  + ]:   11192769 :                 if (unlikely(__get_user(c,src+res)))
      58                 :            :                         return -EFAULT;
      59                 :   11192721 :                 dst[res] = c;
      60         [ +  + ]:   11192721 :                 if (!c)
      61                 :            :                         return res;
      62                 :   10823852 :                 res++;
      63                 :   10823852 :                 max--;
      64                 :            :         }
      65                 :            : 
      66                 :            :         /*
      67                 :            :          * Uhhuh. We hit 'max'. But was that the user-specified maximum
      68                 :            :          * too? If so, that's ok - we got as much as the user asked for.
      69                 :            :          */
      70         [ +  - ]:         47 :         if (res >= count)
      71                 :            :                 return res;
      72                 :            : 
      73                 :            :         /*
      74                 :            :          * Nope: we hit the address space limit, and we still had more
      75                 :            :          * characters the caller would have wanted. That's an EFAULT.
      76                 :            :          */
      77                 :            :         return -EFAULT;
      78                 :            : }
      79                 :            : 
      80                 :            : /**
      81                 :            :  * strncpy_from_user: - Copy a NUL terminated string from userspace.
      82                 :            :  * @dst:   Destination address, in kernel space.  This buffer must be at
      83                 :            :  *         least @count bytes long.
      84                 :            :  * @src:   Source address, in user space.
      85                 :            :  * @count: Maximum number of bytes to copy, including the trailing NUL.
      86                 :            :  *
      87                 :            :  * Copies a NUL-terminated string from userspace to kernel space.
      88                 :            :  *
      89                 :            :  * On success, returns the length of the string (not including the trailing
      90                 :            :  * NUL).
      91                 :            :  *
      92                 :            :  * If access to userspace fails, returns -EFAULT (some data may have been
      93                 :            :  * copied).
      94                 :            :  *
      95                 :            :  * If @count is smaller than the length of the string, copies @count bytes
      96                 :            :  * and returns @count.
      97                 :            :  */
      98                 :          0 : long strncpy_from_user(char *dst, const char __user *src, long count)
      99                 :            : {
     100                 :            :         unsigned long max_addr, src_addr;
     101                 :            : 
     102            [ + ]:   10483571 :         if (unlikely(count <= 0))
     103                 :            :                 return 0;
     104                 :            : 
     105         [ -  + ]:   10483620 :         max_addr = user_addr_max();
     106                 :   10483620 :         src_addr = (unsigned long)src;
     107            [ + ]:   10483620 :         if (likely(src_addr < max_addr)) {
     108                 :   20967086 :                 unsigned long max = max_addr - src_addr;
     109                 :   10483279 :                 return do_strncpy_from_user(dst, src, count, max);
     110                 :            :         }
     111                 :            :         return -EFAULT;
     112                 :            : }
     113                 :            : EXPORT_SYMBOL(strncpy_from_user);

Generated by: LCOV version 1.9