aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/plugin/infoleak-net-ethtool-ioctl.c
blob: 52846c40f8638320c0d8678e715397306a40fe2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/* Reduced from infoleak false positive seen on Linux kernel with
   net/ethtool/ioctl.c  */

/* { dg-do compile } */
/* { dg-options "-std=gnu17 -fanalyzer" } */
/* { dg-require-effective-target analyzer } */

typedef signed char __s8;
typedef unsigned char __u8;
typedef unsigned int __u32;
typedef __s8 s8;
typedef __u32 u32;
enum { false = 0, true = 1 };
typedef unsigned long __kernel_ulong_t;
typedef __kernel_ulong_t __kernel_size_t;
typedef _Bool bool;
typedef __kernel_size_t size_t;

void *memset(void *s, int c, size_t n);

extern bool
check_copy_size(const void *addr, size_t bytes, bool is_source);
extern unsigned long
_copy_from_user(void *, const void *, unsigned long);
extern unsigned long
_copy_to_user(void *, const void *, unsigned long);

static inline
__attribute__((__always_inline__)) unsigned long
copy_from_user(void *to, const void *from, unsigned long n) {
  if (__builtin_expect(!!(check_copy_size(to, n, false)), 1))
    n = _copy_from_user(to, from, n);
  return n;
}
static inline
__attribute__((__always_inline__)) unsigned long
copy_to_user(void *to, const void *from, unsigned long n) {
  if (__builtin_expect(!!(check_copy_size(from, n, true)), 1))
    n = _copy_to_user(to, from, n);
  return n;
}
enum ethtool_link_mode_bit_indices {
  __ETHTOOL_LINK_MODE_MASK_NBITS = 92
};
struct ethtool_link_settings {
  __u32 cmd;
  /* [...snip...] */
  __s8 link_mode_masks_nwords;
  /* [...snip...] */
};

struct ethtool_link_ksettings {
  struct ethtool_link_settings base;
  u32 lanes;
};

int ethtool_get_link_ksettings(void *useraddr) {
  int err = 0;
  struct ethtool_link_ksettings link_ksettings;

  if (copy_from_user(&link_ksettings.base, useraddr,
                     sizeof(link_ksettings.base)))
    return -14;

  if ((((__ETHTOOL_LINK_MODE_MASK_NBITS) + (32) - 1) / (32)) !=
      link_ksettings.base.link_mode_masks_nwords) {

    memset(&link_ksettings, 0, sizeof(link_ksettings));
    link_ksettings.base.cmd = 0x0000004c;

    link_ksettings.base.link_mode_masks_nwords =
        -((s8)(((__ETHTOOL_LINK_MODE_MASK_NBITS) + (32) - 1) / (32)));

    if (copy_to_user(useraddr, &link_ksettings.base,
                     sizeof(link_ksettings.base)))
      return -14;

    return 0;
  }

  return 0;
}