Skip to content

Commit 8c1ed30

Browse files
committed
Merge tag 'ffs-const-v6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull ffs const-attribute cleanups from Kees Cook: "While working on various hardening refactoring a while back we encountered inconsistencies in the application of __attribute_const__ on the ffs() family of functions. This series fixes this across all archs and adds KUnit tests. Notably, this found a theoretical underflow in PCI (also fixed here) and uncovered an inefficiency in ARC (fixed in the ARC arch PR). I kept the series separate from the general hardening PR since it is a stand-alone "topic". - PCI: Fix theoretical underflow in use of ffs(). - Universally apply __attribute_const__ to all architecture's ffs()-family of functions. - Add KUnit tests for ffs() behavior and const-ness" * tag 'ffs-const-v6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: KUnit: ffs: Validate all the __attribute_const__ annotations sparc: Add __attribute_const__ to ffs()-family implementations xtensa: Add __attribute_const__ to ffs()-family implementations s390: Add __attribute_const__ to ffs()-family implementations parisc: Add __attribute_const__ to ffs()-family implementations mips: Add __attribute_const__ to ffs()-family implementations m68k: Add __attribute_const__ to ffs()-family implementations openrisc: Add __attribute_const__ to ffs()-family implementations riscv: Add __attribute_const__ to ffs()-family implementations hexagon: Add __attribute_const__ to ffs()-family implementations alpha: Add __attribute_const__ to ffs()-family implementations sh: Add __attribute_const__ to ffs()-family implementations powerpc: Add __attribute_const__ to ffs()-family implementations x86: Add __attribute_const__ to ffs()-family implementations csky: Add __attribute_const__ to ffs()-family implementations bitops: Add __attribute_const__ to generic ffs()-family implementations KUnit: Introduce ffs()-family tests PCI: Test for bit underflow in pcie_set_readrq()
2 parents 1896ce8 + 95719df commit 8c1ed30

31 files changed

Lines changed: 661 additions & 76 deletions

File tree

arch/alpha/include/asm/bitops.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ static inline unsigned long ffz_b(unsigned long x)
328328
return sum;
329329
}
330330

331-
static inline unsigned long ffz(unsigned long word)
331+
static inline unsigned long __attribute_const__ ffz(unsigned long word)
332332
{
333333
#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
334334
/* Whee. EV67 can calculate it directly. */
@@ -348,7 +348,7 @@ static inline unsigned long ffz(unsigned long word)
348348
/*
349349
* __ffs = Find First set bit in word. Undefined if no set bit exists.
350350
*/
351-
static inline unsigned long __ffs(unsigned long word)
351+
static inline __attribute_const__ unsigned long __ffs(unsigned long word)
352352
{
353353
#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
354354
/* Whee. EV67 can calculate it directly. */
@@ -373,7 +373,7 @@ static inline unsigned long __ffs(unsigned long word)
373373
* differs in spirit from the above __ffs.
374374
*/
375375

376-
static inline int ffs(int word)
376+
static inline __attribute_const__ int ffs(int word)
377377
{
378378
int result = __ffs(word) + 1;
379379
return word ? result : 0;
@@ -383,14 +383,14 @@ static inline int ffs(int word)
383383
* fls: find last bit set.
384384
*/
385385
#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
386-
static inline int fls64(unsigned long word)
386+
static inline __attribute_const__ int fls64(unsigned long word)
387387
{
388388
return 64 - __kernel_ctlz(word);
389389
}
390390
#else
391391
extern const unsigned char __flsm1_tab[256];
392392

393-
static inline int fls64(unsigned long x)
393+
static inline __attribute_const__ int fls64(unsigned long x)
394394
{
395395
unsigned long t, a, r;
396396

@@ -403,12 +403,12 @@ static inline int fls64(unsigned long x)
403403
}
404404
#endif
405405

406-
static inline unsigned long __fls(unsigned long x)
406+
static inline __attribute_const__ unsigned long __fls(unsigned long x)
407407
{
408408
return fls64(x) - 1;
409409
}
410410

411-
static inline int fls(unsigned int x)
411+
static inline __attribute_const__ int fls(unsigned int x)
412412
{
413413
return fls64(x);
414414
}

arch/csky/include/asm/bitops.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
/*
1010
* asm-generic/bitops/ffs.h
1111
*/
12-
static inline int ffs(int x)
12+
static inline __attribute_const__ int ffs(int x)
1313
{
1414
if (!x)
1515
return 0;
@@ -26,7 +26,7 @@ static inline int ffs(int x)
2626
/*
2727
* asm-generic/bitops/__ffs.h
2828
*/
29-
static __always_inline unsigned long __ffs(unsigned long x)
29+
static __always_inline __attribute_const__ unsigned long __ffs(unsigned long x)
3030
{
3131
asm volatile (
3232
"brev %0\n"
@@ -39,7 +39,7 @@ static __always_inline unsigned long __ffs(unsigned long x)
3939
/*
4040
* asm-generic/bitops/fls.h
4141
*/
42-
static __always_inline int fls(unsigned int x)
42+
static __always_inline __attribute_const__ int fls(unsigned int x)
4343
{
4444
asm volatile(
4545
"ff1 %0\n"
@@ -52,7 +52,7 @@ static __always_inline int fls(unsigned int x)
5252
/*
5353
* asm-generic/bitops/__fls.h
5454
*/
55-
static __always_inline unsigned long __fls(unsigned long x)
55+
static __always_inline __attribute_const__ unsigned long __fls(unsigned long x)
5656
{
5757
return fls(x) - 1;
5858
}

arch/hexagon/include/asm/bitops.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
200200
*
201201
* Undefined if no zero exists, so code should check against ~0UL first.
202202
*/
203-
static inline long ffz(int x)
203+
static inline long __attribute_const__ ffz(int x)
204204
{
205205
int r;
206206

@@ -217,7 +217,7 @@ static inline long ffz(int x)
217217
* This is defined the same way as ffs.
218218
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
219219
*/
220-
static inline int fls(unsigned int x)
220+
static inline __attribute_const__ int fls(unsigned int x)
221221
{
222222
int r;
223223

@@ -238,7 +238,7 @@ static inline int fls(unsigned int x)
238238
* the libc and compiler builtin ffs routines, therefore
239239
* differs in spirit from the above ffz (man ffs).
240240
*/
241-
static inline int ffs(int x)
241+
static inline __attribute_const__ int ffs(int x)
242242
{
243243
int r;
244244

@@ -260,7 +260,7 @@ static inline int ffs(int x)
260260
* bits_per_long assumed to be 32
261261
* numbering starts at 0 I think (instead of 1 like ffs)
262262
*/
263-
static inline unsigned long __ffs(unsigned long word)
263+
static inline __attribute_const__ unsigned long __ffs(unsigned long word)
264264
{
265265
int num;
266266

@@ -278,7 +278,7 @@ static inline unsigned long __ffs(unsigned long word)
278278
* Undefined if no set bit exists, so code should check against 0 first.
279279
* bits_per_long assumed to be 32
280280
*/
281-
static inline unsigned long __fls(unsigned long word)
281+
static inline __attribute_const__ unsigned long __fls(unsigned long word)
282282
{
283283
int num;
284284

arch/m68k/include/asm/bitops.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ static inline int find_next_bit(const unsigned long *vaddr, int size,
465465
* ffz = Find First Zero in word. Undefined if no zero exists,
466466
* so code should check against ~0UL first..
467467
*/
468-
static inline unsigned long ffz(unsigned long word)
468+
static inline unsigned long __attribute_const__ ffz(unsigned long word)
469469
{
470470
int res;
471471

@@ -488,15 +488,15 @@ static inline unsigned long ffz(unsigned long word)
488488
*/
489489
#if (defined(__mcfisaaplus__) || defined(__mcfisac__)) && \
490490
!defined(CONFIG_M68000)
491-
static inline unsigned long __ffs(unsigned long x)
491+
static inline __attribute_const__ unsigned long __ffs(unsigned long x)
492492
{
493493
__asm__ __volatile__ ("bitrev %0; ff1 %0"
494494
: "=d" (x)
495495
: "0" (x));
496496
return x;
497497
}
498498

499-
static inline int ffs(int x)
499+
static inline __attribute_const__ int ffs(int x)
500500
{
501501
if (!x)
502502
return 0;
@@ -518,7 +518,7 @@ static inline int ffs(int x)
518518
* the libc and compiler builtin ffs routines, therefore
519519
* differs in spirit from the above ffz (man ffs).
520520
*/
521-
static inline int ffs(int x)
521+
static inline __attribute_const__ int ffs(int x)
522522
{
523523
int cnt;
524524

@@ -528,15 +528,15 @@ static inline int ffs(int x)
528528
return 32 - cnt;
529529
}
530530

531-
static inline unsigned long __ffs(unsigned long x)
531+
static inline __attribute_const__ unsigned long __ffs(unsigned long x)
532532
{
533533
return ffs(x) - 1;
534534
}
535535

536536
/*
537537
* fls: find last bit set.
538538
*/
539-
static inline int fls(unsigned int x)
539+
static inline __attribute_const__ int fls(unsigned int x)
540540
{
541541
int cnt;
542542

@@ -546,7 +546,7 @@ static inline int fls(unsigned int x)
546546
return 32 - cnt;
547547
}
548548

549-
static inline unsigned long __fls(unsigned long x)
549+
static inline __attribute_const__ unsigned long __fls(unsigned long x)
550550
{
551551
return fls(x) - 1;
552552
}

arch/mips/include/asm/bitops.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *
327327
* Return the bit position (0..63) of the most significant 1 bit in a word
328328
* Returns -1 if no 1 bit exists
329329
*/
330-
static __always_inline unsigned long __fls(unsigned long word)
330+
static __always_inline __attribute_const__ unsigned long __fls(unsigned long word)
331331
{
332332
int num;
333333

@@ -393,7 +393,7 @@ static __always_inline unsigned long __fls(unsigned long word)
393393
* Returns 0..SZLONG-1
394394
* Undefined if no bit exists, so code should check against 0 first.
395395
*/
396-
static __always_inline unsigned long __ffs(unsigned long word)
396+
static __always_inline __attribute_const__ unsigned long __ffs(unsigned long word)
397397
{
398398
return __fls(word & -word);
399399
}
@@ -405,7 +405,7 @@ static __always_inline unsigned long __ffs(unsigned long word)
405405
* This is defined the same way as ffs.
406406
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
407407
*/
408-
static inline int fls(unsigned int x)
408+
static inline __attribute_const__ int fls(unsigned int x)
409409
{
410410
int r;
411411

@@ -458,7 +458,7 @@ static inline int fls(unsigned int x)
458458
* the libc and compiler builtin ffs routines, therefore
459459
* differs in spirit from the below ffz (man ffs).
460460
*/
461-
static inline int ffs(int word)
461+
static inline __attribute_const__ int ffs(int word)
462462
{
463463
if (!word)
464464
return 0;

arch/openrisc/include/asm/bitops/__ffs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
1313

14-
static inline unsigned long __ffs(unsigned long x)
14+
static inline __attribute_const__ unsigned long __ffs(unsigned long x)
1515
{
1616
int ret;
1717

arch/openrisc/include/asm/bitops/__fls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
1313

14-
static inline unsigned long __fls(unsigned long x)
14+
static inline __attribute_const__ unsigned long __fls(unsigned long x)
1515
{
1616
int ret;
1717

arch/openrisc/include/asm/bitops/ffs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
1212

13-
static inline int ffs(int x)
13+
static inline __attribute_const__ int ffs(int x)
1414
{
1515
int ret;
1616

arch/openrisc/include/asm/bitops/fls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
1313

14-
static inline int fls(unsigned int x)
14+
static inline __attribute_const__ int fls(unsigned int x)
1515
{
1616
int ret;
1717

arch/parisc/include/asm/bitops.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
123123
* cycles for each mispredicted branch.
124124
*/
125125

126-
static __inline__ unsigned long __ffs(unsigned long x)
126+
static __inline__ __attribute_const__ unsigned long __ffs(unsigned long x)
127127
{
128128
unsigned long ret;
129129

@@ -161,7 +161,7 @@ static __inline__ unsigned long __ffs(unsigned long x)
161161
* This is defined the same way as the libc and compiler builtin
162162
* ffs routines, therefore differs in spirit from the above ffz (man ffs).
163163
*/
164-
static __inline__ int ffs(int x)
164+
static __inline__ __attribute_const__ int ffs(int x)
165165
{
166166
return x ? (__ffs((unsigned long)x) + 1) : 0;
167167
}
@@ -171,7 +171,7 @@ static __inline__ int ffs(int x)
171171
* fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
172172
*/
173173

174-
static __inline__ int fls(unsigned int x)
174+
static __inline__ __attribute_const__ int fls(unsigned int x)
175175
{
176176
int ret;
177177
if (!x)

0 commit comments

Comments
 (0)