Skip to content

Commit 44a9eb6

Browse files
PLEDGE: Move to metadata, add getdents, initial error support (#4232)
- Moved to metadata flags, got rid of stat too - Added getdents64 to tracing and it is also wrapped in the enforcer - Moved rel2abspath to list_util - Updated the tracing and enforcing to be logically consistent, for example, open is now metadata
1 parent fd7a139 commit 44a9eb6

File tree

9 files changed

+182
-201
lines changed

9 files changed

+182
-201
lines changed

devel/pledge/README.md

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,29 +44,32 @@ Tracer [cat.sample.c]: Contract generated -> cat.sample.c.contract
4444
The most important file here is the contract file, if we `cat` it we get:
4545

4646
```
47-
action path count
48-
R </usr/bin/cat> 1
49-
S </usr/lib/debug> 1
50-
R </etc/ld.so.cache> 2
51-
+ </usr/lib/aarch64-linux-gnu/libc.so.6> 4
52-
R </usr/lib/locale/locale-archive> 2
53-
R </etc/locale.alias> 3
54-
R </usr/lib/locale/C.utf8/LC_IDENTIFICATION> 2
55-
R </usr/lib/aarch64-linux-gnu/gconv/gconv-modules.cache> 2
56-
R </usr/lib/locale/C.utf8/LC_MEASUREMENT> 2
57-
R </usr/lib/locale/C.utf8/LC_TELEPHONE> 2
58-
R </usr/lib/locale/C.utf8/LC_ADDRESS> 2
59-
R </usr/lib/locale/C.utf8/LC_NAME> 2
60-
R </usr/lib/locale/C.utf8/LC_PAPER> 2
61-
R </usr/lib/locale/C.utf8/LC_MESSAGES> 1
62-
R </usr/lib/locale/C.utf8/LC_MESSAGES/SYS_LC_MESSAGES> 2
63-
R </usr/lib/locale/C.utf8/LC_MONETARY> 2
64-
R </usr/lib/locale/C.utf8/LC_COLLATE> 2
65-
R </usr/lib/locale/C.utf8/LC_TIME> 2
66-
R </usr/lib/locale/C.utf8/LC_NUMERIC> 2
67-
R </usr/lib/locale/C.utf8/LC_CTYPE> 2
68-
R </home/user/dummy/sample.c> 3
69-
W </dev/pts/0> 1
47+
Access <Path> Count
48+
R </usr/bin/cat> 1
49+
M </usr/lib/debug/libc.so.6> 1
50+
M </usr/lib/debug/> 1
51+
MR </etc/ld.so.cache> 2
52+
MRW </usr/lib/aarch64-linux-gnu/libc.so.6> 4
53+
MR </usr/lib/locale/locale-archive> 2
54+
MR </etc/locale.alias> 3
55+
ME </usr/lib/locale/C.UTF-8/LC_IDENTIFICATION> 1
56+
MR </usr/lib/locale/C.utf8/LC_IDENTIFICATION> 2
57+
MR </usr/lib/aarch64-linux-gnu/gconv/gconv-modules.cache> 2
58+
MR </usr/lib/locale/C.utf8/LC_MEASUREMENT> 2
59+
MR </usr/lib/locale/C.utf8/LC_TELEPHONE> 2
60+
MR </usr/lib/locale/C.utf8/LC_ADDRESS> 2
61+
MR </usr/lib/locale/C.utf8/LC_NAME> 2
62+
MR </usr/lib/locale/C.utf8/LC_PAPER> 2
63+
M </usr/lib/locale/C.utf8/LC_MESSAGES> 1
64+
MR </usr/lib/locale/C.utf8/LC_MESSAGES/SYS_LC_MESSAGES> 2
65+
MR </usr/lib/locale/C.utf8/LC_MONETARY> 2
66+
MR </usr/lib/locale/C.utf8/LC_COLLATE> 2
67+
MR </usr/lib/locale/C.utf8/LC_TIME> 2
68+
MR </usr/lib/locale/C.utf8/LC_NUMERIC> 2
69+
MR </usr/lib/locale/C.utf8/LC_CTYPE> 2
70+
MR </home/user/dummy/sample.c> 3
71+
W </dev/pts/0> 1
72+
7073
```
7174

7275
### Enforcer

devel/pledge/TODO

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
* We need to trace failed calls (we should start with ENOENT)
33
* Dependency graph of our own?
44
* mprotect
5+
* pipes and unfinished
6+
* enforce()'ing needs a check up

devel/pledge/src/Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ TARGETS = $(LIBRARIES) $(PROGRAMS)
88

99
EXTERNAL_DEPENDENCIES = $(CCTOOLS_HOME)/dttools/src/libdttools.a
1010

11-
SOURCES = pledge.c list_util.c util.c enforcer.c
12-
COMMON_SRCS = list_util.c util.c
11+
SOURCES = pledge.c list_util.c enforcer.c
12+
COMMON_SRCS = list_util.c
1313

1414
OBJECTS = list_util.o util.o pledge.o enforcer.o
15-
OBJECTS_PLEDGE = list_util.o util.o pledge.o
15+
OBJECTS_PLEDGE = list_util.o pledge.o
1616

1717
# If we want to color output while enforcing
1818
# DEFS = -DCOLOR_ENFORCING

devel/pledge/src/enforcer.c

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <unistd.h>
1212

1313
#include "list_util.h"
14-
#include "util.h"
1514

1615
#ifdef COLOR_ENFORCING
1716
#define PINK "\033[38;5;198m"
@@ -44,39 +43,36 @@ void flag2letter(struct path_access *r, char *buff, size_t buff_len)
4443
return;
4544
}
4645
memset(buff, 0, buff_len);
47-
if (r->stat)
48-
strncat(buff, "S", buff_len);
46+
if (r->metadata)
47+
strncat(buff, "M", buff_len);
4948
if (r->create)
5049
strncat(buff, "C", buff_len);
5150
if (r->delete)
5251
strncat(buff, "D", buff_len);
53-
if (r->read && r->write)
54-
strncat(buff, "+", buff_len);
55-
else if (r->read)
52+
if (r->read)
5653
strncat(buff, "R", buff_len);
57-
else if (r->write)
54+
if (r->write)
5855
strncat(buff, "W", buff_len);
5956
if (r->list)
6057
strncat(buff, "L", buff_len);
58+
if (r->error)
59+
strncat(buff, "E", buff_len);
6160
}
6261

6362
// TODO: The bit flags need to be changed to a typedef so we can
6463
// change the bit count whenever
6564
uint8_t letter2bitflag(char x)
6665
{
6766
switch (x) {
68-
case 'S':
69-
return STAT_ACCESS;
67+
case 'M':
68+
return METADATA_ACCESS;
7069
break;
7170
case 'R':
7271
return READ_ACCESS;
7372
break;
7473
case 'W':
7574
return WRITE_ACCESS;
7675
break;
77-
case '+':
78-
return READ_ACCESS | WRITE_ACCESS;
79-
break;
8076
case 'C':
8177
return CREATE_ACCESS;
8278
break;
@@ -86,6 +82,9 @@ uint8_t letter2bitflag(char x)
8682
case 'L':
8783
return LIST_ACCESS;
8884
break;
85+
case 'E':
86+
return ERROR_ACCESS;
87+
break;
8988
default:
9089
return UNKOWN_ACCESS;
9190
break;
@@ -365,11 +364,22 @@ bool enforce(const char *pathname,
365364
a_perm);
366365
PRINT_RESET_TERM_C();
367366
return true;
368-
} else if (a->stat && (keys & STAT_ACCESS)) {
367+
} else if (a->metadata && (keys & METADATA_ACCESS)) {
369368
flag2letter(a, a_perm, a_perm_len);
370369
PRINT_GREEN();
371370
fprintf(stderr,
372-
"[ALLOWED STAT]: "
371+
"[ALLOWED METADATA OPERATION]: "
372+
"Path [%s] with permission [%s] is not in violation of the "
373+
"contract.\n",
374+
a->pathname,
375+
a_perm);
376+
PRINT_RESET_TERM_C();
377+
return true;
378+
} else if (a->list && (keys & LIST_ACCESS)) {
379+
flag2letter(a, a_perm, a_perm_len);
380+
PRINT_GREEN();
381+
fprintf(stderr,
382+
"[ALLOWED GETDENTS]: "
373383
"Path [%s] with permission [%s] is not in violation of the "
374384
"contract.\n",
375385
a->pathname,
@@ -428,16 +438,9 @@ int open(const char *pathname,
428438

429439
path_perm |= CREATE_ACCESS;
430440
}
441+
path_perm |= METADATA_ACCESS;
431442

432443
// SECTION: Enforce
433-
if ((flags & O_RDONLY) == O_RDONLY) // O_RDONLY flag is 0 under the hood
434-
{
435-
path_perm |= READ_ACCESS;
436-
} else if (flags & O_WRONLY) {
437-
path_perm |= WRITE_ACCESS;
438-
} else if (flags & O_RDWR) {
439-
path_perm |= READ_ACCESS | WRITE_ACCESS;
440-
}
441444
if (enforce(full_path, path_perm) != true) {
442445
return -1;
443446
}
@@ -517,33 +520,8 @@ fopen(const char *restrict pathname,
517520
// SECTION: Enforcing
518521
uint8_t perm_val = 0x0;
519522
char mode_len = strlen(mode);
520-
// We need to get the values out of the flags
521-
if (strcmp(mode, "r") == 0) {
522-
perm_val |= READ_ACCESS;
523-
} else if (strcmp(mode, "w") == 0) {
524-
perm_val |= WRITE_ACCESS;
525-
} else if (strcmp(mode, "a") == 0) {
526-
perm_val |= WRITE_ACCESS;
527-
} else if (mode_len > 1) {
528-
if (mode[1] == '+') {
529-
perm_val |= READ_ACCESS | WRITE_ACCESS;
530-
// b and + are not the only things we can to an fopen mode flag call
531-
// theres also e, but for now we only want to treat + like its special
532-
// b and e, we dont really concern ourselves
533-
} else {
534-
// not a fan of this
535-
switch (mode[0]) {
536-
case 'r':
537-
perm_val |= READ_ACCESS;
538-
break;
539-
case 'w':
540-
perm_val |= WRITE_ACCESS;
541-
break;
542-
}
543-
}
544-
} else {
545-
fprintf(stderr, "FOPEN: Unkown permission [%s]\n", mode);
546-
}
523+
524+
perm_val |= METADATA_ACCESS;
547525

548526
char full_path[MAXPATHLEN];
549527
if (rel2abspath(full_path, pathname, MAXPATHLEN) == NULL) {
@@ -581,7 +559,7 @@ int stat(const char *restrict pathname,
581559
// Couldn't convert so we fallback to pathname
582560
strncpy(full_path, pathname, MAXPATHLEN);
583561
}
584-
enforce(full_path, STAT_ACCESS);
562+
enforce(full_path, METADATA_ACCESS);
585563

586564
int (*real_stat)(const char *restrict pathname, struct stat *restrict statbuf);
587565
real_stat = dlsym(RTLD_NEXT, "stat");
@@ -622,7 +600,7 @@ int fstatat(int dirfd,
622600
// TODO: This could be made to only have 1 call to enforce instead of 2 in separate
623601
// branches
624602
if (dirfd == AT_FDCWD) {
625-
enforce(full_path, STAT_ACCESS);
603+
enforce(full_path, METADATA_ACCESS);
626604
} else {
627605
// Solve the dirfd and then glue it together with the absolute path
628606
char fd_link[MAXPATHLEN];
@@ -638,7 +616,7 @@ int fstatat(int dirfd,
638616
} else {
639617
strcat(solved_path, pathname);
640618
}
641-
enforce(solved_path, STAT_ACCESS);
619+
enforce(solved_path, METADATA_ACCESS);
642620
}
643621

644622
int (*real_fstatat)(int dirfd, const char *restrict pathname, struct stat *restrict statbuf, int flags);
@@ -669,3 +647,24 @@ int remove(const char *pathname)
669647
real_remove = dlsym(RTLD_NEXT, "remove");
670648
return real_remove(pathname);
671649
}
650+
651+
ssize_t getdents64(int fd, void *dirp, size_t count)
652+
{
653+
char fd_link[BUFSIZ];
654+
snprintf(fd_link, BUFSIZ, "/proc/self/fd/%d", fd);
655+
char solved_path[BUFSIZ];
656+
size_t solved_path_len = readlink(fd_link, solved_path, BUFSIZ);
657+
solved_path[solved_path_len] = '\0';
658+
659+
PRINT_YELLOW();
660+
fprintf(stderr, "[GETDENTS64]: Caught path: [%s]\n", solved_path);
661+
PRINT_RESET_TERM_C();
662+
663+
if (enforce(solved_path, LIST_ACCESS) != true) {
664+
return -1;
665+
}
666+
667+
ssize_t (*real_getdents64)(int fd, void *dirp, size_t count);
668+
real_getdents64 = dlsym(RTLD_NEXT, "getdents64");
669+
return real_getdents64(fd, dirp, count);
670+
}

devel/pledge/src/list_util.c

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,58 @@
11
#include "list_util.h"
22

3+
/// Turn a relative path into an absolute path, based on CWD
4+
/// @param abs_p is the buffer where we will store the absolute path
5+
/// @param rel_p is the user given string
6+
/// @param size is the size/len of abs_p
7+
/// Return If the path does not need to be turned into an absolute path then we just
8+
/// copy to the abs_p buffer and return that
9+
/// TODO: Perhaps we do strlcpy/strlcat?
10+
char *
11+
rel2abspath(char *abs_p,
12+
char *rel_p,
13+
size_t size)
14+
{
15+
if (rel_p == NULL) {
16+
fprintf(stderr, "Attempted to turn an empty string into an absolute path.\n");
17+
abs_p = NULL;
18+
return NULL;
19+
}
20+
// Strnlen??
21+
size_t rel_p_len = strlen(rel_p);
22+
// current directory paths need to get expanded
23+
// TODO: Integrate with dttools/path functions,
24+
// no reason we can't have both
25+
if (rel_p_len == 1) {
26+
if (rel_p[0] == '.') {
27+
realpath(rel_p, abs_p);
28+
return abs_p;
29+
}
30+
}
31+
if (rel_p_len >= 1) {
32+
if (rel_p[0] != '/') {
33+
// Check if its relative of the form ./
34+
if (rel_p[0] == '.' && rel_p[1] == '/') {
35+
rel_p = rel_p + 2;
36+
}
37+
// get cwd
38+
if (getcwd(abs_p, size) == NULL) {
39+
fprintf(stderr, "Attempt to obtain cwd failed.\n");
40+
return rel_p;
41+
}
42+
size_t abs_p_len = strlen(abs_p);
43+
if (abs_p[abs_p_len - 1] != '/') {
44+
strncat(abs_p, "/", MAXPATHLEN);
45+
}
46+
strncat(abs_p, rel_p, MAXPATHLEN);
47+
return abs_p;
48+
}
49+
strncpy(abs_p, rel_p, MAXPATHLEN);
50+
return abs_p;
51+
}
52+
strncpy(abs_p, rel_p, MAXPATHLEN);
53+
return abs_p;
54+
}
55+
356
/// Add a path_access node to our cctools list
457
/// Perhaps this should return the temprary path_access var
558
void new_path_access_node(struct list *c,
@@ -9,10 +62,11 @@ void new_path_access_node(struct list *c,
962
struct path_access *t = malloc(sizeof(struct path_access));
1063
t->read = (access_fl & READ_ACCESS) ? true : false;
1164
t->write = (access_fl & WRITE_ACCESS) ? true : false;
12-
t->stat = (access_fl & STAT_ACCESS) ? true : false;
65+
t->metadata = (access_fl & METADATA_ACCESS) ? true : false;
1366
t->create = (access_fl & CREATE_ACCESS) ? true : false;
1467
t->delete = (access_fl & DELETE_ACCESS) ? true : false;
1568
t->list = (access_fl & LIST_ACCESS) ? true : false;
69+
t->error = (access_fl & ERROR_ACCESS) ? true : false;
1670
t->count = 1;
1771

1872
/// This string gotta be manually removed
@@ -78,8 +132,8 @@ update_path_perms(struct path_access *a,
78132
if (access_fl & WRITE_ACCESS) {
79133
a->write = true;
80134
}
81-
if (access_fl & STAT_ACCESS) {
82-
a->stat = true;
135+
if (access_fl & METADATA_ACCESS) {
136+
a->metadata = true;
83137
}
84138
if (access_fl & CREATE_ACCESS) {
85139
a->create = true;
@@ -90,6 +144,9 @@ update_path_perms(struct path_access *a,
90144
if (access_fl & LIST_ACCESS) {
91145
a->list = true;
92146
}
147+
if (access_fl & ERROR_ACCESS) {
148+
a->list = true;
149+
}
93150
a->count += 1;
94151
// USELESS?: Maybe remove this lol
95152
return a;
@@ -130,25 +187,22 @@ void generate_contract_from_list(FILE *f, struct list *r)
130187
fprintf(o, "%-12s %-14s %s\n", col1_title, col2_title, col3_title);
131188
while ((a = list_next_item(r))) {
132189
// THINK: This might need to become a function
133-
if (a->stat)
134-
strcat(perms, "S");
190+
if (a->metadata)
191+
strcat(perms, "M");
135192
if (a->create)
136193
strcat(perms, "C");
137194
if (a->delete)
138195
strcat(perms, "D");
139-
140-
/// TODO: We should rewrite the enforcer wrapper functions to
141-
/// use 2 separate letters for RW permission and not +
142-
if (a->read && a->write)
143-
strcat(perms, "+");
144-
else if (a->read)
196+
if (a->read)
145197
strcat(perms, "R");
146-
else if (a->write)
198+
if (a->write)
147199
strcat(perms, "W");
148-
149200
if (a->list)
150201
strcat(perms, "L");
151202

203+
if (a->error)
204+
strcat(perms, "E");
205+
152206
fprintf(o, "%-12s <%s> %d\n", perms, a->pathname, a->count);
153207

154208
memset(perms, 0, sizeof(perms)); // reset

0 commit comments

Comments
 (0)