Skip to content

Commit fbc134c

Browse files
kerneltoastzeelog
authored andcommitted
mm: Fix truncated major/minor output in PID maps
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 <shana@zju.edu.cn> Reported-by: 南宫雪珊 <vvb2060@gmail.com> Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com> Signed-off-by: Tashfin Shakeer Rhythm <tashfinshakeerrhythm@gmail.com>
1 parent c056590 commit fbc134c

1 file changed

Lines changed: 57 additions & 7 deletions

File tree

fs/proc/task_mmu.c

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -382,15 +382,65 @@ static int is_stack(struct proc_maps_private *priv,
382382
__len; \
383383
})
384384

385-
#define print_vma_hex2(out, val) \
385+
#define print_vma_hex5(out, val, clz_fn) \
386386
({ \
387387
const typeof(val) __val = val; \
388388
char *const __out = out; \
389+
size_t __len; \
390+
\
391+
if (__val) { \
392+
__len = (sizeof(__val) * 8 - clz_fn(__val) + 3) / 4; \
393+
switch (__len) { \
394+
case 5: \
395+
__out[4] = hex_asc[(__val >> 0) & 0xf]; \
396+
__out[3] = hex_asc[(__val >> 4) & 0xf]; \
397+
__out[2] = hex_asc[(__val >> 8) & 0xf]; \
398+
__out[1] = hex_asc[(__val >> 12) & 0xf]; \
399+
__out[0] = hex_asc[(__val >> 16) & 0xf]; \
400+
break; \
401+
case 4: \
402+
__out[3] = hex_asc[(__val >> 0) & 0xf]; \
403+
__out[2] = hex_asc[(__val >> 4) & 0xf]; \
404+
__out[1] = hex_asc[(__val >> 8) & 0xf]; \
405+
__out[0] = hex_asc[(__val >> 12) & 0xf]; \
406+
break; \
407+
case 3: \
408+
__out[2] = hex_asc[(__val >> 0) & 0xf]; \
409+
__out[1] = hex_asc[(__val >> 4) & 0xf]; \
410+
__out[0] = hex_asc[(__val >> 8) & 0xf]; \
411+
break; \
412+
default: \
413+
__out[1] = hex_asc[(__val >> 0) & 0xf]; \
414+
__out[0] = hex_asc[(__val >> 4) & 0xf]; \
415+
__len = 2; \
416+
break; \
417+
} \
418+
} else { \
419+
*(u16 *)__out = U16_C(0x3030); \
420+
__len = 2; \
421+
} \
422+
\
423+
__len; \
424+
})
425+
426+
#define print_vma_hex3(out, val, clz_fn) \
427+
({ \
428+
const typeof(val) __val = val; \
429+
char *const __out = out; \
430+
size_t __len; \
389431
\
390-
__out[1] = hex_asc[(__val >> 0) & 0xf]; \
391-
__out[0] = hex_asc[(__val >> 4) & 0xf]; \
432+
if (__val & 0xf00) { \
433+
__out[2] = hex_asc[(__val >> 0) & 0xf]; \
434+
__out[1] = hex_asc[(__val >> 4) & 0xf]; \
435+
__out[0] = hex_asc[(__val >> 8) & 0xf]; \
436+
__len = 3; \
437+
} else { \
438+
__out[1] = hex_asc[(__val >> 0) & 0xf]; \
439+
__out[0] = hex_asc[(__val >> 4) & 0xf]; \
440+
__len = 2; \
441+
} \
392442
\
393-
2; \
443+
__len; \
394444
})
395445

396446
static int show_vma_header_prefix(struct seq_file *m, unsigned long start,
@@ -402,7 +452,7 @@ static int show_vma_header_prefix(struct seq_file *m, unsigned long start,
402452
char *out;
403453

404454
/* Set the overflow status to get more memory if there's no space */
405-
if (seq_get_buf(m, &out) < 65) {
455+
if (seq_get_buf(m, &out) < 69) {
406456
seq_commit(m, -1);
407457
return -ENOMEM;
408458
}
@@ -427,11 +477,11 @@ static int show_vma_header_prefix(struct seq_file *m, unsigned long start,
427477

428478
out[len++] = ' ';
429479

430-
len += print_vma_hex2(out + len, MAJOR(dev));
480+
len += print_vma_hex3(out + len, MAJOR(dev), __builtin_clz);
431481

432482
out[len++] = ':';
433483

434-
len += print_vma_hex2(out + len, MINOR(dev));
484+
len += print_vma_hex5(out + len, MINOR(dev), __builtin_clz);
435485

436486
out[len++] = ' ';
437487

0 commit comments

Comments
 (0)