aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHadar Hen Zion <hadarh@mellanox.com>2012-09-05 18:50:49 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-07 12:55:59 -0400
commit7fb40f87c4195ec1728527f30bc744c47a45b366 (patch)
tree4a7356fc76c4db03731d7354c66f7b158682d295
parenta8edc3bf05a3465726afdf635a820761fae0d50b (diff)
net/mlx4_core: Add security check / enforcement for flow steering rules set for VMs
Since VFs may be mapped to VMs which aren't trusted entities, flow steering rules attached through the wrapper on behalf of VFs must be checked to make sure that their L2 specification relate to MAC address assigned to that VF, and add L2 specification if its missing. Signed-off-by: Hadar Hen Zion <hadarh@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c116
-rw-r--r--include/linux/mlx4/device.h11
2 files changed, 127 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 94ceddd17ab2..293c9e820c49 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -42,6 +42,7 @@
42#include <linux/mlx4/cmd.h> 42#include <linux/mlx4/cmd.h>
43#include <linux/mlx4/qp.h> 43#include <linux/mlx4/qp.h>
44#include <linux/if_ether.h> 44#include <linux/if_ether.h>
45#include <linux/etherdevice.h>
45 46
46#include "mlx4.h" 47#include "mlx4.h"
47#include "fw.h" 48#include "fw.h"
@@ -2776,18 +2777,133 @@ ex_put:
2776 return err; 2777 return err;
2777} 2778}
2778 2779
2780/*
2781 * MAC validation for Flow Steering rules.
2782 * VF can attach rules only with a mac address which is assigned to it.
2783 */
2784static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,
2785 struct list_head *rlist)
2786{
2787 struct mac_res *res, *tmp;
2788 __be64 be_mac;
2789
2790 /* make sure it isn't multicast or broadcast mac*/
2791 if (!is_multicast_ether_addr(eth_header->eth.dst_mac) &&
2792 !is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
2793 list_for_each_entry_safe(res, tmp, rlist, list) {
2794 be_mac = cpu_to_be64(res->mac << 16);
2795 if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN))
2796 return 0;
2797 }
2798 pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n",
2799 eth_header->eth.dst_mac, slave);
2800 return -EINVAL;
2801 }
2802 return 0;
2803}
2804
2805/*
2806 * In case of missing eth header, append eth header with a MAC address
2807 * assigned to the VF.
2808 */
2809static int add_eth_header(struct mlx4_dev *dev, int slave,
2810 struct mlx4_cmd_mailbox *inbox,
2811 struct list_head *rlist, int header_id)
2812{
2813 struct mac_res *res, *tmp;
2814 u8 port;
2815 struct mlx4_net_trans_rule_hw_ctrl *ctrl;
2816 struct mlx4_net_trans_rule_hw_eth *eth_header;
2817 struct mlx4_net_trans_rule_hw_ipv4 *ip_header;
2818 struct mlx4_net_trans_rule_hw_tcp_udp *l4_header;
2819 __be64 be_mac = 0;
2820 __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
2821
2822 ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
2823 port = be32_to_cpu(ctrl->vf_vep_port) & 0xff;
2824 eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1);
2825
2826 /* Clear a space in the inbox for eth header */
2827 switch (header_id) {
2828 case MLX4_NET_TRANS_RULE_ID_IPV4:
2829 ip_header =
2830 (struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1);
2831 memmove(ip_header, eth_header,
2832 sizeof(*ip_header) + sizeof(*l4_header));
2833 break;
2834 case MLX4_NET_TRANS_RULE_ID_TCP:
2835 case MLX4_NET_TRANS_RULE_ID_UDP:
2836 l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *)
2837 (eth_header + 1);
2838 memmove(l4_header, eth_header, sizeof(*l4_header));
2839 break;
2840 default:
2841 return -EINVAL;
2842 }
2843 list_for_each_entry_safe(res, tmp, rlist, list) {
2844 if (port == res->port) {
2845 be_mac = cpu_to_be64(res->mac << 16);
2846 break;
2847 }
2848 }
2849 if (!be_mac) {
2850 pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n",
2851 port);
2852 return -EINVAL;
2853 }
2854
2855 memset(eth_header, 0, sizeof(*eth_header));
2856 eth_header->size = sizeof(*eth_header) >> 2;
2857 eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]);
2858 memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN);
2859 memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN);
2860
2861 return 0;
2862
2863}
2864
2779int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, 2865int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
2780 struct mlx4_vhcr *vhcr, 2866 struct mlx4_vhcr *vhcr,
2781 struct mlx4_cmd_mailbox *inbox, 2867 struct mlx4_cmd_mailbox *inbox,
2782 struct mlx4_cmd_mailbox *outbox, 2868 struct mlx4_cmd_mailbox *outbox,
2783 struct mlx4_cmd_info *cmd) 2869 struct mlx4_cmd_info *cmd)
2784{ 2870{
2871
2872 struct mlx4_priv *priv = mlx4_priv(dev);
2873 struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
2874 struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
2785 int err; 2875 int err;
2876 struct mlx4_net_trans_rule_hw_ctrl *ctrl;
2877 struct _rule_hw *rule_header;
2878 int header_id;
2786 2879
2787 if (dev->caps.steering_mode != 2880 if (dev->caps.steering_mode !=
2788 MLX4_STEERING_MODE_DEVICE_MANAGED) 2881 MLX4_STEERING_MODE_DEVICE_MANAGED)
2789 return -EOPNOTSUPP; 2882 return -EOPNOTSUPP;
2790 2883
2884 ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
2885 rule_header = (struct _rule_hw *)(ctrl + 1);
2886 header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
2887
2888 switch (header_id) {
2889 case MLX4_NET_TRANS_RULE_ID_ETH:
2890 if (validate_eth_header_mac(slave, rule_header, rlist))
2891 return -EINVAL;
2892 break;
2893 case MLX4_NET_TRANS_RULE_ID_IPV4:
2894 case MLX4_NET_TRANS_RULE_ID_TCP:
2895 case MLX4_NET_TRANS_RULE_ID_UDP:
2896 pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n");
2897 if (add_eth_header(dev, slave, inbox, rlist, header_id))
2898 return -EINVAL;
2899 vhcr->in_modifier +=
2900 sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;
2901 break;
2902 default:
2903 pr_err("Corrupted mailbox.\n");
2904 return -EINVAL;
2905 }
2906
2791 err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, 2907 err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
2792 vhcr->in_modifier, 0, 2908 vhcr->in_modifier, 0,
2793 MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, 2909 MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 244ba902ab72..6e1b0f973a03 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -798,6 +798,17 @@ enum mlx4_net_trans_rule_id {
798 798
799extern const u16 __sw_id_hw[]; 799extern const u16 __sw_id_hw[];
800 800
801static inline int map_hw_to_sw_id(u16 header_id)
802{
803
804 int i;
805 for (i = 0; i < MLX4_NET_TRANS_RULE_NUM; i++) {
806 if (header_id == __sw_id_hw[i])
807 return i;
808 }
809 return -EINVAL;
810}
811
801enum mlx4_net_trans_promisc_mode { 812enum mlx4_net_trans_promisc_mode {
802 MLX4_FS_PROMISC_NONE = 0, 813 MLX4_FS_PROMISC_NONE = 0,
803 MLX4_FS_PROMISC_UPLINK, 814 MLX4_FS_PROMISC_UPLINK,