LCOV - code coverage report
Current view: top level - lib - strncpy_from_user.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 41 44 93.2 %
Date: 2021-04-22 12:43:58 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : #include <linux/compiler.h>
       3             : #include <linux/export.h>
       4             : #include <linux/fault-inject-usercopy.h>
       5             : #include <linux/kasan-checks.h>
       6             : #include <linux/thread_info.h>
       7             : #include <linux/uaccess.h>
       8             : #include <linux/kernel.h>
       9             : #include <linux/errno.h>
      10             : #include <linux/mm.h>
      11             : 
      12             : #include <asm/byteorder.h>
      13             : #include <asm/word-at-a-time.h>
      14             : 
      15             : #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
      16             : #define IS_UNALIGNED(src, dst)  0
      17             : #else
      18             : #define IS_UNALIGNED(src, dst)  \
      19             :         (((long) dst | (long) src) & (sizeof(long) - 1))
      20             : #endif
      21             : 
      22             : /*
      23             :  * Do a strncpy, return length of string without final '\0'.
      24             :  * 'count' is the user-supplied count (return 'count' if we
      25             :  * hit it), 'max' is the address space maximum (and we return
      26             :  * -EFAULT if we hit it).
      27             :  */
      28      105660 : static inline long do_strncpy_from_user(char *dst, const char __user *src,
      29             :                                         unsigned long count, unsigned long max)
      30             : {
      31      105660 :         const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
      32      105660 :         unsigned long res = 0;
      33             : 
      34      105660 :         if (IS_UNALIGNED(src, dst))
      35             :                 goto byte_at_a_time;
      36             : 
      37      312598 :         while (max >= sizeof(unsigned long)) {
      38      312540 :                 unsigned long c, data, mask;
      39             : 
      40             :                 /* Fall back to byte-at-a-time if we get a page fault */
      41      312540 :                 unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time);
      42             : 
      43             :                 /*
      44             :                  * Note that we mask out the bytes following the NUL. This is
      45             :                  * important to do because string oblivious code may read past
      46             :                  * the NUL. For those routines, we don't want to give them
      47             :                  * potentially random bytes after the NUL in `src`.
      48             :                  *
      49             :                  * One example of such code is BPF map keys. BPF treats map keys
      50             :                  * as an opaque set of bytes. Without the post-NUL mask, any BPF
      51             :                  * maps keyed by strings returned from strncpy_from_user() may
      52             :                  * have multiple entries for semantically identical strings.
      53             :                  */
      54      312545 :                 if (has_zero(c, &data, &constants)) {
      55      105607 :                         data = prep_zero_mask(c, data, &constants);
      56             :                         data = create_zero_mask(data);
      57      105607 :                         mask = zero_bytemask(data);
      58      105607 :                         *(unsigned long *)(dst+res) = c & mask;
      59      105607 :                         return res + find_zero(data);
      60             :                 }
      61             : 
      62      206938 :                 *(unsigned long *)(dst+res) = c;
      63             : 
      64      206938 :                 res += sizeof(unsigned long);
      65      206938 :                 max -= sizeof(unsigned long);
      66             :         }
      67             : 
      68          58 : byte_at_a_time:
      69         161 :         while (max) {
      70         161 :                 char c;
      71             : 
      72         161 :                 unsafe_get_user(c,src+res, efault);
      73         161 :                 dst[res] = c;
      74         161 :                 if (!c)
      75          58 :                         return res;
      76         103 :                 res++;
      77         103 :                 max--;
      78             :         }
      79             : 
      80             :         /*
      81             :          * Uhhuh. We hit 'max'. But was that the user-specified maximum
      82             :          * too? If so, that's ok - we got as much as the user asked for.
      83             :          */
      84           0 :         if (res >= count)
      85           0 :                 return res;
      86             : 
      87             :         /*
      88             :          * Nope: we hit the address space limit, and we still had more
      89             :          * characters the caller would have wanted. That's an EFAULT.
      90             :          */
      91           0 : efault:
      92             :         return -EFAULT;
      93             : }
      94             : 
      95             : /**
      96             :  * strncpy_from_user: - Copy a NUL terminated string from userspace.
      97             :  * @dst:   Destination address, in kernel space.  This buffer must be at
      98             :  *         least @count bytes long.
      99             :  * @src:   Source address, in user space.
     100             :  * @count: Maximum number of bytes to copy, including the trailing NUL.
     101             :  *
     102             :  * Copies a NUL-terminated string from userspace to kernel space.
     103             :  *
     104             :  * On success, returns the length of the string (not including the trailing
     105             :  * NUL).
     106             :  *
     107             :  * If access to userspace fails, returns -EFAULT (some data may have been
     108             :  * copied).
     109             :  *
     110             :  * If @count is smaller than the length of the string, copies @count bytes
     111             :  * and returns @count.
     112             :  */
     113      105670 : long strncpy_from_user(char *dst, const char __user *src, long count)
     114             : {
     115      105670 :         unsigned long max_addr, src_addr;
     116             : 
     117      105670 :         might_fault();
     118      105656 :         if (should_fail_usercopy())
     119             :                 return -EFAULT;
     120      105656 :         if (unlikely(count <= 0))
     121             :                 return 0;
     122             : 
     123      105656 :         max_addr = user_addr_max();
     124      105656 :         src_addr = (unsigned long)untagged_addr(src);
     125      105656 :         if (likely(src_addr < max_addr)) {
     126      105656 :                 unsigned long max = max_addr - src_addr;
     127      105656 :                 long retval;
     128             : 
     129             :                 /*
     130             :                  * Truncate 'max' to the user-specified limit, so that
     131             :                  * we only have one limit we need to check in the loop
     132             :                  */
     133      105656 :                 if (max > count)
     134             :                         max = count;
     135             : 
     136      105656 :                 kasan_check_write(dst, count);
     137      105666 :                 check_object_size(dst, count, false);
     138      105666 :                 if (user_read_access_begin(src, max)) {
     139      105665 :                         retval = do_strncpy_from_user(dst, src, count, max);
     140      105665 :                         user_read_access_end();
     141      105665 :                         return retval;
     142             :                 }
     143             :         }
     144             :         return -EFAULT;
     145             : }
     146             : EXPORT_SYMBOL(strncpy_from_user);

Generated by: LCOV version 1.14