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

bpf: Remove MEM_UNINIT from skb/xdp MTU helpers

We can now undo parts of 4b3786a6c539 ("bpf: Zero former ARG_PTR_TO_{LONG,INT}
args in case of error") as discussed in [0].

Given the BPF helpers now have MEM_WRITE tag, the MEM_UNINIT can be cleared.

The mtu_len is an input as well as output argument, meaning, the BPF program
has to set it to something. It cannot be uninitialized. Therefore, allowing
uninitialized memory and zeroing it on error would be odd. It was done as
an interim step in 4b3786a6c539 as the desired behavior could not have been
expressed before the introduction of MEM_WRITE tag.

Fixes: 4b3786a6c539 ("bpf: Zero former ARG_PTR_TO_{LONG,INT} args in case of error")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/a86eb76d-f52f-dee4-e5d2-87e45de3e16f@iogearbox.net [0]
Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20241021152809.33343-3-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Daniel Borkmann and committed by
Alexei Starovoitov
14a3d3ef 8ea60733

+15 -27
+15 -27
net/core/filter.c
··· 6281 6281 { 6282 6282 int ret = BPF_MTU_CHK_RET_FRAG_NEEDED; 6283 6283 struct net_device *dev = skb->dev; 6284 - int skb_len, dev_len; 6285 - int mtu = 0; 6284 + int mtu, dev_len, skb_len; 6286 6285 6287 - if (unlikely(flags & ~(BPF_MTU_CHK_SEGS))) { 6288 - ret = -EINVAL; 6289 - goto out; 6290 - } 6291 - 6292 - if (unlikely(flags & BPF_MTU_CHK_SEGS && (len_diff || *mtu_len))) { 6293 - ret = -EINVAL; 6294 - goto out; 6295 - } 6286 + if (unlikely(flags & ~(BPF_MTU_CHK_SEGS))) 6287 + return -EINVAL; 6288 + if (unlikely(flags & BPF_MTU_CHK_SEGS && (len_diff || *mtu_len))) 6289 + return -EINVAL; 6296 6290 6297 6291 dev = __dev_via_ifindex(dev, ifindex); 6298 - if (unlikely(!dev)) { 6299 - ret = -ENODEV; 6300 - goto out; 6301 - } 6292 + if (unlikely(!dev)) 6293 + return -ENODEV; 6302 6294 6303 6295 mtu = READ_ONCE(dev->mtu); 6304 6296 dev_len = mtu + dev->hard_header_len; ··· 6325 6333 struct net_device *dev = xdp->rxq->dev; 6326 6334 int xdp_len = xdp->data_end - xdp->data; 6327 6335 int ret = BPF_MTU_CHK_RET_SUCCESS; 6328 - int mtu = 0, dev_len; 6336 + int mtu, dev_len; 6329 6337 6330 6338 /* XDP variant doesn't support multi-buffer segment check (yet) */ 6331 - if (unlikely(flags)) { 6332 - ret = -EINVAL; 6333 - goto out; 6334 - } 6339 + if (unlikely(flags)) 6340 + return -EINVAL; 6335 6341 6336 6342 dev = __dev_via_ifindex(dev, ifindex); 6337 - if (unlikely(!dev)) { 6338 - ret = -ENODEV; 6339 - goto out; 6340 - } 6343 + if (unlikely(!dev)) 6344 + return -ENODEV; 6341 6345 6342 6346 mtu = READ_ONCE(dev->mtu); 6343 6347 dev_len = mtu + dev->hard_header_len; ··· 6345 6357 xdp_len += len_diff; /* minus result pass check */ 6346 6358 if (xdp_len > dev_len) 6347 6359 ret = BPF_MTU_CHK_RET_FRAG_NEEDED; 6348 - out: 6360 + 6349 6361 *mtu_len = mtu; 6350 6362 return ret; 6351 6363 } ··· 6356 6368 .ret_type = RET_INTEGER, 6357 6369 .arg1_type = ARG_PTR_TO_CTX, 6358 6370 .arg2_type = ARG_ANYTHING, 6359 - .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED, 6371 + .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_WRITE | MEM_ALIGNED, 6360 6372 .arg3_size = sizeof(u32), 6361 6373 .arg4_type = ARG_ANYTHING, 6362 6374 .arg5_type = ARG_ANYTHING, ··· 6368 6380 .ret_type = RET_INTEGER, 6369 6381 .arg1_type = ARG_PTR_TO_CTX, 6370 6382 .arg2_type = ARG_ANYTHING, 6371 - .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED, 6383 + .arg3_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_WRITE | MEM_ALIGNED, 6372 6384 .arg3_size = sizeof(u32), 6373 6385 .arg4_type = ARG_ANYTHING, 6374 6386 .arg5_type = ARG_ANYTHING,