Skip to content

Commit 2fe2edf

Browse files
committed
Merge tag 'trace-fixes-v4.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing ring-buffer fixes from Steven Rostedt: "Hao Qin reported an integer overflow possibility with signed and unsigned numbers in the ring-buffer code. https://bugzilla.kernel.org/show_bug.cgi?id=118001 At first I did not think this was too much of an issue, because the overflow would be caught later when either too much data was allocated or it would trigger RB_WARN_ON() which shuts down the ring buffer. But looking closer into it, I found that the right settings could bypass the checks and crash the kernel. Luckily, this is only accessible by root. The first fix is to convert all the variables into long, such that we don't get into issues between 32 bit variables being assigned 64 bit ones. This fixes the RB_WARN_ON() triggering. The next fix is to get rid of a duplicate DIV_ROUND_UP() that when called twice with the right value, can cause a kernel crash. The first DIV_ROUND_UP() is to normalize the input and it is checked against the minimum allowable value. But then DIV_ROUND_UP() is called again, which can overflow due to the (a + b - 1)/b, logic. The first called upped the value, the second can overflow (with the +b part). The second call to DIV_ROUND_UP() came in via a second change a while ago and the code is cleaned up to remove it" * tag 'trace-fixes-v4.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: ring-buffer: Prevent overflow of size in ring_buffer_resize() ring-buffer: Use long for nr_pages to avoid overflow failures
2 parents 9a07a79 + 59643d1 commit 2fe2edf

File tree

1 file changed

+18
-17
lines changed

1 file changed

+18
-17
lines changed

kernel/trace/ring_buffer.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ struct ring_buffer_per_cpu {
437437
raw_spinlock_t reader_lock; /* serialize readers */
438438
arch_spinlock_t lock;
439439
struct lock_class_key lock_key;
440-
unsigned int nr_pages;
440+
unsigned long nr_pages;
441441
unsigned int current_context;
442442
struct list_head *pages;
443443
struct buffer_page *head_page; /* read from head */
@@ -458,7 +458,7 @@ struct ring_buffer_per_cpu {
458458
u64 write_stamp;
459459
u64 read_stamp;
460460
/* ring buffer pages to update, > 0 to add, < 0 to remove */
461-
int nr_pages_to_update;
461+
long nr_pages_to_update;
462462
struct list_head new_pages; /* new pages to add */
463463
struct work_struct update_pages_work;
464464
struct completion update_done;
@@ -1128,10 +1128,10 @@ static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
11281128
return 0;
11291129
}
11301130

1131-
static int __rb_allocate_pages(int nr_pages, struct list_head *pages, int cpu)
1131+
static int __rb_allocate_pages(long nr_pages, struct list_head *pages, int cpu)
11321132
{
1133-
int i;
11341133
struct buffer_page *bpage, *tmp;
1134+
long i;
11351135

11361136
for (i = 0; i < nr_pages; i++) {
11371137
struct page *page;
@@ -1168,7 +1168,7 @@ static int __rb_allocate_pages(int nr_pages, struct list_head *pages, int cpu)
11681168
}
11691169

11701170
static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
1171-
unsigned nr_pages)
1171+
unsigned long nr_pages)
11721172
{
11731173
LIST_HEAD(pages);
11741174

@@ -1193,7 +1193,7 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
11931193
}
11941194

11951195
static struct ring_buffer_per_cpu *
1196-
rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu)
1196+
rb_allocate_cpu_buffer(struct ring_buffer *buffer, long nr_pages, int cpu)
11971197
{
11981198
struct ring_buffer_per_cpu *cpu_buffer;
11991199
struct buffer_page *bpage;
@@ -1293,8 +1293,9 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
12931293
struct lock_class_key *key)
12941294
{
12951295
struct ring_buffer *buffer;
1296+
long nr_pages;
12961297
int bsize;
1297-
int cpu, nr_pages;
1298+
int cpu;
12981299

12991300
/* keep it in its own cache line */
13001301
buffer = kzalloc(ALIGN(sizeof(*buffer), cache_line_size()),
@@ -1420,12 +1421,12 @@ static inline unsigned long rb_page_write(struct buffer_page *bpage)
14201421
}
14211422

14221423
static int
1423-
rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages)
1424+
rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages)
14241425
{
14251426
struct list_head *tail_page, *to_remove, *next_page;
14261427
struct buffer_page *to_remove_page, *tmp_iter_page;
14271428
struct buffer_page *last_page, *first_page;
1428-
unsigned int nr_removed;
1429+
unsigned long nr_removed;
14291430
unsigned long head_bit;
14301431
int page_entries;
14311432

@@ -1642,7 +1643,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
16421643
int cpu_id)
16431644
{
16441645
struct ring_buffer_per_cpu *cpu_buffer;
1645-
unsigned nr_pages;
1646+
unsigned long nr_pages;
16461647
int cpu, err = 0;
16471648

16481649
/*
@@ -1656,14 +1657,13 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
16561657
!cpumask_test_cpu(cpu_id, buffer->cpumask))
16571658
return size;
16581659

1659-
size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
1660-
size *= BUF_PAGE_SIZE;
1660+
nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
16611661

16621662
/* we need a minimum of two pages */
1663-
if (size < BUF_PAGE_SIZE * 2)
1664-
size = BUF_PAGE_SIZE * 2;
1663+
if (nr_pages < 2)
1664+
nr_pages = 2;
16651665

1666-
nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
1666+
size = nr_pages * BUF_PAGE_SIZE;
16671667

16681668
/*
16691669
* Don't succeed if resizing is disabled, as a reader might be
@@ -4640,8 +4640,9 @@ static int rb_cpu_notify(struct notifier_block *self,
46404640
struct ring_buffer *buffer =
46414641
container_of(self, struct ring_buffer, cpu_notify);
46424642
long cpu = (long)hcpu;
4643-
int cpu_i, nr_pages_same;
4644-
unsigned int nr_pages;
4643+
long nr_pages_same;
4644+
int cpu_i;
4645+
unsigned long nr_pages;
46454646

46464647
switch (action) {
46474648
case CPU_UP_PREPARE:

0 commit comments

Comments
 (0)