On Mon, 2017-05-15 at 23:42 +0300, Dan Jurgens wrote:
> From: Daniel Jurgens
>
> Add checkpolicy support for scanning and parsing ibpkeycon labels.
> Also
> create a new ocontext for Infiniband Pkeys and define a new policydb
> version for infiniband support.
>
> Signed-off-by: Daniel Jurgens
>
> ---
> v1:
> Stephen Smalley:
> - Always use s6_addr instead of s6_addr32.
> - Add comment about POLICYDB_VERSION_INFINIBAND being linux specific.
>
> Signed-off-by: Daniel Jurgens
> ---
> checkpolicy/policy_define.c| 105
> +
> checkpolicy/policy_define.h| 1 +
> checkpolicy/policy_parse.y | 15 -
> checkpolicy/policy_scan.l | 3 +
> libsepol/include/sepol/policydb/policydb.h | 32 +
> 5 files changed, 143 insertions(+), 13 deletions(-)
>
> diff --git a/checkpolicy/policy_define.c
> b/checkpolicy/policy_define.c
> index 8fab214..ffdc5f8 100644
> --- a/checkpolicy/policy_define.c
> +++ b/checkpolicy/policy_define.c
> @@ -20,6 +20,7 @@
> * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
> * Copyright (C) 2003 - 2008 Tresys Technology, LLC
> * Copyright (C) 2007 Red Hat Inc.
> + * Copyright (C) 2017 Mellanox Techonologies Inc.
> * 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.
> @@ -5057,6 +5058,110 @@ int define_port_context(unsigned int low,
> unsigned int high)
> return -1;
> }
>
> +int define_ibpkey_context(unsigned int low, unsigned int high)
> +{
> + ocontext_t *newc, *c, *l, *head;
> + struct in6_addr subnet_prefix;
> + char *id;
> + int rc = 0;
> +
> + if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
> + yyerror("ibpkeycon not supported for target");
> + return -1;
> + }
> +
> + if (pass == 1) {
> + id = (char *)queue_remove(id_queue);
> + free(id);
> + parse_security_context(NULL);
> + return 0;
> + }
> +
> + newc = malloc(sizeof(*newc));
> + if (!newc) {
> + yyerror("out of memory");
> + return -1;
> + }
> + memset(newc, 0, sizeof(*newc));
> +
> + id = queue_remove(id_queue);
> + if (!id) {
> + yyerror("failed to read the subnet prefix");
> + rc = -1;
> + goto out;
> + }
> +
> + rc = inet_pton(AF_INET6, id, &subnet_prefix);
> + free(id);
> + if (rc < 1) {
> + yyerror("failed to parse the subnet prefix");
> + if (rc == 0)
> + rc = -1;
> + goto out;
> + }
> +
> + if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) {
> + yyerror("subnet prefix should be 0's in the low
> order 64 bits.");
> + rc = -1;
> + goto out;
> + }
> +
> + memcpy(&newc->u.ibpkey.subnet_prefix[0],
> &subnet_prefix.s6_addr[0],
> + sizeof(newc->u.ibpkey.subnet_prefix));
> +
> + newc->u.ibpkey.low_pkey = low;
> + newc->u.ibpkey.high_pkey = high;
Kernel patch also rejects low or high > 0x, so we likely ought to
do the same here?
> +
> + if (low > high) {
> + yyerror2("low pkey %d exceeds high pkey %d", low,
> high);
> + rc = -1;
> + goto out;
> + }
> +
> + rc = parse_security_context(&newc->context[0]);
> + if (rc)
> + goto out;
> +
> + /* Preserve the matching order specified in the
> configuration. */
> + head = policydbp->ocontexts[OCON_IBPKEY];
> + for (l = NULL, c = head; c; l = c, c = c->next) {
> + unsigned int low2, high2;
> +
> + low2 = c->u.ibpkey.low_pkey;
> + high2 = c->u.ibpkey.high_pkey;
> +
> + if (low == low2 && high == high2 &&
> + !memcmp(&c->u.ibpkey.subnet_prefix[0],
> + &newc->u.ibpkey.subnet_prefix[0],
> + sizeof(c->u.ibpkey.subnet_prefix))) {
> + yyerror2("duplicate ibpkeycon entry for %d-
> %d ",
> + low, high);
> + rc = -1;
> + goto out;
> + }
> + if (low2 <= low && high2 >= high &&
> + !memcmp(&c->u.ibpkey.subnet_prefix[0],
> + &newc->u.ibpkey.subnet_prefix[0],
> + sizeof(c->u.ibpkey.subnet_prefix))) {
> + yyerror2("ibpkeycon entry for %d-%d hidden
> by earlier entry for %d-%d",
> + low, high, low2, high2);
> + rc = -1;
> + goto out;
> + }
> + }
> +
> + if (l)
> + l->next = newc;
> + else
> + policydbp->ocontexts[OCON_IBPKEY] = newc;
> +
> + return 0;
> +
> +out:
> + free(newc);