# Copyright 2018 syzkaller project authors. All rights reserved. # Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. include include include include include include ######################################### ### Generic NVMe over TCP ### nvme_of_msg { pdu nvme_tcp_pdu payload optional[buffer[in]] } [packed] nvme_tcp_pdu [ icreq nvme_tcp_icreq_pdu icresp nvme_tcp_icresp_pdu cmd nvme_tcp_cmd_pdu rsp nvme_tcp_rsp_pdu r2t nvme_tcp_r2t_pdu data_h2c nvme_tcp_data_pdu_h2c data_h2c_hdigest nvme_tcp_data_pdu_h2c_hdigest data_h2c_no_hdigest nvme_tcp_data_pdu_h2c_no_hdigest data_c2h nvme_tcp_data_pdu_c2h ] type nvme_tcp_hdr_t_const[PDU_TYPE, HLEN_SIZE] { type const[PDU_TYPE, int8] flags flags[nvme_tcp_pdu_flags, int8] hlen const[HLEN_SIZE, int8] pdo int8 plen int32 } [packed] type nvme_tcp_hdr_t_const_pdo[PDU_TYPE, HLEN_SIZE, PDO_SIZE] { type const[PDU_TYPE, int8] flags flags[nvme_tcp_pdu_flags, int8] hlen const[HLEN_SIZE, int8] pdo const[PDO_SIZE, int8] plen int32 } [packed] type nvme_tcp_hdr_t_const_plen[PDU_TYPE, HLEN_SIZE, PLEN_SIZE] { type const[PDU_TYPE, int8] flags flags[nvme_tcp_pdu_flags, int8] hlen const[HLEN_SIZE, int8] pdo int8 plen const[PLEN_SIZE, int32] } [packed] nvme_tcp_pdu_flags = NVME_TCP_F_HDGST, NVME_TCP_F_DDGST, NVME_TCP_F_DATA_LAST, NVME_TCP_F_DATA_SUCCESS nvme_tcp_digest_option = NVME_TCP_HDR_DIGEST_ENABLE, NVME_TCP_DATA_DIGEST_ENABLE nvme_tcp_fatal_error_status = 0, NVME_TCP_FES_INVALID_PDU_HDR, NVME_TCP_FES_PDU_SEQ_ERR, NVME_TCP_FES_HDR_DIGEST_ERR, NVME_TCP_FES_DATA_OUT_OF_RANGE, NVME_TCP_FES_R2T_LIMIT_EXCEEDED, NVME_TCP_FES_DATA_LIMIT_EXCEEDED, NVME_TCP_FES_UNSUPPORTED_PARAM nvme_tcp_pfv = NVME_TCP_PFV_1_0 define NVME_TCP_DATA_PDU_SIZE sizeof(struct nvme_tcp_data_pdu) define NVME_TCP_ICREQ_PDU_SIZE sizeof(struct nvme_tcp_icreq_pdu) define NVME_TCP_CMD_PDU_SIZE sizeof(struct nvme_tcp_cmd_pdu) define NVME_TCP_ICRESP_PDU_SIZE sizeof(struct nvme_tcp_icresp_pdu) define NVME_TCP_DISC_PORT 8009 define NVME_TCP_ADMIN_CCSZ SZ_8K define NVME_TCP_DIGEST_LENGTH 4 define NVME_TCP_MIN_MAXH2CDATA 4096 ### End of generic ### ######################################### ######################################### ### nvme_tcp_data_pdu ### type nvme_tcp_data_pdu[HDR_TYPE] { hdr HDR_TYPE command_id int16 ttag int16 data_offset int32 data_length int32 rsvd array[int8, 4] } [size[NVME_TCP_DATA_PDU_SIZE]] type nvme_tcp_hdr_data_pdu_h2c nvme_tcp_hdr_t_const[nvme_tcp_h2c_data, NVME_TCP_DATA_PDU_SIZE] type nvme_tcp_data_pdu_h2c nvme_tcp_data_pdu[nvme_tcp_hdr_data_pdu_h2c] type nvme_tcp_hdr_data_pdu_h2c_hdigest nvme_tcp_hdr_t_const_pdo[nvme_tcp_h2c_data, NVME_TCP_DATA_PDU_SIZE, NVME_TCP_HDR_H2C_DIGEST_PDO_HDIGEST] type nvme_tcp_data_pdu_h2c_hdigest nvme_tcp_data_pdu[nvme_tcp_hdr_data_pdu_h2c_hdigest] type nvme_tcp_hdr_data_pdu_h2c_no_hdigest nvme_tcp_hdr_t_const_pdo[nvme_tcp_h2c_data, NVME_TCP_DATA_PDU_SIZE, NVME_TCP_HDR_H2C_DIGEST_PDO_NO_HDIGEST] type nvme_tcp_data_pdu_h2c_no_hdigest nvme_tcp_data_pdu[nvme_tcp_hdr_data_pdu_h2c_no_hdigest] type nvme_tcp_hdr_data_pdu_c2h nvme_tcp_hdr_t_const[nvme_tcp_c2h_data, NVME_TCP_DATA_PDU_SIZE] type nvme_tcp_data_pdu_c2h nvme_tcp_data_pdu[nvme_tcp_hdr_data_pdu_c2h] define NVME_TCP_HDR_H2C_DIGEST_PDO_HDIGEST NVME_TCP_DATA_PDU_SIZE + NVME_TCP_DIGEST_LENGTH define NVME_TCP_HDR_H2C_DIGEST_PDO_NO_HDIGEST NVME_TCP_DATA_PDU_SIZE define NVME_TCP_HDR_H2C_DIGEST_PLEN_HDIGEST_DDIGEST NVME_TCP_HDR_H2C_DIGEST_PDO_HDIGEST + NVME_TCP_DIGEST_LENGTH ### End of nvme_tcp_r2t_pdu ### ######################################### ######################################### ### nvme_tcp_r2t_pdu ### nvme_tcp_r2t_pdu { hdr nvme_tcp_hdr_r2t_pdu command_id int16 ttag int16 r2t_offset int32 r2t_length int32 rsvd array[const[0, int8], 4] } [size[NVME_TCP_DATA_PDU_SIZE]] type nvme_tcp_hdr_r2t_pdu nvme_tcp_hdr_t_const[nvme_tcp_r2t, NVME_TCP_DATA_PDU_SIZE] ### End of nvme_tcp_r2t_pdu ### ######################################### ######################################### ### nvme_tcp_rsp_pdu ### nvme_tcp_rsp_pdu { hdr nvme_tcp_hdr_rsp_pdu cqe nvme_completion } [size[NVME_TCP_DATA_PDU_SIZE]] nvme_completion { result nvme_result sq_head int16 sq_id int16 command_id int16 status flags[nvme_tcp_fatal_error_status, int16] } [packed] nvme_result [ u16 int16 u32 int32 u64 int64 ] type nvme_tcp_hdr_rsp_pdu nvme_tcp_hdr_t_const[nvme_tcp_rsp, NVME_TCP_DATA_PDU_SIZE] ### End of nvme_tcp_rsp_pdu ### ######################################### ######################################### ### nvme_tcp_icresp_pdu ### nvme_tcp_icresp_pdu { hdr nvme_tcp_hdr_icresp_pdu pfv flags[nvme_tcp_pfv, int16] # Linux NVMe driver only support cpda = 0 cpda const[0, int8] digest flags[nvme_tcp_digest_option, int8] maxdata int32 rsvd array[const[0, int8], 112] } [size[NVME_TCP_ICRESP_PDU_SIZE]] type nvme_tcp_hdr_icresp_pdu nvme_tcp_hdr_t_const[nvme_tcp_icresp, NVME_TCP_ICRESP_PDU_SIZE] ### End of nvme_tcp_icresp_pdu ### ######################################### ######################################### ### nvme_tcp_icreq_pdu ### nvme_tcp_icreq_pdu { hdr nvme_tcp_hdr_icreq_pdu pfv flags[nvme_tcp_pfv, int16] # Linux NVMe driver only support hcpda = 0 hpda const[0, int8] digest flags[nvme_tcp_digest_option, int8] maxr2t int32 rsvd array[const[0, int8], 112] } [size[NVME_TCP_ICREQ_PDU_SIZE]] type nvme_tcp_hdr_icreq_pdu nvme_tcp_hdr_t_const_plen[nvme_tcp_icreq, NVME_TCP_ICREQ_PDU_SIZE, NVME_TCP_ICREQ_PDU_SIZE] ### End of nvme_tcp_icreq_pdu ### ######################################### ######################################### ### nvme_tcp_cmd_pdu ### nvme_tcp_cmd_pdu { hdr nvme_tcp_hdr_cmd_pdu cmd nvme_command } [size[NVME_TCP_CMD_PDU_SIZE]] type nvme_tcp_hdr_cmd_pdu nvme_tcp_hdr_t_const_plen[nvme_tcp_cmd, NVME_TCP_CMD_PDU_SIZE, NVME_TCP_CMD_PDU_SIZE] nvme_command { anon_union nvme_command_union } nvme_command_union [ common nvme_common_command rw nvme_rw_command identify nvme_identify features nvme_features create_cq nvme_create_cq create_sq nvme_create_sq delete_queue nvme_delete_queue dlfw nvme_download_firmware format nvme_format_cmd dsm nvme_dsm_cmd write_zeroes nvme_write_zeroes_cmd zms nvme_zone_mgmt_send_cmd zmr nvme_zone_mgmt_recv_cmd abort nvme_abort_cmd fabrics nvmf_common_command connect nvmf_connect_command prop_set nvmf_property_set_command prop_get nvmf_property_get_command auth_common nvmf_auth_common_command auth_send nvmf_auth_send_command auth_receive nvmf_auth_receive_command dbbuf nvme_dbbuf directive nvme_directive_cmd get_log_page nvme_get_log_page_command ] nvme_get_log_page_command { opcode const[nvme_admin_get_log_page, int8] flags int8 command_id int16 nsid int32 rsvd2 array[const[0, int64], 2] dptr nvme_data_ptr lid int8 lsp int8 numdl int16 numdu int16 rsvd11 const[0, int16] anon_union nvme_get_log_page_command_anon_union rsvd14 array[const[0, int8], 3] csi int8 rsvd15 const[0, int32] } nvme_get_log_page_command_anon_union [ anon_struct nvme_get_log_page_command_anon_union_anon_struct lpo int64 ] nvme_get_log_page_command_anon_union_anon_struct { lpol int32 lpou int32 } nvme_download_firmware { opcode const[nvme_admin_download_fw, int8] flags int8 command_id int16 rsvd1 array[const[0, int32], 5] dptr nvme_data_ptr numd int32 offset int32 rsvd12 array[const[0, int32], 4] } nvme_format_cmd { opcode const[nvme_admin_format_nvm, int8] flags int8 command_id int16 nsid int32 rsvd2 array[const[0, int64], 4] cdw10 int32 rsvd11 array[const[0, int32], 5] } nvme_dsm_cmd { opcode const[nvme_cmd_dsm, int8] flags int8 command_id int16 nsid int32 rsvd2 array[const[0, int64], 2] dptr nvme_data_ptr nr int32 attributes int32 rsvd12 array[const[0, int32], 4] } nvme_write_zeroes_cmd { opcode const[nvme_cmd_write_zeroes, int8] flags int8 command_id int16 nsid int32 rsvd2 const[0, int64] metadata int64 dptr nvme_data_ptr slba int64 length int16 control int16 dsmgmt int32 reftag int32 apptag int16 appmask int16 } nvme_zone_mgmt_send_cmd { opcode const[nvme_cmd_zone_mgmt_send, int8] flags int8 command_id int16 nsid int32 cdw2 array[int32, 2] metadata int64 dptr nvme_data_ptr slba int64 cdw12 int32 zsa int8 select_all int8 rsvd13 array[const[0, int8], 2] cdw14 array[int32, 2] } nvme_zone_mgmt_recv_cmd { opcode const[nvme_cmd_zone_mgmt_recv, int8] flags int8 command_id int16 nsid int32 rsvd2 array[const[0, int64], 2] dptr nvme_data_ptr slba int64 numd int32 zra int8 zrasf int8 pr int8 rsvd13 const[0, int8] cdw14 array[int32, 2] } nvme_abort_cmd { opcode const[nvme_admin_abort_cmd, int8] flags int8 command_id int16 rsvd1 array[const[0, int32], 9] sqid int16 cid int16 rsvd11 array[const[0, int32], 5] } nvmf_common_command { opcode const[nvme_fabrics_command, int8] resv1 int8 command_id int16 fctype int8 resv2 array[int8, 35] ts array[int8, 24] } nvmf_connect_command { opcode const[nvme_fabrics_command, int8] resv1 const[0x40, int8] command_id const[0x0, int16] fctype const[nvme_fabrics_type_connect, int8] resv2 array[int8, 19] dptr nvme_data_ptr recfmt int16 qid int16 sqsize int16 cattr int8 resv3 int8 kato int32 resv4 array[int8, 12] } nvmf_property_set_command { opcode const[nvme_fabrics_command, int8] resv1 int8 command_id int16 fctype const[nvme_fabrics_type_property_set, int8] resv2 array[int8, 35] attrib const[0x0, int8] resv3 array[int8, 3] offset int32 value int64 resv4 array[int8, 8] } nvmf_property_get_command { opcode const[nvme_fabrics_command, int8] resv1 int8 command_id int16 fctype const[nvme_fabrics_type_property_get, int8] resv2 array[int8, 35] attrib int8 resv3 array[int8, 3] offset int32 resv4 array[int8, 16] } nvmf_auth_common_command { opcode const[nvme_fabrics_command, int8] resv1 int8 command_id int16 fctype int8 resv2 array[int8, 19] dptr nvme_data_ptr resv3 int8 spsp0 int8 spsp1 int8 secp int8 al_tl int32 resv4 array[int8, 16] } nvmf_auth_send_command { opcode const[nvme_fabrics_command, int8] resv1 int8 command_id int16 fctype const[nvme_fabrics_type_auth_send, int8] resv2 array[int8, 19] dptr nvme_data_ptr resv3 int8 spsp0 flags[sps_flags, int8] spsp1 flags[sps_flags, int8] secp flags[secp_flags, int8] tl int32 resv4 array[int8, 16] } secp_flags = NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER, 0x0 sps_flags = 0x1, 0x2 nvmf_auth_receive_command { opcode const[nvme_fabrics_command, int8] resv1 int8 command_id int16 fctype const[nvme_fabrics_type_auth_receive, int8] resv2 array[int8, 19] dptr nvme_data_ptr resv3 int8 spsp0 flags[sps_flags, int8] spsp1 flags[sps_flags, int8] secp flags[secp_flags, int8] al int32 resv4 array[int8, 16] } nvme_dbbuf { opcode const[nvme_admin_dbbuf, int8] flags int8 command_id int16 rsvd1 array[const[0, int32], 5] prp1 int64 prp2 int64 rsvd12 array[const[0, int32], 6] } nvme_directive_cmd { opcode flags[nvme_admin_directive_opcodes, int8] flags int8 command_id int16 nsid int32 rsvd2 array[const[0, int64], 2] dptr nvme_data_ptr numd int32 doper int8 dtype int8 dspec int16 endir int8 tdtype int8 rsvd15 const[0, int16] rsvd16 array[int32, 3] } nvme_admin_directive_opcodes = nvme_admin_directive_send, nvme_admin_directive_recv ##################### ##################### nvme_delete_queue { opcode const[nvme_admin_delete_cq, int8] flags int8 command_id int16 rsvd1 array[const[0, int32], 9] qid int16 rsvd10 const[0, int16] rsvd11 array[const[0, int32], 5] } nvme_create_sq { opcode const[nvme_admin_create_sq, int8] flags int8 command_id int16 rsvd1 array[const[0, int32], 5] prp1 int64 rsvd8 const[0, int64] sqid int16 qsize int16 sq_flags int16 cqid int16 rsvd12 array[const[0, int32], 4] } nvme_create_cq { opcode const[nvme_admin_create_cq, int8] flags int8 command_id int16 rsvd1 array[const[0, int32], 5] prp1 int64 rsvd8 const[0, int64] cqid int16 qsize int16 cq_flags int16 irq_vector int16 rsvd12 array[const[0, int32], 4] } nvme_features { opcode flags[nvme_features_opcodes, int8] flags int8 command_id int16 nsid int32 rsvd2 array[const[0, int64], 2] dptr nvme_data_ptr fid int32 dword11 int32 dword12 int32 dword13 int32 dword14 int32 dword15 int32 } nvme_features_opcodes = nvme_admin_set_features, nvme_admin_get_features nvme_identify { opcode const[nvme_admin_identify, int8] flags int8 command_id int16 nsid int32 rsvd2 array[const[0, int64], 2] dptr nvme_data_ptr cns int8 rsvd3 const[0, int8] ctrlid int16 rsvd11 array[const[0, int8], 3] csi int8 rsvd12 array[const[0, int32], 4] } nvme_common_command { opcode flags[nvme_common_command_opcodes, int8] flags int8 command_id int16 nsid int32 cdw2 array[int32, 2] metadata int64 dptr nvme_data_ptr cdws cdws_struct_group } nvme_common_command_opcodes = nvme_cmd_resv_report, nvme_fabrics_command, nvme_cmd_write, nvme_admin_async_event, nvme_cmd_flush, nvme_cmd_read, nvme_cmd_write_zeroes, nvme_cmd_dsm, nvme_admin_security_recv, nvme_admin_security_send, nvme_cmd_flush, nvme_admin_get_log_page, nvme_admin_identify, nvme_admin_abort_cmd, nvme_admin_set_features, nvme_admin_get_features, nvme_admin_async_event, nvme_admin_keep_alive cdws_struct_group [ cdws_anon cdws_anon_struct cdws cdws_anon_struct ] cdws_anon_struct { cdw10 int32 cdw11 int32 cdw12 int32 cdw13 int32 cdw14 int32 cdw15 int32 } nvme_data_ptr [ anon_struct nvme_data_ptr_anon_struct sgl nvme_sgl_desc ksgl nvme_keyed_sgl_desc ] nvme_data_ptr_anon_struct { prp1 int64 prp2 int64 } [packed] nvme_sgl_desc { addr int64 length int32 rsvd array[const[0, int8], 3] type int8 } [packed] nvme_keyed_sgl_desc { addr int64 length array[int8, 3] key array[int8, 4] type int8 } [packed] nvme_rw_command { opcode flags[nvme_opcodes_rw, int8] flags int8 command_id int16 nsid int32 cdw2 int32 cdw3 int32 metadata int64 dptr nvme_data_ptr slba int64 length int16 control int16 dsmgmt int32 reftag int32 apptag int16 appmask int16 } nvme_opcodes_rw = nvme_cmd_write, nvme_cmd_read, nvme_cmd_zone_append ### End of nvme_tcp_cmd_pdu ### ######################################### ######################################### resource nvme_sock[sock] syz_socket_connect_nvme_tcp() nvme_sock sendto$inet_nvme_of_msg(fd nvme_sock, pdu ptr[in, nvme_of_msg], len len[pdu], f const[0], addr const[0], addrlen const[0]) sendto$inet_nvme_pdu(fd nvme_sock, pdu ptr[in, nvme_tcp_pdu], len len[pdu], f const[0], addr const[0], addrlen const[0]) sendto$inet_nvme_icreq_pdu(fd nvme_sock, pdu ptr[in, nvme_tcp_icreq_pdu], len len[pdu], f const[0], addr const[0], addrlen const[0]) recvmsg$inet_nvme(fd nvme_sock, msg ptr[inout, recv_msghdr], f flags[recv_flags]) recvfrom$inet_nvme(fd nvme_sock, buf buffer[out], len len[buf], f flags[recv_flags], addr ptr[in, sockaddr_storage, opt], addrlen len[addr])