library: exploit linux-4.5 resident memory enhancement
Beginning with linux-4.5, the following new fields are
being added under that /proc/<pid>/status pseudo file:
. RssAnon - size of resident anonymous memory
. RssFile - size of resident file mappings
. RssShmem - size of resident shared memory
This patch just represents the initial library and top
support, sharing a commit message with 2 more patches.
p.s. locked resident memory support was also added but
isn't directly related to the kernel 4.5 enhancements.
Reference(s):
commit 1f8e41d019
Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
b921e2e765
commit
8dc378f6a8
@ -242,6 +242,10 @@ REG_set(VM_EXE, ul_int, vm_exe)
|
|||||||
REG_set(VM_LIB, ul_int, vm_lib)
|
REG_set(VM_LIB, ul_int, vm_lib)
|
||||||
REG_set(VM_LOCK, ul_int, vm_lock)
|
REG_set(VM_LOCK, ul_int, vm_lock)
|
||||||
REG_set(VM_RSS, ul_int, vm_rss)
|
REG_set(VM_RSS, ul_int, vm_rss)
|
||||||
|
REG_set(VM_RSS_ANON, ul_int, vm_rss_anon)
|
||||||
|
REG_set(VM_RSS_FILE, ul_int, vm_rss_file)
|
||||||
|
REG_set(VM_RSS_LOCKED, ul_int, vm_lock)
|
||||||
|
REG_set(VM_RSS_SHARED, ul_int, vm_rss_shared)
|
||||||
REG_set(VM_SIZE, ul_int, vm_size)
|
REG_set(VM_SIZE, ul_int, vm_size)
|
||||||
REG_set(VM_STACK, ul_int, vm_stack)
|
REG_set(VM_STACK, ul_int, vm_stack)
|
||||||
REG_set(VM_SWAP, ul_int, vm_swap)
|
REG_set(VM_SWAP, ul_int, vm_swap)
|
||||||
@ -493,6 +497,10 @@ static struct {
|
|||||||
{ RS(VM_LIB), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_LIB), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_LOCK), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_LOCK), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_RSS), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_RSS), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
|
{ RS(VM_RSS_ANON), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
|
{ RS(VM_RSS_FILE), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
|
{ RS(VM_RSS_LOCKED), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
|
{ RS(VM_RSS_SHARED), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_SIZE), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_SIZE), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_STACK), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_STACK), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_SWAP), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_SWAP), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
|
@ -132,6 +132,10 @@ enum pids_item {
|
|||||||
PROCPS_PIDS_VM_LIB, // ul_int
|
PROCPS_PIDS_VM_LIB, // ul_int
|
||||||
PROCPS_PIDS_VM_LOCK, // ul_int
|
PROCPS_PIDS_VM_LOCK, // ul_int
|
||||||
PROCPS_PIDS_VM_RSS, // ul_int
|
PROCPS_PIDS_VM_RSS, // ul_int
|
||||||
|
PROCPS_PIDS_VM_RSS_ANON, // ul_int
|
||||||
|
PROCPS_PIDS_VM_RSS_FILE, // ul_int
|
||||||
|
PROCPS_PIDS_VM_RSS_LOCKED, // ul_int
|
||||||
|
PROCPS_PIDS_VM_RSS_SHARED, // ul_int
|
||||||
PROCPS_PIDS_VM_SIZE, // ul_int
|
PROCPS_PIDS_VM_SIZE, // ul_int
|
||||||
PROCPS_PIDS_VM_STACK, // ul_int
|
PROCPS_PIDS_VM_STACK, // ul_int
|
||||||
PROCPS_PIDS_VM_SWAP, // ul_int
|
PROCPS_PIDS_VM_SWAP, // ul_int
|
||||||
|
149
proc/readproc.c
149
proc/readproc.c
@ -113,7 +113,7 @@ static inline void free_acquired (proc_t *p, int reuse) {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct status_table_struct {
|
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
|
unsigned char len; // name length
|
||||||
#ifdef LABEL_OFFSET
|
#ifdef LABEL_OFFSET
|
||||||
long offset; // jump address offset
|
long offset; // jump address offset
|
||||||
@ -129,8 +129,11 @@ typedef struct status_table_struct {
|
|||||||
#endif
|
#endif
|
||||||
#define NUL {"", 0, 0},
|
#define NUL {"", 0, 0},
|
||||||
|
|
||||||
|
#define GPERF_TABLE_SIZE 128
|
||||||
|
|
||||||
// Derived from:
|
// Derived from:
|
||||||
// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c <if-not-piped>
|
// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c <if-not-piped>
|
||||||
|
// ( --key-positions verified by omission & reported "Computed positions" )
|
||||||
//
|
//
|
||||||
// Suggested method:
|
// Suggested method:
|
||||||
// Grep this file for "case_", then strip those down to the name.
|
// 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.
|
// the F macro and replacing empty strings with the NUL define.
|
||||||
//
|
//
|
||||||
// In the status_table_struct watch out for name size (grrr, expanding)
|
// 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
|
// and the number of entries. Currently, the table is padded to 128
|
||||||
// must be padded out to 64 entries, maybe 128 in the future.
|
// entries and we therefore mask with 127.
|
||||||
|
|
||||||
static void status2proc(char *S, proc_t *restrict P, int is_proc){
|
static void status2proc(char *S, proc_t *restrict P, int is_proc){
|
||||||
long Threads = 0;
|
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
|
// 128 entries because we trust the kernel to use ASCII names
|
||||||
static const unsigned char asso[] =
|
static const unsigned char asso[] =
|
||||||
{
|
{
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 28, 64,
|
101, 101, 101, 101, 101, 101, 101, 101, 6, 101,
|
||||||
64, 64, 64, 64, 64, 64, 8, 25, 23, 25,
|
101, 101, 101, 101, 101, 45, 55, 25, 31, 50,
|
||||||
6, 25, 0, 3, 64, 64, 3, 64, 25, 64,
|
50, 10, 0, 35, 101, 101, 21, 101, 30, 101,
|
||||||
20, 1, 1, 5, 0, 30, 0, 0, 64, 64,
|
20, 36, 0, 5, 0, 40, 0, 0, 101, 101,
|
||||||
64, 64, 64, 64, 64, 64, 64, 3, 64, 0,
|
101, 101, 101, 101, 101, 101, 101, 30, 101, 15,
|
||||||
0, 18, 64, 10, 64, 10, 64, 64, 64, 20,
|
0, 1, 101, 10, 101, 10, 101, 101, 101, 25,
|
||||||
64, 20, 0, 64, 25, 64, 3, 15, 64, 0,
|
101, 40, 0, 101, 0, 50, 6, 40, 101, 1,
|
||||||
30, 64, 64, 64, 64, 64, 64, 64
|
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)
|
F(VmHWM)
|
||||||
NUL NUL
|
|
||||||
F(VmLck)
|
|
||||||
NUL
|
|
||||||
F(VmSwap)
|
|
||||||
F(VmRSS)
|
|
||||||
NUL
|
|
||||||
F(VmStk)
|
|
||||||
NUL
|
|
||||||
F(Tgid)
|
|
||||||
F(State)
|
|
||||||
NUL
|
|
||||||
F(VmLib)
|
|
||||||
NUL
|
|
||||||
F(VmSize)
|
|
||||||
F(SigQ)
|
|
||||||
NUL
|
|
||||||
F(SigIgn)
|
|
||||||
NUL
|
|
||||||
F(VmPTE)
|
|
||||||
F(FDSize)
|
|
||||||
NUL
|
|
||||||
F(SigBlk)
|
|
||||||
NUL
|
|
||||||
F(ShdPnd)
|
|
||||||
F(VmData)
|
|
||||||
NUL
|
|
||||||
F(CapInh)
|
|
||||||
NUL
|
|
||||||
F(PPid)
|
|
||||||
NUL NUL
|
|
||||||
F(CapBnd)
|
|
||||||
NUL
|
|
||||||
F(SigPnd)
|
|
||||||
NUL NUL
|
|
||||||
F(VmPeak)
|
|
||||||
NUL
|
|
||||||
F(SigCgt)
|
|
||||||
NUL NUL
|
|
||||||
F(Threads)
|
F(Threads)
|
||||||
NUL
|
NUL NUL NUL
|
||||||
F(CapPrm)
|
F(VmRSS)
|
||||||
NUL NUL
|
F(VmSwap)
|
||||||
F(Pid)
|
NUL NUL NUL
|
||||||
NUL
|
F(Tgid)
|
||||||
F(CapEff)
|
F(VmStk)
|
||||||
NUL NUL
|
NUL NUL NUL
|
||||||
|
F(VmSize)
|
||||||
F(Gid)
|
F(Gid)
|
||||||
NUL
|
NUL NUL NUL
|
||||||
F(VmExe)
|
F(VmPTE)
|
||||||
NUL NUL
|
F(VmPeak)
|
||||||
|
NUL NUL NUL
|
||||||
|
F(ShdPnd)
|
||||||
|
F(Pid)
|
||||||
|
NUL NUL NUL
|
||||||
|
F(PPid)
|
||||||
|
F(VmLib)
|
||||||
|
NUL NUL NUL
|
||||||
|
F(SigPnd)
|
||||||
|
F(VmLck)
|
||||||
|
NUL NUL NUL
|
||||||
|
F(SigCgt)
|
||||||
|
F(State)
|
||||||
|
NUL NUL NUL
|
||||||
|
F(CapPrm)
|
||||||
F(Uid)
|
F(Uid)
|
||||||
NUL
|
NUL NUL NUL
|
||||||
F(Groups)
|
F(SigIgn)
|
||||||
NUL NUL
|
F(SigQ)
|
||||||
|
NUL NUL NUL
|
||||||
|
F(RssShmem)
|
||||||
F(Name)
|
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 NUL NUL
|
||||||
|
F(CapBnd)
|
||||||
|
NUL NUL NUL NUL
|
||||||
|
F(VmExe)
|
||||||
|
NUL NUL NUL NUL
|
||||||
|
F(Groups)
|
||||||
|
NUL NUL NUL NUL
|
||||||
|
F(RssAnon)
|
||||||
|
NUL NUL NUL NUL
|
||||||
|
F(RssFile)
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef F
|
#undef F
|
||||||
@ -248,7 +249,7 @@ ENTER(0x220);
|
|||||||
// examine a field name (hash and compare)
|
// examine a field name (hash and compare)
|
||||||
base:
|
base:
|
||||||
if(unlikely(!*S)) break;
|
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, ':');
|
colon = strchr(S, ':');
|
||||||
if(unlikely(!colon)) break;
|
if(unlikely(!colon)) break;
|
||||||
if(unlikely(colon[1]!='\t')) break;
|
if(unlikely(colon[1]!='\t')) break;
|
||||||
@ -364,6 +365,15 @@ ENTER(0x220);
|
|||||||
case_VmRSS:
|
case_VmRSS:
|
||||||
P->vm_rss = strtol(S,&S,10);
|
P->vm_rss = strtol(S,&S,10);
|
||||||
continue;
|
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:
|
case_VmSize:
|
||||||
P->vm_size = strtol(S,&S,10);
|
P->vm_size = strtol(S,&S,10);
|
||||||
continue;
|
continue;
|
||||||
@ -439,6 +449,7 @@ ENTER(0x220);
|
|||||||
|
|
||||||
LEAVE(0x220);
|
LEAVE(0x220);
|
||||||
}
|
}
|
||||||
|
#undef GPERF_TABLE_SIZE
|
||||||
|
|
||||||
static void supgrps_from_supgids (proc_t *p) {
|
static void supgrps_from_supgids (proc_t *p) {
|
||||||
char *g, *s;
|
char *g, *s;
|
||||||
|
@ -117,6 +117,9 @@ typedef struct proc_t {
|
|||||||
vm_size, // status equals 'size' (as kb)
|
vm_size, // status equals 'size' (as kb)
|
||||||
vm_lock, // status locked pages (as kb)
|
vm_lock, // status locked pages (as kb)
|
||||||
vm_rss, // status equals 'rss' and/or 'resident' (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_data, // status data only size (as kb)
|
||||||
vm_stack, // status stack 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)
|
vm_swap, // status based on linux-2.6.34 "swap ents" (as kb)
|
||||||
|
Loading…
Reference in New Issue
Block a user