Skip to content

Commit e4dcad2

Browse files
joelagneltorvalds
authored andcommittedDec 1, 2019
rss_stat: add support to detect RSS updates of external mm
When a process updates the RSS of a different process, the rss_stat tracepoint appears in the context of the process doing the update. This can confuse userspace that the RSS of process doing the update is updated, while in reality a different process's RSS was updated. This issue happens in reclaim paths such as with direct reclaim or background reclaim. This patch adds more information to the tracepoint about whether the mm being updated belongs to the current process's context (curr field). We also include a hash of the mm pointer so that the process who the mm belongs to can be uniquely identified (mm_id field). Also vsprintf.c is refactored a bit to allow reuse of hashing code. [akpm@linux-foundation.org: remove unused local `str'] [joelaf@google.com: inline call to ptr_to_hashval] Link: http://lore.kernel.org/r/20191113153816.14b95acd@gandalf.local.home Link: http://lkml.kernel.org/r/20191114164622.GC233237@google.com Link: http://lkml.kernel.org/r/20191106024452.81923-1-joel@joelfernandes.org Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org> Reported-by: Ioannis Ilkos <ilkos@google.com> Acked-by: Petr Mladek <pmladek@suse.com> [lib/vsprintf.c] Cc: Tim Murray <timmurray@google.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Carmen Jackson <carmenjackson@google.com> Cc: Mayank Gupta <mayankgupta@google.com> Cc: Daniel Colascione <dancol@google.com> Cc: Steven Rostedt (VMware) <rostedt@goodmis.org> Cc: Minchan Kim <minchan@kernel.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Jerome Glisse <jglisse@redhat.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Ralph Campbell <rcampbell@nvidia.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent b3d1411 commit e4dcad2

File tree

5 files changed

+66
-20
lines changed

5 files changed

+66
-20
lines changed
 

‎include/linux/mm.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,27 +1643,27 @@ static inline unsigned long get_mm_counter(struct mm_struct *mm, int member)
16431643
return (unsigned long)val;
16441644
}
16451645

1646-
void mm_trace_rss_stat(int member, long count);
1646+
void mm_trace_rss_stat(struct mm_struct *mm, int member, long count);
16471647

16481648
static inline void add_mm_counter(struct mm_struct *mm, int member, long value)
16491649
{
16501650
long count = atomic_long_add_return(value, &mm->rss_stat.count[member]);
16511651

1652-
mm_trace_rss_stat(member, count);
1652+
mm_trace_rss_stat(mm, member, count);
16531653
}
16541654

16551655
static inline void inc_mm_counter(struct mm_struct *mm, int member)
16561656
{
16571657
long count = atomic_long_inc_return(&mm->rss_stat.count[member]);
16581658

1659-
mm_trace_rss_stat(member, count);
1659+
mm_trace_rss_stat(mm, member, count);
16601660
}
16611661

16621662
static inline void dec_mm_counter(struct mm_struct *mm, int member)
16631663
{
16641664
long count = atomic_long_dec_return(&mm->rss_stat.count[member]);
16651665

1666-
mm_trace_rss_stat(member, count);
1666+
mm_trace_rss_stat(mm, member, count);
16671667
}
16681668

16691669
/* Optimized variant when page is already known not to be PageAnon */

‎include/linux/string.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4);
216216
extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
217217
const void *from, size_t available);
218218

219+
int ptr_to_hashval(const void *ptr, unsigned long *hashval_out);
220+
219221
/**
220222
* strstarts - does @str start with @prefix?
221223
* @str: string to examine

‎include/trace/events/kmem.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,24 +316,50 @@ TRACE_EVENT(mm_page_alloc_extfrag,
316316
__entry->change_ownership)
317317
);
318318

319+
/*
320+
* Required for uniquely and securely identifying mm in rss_stat tracepoint.
321+
*/
322+
#ifndef __PTR_TO_HASHVAL
323+
static unsigned int __maybe_unused mm_ptr_to_hash(const void *ptr)
324+
{
325+
int ret;
326+
unsigned long hashval;
327+
328+
ret = ptr_to_hashval(ptr, &hashval);
329+
if (ret)
330+
return 0;
331+
332+
/* The hashed value is only 32-bit */
333+
return (unsigned int)hashval;
334+
}
335+
#define __PTR_TO_HASHVAL
336+
#endif
337+
319338
TRACE_EVENT(rss_stat,
320339

321-
TP_PROTO(int member,
340+
TP_PROTO(struct mm_struct *mm,
341+
int member,
322342
long count),
323343

324-
TP_ARGS(member, count),
344+
TP_ARGS(mm, member, count),
325345

326346
TP_STRUCT__entry(
347+
__field(unsigned int, mm_id)
348+
__field(unsigned int, curr)
327349
__field(int, member)
328350
__field(long, size)
329351
),
330352

331353
TP_fast_assign(
354+
__entry->mm_id = mm_ptr_to_hash(mm);
355+
__entry->curr = !!(current->mm == mm);
332356
__entry->member = member;
333357
__entry->size = (count << PAGE_SHIFT);
334358
),
335359

336-
TP_printk("member=%d size=%ldB",
360+
TP_printk("mm_id=%u curr=%d member=%d size=%ldB",
361+
__entry->mm_id,
362+
__entry->curr,
337363
__entry->member,
338364
__entry->size)
339365
);

‎lib/vsprintf.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -761,34 +761,52 @@ static int __init initialize_ptr_random(void)
761761
early_initcall(initialize_ptr_random);
762762

763763
/* Maps a pointer to a 32 bit unique identifier. */
764+
static inline int __ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
765+
{
766+
unsigned long hashval;
767+
768+
if (static_branch_unlikely(&not_filled_random_ptr_key))
769+
return -EAGAIN;
770+
771+
#ifdef CONFIG_64BIT
772+
hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);
773+
/*
774+
* Mask off the first 32 bits, this makes explicit that we have
775+
* modified the address (and 32 bits is plenty for a unique ID).
776+
*/
777+
hashval = hashval & 0xffffffff;
778+
#else
779+
hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key);
780+
#endif
781+
*hashval_out = hashval;
782+
return 0;
783+
}
784+
785+
int ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
786+
{
787+
return __ptr_to_hashval(ptr, hashval_out);
788+
}
789+
764790
static char *ptr_to_id(char *buf, char *end, const void *ptr,
765791
struct printf_spec spec)
766792
{
767793
const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)";
768794
unsigned long hashval;
795+
int ret;
769796

770797
/* When debugging early boot use non-cryptographically secure hash. */
771798
if (unlikely(debug_boot_weak_hash)) {
772799
hashval = hash_long((unsigned long)ptr, 32);
773800
return pointer_string(buf, end, (const void *)hashval, spec);
774801
}
775802

776-
if (static_branch_unlikely(&not_filled_random_ptr_key)) {
803+
ret = __ptr_to_hashval(ptr, &hashval);
804+
if (ret) {
777805
spec.field_width = 2 * sizeof(ptr);
778806
/* string length must be less than default_width */
779807
return error_string(buf, end, str, spec);
780808
}
781809

782-
#ifdef CONFIG_64BIT
783-
hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);
784-
/*
785-
* Mask off the first 32 bits, this makes explicit that we have
786-
* modified the address (and 32 bits is plenty for a unique ID).
787-
*/
788-
hashval = hashval & 0xffffffff;
789-
#else
790-
hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key);
791-
#endif
792810
return pointer_string(buf, end, (const void *)hashval, spec);
793811
}
794812

‎mm/memory.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ static int __init init_zero_pfn(void)
154154
}
155155
core_initcall(init_zero_pfn);
156156

157-
void mm_trace_rss_stat(int member, long count)
157+
void mm_trace_rss_stat(struct mm_struct *mm, int member, long count)
158158
{
159-
trace_rss_stat(member, count);
159+
trace_rss_stat(mm, member, count);
160160
}
161161

162162
#if defined(SPLIT_RSS_COUNTING)

0 commit comments

Comments
 (0)
Please sign in to comment.