-
Notifications
You must be signed in to change notification settings - Fork 360
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
checkpolicy: add libfuzz based fuzzer
Introduce a libfuzz[1] based fuzzer testing the parsing and policy generation code used within checkpolicy(8) and checkmodule(8), similar to the fuzzer for secilc(8). The fuzzer will work on generated source policy input and try to parse, link, expand, optimize, sort and output it. Build the fuzzer in the oss-fuzz script. [1]: https://llvm.org/docs/LibFuzzer.html Signed-off-by: Christian Göttsche <[email protected]>
- Loading branch information
Showing
7 changed files
with
432 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
#include <assert.h> | ||
#include <unistd.h> | ||
#include <sys/mman.h> | ||
|
||
#include <sepol/debug.h> | ||
#include <sepol/kernel_to_cil.h> | ||
#include <sepol/kernel_to_conf.h> | ||
#include <sepol/policydb/policydb.h> | ||
#include <sepol/policydb/services.h> | ||
#include <sepol/policydb/hierarchy.h> | ||
#include <sepol/policydb/expand.h> | ||
#include <sepol/policydb/link.h> | ||
|
||
#include "queue.h" | ||
|
||
extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); | ||
|
||
extern int mlspol; | ||
extern policydb_t *policydbp; | ||
extern queue_t id_queue; | ||
extern unsigned int policydb_errors; | ||
|
||
extern int yynerrs; | ||
extern FILE *yyin; | ||
extern void init_parser(int); | ||
extern int yyparse(void); | ||
extern void yyrestart(FILE *); | ||
extern void set_source_file(const char *name); | ||
|
||
static int read_source_policy(policydb_t *p, const uint8_t *data, size_t size) | ||
{ | ||
int fd; | ||
ssize_t wr; | ||
|
||
fd = memfd_create("fuzz-input", MFD_CLOEXEC); | ||
if (fd < 0) | ||
return -1; | ||
|
||
wr = write(fd, data, size); | ||
if (wr < 0 || (size_t)wr != size) { | ||
close(fd); | ||
return -1; | ||
} | ||
|
||
fsync(fd); | ||
|
||
yynerrs = 0; | ||
|
||
yyin = fdopen(fd, "re"); | ||
if (!yyin) { | ||
close(fd); | ||
return -1; | ||
} | ||
|
||
rewind(yyin); | ||
|
||
set_source_file("fuzz-input"); | ||
|
||
id_queue = queue_create(); | ||
if (id_queue == NULL) { | ||
fclose(yyin); | ||
return -1; | ||
} | ||
|
||
policydbp = p; | ||
mlspol = p->mls; | ||
|
||
init_parser(1); | ||
|
||
if (yyparse() || policydb_errors) { | ||
queue_destroy(id_queue); | ||
fclose(yyin); | ||
return -1; | ||
} | ||
|
||
rewind(yyin); | ||
init_parser(2); | ||
set_source_file("fuzz-input"); | ||
yyrestart(yyin); | ||
|
||
if (yyparse() || policydb_errors) { | ||
queue_destroy(id_queue); | ||
fclose(yyin); | ||
return -1; | ||
} | ||
|
||
queue_destroy(id_queue); | ||
fclose(yyin); | ||
|
||
return 0; | ||
} | ||
|
||
static int write_binary_policy(policydb_t *p, FILE *outfp) | ||
{ | ||
struct policy_file pf; | ||
|
||
policy_file_init(&pf); | ||
pf.type = PF_USE_STDIO; | ||
pf.fp = outfp; | ||
return policydb_write(p, &pf); | ||
} | ||
|
||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | ||
{ | ||
policydb_t parsepolicydb = {}; | ||
policydb_t kernpolicydb = {}; | ||
sidtab_t sidtab = {}; | ||
FILE *devnull = NULL; | ||
|
||
sepol_debug(0); | ||
sepol_set_policydb(&parsepolicydb); | ||
sepol_set_sidtab(&sidtab); | ||
|
||
if (policydb_init(&parsepolicydb)) | ||
goto exit; | ||
|
||
parsepolicydb.policy_type = POLICY_BASE; | ||
parsepolicydb.mls = 1; | ||
parsepolicydb.handle_unknown = DENY_UNKNOWN; | ||
policydb_set_target_platform(&parsepolicydb, SEPOL_TARGET_SELINUX); | ||
|
||
if (read_source_policy(&parsepolicydb, data, size)) | ||
goto exit; | ||
|
||
if (hierarchy_check_constraints(NULL, &parsepolicydb)) | ||
goto exit; | ||
|
||
if (policydb_init(&kernpolicydb)) | ||
goto exit; | ||
|
||
if (link_modules(NULL, &parsepolicydb, NULL, 0, 0)) | ||
goto exit; | ||
|
||
if (expand_module(NULL, &parsepolicydb, &kernpolicydb, 0, 1)) | ||
goto exit; | ||
|
||
assert(kernpolicydb.policyvers == POLICYDB_VERSION_MAX); | ||
assert(kernpolicydb.policy_type == POLICY_KERN); | ||
assert(kernpolicydb.handle_unknown == SEPOL_DENY_UNKNOWN); | ||
assert(kernpolicydb.mls == 1); | ||
|
||
if (policydb_load_isids(&kernpolicydb, &sidtab)) | ||
goto exit; | ||
|
||
if (policydb_optimize(&kernpolicydb)) | ||
goto exit; | ||
|
||
if (policydb_sort_ocontexts(&kernpolicydb)) | ||
goto exit; | ||
|
||
devnull = fopen("/dev/null", "we"); | ||
if (devnull == NULL) | ||
goto exit; | ||
|
||
(void) write_binary_policy(&kernpolicydb, devnull); | ||
|
||
(void) sepol_kernel_policydb_to_conf(devnull, &kernpolicydb); | ||
|
||
(void) sepol_kernel_policydb_to_cil(devnull, &kernpolicydb); | ||
|
||
exit: | ||
if (devnull != NULL) | ||
fclose(devnull); | ||
|
||
sepol_sidtab_destroy(&sidtab); | ||
policydb_destroy(&kernpolicydb); | ||
policydb_destroy(&parsepolicydb); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Keyword dictionary | ||
|
||
"clone" | ||
"common" | ||
"class" | ||
"constrain" | ||
"validatetrans" | ||
"inherits" | ||
"sid" | ||
"role" | ||
"roles" | ||
"roleattribute" | ||
"attribute_role" | ||
"types" | ||
"typealias" | ||
"typeattribute" | ||
"typebounds" | ||
"type" | ||
"bool" | ||
"tunable" | ||
"if" | ||
"else" | ||
"alias" | ||
"attribute" | ||
"expandattribute" | ||
"type_transition" | ||
"type_member" | ||
"type_change" | ||
"role_transition" | ||
"range_transition" | ||
"sensitivity" | ||
"dominance" | ||
"category" | ||
"level" | ||
"range" | ||
"mlsconstrain" | ||
"mlsvalidatetrans" | ||
"user" | ||
"neverallow" | ||
"allow" | ||
"auditallow" | ||
"auditdeny" | ||
"dontaudit" | ||
"allowxperm" | ||
"auditallowxperm" | ||
"dontauditxperm" | ||
"neverallowxperm" | ||
"source" | ||
"target" | ||
"sameuser" | ||
"module" | ||
"require" | ||
"optional" | ||
"or" | ||
"and" | ||
"not" | ||
"xor" | ||
"eq" | ||
"true" | ||
"false" | ||
"dom" | ||
"domby" | ||
"incomp" | ||
"fscon" | ||
"ibpkeycon" | ||
"ibendportcon" | ||
"portcon" | ||
"netifcon" | ||
"nodecon" | ||
"pirqcon" | ||
"iomemcon" | ||
"ioportcon" | ||
"pcidevicecon" | ||
"devicetreecon" | ||
"fs_use_xattr" | ||
"fs_use_task" | ||
"fs_use_trans" | ||
"genfscon" | ||
"r1" | ||
"r2" | ||
"r3" | ||
"u1" | ||
"u2" | ||
"u3" | ||
"t1" | ||
"t2" | ||
"t3" | ||
"l1" | ||
"l2" | ||
"h1" | ||
"h2" | ||
"policycap" | ||
"permissive" | ||
"default_user" | ||
"default_role" | ||
"default_type" | ||
"default_range" | ||
"low-high" | ||
"high" | ||
"low" | ||
"glblub" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
class process | ||
class blk_file | ||
class chr_file | ||
class dir | ||
class fifo_file | ||
class file | ||
class lnk_file | ||
class sock_file | ||
sid kernel | ||
sid security | ||
sid unlabeled | ||
sid fs | ||
sid file | ||
sid file_labels | ||
sid init | ||
sid any_socket | ||
sid port | ||
sid netif | ||
sid netmsg | ||
sid node | ||
sid igmp_packet | ||
sid icmp_socket | ||
sid tcp_socket | ||
sid sysctl_modprobe | ||
sid sysctl | ||
sid sysctl_fs | ||
sid sysctl_kernel | ||
sid sysctl_net | ||
sid sysctl_net_unix | ||
sid sysctl_vm | ||
sid sysctl_dev | ||
sid kmod | ||
sid policy | ||
sid scmp_packet | ||
sid devnull | ||
class process { dyntransition transition } | ||
default_role { blk_file } source; | ||
default_role { chr_file } source; | ||
default_role { dir } source; | ||
default_role { fifo_file } source; | ||
default_role { file } source; | ||
default_role { lnk_file } source; | ||
default_role { sock_file } source; | ||
type sys_isid; | ||
typealias sys_isid alias { dpkg_script_t rpm_script_t }; | ||
allow sys_isid self : process { dyntransition transition }; | ||
role sys_role; | ||
role sys_role types { sys_isid }; | ||
user sys_user roles sys_role; | ||
sid kernel sys_user:sys_role:sys_isid | ||
sid security sys_user:sys_role:sys_isid | ||
sid unlabeled sys_user:sys_role:sys_isid | ||
sid file sys_user:sys_role:sys_isid | ||
sid port sys_user:sys_role:sys_isid | ||
sid netif sys_user:sys_role:sys_isid | ||
sid netmsg sys_user:sys_role:sys_isid | ||
sid node sys_user:sys_role:sys_isid | ||
sid devnull sys_user:sys_role:sys_isid | ||
fs_use_trans devpts sys_user:sys_role:sys_isid; | ||
fs_use_trans devtmpfs sys_user:sys_role:sys_isid; |
Oops, something went wrong.