16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Generalized labeling frontend for userspace object managers. 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil> 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <sys/types.h> 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <ctype.h> 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <errno.h> 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdio.h> 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdlib.h> 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <string.h> 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <selinux/selinux.h> 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "callbacks.h" 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "label_internal.h" 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef int (*selabel_initfunc)(struct selabel_handle *rec, 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const struct selinux_opt *opts, 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn unsigned nopts); 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic selabel_initfunc initfuncs[] = { 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &selabel_file_init, 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn NULL, 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn NULL, 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn NULL, 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &selabel_property_init, 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}; 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Validation functions 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline int selabel_is_validate_set(const struct selinux_opt *opts, 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn unsigned n) 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while (n--) 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (opts[n].type == SELABEL_OPT_VALIDATE) 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return !!opts[n].value; 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return 0; 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint selabel_validate(struct selabel_handle *rec, 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct selabel_lookup_rec *contexts) 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int rc = 0; 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (!rec->validating || contexts->validated) 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn goto out; 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rc = selinux_validate(&contexts->ctx_raw); 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (rc < 0) 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn goto out; 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn contexts->validated = 1; 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennout: 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return rc; 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Public API 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct selabel_handle *selabel_open(unsigned int backend, 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const struct selinux_opt *opts, 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn unsigned nopts) 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct selabel_handle *rec = NULL; 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (backend >= ARRAY_SIZE(initfuncs)) { 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn errno = EINVAL; 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn goto out; 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (initfuncs[backend] == NULL) 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn goto out; 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rec = (struct selabel_handle *)malloc(sizeof(*rec)); 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (!rec) 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn goto out; 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset(rec, 0, sizeof(*rec)); 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rec->backend = backend; 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rec->validating = selabel_is_validate_set(opts, nopts); 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if ((*initfuncs[backend])(rec, opts, nopts)) { 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free(rec); 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rec = NULL; 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennout: 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return rec; 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic struct selabel_lookup_rec * 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennselabel_lookup_common(struct selabel_handle *rec, 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const char *key, int type) 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct selabel_lookup_rec *lr; 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn lr = rec->func_lookup(rec, key, type); 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (!lr) 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return NULL; 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return lr; 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint selabel_lookup(struct selabel_handle *rec, char **con, 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const char *key, int type) 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct selabel_lookup_rec *lr; 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn lr = selabel_lookup_common(rec, key, type); 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (!lr) 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return -1; 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *con = strdup(lr->ctx_raw); 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return *con ? 0 : -1; 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool selabel_partial_match(struct selabel_handle *rec, const char *key) 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (!rec->func_partial_match) { 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * If the label backend does not support partial matching, 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * then assume a match is possible. 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return true; 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return rec->func_partial_match(rec, key); 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint selabel_lookup_best_match(struct selabel_handle *rec, char **con, 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const char *key, const char **aliases, int type) 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct selabel_lookup_rec *lr; 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (!rec->func_lookup_best_match) { 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn errno = ENOTSUP; 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return -1; 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn lr = rec->func_lookup_best_match(rec, key, aliases, type); 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (!lr) 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return -1; 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *con = strdup(lr->ctx_raw); 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return *con ? 0 : -1; 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid selabel_close(struct selabel_handle *rec) 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rec->func_close(rec); 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free(rec); 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid selabel_stats(struct selabel_handle *rec) 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rec->func_stats(rec); 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn