···665665 void __user *data_in = u64_to_user_ptr(kattr->test.data_in);666666 void *data;667667668668- if (user_size < ETH_HLEN || user_size > PAGE_SIZE - headroom - tailroom)668668+ if (user_size > PAGE_SIZE - headroom - tailroom)669669 return ERR_PTR(-EINVAL);670670671671 size = SKB_DATA_ALIGN(size);···10011001 kattr->test.cpu || kattr->test.batch_size)10021002 return -EINVAL;1003100310041004+ if (size < ETH_HLEN)10051005+ return -EINVAL;10061006+10041007 data = bpf_test_init(kattr, kattr->test.data_size_in,10051008 size, NET_SKB_PAD + NET_IP_ALIGN,10061009 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));···12101207{12111208 bool do_live = (kattr->test.flags & BPF_F_TEST_XDP_LIVE_FRAMES);12121209 u32 tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));12101210+ u32 retval = 0, meta_sz = 0, duration, max_linear_sz, size;12111211+ u32 linear_sz = kattr->test.data_size_in;12131212 u32 batch_size = kattr->test.batch_size;12141214- u32 retval = 0, duration, max_data_sz;12151215- u32 size = kattr->test.data_size_in;12161213 u32 headroom = XDP_PACKET_HEADROOM;12171214 u32 repeat = kattr->test.repeat;12181215 struct netdev_rx_queue *rxqueue;···1249124612501247 if (ctx) {12511248 /* There can't be user provided data before the meta data */12521252- if (ctx->data_meta || ctx->data_end != size ||12491249+ if (ctx->data_meta || ctx->data_end > kattr->test.data_size_in ||12531250 ctx->data > ctx->data_end ||12541251 unlikely(xdp_metalen_invalid(ctx->data)) ||12551252 (do_live && (kattr->test.data_out || kattr->test.ctx_out)))12561253 goto free_ctx;12571254 /* Meta data is allocated from the headroom */12581255 headroom -= ctx->data;12561256+12571257+ meta_sz = ctx->data;12581258+ linear_sz = ctx->data_end;12591259 }1260126012611261- max_data_sz = PAGE_SIZE - headroom - tailroom;12621262- if (size > max_data_sz) {12631263- /* disallow live data mode for jumbo frames */12641264- if (do_live)12651265- goto free_ctx;12661266- size = max_data_sz;12671267- }12611261+ max_linear_sz = PAGE_SIZE - headroom - tailroom;12621262+ linear_sz = min_t(u32, linear_sz, max_linear_sz);1268126312691269- data = bpf_test_init(kattr, size, max_data_sz, headroom, tailroom);12641264+ /* disallow live data mode for jumbo frames */12651265+ if (do_live && kattr->test.data_size_in > linear_sz)12661266+ goto free_ctx;12671267+12681268+ if (kattr->test.data_size_in - meta_sz < ETH_HLEN)12691269+ return -EINVAL;12701270+12711271+ data = bpf_test_init(kattr, linear_sz, max_linear_sz, headroom, tailroom);12701272 if (IS_ERR(data)) {12711273 ret = PTR_ERR(data);12721274 goto free_ctx;12731275 }1274127612751277 rxqueue = __netif_get_rx_queue(current->nsproxy->net_ns->loopback_dev, 0);12761276- rxqueue->xdp_rxq.frag_size = headroom + max_data_sz + tailroom;12781278+ rxqueue->xdp_rxq.frag_size = PAGE_SIZE;12771279 xdp_init_buff(&xdp, rxqueue->xdp_rxq.frag_size, &rxqueue->xdp_rxq);12781278- xdp_prepare_buff(&xdp, data, headroom, size, true);12801280+ xdp_prepare_buff(&xdp, data, headroom, linear_sz, true);12791281 sinfo = xdp_get_shared_info_from_buff(&xdp);1280128212811283 ret = xdp_convert_md_to_buff(ctx, &xdp);12821284 if (ret)12831285 goto free_data;1284128612871287+ size = linear_sz;12851288 if (unlikely(kattr->test.data_size_in > size)) {12861289 void __user *data_in = u64_to_user_ptr(kattr->test.data_in);12871290
+118-17
net/core/filter.c
···41534153 return 0;41544154}4155415541564156-static void bpf_xdp_shrink_data_zc(struct xdp_buff *xdp, int shrink,41574157- enum xdp_mem_type mem_type, bool release)41564156+static struct xdp_buff *bpf_xdp_shrink_data_zc(struct xdp_buff *xdp, int shrink,41574157+ bool tail, bool release)41584158{41594159- struct xdp_buff *zc_frag = xsk_buff_get_tail(xdp);41594159+ struct xdp_buff *zc_frag = tail ? xsk_buff_get_tail(xdp) :41604160+ xsk_buff_get_head(xdp);4160416141614162 if (release) {41624162- xsk_buff_del_tail(zc_frag);41634163- __xdp_return(0, mem_type, false, zc_frag);41634163+ xsk_buff_del_frag(zc_frag);41644164 } else {41654165- zc_frag->data_end -= shrink;41654165+ if (tail)41664166+ zc_frag->data_end -= shrink;41674167+ else41684168+ zc_frag->data += shrink;41664169 }41704170+41714171+ return zc_frag;41674172}4168417341694174static bool bpf_xdp_shrink_data(struct xdp_buff *xdp, skb_frag_t *frag,41704170- int shrink)41754175+ int shrink, bool tail)41714176{41724177 enum xdp_mem_type mem_type = xdp->rxq->mem.type;41734178 bool release = skb_frag_size(frag) == shrink;41794179+ netmem_ref netmem = skb_frag_netmem(frag);41804180+ struct xdp_buff *zc_frag = NULL;4174418141754182 if (mem_type == MEM_TYPE_XSK_BUFF_POOL) {41764176- bpf_xdp_shrink_data_zc(xdp, shrink, mem_type, release);41774177- goto out;41834183+ netmem = 0;41844184+ zc_frag = bpf_xdp_shrink_data_zc(xdp, shrink, tail, release);41784185 }4179418641804180- if (release)41814181- __xdp_return(skb_frag_netmem(frag), mem_type, false, NULL);41874187+ if (release) {41884188+ __xdp_return(netmem, mem_type, false, zc_frag);41894189+ } else {41904190+ if (!tail)41914191+ skb_frag_off_add(frag, shrink);41924192+ skb_frag_size_sub(frag, shrink);41934193+ }4182419441834183-out:41844195 return release;41854196}41864197···4209419842104199 len_free += shrink;42114200 offset -= shrink;42124212- if (bpf_xdp_shrink_data(xdp, frag, shrink)) {42014201+ if (bpf_xdp_shrink_data(xdp, frag, shrink, true))42134202 n_frags_free++;42144214- } else {42154215- skb_frag_size_sub(frag, shrink);42164216- break;42174217- }42184203 }42194204 sinfo->nr_frags -= n_frags_free;42204205 sinfo->xdp_frags_size -= len_free;4221420642224207 if (unlikely(!sinfo->nr_frags)) {42234208 xdp_buff_clear_frags_flag(xdp);42094209+ xdp_buff_clear_frag_pfmemalloc(xdp);42244210 xdp->data_end -= offset;42254211 }42264212···1221812210 return 0;1221912211}12220122121221312213+/**1221412214+ * bpf_xdp_pull_data() - Pull in non-linear xdp data.1221512215+ * @x: &xdp_md associated with the XDP buffer1221612216+ * @len: length of data to be made directly accessible in the linear part1221712217+ *1221812218+ * Pull in data in case the XDP buffer associated with @x is non-linear and1221912219+ * not all @len are in the linear data area.1222012220+ *1222112221+ * Direct packet access allows reading and writing linear XDP data through1222212222+ * packet pointers (i.e., &xdp_md->data + offsets). The amount of data which1222312223+ * ends up in the linear part of the xdp_buff depends on the NIC and its1222412224+ * configuration. When a frag-capable XDP program wants to directly access1222512225+ * headers that may be in the non-linear area, call this kfunc to make sure1222612226+ * the data is available in the linear area. Alternatively, use dynptr or1222712227+ * bpf_xdp_{load,store}_bytes() to access data without pulling.1222812228+ *1222912229+ * This kfunc can also be used with bpf_xdp_adjust_head() to decapsulate1223012230+ * headers in the non-linear data area.1223112231+ *1223212232+ * A call to this kfunc may reduce headroom. If there is not enough tailroom1223312233+ * in the linear data area, metadata and data will be shifted down.1223412234+ *1223512235+ * A call to this kfunc is susceptible to change the buffer geometry.1223612236+ * Therefore, at load time, all checks on pointers previously done by the1223712237+ * verifier are invalidated and must be performed again, if the kfunc is used1223812238+ * in combination with direct packet access.1223912239+ *1224012240+ * Return:1224112241+ * * %0 - success1224212242+ * * %-EINVAL - invalid len1224312243+ */1224412244+__bpf_kfunc int bpf_xdp_pull_data(struct xdp_md *x, u32 len)1224512245+{1224612246+ struct xdp_buff *xdp = (struct xdp_buff *)x;1224712247+ struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);1224812248+ int i, delta, shift, headroom, tailroom, n_frags_free = 0;1224912249+ void *data_hard_end = xdp_data_hard_end(xdp);1225012250+ int data_len = xdp->data_end - xdp->data;1225112251+ void *start;1225212252+1225312253+ if (len <= data_len)1225412254+ return 0;1225512255+1225612256+ if (unlikely(len > xdp_get_buff_len(xdp)))1225712257+ return -EINVAL;1225812258+1225912259+ start = xdp_data_meta_unsupported(xdp) ? xdp->data : xdp->data_meta;1226012260+1226112261+ headroom = start - xdp->data_hard_start - sizeof(struct xdp_frame);1226212262+ tailroom = data_hard_end - xdp->data_end;1226312263+1226412264+ delta = len - data_len;1226512265+ if (unlikely(delta > tailroom + headroom))1226612266+ return -EINVAL;1226712267+1226812268+ shift = delta - tailroom;1226912269+ if (shift > 0) {1227012270+ memmove(start - shift, start, xdp->data_end - start);1227112271+1227212272+ xdp->data_meta -= shift;1227312273+ xdp->data -= shift;1227412274+ xdp->data_end -= shift;1227512275+ }1227612276+1227712277+ for (i = 0; i < sinfo->nr_frags && delta; i++) {1227812278+ skb_frag_t *frag = &sinfo->frags[i];1227912279+ u32 shrink = min_t(u32, delta, skb_frag_size(frag));1228012280+1228112281+ memcpy(xdp->data_end, skb_frag_address(frag), shrink);1228212282+1228312283+ xdp->data_end += shrink;1228412284+ sinfo->xdp_frags_size -= shrink;1228512285+ delta -= shrink;1228612286+ if (bpf_xdp_shrink_data(xdp, frag, shrink, false))1228712287+ n_frags_free++;1228812288+ }1228912289+1229012290+ if (unlikely(n_frags_free)) {1229112291+ memmove(sinfo->frags, sinfo->frags + n_frags_free,1229212292+ (sinfo->nr_frags - n_frags_free) * sizeof(skb_frag_t));1229312293+1229412294+ sinfo->nr_frags -= n_frags_free;1229512295+1229612296+ if (!sinfo->nr_frags) {1229712297+ xdp_buff_clear_frags_flag(xdp);1229812298+ xdp_buff_clear_frag_pfmemalloc(xdp);1229912299+ }1230012300+ }1230112301+1230212302+ return 0;1230312303+}1230412304+1222112305__bpf_kfunc_end_defs();12222123061222312307int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,···12337122371233812238BTF_KFUNCS_START(bpf_kfunc_check_set_xdp)1233912239BTF_ID_FLAGS(func, bpf_dynptr_from_xdp)1224012240+BTF_ID_FLAGS(func, bpf_xdp_pull_data)1234012241BTF_KFUNCS_END(bpf_kfunc_check_set_xdp)12341122421234212243BTF_KFUNCS_START(bpf_kfunc_check_set_sock_addr)
···9797 /* Meta data must be 255 bytes or smaller */9898 test_xdp_context_error(prog_fd, opts, 0, 256, sizeof(data), 0, 0, 0);9999100100- /* Total size of data must match data_end - data_meta */101101- test_xdp_context_error(prog_fd, opts, 0, sizeof(__u32),102102- sizeof(data) - 1, 0, 0, 0);100100+ /* Total size of data must be data_end - data_meta or larger */103101 test_xdp_context_error(prog_fd, opts, 0, sizeof(__u32),104102 sizeof(data) + 1, 0, 0, 0);105103