From 2bcfce77a2712960fadac2f034c1df4826780608 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Mon, 15 Dec 2014 17:20:31 -0500 Subject: [PATCH 1/1] LU-5935 lnet: Fixes to make lnetctl function as expected. During testing of the lnetctl utility I ran into some issues. One of the problems is when you print out help for peer_credits you get help for stats. With this patch the help option for peer_credits is set to return the proper help message. The second problem was for grabbing stats data. No data was returned but instead it reported a error. The reason for this is that libcfs_ioctl_getdata() test to see if the size of the data passed in is less than the struct libcfs_ioctl_data in size. For the stats function its data structure struct lnet_ioctl_lnet_stats is smaller than what is allowed. Instead of checking if the data is less than libcfs_ioctl_data in size we check to ensure that the data is not smaller than the ioctl hdr data which is universal. The bug in libcfs_ioctl_getdata() exposed a bunch of cases with new ioctls that don't check to see if the data imported from userland equals the size reported in the ioctl hdr data. We address those cases in this patch as well. Signed-off-by: James Simmons Change-Id: Ib5abc288d94b0f93549312a3fe283cbb8205febf Reviewed-on: http://review.whamcloud.com/12782 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Liang Zhen Reviewed-by: Doug Oucharek Reviewed-by: Oleg Drokin --- libcfs/include/libcfs/libcfs_ioctl.h | 2 +- libcfs/libcfs/linux/linux-module.c | 2 +- lnet/lnet/api-ni.c | 39 +++++++++++++++++++++++++++++++++++ lnet/utils/.gitignore | 1 + lnet/utils/lnetconfig/liblnetconfig.c | 4 ++-- lnet/utils/lnetctl.c | 2 +- 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/libcfs/include/libcfs/libcfs_ioctl.h b/libcfs/include/libcfs/libcfs_ioctl.h index 3c62e28..b5d650f 100644 --- a/libcfs/include/libcfs/libcfs_ioctl.h +++ b/libcfs/include/libcfs/libcfs_ioctl.h @@ -157,7 +157,7 @@ struct libcfs_ioctl_handler { /* - * DLC Speicif IOCTL numbers. + * DLC Specific IOCTL numbers. * In order to maintain backward compatibility with any possible external * tools which might be accessing the IOCTL numbers, a new group of IOCTL * number have been allocated. diff --git a/libcfs/libcfs/linux/linux-module.c b/libcfs/libcfs/linux/linux-module.c index 4cde538..7175e44 100644 --- a/libcfs/libcfs/linux/linux-module.c +++ b/libcfs/libcfs/linux/linux-module.c @@ -76,7 +76,7 @@ int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, RETURN(-EINVAL); } - if (hdr.ioc_len < sizeof(struct libcfs_ioctl_data)) { + if (hdr.ioc_len < sizeof(struct libcfs_ioctl_hdr)) { CERROR("libcfs ioctl: user buffer too small for ioctl\n"); RETURN(-EINVAL); } diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index 0d1e7ec..7a3c8a3 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -2116,6 +2116,10 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_ADD_ROUTE: config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + LNET_MUTEX_LOCK(&the_lnet.ln_api_mutex); rc = lnet_add_route(config->cfg_net, config->cfg_config_u.cfg_route.rtr_hop, @@ -2127,6 +2131,10 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_DEL_ROUTE: config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + LNET_MUTEX_LOCK(&the_lnet.ln_api_mutex); rc = lnet_del_route(config->cfg_net, config->cfg_nid); LNET_MUTEX_UNLOCK(&the_lnet.ln_api_mutex); @@ -2134,6 +2142,10 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_GET_ROUTE: config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + return lnet_get_route(config->cfg_count, &config->cfg_net, &config->cfg_config_u.cfg_route.rtr_hop, @@ -2144,7 +2156,13 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_GET_NET: { struct lnet_ioctl_net_config *net_config; + size_t total = sizeof(*config) + sizeof(*net_config); + config = arg; + + if (config->cfg_hdr.ioc_len < total) + return -EINVAL; + net_config = (struct lnet_ioctl_net_config *) config->cfg_bulk; if (config == NULL || net_config == NULL) @@ -2168,6 +2186,9 @@ LNetCtl(unsigned int cmd, void *arg) { struct lnet_ioctl_lnet_stats *lnet_stats = arg; + if (lnet_stats->st_hdr.ioc_len < sizeof(*lnet_stats)) + return -EINVAL; + lnet_counters_get(&lnet_stats->st_cntrs); return 0; } @@ -2175,6 +2196,10 @@ LNetCtl(unsigned int cmd, void *arg) #if defined(__KERNEL__) && defined(LNET_ROUTER) case IOC_LIBCFS_CONFIG_RTR: config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + LNET_MUTEX_LOCK(&the_lnet.ln_api_mutex); if (config->cfg_config_u.cfg_buffers.buf_enable) { rc = lnet_rtrpools_enable(); @@ -2187,6 +2212,10 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_ADD_BUF: config = arg; + + if (config->cfg_hdr.ioc_len < sizeof(*config)) + return -EINVAL; + LNET_MUTEX_LOCK(&the_lnet.ln_api_mutex); rc = lnet_rtrpools_adjust(config->cfg_config_u.cfg_buffers. buf_tiny, @@ -2200,13 +2229,23 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_GET_BUF: { struct lnet_ioctl_pool_cfg *pool_cfg; + size_t total = sizeof(*config) + sizeof(*pool_cfg); + config = arg; + + if (config->cfg_hdr.ioc_len < total) + return -EINVAL; + pool_cfg = (struct lnet_ioctl_pool_cfg *)config->cfg_bulk; return lnet_get_rtr_pool_cfg(config->cfg_count, pool_cfg); } case IOC_LIBCFS_GET_PEER_INFO: { struct lnet_ioctl_peer *peer_info = arg; + + if (peer_info->pr_hdr.ioc_len < sizeof(*peer_info)) + return -EINVAL; + return lnet_get_peer_info( peer_info->pr_count, &peer_info->pr_nid, diff --git a/lnet/utils/.gitignore b/lnet/utils/.gitignore index c24c5d2..bc0a39e 100644 --- a/lnet/utils/.gitignore +++ b/lnet/utils/.gitignore @@ -1,4 +1,5 @@ /Makefile.in /routerstat /wirecheck +/lnetctl /lst diff --git a/lnet/utils/lnetconfig/liblnetconfig.c b/lnet/utils/lnetconfig/liblnetconfig.c index bd57092..82ef583 100644 --- a/lnet/utils/lnetconfig/liblnetconfig.c +++ b/lnet/utils/lnetconfig/liblnetconfig.c @@ -988,8 +988,8 @@ int lustre_lnet_show_peer_credits(int seq_no, struct cYAML **show_rc, goto out; peer_root = cYAML_create_seq(root, "peer"); - if (peer_root == NULL) - goto out; + if (peer_root == NULL) + goto out; do { for (i = 0;; i++) { diff --git a/lnet/utils/lnetctl.c b/lnet/utils/lnetctl.c index 978da69..43ed605 100644 --- a/lnet/utils/lnetctl.c +++ b/lnet/utils/lnetctl.c @@ -976,7 +976,7 @@ command_t list[] = { "--help} FILE.yaml"}, {"export", jt_export, 0, "export {--help} FILE.yaml"}, {"stats", jt_stats, 0, "stats {show | help}"}, - {"peer_credits", jt_peer_credits, 0, "stats {show | help}"}, + {"peer_credits", jt_peer_credits, 0, "peer_credits {show | help}"}, {"help", Parser_help, 0, "help"}, {"exit", Parser_quit, 0, "quit"}, {"quit", Parser_quit, 0, "quit"}, -- 1.8.3.1