From: Jim Warner Date: Wed, 13 Apr 2016 05:00:00 +0000 (-0500) Subject: library: exploit linux-4.5 resident memory enhancement X-Git-Tag: v3.3.12~39 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cb0e210930a1dcf588ecee057fcfd5bb62fcc2d2;p=procps-ng library: exploit linux-4.5 resident memory enhancement Since support already exists in the newlib branch this represents an equivalent master branch implementation, and this commit message is shared with 2 more patches. Beginning with linux-4.5, the following new fields are being added under that /proc//status pseudo file: . RssAnon - size of resident anonymous memory . RssFile - size of resident file mappings . RssShmem - size of resident shared memory p.s. Locked resident memory support was also added but isn't directly related to the kernel 4.5 enhancements. p.p.s. Archlinux, Debian-stretch and Fedora-23 already are currently using a 4.5 linux kernel (as of 6/2/16). Signed-off-by: Jim Warner --- diff --git a/proc/readproc.c b/proc/readproc.c index f5d89cf8..e06bd0ff 100644 --- a/proc/readproc.c +++ b/proc/readproc.c @@ -113,7 +113,7 @@ static inline void free_acquired (proc_t *p, int reuse) { /////////////////////////////////////////////////////////////////////////// typedef struct status_table_struct { - unsigned char name[7]; // /proc/*/status field name + unsigned char name[8]; // /proc/*/status field name unsigned char len; // name length #ifdef LABEL_OFFSET long offset; // jump address offset @@ -129,8 +129,11 @@ typedef struct status_table_struct { #endif #define NUL {"", 0, 0}, +#define GPERF_TABLE_SIZE 128 + // Derived from: // gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c +// ( --key-positions verified by omission & reported "Computed positions" ) // // Suggested method: // Grep this file for "case_", then strip those down to the name. @@ -144,8 +147,8 @@ typedef struct status_table_struct { // the F macro and replacing empty strings with the NUL define. // // In the status_table_struct watch out for name size (grrr, expanding) -// and the number of entries (we mask with 63 for now). The table -// must be padded out to 64 entries, maybe 128 in the future. +// and the number of entries. Currently, the table is padded to 128 +// entries and we therefore mask with 127. static void status2proc(char *S, proc_t *restrict P, int is_proc){ long Threads = 0; @@ -155,78 +158,76 @@ static void status2proc(char *S, proc_t *restrict P, int is_proc){ // 128 entries because we trust the kernel to use ASCII names static const unsigned char asso[] = { - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 28, 64, - 64, 64, 64, 64, 64, 64, 8, 25, 23, 25, - 6, 25, 0, 3, 64, 64, 3, 64, 25, 64, - 20, 1, 1, 5, 0, 30, 0, 0, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 3, 64, 0, - 0, 18, 64, 10, 64, 10, 64, 64, 64, 20, - 64, 20, 0, 64, 25, 64, 3, 15, 64, 0, - 30, 64, 64, 64, 64, 64, 64, 64 + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 6, 101, + 101, 101, 101, 101, 101, 45, 55, 25, 31, 50, + 50, 10, 0, 35, 101, 101, 21, 101, 30, 101, + 20, 36, 0, 5, 0, 40, 0, 0, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 30, 101, 15, + 0, 1, 101, 10, 101, 10, 101, 101, 101, 25, + 101, 40, 0, 101, 0, 50, 6, 40, 101, 1, + 35, 101, 101, 101, 101, 101, 101, 101 }; - static const status_table_struct table[] = { + static const status_table_struct table[GPERF_TABLE_SIZE] = { F(VmHWM) - NUL NUL - F(VmLck) - NUL - F(VmSwap) + F(Threads) + NUL NUL NUL F(VmRSS) - NUL - F(VmStk) - NUL + F(VmSwap) + NUL NUL NUL F(Tgid) - F(State) - NUL - F(VmLib) - NUL + F(VmStk) + NUL NUL NUL F(VmSize) - F(SigQ) - NUL - F(SigIgn) - NUL + F(Gid) + NUL NUL NUL F(VmPTE) - F(FDSize) - NUL - F(SigBlk) - NUL + F(VmPeak) + NUL NUL NUL F(ShdPnd) - F(VmData) - NUL - F(CapInh) - NUL + F(Pid) + NUL NUL NUL F(PPid) - NUL NUL - F(CapBnd) - NUL + F(VmLib) + NUL NUL NUL F(SigPnd) - NUL NUL - F(VmPeak) - NUL + F(VmLck) + NUL NUL NUL F(SigCgt) - NUL NUL - F(Threads) - NUL + F(State) + NUL NUL NUL F(CapPrm) - NUL NUL - F(Pid) - NUL + F(Uid) + NUL NUL NUL + F(SigIgn) + F(SigQ) + NUL NUL NUL + F(RssShmem) + F(Name) + NUL NUL NUL + F(CapInh) + F(VmData) + NUL NUL NUL + F(FDSize) + NUL NUL NUL NUL + F(SigBlk) + NUL NUL NUL NUL F(CapEff) - NUL NUL - F(Gid) - NUL + NUL NUL NUL NUL + F(CapBnd) + NUL NUL NUL NUL F(VmExe) - NUL NUL - F(Uid) - NUL + NUL NUL NUL NUL F(Groups) - NUL NUL - F(Name) + NUL NUL NUL NUL + F(RssAnon) + NUL NUL NUL NUL + F(RssFile) }; #undef F @@ -248,7 +249,7 @@ ENTER(0x220); // examine a field name (hash and compare) base: if(unlikely(!*S)) break; - entry = table[63 & (asso[(int)S[3]] + asso[(int)S[2]] + asso[(int)S[0]])]; + entry = table[(GPERF_TABLE_SIZE -1) & (asso[(int)S[3]] + asso[(int)S[2]] + asso[(int)S[0]])]; colon = strchr(S, ':'); if(unlikely(!colon)) break; if(unlikely(colon[1]!='\t')) break; @@ -361,6 +362,15 @@ ENTER(0x220); case_VmRSS: P->vm_rss = strtol(S,&S,10); continue; + case_RssAnon: // subset of VmRSS, linux-4.5 + P->vm_rss_anon = strtol(S,&S,10); + continue; + case_RssFile: // subset of VmRSS, linux-4.5 + P->vm_rss_file = strtol(S,&S,10); + continue; + case_RssShmem: // subset of VmRSS, linux-4.5 + P->vm_rss_shared = strtol(S,&S,10); + continue; case_VmSize: P->vm_size = strtol(S,&S,10); continue; @@ -436,6 +446,7 @@ ENTER(0x220); LEAVE(0x220); } +#undef GPERF_TABLE_SIZE static void supgrps_from_supgids (proc_t *p) { char *g, *s; diff --git a/proc/readproc.h b/proc/readproc.h index fb9b703a..f87b0e9f 100644 --- a/proc/readproc.h +++ b/proc/readproc.h @@ -116,6 +116,9 @@ typedef struct proc_t { vm_size, // status equals 'size' (as kb) vm_lock, // status locked pages (as kb) vm_rss, // status equals 'rss' and/or 'resident' (as kb) + vm_rss_anon, // status the 'anonymous' portion of vm_rss (as kb) + vm_rss_file, // status the 'file-backed' portion of vm_rss (as kb) + vm_rss_shared, // status the 'shared' portion of vm_rss (as kb) vm_data, // status data only size (as kb) vm_stack, // status stack only size (as kb) vm_swap, // status based on linux-2.6.34 "swap ents" (as kb)