@@ -143,42 +143,67 @@ static inline bool xp_unused_options_set(u32 options)
143143static inline bool xp_aligned_validate_desc (struct xsk_buff_pool * pool ,
144144 struct xdp_desc * desc )
145145{
146- u64 addr = desc -> addr - pool -> tx_metadata_len ;
147- u64 len = desc -> len + pool -> tx_metadata_len ;
148- u64 offset = addr & (pool -> chunk_size - 1 );
146+ u64 len = desc -> len ;
147+ u64 addr , offset ;
149148
150- if (!desc -> len )
149+ if (!len )
151150 return false;
152151
153- if (offset + len > pool -> chunk_size )
152+ /* Can overflow if desc->addr < pool->tx_metadata_len */
153+ if (check_sub_overflow (desc -> addr , pool -> tx_metadata_len , & addr ))
154+ return false;
155+
156+ offset = addr & (pool -> chunk_size - 1 );
157+
158+ /*
159+ * Can't overflow: @offset is guaranteed to be < ``U32_MAX``
160+ * (pool->chunk_size is ``u32``), @len is guaranteed
161+ * to be <= ``U32_MAX``.
162+ */
163+ if (offset + len + pool -> tx_metadata_len > pool -> chunk_size )
154164 return false;
155165
156166 if (addr >= pool -> addrs_cnt )
157167 return false;
158168
159169 if (xp_unused_options_set (desc -> options ))
160170 return false;
171+
161172 return true;
162173}
163174
164175static inline bool xp_unaligned_validate_desc (struct xsk_buff_pool * pool ,
165176 struct xdp_desc * desc )
166177{
167- u64 addr = xp_unaligned_add_offset_to_addr ( desc -> addr ) - pool -> tx_metadata_len ;
168- u64 len = desc -> len + pool -> tx_metadata_len ;
178+ u64 len = desc -> len ;
179+ u64 addr , end ;
169180
170- if (!desc -> len )
181+ if (!len )
171182 return false;
172183
184+ /* Can't overflow: @len is guaranteed to be <= ``U32_MAX`` */
185+ len += pool -> tx_metadata_len ;
173186 if (len > pool -> chunk_size )
174187 return false;
175188
176- if (addr >= pool -> addrs_cnt || addr + len > pool -> addrs_cnt ||
177- xp_desc_crosses_non_contig_pg (pool , addr , len ))
189+ /* Can overflow if desc->addr is close to 0 */
190+ if (check_sub_overflow (xp_unaligned_add_offset_to_addr (desc -> addr ),
191+ pool -> tx_metadata_len , & addr ))
192+ return false;
193+
194+ if (addr >= pool -> addrs_cnt )
195+ return false;
196+
197+ /* Can overflow if pool->addrs_cnt is high enough */
198+ if (check_add_overflow (addr , len , & end ) || end > pool -> addrs_cnt )
199+ return false;
200+
201+ if (xp_desc_crosses_non_contig_pg (pool , addr , len ))
178202 return false;
179203
180204 if (xp_unused_options_set (desc -> options ))
181205 return false;
206+
182207 return true;
183208}
184209
0 commit comments