Commit d0fc9f70 authored by Yathindra Naik's avatar Yathindra Naik

Introduced several changes to debug xenstore problems.

- Still there is a confusion betweem perms and capabilities.
- Need to figure out the code path to correctly assign capabilities.
parent 6f55b4b6
......@@ -1518,19 +1518,19 @@ int xc_domain_set_virq_handler(xc_interface *xch, uint32_t domid, int virq)
#ifdef CONFIG_XENCAP
int xc_cap_create(xc_interface *xch, uint32_t domid, struct capability *cap)
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;
/*domctl.domain = domid;*/
domctl.u.cap_create.cap = cap;
DPRINTF("Leaving xc_cap_create().\n");
return do_domctl(xch, &domctl);
}
int xc_cap_grant(xc_interface *xch,
uint32_t from_domid,
/*uint32_t from_domid,*/
uint32_t to_domid,
int type,
void *list,
......@@ -1543,8 +1543,8 @@ int xc_cap_grant(xc_interface *xch,
/* Not sure if I should init the domid here as we
* are not using it in domctl.c
*/
domctl.domain = (domid_t)from_domid;
domctl.u.cap_grant.from = (domid_t)from_domid;
//domctl.domain = (domid_t)from_domid;
/*domctl.u.cap_grant.from = (domid_t)from_domid;*/
domctl.u.cap_grant.to = (domid_t)to_domid;
domctl.u.cap_grant.type = type;
domctl.u.cap_grant.list = list;
......
......@@ -2242,27 +2242,19 @@ int xc_compression_uncompress_page(xc_interface *xch, char *compbuf,
*
* Returns success - 1 or failure - 0.
*/
int xc_cap_create(xc_interface *xch, uint32_t domid, struct capability *cap);
int xc_cap_create(xc_interface *xch, struct capability *cap);
/**
* The owner of the capability can grant it to other VM by invoking this function.
* Returns success - 1 or failure - 0.
*/
int xc_cap_grant(xc_interface *xch,
uint32_t from_domid,
uint32_t to_domid,
int type,
void *list,
int size);
int xc_cap_grant(xc_interface *xch, uint32_t to_domid, int type, void *list, int size);
/**
* Check if the VM has access to a protected resource.
* Returns success - 1 or failure - 0.
*/
int xc_cap_check(xc_interface *xch,
uint32_t domid,
int type,
struct capability *cap);
int xc_cap_check(xc_interface *xch, uint32_t domid, int type, struct capability *cap);
#endif /* CONFIG_XENCAP */
......
......@@ -1044,7 +1044,7 @@ int libxl_domain_setcap(libxl_ctx *ctx, libxl_capabilities *info, uint32_t domid
if(size > 0)
{
printf("Calling xc_cap_grant().\n");
ret = xc_cap_grant(ctx->xch,0,domid,1,list,size);
ret = xc_cap_grant(ctx->xch,domid,1,list,size);
}
return ret;
......
/******************************************************************************
/*******************************************************************************
* Xc.c
*
* Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
......@@ -186,7 +186,7 @@ static PyObject *pyxc_domain_unpause(XcObject *self, PyObject *args)
*/
static PyObject *pyxc_cap_hypercalls(XcObject *self, PyObject *args)
{
uint32_t from_dom, to_dom, dom, cap_flag;
uint32_t to_dom, dom, cap_flag;
PyObject* cap_hypercalls = NULL;
int hypercalls_list[64];
char *str;
......@@ -213,10 +213,9 @@ static PyObject *pyxc_cap_hypercalls(XcObject *self, PyObject *args)
hypercalls_list[i] = 10;
}
from_dom = 0;
to_dom = dom;
if ( xc_cap_grant(self->xc_handle, from_dom, to_dom, 1, hypercalls_list, 64 ) != 0 )
if ( xc_cap_grant(self->xc_handle, to_dom, 1, hypercalls_list, 64 ) != 0 )
return pyxc_error_to_exception(self->xc_handle);
Py_INCREF(Py_None);
......
......@@ -396,7 +396,7 @@ static struct node *read_node(struct connection *conn, const char *name)
talloc_steal(node, data.dptr);
#ifdef CONFIG_XENCAP
if ( conn != NULL && conn->cap_flag ) {
if ( conn != NULL && conn->domain != NULL && is_domain_cap(conn) && conn->cap_flag ) {
/* Datalen, childlen, number of permissions */
p = (uint32_t *)data.dptr;
node->num_perms = p[0];
......@@ -450,7 +450,7 @@ static bool write_node(struct connection *conn, const struct node *node)
log("write_node: %s\n",node->name);
#ifdef CONFIG_XENCAP
if (conn != NULL && conn->cap_flag) {
if (conn != NULL && conn->domain != NULL && is_domain_cap(conn) && conn->cap_flag) {
// log("write_node: node->num_caps %d, size %ld\n",node->num_caps, sizeof(node->caps[0]));
data.dsize = 4*sizeof(uint32_t)
......@@ -520,7 +520,7 @@ static int caps_for_conn(struct connection *conn,
struct capability *caps, enum xs_perm_type perm)
{
int ret = 1; /* success */
int domid = get_domid(conn);
int domid = get_domid(conn);
xc_interface *xch;
xch = xc_interface_open(0,0,0);
......@@ -575,7 +575,11 @@ static int caps_for_conn(struct connection *conn,
case XS_PERM_NONE:
ret = 0;
default:
ret = 0;
/* Return the default capability.
NOTE: DOUBT!!!
return success for now.
*/
ret = 1;
}
xc_interface_close(xch);
......@@ -634,7 +638,7 @@ static enum xs_perm_type ask_parents(struct connection *conn, const char *name)
corrupt(conn, "No permissions file at root");
#ifdef CONFIG_XENCAP
if ( conn != NULL && conn->cap_flag ) {
if ( conn != NULL && conn->domain != NULL && is_domain_cap(conn) && conn->cap_flag ) {
log("checking read cap\n");
if (caps_for_conn(conn, node->caps, XS_PERM_READ))
xs_perms = XS_PERM_READ;
......@@ -681,7 +685,7 @@ struct node *get_node(struct connection *conn,
log("get_node: node->name %s node %p\n",name,node);
#ifdef CONFIG_XENCAP
if ( conn != NULL && conn->cap_flag ) {
if ( conn != NULL && conn->domain != NULL && is_domain_cap(conn) && conn->cap_flag ) {
if (node) {
if (!caps_for_conn(conn, node->caps, perm)) {
errno = EACCES;
......@@ -847,6 +851,51 @@ static const char *onearg(struct buffered_data *in)
}
#ifdef CONFIG_XENCAP
static int grant_def_cap(xc_interface *xch,int *def_domains, int size, struct capability *cap, int def_size)
{
int index;
xprintf("grant_def_cap: Iterating the default domains list.\n");
if (!get_def_domains(def_domains,size)) {
for (index = 0; index < size; ++index)
{
/* Grant def cap. */
if (def_domains[index] != -1)
{
if ( cap == NULL )
continue;
if (def_size == 1)
{
if (!xc_cap_grant(xch,def_domains[index],2,&cap[0],1))
{
xprintf("grant_def_cap: Error in xc_cap_grant\n");
return 1;
}
}
if (def_size == 2)
{
if (!xc_cap_grant(xch,def_domains[index],2,&cap[0],2))
{
xprintf("grant_def_cap: Error in xc_cap_grant\n");
return 1;
}
if (!xc_cap_grant(xch,def_domains[index],2,&cap[1],2))
{
xprintf("grant_def_cap: Error in xc_cap_grant\n");
return 1;
}
}
}
}
}
return 0;
}
/* 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,
......@@ -875,12 +924,17 @@ static const char *onearg(struct buffered_data *in)
bool xs_strings_to_caps(unsigned int num, struct capability *caps, const char *strings)
{
const char *p;
char def_perm;
char *end;
unsigned int i;
xc_interface *xch;
int owner_domid,to_domid;
struct capability list[2];
struct capability def_cap[2];
struct capability *null_cap = NULL;
int def_domains[num];
int flag = 0;
int def_size = 1;
/* I'm guessing we need to handle two cases here.
* The first domain id is the owner. Create 2 capabilities for it.
......@@ -895,33 +949,63 @@ bool xs_strings_to_caps(unsigned int num, struct capability *caps, const char *s
}
/* First, identify the owner domain and
create read and write capabilities. */
create read and write capabilities.
Also, note that the first permission
is the default permission.
*/
p = strings;
def_perm = strings[0];
p++;
owner_domid = strtol(p, &end, 0);
log("xs_strings_to_caps: owner_domid: %d\n",owner_domid);
log("xs_strings_to_caps: creating read and write caps for owner_domid (%d)\n",owner_domid);
if ( caps == NULL )
{
log("xs_strings_to_caps: caps is NULL!\n");
goto out;
}
if (xc_cap_create(xch, owner_domid, &caps[0]))
log("xs_strings_to_caps: creating read and write caps\n");
if (xc_cap_create(xch,&caps[0]))
{
log("xs_strings_to_caps: Error in xc_cap_create.\n");
goto out;
}
if (xc_cap_create(xch, owner_domid, &caps[1]))
if (xc_cap_create(xch, &caps[1]))
{
log("xs_strings_to_caps: Error in xc_cap_create.\n");
goto out;
}
if (def_perm == 'r')
def_cap[0] = caps[0];
if (def_perm == 'w')
def_cap[0] = caps[1];
if (def_perm == 'n')
def_cap[0] = *null_cap;
if (def_perm == 'b')
{
def_cap[0] = caps[0];
def_cap[1] = caps[1];
def_size = 2;
}
/* Grant this to owner. */
list[0] = caps[0];
list[1] = caps[1];
log("xs_strings_to_caps: Granting read and write caps to owner_domid (%d)\n",owner_domid);
if (xc_cap_grant(xch, owner_domid, 2, &list, 2) == 1)
{
log("xs_strings_to_caps: Error in xc_cap_grant.\n");
goto out;
}
for (p = end+1, i = 1; i < num; i++) {
/* "r", "w", or "b" for both. */
switch (*p) {
......@@ -949,12 +1033,14 @@ bool xs_strings_to_caps(unsigned int num, struct capability *caps, const char *s
errno = EINVAL;
goto out;
}
def_domains[i] = to_domid;
if (flag)
{
log("xs_strings_to_caps: Granting read/write cap from domid: %d, to domid: %d\n",owner_domid,to_domid);
/* Read or Write Caps */
if ((xc_cap_grant(xch,owner_domid,to_domid,2,&list,1)) == 1)
if ((xc_cap_grant(xch,to_domid,2,&list,1)) == 1)
{
log("xs_strings_to_caps: Error in xc_cap_grant.\n");
goto out;
......@@ -964,7 +1050,7 @@ bool xs_strings_to_caps(unsigned int num, struct capability *caps, const char *s
{
log("xs_strings_to_caps: Granting both caps from domid: %d, to domid: %d\n",owner_domid,to_domid);
/* Both the flags */
if ((xc_cap_grant(xch,owner_domid,to_domid,2,&list,2)) == 1)
if ((xc_cap_grant(xch,to_domid,2,&list,2)) == 1)
{
log("xs_strings_to_caps: Error in xc_cap_grant.\n");
goto out;
......@@ -973,6 +1059,12 @@ bool xs_strings_to_caps(unsigned int num, struct capability *caps, const char *s
p = end + 1;
}
/* Invoke a function which will iterate through the
given list of domains and grant default caps on them. */
if (!grant_def_cap(xch, def_domains, num, def_cap, def_size))
log("grant_def_cap: Error\n");
xc_interface_close(xch);
return true;
out:
......@@ -1129,21 +1221,21 @@ static struct node *construct_node(struct connection *conn, const char *name)
node->perms = talloc_memdup(node, parent->perms,
node->num_perms * sizeof(node->perms[0]));
#ifdef CONFIG_XENCAP
if ( domid != -1 && conn->cap_flag == 1 )
if ( domid != -1 && conn != NULL && conn->domain != NULL && is_domain_cap(conn) && conn->cap_flag )
{
node->num_caps = 2;
node->caps = talloc_array(node, struct capability, 2);
log("construct_node: Creating read/write caps for domid id: %d\n",domid);
if (xc_cap_create(xch, domid, &node->caps[0]))
if (xc_cap_create(xch, &node->caps[0]))
{
xc_interface_close(xch);
log("construct_node: Error in xc_cap_create.\n");
// should return err
}
if (xc_cap_create(xch, domid, &node->caps[1]))
if (xc_cap_create(xch, &node->caps[1]))
{
xc_interface_close(xch);
log("construct_node: Error in xc_cap_create.\n");
......@@ -1497,7 +1589,7 @@ static void do_get_perms(struct connection *conn, const char *name)
}
#ifdef CONFIG_XENCAP
if ( conn != NULL && conn->cap_flag )
if ( conn != NULL && conn->domain != NULL && is_domain_cap(conn) && conn->cap_flag )
{
//strings = caps_to_strings(node, &len);
log("do_get_perms: domain is in capability mode! Cannot ask the caps!\n");
......@@ -1542,7 +1634,7 @@ static void do_set_perms(struct connection *conn, struct buffered_data *in)
return;
}
#ifdef CONFIG_XENCAP
if ( conn != NULL && conn->cap_flag )
if ( conn != NULL && conn->domain != NULL && is_domain_cap(conn) && conn->cap_flag )
{
log("do_set_perms: Domain is in capability mode\n");
if ( node->num_caps == 0 )
......@@ -1835,7 +1927,7 @@ struct connection *new_connection(connwritefn_t *write, connreadfn_t *read)
/* Heres a thought: Since these connections mostly don't have
any domain associated with it, lets simply grant them acess
to nodes ? */
new->cap_flag = 0;
new->cap_flag = 1;
#endif
INIT_LIST_HEAD(&new->out_list);
INIT_LIST_HEAD(&new->watches);
......
......@@ -275,6 +275,13 @@ int get_domid(struct connection *conn)
return -1;
}
bool is_domain_cap(struct connection *conn)
{
if ( conn != NULL && conn->domain != NULL && conn->domain->cap_flag)
return true;
else
return false;
}
#if 0
bool domain_is_cap(struct connection *conn)
{
......@@ -431,6 +438,101 @@ static struct domain *find_domain_by_domid(unsigned int domid)
}
return NULL;
}
#if 0
#ifdef CONFIG_XENCAP
/* iterate through the list of domains and
return all the domains not present in
the given list.
Note: Caller has to free the returned list.
*/
int grant_def_cap(int *def_domains, int size, struct capability *cap, int def_size)
{
int index;
xprintf("grant_def_cap: Iterating the default domains list.\n");
list_for_each_entry(i, &domains, list) {
for (index = 0; index < size; ++index)
{
/* If its not in the list. Grant def cap. */
if (i->domid != def_domains[index])
{
if ( cap == NULL )
continue;
if (def_size == 1)
{
if (!xc_cap_grant(*xc_handle,i->domid,2,&cap[0],1))
{
xprintf("grant_def_cap: Error in xc_cap_grant\n");
return 1;
}
}
if (def_size == 2)
{
if (!xc_cap_grant(*xc_handle,i->domid,2,&cap[0],2))
{
xprintf("grant_def_cap: Error in xc_cap_grant\n");
return 1;
}
if (!xc_cap_grant(*xc_handle,i->domid,2,&cap[1],2))
{
xprintf("grant_def_cap: Error in xc_cap_grant\n");
return 1;
}
}
}
}
}
return 0;
}
#endif
#endif
#ifdef CONFIG_XENCAP
/* Iterate through the domain list.
Return the default ones.
Note: This changes the original list. */
int get_def_domains(int *def_domains, int size)
{
int mod_index = 0;
int index;
int flag = 0;
int tmp[size];
struct domain *i;
for (index = 0;index < size; ++index)
tmp[index] = -1;
list_for_each_entry(i, &domains, list) {
xprintf("get_def_domains: domain %d\n",(int)i->domid);
for (index = 0; index < size; ++index) {
if (i->domid != def_domains[index])
continue;
else
{
flag = 1;
break;
}
}
if (!flag)
{
tmp[mod_index] = i->domid;
mod_index++;
xprintf("def_domain[%d] = %d\n",mod_index,tmp[mod_index]);
}
flag = 0;
}
for (index = 0; index < size; index++)
def_domains[index] = tmp[index];
return 0;
}
#endif
static void domain_conn_reset(struct domain *domain)
{
......
......@@ -61,9 +61,16 @@ bool domain_is_unprivileged(struct connection *conn);
/* Returns domain id for a connection. */
int get_domid(struct connection *conn);
/* Returns default domains for assigning default caps. */
int get_def_domains(int *def_domains, int size);
/* Is this domain in capabilitiy mode */
bool is_domain_cap(struct connection *conn);
/* Returns true if domain is in capability mode. */
//bool domain_is_cap(struct connection *conn);
//int grant_def_cap(int *def_domains, int size, struct capability *cap, int def_size)
//static char *caps_to_strings(struct connection *conn, unsigned int *len)
#endif
......
......@@ -1061,38 +1061,40 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
#ifdef CONFIG_XENCAP
case XEN_DOMCTL_cap_create:
{
struct domain *d;
/* struct domain *d; */
struct capability *cap;
printk("In XEN_DOMCTL_cap_create().\n");
ret = -ESRCH;
/*
d = rcu_lock_domain_by_id(op->domain);
if ( d == NULL )
{
TT_ERR("Failed to rcu_lock_dom_by_id:%d\n", op->domain);
break;
}
*/
cap = op->u.cap_create.cap;
ret = cap_create(d,cap);
ret = cap_create(cap);
printk("Leaving XEN_DOMCTL_cap_create().\n");
rcu_unlock_domain(d);
// rcu_unlock_domain(d);
}
break;
case XEN_DOMCTL_cap_grant:
{
struct domain *d;
//struct domain *d;
struct domain *to;
struct domain *from;
int type;
void *list;
int size;
printk("In XEN_DOMCTL_cap_grant().\n");
ret = -ESRCH;
/*
d = rcu_lock_domain_by_id(op->domain);
if ( d == NULL )
{
......@@ -1100,23 +1102,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
rcu_unlock_domain(d);
break;
}
from = rcu_lock_domain_by_id(op->u.cap_grant.from);
if ( from == NULL )
{
TT_ERR("Failed to rcu_lock_dom_by_id:%d\n", op->domain);
rcu_unlock_domain(from);
break;
}
if ( from->cap_space == NULL )
{
TT_ERR("cap_space is NULL in from domain in cap_grant()\n");
rcu_unlock_domain(from);
break;
}
*/
to = rcu_lock_domain_by_id(op->u.cap_grant.to);
if ( to == NULL )
{
......@@ -1129,18 +1115,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
list = op->u.cap_grant.list;
size = op->u.cap_grant.size;
if ( (ret = cap_grant(from,to,type,list,size)) != 0 )
if ( (ret = cap_grant(to,type,list,size)) != 0 )
{
TT_ERR("cap_grant failed when called from xc_cap_grant().\n");
rcu_unlock_domain(to);
rcu_unlock_domain(from);
rcu_unlock_domain(d);
//rcu_unlock_domain(d);
break;
}
printk("Leaving XEN_DOMCTL_cap_grant().\n");
rcu_unlock_domain(d);
rcu_unlock_domain(from);
//rcu_unlock_domain(d);
rcu_unlock_domain(to);
}
break;
......@@ -1153,6 +1137,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
printk("In XEN_DOMCTL_cap_check().\n");
ret = -ESRCH;
d = rcu_lock_domain_by_id(op->domain);
if ( d == NULL )
{
......
......@@ -11,6 +11,7 @@
#include <xen/mm.h>
#include <xen/xmalloc.h>
#include <xen/sched.h>
#include <xen/paging.h>
#include <xen/xen-cap.h>
......@@ -145,9 +146,10 @@ int cap_init_hypercalls()
/*
* Creates a capability.
*/
int cap_create(struct domain *d, struct capability *cap)
int cap_create(struct capability *cap)
{
int num_caps;
struct domain *d = current->domain;
init_rand(41);
if ( d->cap_space != NULL )
......@@ -224,9 +226,10 @@ int cap_check(struct domain *d, int type, struct capability *cap)
/*
* 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 cap_grant(struct domain *to, int type, void *list, int size)
{
int i, index, num_caps;
struct domain *from = current->domain;
int ret = 0; /* success */
int *ptr = NULL;
struct capability *cap_ptr = NULL;
......
......@@ -68,8 +68,8 @@ 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_grant(struct domain *from, struct domain *to, int type, void *list,int size );
int cap_create(struct capability *cap);
int cap_grant(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);
extern uint32_t rand_cmwc(void);
......
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