diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 352d9d2ef3d26f73181963ed67f1b107774f32f9..6bee254d34eeb1f3e02b5f0734b3c4ac3e00fc00 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2531,154 +2531,6 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen) return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_SET_RSS_HENA, aq_ret); } -/** - * i40e_vc_validate_vf_msg - * @ver: Virtchnl version info - * @v_opcode: Opcode for the message - * @msg: pointer to the msg buffer - * @msglen: msg length - * - * validate msg format against struct for each opcode - **/ -static int -i40e_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, - u8 *msg, u16 msglen) -{ - bool err_msg_format = false; - int valid_len = 0; - - /* Validate message length. */ - switch (v_opcode) { - case VIRTCHNL_OP_VERSION: - valid_len = sizeof(struct virtchnl_version_info); - break; - case VIRTCHNL_OP_RESET_VF: - break; - case VIRTCHNL_OP_GET_VF_RESOURCES: - if (VF_IS_V11(ver)) - valid_len = sizeof(u32); - break; - case VIRTCHNL_OP_CONFIG_TX_QUEUE: - valid_len = sizeof(struct virtchnl_txq_info); - break; - case VIRTCHNL_OP_CONFIG_RX_QUEUE: - valid_len = sizeof(struct virtchnl_rxq_info); - break; - case VIRTCHNL_OP_CONFIG_VSI_QUEUES: - valid_len = sizeof(struct virtchnl_vsi_queue_config_info); - if (msglen >= valid_len) { - struct virtchnl_vsi_queue_config_info *vqc = - (struct virtchnl_vsi_queue_config_info *)msg; - valid_len += (vqc->num_queue_pairs * - sizeof(struct - virtchnl_queue_pair_info)); - if (vqc->num_queue_pairs == 0) - err_msg_format = true; - } - break; - case VIRTCHNL_OP_CONFIG_IRQ_MAP: - valid_len = sizeof(struct virtchnl_irq_map_info); - if (msglen >= valid_len) { - struct virtchnl_irq_map_info *vimi = - (struct virtchnl_irq_map_info *)msg; - valid_len += (vimi->num_vectors * - sizeof(struct virtchnl_vector_map)); - if (vimi->num_vectors == 0) - err_msg_format = true; - } - break; - case VIRTCHNL_OP_ENABLE_QUEUES: - case VIRTCHNL_OP_DISABLE_QUEUES: - valid_len = sizeof(struct virtchnl_queue_select); - break; - case VIRTCHNL_OP_ADD_ETH_ADDR: - case VIRTCHNL_OP_DEL_ETH_ADDR: - valid_len = sizeof(struct virtchnl_ether_addr_list); - if (msglen >= valid_len) { - struct virtchnl_ether_addr_list *veal = - (struct virtchnl_ether_addr_list *)msg; - valid_len += veal->num_elements * - sizeof(struct virtchnl_ether_addr); - if (veal->num_elements == 0) - err_msg_format = true; - } - break; - case VIRTCHNL_OP_ADD_VLAN: - case VIRTCHNL_OP_DEL_VLAN: - valid_len = sizeof(struct virtchnl_vlan_filter_list); - if (msglen >= valid_len) { - struct virtchnl_vlan_filter_list *vfl = - (struct virtchnl_vlan_filter_list *)msg; - valid_len += vfl->num_elements * sizeof(u16); - if (vfl->num_elements == 0) - err_msg_format = true; - } - break; - case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: - valid_len = sizeof(struct virtchnl_promisc_info); - break; - case VIRTCHNL_OP_GET_STATS: - valid_len = sizeof(struct virtchnl_queue_select); - break; - case VIRTCHNL_OP_IWARP: - /* These messages are opaque to us and will be validated in - * the RDMA client code. We just need to check for nonzero - * length. The firmware will enforce max length restrictions. - */ - if (msglen) - valid_len = msglen; - else - err_msg_format = true; - break; - case VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP: - break; - case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP: - valid_len = sizeof(struct virtchnl_iwarp_qvlist_info); - if (msglen >= valid_len) { - struct virtchnl_iwarp_qvlist_info *qv = - (struct virtchnl_iwarp_qvlist_info *)msg; - if (qv->num_vectors == 0) { - err_msg_format = true; - break; - } - valid_len += ((qv->num_vectors - 1) * - sizeof(struct virtchnl_iwarp_qv_info)); - } - break; - case VIRTCHNL_OP_CONFIG_RSS_KEY: - valid_len = sizeof(struct virtchnl_rss_key); - if (msglen >= valid_len) { - struct virtchnl_rss_key *vrk = - (struct virtchnl_rss_key *)msg; - valid_len += vrk->key_len - 1; - } - break; - case VIRTCHNL_OP_CONFIG_RSS_LUT: - valid_len = sizeof(struct virtchnl_rss_lut); - if (msglen >= valid_len) { - struct virtchnl_rss_lut *vrl = - (struct virtchnl_rss_lut *)msg; - valid_len += vrl->lut_entries - 1; - } - break; - case VIRTCHNL_OP_GET_RSS_HENA_CAPS: - break; - case VIRTCHNL_OP_SET_RSS_HENA: - valid_len = sizeof(struct virtchnl_rss_hena); - break; - /* These are always errors coming from the VF. */ - case VIRTCHNL_OP_EVENT: - case VIRTCHNL_OP_UNKNOWN: - default: - return VIRTCHNL_ERR_PARAM; - } - /* few more checks */ - if ((valid_len != msglen) || (err_msg_format)) - return VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH; - - return 0; -} - /** * i40e_vc_process_vf_msg * @pf: pointer to the PF structure @@ -2708,7 +2560,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode, return I40E_ERR_PARAM; /* perform basic checks on the msg */ - ret = i40e_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen); + ret = virtchnl_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen); /* perform additional checks specific to this driver */ if (v_opcode == VIRTCHNL_OP_CONFIG_RSS_KEY) { diff --git a/include/linux/avf/virtchnl.h b/include/linux/avf/virtchnl.h index 6c6fbb492b5de36cd8a4a59626127a48986ac9d5..dab76e947b9f90ddda58491a2f4f9c36ba08b652 100644 --- a/include/linux/avf/virtchnl.h +++ b/include/linux/avf/virtchnl.h @@ -498,4 +498,151 @@ enum virtchnl_vfr_states { VIRTCHNL_VFR_VFACTIVE, }; +/** + * virtchnl_vc_validate_vf_msg + * @ver: Virtchnl version info + * @v_opcode: Opcode for the message + * @msg: pointer to the msg buffer + * @msglen: msg length + * + * validate msg format against struct for each opcode + */ +static inline int +virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, + u8 *msg, u16 msglen) +{ + bool err_msg_format = false; + int valid_len = 0; + + /* Validate message length. */ + switch (v_opcode) { + case VIRTCHNL_OP_VERSION: + valid_len = sizeof(struct virtchnl_version_info); + break; + case VIRTCHNL_OP_RESET_VF: + break; + case VIRTCHNL_OP_GET_VF_RESOURCES: + if (VF_IS_V11(ver)) + valid_len = sizeof(u32); + break; + case VIRTCHNL_OP_CONFIG_TX_QUEUE: + valid_len = sizeof(struct virtchnl_txq_info); + break; + case VIRTCHNL_OP_CONFIG_RX_QUEUE: + valid_len = sizeof(struct virtchnl_rxq_info); + break; + case VIRTCHNL_OP_CONFIG_VSI_QUEUES: + valid_len = sizeof(struct virtchnl_vsi_queue_config_info); + if (msglen >= valid_len) { + struct virtchnl_vsi_queue_config_info *vqc = + (struct virtchnl_vsi_queue_config_info *)msg; + valid_len += (vqc->num_queue_pairs * + sizeof(struct + virtchnl_queue_pair_info)); + if (vqc->num_queue_pairs == 0) + err_msg_format = true; + } + break; + case VIRTCHNL_OP_CONFIG_IRQ_MAP: + valid_len = sizeof(struct virtchnl_irq_map_info); + if (msglen >= valid_len) { + struct virtchnl_irq_map_info *vimi = + (struct virtchnl_irq_map_info *)msg; + valid_len += (vimi->num_vectors * + sizeof(struct virtchnl_vector_map)); + if (vimi->num_vectors == 0) + err_msg_format = true; + } + break; + case VIRTCHNL_OP_ENABLE_QUEUES: + case VIRTCHNL_OP_DISABLE_QUEUES: + valid_len = sizeof(struct virtchnl_queue_select); + break; + case VIRTCHNL_OP_ADD_ETH_ADDR: + case VIRTCHNL_OP_DEL_ETH_ADDR: + valid_len = sizeof(struct virtchnl_ether_addr_list); + if (msglen >= valid_len) { + struct virtchnl_ether_addr_list *veal = + (struct virtchnl_ether_addr_list *)msg; + valid_len += veal->num_elements * + sizeof(struct virtchnl_ether_addr); + if (veal->num_elements == 0) + err_msg_format = true; + } + break; + case VIRTCHNL_OP_ADD_VLAN: + case VIRTCHNL_OP_DEL_VLAN: + valid_len = sizeof(struct virtchnl_vlan_filter_list); + if (msglen >= valid_len) { + struct virtchnl_vlan_filter_list *vfl = + (struct virtchnl_vlan_filter_list *)msg; + valid_len += vfl->num_elements * sizeof(u16); + if (vfl->num_elements == 0) + err_msg_format = true; + } + break; + case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: + valid_len = sizeof(struct virtchnl_promisc_info); + break; + case VIRTCHNL_OP_GET_STATS: + valid_len = sizeof(struct virtchnl_queue_select); + break; + case VIRTCHNL_OP_IWARP: + /* These messages are opaque to us and will be validated in + * the RDMA client code. We just need to check for nonzero + * length. The firmware will enforce max length restrictions. + */ + if (msglen) + valid_len = msglen; + else + err_msg_format = true; + break; + case VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP: + break; + case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP: + valid_len = sizeof(struct virtchnl_iwarp_qvlist_info); + if (msglen >= valid_len) { + struct virtchnl_iwarp_qvlist_info *qv = + (struct virtchnl_iwarp_qvlist_info *)msg; + if (qv->num_vectors == 0) { + err_msg_format = true; + break; + } + valid_len += ((qv->num_vectors - 1) * + sizeof(struct virtchnl_iwarp_qv_info)); + } + break; + case VIRTCHNL_OP_CONFIG_RSS_KEY: + valid_len = sizeof(struct virtchnl_rss_key); + if (msglen >= valid_len) { + struct virtchnl_rss_key *vrk = + (struct virtchnl_rss_key *)msg; + valid_len += vrk->key_len - 1; + } + break; + case VIRTCHNL_OP_CONFIG_RSS_LUT: + valid_len = sizeof(struct virtchnl_rss_lut); + if (msglen >= valid_len) { + struct virtchnl_rss_lut *vrl = + (struct virtchnl_rss_lut *)msg; + valid_len += vrl->lut_entries - 1; + } + break; + case VIRTCHNL_OP_GET_RSS_HENA_CAPS: + break; + case VIRTCHNL_OP_SET_RSS_HENA: + valid_len = sizeof(struct virtchnl_rss_hena); + break; + /* These are always errors coming from the VF. */ + case VIRTCHNL_OP_EVENT: + case VIRTCHNL_OP_UNKNOWN: + default: + return VIRTCHNL_ERR_PARAM; + } + /* few more checks */ + if ((valid_len != msglen) || (err_msg_format)) + return VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH; + + return 0; +} #endif /* _VIRTCHNL_H_ */