[ovs-dev] [PATCH] ipf: Fix a use-after-free error, and remove the 'do_not_steal' flag.
Ilya Maximets
i.maximets at ovn.org
Tue Jun 15 13:20:01 UTC 2021
On 5/21/21 7:59 PM, Aaron Conole wrote:
> As reported by Wang Liang, the way packets are passed to the ipf module
> doesn't allow for use later on in reassembly. Such packets may be get
> released anyway, such as during cleanup of tx processing. Because the
> ipf module lacks a way of forcing the dp_packet to be retained, it
> will later reuse the packet. Instead, just clone the packet and let the
> ipf queue own the copy until the queue is destroyed.
>
> After this change, there are no more in-tree users of the batch
> 'dnsteal' flag. Thus, we remove it as well.
>
> Fixes: 4ea96698f667 ("Userspace datapath: Add fragmentation handling.")
> Fixes: 0b3ff31d35f5 ("dp-packet: Add 'do_not_steal' packet batch flag.")
> Reported-at: https://mail.openvswitch.org/pipermail/ovs-dev/2021-April/382098.html
> Reported-by: Wang Liang <wangliangrt at didiglobal.com>
> Signed-off-by: Aaron Conole <aconole at redhat.com>
> Co-authored-by: Wang Liang <wangliangrt at didiglobal.com>
> Signed-off-by: Wang Liang <wangliangrt at didiglobal.com>
> ---
Thanks! Applied.
Also, backported down to 2.12.
Best regards, Ilya Maximets.
> lib/dp-packet.h | 2 --
> lib/dpif-netdev.c | 1 -
> lib/ipf.c | 19 ++++++-------------
> 3 files changed, 6 insertions(+), 16 deletions(-)
>
> diff --git a/lib/dp-packet.h b/lib/dp-packet.h
> index 246be14d00..08d93c2779 100644
> --- a/lib/dp-packet.h
> +++ b/lib/dp-packet.h
> @@ -738,7 +738,6 @@ enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */
> struct dp_packet_batch {
> size_t count;
> bool trunc; /* true if the batch needs truncate. */
> - bool do_not_steal; /* Indicate that the packets should not be stolen. */
> struct dp_packet *packets[NETDEV_MAX_BURST];
> };
>
> @@ -747,7 +746,6 @@ dp_packet_batch_init(struct dp_packet_batch *batch)
> {
> batch->count = 0;
> batch->trunc = false;
> - batch->do_not_steal = false;
> }
>
> static inline void
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index 650e67ab30..8fa7eb6d4f 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -4169,7 +4169,6 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
> }
>
> dp_packet_batch_init_packet(&pp, execute->packet);
> - pp.do_not_steal = true;
> dp_netdev_execute_actions(pmd, &pp, false, execute->flow,
> execute->actions, execute->actions_len);
> dp_netdev_pmd_flush_output_packets(pmd, true);
> diff --git a/lib/ipf.c b/lib/ipf.c
> index c20bcc0b33..9c83f1913a 100644
> --- a/lib/ipf.c
> +++ b/lib/ipf.c
> @@ -93,7 +93,6 @@ struct ipf_frag {
> struct dp_packet *pkt;
> uint16_t start_data_byte;
> uint16_t end_data_byte;
> - bool dnsteal; /* 'do not steal': if true, ipf should not free packet. */
> };
>
> /* The key for a collection of fragments potentially making up an unfragmented
> @@ -795,8 +794,7 @@ ipf_is_frag_duped(const struct ipf_frag *frag_list, int last_inuse_idx,
> static bool
> ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list,
> struct dp_packet *pkt, uint16_t start_data_byte,
> - uint16_t end_data_byte, bool ff, bool lf, bool v6,
> - bool dnsteal)
> + uint16_t end_data_byte, bool ff, bool lf, bool v6)
> OVS_REQUIRES(ipf->ipf_lock)
> {
> bool duped_frag = ipf_is_frag_duped(ipf_list->frag_list,
> @@ -811,10 +809,9 @@ ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list,
> * recommend not setting the mempool number of buffers too low
> * and also clamp the number of fragments. */
> struct ipf_frag *frag = &ipf_list->frag_list[last_inuse_idx + 1];
> - frag->pkt = pkt;
> + frag->pkt = dp_packet_clone(pkt);
> frag->start_data_byte = start_data_byte;
> frag->end_data_byte = end_data_byte;
> - frag->dnsteal = dnsteal;
> ipf_list->last_inuse_idx++;
> atomic_count_inc(&ipf->nfrag);
> ipf_count(ipf, v6, IPF_NFRAGS_ACCEPTED);
> @@ -851,8 +848,7 @@ ipf_list_init(struct ipf_list *ipf_list, struct ipf_list_key *key,
> * to a list of fragemnts. */
> static bool
> ipf_handle_frag(struct ipf *ipf, struct dp_packet *pkt, ovs_be16 dl_type,
> - uint16_t zone, long long now, uint32_t hash_basis,
> - bool dnsteal)
> + uint16_t zone, long long now, uint32_t hash_basis)
> OVS_REQUIRES(ipf->ipf_lock)
> {
> struct ipf_list_key key;
> @@ -921,7 +917,7 @@ ipf_handle_frag(struct ipf *ipf, struct dp_packet *pkt, ovs_be16 dl_type,
> }
>
> return ipf_process_frag(ipf, ipf_list, pkt, start_data_byte,
> - end_data_byte, ff, lf, v6, dnsteal);
> + end_data_byte, ff, lf, v6);
> }
>
> /* Filters out fragments from a batch of fragments and adjust the batch. */
> @@ -942,8 +938,7 @@ ipf_extract_frags_from_batch(struct ipf *ipf, struct dp_packet_batch *pb,
> ipf_is_valid_v6_frag(ipf, pkt)))) {
>
> ovs_mutex_lock(&ipf->ipf_lock);
> - if (!ipf_handle_frag(ipf, pkt, dl_type, zone, now, hash_basis,
> - pb->do_not_steal)) {
> + if (!ipf_handle_frag(ipf, pkt, dl_type, zone, now, hash_basis)) {
> dp_packet_batch_refill(pb, pkt, pb_idx);
> }
> ovs_mutex_unlock(&ipf->ipf_lock);
> @@ -1338,9 +1333,7 @@ ipf_destroy(struct ipf *ipf)
> while (ipf_list->last_sent_idx < ipf_list->last_inuse_idx) {
> struct dp_packet *pkt
> = ipf_list->frag_list[ipf_list->last_sent_idx + 1].pkt;
> - if (!ipf_list->frag_list[ipf_list->last_sent_idx + 1].dnsteal) {
> - dp_packet_delete(pkt);
> - }
> + dp_packet_delete(pkt);
> atomic_count_dec(&ipf->nfrag);
> ipf_list->last_sent_idx++;
> }
>
More information about the dev
mailing list