Skip to content

Commit

Permalink
treewide: use prandom_u32_max() when possible, part 1
Browse files Browse the repository at this point in the history
Rather than incurring a division or requesting too many random bytes for
the given range, use the prandom_u32_max() function, which only takes
the minimum required bytes from the RNG and avoids divisions. This was
done mechanically with this coccinelle script:

@basic@
expression E;
type T;
identifier get_random_u32 =~ "get_random_int|prandom_u32|get_random_u32";
typedef u64;
@@
(
- ((T)get_random_u32() % (E))
+ prandom_u32_max(E)
|
- ((T)get_random_u32() & ((E) - 1))
+ prandom_u32_max(E * XXX_MAKE_SURE_E_IS_POW2)
|
- ((u64)(E) * get_random_u32() >> 32)
+ prandom_u32_max(E)
|
- ((T)get_random_u32() & ~PAGE_MASK)
+ prandom_u32_max(PAGE_SIZE)
)

@multi_line@
identifier get_random_u32 =~ "get_random_int|prandom_u32|get_random_u32";
identifier RAND;
expression E;
@@

-       RAND = get_random_u32();
        ... when != RAND
-       RAND %= (E);
+       RAND = prandom_u32_max(E);

// Find a potential literal
@literal_mask@
expression LITERAL;
type T;
identifier get_random_u32 =~ "get_random_int|prandom_u32|get_random_u32";
position p;
@@

        ((T)get_random_u32()@p & (LITERAL))

// Add one to the literal.
@script:python add_one@
literal << literal_mask.LITERAL;
RESULT;
@@

value = None
if literal.startswith('0x'):
        value = int(literal, 16)
elif literal[0] in '123456789':
        value = int(literal, 10)
if value is None:
        print("I don't know how to handle %s" % (literal))
        cocci.include_match(False)
elif value == 2**32 - 1 or value == 2**31 - 1 or value == 2**24 - 1 or value == 2**16 - 1 or value == 2**8 - 1:
        print("Skipping 0x%x for cleanup elsewhere" % (value))
        cocci.include_match(False)
elif value & (value + 1) != 0:
        print("Skipping 0x%x because it's not a power of two minus one" % (value))
        cocci.include_match(False)
elif literal.startswith('0x'):
        coccinelle.RESULT = cocci.make_expr("0x%x" % (value + 1))
else:
        coccinelle.RESULT = cocci.make_expr("%d" % (value + 1))

// Replace the literal mask with the calculated result.
@plus_one@
expression literal_mask.LITERAL;
position literal_mask.p;
expression add_one.RESULT;
identifier FUNC;
@@

-       (FUNC()@p & (LITERAL))
+       prandom_u32_max(RESULT)

@collapse_ret@
type T;
identifier VAR;
expression E;
@@

 {
-       T VAR;
-       VAR = (E);
-       return VAR;
+       return E;
 }

@drop_var@
type T;
identifier VAR;
@@

 {
-       T VAR;
        ... when != VAR
 }

Reviewed-by: Greg Kroah-Hartman <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Reviewed-by: Yury Norov <[email protected]>
Reviewed-by: KP Singh <[email protected]>
Reviewed-by: Jan Kara <[email protected]> # for ext4 and sbitmap
Reviewed-by: Christoph Böhmwalder <[email protected]> # for drbd
Acked-by: Jakub Kicinski <[email protected]>
Acked-by: Heiko Carstens <[email protected]> # for s390
Acked-by: Ulf Hansson <[email protected]> # for mmc
Acked-by: Darrick J. Wong <[email protected]> # for xfs
Signed-off-by: Jason A. Donenfeld <[email protected]>
  • Loading branch information
zx2c4 committed Oct 11, 2022
1 parent d465bff commit 81895a6
Show file tree
Hide file tree
Showing 89 changed files with 204 additions and 218 deletions.
2 changes: 1 addition & 1 deletion arch/arm/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ static unsigned long sigpage_addr(const struct mm_struct *mm,

slots = ((last - first) >> PAGE_SHIFT) + 1;

offset = get_random_int() % slots;
offset = prandom_u32_max(slots);

addr = first + (offset << PAGE_SHIFT);

Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ unsigned long __get_wchan(struct task_struct *p)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() & ~PAGE_MASK;
sp -= prandom_u32_max(PAGE_SIZE);
return sp & ~0xf;
}

Expand Down
2 changes: 1 addition & 1 deletion arch/loongarch/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ unsigned long stack_top(void)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() & ~PAGE_MASK;
sp -= prandom_u32_max(PAGE_SIZE);

return sp & STACK_ALIGN;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/loongarch/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static unsigned long vdso_base(void)
unsigned long base = STACK_TOP;

if (current->flags & PF_RANDOMIZE) {
base += get_random_int() & (VDSO_RANDOMIZE_SIZE - 1);
base += prandom_u32_max(VDSO_RANDOMIZE_SIZE);
base = PAGE_ALIGN(base);
}

Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ unsigned long mips_stack_top(void)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() & ~PAGE_MASK;
sp -= prandom_u32_max(PAGE_SIZE);

return sp & ALMASK;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static unsigned long vdso_base(void)
}

if (current->flags & PF_RANDOMIZE) {
base += get_random_int() & (VDSO_RANDOMIZE_SIZE - 1);
base += prandom_u32_max(VDSO_RANDOMIZE_SIZE);
base = PAGE_ALIGN(base);
}

Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,

map_base = mm->mmap_base;
if (current->flags & PF_RANDOMIZE)
map_base -= (get_random_int() & 0x1f) * PAGE_SIZE;
map_base -= prandom_u32_max(0x20) * PAGE_SIZE;

vdso_text_start = get_unmapped_area(NULL, map_base, vdso_text_len, 0, 0);

Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -2308,6 +2308,6 @@ void notrace __ppc64_runlatch_off(void)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() & ~PAGE_MASK;
sp -= prandom_u32_max(PAGE_SIZE);
return sp & ~0xf;
}
2 changes: 1 addition & 1 deletion arch/s390/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ unsigned long __get_wchan(struct task_struct *p)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() & ~PAGE_MASK;
sp -= prandom_u32_max(PAGE_SIZE);
return sp & ~0xf;
}

Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ static unsigned long vdso_addr(unsigned long start, unsigned long len)
end -= len;

if (end > start) {
offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
offset = prandom_u32_max(((end - start) >> PAGE_SHIFT) + 1);
addr = start + (offset << PAGE_SHIFT);
} else {
addr = start;
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/vdso/vma.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ static unsigned long vdso_addr(unsigned long start, unsigned int len)
unsigned int offset;

/* This loses some more bits than a modulo, but is cheaper */
offset = get_random_int() & (PTRS_PER_PTE - 1);
offset = prandom_u32_max(PTRS_PER_PTE);
return start + (offset << PAGE_SHIFT);
}

Expand Down
2 changes: 1 addition & 1 deletion arch/um/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ int singlestepping(void * t)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() % 8192;
sp -= prandom_u32_max(8192);
return sp & ~0xf;
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/entry/vdso/vma.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
end -= len;

if (end > start) {
offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
offset = prandom_u32_max(((end - start) >> PAGE_SHIFT) + 1);
addr = start + (offset << PAGE_SHIFT);
} else {
addr = start;
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ static unsigned long int get_module_load_offset(void)
*/
if (module_load_offset == 0)
module_load_offset =
(get_random_int() % 1024 + 1) * PAGE_SIZE;
(prandom_u32_max(1024) + 1) * PAGE_SIZE;
mutex_unlock(&module_kaslr_mutex);
}
return module_load_offset;
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ early_param("idle", idle_setup);
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() % 8192;
sp -= prandom_u32_max(8192);
return sp & ~0xf;
}

Expand Down
4 changes: 2 additions & 2 deletions arch/x86/mm/pat/cpa-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@ static int pageattr_test(void)
failed += print_split(&sa);

for (i = 0; i < NTEST; i++) {
unsigned long pfn = prandom_u32() % max_pfn_mapped;
unsigned long pfn = prandom_u32_max(max_pfn_mapped);

addr[i] = (unsigned long)__va(pfn << PAGE_SHIFT);
len[i] = prandom_u32() % NPAGES;
len[i] = prandom_u32_max(NPAGES);
len[i] = min_t(unsigned long, len[i], max_pfn_mapped - pfn - 1);

if (len[i] == 0)
Expand Down
Loading

0 comments on commit 81895a6

Please sign in to comment.