Skip to content

Commit fd7a139

Browse files
PLEDGE: New strace parser (#4225)
* PLEDGE: New strace parser - This parser saves every path in a line and lets us pick and choose which - Statistics are accurate now ones to use * PLEDGE: Small fixes and now we wrap stat() - Moved from perm to keys in the enforce() function, more name changes to come - Fixed some comments - Wrapped stat() * PLEDGE: Better relative path handling for fstatat()
1 parent eb4abb2 commit fd7a139

File tree

6 files changed

+283
-133
lines changed

6 files changed

+283
-133
lines changed

devel/pledge/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ The most important file here is the contract file, if we `cat` it we get:
4646
```
4747
action path count
4848
R </usr/bin/cat> 1
49-
SR </home/user/dummy> 33
5049
S </usr/lib/debug> 1
5150
R </etc/ld.so.cache> 2
5251
+ </usr/lib/aarch64-linux-gnu/libc.so.6> 4

devel/pledge/TODO

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
* Enforcer should allow paths that have a Stat permission lead to other calls without issues
22
* We need to trace failed calls (we should start with ENOENT)
3-
* Implement new tracer for creation, deletion, metadata and list operations
3+
* Dependency graph of our own?
4+
* mprotect

devel/pledge/src/enforcer.c

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ deinit_enforce()
257257
/// @param pathname: This is the pathname to check for enforcing
258258
/// @param perm: This is the permission that this path should have
259259
bool enforce(const char *pathname,
260-
const uint8_t perm)
260+
const uint8_t keys)
261261
{
262262
// WHITELIST check
263263
for (size_t i = 0; WHITELIST[i] != NULL; i++) {
@@ -294,7 +294,7 @@ bool enforce(const char *pathname,
294294
return true;
295295
}
296296
// Order matters a lot for these operations
297-
if (a->delete && (perm & DELETE_ACCESS)) {
297+
if (a->delete && (keys & DELETE_ACCESS)) {
298298
flag2letter(a, a_perm, a_perm_len);
299299
PRINT_GREEN();
300300
fprintf(stderr,
@@ -306,7 +306,7 @@ bool enforce(const char *pathname,
306306
PRINT_RESET_TERM_C();
307307
return true;
308308
}
309-
if (a->list && (perm & LIST_ACCESS)) {
309+
if (a->list && (keys & LIST_ACCESS)) {
310310
flag2letter(a, a_perm, a_perm_len);
311311
PRINT_GREEN();
312312
fprintf(stderr,
@@ -330,7 +330,7 @@ bool enforce(const char *pathname,
330330
// An interesting thing is that an O_CREAT flag on open does not guarantee
331331
// that the OS will return the file descriptor with the permission that was requested
332332
// if the file is created, the fd might be open with READ and WRITE permissions
333-
if (a->create && (perm & CREATE_ACCESS)) {
333+
if (a->create && (keys & CREATE_ACCESS)) {
334334
flag2letter(a, a_perm, a_perm_len);
335335
PRINT_GREEN();
336336
fprintf(stderr,
@@ -343,7 +343,7 @@ bool enforce(const char *pathname,
343343
}
344344

345345
// We are not trying to create or delete, so it doesnt matter
346-
if ((a->read && a->write) && (perm & READ_ACCESS || perm & WRITE_ACCESS)) {
346+
if ((a->read && a->write) && (keys & READ_ACCESS || keys & WRITE_ACCESS)) {
347347
flag2letter(a, a_perm, a_perm_len);
348348
PRINT_GREEN();
349349
fprintf(stderr,
@@ -354,7 +354,7 @@ bool enforce(const char *pathname,
354354
a_perm);
355355
PRINT_RESET_TERM_C();
356356
return true;
357-
} else if ((a->read && (perm & READ_ACCESS)) || (a->write && (perm & WRITE_ACCESS))) {
357+
} else if ((a->read && (keys & READ_ACCESS)) || (a->write && (keys & WRITE_ACCESS))) {
358358
flag2letter(a, a_perm, a_perm_len);
359359
PRINT_GREEN();
360360
fprintf(stderr,
@@ -365,7 +365,7 @@ bool enforce(const char *pathname,
365365
a_perm);
366366
PRINT_RESET_TERM_C();
367367
return true;
368-
} else if (a->stat && (perm & STAT_ACCESS)) {
368+
} else if (a->stat && (keys & STAT_ACCESS)) {
369369
flag2letter(a, a_perm, a_perm_len);
370370
PRINT_GREEN();
371371
fprintf(stderr,
@@ -382,7 +382,7 @@ bool enforce(const char *pathname,
382382
fprintf(stderr,
383383
"[BLOCKED]: "
384384
"Permission [0x%x] for path [%s] does not match contract, expected [%s]\n",
385-
perm,
385+
keys,
386386
a->pathname,
387387
a_perm);
388388
PRINT_RESET_TERM_C();
@@ -560,6 +560,35 @@ fopen(const char *restrict pathname,
560560
return real_fopen(pathname, mode);
561561
}
562562

563+
int stat(const char *restrict pathname,
564+
struct stat *restrict statbuf)
565+
{
566+
PRINT_YELLOW();
567+
fprintf(stderr, "[STAT]: Caught path [%s]\n", pathname);
568+
PRINT_RESET_TERM_C();
569+
570+
size_t path_len = strlen(pathname);
571+
if (path_len < 1) {
572+
// TODO: Better error handling
573+
return -1;
574+
}
575+
576+
// 1. If pathname is relative then we make it absolute basing ourselves
577+
// 2. If the path is absolute, we just use that path to verify
578+
// In theory this is fine because rel2abspath leaves absolute paths as is
579+
char full_path[MAXPATHLEN];
580+
if (rel2abspath(full_path, pathname, MAXPATHLEN) == NULL) {
581+
// Couldn't convert so we fallback to pathname
582+
strncpy(full_path, pathname, MAXPATHLEN);
583+
}
584+
enforce(full_path, STAT_ACCESS);
585+
586+
int (*real_stat)(const char *restrict pathname, struct stat *restrict statbuf);
587+
real_stat = dlsym(RTLD_NEXT, "stat");
588+
589+
return real_stat(pathname, statbuf);
590+
}
591+
563592
int fstatat(int dirfd,
564593
const char *restrict pathname,
565594
struct stat *restrict statbuf,
@@ -601,7 +630,14 @@ int fstatat(int dirfd,
601630
char solved_path[MAXPATHLEN];
602631
size_t solved_path_len = readlink(fd_link, solved_path, MAXPATHLEN);
603632
solved_path[solved_path_len] = '\0';
604-
strcat(solved_path, pathname); // XXX: strncat()?
633+
// XXX: strncat()?
634+
if (path_len > 2) {
635+
if (pathname[0] == '.' && pathname[1] == '/') {
636+
strcat(solved_path, pathname + 2);
637+
}
638+
} else {
639+
strcat(solved_path, pathname);
640+
}
605641
enforce(solved_path, STAT_ACCESS);
606642
}
607643

devel/pledge/src/list_util.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ void generate_contract_from_list(FILE *f, struct list *r)
137137
if (a->delete)
138138
strcat(perms, "D");
139139

140-
/// XXX: We should rewrite the enforcer wrapper functions to
140+
/// TODO: We should rewrite the enforcer wrapper functions to
141141
/// use 2 separate letters for RW permission and not +
142142
if (a->read && a->write)
143143
strcat(perms, "+");

devel/pledge/src/list_util.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
// because otherwise we might not be able to do much
2828
// Now the real question is, do we LABEL an open call as whatever flag it carries
2929
// (aside from creat obviously)
30-
/// Singly linked list containing our paths with their permission
30+
/// Struct containing our paths with their permission
3131
/// TODO: Change name
3232
struct path_access {
3333
/// How many times the file has been accessed
3434
uint32_t count;
35+
/// XXX: For statistics and summarization, if there was an ENOENT on a certain path
36+
/// it should be saved
3537
/// Pathname in absolute form, ideally it should never be relative
3638
char *pathname;
3739
/// Flag for read

0 commit comments

Comments
 (0)