diff --git a/libqpol/config.h b/libqpol/config.h index 9ecae71..f4f216d 100644 --- a/libqpol/config.h +++ b/libqpol/config.h @@ -61,6 +61,14 @@ /* if users and roles are mapped during policy expansion */ #define HAVE_SEPOL_USER_ROLE_MAPPING 1 +/* if source policy Xen devicetreecon and iomemcon 64bit are present */ +#define HAVE_SEPOL_XEN_DEVICETREE 1 +/* OR */ +/* #undef HAVE_SEPOL_XEN_DEVICETREE */ + +/* if source policy ioctl white listing */ +#define HAVE_SEPOL_XPERM_IOCTL 1 + /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 diff --git a/libqpol/include/qpol/policy.h b/libqpol/include/qpol/policy.h index fcbb837..ec5dca1 100644 --- a/libqpol/include/qpol/policy.h +++ b/libqpol/include/qpol/policy.h @@ -63,6 +63,8 @@ extern "C" #include #include #include +#include +#include typedef void (__attribute__ ((format(printf, 4, 0))) *qpol_callback_fn_t) (void *varg, const struct qpol_policy * policy, int level, @@ -131,7 +133,9 @@ extern "C" /** The policy supports filename type_transition rules. */ QPOL_CAP_FILENAME_TRANS, /** The policy supports role transition rules. */ - QPOL_CAP_ROLETRANS + QPOL_CAP_ROLETRANS, + /** The policy supports ioctl extended permissions. */ + QPOL_CAP_XPERM_IOCTL } qpol_capability_e; /** @@ -278,6 +282,16 @@ extern "C" */ extern int qpol_policy_get_policy_handle_unknown(const qpol_policy_t * policy, unsigned int *handle_unknown); +/** + * Get target platform (SELinux or XEN) of the policy. + * @param policy The policy for which to get the target. + * @param target_platform Pointer to the target. + * @return Returns 0 on success and < 0 on failure; if the call fails, + * errno will be set and *target_platform will be 0. + */ + extern int qpol_policy_get_target_platform(const qpol_policy_t *policy, + int *target_platform); + #ifdef __cplusplus } #endif diff --git a/libqpol/include/qpol/xen_query.h b/libqpol/include/qpol/xen_query.h new file mode 100644 index 0000000..1bbf01c --- /dev/null +++ b/libqpol/include/qpol/xen_query.h @@ -0,0 +1,307 @@ +/** + * @file + * Defines the public interface for searching and iterating over + * Xen statements. + * + * @author Richard Haines richard_c_haines@btinternet.com + * Derived from portcon_query.h + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#ifndef QPOL_XEN_QUERY_H +#define QPOL_XEN_QUERY_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include +#include + + typedef struct qpol_iomemcon qpol_iomemcon_t; + typedef struct qpol_ioportcon qpol_ioportcon_t; + typedef struct qpol_pcidevicecon qpol_pcidevicecon_t; + typedef struct qpol_pirqcon qpol_pirqcon_t; + typedef struct qpol_devicetreecon qpol_devicetreecon_t; + +/******************************* iomemcon **************************/ +/** + * Get a single iomemcon statement by range. + * @param policy The policy from which to get the iomemcon statement. + * @param low The low addr of the range of addrs (or single addr). + * @param high The high addr of the range of addrs; if searching for a + * single addr, set high equal to low. + * @param ocon Pointer in which to store the statement returned. + * The caller should not free this pointer. + * @return 0 on success and < 0 on failure; if the call fails, + * errno will be set and *ocon will be NULL. + */ + extern int qpol_policy_get_iomemcon_by_addr( + const qpol_policy_t *policy, + uint64_t low, uint64_t high, + const qpol_iomemcon_t **ocon); + +/** + * Get an iterator for the iomemcon statements in a policy. + * @param policy The policy from which to create the iterator. + * @param iter Iterator over items of type qpol_iomemcon_t returned. + * The caller is responsible for calling qpol_iterator_destroy + * to free memory used by this iterator. + * It is important to note that this iterator is only valid as long + * as the policy is unmodified. + * @return 0 on success and < 0 on failure; if the call fails, + * errno will be set and *iter will be NULL. + */ + extern int qpol_policy_get_iomemcon_iter(const qpol_policy_t *policy, + qpol_iterator_t **iter); + +/** + * Get the low addr from a iomemcon statement. + * @param policy the policy associated with the iomemcon statement. + * @param ocon The iomemcon statement from which to get the low addr. + * @param addr Pointer to set to the addr. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *addr will be 0. + */ + extern int qpol_iomemcon_get_low_addr(const qpol_policy_t *policy, + const qpol_iomemcon_t *ocon, + uint64_t *addr); + +/** + * Get the high addr from a iomemcon statement. + * @param policy the policy associated with the iomemcon statement. + * @param ocon The iomemcon statement from which to get the high addr. + * @param addr Pointer to set to the addr. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *addr will be 0. + */ + extern int qpol_iomemcon_get_high_addr(const qpol_policy_t *policy, + const qpol_iomemcon_t *ocon, + uint64_t *addr); + +/** + * Get the context from a iomemcon statement. + * @param policy the policy associated with the iomemcon statement. + * @param ocon The iomemcon statement from which to get the context. + * @param context Pointer in which to store the context. + * The caller should not free this pointer. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *context will be NULL. + */ + extern int qpol_iomemcon_get_context(const qpol_policy_t *policy, + const qpol_iomemcon_t *ocon, + const qpol_context_t **context); + +/******************************* ioportcon **************************/ +/** + * Get a single ioportcon statement by range. + * @param policy The policy from which to get the ioportcon statement. + * @param low The low port of the range of ports (or single port). + * @param high The high port of the range of ports; if searching for a + * single port, set high equal to low. + * @param ocon Pointer in which to store the statement returned. + * The caller should not free this pointer. + * @return 0 on success and < 0 on failure; if the call fails, + * errno will be set and *ocon will be NULL. + */ + extern int qpol_policy_get_ioportcon_by_port( + const qpol_policy_t *policy, + uint32_t low, uint32_t high, + const qpol_ioportcon_t **ocon); + +/** + * Get an iterator for the ioportcon statements in a policy. + * @param policy The policy from which to create the iterator. + * @param iter Iterator over items of type qpol_ioportcon_t returned. + * The caller is responsible for calling qpol_iterator_destroy + * to free memory used by this iterator. + * It is important to note that this iterator is only valid as long + * as the policy is unmodified. + * @return 0 on success and < 0 on failure; if the call fails, + * errno will be set and *iter will be NULL. + */ + extern int qpol_policy_get_ioportcon_iter(const qpol_policy_t *policy, + qpol_iterator_t **iter); + +/** + * Get the low port from a ioportcon statement. + * @param policy the policy associated with the ioportcon statement. + * @param ocon The ioportcon statement from which to get the low port. + * @param port Pointer to set to the port. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *port will be 0. + */ + extern int qpol_ioportcon_get_low_port(const qpol_policy_t *policy, + const qpol_ioportcon_t *ocon, + uint32_t *port); + +/** + * Get the high port from a ioportcon statement. + * @param policy the policy associated with the ioportcon statement. + * @param ocon The ioportcon statement from which to get the high port. + * @param port Pointer to set to the port. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *port will be 0.32 + */ + extern int qpol_ioportcon_get_high_port(const qpol_policy_t *policy, + const qpol_ioportcon_t *ocon, + uint32_t *port); + +/** + * Get the context from a ioportcon statement. + * @param policy the policy associated with the ioportcon statement. + * @param ocon The ioportcon statement from which to get the context. + * @param context Pointer in which to store the context. + * The caller should not free this pointer. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *context will be NULL. + */ + extern int qpol_ioportcon_get_context(const qpol_policy_t *policy, + const qpol_ioportcon_t *ocon, + const qpol_context_t **context); + + + +/******************************* pcidevicecon **************************/ +/** + * Get an iterator for the pcidevicecon statements in a policy. + * @param policy The policy from which to create the iterator. + * @param iter Iterator over items of type qpol_pcidevicecon_t returned. + * The caller is responsible for calling qpol_iterator_destroy + * to free memory used by this iterator. + * It is important to note that this iterator is only valid as long + * as the policy is unmodified. + * @return 0 on success and < 0 on failure; if the call fails, + * errno will be set and *iter will be NULL. + */ + extern int qpol_policy_get_pcidevicecon_iter( + const qpol_policy_t *policy, + qpol_iterator_t **iter); + +/** + * Get the device id from a pcidevicecon statement. + * @param policy the policy associated with the pcidevicecon statement. + * @param ocon The pcidevicecon statement from which to get the low addr. + * @param device Pointer to set to the device. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *device will be 0. + */ + extern int qpol_pcidevicecon_get_device(const qpol_policy_t *policy, + const qpol_pcidevicecon_t *ocon, + uint32_t *device); + + +/** + * Get the context from a pcidevicecon statement. + * @param policy the policy associated with the pcidevicecon statement. + * @param ocon The pcidevicecon statement from which to get the context. + * @param context Pointer in which to store the context. + * The caller should not free this pointer. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *context will be NULL. + */ + extern int qpol_pcidevicecon_get_context(const qpol_policy_t *policy, + const qpol_pcidevicecon_t *ocon, + const qpol_context_t **context); + +/************************* pirqcon *******************************/ + +/** + * Get an iterator for the pirqcon statements in a policy. + * @param policy The policy from which to create the iterator. + * @param iter Iterator over items of type qpol_pirqcon_t returned. + * The caller is responsible for calling qpol_iterator_destroy + * to free memory used by this iterator. + * It is important to note that this iterator is only valid as long + * as the policy is unmodified. + * @return 0 on success and < 0 on failure; if the call fails, + * errno will be set and *iter will be NULL. + */ + extern int qpol_policy_get_pirqcon_iter(const qpol_policy_t *policy, + qpol_iterator_t **iter); + +/** + * Get the irq id from a pirqcon statement. + * @param policy the policy associated with the pirqcon statement. + * @param ocon The pirqcon statement from which to get the irq. + * @param irq Pointer to set to the irq. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *irq will be 0. + */ + extern int qpol_pirqcon_get_irq(const qpol_policy_t *policy, + const qpol_pirqcon_t *ocon, + uint16_t *irq); + + +/** + * Get the context from a pirqcon statement. + * @param policy the policy associated with the pirqcon statement. + * @param ocon The pirqcon statement from which to get the context. + * @param context Pointer in which to store the context. + * The caller should not free this pointer. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *context will be NULL. + */ + extern int qpol_pirqcon_get_context(const qpol_policy_t *policy, + const qpol_pirqcon_t *ocon, + const qpol_context_t **context); + +/************************* devicetreecon *******************************/ + +/** + * Get an iterator for the devicetreecon statements in a policy. + * @param policy The policy from which to create the iterator. + * @param iter Iterator over items of type qpol_devicetreecon returned. + * The caller is responsible for calling qpol_iterator_destroy + * to free memory used by this iterator. + * It is important to note that this iterator is only valid as long + * as the policy is unmodified. + * @return 0 on success and < 0 on failure; if the call fails, + * errno will be set and *iter will be NULL. + */ + extern int qpol_policy_get_devicetreecon_iter( + const qpol_policy_t *policy, + qpol_iterator_t **iter); + +/** + * Get the path from a devicetreecon statement. + * @param policy the policy associated with the devicetreecon statement. + * @param ocon The devicetreecon statement from which to get the path. + * @param path Pointer to set to the path. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *path will be 0. + */ + extern int qpol_devicetreecon_get_path(const qpol_policy_t *policy, + const qpol_devicetreecon_t *ocon, + char **path); + + +/** + * Get the context from a devicetreecon statement. + * @param policy the policy associated with the devicetreecon statement. + * @param ocon The devicetreecon statement from which to get the context. + * @param context Pointer in which to store the context. + * The caller should not free this pointer. + * @return 0 on success < 0 on failure; if the call fails, + * errno will be set and *context will be NULL. + */ + extern int qpol_devicetreecon_get_context(const qpol_policy_t *policy, + const qpol_devicetreecon_t *ocon, + const qpol_context_t **context); +#ifdef __cplusplus +} +#endif + +#endif /* QPOL_XEN_QUERY_H */ diff --git a/libqpol/include/qpol/xprule_query.h b/libqpol/include/qpol/xprule_query.h new file mode 100644 index 0000000..b874408 --- /dev/null +++ b/libqpol/include/qpol/xprule_query.h @@ -0,0 +1,139 @@ + /** + * @file + * Defines the public interface for searching and iterating over xperm rules. + * + * @author Richard Haines richard_c_haines@btinternet.com + * Derived from avrule_query.h + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#ifndef QPOL_XPRULE_QUERY_H +#define QPOL_XPRULE_QUERY_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + + typedef struct qpol_xprule qpol_xprule_t; + +/* rule type defines (values copied from "sepol/policydb/policydb.h") */ +#define QPOL_RULE_ALLOWXPERM 0x0100 +#define QPOL_RULE_AUDITALLOWXPERM 0x0200 +#define QPOL_RULE_DONTAUDITXPERM 0x0400 +#define QPOL_RULE_NEVERALLOWXPERM 0x0800 + +/** + * Get an iterator over all xperm rules in a policy of a rule type in + * rule_type_mask. It is an error to call this function if rules are + * not loaded. Likewise, it is an error if neverallows are requested + * but they were not loaded. + * @param policy Policy from which to get the av rules. + * @param rule_type_mask Bitwise or'ed set of QPOL_RULE_* values. + * @param iter Iterator over items of type qpol_xprule_t returned. + * The caller is responsible for calling qpol_iterator_destroy() + * to free memory used by this iterator. + * It is important to note that this iterator is only valid as long as + * the policy is unmodifed. + * @returm 0 on success and < 0 on failure; if the call fails, + * errno will be set and *iter will be NULL. + */ + extern int qpol_policy_get_xprule_iter(const qpol_policy_t *policy, + uint32_t rule_type_mask, qpol_iterator_t **iter); + +/** + * Get the source type from an xperm rule. + * @param policy Policy from which the rule comes. + * @param rule The rule from which to get the source type. + * @param source Pointer in which to store the source type. + * The caller should not free this pointer. + * @returm 0 on success and < 0 on failure; if the call fails, + * errno will be set and *source will be NULL. + */ + extern int qpol_xprule_get_source_type(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + const qpol_type_t **source); + +/** + * Get the target type from an xperm rule. + * @param policy Policy from which the rule comes. + * @param rule The rule from which to get the target type. + * @param target Pointer in which to store the target type. + * The caller should not free this pointer. + * @returm 0 on success and < 0 on failure; if the call fails, + * errno will be set and *target will be NULL. + */ + extern int qpol_xprule_get_target_type(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + const qpol_type_t **target); + +/** + * Get the object class from an xperm rule. + * @param policy Policy from which the rule comes. + * @param rule The rule from which to get the object class. + * @param obj_class Pointer in which to store the object class. + * The caller should not free this pointer. + * @returm 0 on success and < 0 on failure; if the call fails, + * errno will be set and *obj_class will be NULL. + */ + extern int qpol_xprule_get_object_class(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + const qpol_class_t **obj_class); + +/** + * Get the extended permissions command from an xperm rule. + * @param policy Policy from which the rule comes. + * @param rule The rule from which to get the permissions. + * @param xprule command Pointer to set to the string. + * @returm 0 on success and < 0 on failure; if the call fails, + * errno will be set and *perms will be NULL. + */ + extern int qpol_xprule_get_command(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + const char **xperm_command); + + +/** + * Get the extended IOCTL permissions from an xperm rule using + * sepol_extended_perms_to_string(). + * @param policy Policy from which the rule comes. + * @param rule The rule from which to get the permissions. + * @param xperm_string Pointer to set to the string. + * @returm 0 on success and < 0 on failure; if the call fails, + * errno will be set and *perms will be NULL. + */ + extern int qpol_xprule_get_xperm_string(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + char **xperm_string); + +/** + * Get the rule type value for an xperm rule. + * @param policy Policy from which the rule comes. + * @param rule The rule from which to get the rule type. + * @param rule_type Integer in which to store the rule type value. + * The value will be one of the QPOL_RULE_* values above. + * @returm 0 on success and < 0 on failure; if the call fails, + * errno will be set and *rule_type will be 0. + */ + extern int qpol_xprule_get_rule_type(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + uint32_t *rule_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libqpol/libqpol.map b/libqpol/libqpol.map index e896650..c840960 100644 --- a/libqpol/libqpol.map +++ b/libqpol/libqpol.map @@ -76,6 +76,12 @@ VERS_1.5 { qpol_policy_polcap_*; qpol_polcap_*; qpol_default_object_*; + qpol_iomemcon_*; + qpol_ioportcon_*; + qpol_pcidevicecon_*; + qpol_pirqcon_*; + qpol_devicetreecon_*; + qpol_xperm_*; init_qpol; PyInit__qpol; } VERS_1.4; diff --git a/libqpol/module_compiler.c b/libqpol/module_compiler.c index e59c689..63132de 100644 --- a/libqpol/module_compiler.c +++ b/libqpol/module_compiler.c @@ -1,9 +1,8 @@ -/** - * @file - * - * This file is a copy of module_compiler.c from NSA's CVS repository. - * - * Author : Joshua Brindle +/* This file is a copy of module_compiler.c from checkpolicy 2.4 to support + * SETools. + */ + +/* Author : Joshua Brindle * Karl MacMillan * Jason Tang * Added support for binary policy modules @@ -308,7 +307,7 @@ role_datum_t *declare_role(unsigned char isattr) return dest_role; /* role already declared for this block */ } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -371,7 +370,7 @@ type_datum_t *declare_type(unsigned char primary, unsigned char isattr) return typdatum; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -507,7 +506,7 @@ user_datum_t *declare_user(void) return dest_user; /* user already declared for this block */ } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -812,7 +811,7 @@ int require_class(int pass) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } @@ -925,7 +924,7 @@ static int require_role_or_attribute(int pass, unsigned char isattr) return 0; /* role already required */ } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -988,7 +987,7 @@ static int require_type_or_attribute(int pass, unsigned char isattr) return 0; /* type already required */ } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -1049,7 +1048,7 @@ int require_user(int pass) return 0; /* user already required */ } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -1100,7 +1099,7 @@ static int require_bool_tunable(int pass, int is_tunable) return 0; /* boolean already required */ } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -1173,7 +1172,7 @@ int require_sens(int pass) return 0; /* sensitivity already required */ } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -1226,7 +1225,7 @@ int require_cat(int pass) return 0; /* category already required */ } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -1253,11 +1252,11 @@ static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack) return is_scope_in_stack(scope, stack->parent); } -int is_id_in_scope(uint32_t symbol_type, const char *id) +int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id) { scope_datum_t *scope = (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type]. - table, (hashtab_key_t)id); + table, id); if (scope == NULL) { return 1; /* id is not known, so return success */ } @@ -1300,17 +1299,17 @@ static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value, return is_perm_in_stack(perm_value, class_value, stack->parent); } -int is_perm_in_scope(hashtab_key_t perm_id, const char *class_id) +int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id) { class_datum_t *cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, - (hashtab_key_t)class_id); + class_id); perm_datum_t *perdatum; if (cladatum == NULL) { return 1; } perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table, - (hashtab_key_t)perm_id); + perm_id); if (perdatum == NULL) { return 1; } @@ -1588,7 +1587,7 @@ static int push_stack(int stack_type, ...) } default: /* invalid stack type given */ - abort(); + assert(0); } va_end(ap); s->parent = stack_top; diff --git a/libqpol/module_compiler.h b/libqpol/module_compiler.h index 4620212..30ec362 100644 --- a/libqpol/module_compiler.h +++ b/libqpol/module_compiler.h @@ -1,9 +1,8 @@ -/** - * @file - * - * This file is a copy of module_compiler.h from NSA's CVS repository. - * - * Author : Joshua Brindle +/* This file is a copy of module_compiler.h from checkpolicy 2.4 to support + * SETools. + */ + +/* Author : Joshua Brindle * Karl MacMillan * Jason Tang * Added support for binary policy modules @@ -12,6 +11,7 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. + * */ #ifndef MODULE_COMPILER_H @@ -76,12 +76,12 @@ int require_cat(int pass); /* Check if an identifier is within the scope of the current * declaration or any of its parents. Return 1 if it is, 0 if not. * If the identifier is not known at all then return 1 (truth). */ -int is_id_in_scope(uint32_t symbol_type, const char * id); +int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id); /* Check if a particular permission is within the scope of the current * declaration or any of its parents. Return 1 if it is, 0 if not. * If the identifier is not known at all then return 1 (truth). */ -int is_perm_in_scope(hashtab_key_t perm_id, const char * class_id); +int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id); /* Search the current avrules block for a conditional with the same * expression as 'cond'. If the conditional does not exist then @@ -117,6 +117,7 @@ int begin_optional_else(int pass); * return -1. */ int end_avrule_block(int pass); +/* Required for SETools libqpol services */ #ifdef __cplusplus } #endif diff --git a/libqpol/policy.c b/libqpol/policy.c index 364c6c4..02a2a7a 100644 --- a/libqpol/policy.c +++ b/libqpol/policy.c @@ -73,6 +73,7 @@ extern unsigned long policydb_lineno; extern char source_file[]; extern policydb_t *policydbp; extern int mlspol; +extern int xenpol; #if __BYTE_ORDER == __LITTLE_ENDIAN #define cpu_to_le16(x) (x) @@ -189,6 +190,7 @@ static int read_source_policy(qpol_policy_t * qpolicy, const char *progname, int policydbp = &qpolicy->p->p; mlspol = policydbp->mls; + xenpol = policydbp->target_platform; INFO(qpolicy, "%s", "Parsing policy. (Step 1 of 5)"); init_scanner(); @@ -416,8 +418,14 @@ static int infer_policy_version(qpol_policy_t * policy) } qpol_iterator_destroy(&iter); -/* Check each version change from 29 to 24 */ -/* If this is available then just set version 29 */ +/* Check each version change from 30 to 24 */ +/* If these are available set version 30 */ +#if defined(HAVE_SEPOL_XPERM_IOCTL) || defined(HAVE_SEPOL_XEN_DEVICETREE) + db->policyvers = 30; + return STATUS_SUCCESS; +#endif + +/* If this is available then set version 29 */ #ifdef HAVE_SEPOL_CONSTRAINT_NAMES db->policyvers = 29; return STATUS_SUCCESS; @@ -1530,6 +1538,27 @@ int qpol_policy_get_policy_handle_unknown(const qpol_policy_t * policy, unsigned return STATUS_SUCCESS; } +int qpol_policy_get_target_platform(const qpol_policy_t *policy, + int *target_platform) +{ + policydb_t *db; + + if (target_platform != NULL) + *target_platform = 0; + + if (policy == NULL || target_platform == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + + *target_platform = db->target_platform; + + return STATUS_SUCCESS; +} + int qpol_policy_get_type(const qpol_policy_t * policy, int *type) { if (!policy || !type) { @@ -1647,6 +1676,14 @@ int qpol_policy_has_capability(const qpol_policy_t * policy, qpol_capability_e c return 1; break; } + case QPOL_CAP_XPERM_IOCTL: + { + if (version >= 30 && policy->type != QPOL_POLICY_MODULE_BINARY) + return 1; + if (version >= 17 && policy->type == QPOL_POLICY_MODULE_BINARY) + return 1; + break; + } case QPOL_CAP_RULES_LOADED: { if (!(policy->options & QPOL_POLICY_OPTION_NO_RULES)) diff --git a/libqpol/policy_define.c b/libqpol/policy_define.c index af5a6e6..82d604c 100644 --- a/libqpol/policy_define.c +++ b/libqpol/policy_define.c @@ -1,10 +1,6 @@ -/** - * @file policy_define.c - * - * This file is based upon checkpolicy/policy_define.c from NSA's SVN - * repository. It has been modified to support older policy formats. - * The older format just seems to be PSID support (see - * int define_fs_use(int behavior). +/* + * This file is a copy of policy_define.c from checkpolicy 2.4 updated to + * support SETools. */ /* @@ -49,6 +45,8 @@ #include #include #include +#include +#include #include #include @@ -56,11 +54,9 @@ #include #include #include -/* Required for SETools libqpol */ #include -#include - #include "queue.h" + /* Required for SETools libqpol - Removed #include "checkpolicy.h"*/ #include @@ -72,10 +68,13 @@ queue_t id_queue = 0; unsigned int pass; char *curfile = 0; int mlspol = 0; +/* Required for SETools libqpol */ +int xenpol = 0; extern unsigned long policydb_lineno; extern unsigned long source_lineno; extern unsigned int policydb_errors; +extern char source_file[PATH_MAX]; extern int yywarn(const char *msg); extern int yyerror(const char *msg); @@ -83,7 +82,7 @@ extern int yyerror(const char *msg); #define ERRORMSG_LEN 255 static char errormsg[ERRORMSG_LEN + 1] = {0}; -static int id_has_dot(const char *id); +static int id_has_dot(char *id); static int parse_security_context(context_struct_t *c); /* initialize all of the state variables for the scanner/parser */ @@ -113,6 +112,14 @@ int define_mls(void) return 0; } +/* Required for SETools libqpol */ +int define_xen(void) +{ + xenpol = 1; + policydbp->target_platform = 1; + + return 0; +} int insert_separator(int push) { @@ -156,7 +163,7 @@ int insert_id(const char *id, int push) /* If the identifier has a dot within it and that its first character is not a dot then return 1, else return 0. */ -static int id_has_dot(const char *id) +static int id_has_dot(char *id) { if (strchr(id, '.') >= id + 1) { return 1; @@ -207,7 +214,7 @@ int define_class(void) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } datum->s.value = value; @@ -781,7 +788,7 @@ int define_sens(void) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } @@ -820,7 +827,7 @@ int define_sens(void) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -950,7 +957,7 @@ int define_category(void) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } datum->s.value = value; @@ -992,7 +999,7 @@ int define_category(void) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -1209,7 +1216,7 @@ static int add_aliases_to_type(type_datum_t * type) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } } @@ -1288,7 +1295,8 @@ int define_typeattribute(void) free(id); return -1; } - attr = hashtab_search(policydbp->p_types.table, id); + attr = hashtab_search(policydbp->p_types.table, + (hashtab_key_t)id); /* SETools */ if (!attr) { /* treat it as a fatal error */ yyerror2("attribute %s is not declared", id); @@ -1316,7 +1324,8 @@ int define_typeattribute(void) return 0; } -static int define_typebounds_helper(const char *bounds_id, const char *type_id) + /* SETools */ +static int define_typebounds_helper(char *bounds_id, hashtab_key_t type_id) { type_datum_t *bounds, *type; @@ -1325,7 +1334,8 @@ static int define_typebounds_helper(const char *bounds_id, const char *type_id) return -1; } - bounds = hashtab_search(policydbp->p_types.table, (hashtab_key_t)bounds_id); + bounds = hashtab_search(policydbp->p_types.table, + (hashtab_key_t)bounds_id); /* SETools */ if (!bounds || bounds->flavor == TYPE_ATTRIB) { yyerror2("hoge unknown type %s", bounds_id); return -1; @@ -1336,7 +1346,8 @@ static int define_typebounds_helper(const char *bounds_id, const char *type_id) return -1; } - type = hashtab_search(policydbp->p_types.table, (hashtab_key_t)type_id); + type = hashtab_search(policydbp->p_types.table, + (hashtab_key_t)type_id); /* SETools */ if (!type || type->flavor == TYPE_ATTRIB) { yyerror2("type %s is not declared", type_id); return -1; @@ -1438,7 +1449,8 @@ int define_type(int alias) free(id); return -1; } - attr = hashtab_search(policydbp->p_types.table, (hashtab_key_t)id); + attr = hashtab_search(policydbp->p_types.table, + (hashtab_key_t)id); /* SETools */ if (!attr) { /* treat it as a fatal error */ yyerror2("attribute %s is not declared", id); @@ -1511,7 +1523,8 @@ static int set_types(type_set_t * set, char *id, int *add, char starallowed) free(id); return -1; } - t = hashtab_search(policydbp->p_types.table, (hashtab_key_t)id); + t = hashtab_search(policydbp->p_types.table, + (hashtab_key_t)id); /* SETools */ if (!t) { yyerror2("unknown type %s", id); free(id); @@ -1542,8 +1555,7 @@ int define_compute_type_helper(int which, avrule_t ** rule) ebitmap_node_t *node; avrule_t *avrule; class_perm_node_t *perm; - unsigned int i; - int add = 1; + int i, add = 1; avrule = malloc(sizeof(avrule_t)); if (!avrule) { @@ -1553,6 +1565,12 @@ int define_compute_type_helper(int which, avrule_t ** rule) avrule_init(avrule); avrule->specified = which; avrule->line = policydb_lineno; + avrule->source_line = source_lineno; + avrule->source_filename = strdup(source_file); + if (!avrule->source_filename) { + yyerror("out of memory"); + return -1; + } while ((id = queue_remove(id_queue))) { if (set_types(&avrule->stypes, id, &add, 0)) @@ -1632,7 +1650,7 @@ int define_compute_type(int which) append_avrule(avrule); return 0; - } +} avrule_t *define_cond_compute_type(int which) { @@ -1708,7 +1726,7 @@ int define_bool_tunable(int is_tunable) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } datum->s.value = value; @@ -1744,6 +1762,681 @@ avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl) return sl; } +/* START XPERM */ +typedef struct av_ioctl_range { + uint16_t low; + uint16_t high; +} av_ioctl_range_t; + +struct av_ioctl_range_list { + uint8_t omit; + av_ioctl_range_t range; + struct av_ioctl_range_list *next; +}; + +int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead) +{ + struct av_ioctl_range_list *r, *r2, *sorted, *sortedhead = NULL; + + /* order list by range.low */ + for (r = *rangehead; r != NULL; r = r->next) { + sorted = malloc(sizeof(struct av_ioctl_range_list)); + if (sorted == NULL) + goto error; + memcpy(sorted, r, sizeof(struct av_ioctl_range_list)); + sorted->next = NULL; + if (sortedhead == NULL) { + sortedhead = sorted; + continue; + } + for (r2 = sortedhead; r2 != NULL; r2 = r2->next) { + if (sorted->range.low < r2->range.low) { + /* range is the new head */ + sorted->next = r2; + sortedhead = sorted; + break; + } else if ((r2->next != NULL) && + (r->range.low < r2->next->range.low)) { + /* insert range between elements */ + sorted->next = r2->next; + r2->next = sorted; + break; + } else if (r2->next == NULL) { + /* range is the new tail*/ + r2->next = sorted; + break; + } + } + } + + r = *rangehead; + while (r != NULL) { + r2 = r; + r = r->next; + free(r2); + } + *rangehead = sortedhead; + return 0; +error: + yyerror("out of memory"); + return -1; +} + +int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead) +{ + struct av_ioctl_range_list *r, *tmp; + + r = *rangehead; + while (r != NULL && r->next != NULL) { + /* merge */ + if ((r->range.high + 1) >= r->next->range.low) { + /* keep the higher of the two */ + if (r->range.high < r->next->range.high) + r->range.high = r->next->range.high; + tmp = r->next; + r->next = r->next->next; + free(tmp); + continue; + } + r = r->next; + } + return 0; +} + +int avrule_read_ioctls(struct av_ioctl_range_list **rangehead) +{ + char *id; + struct av_ioctl_range_list *rnew, *r = NULL; + *rangehead = NULL; + uint8_t omit = 0; + + /* read in all the ioctl commands */ + while ((id = queue_remove(id_queue))) { + if (strcmp(id, "~") == 0) { + /* these are values to be omitted */ + free(id); + omit = 1; + } else if (strcmp(id, "-") == 0) { + /* high value of range */ + free(id); + id = queue_remove(id_queue); + r->range.high = (uint16_t) strtoul(id, NULL, 0); + if (r->range.high < r->range.low) { + yyerror("Ioctl ranges must be in ascending order."); + return -1; + } + free(id); + } else { + /* read in new low value */ + rnew = malloc(sizeof(struct av_ioctl_range_list)); + if (rnew == NULL) + goto error; + rnew->next = NULL; + if (*rangehead == NULL) { + *rangehead = rnew; + r = *rangehead; + } else { + r->next = rnew; + r = r->next; + } + rnew->range.low = (uint16_t) strtoul(id, NULL, 0); + rnew->range.high = rnew->range.low; + free(id); + } + } + r = *rangehead; + r->omit = omit; + return 0; +error: + yyerror("out of memory"); + return -1; +} + +/* flip to included ranges */ +int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead) +{ + struct av_ioctl_range_list *rnew, *r, *newhead, *r2; + + rnew = calloc(1, sizeof(struct av_ioctl_range_list)); + if (!rnew) + goto error; + + newhead = rnew; + + r = *rangehead; + r2 = newhead; + + if (r->range.low == 0) { + r2->range.low = r->range.high + 1; + r = r->next; + } else { + r2->range.low = 0; + } + + while (r) { + r2->range.high = r->range.low - 1; + rnew = calloc(1, sizeof(struct av_ioctl_range_list)); + if (!rnew) + goto error; + r2->next = rnew; + r2 = r2->next; + + r2->range.low = r->range.high + 1; + if (!r->next) + r2->range.high = 0xffff; + r = r->next; + } + + r = *rangehead; + while (r != NULL) { + r2 = r; + r = r->next; + free(r2); + } + *rangehead = newhead; + return 0; + +error: + yyerror("out of memory"); + return -1; +} + +int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist) +{ + struct av_ioctl_range_list *rangehead; + uint8_t omit; + + /* read in ranges to include and omit */ + if (avrule_read_ioctls(&rangehead)) + return -1; + omit = rangehead->omit; + if (rangehead == NULL) { + yyerror("error processing ioctl commands"); + return -1; + } + /* sort and merge the input ioctls */ + if (avrule_sort_ioctls(&rangehead)) + return -1; + if (avrule_merge_ioctls(&rangehead)) + return -1; + /* flip ranges if these are ommited*/ + if (omit) { + if (avrule_omit_ioctls(&rangehead)) + return -1; + } + + *rangelist = rangehead; + return 0; +} + +int define_te_avtab_xperms_helper(int which, avrule_t **rule) +{ + char *id; + class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL; + class_datum_t *cladatum; + perm_datum_t *perdatum = NULL; + ebitmap_t tclasses; + ebitmap_node_t *node; + avrule_t *avrule; + unsigned int i; + int add = 1, ret = 0; + + avrule = (avrule_t *) malloc(sizeof(avrule_t)); + if (!avrule) { + yyerror("out of memory"); + ret = -1; + goto out; + } + avrule_init(avrule); + avrule->specified = which; + avrule->line = policydb_lineno; + avrule->source_line = source_lineno; + avrule->source_filename = strdup(source_file); + avrule->xperms = NULL; + if (!avrule->source_filename) { + yyerror("out of memory"); + return -1; + } + + while ((id = queue_remove(id_queue))) { + if (set_types + (&avrule->stypes, id, &add, + which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) { + ret = -1; + goto out; + } + } + add = 1; + while ((id = queue_remove(id_queue))) { + if (strcmp(id, "self") == 0) { + free(id); + avrule->flags |= RULE_SELF; + continue; + } + if (set_types + (&avrule->ttypes, id, &add, + which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) { + ret = -1; + goto out; + } + } + + ebitmap_init(&tclasses); + ret = read_classes(&tclasses); + if (ret) + goto out; + + perms = NULL; + id = queue_head(id_queue); + ebitmap_for_each_bit(&tclasses, node, i) { + if (!ebitmap_node_get_bit(node, i)) + continue; + cur_perms = + (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); + if (!cur_perms) { + yyerror("out of memory"); + ret = -1; + goto out; + } + class_perm_node_init(cur_perms); + cur_perms->tclass = i + 1; + if (!perms) + perms = cur_perms; + if (tail) + tail->next = cur_perms; + tail = cur_perms; + + cladatum = policydbp->class_val_to_struct[i]; + perdatum = hashtab_search(cladatum->permissions.table, id); + if (!perdatum) { + if (cladatum->comdatum) { + perdatum = hashtab_search(cladatum->comdatum-> + permissions.table, + id); + } + } + if (!perdatum) { + yyerror2("permission %s is not defined" + " for class %s", id, + policydbp->p_class_val_to_name[i]); + continue; + } else if (!is_perm_in_scope(id, + policydbp->p_class_val_to_name[i])) { + yyerror2("permission %s of class %s is" + " not within scope", id, + policydbp->p_class_val_to_name[i]); + continue; + } else { + cur_perms->data |= 1U << (perdatum->s.value - 1); + } + } + + ebitmap_destroy(&tclasses); + + avrule->perms = perms; + *rule = avrule; + +out: + return ret; +} + +/* index of the u32 containing the permission */ +#define XPERM_IDX(x) (x >> 5) +/* set bits 0 through x-1 within the u32 */ +#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1) +/* low value for this u32 */ +#define XPERM_LOW(x) (x << 5) +/* high value for this u32 */ +#define XPERM_HIGH(x) (((x + 1) << 5) - 1) +void avrule_xperm_setrangebits(uint16_t low, uint16_t high, + av_extended_perms_t *xperms) +{ + unsigned int i; + uint16_t h = high + 1; + /* for each u32 that this low-high range touches, + * set driver permissions */ + for (i = XPERM_IDX(low); i <= XPERM_IDX(high); i++) { + /* set all bits in u32 */ + if ((low <= XPERM_LOW(i)) && (high >= XPERM_HIGH(i))) + xperms->perms[i] |= ~0U; + /* set low bits */ + else if ((low <= XPERM_LOW(i)) && (high < XPERM_HIGH(i))) + xperms->perms[i] |= XPERM_SETBITS(h); + /* set high bits */ + else if ((low > XPERM_LOW(i)) && (high >= XPERM_HIGH(i))) + xperms->perms[i] |= ~0U - XPERM_SETBITS(low); + /* set middle bits */ + else if ((low > XPERM_LOW(i)) && (high <= XPERM_HIGH(i))) + xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low); + } +} + +int avrule_xperms_used(av_extended_perms_t *xperms) +{ + unsigned int i; + + for (i = 0; i < sizeof(xperms->perms)/sizeof(xperms->perms[0]); i++) { + if (xperms->perms[i]) + return 1; + } + return 0; +} + +/* + * using definitions found in kernel document ioctl-number.txt + * The kernel components of an ioctl command are: + * dir, size, driver, and fucntion. Only the driver and function fields + * are considered here + */ +#define IOC_DRIV(x) (x >> 8) +#define IOC_FUNC(x) (x & 0xff) +#define IOC_CMD(driver, func) ((driver << 8) + func) +int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist, + av_extended_perms_t *complete_driver, + av_extended_perms_t **extended_perms) +{ + struct av_ioctl_range_list *r; + av_extended_perms_t *xperms; + uint8_t low, high; + + xperms = calloc(1, sizeof(av_extended_perms_t)); + if (!xperms) { + yyerror("out of memory"); + return -1; + } + + r = rangelist; + while (r) { + low = IOC_DRIV(r->range.low); + high = IOC_DRIV(r->range.high); + if (complete_driver) { + if (!xperm_test(low, complete_driver->perms)) + xperm_set(low, xperms->perms); + if (!xperm_test(high, complete_driver->perms)) + xperm_set(high, xperms->perms); + } else { + xperm_set(low, xperms->perms); + xperm_set(high, xperms->perms); + } + r = r->next; + } + if (avrule_xperms_used(xperms)) { + *extended_perms = xperms; + } else { + free(xperms); + *extended_perms = NULL; + } + return 0; + +} + +int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist, + av_extended_perms_t **extended_perms) +{ + struct av_ioctl_range_list *r; + av_extended_perms_t *xperms; + uint16_t low, high; + + xperms = calloc(1, sizeof(av_extended_perms_t)); + if (!xperms) { + yyerror("out of memory"); + return -1; + } + + r = rangelist; + while (r) { + /* + * Any driver code that has sequence 0x00 - 0xff is a + * complete code, + * + * if command number = 0xff, then round high up to next code, + * else 0x00 - 0xfe keep current code + * of this range. temporarily u32 for the + 1 + * to account for possible rollover before right shift + */ + high = IOC_DRIV((uint32_t) (r->range.high + 1)); + /* if 0x00 keep current driver code else 0x01 - 0xff round up + * to next code*/ + low = IOC_DRIV(r->range.low); + if (IOC_FUNC(r->range.low)) + low++; + if (high > low) + avrule_xperm_setrangebits(low, high - 1, xperms); + r = r->next; + } + if (avrule_xperms_used(xperms)) { + xperms->driver = 0x00; + xperms->specified = AVRULE_XPERMS_IOCTLDRIVER; + *extended_perms = xperms; + } else { + free(xperms); + *extended_perms = NULL; + } + return 0; +} + +int avrule_ioctl_func(struct av_ioctl_range_list *rangelist, + av_extended_perms_t **extended_perms, unsigned int driver) +{ + struct av_ioctl_range_list *r; + av_extended_perms_t *xperms; + uint16_t low, high; + + *extended_perms = NULL; + xperms = calloc(1, sizeof(av_extended_perms_t)); + if (!xperms) { + yyerror("out of memory"); + return -1; + } + + r = rangelist; + /* for the passed in driver code, find the ranges that apply */ + while (r) { + low = r->range.low; + high = r->range.high; + if ((driver != IOC_DRIV(low)) && (driver != IOC_DRIV(high))) { + r = r->next; + continue; + } + + if (driver == IOC_DRIV(low)) { + if (high > IOC_CMD(driver, 0xff)) + high = IOC_CMD(driver, 0xff); + + } else { + if (low < IOC_CMD(driver, 0)) + low = IOC_CMD(driver, 0); + } + + low = IOC_FUNC(low); + high = IOC_FUNC(high); + avrule_xperm_setrangebits(low, high, xperms); + xperms->driver = driver; + xperms->specified = AVRULE_XPERMS_IOCTLFUNCTION; + r = r->next; + } + + if (avrule_xperms_used(xperms)) { + *extended_perms = xperms; + } else { + free(xperms); + *extended_perms = NULL; + } + return 0; +} + +void avrule_ioctl_freeranges(struct av_ioctl_range_list *rangelist) +{ + struct av_ioctl_range_list *r, *tmp; + + r = rangelist; + while (r) { + tmp = r; + r = r->next; + free(tmp); + } +} + +unsigned int xperms_for_each_bit(unsigned int *bit, + av_extended_perms_t *xperms) { + unsigned int i; + + for (i = *bit; i < sizeof(xperms->perms)*8; i++) { + if (xperm_test(i, xperms->perms)) { + xperm_clear(i, xperms->perms); + *bit = i; + return 1; + } + } + return 0; +} + +int avrule_cpy(avrule_t *dest, avrule_t *src) +{ + class_perm_node_t *src_perms; + class_perm_node_t *dest_perms, *dest_tail; + + dest_tail = NULL; + + avrule_init(dest); + dest->specified = src->specified; + dest->flags = src->flags; + if (type_set_cpy(&dest->stypes, &src->stypes)) { + yyerror("out of memory"); + return -1; + } + if (type_set_cpy(&dest->ttypes, &src->ttypes)) { + yyerror("out of memory"); + return -1; + } + dest->line = src->line; + dest->source_filename = strdup(source_file); + if (!dest->source_filename) { + yyerror("out of memory"); + return -1; + } + dest->source_line = src->source_line; + + /* increment through the class perms and copy over */ + src_perms = src->perms; + while (src_perms) { + dest_perms = (class_perm_node_t *) calloc + (1, sizeof(class_perm_node_t)); + class_perm_node_init(dest_perms); + if (!dest_perms) { + yyerror("out of memory"); + return -1; + } + if (!dest->perms) + dest->perms = dest_perms; + else + dest_tail->next = dest_perms; + + dest_perms->tclass = src_perms->tclass; + dest_perms->data = src_perms->data; + dest_perms->next = NULL; + dest_tail = dest_perms; + src_perms = src_perms->next; + } + return 0; +} + +int define_te_avtab_ioctl(avrule_t *avrule_template) +{ + avrule_t *avrule; + struct av_ioctl_range_list *rangelist; + av_extended_perms_t *complete_driver, *partial_driver, *xperms; + unsigned int i; + + + /* organize ioctl ranges */ + if (avrule_ioctl_ranges(&rangelist)) + return -1; + + /* create rule for ioctl driver types that are entirely enabled */ + if (avrule_ioctl_completedriver(rangelist, &complete_driver)) + return -1; + if (complete_driver) { + avrule = (avrule_t *) calloc(1, sizeof(avrule_t)); + if (!avrule) { + yyerror("out of memory"); + return -1; + } + if (avrule_cpy(avrule, avrule_template)) + return -1; + avrule->xperms = complete_driver; + append_avrule(avrule); + } + + /* flag ioctl driver codes that are partially enabled */ + if (avrule_ioctl_partialdriver(rangelist, complete_driver, + &partial_driver)) + return -1; + + if (!partial_driver || !avrule_xperms_used(partial_driver)) + goto done; + + /* + * create rule for each partially used driver codes + * "partially used" meaning that the code number e.g. socket 0x89 + * has some permission bits set and others not set. + */ + i = 0; + while (xperms_for_each_bit(&i, partial_driver)) { + if (avrule_ioctl_func(rangelist, &xperms, i)) + return -1; + + if (xperms) { + avrule = (avrule_t *) calloc(1, sizeof(avrule_t)); + if (!avrule) { + yyerror("out of memory"); + return -1; + } + if (avrule_cpy(avrule, avrule_template)) + return -1; + avrule->xperms = xperms; + append_avrule(avrule); + } + } + +done: + if (partial_driver) + free(partial_driver); + + return 0; +} + +int define_te_avtab_extended_perms(int which) +{ + char *id; + unsigned int i; + avrule_t *avrule_template; + + if (pass == 1) { + for (i = 0; i < 4; i++) { + while ((id = queue_remove(id_queue))) + free(id); + } + return 0; + } + + /* populate avrule template with source/target/tclass */ + if (define_te_avtab_xperms_helper(which, &avrule_template)) + return -1; + + id = queue_remove(id_queue); + if (strcmp(id, "ioctl") == 0) { + if (define_te_avtab_ioctl(avrule_template)) + return -1; + free(id); + } else { + yyerror("only ioctl extended permissions are supported"); + return -1; + } + return 0; +} +/* END XPERMS */ + int define_te_avtab_helper(int which, avrule_t ** rule) { char *id; @@ -1766,6 +2459,14 @@ int define_te_avtab_helper(int which, avrule_t ** rule) avrule_init(avrule); avrule->specified = which; avrule->line = policydb_lineno; + avrule->source_line = source_lineno; + avrule->source_filename = strdup(source_file); + avrule->xperms = NULL; + if (!avrule->source_filename) { + yyerror("out of memory"); + return -1; + } + while ((id = queue_remove(id_queue))) { if (set_types @@ -2140,7 +2841,7 @@ static int dominate_role_recheck(hashtab_key_t key __attribute__ ((unused)), role_datum_t *rdp = (role_datum_t *) arg; role_datum_t *rdatum = (role_datum_t *) datum; ebitmap_node_t *node; - unsigned int i; + int i; /* Don't bother to process against self role */ if (rdatum->s.value == rdp->s.value) @@ -2232,7 +2933,7 @@ role_datum_t *define_role_dom(role_datum_t * r) break; } default:{ - abort(); /* should never get here */ + abort(); /* SETools - should never get here */ } } if (ebitmap_set_bit(&role->dominates, role->s.value - 1, TRUE)) { @@ -2395,7 +3096,7 @@ int define_role_trans(int class_specified) return -1; } else { cladatum = hashtab_search(policydbp->p_classes.table, - (hashtab_key_t)"process"); + (hashtab_key_t)"process"); /* SETools */ if (!cladatum) { yyerror2("could not find process class for " "legacy role_transition statement"); @@ -3943,7 +4644,12 @@ bad: return -1; } + +#ifdef HAVE_SEPOL_XEN_DEVICETREE +int define_iomem_context(uint64_t low, uint64_t high) +#else int define_iomem_context(unsigned long low, unsigned long high) +#endif { ocontext_t *newc, *c, *l, *head; char *id; @@ -3971,7 +4677,7 @@ int define_iomem_context(unsigned long low, unsigned long high) newc->u.iomem.high_iomem = high; if (low > high) { - yyerror2("low memory 0x%lx exceeds high memory 0x%lx", low, high); + yyerror2("low memory 0x%"PRIx64" exceeds high memory 0x%"PRIx64"", low, high); free(newc); return -1; } @@ -3983,13 +4689,17 @@ int define_iomem_context(unsigned long low, unsigned long high) head = policydbp->ocontexts[OCON_XEN_IOMEM]; for (l = NULL, c = head; c; l = c, c = c->next) { - unsigned int low2, high2; +#ifdef HAVE_SEPOL_XEN_DEVICETREE + uint64_t low2, high2; +#else + unsigned long low2, high2; /* SETools */ +#endif low2 = c->u.iomem.low_iomem; high2 = c->u.iomem.high_iomem; if (low <= high2 && low2 <= high) { - yyerror2("iomemcon entry for 0x%lx-0x%lx overlaps with " - "earlier entry 0x%x-0x%x", low, high, + yyerror2("iomemcon entry for 0x%"PRIx64"-0x%"PRIx64" overlaps with " + "earlier entry 0x%"PRIx64"-0x%"PRIx64"", low, high, low2, high2); goto bad; } @@ -4047,7 +4757,7 @@ int define_ioport_context(unsigned long low, unsigned long high) head = policydbp->ocontexts[OCON_XEN_IOPORT]; for (l = NULL, c = head; c; l = c, c = c->next) { - unsigned int low2, high2; + uint32_t low2, high2; low2 = c->u.ioport.low_ioport; high2 = c->u.ioport.high_ioport; @@ -4126,6 +4836,66 @@ bad: return -1; } +int define_devicetree_context(void) /* SETools */ +{ +#ifdef HAVE_SEPOL_XEN_DEVICETREE + ocontext_t *newc, *c, *l, *head; +#endif + if (policydbp->target_platform != SEPOL_TARGET_XEN) { + yyerror("devicetreecon not supported for target"); + return -1; + } + + if (pass == 1) { + free(queue_remove(id_queue)); + parse_security_context(NULL); + return 0; + } + +#ifdef HAVE_SEPOL_XEN_DEVICETREE + newc = malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + memset(newc, 0, sizeof(ocontext_t)); + + newc->u.name = (char *)queue_remove(id_queue); + if (!newc->u.name) { + free(newc); + return -1; + } + + if (parse_security_context(&newc->context[0])) { + free(newc->u.name); + free(newc); + return -1; + } + + head = policydbp->ocontexts[OCON_XEN_DEVICETREE]; + for (l = NULL, c = head; c; l = c, c = c->next) { + if (strcmp(newc->u.name, c->u.name) == 0) { + yyerror2("duplicate devicetree entry for '%s'", newc->u.name); + goto bad; + } + } + + if (l) + l->next = newc; + else + policydbp->ocontexts[OCON_XEN_DEVICETREE] = newc; + + return 0; + +bad: + free(newc->u.name); + free(newc); + return -1; +#else + yyerror("This version of SETools does not have devicetreecon support."); + return -1; +#endif +} int define_port_context(unsigned int low, unsigned int high) { ocontext_t *newc, *c, *l, *head; @@ -4273,7 +5043,7 @@ int define_netif_context(void) return 0; } -int define_ipv4_node_context(void) +int define_ipv4_node_context(void) /* SETools */ { char *id; int rc = 0; @@ -4692,7 +5462,7 @@ int define_range_trans(int class_specified) goto out; } else { cladatum = hashtab_search(policydbp->p_classes.table, - (hashtab_key_t)"process"); + (hashtab_key_t)"process"); /* SETools */ if (!cladatum) { yyerror2("could not find process class for " "legacy range_transition statement"); diff --git a/libqpol/policy_define.h b/libqpol/policy_define.h index 6dfbb87..1a5b326 100644 --- a/libqpol/policy_define.h +++ b/libqpol/policy_define.h @@ -1,7 +1,6 @@ -/** - * @file policy_define.h - * This file is based upon checkpolicy/policy_define.h from NSA's SVN - * repository. +/* + * This file is a copy of policy_define.h from checkpolicy 2.4 updated to + * support SETools. */ /* Functions used to define policy grammar components. */ @@ -18,8 +17,10 @@ #define TRUE 1 #define FALSE 0 -/* Used by SETools to determine if source MLS or not */ + +/* Used by SETools to determine if source has MLS and/or XEN support */ int define_mls(void); +int define_xen(void); avrule_t *define_cond_compute_type(int which); avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *stmt); @@ -54,9 +55,15 @@ int define_permissive(void); int define_polcap(void); int define_port_context(unsigned int low, unsigned int high); int define_pirq_context(unsigned int pirq); +/* Support SETools */ +#ifdef HAVE_SEPOL_XEN_DEVICETREE +int define_iomem_context(uint64_t low, uint64_t high); +#else int define_iomem_context(unsigned long low, unsigned long high); +#endif int define_ioport_context(unsigned long low, unsigned long high); int define_pcidevice_context(unsigned long device); +int define_devicetree_context(void); int define_range_trans(int class_specified); int define_role_allow(void); int define_role_trans(int class_specified); @@ -66,6 +73,7 @@ int define_roleattribute(void); int define_filename_trans(void); int define_sens(void); int define_te_avtab(int which); +int define_te_avtab_extended_perms(int which); int define_typealias(void); int define_typeattribute(void); int define_typebounds(void); diff --git a/libqpol/policy_extend.c b/libqpol/policy_extend.c index bccb647..9f58513 100644 --- a/libqpol/policy_extend.c +++ b/libqpol/policy_extend.c @@ -231,7 +231,7 @@ static int qpol_policy_build_attrs_from_map(qpol_policy_t * policy) } /* Already exists */ - else + else tmp_name = db->p_type_val_to_name[i]; tmp_type = calloc(1, sizeof(type_datum_t)); @@ -311,6 +311,7 @@ static int qpol_policy_build_attrs_from_map(qpol_policy_t * policy) * errno will be set. On failure, the policy state may be inconsistent * especially in the case where the hashtab functions return the error. */ + static int qpol_policy_fill_attr_holes(qpol_policy_t * policy) { policydb_t *db = NULL; @@ -1007,6 +1008,7 @@ int policy_extend(qpol_policy_t * policy) error = errno; goto err; } + if (db->attr_type_map) { retv = qpol_policy_build_attrs_from_map(policy); if (retv) { diff --git a/libqpol/policy_parse.y b/libqpol/policy_parse.y index 63a07d7..fac1872 100644 --- a/libqpol/policy_parse.y +++ b/libqpol/policy_parse.y @@ -1,10 +1,6 @@ -/** - * @file policy_parse.y - * - * This file is based upon checkpolicy/policy_parse.y from NSA's SVN - * repository. It has been modified to support older policy formats. - * The older format just seems to be FSUSEPSID support (see fs_use_def - * entry. +/* + * This file is a copy of policy_parse.y from checkpolicy 2.4 updated to + * support SETools. */ /* @@ -37,7 +33,7 @@ /* FLASK */ %{ -/* Add for SETools */ +/* Required for SETools libqpol services */ #include #include @@ -61,7 +57,7 @@ #include #include "queue.h" -/* #include "checkpolicy.h" - Remove for setools and replace with: */ +/* #include "checkpolicy.h" - Remove for SETools and replace with: */ #include #include "module_compiler.h" @@ -88,6 +84,7 @@ extern char *qpol_src_inputlim;/* end of data */ %union { unsigned int val; + uint64_t val64; uintptr_t valptr; void *ptr; require_func_t require_func; @@ -99,9 +96,11 @@ extern char *qpol_src_inputlim;/* end of data */ %type role_def roles %type cexpr cexpr_prim op role_mls_op %type ipv4_addr_def number +%type number64 %type require_decl_def %token PATH +%token QPATH %token FILENAME %token CLONE %token COMMON @@ -144,11 +143,15 @@ extern char *qpol_src_inputlim;/* end of data */ %token AUDITALLOW %token AUDITDENY %token DONTAUDIT +%token ALLOWXPERM +%token AUDITALLOWXPERM +%token DONTAUDITXPERM +%token NEVERALLOWXPERM %token SOURCE %token TARGET %token SAMEUSER %token FSCON PORTCON NETIFCON NODECON -%token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON +%token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON %token FSUSEXATTR FSUSETASK FSUSETRANS %token GENFSCON %token U1 U2 U3 R1 R2 R3 T1 T2 T3 L1 L2 H1 H2 @@ -266,14 +269,8 @@ mls : sensitivities dominance opt_categories levels mlspolicy sensitivities : sensitivity_def | sensitivities sensitivity_def ; -/*sensitivity_def : SENSITIVITY identifier alias_def ';' - {if (define_sens()) return -1;} - | SENSITIVITY identifier ';' - {if (define_sens()) return -1;} - ; -The above has been replaced by: */ -/* Needed for SETools to call define_mls here, as we are working */ -/* with files only, not command line options */ +/* SETools - Add define_mls() to set MLS, as we are working with + * files only, not checkpolicy/module command line options */ sensitivity_def : SENSITIVITY identifier alias_def ';' {if (define_mls() | define_sens()) return -1;} | SENSITIVITY identifier ';' @@ -483,6 +480,10 @@ te_avtab_def : allow_def | auditdeny_def | dontaudit_def | neverallow_def + | xperm_allow_def + | xperm_auditallow_def + | xperm_dontaudit_def + | xperm_neverallow_def ; allow_def : ALLOW names names ':' names names ';' {if (define_te_avtab(AVRULE_ALLOWED)) return -1; } @@ -499,6 +500,18 @@ dontaudit_def : DONTAUDIT names names ':' names names ';' neverallow_def : NEVERALLOW names names ':' names names ';' {if (define_te_avtab(AVRULE_NEVERALLOW)) return -1; } ; +xperm_allow_def : ALLOWXPERM names names ':' names identifier xperms ';' + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_ALLOWED)) return -1; } + ; +xperm_auditallow_def : AUDITALLOWXPERM names names ':' names identifier xperms ';' + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_AUDITALLOW)) return -1; } + ; +xperm_dontaudit_def : DONTAUDITXPERM names names ':' names identifier xperms ';' + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT)) return -1; } + ; +xperm_neverallow_def : NEVERALLOWXPERM names names ':' names identifier xperms ';' + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_NEVERALLOW)) return -1; } + ; attribute_role_def : ATTRIBUTE_ROLE identifier ';' {if (define_attrib_role()) return -1; } ; @@ -670,23 +683,29 @@ dev_contexts : dev_context_def dev_context_def : pirq_context_def | iomem_context_def | ioport_context_def | - pci_context_def + pci_context_def | + dtree_context_def ; +/* SETools - Add define_xen() to set policy type, as we are working + * with files only, not checkpolicy/module command line options */ pirq_context_def : PIRQCON number security_context_def - {if (define_pirq_context($2)) return -1;} + {if (define_xen() | define_pirq_context($2)) return -1;} ; -iomem_context_def : IOMEMCON number security_context_def - {if (define_iomem_context($2,$2)) return -1;} - | IOMEMCON number '-' number security_context_def - {if (define_iomem_context($2,$4)) return -1;} +iomem_context_def : IOMEMCON number64 security_context_def + {if (define_xen() | define_iomem_context($2,$2)) return -1;} + | IOMEMCON number64 '-' number64 security_context_def + {if (define_xen() | define_iomem_context($2,$4)) return -1;} ; ioport_context_def : IOPORTCON number security_context_def - {if (define_ioport_context($2,$2)) return -1;} + {if (define_xen() | define_ioport_context($2,$2)) return -1;} | IOPORTCON number '-' number security_context_def - {if (define_ioport_context($2,$4)) return -1;} + {if (define_xen() | define_ioport_context($2,$4)) return -1;} ; pci_context_def : PCIDEVICECON number security_context_def - {if (define_pcidevice_context($2)) return -1;} + {if (define_xen() | define_pcidevice_context($2)) return -1;} + ; +dtree_context_def : DEVICETREECON path security_context_def + {if (define_xen() | define_devicetree_context()) return -1;} ; opt_fs_contexts : fs_contexts | @@ -759,6 +778,28 @@ genfs_context_def : GENFSCON filesystem path '-' identifier security_context_def ipv4_addr_def : IPV4_ADDR { if (insert_id(yytext,0)) return -1; } ; +xperms : xperm + { if (insert_separator(0)) return -1; } + | nested_xperm_set + { if (insert_separator(0)) return -1; } + | tilde xperm + { if (insert_id("~", 0)) return -1; } + | tilde nested_xperm_set + { if (insert_id("~", 0)) return -1; + if (insert_separator(0)) return -1; } + ; +nested_xperm_set : '{' nested_xperm_list '}' + ; +nested_xperm_list : nested_xperm_element + | nested_xperm_list nested_xperm_element + ; +nested_xperm_element: xperm '-' { if (insert_id("-", 0)) return -1; } xperm + | xperm + | nested_xperm_set + ; +xperm : number + { if (insert_id(yytext,0)) return -1; } + ; security_context_def : identifier ':' identifier ':' identifier opt_mls_range_def ; opt_mls_range_def : ':' mls_range_def @@ -834,6 +875,8 @@ filesystem : FILESYSTEM ; path : PATH { if (insert_id(yytext,0)) return -1; } + | QPATH + { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; } ; filename : FILENAME { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; } @@ -841,6 +884,9 @@ filename : FILENAME number : NUMBER { $$ = strtoul(yytext,NULL,0); } ; +number64 : NUMBER + { $$ = strtoull(yytext,NULL,0); } + ; ipv6_addr : IPV6_ADDR { if (insert_id(yytext,0)) return -1; } ; diff --git a/libqpol/policy_scan.l b/libqpol/policy_scan.l index 9ce4c4b..e82ba4f 100644 --- a/libqpol/policy_scan.l +++ b/libqpol/policy_scan.l @@ -1,14 +1,13 @@ -/** - * @file policy_parse.y - * - * This file is based upon checkpolicy/policy_scan.l fram NSA's SVN - * repository. It has been modified to support older policy formats. - * The older format just seems to be FSUSEPSID support (see fs_use_psid - * entry. - * +/* + * This file is a copy of policy_scan.l from checkpolicy 2.4 updated to + * support SETools. + */ + +/* * Author : Stephen Smalley, - * - * Updated: David Caplan, + */ + +/* Updated: David Caplan, * * Added conditional policy language extensions * @@ -36,7 +35,7 @@ #include #include -typedef int (* require_func_t)(int pass); +typedef int (* require_func_t)(void); /* For SETools libqpol services leave this as policy_parse.h */ #include "policy_parse.h" @@ -44,7 +43,6 @@ typedef int (* require_func_t)(int pass); static char linebuf[2][255]; static unsigned int lno = 0; int yywarn(const char *msg); -int yyerror(const char *msg); void set_source_file(const char *name); @@ -159,6 +157,14 @@ AUDITDENY | auditdeny { return(AUDITDENY); } DONTAUDIT | dontaudit { return(DONTAUDIT); } +ALLOWXPERM | +allowxperm { return(ALLOWXPERM); } +AUDITALLOWXPERM | +auditallowxperm { return(AUDITALLOWXPERM); } +DONTAUDITXPERM | +dontauditxperm { return(DONTAUDITXPERM); } +NEVERALLOWXPERM | +neverallowxperm { return(NEVERALLOWXPERM); } SOURCE | source { return(SOURCE); } TARGET | @@ -204,6 +210,8 @@ ioportcon | IOPORTCON { return(IOPORTCON);} pcidevicecon | PCIDEVICECON { return(PCIDEVICECON);} +devicetreecon | +DEVICETREECON { return(DEVICETREECON);} fs_use_xattr | FS_USE_XATTR { return(FSUSEXATTR);} fs_use_task | @@ -257,10 +265,11 @@ HIGH { return(HIGH); } low | LOW { return(LOW); } "/"({alnum}|[_\.\-/])* { return(PATH); } +\""/"[ !#-~]*\" { return(QPATH); } \"({alnum}|[_\.\-\+\~\: ])+\" { return(FILENAME); } {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))* { return(IDENTIFIER); } -{alnum}*{letter}{alnum}* { return(FILESYSTEM); } {digit}+|0x{hexval}+ { return(NUMBER); } +{alnum}*{letter}{alnum}* { return(FILESYSTEM); } {digit}{1,3}(\.{digit}{1,3}){3} { return(IPV4_ADDR); } {hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])* { return(IPV6_ADDR); } {digit}+(\.({alnum}|[_.])*)? { return(VERSION_IDENTIFIER); } @@ -325,6 +334,8 @@ void set_source_file(const char *name) source_lineno = 1; strncpy(source_file, name, sizeof(source_file)-1); source_file[sizeof(source_file)-1] = '\0'; + if (strlen(source_file) && source_file[strlen(source_file)-1] == '"') + source_file[strlen(source_file)-1] = '\0'; } /* Required for SETools libqpol services */ diff --git a/libqpol/queue.c b/libqpol/queue.c index 45a510a..8b84f50 100644 --- a/libqpol/queue.c +++ b/libqpol/queue.c @@ -1,12 +1,9 @@ -/** - * @file - * - * This file is a copy of queue.c from NSA's CVS repository. - * - * Author : Stephen Smalley, +/* + * This file is a copy of queue.c from checkpolicy 2.4. There are + * NO updates required to support SETools. */ -/* No changes for SETools libqpol services - Just the header */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/libqpol/queue.h b/libqpol/queue.h index dca1b2e..d20b361 100644 --- a/libqpol/queue.h +++ b/libqpol/queue.h @@ -1,12 +1,9 @@ -/** - * @file - * - * This file is a copy of queue.h from NSA's CVS repository. - * - * Author : Stephen Smalley, +/* + * This file is a copy of queue.h from checkpolicy 2.4. There are + * NO updates required to support SETools. */ -/* No changes for SETools libqpol services - Just the header */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/libqpol/xen_query.c b/libqpol/xen_query.c new file mode 100644 index 0000000..0fe1572 --- /dev/null +++ b/libqpol/xen_query.c @@ -0,0 +1,557 @@ +/** + * @file + * Defines the public interface for searching and iterating over + * Xen statements. + * + * @author Richard Haines richard_c_haines@btinternet.com + * Derived from portcon_query.c + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qpol_internal.h" +#include "iterator_internal.h" + +/******************************* iomemcon **************************/ +int qpol_policy_get_iomemcon_by_addr(const qpol_policy_t *policy, + uint64_t low, uint64_t high, + const qpol_iomemcon_t **ocon) +{ + ocontext_t *tmp = NULL; + policydb_t *db = NULL; + + if (ocon != NULL) + *ocon = NULL; + + if (policy == NULL || ocon == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + for (tmp = db->ocontexts[OCON_XEN_IOMEM]; tmp; tmp = tmp->next) { + if (tmp->u.iomem.low_iomem == low && + tmp->u.iomem.high_iomem == high) + break; + } + + *ocon = (qpol_iomemcon_t *) tmp; + + if (*ocon == NULL) { + ERR(policy, "could not find iomemcon statement for %lu-%lu", + low, high); + errno = ENOENT; + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +int qpol_policy_get_iomemcon_iter(const qpol_policy_t *policy, + qpol_iterator_t **iter) +{ + policydb_t *db = NULL; + int error = 0; + ocon_state_t *os = NULL; + + if (iter != NULL) + *iter = NULL; + + if (policy == NULL || iter == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + + os = calloc(1, sizeof(ocon_state_t)); + if (os == NULL) { + error = errno; + ERR(policy, "%s", strerror(ENOMEM)); + errno = error; + return STATUS_ERR; + } + + os->head = os->cur = db->ocontexts[OCON_XEN_IOMEM]; + + if (qpol_iterator_create(policy, (void *)os, ocon_state_get_cur, + ocon_state_next, ocon_state_end, ocon_state_size, + free, iter)) { + free(os); + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +int qpol_iomemcon_get_low_addr(const qpol_policy_t *policy, + const qpol_iomemcon_t *ocon, + uint64_t *addr) +{ + ocontext_t *internal_ocon = NULL; + + if (addr != NULL) + *addr = 0; + + if (policy == NULL || ocon == NULL || addr == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + + *addr = internal_ocon->u.iomem.low_iomem; + + return STATUS_SUCCESS; +} + +int qpol_iomemcon_get_high_addr(const qpol_policy_t *policy, + const qpol_iomemcon_t *ocon, + uint64_t *addr) +{ + ocontext_t *internal_ocon = NULL; + + if (addr != NULL) + *addr = 0; + + if (policy == NULL || ocon == NULL || addr == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + + *addr = internal_ocon->u.iomem.high_iomem; + + return STATUS_SUCCESS; +} + +int qpol_iomemcon_get_context(const qpol_policy_t *policy, + const qpol_iomemcon_t *ocon, + const qpol_context_t **context) +{ + ocontext_t *internal_ocon = NULL; + + if (context != NULL) + *context = NULL; + + if (policy == NULL || ocon == NULL || context == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + *context = (qpol_context_t *) &(internal_ocon->context[0]); + + return STATUS_SUCCESS; +} + + +/******************************* ioportcon **************************/ +int qpol_policy_get_ioportcon_by_port(const qpol_policy_t *policy, + uint32_t low, uint32_t high, + const qpol_ioportcon_t **ocon) +{ + ocontext_t *tmp = NULL; + policydb_t *db = NULL; + + if (ocon != NULL) + *ocon = NULL; + + if (policy == NULL || ocon == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + for (tmp = db->ocontexts[OCON_XEN_IOPORT]; tmp; tmp = tmp->next) { + if (tmp->u.ioport.low_ioport == low && + tmp->u.ioport.high_ioport == high) + break; + } + + *ocon = (qpol_ioportcon_t *) tmp; + + if (*ocon == NULL) { + ERR(policy, "could not find ioportcon statement for %u-%u", + low, high); + errno = ENOENT; + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +int qpol_policy_get_ioportcon_iter(const qpol_policy_t *policy, + qpol_iterator_t **iter) +{ + policydb_t *db = NULL; + int error = 0; + ocon_state_t *os = NULL; + + if (iter != NULL) + *iter = NULL; + + if (policy == NULL || iter == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + + os = calloc(1, sizeof(ocon_state_t)); + if (os == NULL) { + error = errno; + ERR(policy, "%s", strerror(ENOMEM)); + errno = error; + return STATUS_ERR; + } + + os->head = os->cur = db->ocontexts[OCON_XEN_IOPORT]; + + if (qpol_iterator_create(policy, (void *)os, ocon_state_get_cur, + ocon_state_next, ocon_state_end, + ocon_state_size, free, iter)) { + free(os); + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +int qpol_ioportcon_get_low_port(const qpol_policy_t *policy, + const qpol_ioportcon_t *ocon, + uint32_t *port) +{ + ocontext_t *internal_ocon = NULL; + + if (port != NULL) + *port = 0; + + if (policy == NULL || ocon == NULL || port == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + + *port = internal_ocon->u.ioport.low_ioport; + + return STATUS_SUCCESS; +} + +int qpol_ioportcon_get_high_port(const qpol_policy_t *policy, + const qpol_ioportcon_t *ocon, + uint32_t *port) +{ + ocontext_t *internal_ocon = NULL; + + if (port != NULL) + *port = 0; + + if (policy == NULL || ocon == NULL || port == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + + *port = internal_ocon->u.ioport.high_ioport; + + return STATUS_SUCCESS; +} + +int qpol_ioportcon_get_context(const qpol_policy_t *policy, + const qpol_ioportcon_t *ocon, + const qpol_context_t **context) +{ + ocontext_t *internal_ocon = NULL; + + if (context != NULL) + *context = NULL; + + if (policy == NULL || ocon == NULL || context == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + *context = (qpol_context_t *) &(internal_ocon->context[0]); + + return STATUS_SUCCESS; +} + + +/******************************* pcidevicecon **************************/ +int qpol_policy_get_pcidevicecon_iter(const qpol_policy_t *policy, + qpol_iterator_t **iter) +{ + policydb_t *db = NULL; + int error = 0; + ocon_state_t *os = NULL; + + if (iter != NULL) + *iter = NULL; + + if (policy == NULL || iter == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + + os = calloc(1, sizeof(ocon_state_t)); + if (os == NULL) { + error = errno; + ERR(policy, "%s", strerror(ENOMEM)); + errno = error; + return STATUS_ERR; + } + + os->head = os->cur = db->ocontexts[OCON_XEN_PCIDEVICE]; + + if (qpol_iterator_create(policy, (void *)os, ocon_state_get_cur, + ocon_state_next, ocon_state_end, + ocon_state_size, free, iter)) { + free(os); + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +int qpol_pcidevicecon_get_device(const qpol_policy_t *policy, + const qpol_pcidevicecon_t *ocon, + uint32_t *device) +{ + ocontext_t *internal_ocon = NULL; + + if (device != NULL) + *device = 0; + + if (policy == NULL || ocon == NULL || device == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + + *device = internal_ocon->u.device; + + return STATUS_SUCCESS; +} + +int qpol_pcidevicecon_get_context(const qpol_policy_t *policy, + const qpol_pcidevicecon_t *ocon, + const qpol_context_t **context) +{ + ocontext_t *internal_ocon = NULL; + + if (context != NULL) + *context = NULL; + + if (policy == NULL || ocon == NULL || context == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + *context = (qpol_context_t *) &(internal_ocon->context[0]); + + return STATUS_SUCCESS; +} + + +/******************************* pirqcon **************************/ +int qpol_policy_get_pirqcon_iter(const qpol_policy_t *policy, + qpol_iterator_t **iter) +{ + policydb_t *db = NULL; + int error = 0; + ocon_state_t *os = NULL; + + if (iter != NULL) + *iter = NULL; + + if (policy == NULL || iter == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + + os = calloc(1, sizeof(ocon_state_t)); + if (os == NULL) { + error = errno; + ERR(policy, "%s", strerror(ENOMEM)); + errno = error; + return STATUS_ERR; + } + + os->head = os->cur = db->ocontexts[OCON_XEN_PIRQ]; + + if (qpol_iterator_create(policy, (void *)os, ocon_state_get_cur, + ocon_state_next, ocon_state_end, + ocon_state_size, free, iter)) { + free(os); + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +int qpol_pirqcon_get_irq(const qpol_policy_t *policy, + const qpol_pirqcon_t *ocon, + uint16_t *irq) +{ + ocontext_t *internal_ocon = NULL; + + if (irq != NULL) + *irq = 0; + + if (policy == NULL || ocon == NULL || irq == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + + *irq = internal_ocon->u.pirq; + + return STATUS_SUCCESS; +} + +int qpol_pirqcon_get_context(const qpol_policy_t *policy, + const qpol_pirqcon_t *ocon, + const qpol_context_t **context) +{ + ocontext_t *internal_ocon = NULL; + + if (context != NULL) + *context = NULL; + + if (policy == NULL || ocon == NULL || context == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + *context = (qpol_context_t *) &(internal_ocon->context[0]); + + return STATUS_SUCCESS; +} + +/******************************* devicetreecon **************************/ + +int qpol_policy_get_devicetreecon_iter(const qpol_policy_t *policy, + qpol_iterator_t **iter) +{ + policydb_t *db = NULL; + ocon_state_t *os = NULL; + int error = 0; + + if (iter != NULL) + *iter = NULL; + + if (policy == NULL || iter == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + + os = calloc(1, sizeof(ocon_state_t)); + if (os == NULL) { + error = errno; + ERR(policy, "%s", strerror(ENOMEM)); + errno = error; + return STATUS_ERR; + } + + os->head = os->cur = db->ocontexts[OCON_XEN_DEVICETREE]; + if (qpol_iterator_create(policy, (void *)os, ocon_state_get_cur, + ocon_state_next, ocon_state_end, + ocon_state_size, free, iter)) { + free(os); + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +int qpol_devicetreecon_get_path(const qpol_policy_t *policy, + const qpol_devicetreecon_t *ocon, + char **path) +{ + ocontext_t *internal_ocon = NULL; + + if (path != NULL) + *path = NULL; + + if (policy == NULL || ocon == NULL || path == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + + *path = internal_ocon->u.name; + + return STATUS_SUCCESS; +} + +int qpol_devicetreecon_get_context(const qpol_policy_t *policy, + const qpol_devicetreecon_t *ocon, + const qpol_context_t **context) +{ + ocontext_t *internal_ocon = NULL; + + if (context != NULL) + *context = NULL; + + if (policy == NULL || ocon == NULL || context == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_ocon = (ocontext_t *) ocon; + *context = (qpol_context_t *) &(internal_ocon->context[0]); + + return STATUS_SUCCESS; +} diff --git a/libqpol/xprule_query.c b/libqpol/xprule_query.c new file mode 100644 index 0000000..c88a231 --- /dev/null +++ b/libqpol/xprule_query.c @@ -0,0 +1,235 @@ + /** + * @file + * Implementation for the public interface for searching and iterating over + * xperm rules. + * + * @author Richard Haines richard_c_haines@btinternet.com + * Derived from avrule_query.c + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#include +#include +#include + +#include "iterator_internal.h" +#include +#include +#include +#include +#include +#include +#include +#include "qpol_internal.h" + +int qpol_policy_get_xprule_iter(const qpol_policy_t *policy, + uint32_t rule_type_mask, + qpol_iterator_t **iter) +{ + policydb_t *db; + avtab_state_t *state; + + if (iter) + *iter = NULL; + + if (policy == NULL || iter == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + if ((rule_type_mask & QPOL_RULE_NEVERALLOWXPERM) && + !qpol_policy_has_capability(policy, + QPOL_CAP_NEVERALLOW)) { + ERR(policy, "%s", "Cannot get xperms: Neverallow rules requested but not available"); + errno = ENOTSUP; + return STATUS_ERR; + } + + db = &policy->p->p; + + state = calloc(1, sizeof(avtab_state_t)); + if (state == NULL) { + ERR(policy, "%s", strerror(ENOMEM)); + errno = ENOMEM; + return STATUS_ERR; + } + + state->ucond_tab = &db->te_avtab; + state->cond_tab = &db->te_cond_avtab; + state->rule_type_mask = rule_type_mask; + state->node = db->te_avtab.htable[0]; + + if (qpol_iterator_create + (policy, state, avtab_state_get_cur, avtab_state_next, + avtab_state_end, avtab_state_size, free, iter)) { + free(state); + return STATUS_ERR; + } + if (state->node == NULL || + !(state->node->key.specified & state->rule_type_mask)) { + avtab_state_next(*iter); + } + + return STATUS_SUCCESS; +} + +int qpol_xprule_get_source_type(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + const qpol_type_t **source) +{ + policydb_t *db = NULL; + avtab_ptr_t xperm = NULL; + + if (source) + *source = NULL; + + if (!policy || !rule || !source) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + xperm = (avtab_ptr_t)rule; + + *source = (qpol_type_t *) + db->type_val_to_struct[xperm->key.source_type - 1]; + + return STATUS_SUCCESS; +} + +int qpol_xprule_get_target_type(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + const qpol_type_t **target) +{ + policydb_t *db = NULL; + avtab_ptr_t xperm = NULL; + + if (target) + *target = NULL; + + if (!policy || !rule || !target) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + xperm = (avtab_ptr_t)rule; + + *target = (qpol_type_t *) + db->type_val_to_struct[xperm->key.target_type - 1]; + + return STATUS_SUCCESS; +} + +int qpol_xprule_get_object_class(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + const qpol_class_t **obj_class) +{ + policydb_t *db = NULL; + avtab_ptr_t xperm = NULL; + + if (obj_class) + *obj_class = NULL; + + if (!policy || !rule || !obj_class) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + db = &policy->p->p; + xperm = (avtab_ptr_t)rule; + + *obj_class = (qpol_class_t *) + db->class_val_to_struct[xperm->key.target_class - 1]; + + return STATUS_SUCCESS; +} + +int qpol_xprule_get_command(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + const char **xprule_command) +{ + avtab_ptr_t xperm = NULL; + + if (xprule_command) + *xprule_command = NULL; + + if (!policy || !rule || !xprule_command) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + xperm = (avtab_ptr_t)rule; + + switch (xperm->datum.xperms->specified) { + case AVRULE_XPERMS_IOCTLFUNCTION: + case AVRULE_XPERMS_IOCTLDRIVER: + *xprule_command = "ioctl"; + break; + default: + return STATUS_ERR; + } + + return STATUS_SUCCESS; +} + +int qpol_xprule_get_xperm_string(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + char **xperm_string) +{ + avtab_ptr_t xperm = NULL; + + if (xperm_string) + *xperm_string = NULL; + + if (!policy || !rule || !xperm_string) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + xperm = (avtab_ptr_t)rule; + *xperm_string = sepol_extended_perms_to_string(xperm->datum.xperms); + + return STATUS_SUCCESS; +} + +int qpol_xprule_get_rule_type(const qpol_policy_t *policy, + const qpol_xprule_t *rule, + uint32_t *rule_type) +{ + avtab_ptr_t xperm = NULL; + + if (rule_type) + *rule_type = 0; + + if (!policy || !rule || !rule_type) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + xperm = (avtab_ptr_t)rule; + + *rule_type = (xperm->key.specified & ( + QPOL_RULE_ALLOWXPERM | + QPOL_RULE_NEVERALLOWXPERM | + QPOL_RULE_AUDITALLOWXPERM | + QPOL_RULE_DONTAUDITXPERM)); + + return STATUS_SUCCESS; +} diff --git a/setools/policyrep/qpol.i b/setools/policyrep/qpol.i index 300b296..a4a4d99 100644 --- a/setools/policyrep/qpol.i +++ b/setools/policyrep/qpol.i @@ -53,6 +53,8 @@ #include "include/qpol/type_query.h" #include "include/qpol/user_query.h" #include "include/qpol/util.h" +#include "include/qpol/xen_query.h" +#include "include/qpol/xprule_query.h" /* Provide hooks so that language-specific modules can define the * callback function, used by the handler in @@ -177,7 +179,8 @@ typedef enum qpol_capability QPOL_CAP_DEFAULT_TYPE, QPOL_CAP_PERMISSIVE, QPOL_CAP_FILENAME_TRANS, - QPOL_CAP_ROLETRANS + QPOL_CAP_ROLETRANS, + QPOL_CAP_XPERM_IOCTL } qpol_capability_e; %exception qpol_policy { $action @@ -224,6 +227,17 @@ typedef enum qpol_capability } }; + /* This is whether SELinux or XEN policy */ + const char *target_platform () { + int t; + (void)qpol_policy_get_target_platform(self, &t); + switch (t) { + case SEPOL_TARGET_SELINUX: return "selinux"; + case SEPOL_TARGET_XEN: return "xen"; + default: return "unknown"; + } + }; + int capability (qpol_capability_e cap) { return qpol_policy_has_capability(self, cap); }; @@ -766,6 +780,75 @@ typedef enum qpol_capability return 0; }; + %newobject xprule_iter(int); + %pythoncode %{ @QpolGenerator(_qpol.qpol_xprule_from_void) %} + qpol_iterator_t *xprule_iter() { + qpol_iterator_t *iter; + uint32_t rule_types = QPOL_RULE_ALLOWXPERM | QPOL_RULE_AUDITALLOWXPERM | QPOL_RULE_DONTAUDITXPERM; + + if (qpol_policy_has_capability(self, QPOL_CAP_NEVERALLOW)) + rule_types |= QPOL_RULE_NEVERALLOWXPERM; + + if (qpol_policy_get_xprule_iter(self, rule_types, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + return iter; + fail: + return NULL; + }; + + size_t xprule_allow_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_xprule_iter(self, QPOL_RULE_ALLOWXPERM, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + size_t xprule_auditallow_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_xprule_iter(self, QPOL_RULE_AUDITALLOWXPERM, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + size_t xprule_neverallow_count() { + if (qpol_policy_has_capability(self, QPOL_CAP_NEVERALLOW)) { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_xprule_iter(self, QPOL_RULE_NEVERALLOWXPERM, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + } else { + return 0; + } + fail: + return 0; + }; + + size_t xprule_dontaudit_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_xprule_iter(self, QPOL_RULE_DONTAUDITXPERM, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject terule_iter(int); %pythoncode %{ @QpolGenerator(_qpol.qpol_terule_from_void) %} qpol_iterator_t *terule_iter() { @@ -934,6 +1017,122 @@ typedef enum qpol_capability fail: return NULL; }; + + %newobject iomemcon_iter(); + %pythoncode %{ @QpolGenerator(_qpol.qpol_iomemcon_from_void) %} + qpol_iterator_t *iomemcon_iter() { + qpol_iterator_t *iter; + if (qpol_policy_get_iomemcon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + return iter; + fail: + return NULL; + }; + size_t iomemcon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_iomemcon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + %newobject ioportcon_iter(); + %pythoncode %{ @QpolGenerator(_qpol.qpol_ioportcon_from_void) %} + qpol_iterator_t *ioportcon_iter() { + qpol_iterator_t *iter; + if (qpol_policy_get_ioportcon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + return iter; + fail: + return NULL; + }; + + size_t ioportcon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_ioportcon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + %newobject pcidevicecon_iter(); + %pythoncode %{ @QpolGenerator(_qpol.qpol_pcidevicecon_from_void) %} + qpol_iterator_t *pcidevicecon_iter() { + qpol_iterator_t *iter; + if (qpol_policy_get_pcidevicecon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + return iter; + fail: + return NULL; + }; + size_t pcidevicecon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_pcidevicecon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + %newobject pirqcon_iter(); + %pythoncode %{ @QpolGenerator(_qpol.qpol_pirqcon_from_void) %} + qpol_iterator_t *pirqcon_iter() { + qpol_iterator_t *iter; + if (qpol_policy_get_pirqcon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + return iter; + fail: + return NULL; + }; + size_t pirqcon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_pirqcon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + %newobject devicetreecon_iter(); + %pythoncode %{ @QpolGenerator(_qpol.qpol_devicetreecon_from_void) %} + qpol_iterator_t *devicetreecon_iter() { + qpol_iterator_t *iter; + if (qpol_policy_get_devicetreecon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + return iter; + fail: + return NULL; + }; + size_t devicetreecon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_devicetreecon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; }; /* qpol iterator */ @@ -2566,6 +2765,85 @@ typedef struct qpol_avrule {} qpol_avrule_t; }; %} +/* qpol xperm rules */ +#define QPOL_RULE_ALLOWXPERM 0x0100 +#define QPOL_RULE_AUDITALLOWXPERM 0x0200 +#define QPOL_RULE_DONTAUDITXPERM 0x0400 +#define QPOL_RULE_NEVERALLOWXPERM 0x0800 + +typedef struct qpol_xprule {} qpol_xprule_t; +%extend qpol_xprule { + qpol_xprule() { + SWIG_exception(SWIG_RuntimeError, "Cannot directly create qpol_xprule_t objects"); + fail: + return NULL; + }; + ~qpol_xprule() { + /* no op */ + return; + }; + const char * rule_type(qpol_policy_t *p) { + uint32_t rt; + if (qpol_xprule_get_rule_type(p, self, &rt)) { + SWIG_exception(SWIG_ValueError, "Could not get rule type for xperm rule"); + } + switch (rt) { + case QPOL_RULE_ALLOWXPERM: return "allowxperm"; break; + case QPOL_RULE_NEVERALLOWXPERM: return "neverallowxperm"; break; + case QPOL_RULE_AUDITALLOWXPERM: return "auditallowxperm"; break; + case QPOL_RULE_DONTAUDITXPERM: return "dontauditxperm"; break; + } + fail: + return NULL; + }; + const qpol_type_t *source_type(qpol_policy_t *p) { + const qpol_type_t *t; + if (qpol_xprule_get_source_type(p, self, &t)) { + SWIG_exception(SWIG_ValueError, "Could not get source for xperm rule"); + } + fail: + return t; + }; + const qpol_type_t *target_type(qpol_policy_t *p) { + const qpol_type_t *t; + if (qpol_xprule_get_target_type(p, self, &t)) { + SWIG_exception(SWIG_ValueError, "Could not get target for xperm rule"); + } + fail: + return t; + }; + const qpol_class_t *object_class(qpol_policy_t *p) { + const qpol_class_t *cls; + if (qpol_xprule_get_object_class(p, self, &cls)) { + SWIG_exception(SWIG_ValueError, "Could not get class for xperm rule"); + } + fail: + return cls; + }; + /* This function gets the cmd (e.g. ioctl) and xperms via sepol_extended_perms_to_string() */ + char *xprule_xperm_string(qpol_policy_t *p) { + char *xprule_xperm_string = NULL; + if (qpol_xprule_get_xperm_string(p, self, &xprule_xperm_string)) { + SWIG_exception(SWIG_ValueError, "Could not get extended permissions for xperm rule"); + } + fail: + return xprule_xperm_string; + }; + const char *xprule_command(qpol_policy_t *p) { + const char *xprule_command = NULL; + if (qpol_xprule_get_command(p, self, &xprule_command)) { + SWIG_exception(SWIG_ValueError, "Could not get command for xperm rule"); + } + fail: + return xprule_command; + }; +}; +%inline %{ + qpol_xprule_t *qpol_xprule_from_void(void *x) { + return (qpol_xprule_t*)x; + }; +%} + /* qpol te rule */ #define QPOL_RULE_TYPE_TRANS 16 #define QPOL_RULE_TYPE_CHANGE 64 @@ -3061,3 +3339,197 @@ typedef struct qpol_default_object {} qpol_default_object_t; return (qpol_default_object_t*)x; }; %} + +/* qpol iomemcon */ +typedef struct qpol_iomemcon {} qpol_iomemcon_t; +%extend qpol_iomemcon { + qpol_iomemcon(qpol_policy_t *p, uint64_t low, uint64_t high) { + const qpol_iomemcon_t *qp; + if (qpol_policy_get_iomemcon_by_addr(p, low, high, &qp)) { + SWIG_exception(SWIG_RuntimeError, "iomemcon statement does not exist"); + } + fail: + return (qpol_iomemcon_t*)qp; + }; + ~qpol_iomemcon() { + /* no op */ + return; + }; + uint64_t low_addr(qpol_policy_t *p) { + uint64_t addr = 0; + if(qpol_iomemcon_get_low_addr(p, self, &addr)) { + SWIG_exception(SWIG_RuntimeError, "Could not get low addr for iomemcon statement"); + } + fail: + return addr; + }; + uint64_t high_addr(qpol_policy_t *p) { + uint64_t addr = 0; + if(qpol_iomemcon_get_high_addr(p, self, &addr)) { + SWIG_exception(SWIG_RuntimeError, "Could not get high addr for iomemcon statement"); + } + fail: + return addr; + }; + const qpol_context_t *context(qpol_policy_t *p) { + const qpol_context_t *ctx; + if (qpol_iomemcon_get_context(p, self, &ctx)) { + SWIG_exception(SWIG_ValueError, "Could not get context for iomemcon statement"); + } + fail: + return ctx; + }; +} +%inline %{ + qpol_iomemcon_t *qpol_iomemcon_from_void(void *x) { + return (qpol_iomemcon_t*)x; + }; +%} + +/* qpol ioportcon */ +typedef struct qpol_ioportcon {} qpol_ioportcon_t; +%extend qpol_ioportcon { + qpol_ioportcon(qpol_policy_t *p, uint32_t low, uint32_t high) { + const qpol_ioportcon_t *qp; + if (qpol_policy_get_ioportcon_by_port(p, low, high, &qp)) { + SWIG_exception(SWIG_RuntimeError, "ioportcon statement does not exist"); + } + fail: + return (qpol_ioportcon_t*)qp; + }; + ~qpol_ioportcon() { + /* no op */ + return; + }; + uint32_t low_port(qpol_policy_t *p) { + uint32_t port = 0; + if(qpol_ioportcon_get_low_port(p, self, &port)) { + SWIG_exception(SWIG_RuntimeError, "Could not get low port for ioportcon statement"); + } + fail: + return port; + }; + uint32_t high_port(qpol_policy_t *p) { + uint32_t port = 0; + if(qpol_ioportcon_get_high_port(p, self, &port)) { + SWIG_exception(SWIG_RuntimeError, "Could not get high port for ioportcon statement"); + } + fail: + return port; + }; + const qpol_context_t *context(qpol_policy_t *p) { + const qpol_context_t *ctx; + if (qpol_ioportcon_get_context(p, self, &ctx)) { + SWIG_exception(SWIG_ValueError, "Could not get context for ioportcon statement"); + } + fail: + return ctx; + }; +} +%inline %{ + qpol_ioportcon_t *qpol_ioportcon_from_void(void *x) { + return (qpol_ioportcon_t*)x; + }; +%} + +/* qpol pcidevicecon */ +typedef struct qpol_pcidevicecon {} qpol_pcidevicecon_t; +%extend qpol_pcidevicecon { + qpol_pcidevicecon() { + SWIG_exception(SWIG_RuntimeError, "pcidevicecon statement does not exist"); + fail: + return NULL; + }; + ~qpol_pcidevicecon() { + return; + }; + uint32_t device(qpol_policy_t *p) { + uint32_t device = 0; + if(qpol_pcidevicecon_get_device(p, self, &device)) { + SWIG_exception(SWIG_RuntimeError, "Could not get device for pcidevicecon statement"); + } + fail: + return device; + }; + const qpol_context_t *context(qpol_policy_t *p) { + const qpol_context_t *ctx; + if (qpol_pcidevicecon_get_context(p, self, &ctx)) { + SWIG_exception(SWIG_ValueError, "Could not get context for pcidevicecon statement"); + } + fail: + return ctx; + }; +} +%inline %{ + qpol_pcidevicecon_t *qpol_pcidevicecon_from_void(void *x) { + return (qpol_pcidevicecon_t*)x; + }; +%} + +/* qpol pirqcon */ +typedef struct qpol_pirqcon {} qpol_pirqcon_t; +%extend qpol_pirqcon { + qpol_pirqcon() { + SWIG_exception(SWIG_RuntimeError, "pirqcon statement does not exist"); + fail: + return NULL; + }; + ~qpol_pirqcon() { + return; + }; + uint32_t irq(qpol_policy_t *p) { + uint16_t irq = 0; + if(qpol_pirqcon_get_irq(p, self, &irq)) { + SWIG_exception(SWIG_RuntimeError, "Could not get irq for pirqcon statement"); + } + fail: + return irq; + }; + const qpol_context_t *context(qpol_policy_t *p) { + const qpol_context_t *ctx; + if (qpol_pirqcon_get_context(p, self, &ctx)) { + SWIG_exception(SWIG_ValueError, "Could not get context for pirqcon statement"); + } + fail: + return ctx; + }; +} +%inline %{ + qpol_pirqcon_t *qpol_pirqcon_from_void(void *x) { + return (qpol_pirqcon_t*)x; + }; +%} + +/* qpol devicetreecon */ +typedef struct qpol_devicetreecon {} qpol_devicetreecon_t; +%extend qpol_devicetreecon { + qpol_devicetreecon() { + + SWIG_exception(SWIG_RuntimeError, "devicetreecon statement does not exist"); + + fail: + return NULL; + }; + char *path(qpol_policy_t *p) { + char *path = NULL; + if(qpol_devicetreecon_get_path(p, self, &path)) { + SWIG_exception(SWIG_RuntimeError, "Could not get path for devicetreecon statement"); + } + fail: + return path; + }; + const qpol_context_t *context(qpol_policy_t *p) { + const qpol_context_t *ctx; + if (qpol_devicetreecon_get_context(p, self, &ctx)) { + SWIG_exception(SWIG_ValueError, "Could not get context for devicetreecon statement"); + } + fail: + return ctx; + }; +} +%inline %{ + qpol_devicetreecon_t *qpol_devicetreecon_from_void(void *x) { + return (qpol_devicetreecon_t*)x; + }; +%} + diff --git a/setup.py b/setup.py index d81821b..606f846 100644 --- a/setup.py +++ b/setup.py @@ -104,7 +104,9 @@ ext_py_mods = [Extension('setools.policyrep._qpol', 'libqpol/user_query.c', 'libqpol/util.c', 'libqpol/policy_parse.c', - 'libqpol/policy_scan.c'], + 'libqpol/policy_scan.c', + 'libqpol/xen_query.c', + 'libqpol/xprule_query.c'], include_dirs=['libqpol', 'libqpol/include'], libraries=['bz2', 'selinux', 'sepol'], extra_compile_args=['-Werror', '-Wextra',