If is_ptp_ring == true in the loop of __aq_ring_xdp_clean function,
then a timestamp is stored from a packet in a field of skb object,
which is not allocated at the moment of the call (skb == NULL).
Generalize aq_ptp_extract_ts and other affected functions so they don't
work with struct sk_buff*, but with struct skb_shared_hwtstamps*.
Found by Linux Verification Center (linuxtesting.org) with SVACE
Fixes: 26efaef759a1 ("net: atlantic: Implement xdp data plane")
Signed-off-by: Daniil Maximov <daniil31415it@gmail.com>
Reviewed-by: Igor Russkikh <irusskikh@marvell.com>
Link: https://lore.kernel.org/r/20231204085810.1681386-1-daniil31415it@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 
 /* aq_ptp_rx_hwtstamp - utility function which checks for RX time stamp
  * @adapter: pointer to adapter struct
- * @skb: particular skb to send timestamp with
+ * @shhwtstamps: particular skb_shared_hwtstamps to save timestamp
  *
  * if the timestamp is valid, we convert it into the timecounter ns
  * value, then store that result into the hwtstamps structure which
  * is passed up the network stack
  */
-static void aq_ptp_rx_hwtstamp(struct aq_ptp_s *aq_ptp, struct sk_buff *skb,
+static void aq_ptp_rx_hwtstamp(struct aq_ptp_s *aq_ptp, struct skb_shared_hwtstamps *shhwtstamps,
                               u64 timestamp)
 {
        timestamp -= atomic_read(&aq_ptp->offset_ingress);
-       aq_ptp_convert_to_hwtstamp(aq_ptp, skb_hwtstamps(skb), timestamp);
+       aq_ptp_convert_to_hwtstamp(aq_ptp, shhwtstamps, timestamp);
 }
 
 void aq_ptp_hwtstamp_config_get(struct aq_ptp_s *aq_ptp,
               &aq_ptp->ptp_rx == ring || &aq_ptp->hwts_rx == ring;
 }
 
-u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct sk_buff *skb, u8 *p,
+u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct skb_shared_hwtstamps *shhwtstamps, u8 *p,
                      unsigned int len)
 {
        struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
                                                   p, len, ×tamp);
 
        if (ret > 0)
-               aq_ptp_rx_hwtstamp(aq_ptp, skb, timestamp);
+               aq_ptp_rx_hwtstamp(aq_ptp, shhwtstamps, timestamp);
 
        return ret;
 }
 
 /* Return either ring is belong to PTP or not*/
 bool aq_ptp_ring(struct aq_nic_s *aq_nic, struct aq_ring_s *ring);
 
-u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct sk_buff *skb, u8 *p,
+u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct skb_shared_hwtstamps *shhwtstamps, u8 *p,
                      unsigned int len);
 
 struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp);
 }
 
 static inline u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic,
-                                   struct sk_buff *skb, u8 *p,
+                                   struct skb_shared_hwtstamps *shhwtstamps, u8 *p,
                                    unsigned int len)
 {
        return 0;
 
                }
                if (is_ptp_ring)
                        buff->len -=
-                               aq_ptp_extract_ts(self->aq_nic, skb,
+                               aq_ptp_extract_ts(self->aq_nic, skb_hwtstamps(skb),
                                                  aq_buf_vaddr(&buff->rxdata),
                                                  buff->len);
 
                struct aq_ring_buff_s *buff = &rx_ring->buff_ring[rx_ring->sw_head];
                bool is_ptp_ring = aq_ptp_ring(rx_ring->aq_nic, rx_ring);
                struct aq_ring_buff_s *buff_ = NULL;
+               u16 ptp_hwtstamp_len = 0;
+               struct skb_shared_hwtstamps shhwtstamps;
                struct sk_buff *skb = NULL;
                unsigned int next_ = 0U;
                struct xdp_buff xdp;
                hard_start = page_address(buff->rxdata.page) +
                             buff->rxdata.pg_off - rx_ring->page_offset;
 
-               if (is_ptp_ring)
-                       buff->len -=
-                               aq_ptp_extract_ts(rx_ring->aq_nic, skb,
-                                                 aq_buf_vaddr(&buff->rxdata),
-                                                 buff->len);
+               if (is_ptp_ring) {
+                       ptp_hwtstamp_len = aq_ptp_extract_ts(rx_ring->aq_nic, &shhwtstamps,
+                                                            aq_buf_vaddr(&buff->rxdata),
+                                                            buff->len);
+                       buff->len -= ptp_hwtstamp_len;
+               }
 
                xdp_init_buff(&xdp, frame_sz, &rx_ring->xdp_rxq);
                xdp_prepare_buff(&xdp, hard_start, rx_ring->page_offset,
                if (IS_ERR(skb) || !skb)
                        continue;
 
+               if (ptp_hwtstamp_len > 0)
+                       *skb_hwtstamps(skb) = shhwtstamps;
+
                if (buff->is_vlan)
                        __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
                                               buff->vlan_rx_tag);