From 6febd9b3edfbe66a8adca43ae4f432b891564465 Mon Sep 17 00:00:00 2001 From: Nicholas Tsirakis Date: Fri, 12 Apr 2019 11:04:37 -0400 Subject: [PATCH 1/4] [argo-module] Add viptables Add hypervisor wrapper calls for viptables add, del, and list to argo kernel module. OXT-1502 Signed-off-by: Christopher Clark Signed-off-by: Nicholas Tsirakis --- argo-linux/argo-module.c | 102 ++++++++++++++++++++++++++++ argo-linux/include/linux/argo_dev.h | 8 +++ argo-linux/include/xen/argo.h | 32 +++++++++ 3 files changed, 142 insertions(+) diff --git a/argo-linux/argo-module.c b/argo-linux/argo-module.c index d730b83..10ef8bb 100644 --- a/argo-linux/argo-module.c +++ b/argo-linux/argo-module.c @@ -700,6 +700,27 @@ H_argo_notify(xen_argo_ring_data_t *rd) return HYPERVISOR_argo_op(XEN_ARGO_OP_notify, rd, NULL, 0, 0); } +static int +H_viptables_add(xen_argo_viptables_rule_t* rule, int position) +{ + return HYPERVISOR_argo_op(XEN_ARGO_OP_viptables_add, rule, NULL, 0, + position); +} + +static int +H_viptables_del(xen_argo_viptables_rule_t* rule, int position) +{ + return HYPERVISOR_argo_op(XEN_ARGO_OP_viptables_del, rule, NULL, 0, + position); +} + +static int +H_viptables_list(xen_argo_viptables_list_t *rules_list) +{ + return HYPERVISOR_argo_op(XEN_ARGO_OP_viptables_list, rules_list, NULL, 0, + 0); +} + /*********************port/ring uniqueness **********/ /*Need to hold write lock for all of these*/ @@ -1539,6 +1560,28 @@ argo_notify(void) DEBUG_APPLE; } +/*********************** viptables ********************/ +static int +viptables_add(struct argo_private *p, struct xen_argo_viptables_rule* rule, + int position) +{ + return H_viptables_add(rule, position); +} + +static int +viptables_del(struct argo_private *p, struct xen_argo_viptables_rule* rule, + int position) +{ + return H_viptables_del(rule, position); +} + +static int +viptables_list(struct argo_private *p, + struct xen_argo_viptables_list *rules_list) +{ + return H_viptables_list(rules_list); +} + /*********************** state machines ********************/ static int connector_state_machine(struct argo_private *p, struct argo_stream_header *sh) @@ -3818,6 +3861,65 @@ argo_ioctl(struct file *f, unsigned int cmd, unsigned long arg) rc = argo_recvfrom (p, a.buf, a.len, a.flags, NULL, nonblock); } break; + case ARGOIOCVIPTABLESADD: + DEBUG_APPLE; + { + struct viptables_rule_pos rule_pos; + struct xen_argo_viptables_rule rule; + + if ( copy_from_user(&rule_pos, (void __user *)arg, + sizeof(struct viptables_rule_pos)) || + copy_from_user(&rule, rule_pos.rule, + sizeof(struct xen_argo_viptables_rule)) ) + return -EFAULT; + + rc = viptables_add(p, &rule, rule_pos.position); + } + break; + case ARGOIOCVIPTABLESDEL: + DEBUG_APPLE; + { + struct viptables_rule_pos rule_pos; + struct xen_argo_viptables_rule rule; + + if ( copy_from_user(&rule_pos, (void __user *)arg, + sizeof(struct viptables_rule_pos)) ) + return -EFAULT; + + if ( rule_pos.rule ) + { + if ( copy_from_user(&rule, rule_pos.rule, + sizeof(struct xen_argo_viptables_rule)) ) + return -EFAULT; + + rc = viptables_del(p, &rule, rule_pos.position); + } + else + rc = viptables_del(p, NULL, rule_pos.position); + } + break; + case ARGOIOCVIPTABLESLIST: + DEBUG_APPLE; + { + struct xen_argo_viptables_list rules_list; + + if ( !access_ok(VERIFY_WRITE, (void __user *)arg, + sizeof (struct xen_argo_viptables_list)) ) + return -EFAULT; + + if ( get_user(rules_list.nrules, + &((struct xen_argo_viptables_list *)arg)->nrules) ) + return -EFAULT; + + rc = viptables_list(p, &rules_list); + if ( rc ) + return rc; + + if ( copy_to_user((void __user *)arg, &rules_list, + sizeof(struct xen_argo_viptables_list)) ) + return -EFAULT; + } + break; default: printk(KERN_ERR "unknown ioctl: cmd=%x ARGOIOCACCEPT=%lx\n", cmd, ARGOIOCACCEPT); diff --git a/argo-linux/include/linux/argo_dev.h b/argo-linux/include/linux/argo_dev.h index 5f86797..0d1b985 100644 --- a/argo-linux/include/linux/argo_dev.h +++ b/argo-linux/include/linux/argo_dev.h @@ -58,6 +58,11 @@ struct argo_ring_id { xen_argo_port_t aport; }; +struct viptables_rule_pos { + struct xen_argo_viptables_rule* rule; + int position; +}; + #define ARGO_TYPE 'W' #define ARGOIOCSETRINGSIZE _IOW (ARGO_TYPE, 1, uint32_t) @@ -74,5 +79,8 @@ struct argo_ring_id { #define ARGOIOCSEND32 _IOW (ARGO_TYPE, 9, struct argo_dev_32) #define ARGOIOCRECV32 _IOW (ARGO_TYPE, 10, struct argo_dev_32) #define ARGOIOCGETSOCKTYPE _IOW (ARGO_TYPE, 11, int) +#define ARGOIOCVIPTABLESADD _IOW (ARGO_TYPE, 12, struct viptables_rule_pos) +#define ARGOIOCVIPTABLESDEL _IOW (ARGO_TYPE, 13, struct viptables_rule_pos) +#define ARGOIOCVIPTABLESLIST _IOW (ARGO_TYPE, 14, uint32_t) /*unused args */ #endif diff --git a/argo-linux/include/xen/argo.h b/argo-linux/include/xen/argo.h index 136a91f..2b300b9 100644 --- a/argo-linux/include/xen/argo.h +++ b/argo-linux/include/xen/argo.h @@ -43,6 +43,8 @@ /* Fixed-width type for "argo port" number. Nothing to do with evtchns. */ typedef uint32_t xen_argo_port_t; +#define XEN_ARGO_PORT_ANY 0xffffffffU + /* gfn type: 64-bit fixed-width on all architectures */ typedef uint64_t xen_argo_gfn_t; @@ -166,6 +168,21 @@ struct xen_argo_ring_message_header #endif }; +typedef struct xen_argo_viptables_rule +{ + struct xen_argo_addr src; + struct xen_argo_addr dst; + uint32_t accept; +} xen_argo_viptables_rule_t; + +#define XEN_ARGO_VIPTABLES_LIST_SIZE 8 + +typedef struct xen_argo_viptables_list +{ + struct xen_argo_viptables_rule rules[XEN_ARGO_VIPTABLES_LIST_SIZE]; + uint32_t nrules; +} xen_argo_viptables_list_t; + /* * Hypercall operations */ @@ -275,4 +292,19 @@ struct xen_argo_ring_message_header */ #define XEN_ARGO_OP_notify 4 +/* + * XEN_ARGO_OP_viptables_add + */ +#define XEN_ARGO_OP_viptables_add 6 + +/* + * XEN_ARGO_OP_viptables_del + */ +#define XEN_ARGO_OP_viptables_del 7 + +/* + * XEN_ARGO_OP_viptables_list + */ +#define XEN_ARGO_OP_viptables_list 8 + #endif From b5f2406d1dd5ae5d4b1b26ea67f905966d69f8d2 Mon Sep 17 00:00:00 2001 From: Nicholas Tsirakis Date: Fri, 12 Apr 2019 11:04:58 -0400 Subject: [PATCH 2/4] [libargo] Add viptables Add kernel wrapper calls for viptables add, del, list, and flush to libargo. OXT-1502 Signed-off-by: Christopher Clark Signed-off-by: Nicholas Tsirakis --- libargo/src/argo.c | 121 ++++++++++++++++++++++++++++++++++++++++++ libargo/src/libargo.h | 4 ++ 2 files changed, 125 insertions(+) diff --git a/libargo/src/argo.c b/libargo/src/argo.c index be294f7..c4e1aec 100644 --- a/libargo/src/argo.c +++ b/libargo/src/argo.c @@ -398,3 +398,124 @@ argo_getsockopt (int fd, int level, int optname, errno = ENOPROTOOPT; return -1; } + +int +viptables_add (int fd, xen_argo_viptables_rule_t* rule, int position) +{ + int ret; + struct viptables_rule_pos rule_pos; + + mlock (rule, sizeof(xen_argo_viptables_rule_t)); + rule_pos.rule = rule; + rule_pos.position = position; + + ret = argo_ioctl (fd, ARGOIOCVIPTABLESADD, &rule_pos); + + munlock (rule, sizeof(xen_argo_viptables_rule_t)); + + return ret; +} + +int +viptables_del (int fd, xen_argo_viptables_rule_t* rule, int position) +{ + int ret; + + struct viptables_rule_pos rule_pos; + + if (rule != NULL) + mlock (rule, sizeof(xen_argo_viptables_rule_t)); + + rule_pos.rule = rule; + rule_pos.position = position; + + ret = argo_ioctl (fd, ARGOIOCVIPTABLESDEL, &rule_pos); + + if (rule != NULL) + munlock (rule, sizeof(xen_argo_viptables_rule_t)); + + return ret; +} + +int +viptables_flush (int fd) +{ + int ret; + + struct viptables_rule_pos rule_pos; + + rule_pos.rule = NULL; + rule_pos.position = -1; + + ret = argo_ioctl (fd, ARGOIOCVIPTABLESDEL, &rule_pos); + + return ret; +} + +static void +viptables_print_rule(struct xen_argo_viptables_rule *rule) +{ + if (rule->accept == 1) + printf("ACCEPT"); + else + printf("REJECT"); + + printf(" "); + + if (rule->src.domain_id == DOMID_INVALID) + printf("*"); + else + printf("%i", rule->src.domain_id); + + printf(":"); + + if (rule->src.aport == XEN_ARGO_PORT_ANY) + printf("*"); + else + printf("%i", rule->src.aport); + + printf(" -> "); + + if (rule->dst.domain_id == DOMID_INVALID) + printf("*"); + else + printf("%i", rule->dst.domain_id); + + printf(":"); + + if (rule->dst.aport == XEN_ARGO_PORT_ANY) + printf("*"); + else + printf("%i", rule->dst.aport); + + printf("\n"); +} + +int +viptables_list (int fd) +{ + int ret, i, total_rules_printed = 0, rules_i = 1; + + struct xen_argo_viptables_list rules_list; + memset(&rules_list, 0, sizeof (rules_list)); + + do + { + rules_list.nrules = total_rules_printed; + ret = argo_ioctl (fd, ARGOIOCVIPTABLESLIST, &rules_list); + + if (ret != 0) + return ret; + + for (i = 0; i < rules_list.nrules; ++i) + { + printf("%i : ", rules_i++); + viptables_print_rule(&rules_list.rules[i]); + } + + total_rules_printed += rules_list.nrules; + + } while (rules_list.nrules == XEN_ARGO_VIPTABLES_LIST_SIZE); + + return ret; +} diff --git a/libargo/src/libargo.h b/libargo/src/libargo.h index 4cb7ffd..c07d028 100644 --- a/libargo/src/libargo.h +++ b/libargo/src/libargo.h @@ -60,6 +60,10 @@ ssize_t argo_recvfrom(int fd, void *buf, size_t len, int flags, xen_argo_addr_t int argo_getsockname(int fd, xen_argo_addr_t *out_addr, domid_t *out_partner_id); int argo_getpeername(int fd, xen_argo_addr_t *out_addr); int argo_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen); +int viptables_add (int fd, xen_argo_viptables_rule_t *rule, int position); +int viptables_del (int fd, xen_argo_viptables_rule_t *rule, int position); +int viptables_flush (int fd); +int viptables_list (int fd); # ifdef __cplusplus } From 44a7f21bb12b802eda0d347bd77eb70cc2a98b0c Mon Sep 17 00:00:00 2001 From: Nicholas Tsirakis Date: Fri, 12 Apr 2019 11:05:25 -0400 Subject: [PATCH 3/4] [viptables] Add the viptables utility binary OXT-1502 Signed-off-by: Christopher Clark Signed-off-by: Nicholas Tsirakis --- libargo/app/Makefile.am | 5 +- libargo/app/viptables.c | 190 ++++++++++++++++++++++++++++++++++++++++ libargo/man/viptables.1 | 77 ++++++++++++++++ 3 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 libargo/app/viptables.c create mode 100644 libargo/man/viptables.1 diff --git a/libargo/app/Makefile.am b/libargo/app/Makefile.am index 78a00c1..c875473 100644 --- a/libargo/app/Makefile.am +++ b/libargo/app/Makefile.am @@ -20,10 +20,13 @@ AM_CPPFLAGS = -I$(srcdir)/../src AM_CFLAGS = -g -bin_PROGRAMS = ttcp-argo argo-proxy +bin_PROGRAMS = ttcp-argo argo-proxy viptables ttcp_argo_SOURCES = ttcp.c ttcp_argo_LDADD = ../src/libargo.la argo_proxy_SOURCES = proxy.c argo_proxy_LDADD = ../src/libargo.la + +viptables_SOURCES = viptables.c +viptables_LDADD = ../src/libargo.la diff --git a/libargo/app/viptables.c b/libargo/app/viptables.c new file mode 100644 index 0000000..798b93e --- /dev/null +++ b/libargo/app/viptables.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2019 BAE Systems + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include "libargo.h" + +enum action_e +{ + NONE, + APPEND, + INSERT, + LIST, + DELETE, + FLUSH +}; + +void usage(int exit_value) +{ + fprintf(stderr, "Usage: viptables command [rule]\n"); + fprintf(stderr, "Commands :\n"); + fprintf(stderr, " --append -A Append rule\n"); + fprintf(stderr, " --insert -I Insert rule before rule \n"); + fprintf(stderr, " --list -L List rules\n"); + fprintf(stderr, " --delete -D[] Delete rule or the following rule\n"); + fprintf(stderr, " --flush -F Flush rules\n"); + fprintf(stderr, " --help -h Help\n"); + fprintf(stderr, "Rule options:\n"); + fprintf(stderr, " --dom-in -d Client domid\n"); + fprintf(stderr, " --dom-out -e Server domid\n"); + fprintf(stderr, " --port-in -p Client port\n"); + fprintf(stderr, " --port-out -q Server port\n"); + fprintf(stderr, " --jump -j {ACCEPT|REJECT} What to do\n"); + + exit(exit_value); +} + +int main (int argc, char** argv) +{ + int c; + int fd; + int rc = -1; + + xen_argo_viptables_rule_t rule; + int position = -1; + enum action_e action = NONE; + + rule.src.domain_id = DOMID_INVALID; + rule.src.aport = XEN_ARGO_PORT_ANY; + rule.dst.domain_id = DOMID_INVALID; + rule.dst.aport = XEN_ARGO_PORT_ANY; + rule.accept = XEN_ARGO_PORT_ANY; + + static struct option long_options[] = + { + {"append", no_argument, 0, 'A'}, + {"insert", required_argument, 0, 'I'}, + {"list", no_argument, 0, 'L'}, + {"delete", optional_argument, 0, 'D'}, + {"flush", no_argument, 0, 'F'}, + + {"dom-in", required_argument, 0, 'd'}, + {"dom-out", required_argument, 0, 'e'}, + {"port-in", required_argument, 0, 'p'}, + {"port-out", required_argument, 0, 'q'}, + + {"jump", required_argument, 0, 'j'}, + + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + int option_index = 0; + + c = getopt_long (argc, argv, "AI:LD::Fd:e:p:q:j:h", + long_options, &option_index); + + if (c == -1) + usage(1); + + while (c >= 0) + { + switch (c) + { + case 'A': + action = APPEND; + break; + case 'I': + action = INSERT; + position = atoi(optarg); + break; + case 'L': + action = LIST; + break; + case 'D': + action = DELETE; + if (optarg != NULL && *optarg != '\0') + position = atoi(optarg); + break; + case 'F': + action = FLUSH; + break; + case 'd': + rule.src.domain_id = atoi(optarg); + break; + case 'e': + rule.dst.domain_id = atoi(optarg); + break; + case 'p': + rule.src.aport = atoi(optarg); + break; + case 'q': + rule.dst.aport = atoi(optarg); + break; + case 'j': + if (!strcmp(optarg, "ACCEPT")) + rule.accept = 1; + else if (!strcmp(optarg, "REJECT")) + rule.accept = 0; + else + usage(1); + break; + case 'h': + usage(0); + break; + default: + usage(1); + } + + c = getopt_long (argc, argv, "AI:LD:d:e:p:q:j:h", + long_options, &option_index); + } + + fd = argo_socket(SOCK_STREAM); + if (fd < 0) + { + perror("argo_socket"); + exit(1); + } + + switch (action) + { + case APPEND: + if (rule.accept == -1) + usage(1); + rc = viptables_add(fd, &rule, -1); + break; + case INSERT: + if (rule.accept == -1) + usage(1); + rc = viptables_add(fd, &rule, position); + break; + case LIST: + rc = viptables_list(fd); + break; + case DELETE: + if (position != -1) + rc = viptables_del(fd, NULL, position); + else + rc = viptables_del(fd, &rule, -1); + break; + case FLUSH: + rc = viptables_flush(fd); + break; + default: + usage(1); + } + + argo_close(fd); + + return rc; +} diff --git a/libargo/man/viptables.1 b/libargo/man/viptables.1 new file mode 100644 index 0000000..bd7123d --- /dev/null +++ b/libargo/man/viptables.1 @@ -0,0 +1,77 @@ +.TH USAGE: "1" "November 2011" "Usage: viptables command [rule]" "User Commands" +.SH NAME +Usage: \- Usage of viptables +.SH SYNOPSIS +.B viptables +\fIcommand \fR[\fIrule\fR] +.SH DESCRIPTION +.SS "Commands :" +.TP +\fB\-\-append\fR \fB\-A\fR +Append rule +.TP +\fB\-\-insert\fR \fB\-I\fR +Insert rule before rule +.TP +\fB\-\-list\fR \fB\-L\fR +List rules +.TP +\fB\-\-delete\fR \fB\-D[\fR] +Delete rule or the following rule +.TP +\fB\-\-flush\fR \fB\-F\fR +Flush rules +.TP +\fB\-\-help\fR \fB\-h\fR +Help +.SS "Rule options:" +.TP +\fB\-\-dom\-in\fR \fB\-d\fR +Client domid +.TP +\fB\-\-dom\-out\fR \fB\-e\fR +Server domid +.TP +\fB\-\-port\-in\fR \fB\-p\fR +Client port +.TP +\fB\-\-port\-out\fR \fB\-q\fR +Server port +.TP +\fB\-\-jump\fR \fB\-j\fR {ACCEPT|REJECT} +What to do +.SS "Commands :" +.TP +\fB\-\-append\fR \fB\-A\fR +Append rule +.TP +\fB\-\-insert\fR \fB\-I\fR +Insert rule before rule +.TP +\fB\-\-list\fR \fB\-L\fR +List rules +.TP +\fB\-\-delete\fR \fB\-D[\fR] +Delete rule or the following rule +.TP +\fB\-\-flush\fR \fB\-F\fR +Flush rules +.TP +\fB\-\-help\fR \fB\-h\fR +Help +.SS "Rule options:" +.TP +\fB\-\-dom\-in\fR \fB\-d\fR +Client domid +.TP +\fB\-\-dom\-out\fR \fB\-e\fR +Server domid +.TP +\fB\-\-port\-in\fR \fB\-p\fR +Client port +.TP +\fB\-\-port\-out\fR \fB\-q\fR +Server port +.TP +\fB\-\-jump\fR \fB\-j\fR {ACCEPT|REJECT} +What to do From d4a0ec92fc41d4e6d6f2514b4fa1475d55d85aac Mon Sep 17 00:00:00 2001 From: Nicholas Tsirakis Date: Wed, 17 Apr 2019 10:07:19 -0400 Subject: [PATCH 4/4] [argo-module] Add 4.19 kernel support OXT-1616 Signed-off-by: Nicholas Tsirakis --- argo-linux/argo-module.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/argo-linux/argo-module.c b/argo-linux/argo-module.c index 10ef8bb..d64e469 100644 --- a/argo-linux/argo-module.c +++ b/argo-linux/argo-module.c @@ -3078,8 +3078,8 @@ static int allocate_fd_with_private (void *private) { int fd; + const char * name = ""; struct file *f; - struct qstr name = { .name = "" }; struct path path; struct inode *ind; @@ -3091,12 +3091,14 @@ allocate_fd_with_private (void *private) if ( fd < 0 ) return fd; +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) ) path.dentry = d_alloc_pseudo(argo_mnt->mnt_sb, &name); - if ( unlikely(!path.dentry) ) - { + if (unlikely(!path.dentry)) { put_unused_fd(fd); - return -ENOMEM; + return -ENOMEM; } +#endif + ind = new_inode(argo_mnt->mnt_sb); ind->i_ino = get_next_ino(); ind->i_fop = argo_mnt->mnt_root->d_inode->i_fop; @@ -3104,12 +3106,17 @@ allocate_fd_with_private (void *private) ind->i_mode = argo_mnt->mnt_root->d_inode->i_mode; ind->i_uid = current_fsuid(); ind->i_gid = current_fsgid(); +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) ) d_instantiate(path.dentry, ind); - path.mnt = mntget(argo_mnt); +#endif DEBUG_APPLE; +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) ) f = alloc_file(&path, FMODE_READ | FMODE_WRITE, &argo_fops_stream); +#else + f = alloc_file_pseudo(ind, argo_mnt, name, O_RDWR, &argo_fops_stream); +#endif if ( !f ) { //FIXME putback fd? @@ -3117,8 +3124,9 @@ allocate_fd_with_private (void *private) } f->private_data = private; +#if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) ) f->f_flags = O_RDWR; - +#endif fd_install (fd, f); return fd;