Blame view

include/linux/nospec.h 2.14 KB
478742cf8   Dan Williams   array_index_nospe...
1
2
3
4
5
6
7
  // SPDX-License-Identifier: GPL-2.0
  // Copyright(c) 2018 Linus Torvalds. All rights reserved.
  // Copyright(c) 2018 Alexei Starovoitov. All rights reserved.
  // Copyright(c) 2018 Intel Corporation. All rights reserved.
  
  #ifndef _LINUX_NOSPEC_H
  #define _LINUX_NOSPEC_H
2e19277e1   Dan Williams   nospec: Include <...
8
  #include <asm/barrier.h>
478742cf8   Dan Williams   array_index_nospe...
9

7d1254a14   Kees Cook   nospec: Allow get...
10
  struct task_struct;
478742cf8   Dan Williams   array_index_nospe...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /**
   * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
   * @index: array element index
   * @size: number of elements in array
   *
   * When @index is out of bounds (@index >= @size), the sign bit will be
   * set.  Extend the sign bit to all bits and invert, giving a result of
   * zero for an out of bounds index, or ~0 if within bounds [0, @size).
   */
  #ifndef array_index_mask_nospec
  static inline unsigned long array_index_mask_nospec(unsigned long index,
  						    unsigned long size)
  {
  	/*
478742cf8   Dan Williams   array_index_nospe...
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
  	 * Always calculate and emit the mask even if the compiler
  	 * thinks the mask is not needed. The compiler does not take
  	 * into account the value of @index under speculation.
  	 */
  	OPTIMIZER_HIDE_VAR(index);
  	return ~(long)(index | (size - 1UL - index)) >> (BITS_PER_LONG - 1);
  }
  #endif
  
  /*
   * array_index_nospec - sanitize an array index after a bounds check
   *
   * For a code sequence like:
   *
   *     if (index < size) {
   *         index = array_index_nospec(index, size);
   *         val = array[index];
   *     }
   *
   * ...if the CPU speculates past the bounds check then
   * array_index_nospec() will clamp the index within the range of [0,
   * size).
   */
  #define array_index_nospec(index, size)					\
  ({									\
  	typeof(index) _i = (index);					\
  	typeof(size) _s = (size);					\
bebe3994d   Dan Williams   nospec: Kill arra...
52
  	unsigned long _mask = array_index_mask_nospec(_i, _s);		\
478742cf8   Dan Williams   array_index_nospe...
53
54
55
56
  									\
  	BUILD_BUG_ON(sizeof(_i) > sizeof(long));			\
  	BUILD_BUG_ON(sizeof(_s) > sizeof(long));			\
  									\
656772cb7   Rasmus Villemoes   nospec: Allow ind...
57
  	(typeof(_i)) (_i & _mask);					\
478742cf8   Dan Williams   array_index_nospe...
58
  })
33f6a0681   Thomas Gleixner   prctl: Add specul...
59
60
  
  /* Speculation control prctl */
7d1254a14   Kees Cook   nospec: Allow get...
61
62
63
  int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which);
  int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
  			     unsigned long ctrl);
61dfdc12f   Thomas Gleixner   seccomp: Move spe...
64
65
  /* Speculation control for seccomp enforced mitigation */
  void arch_seccomp_spec_mitigate(struct task_struct *task);
33f6a0681   Thomas Gleixner   prctl: Add specul...
66

478742cf8   Dan Williams   array_index_nospe...
67
  #endif /* _LINUX_NOSPEC_H */