#include <netinet/in.h> #include <stdlib.h> #include "debug.h" #include "context.h" #include "handle.h" #include <sepol/policydb/policydb.h> #include "ibendport_internal.h" /* Create a low level ibendport structure from * a high level representation */ static int ibendport_from_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t **ibendport, const sepol_ibendport_t *data) { ocontext_t *tmp_ibendport = NULL; context_struct_t *tmp_con = NULL; char *ibdev_name = NULL; int port = sepol_ibendport_get_port(data); tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t)); if (!tmp_ibendport) goto omem; if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibendport->u.ibendport.dev_name) < 0) goto omem; if (sepol_ibendport_get_ibdev_name(handle, data, &ibdev_name) < 0) goto err; strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX); free(ibdev_name); ibdev_name = NULL; tmp_ibendport->u.ibendport.port = port; /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_ibendport_get_con(data)) < 0) goto err; context_cpy(&tmp_ibendport->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *ibendport = tmp_ibendport; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_ibendport) { context_destroy(&tmp_ibendport->context[0]); free(tmp_ibendport); } context_destroy(tmp_con); free(tmp_con); free(ibdev_name); ERR(handle, "could not create ibendport structure"); return STATUS_ERR; } static int ibendport_to_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t *ibendport, sepol_ibendport_t **record) { int port = ibendport->u.ibendport.port; context_struct_t *con = &ibendport->context[0]; sepol_context_t *tmp_con = NULL; sepol_ibendport_t *tmp_record = NULL; if (sepol_ibendport_create(handle, &tmp_record) < 0) goto err; if (sepol_ibendport_set_ibdev_name(handle, tmp_record, ibendport->u.ibendport.dev_name) < 0) goto err; sepol_ibendport_set_port(tmp_record, port); if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert ibendport to record"); sepol_context_free(tmp_con); sepol_ibendport_free(tmp_record); return STATUS_ERR; } /* Return the number of ibendports */ extern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a ibendport exists */ int sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, const sepol_ibendport_key_t *key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { const char *ibdev_name2 = c->u.ibendport.dev_name; int port2 = c->u.ibendport.port; if (port2 == port && (!strcmp(ibdev_name, ibdev_name2))) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; } int sepol_ibendport_query(sepol_handle_t *handle, const sepol_policydb_t *p, const sepol_ibendport_key_t *key, sepol_ibendport_t **response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { const char *ibdev_name2 = c->u.ibendport.dev_name; int port2 = c->u.ibendport.port; if (port2 == port && (!strcmp(ibdev_name, ibdev_name2))) { if (ibendport_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query ibendport, IB device: %s port %u", ibdev_name, port); return STATUS_ERR; } /* Load a ibendport into policy */ int sepol_ibendport_modify(sepol_handle_t *handle, sepol_policydb_t *p, const sepol_ibendport_key_t *key, const sepol_ibendport_t *data) { policydb_t *policydb = &p->p; ocontext_t *ibendport = NULL; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); if (ibendport_from_record(handle, policydb, &ibendport, data) < 0) goto err; /* Attach to context list */ ibendport->next = policydb->ocontexts[OCON_IBENDPORT]; policydb->ocontexts[OCON_IBENDPORT] = ibendport; return STATUS_SUCCESS; err: ERR(handle, "could not load ibendport %s/%d", ibdev_name, port); if (ibendport) { context_destroy(&ibendport->context[0]); free(ibendport); } return STATUS_ERR; } int sepol_ibendport_iterate(sepol_handle_t *handle, const sepol_policydb_t *p, int (*fn)(const sepol_ibendport_t *ibendport, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_ibendport_t *ibendport = NULL; head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { int status; if (ibendport_to_record(handle, policydb, c, &ibendport) < 0) goto err; /* Invoke handler */ status = fn(ibendport, arg); if (status < 0) goto err; sepol_ibendport_free(ibendport); ibendport = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over ibendports"); sepol_ibendport_free(ibendport); return STATUS_ERR; }