(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
plugin/
taint-antipatterns-1.c
       1  /* { dg-do compile } */
       2  // TODO: remove need for -fanalyzer-checker=taint here:
       3  /* { dg-options "-fanalyzer -fanalyzer-checker=taint" } */
       4  /* { dg-require-effective-target analyzer } */
       5  
       6  #include "test-uaccess.h"
       7  
       8  /* Adapted and simplified decls from linux kernel headers.  */
       9  
      10  typedef unsigned char u8;
      11  typedef unsigned __INT16_TYPE__ u16;
      12  typedef unsigned __INT32_TYPE__ u32;
      13  typedef signed __INT32_TYPE__ s32;
      14  typedef __SIZE_TYPE__ size_t;
      15  
      16  #define   EFAULT          14
      17  
      18  typedef unsigned int gfp_t;
      19  #define GFP_KERNEL 0
      20  
      21  void kfree(const void *);
      22  void *kmalloc(size_t size, gfp_t flags)
      23    __attribute__((malloc (kfree)));
      24  
      25  /* Adapted from antipatterns.ko:taint.c (GPL-v2.0).   */
      26  
      27  struct cmd_1
      28  {
      29    u32 idx;
      30    u32 val;
      31  };
      32  
      33  static u32 arr[16];
      34  
      35  int taint_array_access(void __user *src)
      36  {
      37    struct cmd_1 cmd;
      38    if (copy_from_user(&cmd, src, sizeof(cmd)))
      39      return -EFAULT;
      40    /*
      41     * cmd.idx is an unsanitized value from user-space, hence
      42     * this is an arbitrary kernel memory access.
      43     */
      44    arr[cmd.idx] = cmd.val; /* { dg-warning "use of attacker-controlled value 'cmd.idx' in array lookup without upper-bounds checking" } */
      45    return 0;
      46  }
      47  
      48  struct cmd_2
      49  {
      50    s32 idx;
      51    u32 val;
      52  };
      53  
      54  int taint_signed_array_access(void __user *src)
      55  {
      56    struct cmd_2 cmd;
      57    if (copy_from_user(&cmd, src, sizeof(cmd)))
      58      return -EFAULT;
      59    if (cmd.idx >= 16)
      60      return -EFAULT;
      61  
      62    /*
      63     * cmd.idx hasn't been checked for being negative, hence
      64     * this is an arbitrary kernel memory access.
      65     */
      66    arr[cmd.idx] = cmd.val; /* { dg-warning "use of attacker-controlled value 'cmd.idx' in array lookup without checking for negative" } */
      67    return 0;
      68  }
      69  
      70  struct cmd_s32_binop
      71  {
      72    s32 a;
      73    s32 b;
      74    s32 result;
      75  };
      76  
      77  int taint_divide_by_zero_direct(void __user *uptr)
      78  {
      79    struct cmd_s32_binop cmd;
      80    if (copy_from_user(&cmd, uptr, sizeof(cmd)))
      81      return -EFAULT;
      82  
      83    /* cmd.b is attacker-controlled and could be zero */
      84    cmd.result = cmd.a / cmd.b; /* { dg-warning "use of attacker-controlled value 'cmd.b' as divisor without checking for zero" } */
      85  
      86    if (copy_to_user (uptr, &cmd, sizeof(cmd)))
      87      return -EFAULT;
      88    return 0;
      89  }
      90  
      91  int taint_divide_by_zero_compound(void __user *uptr)
      92  {
      93    struct cmd_s32_binop cmd;
      94    if (copy_from_user(&cmd, uptr, sizeof(cmd)))
      95      return -EFAULT;
      96  
      97    /*
      98     * cmd.b is attacker-controlled and could be -1, hence
      99     * the divisor could be zero
     100     */
     101    cmd.result = cmd.a / (cmd.b + 1); /* { dg-warning "use of attacker-controlled value 'cmd.b \\+ 1' as divisor without checking for zero" } */
     102  
     103    if (copy_to_user (uptr, &cmd, sizeof(cmd)))
     104      return -EFAULT;
     105    return 0;
     106  }
     107  
     108  int taint_mod_by_zero_direct(void __user *uptr)
     109  {
     110    struct cmd_s32_binop cmd;
     111    if (copy_from_user(&cmd, uptr, sizeof(cmd)))
     112      return -EFAULT;
     113  
     114    /* cmd.b is attacker-controlled and could be zero */
     115    cmd.result = cmd.a % cmd.b; /* { dg-warning "use of attacker-controlled value 'cmd.b' as divisor without checking for zero" } */
     116  
     117    if (copy_to_user (uptr, &cmd, sizeof(cmd)))
     118      return -EFAULT;
     119    return 0;
     120  }
     121  
     122  int taint_mod_by_zero_compound(void __user *uptr)
     123  {
     124    struct cmd_s32_binop cmd;
     125    if (copy_from_user(&cmd, uptr, sizeof(cmd)))
     126      return -EFAULT;
     127  
     128    /*
     129     * cmd.b is attacker-controlled and could be -1, hence
     130     * the divisor could be zero
     131     */
     132    cmd.result = cmd.a % (cmd.b + 1); /* { dg-warning "use of attacker-controlled value 'cmd.b \\+ 1' as divisor without checking for zero" } */
     133  
     134    if (copy_to_user (uptr, &cmd, sizeof(cmd)))
     135      return -EFAULT;
     136    return 0;
     137  }
     138  
     139  /* TODO: etc.  */