Skip to content

Commit e724918

Browse files
committed
Merge tag 'hardening-v6.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull hardening fixes from Kees Cook: - gcc-plugins: randstruct: Remove GCC 4.7 or newer requirement (Thorsten Blum) - kallsyms: Clean up interaction with LTO suffixes (Song Liu) - refcount: Report UAF for refcount_sub_and_test(0) when counter==0 (Petr Pavlu) - kunit/overflow: Avoid misallocation of driver name (Ivan Orlov) * tag 'hardening-v6.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: kallsyms: Match symbols exactly with CONFIG_LTO_CLANG kallsyms: Do not cleanup .llvm.<hash> suffix before sorting symbols kunit/overflow: Fix UB in overflow_allocation_test gcc-plugins: randstruct: Remove GCC 4.7 or newer requirement refcount: Report UAF for refcount_sub_and_test(0) when counter==0
2 parents a4a35f6 + fb6a421 commit e724918

File tree

8 files changed

+28
-111
lines changed

8 files changed

+28
-111
lines changed

drivers/misc/lkdtm/refcount.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,21 @@ static void lkdtm_REFCOUNT_SUB_AND_TEST_NEGATIVE(void)
182182
check_negative(&neg, 3);
183183
}
184184

185+
/*
186+
* A refcount_sub_and_test() by zero when the counter is at zero should act like
187+
* refcount_sub_and_test() above when going negative.
188+
*/
189+
static void lkdtm_REFCOUNT_SUB_AND_TEST_ZERO(void)
190+
{
191+
refcount_t neg = REFCOUNT_INIT(0);
192+
193+
pr_info("attempting bad refcount_sub_and_test() at zero\n");
194+
if (refcount_sub_and_test(0, &neg))
195+
pr_warn("Weird: refcount_sub_and_test() reported zero\n");
196+
197+
check_negative(&neg, 0);
198+
}
199+
185200
static void check_from_zero(refcount_t *ref)
186201
{
187202
switch (refcount_read(ref)) {
@@ -400,6 +415,7 @@ static struct crashtype crashtypes[] = {
400415
CRASHTYPE(REFCOUNT_DEC_NEGATIVE),
401416
CRASHTYPE(REFCOUNT_DEC_AND_TEST_NEGATIVE),
402417
CRASHTYPE(REFCOUNT_SUB_AND_TEST_NEGATIVE),
418+
CRASHTYPE(REFCOUNT_SUB_AND_TEST_ZERO),
403419
CRASHTYPE(REFCOUNT_INC_ZERO),
404420
CRASHTYPE(REFCOUNT_ADD_ZERO),
405421
CRASHTYPE(REFCOUNT_INC_SATURATED),

include/linux/refcount.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,12 @@ bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp)
266266
if (oldp)
267267
*oldp = old;
268268

269-
if (old == i) {
269+
if (old > 0 && old == i) {
270270
smp_acquire__after_ctrl_dep();
271271
return true;
272272
}
273273

274-
if (unlikely(old < 0 || old - i < 0))
274+
if (unlikely(old <= 0 || old - i < 0))
275275
refcount_warn_saturate(r, REFCOUNT_SUB_UAF);
276276

277277
return false;

kernel/kallsyms.c

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -160,38 +160,6 @@ unsigned long kallsyms_sym_address(int idx)
160160
return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
161161
}
162162

163-
static void cleanup_symbol_name(char *s)
164-
{
165-
char *res;
166-
167-
if (!IS_ENABLED(CONFIG_LTO_CLANG))
168-
return;
169-
170-
/*
171-
* LLVM appends various suffixes for local functions and variables that
172-
* must be promoted to global scope as part of LTO. This can break
173-
* hooking of static functions with kprobes. '.' is not a valid
174-
* character in an identifier in C. Suffixes only in LLVM LTO observed:
175-
* - foo.llvm.[0-9a-f]+
176-
*/
177-
res = strstr(s, ".llvm.");
178-
if (res)
179-
*res = '\0';
180-
181-
return;
182-
}
183-
184-
static int compare_symbol_name(const char *name, char *namebuf)
185-
{
186-
/* The kallsyms_seqs_of_names is sorted based on names after
187-
* cleanup_symbol_name() (see scripts/kallsyms.c) if clang lto is enabled.
188-
* To ensure correct bisection in kallsyms_lookup_names(), do
189-
* cleanup_symbol_name(namebuf) before comparing name and namebuf.
190-
*/
191-
cleanup_symbol_name(namebuf);
192-
return strcmp(name, namebuf);
193-
}
194-
195163
static unsigned int get_symbol_seq(int index)
196164
{
197165
unsigned int i, seq = 0;
@@ -219,7 +187,7 @@ static int kallsyms_lookup_names(const char *name,
219187
seq = get_symbol_seq(mid);
220188
off = get_symbol_offset(seq);
221189
kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
222-
ret = compare_symbol_name(name, namebuf);
190+
ret = strcmp(name, namebuf);
223191
if (ret > 0)
224192
low = mid + 1;
225193
else if (ret < 0)
@@ -236,7 +204,7 @@ static int kallsyms_lookup_names(const char *name,
236204
seq = get_symbol_seq(low - 1);
237205
off = get_symbol_offset(seq);
238206
kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
239-
if (compare_symbol_name(name, namebuf))
207+
if (strcmp(name, namebuf))
240208
break;
241209
low--;
242210
}
@@ -248,7 +216,7 @@ static int kallsyms_lookup_names(const char *name,
248216
seq = get_symbol_seq(high + 1);
249217
off = get_symbol_offset(seq);
250218
kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
251-
if (compare_symbol_name(name, namebuf))
219+
if (strcmp(name, namebuf))
252220
break;
253221
high++;
254222
}
@@ -407,8 +375,7 @@ static int kallsyms_lookup_buildid(unsigned long addr,
407375
if (modbuildid)
408376
*modbuildid = NULL;
409377

410-
ret = strlen(namebuf);
411-
goto found;
378+
return strlen(namebuf);
412379
}
413380

414381
/* See if it's in a module or a BPF JITed image. */
@@ -422,8 +389,6 @@ static int kallsyms_lookup_buildid(unsigned long addr,
422389
ret = ftrace_mod_address_lookup(addr, symbolsize,
423390
offset, modname, namebuf);
424391

425-
found:
426-
cleanup_symbol_name(namebuf);
427392
return ret;
428393
}
429394

@@ -450,8 +415,6 @@ const char *kallsyms_lookup(unsigned long addr,
450415

451416
int lookup_symbol_name(unsigned long addr, char *symname)
452417
{
453-
int res;
454-
455418
symname[0] = '\0';
456419
symname[KSYM_NAME_LEN - 1] = '\0';
457420

@@ -462,16 +425,10 @@ int lookup_symbol_name(unsigned long addr, char *symname)
462425
/* Grab name */
463426
kallsyms_expand_symbol(get_symbol_offset(pos),
464427
symname, KSYM_NAME_LEN);
465-
goto found;
428+
return 0;
466429
}
467430
/* See if it's in a module. */
468-
res = lookup_module_symbol_name(addr, symname);
469-
if (res)
470-
return res;
471-
472-
found:
473-
cleanup_symbol_name(symname);
474-
return 0;
431+
return lookup_module_symbol_name(addr, symname);
475432
}
476433

477434
/* Look up a kernel symbol and return it in a text buffer. */

kernel/kallsyms_selftest.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -187,31 +187,11 @@ static void test_perf_kallsyms_lookup_name(void)
187187
stat.min, stat.max, div_u64(stat.sum, stat.real_cnt));
188188
}
189189

190-
static bool match_cleanup_name(const char *s, const char *name)
191-
{
192-
char *p;
193-
int len;
194-
195-
if (!IS_ENABLED(CONFIG_LTO_CLANG))
196-
return false;
197-
198-
p = strstr(s, ".llvm.");
199-
if (!p)
200-
return false;
201-
202-
len = strlen(name);
203-
if (p - s != len)
204-
return false;
205-
206-
return !strncmp(s, name, len);
207-
}
208-
209190
static int find_symbol(void *data, const char *name, unsigned long addr)
210191
{
211192
struct test_stat *stat = (struct test_stat *)data;
212193

213-
if (strcmp(name, stat->name) == 0 ||
214-
(!stat->perf && match_cleanup_name(name, stat->name))) {
194+
if (!strcmp(name, stat->name)) {
215195
stat->real_cnt++;
216196
stat->addr = addr;
217197

lib/overflow_kunit.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,6 @@ DEFINE_TEST_ALLOC(devm_kzalloc, devm_kfree, 1, 1, 0);
668668

669669
static void overflow_allocation_test(struct kunit *test)
670670
{
671-
const char device_name[] = "overflow-test";
672671
struct device *dev;
673672
int count = 0;
674673

@@ -678,7 +677,7 @@ static void overflow_allocation_test(struct kunit *test)
678677
} while (0)
679678

680679
/* Create dummy device for devm_kmalloc()-family tests. */
681-
dev = kunit_device_register(test, device_name);
680+
dev = kunit_device_register(test, "overflow-test");
682681
KUNIT_ASSERT_FALSE_MSG(test, IS_ERR(dev),
683682
"Cannot register test device\n");
684683

scripts/gcc-plugins/randomize_layout_plugin.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@
1919
#include "gcc-common.h"
2020
#include "randomize_layout_seed.h"
2121

22-
#if BUILDING_GCC_MAJOR < 4 || (BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR < 7)
23-
#error "The RANDSTRUCT plugin requires GCC 4.7 or newer."
24-
#endif
25-
2622
#define ORIG_TYPE_NAME(node) \
2723
(TYPE_NAME(TYPE_MAIN_VARIANT(node)) != NULL_TREE ? ((const unsigned char *)IDENTIFIER_POINTER(TYPE_NAME(TYPE_MAIN_VARIANT(node)))) : (const unsigned char *)"anonymous")
2824

scripts/kallsyms.c

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
* This software may be used and distributed according to the terms
66
* of the GNU General Public License, incorporated herein by reference.
77
*
8-
* Usage: kallsyms [--all-symbols] [--absolute-percpu]
9-
* [--lto-clang] in.map > out.S
8+
* Usage: kallsyms [--all-symbols] [--absolute-percpu] in.map > out.S
109
*
1110
* Table compression uses all the unused char codes on the symbols and
1211
* maps these to the most used substrings (tokens). For instance, it might
@@ -62,7 +61,6 @@ static struct sym_entry **table;
6261
static unsigned int table_size, table_cnt;
6362
static int all_symbols;
6463
static int absolute_percpu;
65-
static int lto_clang;
6664

6765
static int token_profit[0x10000];
6866

@@ -73,8 +71,7 @@ static unsigned char best_table_len[256];
7371

7472
static void usage(void)
7573
{
76-
fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] "
77-
"[--lto-clang] in.map > out.S\n");
74+
fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] in.map > out.S\n");
7875
exit(1);
7976
}
8077

@@ -344,25 +341,6 @@ static bool symbol_absolute(const struct sym_entry *s)
344341
return s->percpu_absolute;
345342
}
346343

347-
static void cleanup_symbol_name(char *s)
348-
{
349-
char *p;
350-
351-
/*
352-
* ASCII[.] = 2e
353-
* ASCII[0-9] = 30,39
354-
* ASCII[A-Z] = 41,5a
355-
* ASCII[_] = 5f
356-
* ASCII[a-z] = 61,7a
357-
*
358-
* As above, replacing the first '.' in ".llvm." with '\0' does not
359-
* affect the main sorting, but it helps us with subsorting.
360-
*/
361-
p = strstr(s, ".llvm.");
362-
if (p)
363-
*p = '\0';
364-
}
365-
366344
static int compare_names(const void *a, const void *b)
367345
{
368346
int ret;
@@ -526,10 +504,6 @@ static void write_src(void)
526504
output_address(relative_base);
527505
printf("\n");
528506

529-
if (lto_clang)
530-
for (i = 0; i < table_cnt; i++)
531-
cleanup_symbol_name((char *)table[i]->sym);
532-
533507
sort_symbols_by_name();
534508
output_label("kallsyms_seqs_of_names");
535509
for (i = 0; i < table_cnt; i++)
@@ -807,7 +781,6 @@ int main(int argc, char **argv)
807781
static const struct option long_options[] = {
808782
{"all-symbols", no_argument, &all_symbols, 1},
809783
{"absolute-percpu", no_argument, &absolute_percpu, 1},
810-
{"lto-clang", no_argument, &lto_clang, 1},
811784
{},
812785
};
813786

scripts/link-vmlinux.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,6 @@ kallsyms()
156156
kallsymopt="${kallsymopt} --absolute-percpu"
157157
fi
158158

159-
if is_enabled CONFIG_LTO_CLANG; then
160-
kallsymopt="${kallsymopt} --lto-clang"
161-
fi
162-
163159
info KSYMS "${2}.S"
164160
scripts/kallsyms ${kallsymopt} "${1}" > "${2}.S"
165161

0 commit comments

Comments
 (0)