direct-io.hg

changeset 7507:7ba4019f7b2d

This patch

* adapts the Xen access control module to recent changes in the "unbound
event channel" interface and its usage
* adds checks that became necessary because of domain structures "hanging
around" in the domain list after domain destruction

This patch is tested on today's xen-unstable with Null, CHWALL, STE,
CHWALL_STE policies.

Signed-off by: Reiner Sailer <sailer@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Oct 27 17:24:06 2005 +0100 (2005-10-27)
parents 897adc98fec2
children d6ebcfc5a30b
files xen/acm/acm_simple_type_enforcement_hooks.c xen/common/acm_ops.c xen/include/acm/acm_hooks.h
line diff
     1.1 --- a/xen/acm/acm_simple_type_enforcement_hooks.c	Thu Oct 27 17:20:33 2005 +0100
     1.2 +++ b/xen/acm/acm_simple_type_enforcement_hooks.c	Thu Oct 27 17:24:06 2005 +0100
     1.3 @@ -392,8 +392,11 @@ check_cache(struct domain *dom, domid_t 
     1.4      int i;
     1.5  
     1.6      printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
     1.7 +
     1.8 +    if (dom->ssid == NULL)
     1.9 +        return 0;
    1.10      ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
    1.11 -                         (struct acm_ssid_domain *)(dom)->ssid);
    1.12 +                         (struct acm_ssid_domain *)(dom->ssid));
    1.13  
    1.14      for(i=0; i< ACM_TE_CACHE_SIZE; i++) {
    1.15          if ((ste_ssid->ste_cache[i].valid == VALID) &&
    1.16 @@ -412,6 +415,8 @@ cache_result(struct domain *subj, struct
    1.17      struct ste_ssid *ste_ssid;
    1.18      int i;
    1.19      printkd("caching from doms: %x --> %x.\n", subj->domain_id, obj->domain_id);
    1.20 +    if (subj->ssid == NULL)
    1.21 +        return;
    1.22      ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
    1.23                           (struct acm_ssid_domain *)(subj)->ssid);
    1.24      for(i=0; i< ACM_TE_CACHE_SIZE; i++)
    1.25 @@ -431,26 +436,34 @@ clean_id_from_cache(domid_t id)
    1.26      struct ste_ssid *ste_ssid;
    1.27      int i;
    1.28      struct domain **pd;
    1.29 +    struct acm_ssid_domain *ssid;
    1.30  
    1.31      printkd("deleting cache for dom %x.\n", id);
    1.32 -
    1.33      read_lock(&domlist_lock); /* look through caches of all domains */
    1.34      pd = &domain_list;
    1.35      for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
    1.36 -        ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 
    1.37 -                             (struct acm_ssid_domain *)(*pd)->ssid);
    1.38 +        ssid = (struct acm_ssid_domain *)((*pd)->ssid);
    1.39 +
    1.40 +        if (ssid == NULL)
    1.41 +            continue; /* hanging domain structure, no ssid any more ... */
    1.42 +        ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssid);
    1.43 +        if (!ste_ssid) {
    1.44 +            printk("%s: deleting ID from cache ERROR (no ste_ssid)!\n",
    1.45 +                   __func__);
    1.46 +            goto out;
    1.47 +        }
    1.48          for (i=0; i<ACM_TE_CACHE_SIZE; i++)
    1.49              if ((ste_ssid->ste_cache[i].valid == VALID) &&
    1.50 -                (ste_ssid->ste_cache[i].id = id))
    1.51 +                (ste_ssid->ste_cache[i].id == id))
    1.52                  ste_ssid->ste_cache[i].valid = FREE;
    1.53      }
    1.54 + out:
    1.55      read_unlock(&domlist_lock);
    1.56  }
    1.57  
    1.58  /***************************
    1.59   * Authorization functions
    1.60   **************************/
    1.61 -
    1.62  static int 
    1.63  ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
    1.64  {      
    1.65 @@ -484,44 +497,13 @@ ste_post_domain_destroy(void *subject_ss
    1.66  
    1.67  /* -------- EVENTCHANNEL OPERATIONS -----------*/
    1.68  static int
    1.69 -ste_pre_eventchannel_unbound(domid_t id) {
    1.70 -    struct domain *subj, *obj;
    1.71 -    int ret;
    1.72 -    traceprintk("%s: dom%x-->dom%x.\n", 
    1.73 -                __func__, current->domain->domain_id, id);
    1.74 -
    1.75 -    if (check_cache(current->domain, id)) {
    1.76 -        atomic_inc(&ste_bin_pol.ec_cachehit_count);
    1.77 -        return ACM_ACCESS_PERMITTED;
    1.78 -    }
    1.79 -    atomic_inc(&ste_bin_pol.ec_eval_count);
    1.80 -    subj = current->domain;
    1.81 -    obj = find_domain_by_id(id);
    1.82 -
    1.83 -    if (share_common_type(subj, obj)) {
    1.84 -        cache_result(subj, obj);
    1.85 -        ret = ACM_ACCESS_PERMITTED;
    1.86 -    } else {
    1.87 -        atomic_inc(&ste_bin_pol.ec_denied_count); 
    1.88 -        ret = ACM_ACCESS_DENIED; 
    1.89 -    }
    1.90 -    if (obj != NULL)
    1.91 -        put_domain(obj);
    1.92 -    return ret;
    1.93 -}
    1.94 -
    1.95 -static int
    1.96 -ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
    1.97 -{
    1.98 +ste_pre_eventchannel_unbound(domid_t id1, domid_t id2) {
    1.99      struct domain *subj, *obj;
   1.100      int ret;
   1.101      traceprintk("%s: dom%x-->dom%x.\n", __func__,
   1.102                  (id1 == DOMID_SELF) ? current->domain->domain_id : id1,
   1.103                  (id2 == DOMID_SELF) ? current->domain->domain_id : id2);
   1.104  
   1.105 -    /* following is a bit longer but ensures that we
   1.106 -     * "put" only domains that we where "find"-ing 
   1.107 -     */
   1.108      if (id1 == DOMID_SELF) id1 = current->domain->domain_id;
   1.109      if (id2 == DOMID_SELF) id2 = current->domain->domain_id;
   1.110  
   1.111 @@ -531,7 +513,7 @@ ste_pre_eventchannel_interdomain(domid_t
   1.112          ret = ACM_ACCESS_DENIED;
   1.113          goto out;
   1.114      }
   1.115 -    /* cache check late, but evtchn is not on performance critical path */
   1.116 +    /* cache check late */
   1.117      if (check_cache(subj, obj->domain_id)) {
   1.118          atomic_inc(&ste_bin_pol.ec_cachehit_count);
   1.119          ret = ACM_ACCESS_PERMITTED;
   1.120 @@ -546,7 +528,7 @@ ste_pre_eventchannel_interdomain(domid_t
   1.121          atomic_inc(&ste_bin_pol.ec_denied_count); 
   1.122          ret = ACM_ACCESS_DENIED; 
   1.123      }
   1.124 - out:
   1.125 +  out:
   1.126      if (obj != NULL)
   1.127          put_domain(obj);
   1.128      if (subj != NULL)
   1.129 @@ -554,6 +536,50 @@ ste_pre_eventchannel_interdomain(domid_t
   1.130      return ret;
   1.131  }
   1.132  
   1.133 +static int
   1.134 +ste_pre_eventchannel_interdomain(domid_t id)
   1.135 +{
   1.136 +    struct domain *subj=NULL, *obj=NULL;
   1.137 +    int ret;
   1.138 +
   1.139 +    traceprintk("%s: dom%x-->dom%x.\n", __func__,
   1.140 +                current->domain->domain_id,
   1.141 +                (id == DOMID_SELF) ? current->domain->domain_id : id);
   1.142 +
   1.143 +    /* following is a bit longer but ensures that we
   1.144 +     * "put" only domains that we where "find"-ing 
   1.145 +     */
   1.146 +    if (id == DOMID_SELF) id = current->domain->domain_id;
   1.147 +
   1.148 +    subj = current->domain;
   1.149 +    obj  = find_domain_by_id(id);
   1.150 +    if (obj == NULL) {
   1.151 +        ret = ACM_ACCESS_DENIED;
   1.152 +        goto out;
   1.153 +    }
   1.154 +
   1.155 +    /* cache check late, but evtchn is not on performance critical path */
   1.156 +    if (check_cache(subj, obj->domain_id)) {
   1.157 +        atomic_inc(&ste_bin_pol.ec_cachehit_count);
   1.158 +        ret = ACM_ACCESS_PERMITTED;
   1.159 +        goto out;
   1.160 +    }
   1.161 +
   1.162 +    atomic_inc(&ste_bin_pol.ec_eval_count);
   1.163 +
   1.164 +    if (share_common_type(subj, obj)) {
   1.165 +        cache_result(subj, obj);
   1.166 +        ret = ACM_ACCESS_PERMITTED;
   1.167 +    } else {
   1.168 +        atomic_inc(&ste_bin_pol.ec_denied_count); 
   1.169 +        ret = ACM_ACCESS_DENIED; 
   1.170 +    }
   1.171 + out:
   1.172 +    if (obj != NULL)
   1.173 +        put_domain(obj);
   1.174 +    return ret;
   1.175 +}
   1.176 +
   1.177  /* -------- SHARED MEMORY OPERATIONS -----------*/
   1.178  
   1.179  static int
     2.1 --- a/xen/common/acm_ops.c	Thu Oct 27 17:20:33 2005 +0100
     2.2 +++ b/xen/common/acm_ops.c	Thu Oct 27 17:24:06 2005 +0100
     2.3 @@ -133,7 +133,10 @@ long do_acm_op(struct acm_op * u_acm_op)
     2.4              struct domain *subj = find_domain_by_id(op->u.getssid.id.domainid);
     2.5              if (!subj)
     2.6                  return -ESRCH; /* domain not found */
     2.7 -
     2.8 +            if (subj->ssid == NULL) {
     2.9 +                put_domain(subj);
    2.10 +                return -ESRCH;
    2.11 +            }
    2.12              ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
    2.13              put_domain(subj);
    2.14          } else
    2.15 @@ -167,6 +170,10 @@ long do_acm_op(struct acm_op * u_acm_op)
    2.16                  ret = -ESRCH; /* domain not found */
    2.17                  goto out;
    2.18              }
    2.19 +            if (subj->ssid == NULL) {
    2.20 +                put_domain(subj);
    2.21 +                ret = -ESRCH;
    2.22 +            }
    2.23              ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
    2.24              put_domain(subj);
    2.25          } else {
    2.26 @@ -182,6 +189,10 @@ long do_acm_op(struct acm_op * u_acm_op)
    2.27                  ret = -ESRCH; /* domain not found */
    2.28                  goto out;
    2.29              }
    2.30 +            if (subj->ssid == NULL) {
    2.31 +                put_domain(subj);
    2.32 +                return -ESRCH;
    2.33 +            }
    2.34              ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
    2.35              put_domain(subj);
    2.36          } else {
     3.1 --- a/xen/include/acm/acm_hooks.h	Thu Oct 27 17:20:33 2005 +0100
     3.2 +++ b/xen/include/acm/acm_hooks.h	Thu Oct 27 17:24:06 2005 +0100
     3.3 @@ -100,10 +100,10 @@ struct acm_operations {
     3.4      void (*fail_domain_create)         (void *subject_ssid, ssidref_t ssidref);
     3.5      void (*post_domain_destroy)        (void *object_ssid, domid_t id);
     3.6      /* event channel control hooks  (can be NULL) */
     3.7 -    int  (*pre_eventchannel_unbound)      (domid_t id);
     3.8 -    void (*fail_eventchannel_unbound)     (domid_t id);
     3.9 -    int  (*pre_eventchannel_interdomain)  (domid_t id1, domid_t id2);
    3.10 -    int  (*fail_eventchannel_interdomain) (domid_t id1, domid_t id2);
    3.11 +    int  (*pre_eventchannel_unbound)      (domid_t id1, domid_t id2);
    3.12 +    void (*fail_eventchannel_unbound)     (domid_t id1, domid_t id2);
    3.13 +    int  (*pre_eventchannel_interdomain)  (domid_t id);
    3.14 +    void (*fail_eventchannel_interdomain) (domid_t id);
    3.15      /* grant table control hooks (can be NULL)  */
    3.16      int  (*pre_grant_map_ref)          (domid_t id);
    3.17      void (*fail_grant_map_ref)         (domid_t id);
    3.18 @@ -193,31 +193,31 @@ static inline void acm_post_domain_destr
    3.19      return;
    3.20  }
    3.21  
    3.22 -static inline int acm_pre_eventchannel_unbound(domid_t id)
    3.23 +static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2)
    3.24  {
    3.25      if ((acm_primary_ops->pre_eventchannel_unbound != NULL) && 
    3.26 -        acm_primary_ops->pre_eventchannel_unbound(id))
    3.27 +        acm_primary_ops->pre_eventchannel_unbound(id1, id2))
    3.28          return ACM_ACCESS_DENIED;
    3.29      else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) && 
    3.30 -             acm_secondary_ops->pre_eventchannel_unbound(id)) {
    3.31 +             acm_secondary_ops->pre_eventchannel_unbound(id1, id2)) {
    3.32          /* roll-back primary */
    3.33          if (acm_primary_ops->fail_eventchannel_unbound != NULL)
    3.34 -            acm_primary_ops->fail_eventchannel_unbound(id);
    3.35 +            acm_primary_ops->fail_eventchannel_unbound(id1, id2);
    3.36          return ACM_ACCESS_DENIED;
    3.37      } else
    3.38          return ACM_ACCESS_PERMITTED;
    3.39  }
    3.40  
    3.41 -static inline int acm_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
    3.42 +static inline int acm_pre_eventchannel_interdomain(domid_t id)
    3.43  {
    3.44      if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) &&
    3.45 -        acm_primary_ops->pre_eventchannel_interdomain(id1, id2))
    3.46 +        acm_primary_ops->pre_eventchannel_interdomain(id))
    3.47          return ACM_ACCESS_DENIED;
    3.48      else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) &&
    3.49 -             acm_secondary_ops->pre_eventchannel_interdomain(id1, id2)) {
    3.50 +             acm_secondary_ops->pre_eventchannel_interdomain(id)) {
    3.51          /* roll-back primary */
    3.52          if (acm_primary_ops->fail_eventchannel_interdomain != NULL)
    3.53 -            acm_primary_ops->fail_eventchannel_interdomain(id1, id2);
    3.54 +            acm_primary_ops->fail_eventchannel_interdomain(id);
    3.55          return ACM_ACCESS_DENIED;
    3.56      } else
    3.57          return ACM_ACCESS_PERMITTED;
    3.58 @@ -234,10 +234,22 @@ static inline int acm_pre_dom0_op(dom0_o
    3.59              current->domain->ssid, op->u.createdomain.ssidref);
    3.60          break;
    3.61      case DOM0_DESTROYDOMAIN:
    3.62 +        if (*ssid != NULL) {
    3.63 +            printkd("%s: Warning. Overlapping destruction.\n", 
    3.64 +                    __func__);
    3.65 +            return -EACCES;
    3.66 +        }
    3.67          d = find_domain_by_id(op->u.destroydomain.domain);
    3.68          if (d != NULL) {
    3.69              *ssid = d->ssid; /* save for post destroy when d is gone */
    3.70 -            /* no policy-specific hook */
    3.71 +            if (*ssid == NULL) {
    3.72 +                printk("%s: Warning. Destroying domain without ssid pointer.\n", 
    3.73 +                       __func__);
    3.74 +                put_domain(d);
    3.75 +                return -EACCES;
    3.76 +            }
    3.77 +            d->ssid = NULL; /* make sure it's not used any more */
    3.78 +             /* no policy-specific hook */
    3.79              put_domain(d);
    3.80              ret = 0;
    3.81          }
    3.82 @@ -248,7 +260,7 @@ static inline int acm_pre_dom0_op(dom0_o
    3.83      return ret;
    3.84  }
    3.85  
    3.86 -static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid) 
    3.87 +static inline void acm_post_dom0_op(dom0_op_t *op, void **ssid)
    3.88  {
    3.89      switch(op->cmd) {
    3.90      case DOM0_CREATEDOMAIN:
    3.91 @@ -261,7 +273,8 @@ static inline void acm_post_dom0_op(dom0
    3.92      case DOM0_DESTROYDOMAIN:
    3.93          acm_post_domain_destroy(ssid, op->u.destroydomain.domain);
    3.94          /* free security ssid for the destroyed domain (also if null policy */
    3.95 -        acm_free_domain_ssid((struct acm_ssid_domain *)ssid);
    3.96 +        acm_free_domain_ssid((struct acm_ssid_domain *)(*ssid));
    3.97 +        *ssid = NULL;
    3.98          break;
    3.99      }
   3.100  }
   3.101 @@ -282,12 +295,13 @@ static inline int acm_pre_event_channel(
   3.102  
   3.103      switch(op->cmd) {
   3.104      case EVTCHNOP_alloc_unbound:
   3.105 -        ret = acm_pre_eventchannel_unbound(op->u.alloc_unbound.dom);
   3.106 +        ret = acm_pre_eventchannel_unbound(
   3.107 +                  op->u.alloc_unbound.dom,
   3.108 +                  op->u.alloc_unbound.remote_dom);
   3.109          break;
   3.110      case EVTCHNOP_bind_interdomain:
   3.111          ret = acm_pre_eventchannel_interdomain(
   3.112 -            current->domain->domain_id,
   3.113 -            op->u.bind_interdomain.remote_dom);
   3.114 +                  op->u.bind_interdomain.remote_dom);
   3.115          break;
   3.116      default:
   3.117          ret = 0; /* ok */