Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'bpf-sockmap-sg-api-fixes'

Prashant Bhole says:

====================
These patches fix sg api usage in sockmap. Previously sockmap didn't
use sg_init_table(), which caused hitting BUG_ON in sg api, when
CONFIG_DEBUG_SG is enabled

v1: added sg_init_table() calls wherever needed.

v2:
- Patch1 adds new helper function in sg api. sg_init_marker()
- Patch2 sg_init_marker() and sg_init_table() in appropriate places

Backgroud:
While reviewing v1, John Fastabend raised a valid point about
unnecessary memset in sg_init_table() because sockmap uses sg table
which embedded in a struct. As enclosing struct is zeroed out, there
is unnecessary memset in sg_init_table.

So Daniel Borkmann suggested to define another static inline function
in scatterlist.h which only initializes sg_magic. Also this function
will be called from sg_init_table. From this suggestion I defined a
function sg_init_marker() which sets sg_magic and calls sg_mark_end()
====================

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

+27 -13
+18
include/linux/scatterlist.h
··· 248 248 return page_address(sg_page(sg)) + sg->offset; 249 249 } 250 250 251 + /** 252 + * sg_init_marker - Initialize markers in sg table 253 + * @sgl: The SG table 254 + * @nents: Number of entries in table 255 + * 256 + **/ 257 + static inline void sg_init_marker(struct scatterlist *sgl, 258 + unsigned int nents) 259 + { 260 + #ifdef CONFIG_DEBUG_SG 261 + unsigned int i; 262 + 263 + for (i = 0; i < nents; i++) 264 + sgl[i].sg_magic = SG_MAGIC; 265 + #endif 266 + sg_mark_end(&sgl[nents - 1]); 267 + } 268 + 251 269 int sg_nents(struct scatterlist *sg); 252 270 int sg_nents_for_len(struct scatterlist *sg, u64 len); 253 271 struct scatterlist *sg_next(struct scatterlist *);
+8 -5
kernel/bpf/sockmap.c
··· 341 341 md->sg_start++; 342 342 if (md->sg_start == MAX_SKB_FRAGS) 343 343 md->sg_start = 0; 344 - memset(sg, 0, sizeof(*sg)); 344 + sg_init_table(sg, 1); 345 345 346 346 if (md->sg_start == md->sg_end) 347 347 break; ··· 843 843 } 844 844 845 845 sg = md.sg_data; 846 - sg_init_table(sg, MAX_SKB_FRAGS); 846 + sg_init_marker(sg, MAX_SKB_FRAGS); 847 847 rcu_read_unlock(); 848 848 849 849 lock_sock(sk); ··· 950 950 951 951 lock_sock(sk); 952 952 953 - if (psock->cork_bytes) 953 + if (psock->cork_bytes) { 954 954 m = psock->cork; 955 - else 955 + sg = &m->sg_data[m->sg_end]; 956 + } else { 956 957 m = &md; 958 + sg = m->sg_data; 959 + sg_init_marker(sg, MAX_SKB_FRAGS); 960 + } 957 961 958 962 /* Catch case where ring is full and sendpage is stalled. */ 959 963 if (unlikely(m->sg_end == m->sg_start && ··· 965 961 goto out_err; 966 962 967 963 psock->sg_size += size; 968 - sg = &m->sg_data[m->sg_end]; 969 964 sg_set_page(sg, page, size, offset); 970 965 get_page(page); 971 966 m->sg_copy[m->sg_end] = true;
+1 -8
lib/scatterlist.c
··· 132 132 void sg_init_table(struct scatterlist *sgl, unsigned int nents) 133 133 { 134 134 memset(sgl, 0, sizeof(*sgl) * nents); 135 - #ifdef CONFIG_DEBUG_SG 136 - { 137 - unsigned int i; 138 - for (i = 0; i < nents; i++) 139 - sgl[i].sg_magic = SG_MAGIC; 140 - } 141 - #endif 142 - sg_mark_end(&sgl[nents - 1]); 135 + sg_init_marker(sgl, nents); 143 136 } 144 137 EXPORT_SYMBOL(sg_init_table); 145 138