(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
plugin/
infoleak-antipatterns-1.c
       1  /* Adapted and simplified decls from linux kernel headers.  */
       2  
       3  /* { dg-do compile } */
       4  /* { dg-options "-fanalyzer" } */
       5  /* { dg-require-effective-target analyzer } */
       6  /* { dg-skip-if "structure layout assumption not met" { default_packed } } */
       7  
       8  typedef unsigned char u8;
       9  typedef unsigned __INT16_TYPE__ u16;
      10  typedef unsigned __INT32_TYPE__ u32;
      11  typedef __SIZE_TYPE__ size_t;
      12  
      13  #define   EFAULT          14
      14  
      15  #include "test-uaccess.h"
      16  
      17  typedef unsigned int gfp_t;
      18  #define GFP_KERNEL 0
      19  
      20  void kfree(const void *);
      21  void *kmalloc(size_t size, gfp_t flags)
      22    __attribute__((malloc (kfree)));
      23  
      24  /* Adapted from antipatterns.ko:infoleak.c (GPL-v2.0).   */
      25  
      26  struct infoleak_buf
      27  {
      28    char buf[256];
      29  };
      30  
      31  int infoleak_stack_no_init(void __user *dst)
      32  {
      33    struct infoleak_buf st; /* { dg-message "region created on stack here" "where" } */
      34    /* { dg-message "capacity: 256 bytes" "capacity" { target *-*-* } .-1 } */
      35    
      36    /* No initialization of "st" at all.  */
      37    if (copy_to_user(dst, &st, sizeof(st))) /* { dg-warning "potential exposure of sensitive information by copying uninitialized data from stack" "warning" } */
      38      /* { dg-message "256 bytes are uninitialized" "note how much" { target *-*-* } .-1 } */
      39      return -EFAULT;
      40    return 0;
      41  }
      42  
      43  int infoleak_heap_no_init(void __user *dst)
      44  {
      45    struct infoleak_buf *heapbuf = kmalloc(sizeof(*heapbuf), GFP_KERNEL);
      46    /* No initialization of "heapbuf" at all.  */
      47  
      48    /* TODO: we also don't check that heapbuf could be NULL when copying
      49       from it.  */
      50    if (copy_to_user(dst, heapbuf, sizeof(*heapbuf))) /* { dg-warning "exposure" "warning" { xfail *-*-* } } */
      51      /* TODO(xfail).  */
      52      return -EFAULT; /* { dg-warning "leak of 'heapbuf'" } */
      53  
      54    kfree(heapbuf);
      55    return 0;
      56  }
      57  
      58  struct infoleak_2
      59  {
      60    u32 a;
      61    u32 b; /* { dg-message "field 'b' is uninitialized \\(4 bytes\\)" } */
      62  };
      63  
      64  int infoleak_stack_missing_a_field(void __user *dst, u32 v)
      65  {
      66    struct infoleak_2 st; /* { dg-message "region created on stack here" "where" } */
      67    /* { dg-message "capacity: 8 bytes" "capacity" { target *-*-* } .-1 } */
      68    
      69    st.a = v;
      70    /* No initialization of "st.b".  */
      71    if (copy_to_user(dst, &st, sizeof(st))) /* { dg-warning "potential exposure of sensitive information by copying uninitialized data from stack" "warning" } */
      72      /* { dg-message "4 bytes are uninitialized" "note how much" { target *-*-* } .-1 } */
      73      return -EFAULT;
      74    return 0;
      75  }
      76  
      77  int infoleak_heap_missing_a_field(void __user *dst, u32 v)
      78  {
      79    struct infoleak_2 *heapbuf = kmalloc(sizeof(*heapbuf), GFP_KERNEL);
      80    heapbuf->a = v; /* { dg-warning "dereference of possibly-NULL 'heapbuf'" } */
      81    /* No initialization of "heapbuf->b".  */
      82    if (copy_to_user(dst, heapbuf, sizeof(*heapbuf))) /* { dg-warning "exposure" "warning" { xfail *-*-* } } */
      83      /* TODO(xfail).  */
      84      {
      85        kfree(heapbuf);
      86        return -EFAULT;
      87      }
      88    kfree(heapbuf);
      89    return 0;
      90  }
      91  
      92  struct infoleak_3
      93  {
      94    u8 a; /* { dg-message "padding after field 'a' is uninitialized \\(3 bytes\\)" } */
      95    /* padding here */
      96    u32 b;
      97  };
      98  
      99  int infoleak_stack_padding(void __user *dst, u8 p, u32 q)
     100  {
     101    struct infoleak_3 st; /* { dg-message "region created on stack here" "where" } */
     102    /* { dg-message "capacity: 8 bytes" "capacity" { target *-*-* } .-1 } */
     103  
     104    st.a = p;
     105    st.b = q;
     106    /* No initialization of padding.  */
     107    if (copy_to_user(dst, &st, sizeof(st))) /* { dg-warning "potential exposure of sensitive information by copying uninitialized data from stack" "warning" } */
     108      /* { dg-message "3 bytes are uninitialized" "note how much" { target *-*-* } .-1 } */
     109      return -EFAULT;
     110    return 0;
     111  }
     112  
     113  int infoleak_stack_unchecked_err(void __user *dst, void __user *src)
     114  {
     115    struct infoleak_buf st;  /* { dg-message "region created on stack here" "where" } */
     116    /* { dg-message "capacity: 256 bytes" "capacity" { target *-*-* } .-1 } */
     117  
     118    /*
     119     * If the copy_from_user call fails, then st is still uninitialized,
     120     * and if the copy_to_user call succeds, we have an infoleak.
     121     */
     122    int err = copy_from_user (&st, src, sizeof(st)); /* { dg-message "when 'copy_from_user' fails" } */
     123    err |= copy_to_user (dst, &st, sizeof(st)); /* { dg-warning "exposure" "warning" } */
     124    /* { dg-message "256 bytes are uninitialized" "note how much" { target *-*-* } .-1 } */
     125    /* Actually, it's *up to* 256 bytes.  */
     126  
     127    if (err)
     128      return -EFAULT;
     129    return 0;
     130  }
     131  
     132  struct infoleak_4
     133  {
     134    union {
     135      u8 f1;
     136      u32 f2;
     137    } u;
     138  };
     139  
     140  int infoleak_stack_union(void __user *dst, u8 v)
     141  {
     142    struct infoleak_4 st;
     143    /*
     144     * This write only initializes the u8 within the union "u",
     145     * leaving the remaining 3 bytes uninitialized.
     146     */
     147    st.u.f1 = v;
     148    if (copy_to_user(dst, &st, sizeof(st))) /* { dg-warning "potential exposure of sensitive information by copying uninitialized data from stack" "warning" } */
     149      /* { dg-message "3 bytes are uninitialized" "note how much" { target *-*-* } .-1 } */
     150      return -EFAULT;
     151    return 0;
     152  }
     153  
     154  struct infoleak_5
     155  {
     156    void *ptr;
     157  };
     158  
     159  int infoleak_stack_kernel_ptr(void __user *dst, void *kp)
     160  {
     161    struct infoleak_5 st;
     162    /* This writes a kernel-space pointer into a user space buffer.  */
     163    st.ptr = kp;
     164    if (copy_to_user(dst, &st, sizeof(st))) // TODO: we don't complain about this yet
     165      return -EFAULT;
     166    return 0;
     167  }