From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean Guyader Subject: [PATCH 5/5] v4v: Introduce basic access control to V4V Date: Thu, 28 Jun 2012 17:26:26 +0100 Message-ID: <1340900786-21802-6-git-send-email-jean.guyader@citrix.com> References: <1340900786-21802-1-git-send-email-jean.guyader@citrix.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------true" Return-path: In-Reply-To: <1340900786-21802-1-git-send-email-jean.guyader@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: Jean Guyader List-Id: xen-devel@lists.xenproject.org --------------true Content-Type: text/plain; charset="UTF-8"; format=fixed Content-Transfer-Encoding: quoted-printable Signed-off-by: Jean Guyader --- xen/common/v4v.c | 265 ++++++++++++++++++++++++++++++++++++++++= ++++++ xen/include/public/v4v.h | 3 + xen/include/xen/v4v.h | 26 +++++ 3 files changed, 294 insertions(+) --------------true Content-Type: text/x-patch; name="0005-v4v-Introduce-basic-access-control-to-V4V.patch" Content-Disposition: attachment; filename="0005-v4v-Introduce-basic-access-control-to-V4V.patch" Content-Transfer-Encoding: quoted-printable diff --git a/xen/common/v4v.c b/xen/common/v4v.c index e589fda..381fcdd 100644 --- a/xen/common/v4v.c +++ b/xen/common/v4v.c @@ -43,6 +43,7 @@ #endif =20 =20 +struct list_head viprules =3D LIST_HEAD_INIT(viprules); =20 DEFINE_XEN_GUEST_HANDLE (uint8_t); static struct v4v_ring_info *v4v_ring_find_info (struct domain *d, @@ -1312,7 +1313,221 @@ v4v_notify (struct domain *d, return ret; } =20 +#ifdef V4V_DEBUG +void +v4v_viptables_print_rule (struct v4v_viptables_rule_node *rule) +{ + if (rule =3D=3D NULL) + { + printk("(null)\n"); + return; + } + + if (rule->accept =3D=3D 1) + printk("ACCEPT"); + else + printk("REJECT"); + + printk(" "); + + if (rule->src.domain =3D=3D DOMID_INVALID) + printk("*"); + else + printk("%i", rule->src.domain); + + printk(":"); + + if (rule->src.port =3D=3D -1) + printk("*"); + else + printk("%i", rule->src.port); + + printk(" -> "); + + if (rule->dst.domain =3D=3D DOMID_INVALID) + printk("*"); + else + printk("%i", rule->dst.domain); =20 + printk(":"); + + if (rule->dst.port =3D=3D -1) + printk("*"); + else + printk("%i", rule->dst.port); + + printk("\n"); +} +#endif /* V4V_DEBUG */ + +int +v4v_viptables_add (struct domain *src_d, XEN_GUEST_HANDLE(v4v_viptables_= rule_t) rule, + int32_t position) +{ + struct v4v_viptables_rule_node* new; + struct list_head* tmp; + + /* First rule is n.1 */ + position--; + + new =3D xmalloc (struct v4v_viptables_rule_node); + + if (copy_field_from_guest (new, rule, src)) + return -EFAULT; + if (copy_field_from_guest (new, rule, dst)) + return -EFAULT; + if (copy_field_from_guest (new, rule, accept)) + return -EFAULT; + +#ifdef V4V_DEBUG + printk(KERN_ERR "VIPTables: "); + v4v_viptables_print_rule(new); +#endif /* V4V_DEBUG */ + + tmp =3D &viprules; + while (position !=3D 0 && tmp->next !=3D &viprules) + { + tmp =3D tmp->next; + position--; + } + list_add(&new->list, tmp); + + return 0; +} + +int +v4v_viptables_del (struct domain *src_d, XEN_GUEST_HANDLE(v4v_viptables_= rule_t) rule, + int32_t position) +{ + struct list_head *tmp =3D NULL; + struct list_head *next =3D NULL; + struct v4v_viptables_rule_node *node; + struct v4v_viptables_rule *r; + + if (position !=3D -1) + { + /* We want to delete the rule number */ + tmp =3D &viprules; + while (position !=3D 0 && tmp->next !=3D &viprules) + { + tmp =3D tmp->next; + position--; + } + } + else if (!guest_handle_is_null(rule)) + { + /* We want to delete the rule */ + r =3D xmalloc (struct v4v_viptables_rule); + + if (copy_field_from_guest (r, rule, src)) + return -EFAULT; + if (copy_field_from_guest (r, rule, dst)) + return -EFAULT; + if (copy_field_from_guest (r, rule, accept)) + return -EFAULT; + + list_for_each(tmp, &viprules) + { + node =3D list_entry(tmp, struct v4v_viptables_rule_node, list)= ; + + if ((node->src.domain =3D=3D r->src.domain) && + (node->src.port =3D=3D r->src.port) && + (node->dst.domain =3D=3D r->dst.domain) && + (node->dst.port =3D=3D r->dst.port)) + { + position =3D 0; + break; + } + } + xfree(r); + } + else + { + /* We want to flush the rules! */ + printk(KERN_ERR "VIPTables: flushing rules\n"); + list_for_each_safe(tmp, next, &viprules) + { + node =3D list_entry(tmp, struct v4v_viptables_rule_node, list)= ; + list_del(tmp); + xfree(node); + } + } + +#ifdef V4V_DEBUG + if (position =3D=3D 0 && tmp !=3D &viprules) + { + printk(KERN_ERR "VIPTables: deleting rule: "); + node =3D list_entry(tmp, struct v4v_viptables_rule_node, list); + v4v_viptables_print_rule(node); + list_del(tmp); + xfree(node); + } +#endif /* V4V_DEBUG */ + + return 0; +} + +static size_t +v4v_viptables_list (struct domain *src_d, XEN_GUEST_HANDLE(v4v_viptables= _list_t) list_hnd) +{ + struct list_head *ptr; + struct v4v_viptables_rule_node *node; + struct v4v_viptables_list rules_list; + uint32_t nbrules; + + memset(&rules_list, 0, sizeof (rules_list)); + if (copy_field_from_guest (&rules_list, list_hnd, nb_rules)) + return -EFAULT; + + ptr =3D viprules.next; + while (rules_list.nb_rules !=3D 0 && ptr->next !=3D &viprules) + { + ptr =3D ptr->next; + rules_list.start_rule--; + } + + if (rules_list.nb_rules !=3D 0) + return -EFAULT; + + nbrules =3D 0; + while (nbrules < rules_list.nb_rules && ptr !=3D &viprules) + { + node =3D list_entry(ptr, struct v4v_viptables_rule_node, list); + + rules_list.rules[rules_list.nb_rules].src =3D node->src; + rules_list.rules[rules_list.nb_rules].dst =3D node->dst; + rules_list.rules[rules_list.nb_rules].accept =3D node->accept; + + nbrules++; + ptr =3D ptr->next; + } + + if (copy_to_guest(list_hnd, &rules_list, 1)) + return -EFAULT; + + return 0; +} + +static size_t +v4v_viptables_check (v4v_addr_t * src, v4v_addr_t * dst) +{ + struct list_head *ptr; + struct v4v_viptables_rule_node *node; + + list_for_each(ptr, &viprules) + { + node =3D list_entry(ptr, struct v4v_viptables_rule_node, list); + + if ((node->src.domain =3D=3D DOMID_INVALID || node->src.domain =3D= =3D src->domain) && + (node->src.port =3D=3D -1 || node->src.port =3D= =3D src->port) && + (node->dst.domain =3D=3D DOMID_INVALID || node->dst.domain =3D= =3D dst->domain) && + (node->dst.port =3D=3D -1 || node->dst.port =3D= =3D dst->port)) + return !node->accept; + } + + /* Defaulting to ACCEPT */ + return 0; +} =20 /*Hypercall to do the send*/ static size_t @@ -1351,6 +1566,15 @@ v4v_send (struct domain *src_d, v4v_addr_t * src_a= ddr, return -ECONNREFUSED; } =20 + if (v4v_viptables_check(src_addr, dst_addr) !=3D 0) + { + read_unlock (&v4v_lock); + printk(KERN_ERR "V4V: VIPTables REJECTED %i:%i -> %i:%i\n", + src_addr->domain, src_addr->port, + dst_addr->domain, dst_addr->port); + return -ECONNREFUSED; + } + do { if ( !dst_d->v4v ) @@ -1437,6 +1661,15 @@ v4v_sendv (struct domain *src_d, v4v_addr_t * src_= addr, return -ECONNREFUSED; } =20 + if (v4v_viptables_check(src_addr, dst_addr) !=3D 0) + { + read_unlock (&v4v_lock); + printk(KERN_ERR "V4V: VIPTables REJECTED %i:%i -> %i:%i\n", + src_addr->domain, src_addr->port, + dst_addr->domain, dst_addr->port); + return -ECONNREFUSED; + } + do { if ( !dst_d->v4v ) @@ -1596,6 +1829,38 @@ do_v4v_op (int cmd, XEN_GUEST_HANDLE (void) arg1, rc =3D v4v_notify (d, ring_data_hnd); break; } + case V4VOP_viptables_add: + { + uint32_t position =3D arg4; + XEN_GUEST_HANDLE (v4v_viptables_rule_t) rule_hnd =3D + guest_handle_cast (arg1, v4v_viptables_rule_t); + rc =3D -EPERM; + if (!IS_PRIV(d)) + goto out; + rc =3D v4v_viptables_add (d, rule_hnd, position); + break; + } + case V4VOP_viptables_del: + { + uint32_t position =3D arg4; + XEN_GUEST_HANDLE (v4v_viptables_rule_t) rule_hnd =3D + guest_handle_cast (arg1, v4v_viptables_rule_t); + rc =3D -EPERM; + if (!IS_PRIV(d)) + goto out; + rc =3D v4v_viptables_del (d, rule_hnd, position); + break; + } + case V4VOP_viptables_list: + { + XEN_GUEST_HANDLE (v4v_viptables_list_t) rules_list_hnd =3D + guest_handle_cast(arg1, v4v_viptables_list_t); + rc =3D -EPERM; + if (!IS_PRIV(d)) + goto out; + rc =3D v4v_viptables_list (d, rules_list_hnd); + break; + } default: rc =3D -ENOSYS; break; diff --git a/xen/include/public/v4v.h b/xen/include/public/v4v.h index 197770e..d8ca507 100644 --- a/xen/include/public/v4v.h +++ b/xen/include/public/v4v.h @@ -213,6 +213,9 @@ * NULL, NULL, nent, 0) */ =20 +#define V4VOP_viptables_add 6 +#define V4VOP_viptables_del 7 +#define V4VOP_viptables_list 8 =20 #define V4VOP_sendv 5 /* diff --git a/xen/include/xen/v4v.h b/xen/include/xen/v4v.h index 641a6a8..e5b4cb7 100644 --- a/xen/include/xen/v4v.h +++ b/xen/include/xen/v4v.h @@ -103,6 +103,32 @@ struct v4v_ring_message_header uint8_t data[0]; } V4V_PACKED; =20 +typedef struct v4v_viptables_rule +{ + struct v4v_addr src; + struct v4v_addr dst; + uint32_t accept; +} V4V_PACKED v4v_viptables_rule_t; + +DEFINE_XEN_GUEST_HANDLE (v4v_viptables_rule_t); + +struct v4v_viptables_rule_node +{ + struct list_head list; + struct v4v_addr src; + struct v4v_addr dst; + uint32_t accept; +} V4V_PACKED; + +typedef struct v4v_viptables_list +{ + uint32_t start_rule; + uint32_t nb_rules; + struct v4v_viptables_rule rules[0]; +} V4V_PACKED v4v_viptables_list_t; + +DEFINE_XEN_GUEST_HANDLE (v4v_viptables_list_t); + /* * Helper functions */ --------------true Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel --------------true--