LCOV - code coverage report
Current view: top level - arch/arm/include/asm - uaccess.h (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 15 15 100.0 %
Date: 2020-09-30 20:25:40 Functions: 3 3 100.0 %
Branches: 2 2 100.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :            : /*
       3                 :            :  *  arch/arm/include/asm/uaccess.h
       4                 :            :  */
       5                 :            : #ifndef _ASMARM_UACCESS_H
       6                 :            : #define _ASMARM_UACCESS_H
       7                 :            : 
       8                 :            : /*
       9                 :            :  * User space memory access functions
      10                 :            :  */
      11                 :            : #include <linux/string.h>
      12                 :            : #include <asm/memory.h>
      13                 :            : #include <asm/domain.h>
      14                 :            : #include <asm/unified.h>
      15                 :            : #include <asm/compiler.h>
      16                 :            : 
      17                 :            : #include <asm/extable.h>
      18                 :            : 
      19                 :            : /*
      20                 :            :  * These two functions allow hooking accesses to userspace to increase
      21                 :            :  * system integrity by ensuring that the kernel can not inadvertantly
      22                 :            :  * perform such accesses (eg, via list poison values) which could then
      23                 :            :  * be exploited for priviledge escalation.
      24                 :            :  */
      25                 :            : static __always_inline unsigned int uaccess_save_and_enable(void)
      26                 :            : {
      27                 :            : #ifdef CONFIG_CPU_SW_DOMAIN_PAN
      28                 :            :         unsigned int old_domain = get_domain();
      29                 :            : 
      30                 :            :         /* Set the current domain access to permit user accesses */
      31                 :            :         set_domain((old_domain & ~domain_mask(DOMAIN_USER)) |
      32                 :            :                    domain_val(DOMAIN_USER, DOMAIN_CLIENT));
      33                 :            : 
      34                 :            :         return old_domain;
      35                 :            : #else
      36                 :            :         return 0;
      37                 :            : #endif
      38                 :            : }
      39                 :            : 
      40                 :            : static __always_inline void uaccess_restore(unsigned int flags)
      41                 :            : {
      42                 :            : #ifdef CONFIG_CPU_SW_DOMAIN_PAN
      43                 :            :         /* Restore the user access mask */
      44                 :            :         set_domain(flags);
      45                 :            : #endif
      46                 :            : }
      47                 :            : 
      48                 :            : /*
      49                 :            :  * These two are intentionally not defined anywhere - if the kernel
      50                 :            :  * code generates any references to them, that's a bug.
      51                 :            :  */
      52                 :            : extern int __get_user_bad(void);
      53                 :            : extern int __put_user_bad(void);
      54                 :            : 
      55                 :            : /*
      56                 :            :  * Note that this is actually 0x1,0000,0000
      57                 :            :  */
      58                 :            : #define KERNEL_DS       0x00000000
      59                 :            : 
      60                 :            : #ifdef CONFIG_MMU
      61                 :            : 
      62                 :            : #define USER_DS         TASK_SIZE
      63                 :            : #define get_fs()        (current_thread_info()->addr_limit)
      64                 :            : 
      65                 :            : static inline void set_fs(mm_segment_t fs)
      66                 :            : {
      67                 :   30827011 :         current_thread_info()->addr_limit = fs;
      68                 :            : 
      69                 :            :         /*
      70                 :            :          * Prevent a mispredicted conditional call to set_fs from forwarding
      71                 :            :          * the wrong address limit to access_ok under speculation.
      72                 :            :          */
      73                 :   30827011 :         dsb(nsh);
      74                 :   30827330 :         isb();
      75                 :            : 
      76                 :            :         modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
      77                 :            : }
      78                 :            : 
      79                 :            : #define segment_eq(a, b)        ((a) == (b))
      80                 :            : 
      81                 :            : /* We use 33-bit arithmetic here... */
      82                 :            : #define __range_ok(addr, size) ({ \
      83                 :            :         unsigned long flag, roksum; \
      84                 :            :         __chk_user_ptr(addr);   \
      85                 :            :         __asm__(".syntax unified\n" \
      86                 :            :                 "adds %1, %2, %3; sbcscc %1, %1, %0; movcc %0, #0" \
      87                 :            :                 : "=&r" (flag), "=&r" (roksum) \
      88                 :            :                 : "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \
      89                 :            :                 : "cc"); \
      90                 :            :         flag; })
      91                 :            : 
      92                 :            : /*
      93                 :            :  * This is a type: either unsigned long, if the argument fits into
      94                 :            :  * that type, or otherwise unsigned long long.
      95                 :            :  */
      96                 :            : #define __inttype(x) \
      97                 :            :         __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
      98                 :            : 
      99                 :            : /*
     100                 :            :  * Sanitise a uaccess pointer such that it becomes NULL if addr+size
     101                 :            :  * is above the current addr_limit.
     102                 :            :  */
     103                 :            : #define uaccess_mask_range_ptr(ptr, size)                       \
     104                 :            :         ((__typeof__(ptr))__uaccess_mask_range_ptr(ptr, size))
     105                 :            : static inline void __user *__uaccess_mask_range_ptr(const void __user *ptr,
     106                 :            :                                                     size_t size)
     107                 :            : {
     108                 :            :         void __user *safe_ptr = (void __user *)ptr;
     109                 :            :         unsigned long tmp;
     110                 :            : 
     111                 :   48212782 :         asm volatile(
     112                 :            :         "  .syntax unified\n"
     113                 :            :         "  sub     %1, %3, #1\n"
     114                 :            :         "  subs    %1, %1, %0\n"
     115                 :            :         "  addhs   %1, %1, #1\n"
     116                 :            :         "  subshs  %1, %1, %2\n"
     117                 :            :         "  movlo   %0, #0\n"
     118                 :            :         : "+r" (safe_ptr), "=&r" (tmp)
     119                 :   48212782 :         : "r" (size), "r" (current_thread_info()->addr_limit)
     120                 :            :         : "cc");
     121                 :            : 
     122                 :   48226265 :         csdb();
     123                 :            :         return safe_ptr;
     124                 :            : }
     125                 :            : 
     126                 :            : /*
     127                 :            :  * Single-value transfer routines.  They automatically use the right
     128                 :            :  * size if we just have the right pointer type.  Note that the functions
     129                 :            :  * which read from user space (*get_*) need to take care not to leak
     130                 :            :  * kernel data even if the calling code is buggy and fails to check
     131                 :            :  * the return value.  This means zeroing out the destination variable
     132                 :            :  * or buffer on error.  Normally this is done out of line by the
     133                 :            :  * fixup code, but there are a few places where it intrudes on the
     134                 :            :  * main code path.  When we only write to user space, there is no
     135                 :            :  * problem.
     136                 :            :  */
     137                 :            : extern int __get_user_1(void *);
     138                 :            : extern int __get_user_2(void *);
     139                 :            : extern int __get_user_4(void *);
     140                 :            : extern int __get_user_32t_8(void *);
     141                 :            : extern int __get_user_8(void *);
     142                 :            : extern int __get_user_64t_1(void *);
     143                 :            : extern int __get_user_64t_2(void *);
     144                 :            : extern int __get_user_64t_4(void *);
     145                 :            : 
     146                 :            : #define __GUP_CLOBBER_1 "lr", "cc"
     147                 :            : #ifdef CONFIG_CPU_USE_DOMAINS
     148                 :            : #define __GUP_CLOBBER_2 "ip", "lr", "cc"
     149                 :            : #else
     150                 :            : #define __GUP_CLOBBER_2 "lr", "cc"
     151                 :            : #endif
     152                 :            : #define __GUP_CLOBBER_4 "lr", "cc"
     153                 :            : #define __GUP_CLOBBER_32t_8 "lr", "cc"
     154                 :            : #define __GUP_CLOBBER_8 "lr", "cc"
     155                 :            : 
     156                 :            : #define __get_user_x(__r2, __p, __e, __l, __s)                          \
     157                 :            :            __asm__ __volatile__ (                                       \
     158                 :            :                 __asmeq("%0", "r0") __asmeq("%1", "r2")                 \
     159                 :            :                 __asmeq("%3", "r1")                                 \
     160                 :            :                 "bl        __get_user_" #__s                          \
     161                 :            :                 : "=&r" (__e), "=r" (__r2)                              \
     162                 :            :                 : "0" (__p), "r" (__l)                                      \
     163                 :            :                 : __GUP_CLOBBER_##__s)
     164                 :            : 
     165                 :            : /* narrowing a double-word get into a single 32bit word register: */
     166                 :            : #ifdef __ARMEB__
     167                 :            : #define __get_user_x_32t(__r2, __p, __e, __l, __s)                      \
     168                 :            :         __get_user_x(__r2, __p, __e, __l, 32t_8)
     169                 :            : #else
     170                 :            : #define __get_user_x_32t __get_user_x
     171                 :            : #endif
     172                 :            : 
     173                 :            : /*
     174                 :            :  * storing result into proper least significant word of 64bit target var,
     175                 :            :  * different only for big endian case where 64 bit __r2 lsw is r3:
     176                 :            :  */
     177                 :            : #ifdef __ARMEB__
     178                 :            : #define __get_user_x_64t(__r2, __p, __e, __l, __s)                      \
     179                 :            :            __asm__ __volatile__ (                                       \
     180                 :            :                 __asmeq("%0", "r0") __asmeq("%1", "r2")                 \
     181                 :            :                 __asmeq("%3", "r1")                                 \
     182                 :            :                 "bl        __get_user_64t_" #__s                              \
     183                 :            :                 : "=&r" (__e), "=r" (__r2)                              \
     184                 :            :                 : "0" (__p), "r" (__l)                                      \
     185                 :            :                 : __GUP_CLOBBER_##__s)
     186                 :            : #else
     187                 :            : #define __get_user_x_64t __get_user_x
     188                 :            : #endif
     189                 :            : 
     190                 :            : 
     191                 :            : #define __get_user_check(x, p)                                          \
     192                 :            :         ({                                                              \
     193                 :            :                 unsigned long __limit = current_thread_info()->addr_limit - 1; \
     194                 :            :                 register typeof(*(p)) __user *__p asm("r0") = (p);    \
     195                 :            :                 register __inttype(x) __r2 asm("r2");                 \
     196                 :            :                 register unsigned long __l asm("r1") = __limit;               \
     197                 :            :                 register int __e asm("r0");                           \
     198                 :            :                 unsigned int __ua_flags = uaccess_save_and_enable();    \
     199                 :            :                 switch (sizeof(*(__p))) {                               \
     200                 :            :                 case 1:                                                 \
     201                 :            :                         if (sizeof((x)) >= 8)                                \
     202                 :            :                                 __get_user_x_64t(__r2, __p, __e, __l, 1); \
     203                 :            :                         else                                            \
     204                 :            :                                 __get_user_x(__r2, __p, __e, __l, 1);   \
     205                 :            :                         break;                                          \
     206                 :            :                 case 2:                                                 \
     207                 :            :                         if (sizeof((x)) >= 8)                                \
     208                 :            :                                 __get_user_x_64t(__r2, __p, __e, __l, 2); \
     209                 :            :                         else                                            \
     210                 :            :                                 __get_user_x(__r2, __p, __e, __l, 2);   \
     211                 :            :                         break;                                          \
     212                 :            :                 case 4:                                                 \
     213                 :            :                         if (sizeof((x)) >= 8)                                \
     214                 :            :                                 __get_user_x_64t(__r2, __p, __e, __l, 4); \
     215                 :            :                         else                                            \
     216                 :            :                                 __get_user_x(__r2, __p, __e, __l, 4);   \
     217                 :            :                         break;                                          \
     218                 :            :                 case 8:                                                 \
     219                 :            :                         if (sizeof((x)) < 8)                         \
     220                 :            :                                 __get_user_x_32t(__r2, __p, __e, __l, 4); \
     221                 :            :                         else                                            \
     222                 :            :                                 __get_user_x(__r2, __p, __e, __l, 8);   \
     223                 :            :                         break;                                          \
     224                 :            :                 default: __e = __get_user_bad(); break;                 \
     225                 :            :                 }                                                       \
     226                 :            :                 uaccess_restore(__ua_flags);                            \
     227                 :            :                 x = (typeof(*(p))) __r2;                                \
     228                 :            :                 __e;                                                    \
     229                 :            :         })
     230                 :            : 
     231                 :            : #define get_user(x, p)                                                  \
     232                 :            :         ({                                                              \
     233                 :            :                 might_fault();                                          \
     234                 :            :                 __get_user_check(x, p);                                 \
     235                 :            :          })
     236                 :            : 
     237                 :            : extern int __put_user_1(void *, unsigned int);
     238                 :            : extern int __put_user_2(void *, unsigned int);
     239                 :            : extern int __put_user_4(void *, unsigned int);
     240                 :            : extern int __put_user_8(void *, unsigned long long);
     241                 :            : 
     242                 :            : #define __put_user_check(__pu_val, __ptr, __err, __s)                   \
     243                 :            :         ({                                                              \
     244                 :            :                 unsigned long __limit = current_thread_info()->addr_limit - 1; \
     245                 :            :                 register typeof(__pu_val) __r2 asm("r2") = __pu_val;  \
     246                 :            :                 register const void __user *__p asm("r0") = __ptr;    \
     247                 :            :                 register unsigned long __l asm("r1") = __limit;               \
     248                 :            :                 register int __e asm("r0");                           \
     249                 :            :                 __asm__ __volatile__ (                                  \
     250                 :            :                         __asmeq("%0", "r0") __asmeq("%2", "r2")         \
     251                 :            :                         __asmeq("%3", "r1")                         \
     252                 :            :                         "bl        __put_user_" #__s                  \
     253                 :            :                         : "=&r" (__e)                                     \
     254                 :            :                         : "0" (__p), "r" (__r2), "r" (__l)                \
     255                 :            :                         : "ip", "lr", "cc");                              \
     256                 :            :                 __err = __e;                                            \
     257                 :            :         })
     258                 :            : 
     259                 :            : #else /* CONFIG_MMU */
     260                 :            : 
     261                 :            : /*
     262                 :            :  * uClinux has only one addr space, so has simplified address limits.
     263                 :            :  */
     264                 :            : #define USER_DS                 KERNEL_DS
     265                 :            : 
     266                 :            : #define segment_eq(a, b)                (1)
     267                 :            : #define __addr_ok(addr)         ((void)(addr), 1)
     268                 :            : #define __range_ok(addr, size)  ((void)(addr), 0)
     269                 :            : #define get_fs()                (KERNEL_DS)
     270                 :            : 
     271                 :            : static inline void set_fs(mm_segment_t fs)
     272                 :            : {
     273                 :            : }
     274                 :            : 
     275                 :            : #define get_user(x, p)  __get_user(x, p)
     276                 :            : #define __put_user_check __put_user_nocheck
     277                 :            : 
     278                 :            : #endif /* CONFIG_MMU */
     279                 :            : 
     280                 :            : #define access_ok(addr, size)   (__range_ok(addr, size) == 0)
     281                 :            : 
     282                 :            : #define user_addr_max() \
     283                 :            :         (uaccess_kernel() ? ~0UL : get_fs())
     284                 :            : 
     285                 :            : #ifdef CONFIG_CPU_SPECTRE
     286                 :            : /*
     287                 :            :  * When mitigating Spectre variant 1, it is not worth fixing the non-
     288                 :            :  * verifying accessors, because we need to add verification of the
     289                 :            :  * address space there.  Force these to use the standard get_user()
     290                 :            :  * version instead.
     291                 :            :  */
     292                 :            : #define __get_user(x, ptr) get_user(x, ptr)
     293                 :            : #else
     294                 :            : 
     295                 :            : /*
     296                 :            :  * The "__xxx" versions of the user access functions do not verify the
     297                 :            :  * address space - it must have been done previously with a separate
     298                 :            :  * "access_ok()" call.
     299                 :            :  *
     300                 :            :  * The "xxx_error" versions set the third argument to EFAULT if an
     301                 :            :  * error occurs, and leave it unchanged on success.  Note that these
     302                 :            :  * versions are void (ie, don't return a value as such).
     303                 :            :  */
     304                 :            : #define __get_user(x, ptr)                                              \
     305                 :            : ({                                                                      \
     306                 :            :         long __gu_err = 0;                                              \
     307                 :            :         __get_user_err((x), (ptr), __gu_err);                           \
     308                 :            :         __gu_err;                                                       \
     309                 :            : })
     310                 :            : 
     311                 :            : #define __get_user_err(x, ptr, err)                                     \
     312                 :            : do {                                                                    \
     313                 :            :         unsigned long __gu_addr = (unsigned long)(ptr);                 \
     314                 :            :         unsigned long __gu_val;                                         \
     315                 :            :         unsigned int __ua_flags;                                        \
     316                 :            :         __chk_user_ptr(ptr);                                            \
     317                 :            :         might_fault();                                                  \
     318                 :            :         __ua_flags = uaccess_save_and_enable();                         \
     319                 :            :         switch (sizeof(*(ptr))) {                                       \
     320                 :            :         case 1: __get_user_asm_byte(__gu_val, __gu_addr, err);  break;  \
     321                 :            :         case 2: __get_user_asm_half(__gu_val, __gu_addr, err);  break;  \
     322                 :            :         case 4: __get_user_asm_word(__gu_val, __gu_addr, err);  break;  \
     323                 :            :         default: (__gu_val) = __get_user_bad();                         \
     324                 :            :         }                                                               \
     325                 :            :         uaccess_restore(__ua_flags);                                    \
     326                 :            :         (x) = (__typeof__(*(ptr)))__gu_val;                             \
     327                 :            : } while (0)
     328                 :            : 
     329                 :            : #define __get_user_asm(x, addr, err, instr)                     \
     330                 :            :         __asm__ __volatile__(                                   \
     331                 :            :         "1:        " TUSER(instr) " %1, [%2], #0\n"         \
     332                 :            :         "2:\n"                                                        \
     333                 :            :         "  .pushsection .text.fixup,\"ax\"\n"               \
     334                 :            :         "  .align  2\n"                                       \
     335                 :            :         "3:        mov     %0, %3\n"                          \
     336                 :            :         "  mov     %1, #0\n"                          \
     337                 :            :         "  b       2b\n"                                      \
     338                 :            :         "  .popsection\n"                                     \
     339                 :            :         "  .pushsection __ex_table,\"a\"\n"         \
     340                 :            :         "  .align  3\n"                                       \
     341                 :            :         "  .long   1b, 3b\n"                          \
     342                 :            :         "  .popsection"                                       \
     343                 :            :         : "+r" (err), "=&r" (x)                                 \
     344                 :            :         : "r" (addr), "i" (-EFAULT)                         \
     345                 :            :         : "cc")
     346                 :            : 
     347                 :            : #define __get_user_asm_byte(x, addr, err)                       \
     348                 :            :         __get_user_asm(x, addr, err, ldrb)
     349                 :            : 
     350                 :            : #if __LINUX_ARM_ARCH__ >= 6
     351                 :            : 
     352                 :            : #define __get_user_asm_half(x, addr, err)                       \
     353                 :            :         __get_user_asm(x, addr, err, ldrh)
     354                 :            : 
     355                 :            : #else
     356                 :            : 
     357                 :            : #ifndef __ARMEB__
     358                 :            : #define __get_user_asm_half(x, __gu_addr, err)                  \
     359                 :            : ({                                                              \
     360                 :            :         unsigned long __b1, __b2;                               \
     361                 :            :         __get_user_asm_byte(__b1, __gu_addr, err);              \
     362                 :            :         __get_user_asm_byte(__b2, __gu_addr + 1, err);          \
     363                 :            :         (x) = __b1 | (__b2 << 8);                         \
     364                 :            : })
     365                 :            : #else
     366                 :            : #define __get_user_asm_half(x, __gu_addr, err)                  \
     367                 :            : ({                                                              \
     368                 :            :         unsigned long __b1, __b2;                               \
     369                 :            :         __get_user_asm_byte(__b1, __gu_addr, err);              \
     370                 :            :         __get_user_asm_byte(__b2, __gu_addr + 1, err);          \
     371                 :            :         (x) = (__b1 << 8) | __b2;                         \
     372                 :            : })
     373                 :            : #endif
     374                 :            : 
     375                 :            : #endif /* __LINUX_ARM_ARCH__ >= 6 */
     376                 :            : 
     377                 :            : #define __get_user_asm_word(x, addr, err)                       \
     378                 :            :         __get_user_asm(x, addr, err, ldr)
     379                 :            : #endif
     380                 :            : 
     381                 :            : 
     382                 :            : #define __put_user_switch(x, ptr, __err, __fn)                          \
     383                 :            :         do {                                                            \
     384                 :            :                 const __typeof__(*(ptr)) __user *__pu_ptr = (ptr);      \
     385                 :            :                 __typeof__(*(ptr)) __pu_val = (x);                      \
     386                 :            :                 unsigned int __ua_flags;                                \
     387                 :            :                 might_fault();                                          \
     388                 :            :                 __ua_flags = uaccess_save_and_enable();                 \
     389                 :            :                 switch (sizeof(*(ptr))) {                               \
     390                 :            :                 case 1: __fn(__pu_val, __pu_ptr, __err, 1); break;      \
     391                 :            :                 case 2: __fn(__pu_val, __pu_ptr, __err, 2); break;      \
     392                 :            :                 case 4: __fn(__pu_val, __pu_ptr, __err, 4); break;      \
     393                 :            :                 case 8: __fn(__pu_val, __pu_ptr, __err, 8); break;      \
     394                 :            :                 default: __err = __put_user_bad(); break;               \
     395                 :            :                 }                                                       \
     396                 :            :                 uaccess_restore(__ua_flags);                            \
     397                 :            :         } while (0)
     398                 :            : 
     399                 :            : #define put_user(x, ptr)                                                \
     400                 :            : ({                                                                      \
     401                 :            :         int __pu_err = 0;                                               \
     402                 :            :         __put_user_switch((x), (ptr), __pu_err, __put_user_check);      \
     403                 :            :         __pu_err;                                                       \
     404                 :            : })
     405                 :            : 
     406                 :            : #ifdef CONFIG_CPU_SPECTRE
     407                 :            : /*
     408                 :            :  * When mitigating Spectre variant 1.1, all accessors need to include
     409                 :            :  * verification of the address space.
     410                 :            :  */
     411                 :            : #define __put_user(x, ptr) put_user(x, ptr)
     412                 :            : 
     413                 :            : #else
     414                 :            : #define __put_user(x, ptr)                                              \
     415                 :            : ({                                                                      \
     416                 :            :         long __pu_err = 0;                                              \
     417                 :            :         __put_user_switch((x), (ptr), __pu_err, __put_user_nocheck);    \
     418                 :            :         __pu_err;                                                       \
     419                 :            : })
     420                 :            : 
     421                 :            : #define __put_user_nocheck(x, __pu_ptr, __err, __size)                  \
     422                 :            :         do {                                                            \
     423                 :            :                 unsigned long __pu_addr = (unsigned long)__pu_ptr;      \
     424                 :            :                 __put_user_nocheck_##__size(x, __pu_addr, __err);       \
     425                 :            :         } while (0)
     426                 :            : 
     427                 :            : #define __put_user_nocheck_1 __put_user_asm_byte
     428                 :            : #define __put_user_nocheck_2 __put_user_asm_half
     429                 :            : #define __put_user_nocheck_4 __put_user_asm_word
     430                 :            : #define __put_user_nocheck_8 __put_user_asm_dword
     431                 :            : 
     432                 :            : #define __put_user_asm(x, __pu_addr, err, instr)                \
     433                 :            :         __asm__ __volatile__(                                   \
     434                 :            :         "1:        " TUSER(instr) " %1, [%2], #0\n"         \
     435                 :            :         "2:\n"                                                        \
     436                 :            :         "  .pushsection .text.fixup,\"ax\"\n"               \
     437                 :            :         "  .align  2\n"                                       \
     438                 :            :         "3:        mov     %0, %3\n"                          \
     439                 :            :         "  b       2b\n"                                      \
     440                 :            :         "  .popsection\n"                                     \
     441                 :            :         "  .pushsection __ex_table,\"a\"\n"         \
     442                 :            :         "  .align  3\n"                                       \
     443                 :            :         "  .long   1b, 3b\n"                          \
     444                 :            :         "  .popsection"                                       \
     445                 :            :         : "+r" (err)                                          \
     446                 :            :         : "r" (x), "r" (__pu_addr), "i" (-EFAULT)         \
     447                 :            :         : "cc")
     448                 :            : 
     449                 :            : #define __put_user_asm_byte(x, __pu_addr, err)                  \
     450                 :            :         __put_user_asm(x, __pu_addr, err, strb)
     451                 :            : 
     452                 :            : #if __LINUX_ARM_ARCH__ >= 6
     453                 :            : 
     454                 :            : #define __put_user_asm_half(x, __pu_addr, err)                  \
     455                 :            :         __put_user_asm(x, __pu_addr, err, strh)
     456                 :            : 
     457                 :            : #else
     458                 :            : 
     459                 :            : #ifndef __ARMEB__
     460                 :            : #define __put_user_asm_half(x, __pu_addr, err)                  \
     461                 :            : ({                                                              \
     462                 :            :         unsigned long __temp = (__force unsigned long)(x);      \
     463                 :            :         __put_user_asm_byte(__temp, __pu_addr, err);            \
     464                 :            :         __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err);     \
     465                 :            : })
     466                 :            : #else
     467                 :            : #define __put_user_asm_half(x, __pu_addr, err)                  \
     468                 :            : ({                                                              \
     469                 :            :         unsigned long __temp = (__force unsigned long)(x);      \
     470                 :            :         __put_user_asm_byte(__temp >> 8, __pu_addr, err); \
     471                 :            :         __put_user_asm_byte(__temp, __pu_addr + 1, err);        \
     472                 :            : })
     473                 :            : #endif
     474                 :            : 
     475                 :            : #endif /* __LINUX_ARM_ARCH__ >= 6 */
     476                 :            : 
     477                 :            : #define __put_user_asm_word(x, __pu_addr, err)                  \
     478                 :            :         __put_user_asm(x, __pu_addr, err, str)
     479                 :            : 
     480                 :            : #ifndef __ARMEB__
     481                 :            : #define __reg_oper0     "%R2"
     482                 :            : #define __reg_oper1     "%Q2"
     483                 :            : #else
     484                 :            : #define __reg_oper0     "%Q2"
     485                 :            : #define __reg_oper1     "%R2"
     486                 :            : #endif
     487                 :            : 
     488                 :            : #define __put_user_asm_dword(x, __pu_addr, err)                 \
     489                 :            :         __asm__ __volatile__(                                   \
     490                 :            :  ARM(   "1:        " TUSER(str) "        " __reg_oper1 ", [%1], #4\n"     ) \
     491                 :            :  ARM(   "2:        " TUSER(str) "        " __reg_oper0 ", [%1]\n" ) \
     492                 :            :  THUMB( "1:        " TUSER(str) "        " __reg_oper1 ", [%1]\n" ) \
     493                 :            :  THUMB( "2:        " TUSER(str) "        " __reg_oper0 ", [%1, #4]\n"     ) \
     494                 :            :         "3:\n"                                                        \
     495                 :            :         "  .pushsection .text.fixup,\"ax\"\n"               \
     496                 :            :         "  .align  2\n"                                       \
     497                 :            :         "4:        mov     %0, %3\n"                          \
     498                 :            :         "  b       3b\n"                                      \
     499                 :            :         "  .popsection\n"                                     \
     500                 :            :         "  .pushsection __ex_table,\"a\"\n"         \
     501                 :            :         "  .align  3\n"                                       \
     502                 :            :         "  .long   1b, 4b\n"                          \
     503                 :            :         "  .long   2b, 4b\n"                          \
     504                 :            :         "  .popsection"                                       \
     505                 :            :         : "+r" (err), "+r" (__pu_addr)                              \
     506                 :            :         : "r" (x), "i" (-EFAULT)                            \
     507                 :            :         : "cc")
     508                 :            : 
     509                 :            : #endif /* !CONFIG_CPU_SPECTRE */
     510                 :            : 
     511                 :            : #ifdef CONFIG_MMU
     512                 :            : extern unsigned long __must_check
     513                 :            : arm_copy_from_user(void *to, const void __user *from, unsigned long n);
     514                 :            : 
     515                 :            : extern unsigned long __must_check
     516                 :            : __copy_from_user_std(void *to, const void __user *from, unsigned long n);
     517                 :            : 
     518                 :            : static inline unsigned long __must_check
     519                 :    8107583 : raw_copy_from_user(void *to, const void __user *from, unsigned long n)
     520                 :            : {
     521                 :            :         unsigned int __ua_flags;
     522                 :            : 
     523                 :            :         __ua_flags = uaccess_save_and_enable();
     524                 :   31231506 :         n = arm_copy_from_user(to, from, n);
     525                 :            :         uaccess_restore(__ua_flags);
     526                 :    8107868 :         return n;
     527                 :            : }
     528                 :            : 
     529                 :            : extern unsigned long __must_check
     530                 :            : arm_copy_to_user(void __user *to, const void *from, unsigned long n);
     531                 :            : extern unsigned long __must_check
     532                 :            : __copy_to_user_std(void __user *to, const void *from, unsigned long n);
     533                 :            : 
     534                 :            : static inline unsigned long __must_check
     535                 :   30146568 : raw_copy_to_user(void __user *to, const void *from, unsigned long n)
     536                 :            : {
     537                 :            : #ifndef CONFIG_UACCESS_WITH_MEMCPY
     538                 :            :         unsigned int __ua_flags;
     539                 :            :         __ua_flags = uaccess_save_and_enable();
     540                 :            :         n = arm_copy_to_user(to, from, n);
     541                 :            :         uaccess_restore(__ua_flags);
     542                 :            :         return n;
     543                 :            : #else
     544                 :  109387975 :         return arm_copy_to_user(to, from, n);
     545                 :            : #endif
     546                 :            : }
     547                 :            : 
     548                 :            : extern unsigned long __must_check
     549                 :            : arm_clear_user(void __user *addr, unsigned long n);
     550                 :            : extern unsigned long __must_check
     551                 :            : __clear_user_std(void __user *addr, unsigned long n);
     552                 :            : 
     553                 :            : static inline unsigned long __must_check
     554                 :            : __clear_user(void __user *addr, unsigned long n)
     555                 :            : {
     556                 :            :         unsigned int __ua_flags = uaccess_save_and_enable();
     557                 :     578575 :         n = arm_clear_user(addr, n);
     558                 :            :         uaccess_restore(__ua_flags);
     559                 :            :         return n;
     560                 :            : }
     561                 :            : 
     562                 :            : #else
     563                 :            : static inline unsigned long
     564                 :            : raw_copy_from_user(void *to, const void __user *from, unsigned long n)
     565                 :            : {
     566                 :            :         memcpy(to, (const void __force *)from, n);
     567                 :            :         return 0;
     568                 :            : }
     569                 :            : static inline unsigned long
     570                 :            : raw_copy_to_user(void __user *to, const void *from, unsigned long n)
     571                 :            : {
     572                 :            :         memcpy((void __force *)to, from, n);
     573                 :            :         return 0;
     574                 :            : }
     575                 :            : #define __clear_user(addr, n)           (memset((void __force *)addr, 0, n), 0)
     576                 :            : #endif
     577                 :            : #define INLINE_COPY_TO_USER
     578                 :            : #define INLINE_COPY_FROM_USER
     579                 :            : 
     580                 :     578620 : static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
     581                 :            : {
     582         [ +  + ]:     578620 :         if (access_ok(to, n))
     583                 :            :                 n = __clear_user(to, n);
     584                 :     578869 :         return n;
     585                 :            : }
     586                 :            : 
     587                 :            : /* These are from lib/ code, and use __get_user() and friends */
     588                 :            : extern long strncpy_from_user(char *dest, const char __user *src, long count);
     589                 :            : 
     590                 :            : extern __must_check long strnlen_user(const char __user *str, long n);
     591                 :            : 
     592                 :            : #endif /* _ASMARM_UACCESS_H */

Generated by: LCOV version 1.14