From 43dba8f07291e099b14d1646dbedf884b4e945ba Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Mon, 13 Feb 2023 21:58:42 -0800 Subject: [PATCH] mm: Fix truncated major/minor output in PID maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The major and minor can be up to 12 bits and 20 bits long, respectively. The current output generated after the micro-optimizations applied to show_vma_header_prefix() only show up to 8 bits of each (2 hex digits), resulting in the major and minor being truncated. Fix it by introducing new optimized macros to print up to 3 and 5 hex digits for the major and minor, respectively. Reported-by: LoveSy Reported-by: 南宫雪珊 Signed-off-by: Sultan Alsawaf Change-Id: I2fb9abe498e401beb39500864f9ba7894b5500e3 Signed-off-by: Richard Raya --- fs/proc/task_mmu.c | 64 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 009ccf32157a..7519ddac9e20 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -390,15 +390,65 @@ static int is_stack(struct vm_area_struct *vma) __len; \ }) -#define print_vma_hex2(out, val) \ +#define print_vma_hex5(out, val, clz_fn) \ ({ \ const typeof(val) __val = val; \ char *const __out = out; \ + size_t __len; \ \ - __out[1] = hex_asc[(__val >> 0) & 0xf]; \ - __out[0] = hex_asc[(__val >> 4) & 0xf]; \ + if (__val) { \ + __len = (sizeof(__val) * 8 - clz_fn(__val) + 3) / 4; \ + switch (__len) { \ + case 5: \ + __out[4] = hex_asc[(__val >> 0) & 0xf]; \ + __out[3] = hex_asc[(__val >> 4) & 0xf]; \ + __out[2] = hex_asc[(__val >> 8) & 0xf]; \ + __out[1] = hex_asc[(__val >> 12) & 0xf]; \ + __out[0] = hex_asc[(__val >> 16) & 0xf]; \ + break; \ + case 4: \ + __out[3] = hex_asc[(__val >> 0) & 0xf]; \ + __out[2] = hex_asc[(__val >> 4) & 0xf]; \ + __out[1] = hex_asc[(__val >> 8) & 0xf]; \ + __out[0] = hex_asc[(__val >> 12) & 0xf]; \ + break; \ + case 3: \ + __out[2] = hex_asc[(__val >> 0) & 0xf]; \ + __out[1] = hex_asc[(__val >> 4) & 0xf]; \ + __out[0] = hex_asc[(__val >> 8) & 0xf]; \ + break; \ + default: \ + __out[1] = hex_asc[(__val >> 0) & 0xf]; \ + __out[0] = hex_asc[(__val >> 4) & 0xf]; \ + __len = 2; \ + break; \ + } \ + } else { \ + *(u16 *)__out = U16_C(0x3030); \ + __len = 2; \ + } \ \ - 2; \ + __len; \ +}) + +#define print_vma_hex3(out, val, clz_fn) \ +({ \ + const typeof(val) __val = val; \ + char *const __out = out; \ + size_t __len; \ + \ + if (__val & 0xf00) { \ + __out[2] = hex_asc[(__val >> 0) & 0xf]; \ + __out[1] = hex_asc[(__val >> 4) & 0xf]; \ + __out[0] = hex_asc[(__val >> 8) & 0xf]; \ + __len = 3; \ + } else { \ + __out[1] = hex_asc[(__val >> 0) & 0xf]; \ + __out[0] = hex_asc[(__val >> 4) & 0xf]; \ + __len = 2; \ + } \ + \ + __len; \ }) static int show_vma_header_prefix(struct seq_file *m, unsigned long start, @@ -410,7 +460,7 @@ static int show_vma_header_prefix(struct seq_file *m, unsigned long start, char *out; /* Set the overflow status to get more memory if there's no space */ - if (seq_get_buf(m, &out) < 65) { + if (seq_get_buf(m, &out) < 69) { seq_commit(m, -1); return -ENOMEM; } @@ -435,11 +485,11 @@ static int show_vma_header_prefix(struct seq_file *m, unsigned long start, out[len++] = ' '; - len += print_vma_hex2(out + len, MAJOR(dev)); + len += print_vma_hex3(out + len, MAJOR(dev), __builtin_clz); out[len++] = ':'; - len += print_vma_hex2(out + len, MINOR(dev)); + len += print_vma_hex5(out + len, MINOR(dev), __builtin_clz); out[len++] = ' ';