16cd6a6acSopenharmony_ci#include <stdlib.h> 26cd6a6acSopenharmony_ci 36cd6a6acSopenharmony_ci#include "debug.h" 46cd6a6acSopenharmony_ci#include "context.h" 56cd6a6acSopenharmony_ci#include "handle.h" 66cd6a6acSopenharmony_ci 76cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 86cd6a6acSopenharmony_ci#include <sepol/interfaces.h> 96cd6a6acSopenharmony_ci#include "iface_internal.h" 106cd6a6acSopenharmony_ci 116cd6a6acSopenharmony_ci/* Create a low level structure from record */ 126cd6a6acSopenharmony_cistatic int iface_from_record(sepol_handle_t * handle, 136cd6a6acSopenharmony_ci const policydb_t * policydb, 146cd6a6acSopenharmony_ci ocontext_t ** iface, const sepol_iface_t * record) 156cd6a6acSopenharmony_ci{ 166cd6a6acSopenharmony_ci 176cd6a6acSopenharmony_ci ocontext_t *tmp_iface = NULL; 186cd6a6acSopenharmony_ci context_struct_t *tmp_con = NULL; 196cd6a6acSopenharmony_ci 206cd6a6acSopenharmony_ci tmp_iface = (ocontext_t *) calloc(1, sizeof(ocontext_t)); 216cd6a6acSopenharmony_ci if (!tmp_iface) 226cd6a6acSopenharmony_ci goto omem; 236cd6a6acSopenharmony_ci 246cd6a6acSopenharmony_ci /* Name */ 256cd6a6acSopenharmony_ci tmp_iface->u.name = strdup(sepol_iface_get_name(record)); 266cd6a6acSopenharmony_ci if (!tmp_iface->u.name) 276cd6a6acSopenharmony_ci goto omem; 286cd6a6acSopenharmony_ci 296cd6a6acSopenharmony_ci /* Interface Context */ 306cd6a6acSopenharmony_ci if (context_from_record(handle, policydb, 316cd6a6acSopenharmony_ci &tmp_con, sepol_iface_get_ifcon(record)) < 0) 326cd6a6acSopenharmony_ci goto err; 336cd6a6acSopenharmony_ci context_cpy(&tmp_iface->context[0], tmp_con); 346cd6a6acSopenharmony_ci context_destroy(tmp_con); 356cd6a6acSopenharmony_ci free(tmp_con); 366cd6a6acSopenharmony_ci tmp_con = NULL; 376cd6a6acSopenharmony_ci 386cd6a6acSopenharmony_ci /* Message Context */ 396cd6a6acSopenharmony_ci if (context_from_record(handle, policydb, 406cd6a6acSopenharmony_ci &tmp_con, sepol_iface_get_msgcon(record)) < 0) 416cd6a6acSopenharmony_ci goto err; 426cd6a6acSopenharmony_ci context_cpy(&tmp_iface->context[1], tmp_con); 436cd6a6acSopenharmony_ci context_destroy(tmp_con); 446cd6a6acSopenharmony_ci free(tmp_con); 456cd6a6acSopenharmony_ci tmp_con = NULL; 466cd6a6acSopenharmony_ci 476cd6a6acSopenharmony_ci *iface = tmp_iface; 486cd6a6acSopenharmony_ci return STATUS_SUCCESS; 496cd6a6acSopenharmony_ci 506cd6a6acSopenharmony_ci omem: 516cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 526cd6a6acSopenharmony_ci 536cd6a6acSopenharmony_ci err: 546cd6a6acSopenharmony_ci if (tmp_iface != NULL) { 556cd6a6acSopenharmony_ci free(tmp_iface->u.name); 566cd6a6acSopenharmony_ci context_destroy(&tmp_iface->context[0]); 576cd6a6acSopenharmony_ci context_destroy(&tmp_iface->context[1]); 586cd6a6acSopenharmony_ci free(tmp_iface); 596cd6a6acSopenharmony_ci } 606cd6a6acSopenharmony_ci context_destroy(tmp_con); 616cd6a6acSopenharmony_ci free(tmp_con); 626cd6a6acSopenharmony_ci ERR(handle, "error creating interface structure"); 636cd6a6acSopenharmony_ci return STATUS_ERR; 646cd6a6acSopenharmony_ci} 656cd6a6acSopenharmony_ci 666cd6a6acSopenharmony_cistatic int iface_to_record(sepol_handle_t * handle, 676cd6a6acSopenharmony_ci const policydb_t * policydb, 686cd6a6acSopenharmony_ci ocontext_t * iface, sepol_iface_t ** record) 696cd6a6acSopenharmony_ci{ 706cd6a6acSopenharmony_ci 716cd6a6acSopenharmony_ci char *name = iface->u.name; 726cd6a6acSopenharmony_ci context_struct_t *ifcon = &iface->context[0]; 736cd6a6acSopenharmony_ci context_struct_t *msgcon = &iface->context[1]; 746cd6a6acSopenharmony_ci 756cd6a6acSopenharmony_ci sepol_context_t *tmp_con = NULL; 766cd6a6acSopenharmony_ci sepol_iface_t *tmp_record = NULL; 776cd6a6acSopenharmony_ci 786cd6a6acSopenharmony_ci if (sepol_iface_create(handle, &tmp_record) < 0) 796cd6a6acSopenharmony_ci goto err; 806cd6a6acSopenharmony_ci 816cd6a6acSopenharmony_ci if (sepol_iface_set_name(handle, tmp_record, name) < 0) 826cd6a6acSopenharmony_ci goto err; 836cd6a6acSopenharmony_ci 846cd6a6acSopenharmony_ci if (context_to_record(handle, policydb, ifcon, &tmp_con) < 0) 856cd6a6acSopenharmony_ci goto err; 866cd6a6acSopenharmony_ci if (sepol_iface_set_ifcon(handle, tmp_record, tmp_con) < 0) 876cd6a6acSopenharmony_ci goto err; 886cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 896cd6a6acSopenharmony_ci tmp_con = NULL; 906cd6a6acSopenharmony_ci 916cd6a6acSopenharmony_ci if (context_to_record(handle, policydb, msgcon, &tmp_con) < 0) 926cd6a6acSopenharmony_ci goto err; 936cd6a6acSopenharmony_ci if (sepol_iface_set_msgcon(handle, tmp_record, tmp_con) < 0) 946cd6a6acSopenharmony_ci goto err; 956cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 966cd6a6acSopenharmony_ci tmp_con = NULL; 976cd6a6acSopenharmony_ci 986cd6a6acSopenharmony_ci *record = tmp_record; 996cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1006cd6a6acSopenharmony_ci 1016cd6a6acSopenharmony_ci err: 1026cd6a6acSopenharmony_ci ERR(handle, "could not convert interface %s to record", name); 1036cd6a6acSopenharmony_ci sepol_context_free(tmp_con); 1046cd6a6acSopenharmony_ci sepol_iface_free(tmp_record); 1056cd6a6acSopenharmony_ci return STATUS_ERR; 1066cd6a6acSopenharmony_ci} 1076cd6a6acSopenharmony_ci 1086cd6a6acSopenharmony_ci/* Check if an interface exists */ 1096cd6a6acSopenharmony_ciint sepol_iface_exists(sepol_handle_t * handle __attribute__ ((unused)), 1106cd6a6acSopenharmony_ci const sepol_policydb_t * p, 1116cd6a6acSopenharmony_ci const sepol_iface_key_t * key, int *response) 1126cd6a6acSopenharmony_ci{ 1136cd6a6acSopenharmony_ci 1146cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1156cd6a6acSopenharmony_ci ocontext_t *c, *head; 1166cd6a6acSopenharmony_ci 1176cd6a6acSopenharmony_ci const char *name; 1186cd6a6acSopenharmony_ci sepol_iface_key_unpack(key, &name); 1196cd6a6acSopenharmony_ci 1206cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NETIF]; 1216cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 1226cd6a6acSopenharmony_ci if (!strcmp(name, c->u.name)) { 1236cd6a6acSopenharmony_ci *response = 1; 1246cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1256cd6a6acSopenharmony_ci } 1266cd6a6acSopenharmony_ci } 1276cd6a6acSopenharmony_ci *response = 0; 1286cd6a6acSopenharmony_ci 1296cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1306cd6a6acSopenharmony_ci} 1316cd6a6acSopenharmony_ci 1326cd6a6acSopenharmony_ci/* Query an interface */ 1336cd6a6acSopenharmony_ciint sepol_iface_query(sepol_handle_t * handle, 1346cd6a6acSopenharmony_ci const sepol_policydb_t * p, 1356cd6a6acSopenharmony_ci const sepol_iface_key_t * key, sepol_iface_t ** response) 1366cd6a6acSopenharmony_ci{ 1376cd6a6acSopenharmony_ci 1386cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 1396cd6a6acSopenharmony_ci ocontext_t *c, *head; 1406cd6a6acSopenharmony_ci 1416cd6a6acSopenharmony_ci const char *name; 1426cd6a6acSopenharmony_ci sepol_iface_key_unpack(key, &name); 1436cd6a6acSopenharmony_ci 1446cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NETIF]; 1456cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 1466cd6a6acSopenharmony_ci if (!strcmp(name, c->u.name)) { 1476cd6a6acSopenharmony_ci 1486cd6a6acSopenharmony_ci if (iface_to_record(handle, policydb, c, response) < 0) 1496cd6a6acSopenharmony_ci goto err; 1506cd6a6acSopenharmony_ci 1516cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1526cd6a6acSopenharmony_ci } 1536cd6a6acSopenharmony_ci } 1546cd6a6acSopenharmony_ci 1556cd6a6acSopenharmony_ci *response = NULL; 1566cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1576cd6a6acSopenharmony_ci 1586cd6a6acSopenharmony_ci err: 1596cd6a6acSopenharmony_ci ERR(handle, "could not query interface %s", name); 1606cd6a6acSopenharmony_ci return STATUS_ERR; 1616cd6a6acSopenharmony_ci} 1626cd6a6acSopenharmony_ci 1636cd6a6acSopenharmony_ci/* Load an interface into policy */ 1646cd6a6acSopenharmony_ciint sepol_iface_modify(sepol_handle_t * handle, 1656cd6a6acSopenharmony_ci sepol_policydb_t * p, 1666cd6a6acSopenharmony_ci const sepol_iface_key_t * key, 1676cd6a6acSopenharmony_ci const sepol_iface_t * data) 1686cd6a6acSopenharmony_ci{ 1696cd6a6acSopenharmony_ci 1706cd6a6acSopenharmony_ci policydb_t *policydb = &p->p; 1716cd6a6acSopenharmony_ci ocontext_t *head, *prev, *c, *iface = NULL; 1726cd6a6acSopenharmony_ci 1736cd6a6acSopenharmony_ci const char *name; 1746cd6a6acSopenharmony_ci sepol_iface_key_unpack(key, &name); 1756cd6a6acSopenharmony_ci 1766cd6a6acSopenharmony_ci if (iface_from_record(handle, policydb, &iface, data) < 0) 1776cd6a6acSopenharmony_ci goto err; 1786cd6a6acSopenharmony_ci 1796cd6a6acSopenharmony_ci prev = NULL; 1806cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NETIF]; 1816cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 1826cd6a6acSopenharmony_ci if (!strcmp(name, c->u.name)) { 1836cd6a6acSopenharmony_ci 1846cd6a6acSopenharmony_ci /* Replace */ 1856cd6a6acSopenharmony_ci iface->next = c->next; 1866cd6a6acSopenharmony_ci if (prev == NULL) 1876cd6a6acSopenharmony_ci policydb->ocontexts[OCON_NETIF] = iface; 1886cd6a6acSopenharmony_ci else 1896cd6a6acSopenharmony_ci prev->next = iface; 1906cd6a6acSopenharmony_ci free(c->u.name); 1916cd6a6acSopenharmony_ci context_destroy(&c->context[0]); 1926cd6a6acSopenharmony_ci context_destroy(&c->context[1]); 1936cd6a6acSopenharmony_ci free(c); 1946cd6a6acSopenharmony_ci 1956cd6a6acSopenharmony_ci return STATUS_SUCCESS; 1966cd6a6acSopenharmony_ci } 1976cd6a6acSopenharmony_ci prev = c; 1986cd6a6acSopenharmony_ci } 1996cd6a6acSopenharmony_ci 2006cd6a6acSopenharmony_ci /* Attach to context list */ 2016cd6a6acSopenharmony_ci iface->next = policydb->ocontexts[OCON_NETIF]; 2026cd6a6acSopenharmony_ci policydb->ocontexts[OCON_NETIF] = iface; 2036cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2046cd6a6acSopenharmony_ci 2056cd6a6acSopenharmony_ci err: 2066cd6a6acSopenharmony_ci ERR(handle, "error while loading interface %s", name); 2076cd6a6acSopenharmony_ci 2086cd6a6acSopenharmony_ci if (iface != NULL) { 2096cd6a6acSopenharmony_ci free(iface->u.name); 2106cd6a6acSopenharmony_ci context_destroy(&iface->context[0]); 2116cd6a6acSopenharmony_ci context_destroy(&iface->context[1]); 2126cd6a6acSopenharmony_ci free(iface); 2136cd6a6acSopenharmony_ci } 2146cd6a6acSopenharmony_ci return STATUS_ERR; 2156cd6a6acSopenharmony_ci} 2166cd6a6acSopenharmony_ci 2176cd6a6acSopenharmony_ci/* Return the number of interfaces */ 2186cd6a6acSopenharmony_ciextern int sepol_iface_count(sepol_handle_t * handle __attribute__ ((unused)), 2196cd6a6acSopenharmony_ci const sepol_policydb_t * p, unsigned int *response) 2206cd6a6acSopenharmony_ci{ 2216cd6a6acSopenharmony_ci 2226cd6a6acSopenharmony_ci unsigned int count = 0; 2236cd6a6acSopenharmony_ci ocontext_t *c, *head; 2246cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 2256cd6a6acSopenharmony_ci 2266cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NETIF]; 2276cd6a6acSopenharmony_ci for (c = head; c != NULL; c = c->next) 2286cd6a6acSopenharmony_ci count++; 2296cd6a6acSopenharmony_ci 2306cd6a6acSopenharmony_ci *response = count; 2316cd6a6acSopenharmony_ci 2326cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2336cd6a6acSopenharmony_ci} 2346cd6a6acSopenharmony_ci 2356cd6a6acSopenharmony_ciint sepol_iface_iterate(sepol_handle_t * handle, 2366cd6a6acSopenharmony_ci const sepol_policydb_t * p, 2376cd6a6acSopenharmony_ci int (*fn) (const sepol_iface_t * iface, 2386cd6a6acSopenharmony_ci void *fn_arg), void *arg) 2396cd6a6acSopenharmony_ci{ 2406cd6a6acSopenharmony_ci 2416cd6a6acSopenharmony_ci const policydb_t *policydb = &p->p; 2426cd6a6acSopenharmony_ci ocontext_t *c, *head; 2436cd6a6acSopenharmony_ci sepol_iface_t *iface = NULL; 2446cd6a6acSopenharmony_ci 2456cd6a6acSopenharmony_ci head = policydb->ocontexts[OCON_NETIF]; 2466cd6a6acSopenharmony_ci for (c = head; c; c = c->next) { 2476cd6a6acSopenharmony_ci int status; 2486cd6a6acSopenharmony_ci 2496cd6a6acSopenharmony_ci if (iface_to_record(handle, policydb, c, &iface) < 0) 2506cd6a6acSopenharmony_ci goto err; 2516cd6a6acSopenharmony_ci 2526cd6a6acSopenharmony_ci /* Invoke handler */ 2536cd6a6acSopenharmony_ci status = fn(iface, arg); 2546cd6a6acSopenharmony_ci if (status < 0) 2556cd6a6acSopenharmony_ci goto err; 2566cd6a6acSopenharmony_ci 2576cd6a6acSopenharmony_ci sepol_iface_free(iface); 2586cd6a6acSopenharmony_ci iface = NULL; 2596cd6a6acSopenharmony_ci 2606cd6a6acSopenharmony_ci /* Handler requested exit */ 2616cd6a6acSopenharmony_ci if (status > 0) 2626cd6a6acSopenharmony_ci break; 2636cd6a6acSopenharmony_ci } 2646cd6a6acSopenharmony_ci 2656cd6a6acSopenharmony_ci return STATUS_SUCCESS; 2666cd6a6acSopenharmony_ci 2676cd6a6acSopenharmony_ci err: 2686cd6a6acSopenharmony_ci ERR(handle, "could not iterate over interfaces"); 2696cd6a6acSopenharmony_ci sepol_iface_free(iface); 2706cd6a6acSopenharmony_ci return STATUS_ERR; 2716cd6a6acSopenharmony_ci} 272