-
Notifications
You must be signed in to change notification settings - Fork 243
Expand file tree
/
Copy pathproc-status.c
More file actions
139 lines (120 loc) · 2.67 KB
/
proc-status.c
File metadata and controls
139 lines (120 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include "proc-status.h"
ssize_t proc_status_read(char *buf, size_t bufsz)
{
ssize_t n;
int fd;
if (buf == NULL || bufsz < 2)
return -1;
fd = open("/proc/self/status", O_RDONLY);
if (fd < 0)
return -1;
n = read(fd, buf, bufsz - 1);
close(fd);
if (n <= 0)
return -1;
buf[n] = '\0';
return n;
}
char *proc_status_slurp(void)
{
char *buf = NULL;
size_t cap = 0, off = 0;
int fd;
fd = open("/proc/self/status", O_RDONLY);
if (fd < 0)
return NULL;
for (;;) {
ssize_t n;
/* Grow on demand, leaving room for the trailing NUL. */
if (off + 2 > cap) {
size_t newcap = cap ? cap * 2 : 4096;
char *nb = malloc(newcap);
if (nb == NULL) {
/*
* Fuzzer may have called mlockall(MCL_FUTURE),
* which pins the heap and can short-circuit
* allocation. Undo the pin and retry once.
*/
munlockall();
nb = malloc(newcap);
}
if (nb == NULL) {
free(buf);
close(fd);
return NULL;
}
if (buf != NULL) {
memcpy(nb, buf, off);
free(buf);
}
buf = nb;
cap = newcap;
}
n = read(fd, buf + off, cap - off - 1);
if (n < 0) {
free(buf);
close(fd);
return NULL;
}
if (n == 0)
break;
off += (size_t) n;
}
close(fd);
buf[off] = '\0';
return buf;
}
const char *proc_status_find_field(const char *buf, const char *name)
{
char needle[64];
const char *hit;
int len;
if (buf == NULL || name == NULL)
return NULL;
/*
* Build "\n<name>:" so the match cannot land inside an earlier field's
* value (e.g. a process Name: that contains "Uid") and cannot collide
* with a sibling field that shares a prefix (Cpus_allowed vs
* Cpus_allowed_list). Trailing ':' is part of the anchor.
*/
len = snprintf(needle, sizeof(needle), "\n%s:", name);
if (len <= 0 || (size_t)len >= sizeof(needle))
return NULL;
hit = strstr(buf, needle);
if (hit == NULL)
return NULL;
return hit + len;
}
bool proc_status_parse_u(const char *value, unsigned long *out)
{
if (value == NULL || out == NULL)
return false;
return sscanf(value, "%lu", out) == 1;
}
bool proc_status_parse_uid_gid_quad(const char *value, unsigned long out[4])
{
if (value == NULL || out == NULL)
return false;
return sscanf(value, "%lu %lu %lu %lu",
&out[0], &out[1], &out[2], &out[3]) == 4;
}
bool proc_status_parse_hex_mask(const char *value, uint64_t *out)
{
unsigned long long v;
if (value == NULL || out == NULL)
return false;
if (sscanf(value, "%llx", &v) != 1)
return false;
*out = (uint64_t)v;
return true;
}