debuggers.hg

changeset 20964:a3fa6d444b25

Fix domain reference leaks

Besides two unlikely/rarely hit ones in x86 code, the main offender
was tmh_client_from_cli_id(), which didn't even have a counterpart
(albeit it had a comment correctly saying that it causes d->refcnt to
get incremented). Unfortunately(?) this required a bit of code
restructuring (as I needed to change the code anyway, I also fixed
a couple os missing bounds checks which would sooner or later be
reported as security vulnerabilities), so I would hope Dan could give
it his blessing before it gets applied.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 10 09:18:43 2010 +0000 (2010-02-10)
parents da7ae6d8838a
children 10a54ab63607
files xen/arch/x86/debug.c xen/arch/x86/mm.c xen/common/tmem.c xen/common/tmem_xen.c xen/include/xen/tmem_xen.h
line diff
     1.1 --- a/xen/arch/x86/debug.c	Wed Feb 10 09:18:11 2010 +0000
     1.2 +++ b/xen/arch/x86/debug.c	Wed Feb 10 09:18:43 2010 +0000
     1.3 @@ -252,10 +252,11 @@ dbg_rw_mem(dbgva_t addr, dbgbyte_t *buf,
     1.4          else
     1.5              len = __copy_from_user(buf, (void *)addr, len);
     1.6      }
     1.7 -    else
     1.8 +    else if ( dp )
     1.9      {
    1.10 -        if ( dp && !dp->is_dying )   /* make sure guest is still there */
    1.11 +        if ( !dp->is_dying )   /* make sure guest is still there */
    1.12              len= dbg_rw_guest_mem(addr, buf, len, dp, toaddr, pgd3);
    1.13 +        put_domain(dp);
    1.14      }
    1.15  
    1.16      DBGP2("gmem:exit:len:$%d\n", len);
     2.1 --- a/xen/arch/x86/mm.c	Wed Feb 10 09:18:11 2010 +0000
     2.2 +++ b/xen/arch/x86/mm.c	Wed Feb 10 09:18:43 2010 +0000
     2.3 @@ -3803,6 +3803,7 @@ int steal_page(
     2.4      struct domain *d, struct page_info *page, unsigned int memflags)
     2.5  {
     2.6      unsigned long x, y;
     2.7 +    bool_t drop_dom_ref = 0;
     2.8  
     2.9      spin_lock(&d->page_alloc_lock);
    2.10  
    2.11 @@ -3830,11 +3831,13 @@ int steal_page(
    2.12      } while ( (y = cmpxchg(&page->count_info, x, x | 1)) != x );
    2.13  
    2.14      /* Unlink from original owner. */
    2.15 -    if ( !(memflags & MEMF_no_refcount) )
    2.16 -        d->tot_pages--;
    2.17 +    if ( !(memflags & MEMF_no_refcount) && !--d->tot_pages )
    2.18 +        drop_dom_ref = 1;
    2.19      page_list_del(page, &d->page_list);
    2.20  
    2.21      spin_unlock(&d->page_alloc_lock);
    2.22 +    if ( unlikely(drop_dom_ref) )
    2.23 +        put_domain(d);
    2.24      return 0;
    2.25  
    2.26   fail:
     3.1 --- a/xen/common/tmem.c	Wed Feb 10 09:18:11 2010 +0000
     3.2 +++ b/xen/common/tmem.c	Wed Feb 10 09:18:43 2010 +0000
     3.3 @@ -912,14 +912,14 @@ static client_t *client_create(cli_id_t 
     3.4          return NULL;
     3.5      }
     3.6      memset(client,0,sizeof(client_t));
     3.7 -    if ( (client->tmh = tmh_client_init()) == NULL )
     3.8 +    if ( (client->tmh = tmh_client_init(cli_id)) == NULL )
     3.9      {
    3.10          printk("failed... can't allocate host-dependent part of client\n");
    3.11          if ( client )
    3.12              tmh_free_infra(client);
    3.13          return NULL;
    3.14      }
    3.15 -    tmh_set_client_from_id(client,cli_id);
    3.16 +    tmh_set_client_from_id(client, client->tmh, cli_id);
    3.17      client->cli_id = cli_id;
    3.18  #ifdef __i386__
    3.19      client->compress = 0;
    3.20 @@ -1528,7 +1528,7 @@ static NOINLINE int do_tmem_destroy_pool
    3.21  }
    3.22  
    3.23  static NOINLINE int do_tmem_new_pool(cli_id_t this_cli_id,
    3.24 -                                     uint32_t this_pool_id, uint32_t flags,
    3.25 +                                     uint32_t d_poolid, uint32_t flags,
    3.26                                       uint64_t uuid_lo, uint64_t uuid_hi)
    3.27  {
    3.28      client_t *client;
    3.29 @@ -1540,19 +1540,13 @@ static NOINLINE int do_tmem_new_pool(cli
    3.30      int specversion = (flags >> TMEM_POOL_VERSION_SHIFT)
    3.31           & TMEM_POOL_VERSION_MASK;
    3.32      pool_t *pool, *shpool;
    3.33 -    int s_poolid, d_poolid, first_unused_s_poolid;
    3.34 +    int s_poolid, first_unused_s_poolid;
    3.35      int i;
    3.36  
    3.37      if ( this_cli_id == CLI_ID_NULL )
    3.38 -    {
    3.39 -        client = tmh_client_from_current();
    3.40          cli_id = tmh_get_cli_id_from_current();
    3.41 -    } else {
    3.42 -        if ( (client = tmh_client_from_cli_id(this_cli_id)) == NULL)
    3.43 -            return -EPERM;
    3.44 +    else
    3.45          cli_id = this_cli_id;
    3.46 -    }
    3.47 -    ASSERT(client != NULL);
    3.48      printk("tmem: allocating %s-%s tmem pool for %s=%d...",
    3.49          persistent ? "persistent" : "ephemeral" ,
    3.50          shared ? "shared" : "private", cli_id_str, cli_id);
    3.51 @@ -1573,19 +1567,24 @@ static NOINLINE int do_tmem_new_pool(cli
    3.52      }
    3.53      if ( this_cli_id != CLI_ID_NULL )
    3.54      {
    3.55 -        d_poolid = this_pool_id;
    3.56 -        if ( client->pools[d_poolid] != NULL )
    3.57 -            return -EPERM;
    3.58 -        d_poolid = this_pool_id;
    3.59 +        if ( (client = tmh_client_from_cli_id(this_cli_id)) == NULL
    3.60 +             || d_poolid >= MAX_POOLS_PER_DOMAIN
    3.61 +             || client->pools[d_poolid] != NULL )
    3.62 +            goto fail;
    3.63      }
    3.64 -    else for ( d_poolid = 0; d_poolid < MAX_POOLS_PER_DOMAIN; d_poolid++ )
    3.65 -        if ( client->pools[d_poolid] == NULL )
    3.66 -            break;
    3.67 -    if ( d_poolid >= MAX_POOLS_PER_DOMAIN )
    3.68 +    else
    3.69      {
    3.70 -        printk("failed... no more pool slots available for this %s\n",
    3.71 -            client_str);
    3.72 -        goto fail;
    3.73 +        client = tmh_client_from_current();
    3.74 +        ASSERT(client != NULL);
    3.75 +        for ( d_poolid = 0; d_poolid < MAX_POOLS_PER_DOMAIN; d_poolid++ )
    3.76 +            if ( client->pools[d_poolid] == NULL )
    3.77 +                break;
    3.78 +        if ( d_poolid >= MAX_POOLS_PER_DOMAIN )
    3.79 +        {
    3.80 +            printk("failed... no more pool slots available for this %s\n",
    3.81 +                   client_str);
    3.82 +            goto fail;
    3.83 +        }
    3.84      }
    3.85      if ( shared )
    3.86      {
    3.87 @@ -1618,6 +1617,8 @@ static NOINLINE int do_tmem_new_pool(cli
    3.88                      client->pools[d_poolid] = global_shared_pools[s_poolid];
    3.89                      shared_pool_join(global_shared_pools[s_poolid], client);
    3.90                      pool_free(pool);
    3.91 +                    if ( this_cli_id != CLI_ID_NULL )
    3.92 +                        tmh_client_put(client->tmh);
    3.93                      return d_poolid;
    3.94                  }
    3.95              }
    3.96 @@ -1638,6 +1639,8 @@ static NOINLINE int do_tmem_new_pool(cli
    3.97          }
    3.98      }
    3.99      client->pools[d_poolid] = pool;
   3.100 +    if ( this_cli_id != CLI_ID_NULL )
   3.101 +        tmh_client_put(client->tmh);
   3.102      list_add_tail(&pool->pool_list, &global_pool_list);
   3.103      pool->pool_id = d_poolid;
   3.104      pool->persistent = persistent;
   3.105 @@ -1647,6 +1650,8 @@ static NOINLINE int do_tmem_new_pool(cli
   3.106  
   3.107  fail:
   3.108      pool_free(pool);
   3.109 +    if ( this_cli_id != CLI_ID_NULL )
   3.110 +        tmh_client_put(client->tmh);
   3.111      return -EPERM;
   3.112  }
   3.113  
   3.114 @@ -1672,6 +1677,7 @@ static int tmemc_freeze_pools(cli_id_t c
   3.115          if ( (client = tmh_client_from_cli_id(cli_id)) == NULL)
   3.116              return -1;
   3.117          client_freeze(client,freeze);
   3.118 +        tmh_client_put(client->tmh);
   3.119          printk("tmem: all pools %s for %s=%d\n",s,cli_id_str,cli_id);
   3.120      }
   3.121      return 0;
   3.122 @@ -1876,8 +1882,10 @@ static int tmemc_list(cli_id_t cli_id, t
   3.123      }
   3.124      else if ( (client = tmh_client_from_cli_id(cli_id)) == NULL)
   3.125          return -1;
   3.126 -    else
   3.127 +    else {
   3.128          off = tmemc_list_client(client, buf, 0, len, use_long);
   3.129 +        tmh_client_put(client->tmh);
   3.130 +    }
   3.131  
   3.132      return 0;
   3.133  }
   3.134 @@ -1925,7 +1933,10 @@ static int tmemc_set_var(cli_id_t cli_id
   3.135      else if ( (client = tmh_client_from_cli_id(cli_id)) == NULL)
   3.136          return -1;
   3.137      else
   3.138 -            tmemc_set_var_one(client, subop, arg1);
   3.139 +    {
   3.140 +        tmemc_set_var_one(client, subop, arg1);
   3.141 +        tmh_client_put(client->tmh);
   3.142 +    }
   3.143      return 0;
   3.144  }
   3.145  
   3.146 @@ -1941,6 +1952,8 @@ static NOINLINE int tmemc_shared_pool_au
   3.147          return 1;
   3.148      }
   3.149      client = tmh_client_from_cli_id(cli_id);
   3.150 +    if ( client == NULL )
   3.151 +        return -EINVAL;
   3.152      for ( i = 0; i < MAX_GLOBAL_SHARED_POOLS; i++)
   3.153      {
   3.154          if ( (client->shared_auth_uuid[i][0] == uuid_lo) &&
   3.155 @@ -1949,6 +1962,7 @@ static NOINLINE int tmemc_shared_pool_au
   3.156              if ( auth == 0 )
   3.157                  client->shared_auth_uuid[i][0] =
   3.158                      client->shared_auth_uuid[i][1] = -1L;
   3.159 +            tmh_client_put(client->tmh);
   3.160              return 1;
   3.161          }
   3.162          if ( (auth == 1) && (client->shared_auth_uuid[i][0] == -1L) &&
   3.163 @@ -1956,11 +1970,15 @@ static NOINLINE int tmemc_shared_pool_au
   3.164              free = i;
   3.165      }
   3.166      if ( auth == 0 )
   3.167 +    {
   3.168 +        tmh_client_put(client->tmh);
   3.169          return 0;
   3.170 +    }
   3.171      if ( auth == 1 && free == -1 )
   3.172          return -ENOMEM;
   3.173      client->shared_auth_uuid[free][0] = uuid_lo;
   3.174      client->shared_auth_uuid[free][1] = uuid_hi;
   3.175 +    tmh_client_put(client->tmh);
   3.176      return 1;
   3.177  }
   3.178  
   3.179 @@ -1968,10 +1986,12 @@ static NOINLINE int tmemc_save_subop(int
   3.180                          uint32_t subop, tmem_cli_va_t buf, uint32_t arg1)
   3.181  {
   3.182      client_t *client = tmh_client_from_cli_id(cli_id);
   3.183 -    pool_t *pool =  (client == NULL) ? NULL : client->pools[pool_id];
   3.184 +    pool_t *pool = (client == NULL || pool_id >= MAX_POOLS_PER_DOMAIN)
   3.185 +                   ? NULL : client->pools[pool_id];
   3.186      uint32_t p;
   3.187      uint64_t *uuid;
   3.188      pgp_t *pgp, *pgp2;
   3.189 +    int rc = -1;
   3.190  
   3.191      switch(subop)
   3.192      {
   3.193 @@ -1982,45 +2002,55 @@ static NOINLINE int tmemc_save_subop(int
   3.194              if ( client->pools[p] != NULL )
   3.195                  break;
   3.196          if ( p == MAX_POOLS_PER_DOMAIN )
   3.197 -            return 0;
   3.198 +        {
   3.199 +            rc = 0;
   3.200 +            break;
   3.201 +        }
   3.202          client->was_frozen = client->frozen;
   3.203          client->frozen = 1;
   3.204          if ( arg1 != 0 )
   3.205              client->live_migrating = 1;
   3.206 -        return 1;
   3.207 +        rc = 1;
   3.208 +        break;
   3.209      case TMEMC_RESTORE_BEGIN:
   3.210 -        ASSERT(client == NULL);
   3.211 -        if ( (client = client_create(cli_id)) == NULL )
   3.212 -            return -1;
   3.213 -        return 1;
   3.214 +        if ( client == NULL && (client = client_create(cli_id)) != NULL )
   3.215 +            return 1;
   3.216 +        break;
   3.217      case TMEMC_SAVE_GET_VERSION:
   3.218 -        return TMEM_SPEC_VERSION;
   3.219 +        rc = TMEM_SPEC_VERSION;
   3.220 +        break;
   3.221      case TMEMC_SAVE_GET_MAXPOOLS:
   3.222 -        return MAX_POOLS_PER_DOMAIN;
   3.223 +        rc = MAX_POOLS_PER_DOMAIN;
   3.224 +        break;
   3.225      case TMEMC_SAVE_GET_CLIENT_WEIGHT:
   3.226 -        return client->weight == -1 ? -2 : client->weight;
   3.227 +        rc = client->weight == -1 ? -2 : client->weight;
   3.228 +        break;
   3.229      case TMEMC_SAVE_GET_CLIENT_CAP:
   3.230 -        return client->cap == -1 ? -2 : client->cap;
   3.231 +        rc = client->cap == -1 ? -2 : client->cap;
   3.232 +        break;
   3.233      case TMEMC_SAVE_GET_CLIENT_FLAGS:
   3.234 -        return (client->compress ? TMEM_CLIENT_COMPRESS : 0 ) |
   3.235 -               (client->was_frozen ? TMEM_CLIENT_FROZEN : 0 );
   3.236 +        rc = (client->compress ? TMEM_CLIENT_COMPRESS : 0 ) |
   3.237 +             (client->was_frozen ? TMEM_CLIENT_FROZEN : 0 );
   3.238 +        break;
   3.239      case TMEMC_SAVE_GET_POOL_FLAGS:
   3.240           if ( pool == NULL )
   3.241 -             return -1;
   3.242 -         return (pool->persistent ? TMEM_POOL_PERSIST : 0) |
   3.243 -                (pool->shared ? TMEM_POOL_SHARED : 0) |
   3.244 -                (pool->pageshift << TMEM_POOL_PAGESIZE_SHIFT);
   3.245 +             break;
   3.246 +         rc = (pool->persistent ? TMEM_POOL_PERSIST : 0) |
   3.247 +              (pool->shared ? TMEM_POOL_SHARED : 0) |
   3.248 +              (pool->pageshift << TMEM_POOL_PAGESIZE_SHIFT);
   3.249 +        break;
   3.250      case TMEMC_SAVE_GET_POOL_NPAGES:
   3.251           if ( pool == NULL )
   3.252 -             return -1;
   3.253 -        return _atomic_read(pool->pgp_count);
   3.254 +             break;
   3.255 +        rc = _atomic_read(pool->pgp_count);
   3.256 +        break;
   3.257      case TMEMC_SAVE_GET_POOL_UUID:
   3.258           if ( pool == NULL )
   3.259 -             return -1;
   3.260 +             break;
   3.261          uuid = (uint64_t *)buf.p;
   3.262          *uuid++ = pool->uuid[0];
   3.263          *uuid = pool->uuid[1];
   3.264 -        return 0;
   3.265 +        rc = 0;
   3.266      case TMEMC_SAVE_END:
   3.267          client->live_migrating = 0;
   3.268          if ( !list_empty(&client->persistent_invalidated_list) )
   3.269 @@ -2028,27 +2058,34 @@ static NOINLINE int tmemc_save_subop(int
   3.270                &client->persistent_invalidated_list, client_inv_pages)
   3.271                  pgp_free_from_inv_list(client,pgp);
   3.272          client->frozen = client->was_frozen;
   3.273 -        return 0;
   3.274 +        rc = 0;
   3.275      }
   3.276 -    return -1;
   3.277 +    if ( client )
   3.278 +        tmh_client_put(client->tmh);
   3.279 +    return rc;
   3.280  }
   3.281  
   3.282  static NOINLINE int tmemc_save_get_next_page(int cli_id, int pool_id,
   3.283                          tmem_cli_va_t buf, uint32_t bufsize)
   3.284  {
   3.285      client_t *client = tmh_client_from_cli_id(cli_id);
   3.286 -    pool_t *pool =  (client == NULL) ? NULL : client->pools[pool_id];
   3.287 +    pool_t *pool = (client == NULL || pool_id >= MAX_POOLS_PER_DOMAIN)
   3.288 +                   ? NULL : client->pools[pool_id];
   3.289      pgp_t *pgp;
   3.290      int ret = 0;
   3.291      struct tmem_handle *h;
   3.292      unsigned int pagesize = 1 << (pool->pageshift+12);
   3.293  
   3.294 -    if ( pool == NULL )
   3.295 +    if ( pool == NULL || is_ephemeral(pool) )
   3.296 +    {
   3.297 +        tmh_client_put(client->tmh);
   3.298          return -1;
   3.299 -    if ( is_ephemeral(pool) )
   3.300 -        return -1;
   3.301 +    }
   3.302      if ( bufsize < pagesize + sizeof(struct tmem_handle) )
   3.303 +    {
   3.304 +        tmh_client_put(client->tmh);
   3.305          return -ENOMEM;
   3.306 +    }
   3.307  
   3.308      tmem_spin_lock(&pers_lists_spinlock);
   3.309      if ( list_empty(&pool->persistent_page_list) )
   3.310 @@ -2080,6 +2117,7 @@ static NOINLINE int tmemc_save_get_next_
   3.311  
   3.312  out:
   3.313      tmem_spin_unlock(&pers_lists_spinlock);
   3.314 +    tmh_client_put(client->tmh);
   3.315      return ret;
   3.316  }
   3.317  
   3.318 @@ -2094,7 +2132,10 @@ static NOINLINE int tmemc_save_get_next_
   3.319      if ( client == NULL )
   3.320          return 0;
   3.321      if ( bufsize < sizeof(struct tmem_handle) )
   3.322 +    {
   3.323 +        tmh_client_put(client->tmh);
   3.324          return 0;
   3.325 +    }
   3.326      tmem_spin_lock(&pers_lists_spinlock);
   3.327      if ( list_empty(&client->persistent_invalidated_list) )
   3.328          goto out;
   3.329 @@ -2121,6 +2162,7 @@ static NOINLINE int tmemc_save_get_next_
   3.330      ret = 1;
   3.331  out:
   3.332      tmem_spin_unlock(&pers_lists_spinlock);
   3.333 +    tmh_client_put(client->tmh);
   3.334      return ret;
   3.335  }
   3.336  
   3.337 @@ -2128,22 +2170,26 @@ static int tmemc_restore_put_page(int cl
   3.338                        uint32_t index, tmem_cli_va_t buf, uint32_t bufsize)
   3.339  {
   3.340      client_t *client = tmh_client_from_cli_id(cli_id);
   3.341 -    pool_t *pool =  (client == NULL) ? NULL : client->pools[pool_id];
   3.342 +    pool_t *pool = (client == NULL || pool_id >= MAX_POOLS_PER_DOMAIN)
   3.343 +                   ? NULL : client->pools[pool_id];
   3.344 +    int rc = pool ? do_tmem_put(pool,oid,index,0,0,0,bufsize,buf.p) : -1;
   3.345  
   3.346 -    if ( pool == NULL )
   3.347 -        return -1;
   3.348 -    return do_tmem_put(pool,oid,index,0,0,0,bufsize,buf.p);
   3.349 +    if ( client )
   3.350 +        tmh_client_put(client->tmh);
   3.351 +    return rc;
   3.352  }
   3.353  
   3.354  static int tmemc_restore_flush_page(int cli_id, int pool_id, uint64_t oid,
   3.355                          uint32_t index)
   3.356  {
   3.357      client_t *client = tmh_client_from_cli_id(cli_id);
   3.358 -    pool_t *pool =  (client == NULL) ? NULL : client->pools[pool_id];
   3.359 +    pool_t *pool = (client == NULL || pool_id >= MAX_POOLS_PER_DOMAIN)
   3.360 +                   ? NULL : client->pools[pool_id];
   3.361 +    int rc = pool ? do_tmem_flush_page(pool, oid, index) : -1;
   3.362  
   3.363 -    if ( pool == NULL )
   3.364 -        return -1;
   3.365 -    return do_tmem_flush_page(pool, oid, index);
   3.366 +    if ( client )
   3.367 +        tmh_client_put(client->tmh);
   3.368 +    return rc;
   3.369  }
   3.370  
   3.371  static NOINLINE int do_tmem_control(struct tmem_op *op)
     4.1 --- a/xen/common/tmem_xen.c	Wed Feb 10 09:18:11 2010 +0000
     4.2 +++ b/xen/common/tmem_xen.c	Wed Feb 10 09:18:43 2010 +0000
     4.3 @@ -286,17 +286,16 @@ static void tmh_persistent_pool_page_put
     4.4  
     4.5  /******************  XEN-SPECIFIC CLIENT HANDLING ********************/
     4.6  
     4.7 -EXPORT tmh_client_t *tmh_client_init(void)
     4.8 +EXPORT tmh_client_t *tmh_client_init(cli_id_t cli_id)
     4.9  {
    4.10      tmh_client_t *tmh;
    4.11      char name[5];
    4.12 -    domid_t domid = current->domain->domain_id;
    4.13      int i, shift;
    4.14  
    4.15      if ( (tmh = xmalloc(tmh_client_t)) == NULL )
    4.16          return NULL;
    4.17      for (i = 0, shift = 12; i < 4; shift -=4, i++)
    4.18 -        name[i] = (((unsigned short)domid >> shift) & 0xf) + '0';
    4.19 +        name[i] = (((unsigned short)cli_id >> shift) & 0xf) + '0';
    4.20      name[4] = '\0';
    4.21  #ifndef __i386__
    4.22      tmh->persistent_pool = xmem_pool_create(name, tmh_persistent_pool_page_get,
    4.23 @@ -307,7 +306,6 @@ EXPORT tmh_client_t *tmh_client_init(voi
    4.24          return NULL;
    4.25      }
    4.26  #endif
    4.27 -    tmh->domain = current->domain;
    4.28      return tmh;
    4.29  }
    4.30  
    4.31 @@ -317,6 +315,7 @@ EXPORT void tmh_client_destroy(tmh_clien
    4.32      xmem_pool_destroy(tmh->persistent_pool);
    4.33  #endif
    4.34      put_domain(tmh->domain);
    4.35 +    tmh->domain = NULL;
    4.36  }
    4.37  
    4.38  /******************  XEN-SPECIFIC HOST INITIALIZATION ********************/
     5.1 --- a/xen/include/xen/tmem_xen.h	Wed Feb 10 09:18:11 2010 +0000
     5.2 +++ b/xen/include/xen/tmem_xen.h	Wed Feb 10 09:18:43 2010 +0000
     5.3 @@ -43,8 +43,6 @@ extern rwlock_t tmem_rwlock;
     5.4  
     5.5  extern void tmh_copy_page(char *to, char*from);
     5.6  extern int tmh_init(void);
     5.7 -extern tmh_client_t *tmh_client_init(void);
     5.8 -extern void tmh_client_destroy(tmh_client_t *);
     5.9  #define tmh_hash hash_long
    5.10  
    5.11  extern void tmh_release_avail_pages_to_host(void);
    5.12 @@ -281,6 +279,9 @@ typedef domid_t cli_id_t;
    5.13  typedef struct domain tmh_cli_ptr_t;
    5.14  typedef struct page_info pfp_t;
    5.15  
    5.16 +extern tmh_client_t *tmh_client_init(cli_id_t);
    5.17 +extern void tmh_client_destroy(tmh_client_t *);
    5.18 +
    5.19  /* this appears to be unreliable when a domain is being shut down */
    5.20  static inline struct client *tmh_client_from_cli_id(cli_id_t cli_id)
    5.21  {
    5.22 @@ -290,6 +291,11 @@ static inline struct client *tmh_client_
    5.23      return (struct client *)(d->tmem);
    5.24  }
    5.25  
    5.26 +static inline void tmh_client_put(tmh_client_t *tmh)
    5.27 +{
    5.28 +    put_domain(tmh->domain);
    5.29 +}
    5.30 +
    5.31  static inline struct client *tmh_client_from_current(void)
    5.32  {
    5.33      return (struct client *)(current->domain->tmem);
    5.34 @@ -307,10 +313,12 @@ static inline tmh_cli_ptr_t *tmh_get_cli
    5.35      return current->domain;
    5.36  }
    5.37  
    5.38 -static inline void tmh_set_client_from_id(struct client *client,cli_id_t cli_id)
    5.39 +static inline void tmh_set_client_from_id(struct client *client,
    5.40 +                                          tmh_client_t *tmh, cli_id_t cli_id)
    5.41  {
    5.42      struct domain *d = get_domain_by_id(cli_id);
    5.43      d->tmem = client;
    5.44 +    tmh->domain = d;
    5.45  }
    5.46  
    5.47  static inline bool_t tmh_current_is_privileged(void)