EpiRootkit
By STDBOOL
Loading...
Searching...
No Matches
ulist.c File Reference
#include "ulist.h"
#include <linux/err.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/slab.h>
#include <linux/string.h>
#include "config.h"
#include "io.h"
Include dependency graph for ulist.c:

Go to the source code of this file.

Functions

static bool ulist_has_item (struct ulist *ul, const char *value)
 
void ulist_clear (struct ulist *ul)
 
int ulist_load (struct ulist *ul)
 
int ulist_save (struct ulist *ul)
 
int ulist_add (struct ulist *ul, const char *value, u32 flags, const char *payload)
 
int ulist_remove (struct ulist *ul, const char *value)
 
int ulist_contains (struct ulist *ul, const char *value)
 
int ulist_list (struct ulist *ul, char *buf, size_t buf_size)
 

Function Documentation

◆ ulist_add()

int ulist_add ( struct ulist ul,
const char *  value,
u32  flags,
const char *  payload 
)

ulist_add - Adds a new item to the ulist.

Parameters
ulPointer to the ulist structure.
valueThe string value to add.
flagsFlags associated with the item.
payloadOptional payload string (can be NULL).

Returns 0 on success, -EEXIST if the item already exists, or -ENOMEM on memory allocation failure.

Definition at line 208 of file ulist.c.

209 {
210 if (ulist_has_item(ul, value)) {
211 return -EEXIST;
212 }
213
214 struct ulist_item *it = kzalloc(sizeof(*it), GFP_KERNEL);
215 if (!it)
216 return -ENOMEM;
217
218 it->value = kstrdup(value, GFP_KERNEL);
219 it->flags = flags;
220 it->payload = payload ? kstrdup(payload, GFP_KERNEL) : NULL;
221 INIT_LIST_HEAD(&it->list);
222
223 spin_lock(&ul->lock);
224 list_add_tail(&it->list, &ul->head);
225 spin_unlock(&ul->lock);
226 return SUCCESS;
227}
#define SUCCESS
Definition config.h:5
char * payload
Definition ulist.h:11
struct list_head list
Definition ulist.h:12
char * value
Definition ulist.h:9
u32 flags
Definition ulist.h:10
struct list_head head
Definition ulist.h:16
spinlock_t lock
Definition ulist.h:17
static bool ulist_has_item(struct ulist *ul, const char *value)
Definition ulist.c:23

◆ ulist_clear()

void ulist_clear ( struct ulist ul)

ulist_clear - Removes and frees all items from a ulist.

Parameters
ulPointer to the ulist structure to clear.

Definition at line 39 of file ulist.c.

39 {
40 struct ulist_item *it, *tmp;
41 spin_lock(&ul->lock);
42 list_for_each_entry_safe(it, tmp, &ul->head, list) {
43 list_del(&it->list);
44 kfree(it->value);
45 kfree(it->payload);
46 kfree(it);
47 }
48 spin_unlock(&ul->lock);
49}

◆ ulist_contains()

int ulist_contains ( struct ulist ul,
const char *  value 
)

ulist_contains - Checks if a value exists in the ulist.

Parameters
ulPointer to the ulist structure.
valueThe string value to check for.

Returns 1 if the value is found, 0 otherwise.

Definition at line 258 of file ulist.c.

258 {
259 struct ulist_item *it;
260 int found = 0;
261
262 spin_lock(&ul->lock);
263 list_for_each_entry(it, &ul->head, list) {
264 if (!strcmp(it->value, value)) {
265 found = 1;
266 break;
267 }
268 }
269 spin_unlock(&ul->lock);
270 return found;
271}

◆ ulist_has_item()

static bool ulist_has_item ( struct ulist ul,
const char *  value 
)
static

ulist_has_item - Checks if a value exists in the ulist.

Parameters
ulPointer to the ulist structure to search.
valueThe string value to look for in the list. Note: Only the value field is compared; flags and payload are ignored.

Return: true if the value is found in the list, false otherwise.

Definition at line 23 of file ulist.c.

23 {
24 struct ulist_item *it;
25
26 // Check only the value in the list
27 // (we don't care about flags or payload)
28 list_for_each_entry(it, &ul->head, list) {
29 if (strcmp(it->value, value) == 0)
30 return true;
31 }
32 return false;
33}

◆ ulist_list()

int ulist_list ( struct ulist ul,
char *  buf,
size_t  buf_size 
)

ulist_list - Lists all items in the ulist into a buffer.

Parameters
ulPointer to the ulist structure.
bufBuffer to store the list of items.
buf_sizeSize of the buffer.

Returns the number of bytes written to the buffer, or a negative error code on failure. The format is "value|flags|payload\n" for each item.

Definition at line 282 of file ulist.c.

282 {
283 struct ulist_item *it;
284 size_t left = buf_size;
285 char *p = buf;
286 int n;
287
288 if (!ul || !buf || buf_size == 0)
289 return -EINVAL;
290
291 spin_lock(&ul->lock);
292 list_for_each_entry(it, &ul->head, list) {
293 n = scnprintf(p, left, "%s|%u|%s\n", it->value, it->flags,
294 it->payload ?: "");
295 if (n >= left)
296 break;
297 p += n;
298 left -= n;
299 }
300 spin_unlock(&ul->lock);
301
302 if (left > 0)
303 *p = '\0';
304 else
305 buf[buf_size - 1] = '\0';
306
307 return p - buf;
308}

◆ ulist_load()

int ulist_load ( struct ulist ul)

ulist_init - Initializes a ulist structure.

Parameters
ulPointer to the ulist structure to initialize.

Initializes the ulist structure, setting up the lock and list head, and storing the filename for later use in loading/saving.

Definition at line 58 of file ulist.c.

58 {
59 char cfgpath[512];
60 char *buf = NULL;
61 char *p, *newline;
62 int ret;
63
64 if (!ul || !ul->filename) {
65 ERR_MSG("ulist_load: invalid arguments ul=%p filename=%p\n", ul,
66 ul ? ul->filename : NULL);
67 return -EINVAL;
68 }
69 build_cfg_path(ul->filename, cfgpath, sizeof(cfgpath));
70
71 ret = _read_file(cfgpath, &buf);
72 if (ret < 0) {
73 if (ret == -ENOENT) {
74 DBG_MSG("ulist_load: no config file '%s'\n", cfgpath);
75 return 0;
76 }
77 ERR_MSG("ulist_load: error reading '%s': %d\n", cfgpath, ret);
78 return ret;
79 }
80
81 if (!buf[0]) {
82 DBG_MSG("ulist_load: empty config '%s'\n", cfgpath);
83 kfree(buf);
84 return 0;
85 }
86
87 p = buf;
88 while (*p) {
89 char line[ULIST_LINE_MAX];
90 size_t len;
91 char *fields[3] = { NULL, NULL, NULL };
92 char *cursor;
93 u32 flags = 0;
94 char *payload = NULL;
95 int rc;
96
97 // Find end of this line
98 newline = strpbrk(p, "\r\n");
99 len = newline ? (newline - p) : strlen(p);
100
101 // Skip empty lines
102 if (len == 0) {
103 if (!newline)
104 break;
105 p = newline + 1;
106 continue;
107 }
108
109 // Clamp overly long lines
110 if (len >= ULIST_LINE_MAX) {
111 ERR_MSG("ulist_load: skipping too-long line\n");
112 if (!newline)
113 break;
114 p = newline + 1;
115 continue;
116 }
117
118 memcpy(line, p, len);
119 line[len] = '\0';
120
121 // Split into exactly three fields around '|'
122 cursor = line;
123 fields[0] = strsep(&cursor, "|");
124 fields[1] = strsep(&cursor, "|");
125 fields[2] = cursor;
126
127 // The field[0] must be non-empty eheh
128 if (!fields[0] || !*fields[0]) {
129 ERR_MSG("ulist_load: missing value, skipping line\n");
130 if (!newline)
131 break;
132 p = newline + 1;
133 }
134
135 // Parse flags (default to 0 on error)
136 if (fields[1] && *fields[1]) {
137 int err = kstrtou32(fields[1], 10, &flags);
138 if (err) {
139 ERR_MSG("ulist_load: bad flags '%s', using 0\n", fields[1]);
140 flags = 0;
141 }
142 }
143
144 // Payload may be empty string so treat it as NULL lol
145 if (fields[2] && *fields[2])
146 payload = fields[2];
147
148 // Add to list
149 rc = ulist_add(ul, fields[0], flags, payload);
150 if (rc < 0)
151 ERR_MSG("ulist_load: ulist_add(%s) failed: %d\n", fields[0], rc);
152
153 if (!newline)
154 break;
155 p = newline + 1;
156 }
157
158 kfree(buf);
159 return 0;
160}
#define ERR_MSG(fmt, args...)
Definition config.h:16
#define DBG_MSG(fmt, args...)
Definition config.h:15
#define ULIST_LINE_MAX
Definition config.h:70
void build_cfg_path(const char *fname, char *out, size_t sz)
Definition io.c:87
int _read_file(const char *path, char **out_buf)
Definition io.c:12
const char * filename
Definition ulist.h:18
int ulist_add(struct ulist *ul, const char *value, u32 flags, const char *payload)
Definition ulist.c:208

◆ ulist_remove()

int ulist_remove ( struct ulist ul,
const char *  value 
)

ulist_remove - Removes an item from the ulist by value.

Parameters
ulPointer to the ulist structure.
valueThe string value to remove.

Returns 0 on success, or -ENOENT if the item was not found.

Definition at line 236 of file ulist.c.

236 {
237 struct ulist_item *it, *tmp;
238 spin_lock(&ul->lock);
239 list_for_each_entry_safe(it, tmp, &ul->head, list) {
240 if (!strcmp(it->value, value)) {
241 list_del(&it->list);
242 kfree(it->value);
243 kfree(it->payload);
244 kfree(it);
245 }
246 }
247 spin_unlock(&ul->lock);
248 return 0;
249}

◆ ulist_save()

int ulist_save ( struct ulist ul)

ulist_init - Initializes a ulist structure.

Parameters
ulPointer to the ulist structure to initialize.

Initializes the ulist structure, setting up the lock and list head, and storing the filename for later use in loading/saving.

Definition at line 169 of file ulist.c.

169 {
170 char cfgpath[128];
171 char *buf, *q;
172 size_t left = STD_BUFFER_SIZE;
173 struct ulist_item *it;
174 int ret;
175
176 buf = kzalloc(STD_BUFFER_SIZE, GFP_KERNEL);
177 if (!buf)
178 return -ENOMEM;
179 q = buf;
180
181 spin_lock(&ul->lock);
182 list_for_each_entry(it, &ul->head, list) {
183 int n = scnprintf(q, left, "%s|%u|%s\n", it->value, it->flags,
184 it->payload ?: "");
185 q += n;
186 left -= n;
187 if (left <= 0)
188 break;
189 }
190 spin_unlock(&ul->lock);
191
192 build_cfg_path(ul->filename, cfgpath, sizeof(cfgpath));
193 ret = _write_file(cfgpath, buf, q - buf);
194 kfree(buf);
195 return ret > 0 ? 1 : ret;
196}
#define STD_BUFFER_SIZE
Definition config.h:68
int _write_file(const char *path, const char *buf, size_t len)
Definition io.c:67