Commit 40d05e5f authored by Yathindra Naik's avatar Yathindra Naik

This is an on-going effort to use capabilities security model for xenstore.

It primarily includes changes to xenstore client and xenstore deamon.
I'll continue to make changes. Not everything is patched yet.
parent a528c66c
......@@ -221,12 +221,9 @@ int xc_domain_getinfo(xc_interface *xch,
info->running = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
info->hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
info->debugged = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_debugged);
#if 0
#ifdef CONFIG_XENCAP
info->cap_flag = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_cap_flag);
PPRINTF("cap_flag:%d\n",info->cap_flag);
#endif
#endif
info->shutdown_reason =
(domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
XEN_DOMINF_shutdownmask;
......@@ -1526,7 +1523,7 @@ int xc_cap_create(xc_interface *xch, uint32_t domid, struct capability *cap)
DECLARE_DOMCTL;
DPRINTF("In xc_cap_create().\n");
domctl.cmd = XEN_DOMCTL_cap_create;
domctl.domain = (domid_t)domid;
domctl.domain = domid;
domctl.u.cap_create.cap = cap;
DPRINTF("Leaving xc_cap_create().\n");
return do_domctl(xch, &domctl);
......
......@@ -48,7 +48,7 @@
#include <xen/tmem.h>
#ifdef CONFIG_XENCAP
//#include <xen/xen-cap.h>
#include <xen/xsm/cap.h>
#endif
#include "xentoollog.h"
......
......@@ -522,6 +522,9 @@ static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo,
xlinfo->paused = !!(xcinfo->flags&XEN_DOMINF_paused);
xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked);
xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running);
#ifdef CONFIG_XENCAP
xlinfo->cap_flag = !!(xcinfo->flags&XEN_DOMINF_cap_flag);
#endif
if (xlinfo->shutdown || xlinfo->dying)
xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask;
......
......@@ -423,12 +423,15 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info, libxl_capa
goto out;
}
#ifdef CONFIG_XENCAP
ret = libxl_domain_setcap(ctx, cap, *domid);
if (ret) {
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot grant capabilities: %d", ret);
rc = ERROR_FAIL;
goto out;
}
if ( cap != NULL )
{
ret = libxl_domain_setcap(ctx, cap, *domid);
if (ret) {
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot grant capabilities: %d", ret);
rc = ERROR_FAIL;
goto out;
}
}
#endif
ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
if (ret < 0) {
......
......@@ -192,7 +192,9 @@ libxl_dominfo = Struct("dominfo",[
("paused", bool),
("shutdown", bool),
("dying", bool),
#ifdef CONFIG_XENCAP
("cap_flag", bool),
#endif
# Valid iff (shutdown||dying).
#
# Otherwise set to a value guaranteed not to clash with any valid
......
......@@ -2906,7 +2906,7 @@ static void list_domains(int verbose, int context, const libxl_dominfo *info, in
unsigned shutdown_reason;
domname = libxl_domid_to_name(ctx, info[i].domid);
shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f",
printf("%-40s %5d %5lu %5d %c%c%c%c%c%c%c %8.1f",
domname,
info[i].domid,
(unsigned long) (info[i].current_memkb / 1024),
......@@ -2915,6 +2915,9 @@ static void list_domains(int verbose, int context, const libxl_dominfo *info, in
info[i].blocked ? 'b' : '-',
info[i].paused ? 'p' : '-',
info[i].shutdown ? 's' : '-',
#ifdef CONFIG_XENCAP
info[i].cap_flag ? 'c' : '-',
#endif
(shutdown_reason >= 0 &&
shutdown_reason < sizeof(shutdown_reason_letters)-1
? shutdown_reason_letters[shutdown_reason] : '?'),
......
......@@ -375,12 +375,20 @@ static PyObject *pyxc_domain_getinfo(XcObject *self,
for ( i = 0 ; i < nr_doms; i++ )
{
info_dict = Py_BuildValue(
#ifdef CONFIG_XENCAP
"{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
",s:L,s:L,s:L,s:i,s:i,s:i}",
#else
"{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
",s:L,s:L,s:L,s:i,s:i,s:i}",
#endif
"domid", (int)info[i].domid,
"online_vcpus", info[i].nr_online_vcpus,
"max_vcpu_id", info[i].max_vcpu_id,
"hvm", info[i].hvm,
#ifdef CONFIG_XENCAP
"capability_mode", info[i].cap_flag,
#endif
"dying", info[i].dying,
"crashed", info[i].crashed,
"shutdown", info[i].shutdown,
......
This diff is collapsed.
......@@ -84,8 +84,9 @@ struct connection
/* The domain I'm associated with, if any. */
struct domain *domain;
/* The target of the domain I'm associated with. */
struct connection *target;
/* The target of the domain I'm associated with. */
struct connection *target;
/* My watches. */
struct list_head watches;
......@@ -108,7 +109,15 @@ struct node {
/* Permissions. */
unsigned int num_perms;
struct xs_permissions *perms;
#ifdef CONFIG_XENCAP
/* Capabilities to access this node
* There are 2 capabilities,
* cap[0] - read_cap
* cap[1] - write_cap
*/
unsigned int num_caps;
struct capability *caps;
#endif
/* Contents. */
unsigned int datalen;
void *data;
......
......@@ -61,6 +61,10 @@ struct domain
/* Domain path in store. */
char *path;
#ifdef CONFIG_XENCAP
int cap_flag;
#endif
/* Shared page. */
struct xenstore_domain_interface *interface;
......@@ -262,6 +266,18 @@ bool domain_is_unprivileged(struct connection *conn)
return (conn && conn->domain && conn->domain->domid != 0 && conn->domain->domid != priv_domid);
}
#ifdef CONFIG_XENCAP
int get_domid(struct connection *conn)
{
return conn->domain->domid;
}
bool domain_is_cap(struct connection *conn)
{
return (conn && conn->domain && conn->domain->cap_flag);
}
#endif
bool domain_can_write(struct connection *conn)
{
struct xenstore_domain_interface *intf = conn->domain->interface;
......@@ -278,6 +294,9 @@ static struct domain *new_domain(void *context, unsigned int domid,
{
struct domain *domain;
int rc;
#ifdef CONFIG_XENCAP
xc_dominfo_t dominfo;
#endif
domain = talloc(context, struct domain);
domain->port = 0;
......@@ -294,6 +313,13 @@ static struct domain *new_domain(void *context, unsigned int domid,
return NULL;
domain->port = rc;
#ifdef CONFIG_XENCAP
if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
&dominfo) == 1 && dominfo.domid == domain->domid) {
domain->cap_flag = dominfo.cap_flag;
}
#endif
domain->conn = new_connection(writechn, readchn);
domain->conn->domain = domain;
domain->conn->id = domid;
......
......@@ -57,6 +57,14 @@ bool domain_can_write(struct connection *conn);
bool domain_is_unprivileged(struct connection *conn);
#ifdef CONFIG_XENCAP
/* Returns domain id for a connection. */
int get_domid(struct connection *conn);
/* Returns true if domain is in capability mode. */
bool domain_is_cap(struct connection *conn);
#endif
/* Quota manipulation */
void domain_entry_inc(struct connection *conn, struct node *);
void domain_entry_dec(struct connection *conn, struct node *);
......
......@@ -666,7 +666,7 @@ bool xs_set_permissions(struct xs_handle *h,
iov[0].iov_base = (void *)path;
iov[0].iov_len = strlen(path) + 1;
for (i = 0; i < num_perms; i++) {
char buffer[MAX_STRLEN(unsigned int)+1];
......
......@@ -107,6 +107,131 @@ bool xs_write_all(int fd, const void *data, unsigned int len)
return true;
}
#ifdef CONFIG_XENCAP
/* Convert strings to capabilities. False if a problem.
* Permission scheme in xenstore is weird. Here are the rules -
1) Domain 0 may read or write anywhere in the store,
regardless of permissions, and permissions are set
up by the tools in domain 0, or by Xenstored when
it first starts up.
2) The first element in this list specifies the owner of the path.
3) The owner always has read and write access to their nodes.
4) The example below, therefore, sets the permissions in the path
to be such that domain 0 (being privileged), dom1 (being the owner),
and domains dom2 and dom3 (being explicitly specified) can _all_ write
to the node. Any other domain can only read, as specified by the first
pair of 'read' and 'write' flags.
Example:
xstransact.SetPermissions(path, { 'dom' : dom1,
'read' : True,
'write' : False },
{ 'dom' : dom2,
'read' : True,
'write' : True },
{ 'dom' : dom3,
'read' : True,
'write' : True })
*/
bool xs_strings_to_caps(unsigned int num, const char *strings)
{
const char *p;
char *end;
unsigned int i;
xc_interface *xch;
int owner_domid;
int list[2] = {-1,-1};
int flag = 0;
/* I'm guessing we need to handle two cases here.
* The first domain id is the owner. Create 2 capabilities for it.
* Rest of the domain id's we can simply grant from the owner.
*/
xc_interface *xch;
xch = xc_interface_open(0,0,0);
if(xch == 0)
{
printf("\nxc_interface_open failed to get xc_handle!\n");
return FALSE;
}
/* First, identify the owner domain and
create read and write capabilities. */
p = strings;
p++;
owner_domid = strtol(p, &end, 0);
if (!xc_cap_create(owner_domid, node->caps[0]))
{
xc_interface_close(xch);
printf("xs_strings_to_caps: Error in xc_cap_create.\n");
return FALSE;
}
if (!xc_cap_create(owner_domid, node->caps[1]))
{
xc_interface_close(xch);
printf("xs_strings_to_caps: Error in xc_cap_create.\n");
return FALSE;
}
for (p = end+1, i = 1; i < num; i++) {
/* "r", "w", or "b" for both. */
switch (*p) {
case 'r':
list[0] = 0;
flag = 1;
break;
case 'w':
list[0] = 1;
flag = 1;
break;
case 'b':
list[0] = 0;
list[1] = 1;
break;
case 'n':
break;
default:
errno = EINVAL;
return false;
}
p++;
to_domid = strtol(p, &end, 0);
if (*end || !*p) {
errno = EINVAL;
return false;
}
if (flag)
{
/* Read or Write Caps */
if ((xc_cap_grant(owner_domid,to_domid,2,list,1)) == 1)
{
xc_interface_close(xch);
printf("xs_strings_to_caps: Error in xc_cap_grant.\n");
return FALSE;
}
}
else
{
/* Both the flags */
if ((xc_cap_grant(owner_domid,to_domid,2,list,2)) == 1)
{
xc_interface_close(xch);
printf("xs_strings_to_caps: Error in xc_cap_grant.\n");
return FALSE;
}
}
p = end + 1;
}
return true;
}
#endif
/* Convert strings to permissions. False if a problem. */
bool xs_strings_to_perms(struct xs_permissions *perms, unsigned int num,
const char *strings)
......
......@@ -149,6 +149,9 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
(d->is_shut_down ? XEN_DOMINF_shutdown : 0) |
(d->is_paused_by_controller ? XEN_DOMINF_paused : 0) |
(d->debugger_attached ? XEN_DOMINF_debugged : 0) |
#ifdef CONFIG_XENCAP
(d->cap_flag ? XEN_DOMINF_cap_flag : 0) |
#endif
d->shutdown_code << XEN_DOMINF_shutdownshift;
if ( is_hvm_domain(d) )
......@@ -468,7 +471,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
domcr_flags |= DOMCRF_oos_off;
#ifdef CONFIG_XENCAP
if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_cap_flag ) {
TT_DBG("Setting cap-flag for the new domain\n");
domcr_flags |= DOMCRF_cap_flag;
}
#endif
......@@ -1071,7 +1073,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
}
cap = op->u.cap_create.cap;
ret = cap_create(d, cap);
ret = cap_create(d,cap);
printk("Leaving XEN_DOMCTL_cap_create().\n");
rcu_unlock_domain(d);
......
......@@ -10,7 +10,7 @@
*/
#include <xen/mm.h>
//#include <xen/xmalloc.h>
#include <xen/xmalloc.h>
#include <xen/paging.h>
#include <xen/xen-cap.h>
......@@ -142,17 +142,44 @@ int cap_init_hypercalls()
return 0;
}
/*
* Creates a capability.
*/
int cap_create(struct domain *d, struct capability *cap)
{
int num_caps;
init_rand(41);
if ( d->cap_space != NULL )
num_caps = d->cap_space->num_caps;
else
{
TT_DBG("cap_create: cap_space not init'ed\n");
return 1;
}
TT_DBG("In cap_create()\n");
cap->magic = rand_cmwc();
/* NOTE: I'm not sure if we need to insert the newly
* create cap in calling domains cap_space.
* For now, this will help me with xenstore since
* which ever domain is calling cap_create will have
* the necessary capabilities in its cap_space.
* Also, note that the *cap below might be a local
* pointer!!!!!
*/
d->cap_space->caps[num_caps] = *cap;
d->cap_space->num_caps++;
return 0;
}
/*
* Grant a list of capabilities from source domain to destination domain.
*/
int cap_grant(struct domain *from, struct domain *to, int type, void *list, int size)
{
int i, index;
......@@ -171,18 +198,36 @@ int cap_grant(struct domain *from, struct domain *to, int type, void *list, int
{
index = ptr[i];
printk("cap_grant: index=%d, i=%d\n",index,i);
printk("cap_grant_hyp: index=%d, i=%d\n",index,i);
if(index == -1)
continue;
to->cap_space->cap_hypercalls[index] = from->cap_space->cap_hypercalls[index];
TT_DBG("Granting Capability: Domain %d, Capability: 0x%x\n",to->domain_id, from->cap_space->cap_hypercalls[index].magic);
}
break;
case 2:
/* General */
for ( i = 0; i < size; ++i )
{
index = ptr[i];
printk("cap_grant_gen: index=%d, i=%d\n",index,i);
if(index == -1)
continue;
to->cap_space->caps[index] = from->cap_space->caps[index];
TT_DBG("Granting Capability: Domain %d, Capability: 0x%x\n",to->domain_id, from->cap_space->caps[index].magic);
}
break;
}
return 0;
}
/*
* Check if the domain has the required capability.
*/
int cap_check(struct domain *d, int type, struct capability *cap)
{
int i;
......
......@@ -93,6 +93,11 @@ struct xen_domctl_getdomaininfo {
/* Being debugged. */
#define _XEN_DOMINF_debugged 6
#define XEN_DOMINF_debugged (1U<<_XEN_DOMINF_debugged)
#ifdef CONFIG_XENCAP
/* Domain is in capability mode. */
#define _XEN_DOMINF_cap_flag 7
#define XEN_DOMINF_cap_flag (1U<<_XEN_DOMINF_cap_flag)
#endif
/* XEN_DOMINF_shutdown guest-supplied code. */
#define XEN_DOMINF_shutdownmask 255
#define XEN_DOMINF_shutdownshift 16
......
......@@ -52,10 +52,11 @@ struct cap_space
* in efficient lookup structures. Hence, we need
* to have different pointers.
*/
int num_caps;
/* Hypercalls are limited and hence can be stored
efficiently in fixed sized arrays. */
struct capability *cap_hypercalls;
struct capability *caps;
};
#define CAP_INIT(x,y) { (x), (y) }
......@@ -66,7 +67,7 @@ struct cap_space
int cap_init(void);
int cap_init_hypercalls(void);
int cap_share_boot_info_page(void);
int cap_create(struct domain *d, struct capability *cap);
int cap_create(struct domain*d, struct capability *cap);
int cap_grant(struct domain *from, struct domain *to, int type, void *list,int size );
int cap_check(struct domain *d, int type, struct capability *cap);
extern void init_rand(uint32_t x);
......
......@@ -40,7 +40,9 @@ static int cap_domain_create(struct domain *d, u32 ssidref)
TT_DBG_ON(cap_debug,"dom_cap_space allocation failed in cap_domain_create()!\n");
return -1;
}
dom_cap_space->cap_hypercalls = xmalloc_array(struct capability, NUM_HYPERCALLS);
dom_cap_space->num_caps = 0;
if ( dom_cap_space->cap_hypercalls == NULL )
{
......@@ -66,7 +68,9 @@ static int cap_domain_create(struct domain *d, u32 ssidref)
{
TT_DBG_ON(cap_debug,"Init'ing capabilities for domain %d\n",d->domain_id);
dom_cap_space->cap_hypercalls = CAP_BOOT_INFO->cap_hypercalls;
dom_cap_space->num_caps = 0;
d->cap_space = dom_cap_space;
d->cap_flag = 1;
return rc;
}
......@@ -77,7 +81,7 @@ static int cap_domain_create(struct domain *d, u32 ssidref)
* the first time we make a hypercall.
*/
d->cap_space = dom_cap_space;
d->cap_flag = 0;
d->cap_flag = 1;
TT_DBG_ON(cap_debug,"Returning from cap_domain_create\n");
return rc;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment