[PATCH openEuler-23.09,0/6] tcp compression bugfix

Lu Wei (1): tcp_comp: Fix receives err when server receives a large packet Wang Yufen (5): tcp_comp: Avoiding the null pointer problem of ctx in comp_stream_read tcp_comp: Fix comp_read_size return value tcp_comp: Fix ZSTD_decompressStream failed tcp_comp: Add dpkt to save decompressed skb tcp_comp: Del compressed_data and remaining_data from tcp_comp_context_rx net/ipv4/tcp_comp.c | 193 ++++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 95 deletions(-) -- 2.31.1

From: Wang Yufen <wangyufen@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I45UYC?from=project-issue CVE: NA ------------------------------------------------- In comp_stream_read ctx might be null, add null check to avoid oops. And delete unnecessary tcp_comp_err_abort. Signed-off-by: Wang Yufen <wangyufen@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> Reviewed-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> --- net/ipv4/tcp_comp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_comp.c b/net/ipv4/tcp_comp.c index 1e5e00369f88..739e59036e25 100644 --- a/net/ipv4/tcp_comp.c +++ b/net/ipv4/tcp_comp.c @@ -697,8 +697,6 @@ static int tcp_comp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (!ctx->rx.decompressed) { err = tcp_comp_decompress(sk, skb); if (err < 0) { - if (err != -ENOSPC) - tcp_comp_err_abort(sk, EBADMSG); goto recv_end; } ctx->rx.decompressed = true; @@ -732,6 +730,9 @@ bool comp_stream_read(struct sock *sk) { struct tcp_comp_context *ctx = comp_get_ctx(sk); + if (!ctx) + return false; + if (ctx->rx.pkt) return true; -- 2.31.1

From: Wang Yufen <wangyufen@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I47SV5?from=project-issue CVE: NA ------------------------------------------------- In comp_read_size rxm->offset should be subtracted from skb->len. And use strp_done to release resoureces when destroy sock. Signed-off-by: Wang Yufen <wangyufen@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> Reviewed-by: Wei Yongjun <weiyongjun1@huawei.com> Reviewed-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> --- net/ipv4/tcp_comp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_comp.c b/net/ipv4/tcp_comp.c index 739e59036e25..bbb635284af4 100644 --- a/net/ipv4/tcp_comp.c +++ b/net/ipv4/tcp_comp.c @@ -763,7 +763,7 @@ static int comp_read_size(struct strparser *strp, struct sk_buff *skb) if (rxm->offset > skb->len) return 0; - return skb->len; + return skb->len - rxm->offset; } void comp_setup_strp(struct sock *sk, struct tcp_comp_context *ctx) @@ -870,6 +870,7 @@ static void tcp_comp_context_free(struct rcu_head *head) tcp_comp_context_tx_free(ctx); tcp_comp_context_rx_free(ctx); + strp_done(&ctx->rx.strp); kfree(ctx); } @@ -885,6 +886,7 @@ void tcp_cleanup_compression(struct sock *sk) kfree_skb(ctx->rx.pkt); ctx->rx.pkt = NULL; } + strp_stop(&ctx->rx.strp); rcu_assign_pointer(icsk->icsk_ulp_data, NULL); call_rcu(&ctx->rcu, tcp_comp_context_free); -- 2.31.1

From: Wang Yufen <wangyufen@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I48H9Z?from=project-issue CVE: NA ------------------------------------------------- This patch fixes possible ZSTD_decompressStream failures. When decompressing skb->data, should skip the previous rxm->offset data. Signed-off-by: Wang Yufen <wangyufen@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> Reviewed-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> --- net/ipv4/tcp_comp.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/ipv4/tcp_comp.c b/net/ipv4/tcp_comp.c index bbb635284af4..fe9451984fdb 100644 --- a/net/ipv4/tcp_comp.c +++ b/net/ipv4/tcp_comp.c @@ -569,8 +569,8 @@ static void *tcp_comp_get_rx_stream(struct sock *sk) static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) { struct tcp_comp_context *ctx = comp_get_ctx(sk); + struct strp_msg *rxm = strp_msg(skb); const int plen = skb->len; - struct strp_msg *rxm; ZSTD_outBuffer outbuf; ZSTD_inBuffer inbuf; int len; @@ -591,11 +591,11 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) ctx->rx.data_offset); memcpy((char *)ctx->rx.compressed_data + ctx->rx.data_offset, - skb->data, plen); + (char *)skb->data + rxm->offset, plen - rxm->offset); inbuf.src = ctx->rx.compressed_data; inbuf.pos = 0; - inbuf.size = plen + ctx->rx.data_offset; + inbuf.size = plen - rxm->offset + ctx->rx.data_offset; ctx->rx.data_offset = 0; outbuf.dst = ctx->rx.plaintext_data; @@ -606,7 +606,6 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) size_t ret; to = outbuf.dst; - ret = ZSTD_decompressStream(ctx->rx.dstream, &outbuf, &inbuf); if (ZSTD_isError(ret)) return -EIO; @@ -616,8 +615,8 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) len = skb_tailroom(skb); __skb_put(skb, len); - rxm = strp_msg(skb); - rxm->full_len += len; + rxm->full_len += (len + rxm->offset); + rxm->offset = 0; len += plen; skb_copy_to_linear_data(skb, to, len); -- 2.31.1

From: Wang Yufen <wangyufen@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I48H9Z?from=project-issue CVE: NA ------------------------------------------------- In order to separate the compressed data and decompressed data, this patch adds dpkt to tcp_comp_context_rx, dpkt is used to save decompressed skb. Signed-off-by: Wang Yufen <wangyufen@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> Reviewed-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> --- net/ipv4/tcp_comp.c | 94 ++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/net/ipv4/tcp_comp.c b/net/ipv4/tcp_comp.c index fe9451984fdb..531c90210493 100644 --- a/net/ipv4/tcp_comp.c +++ b/net/ipv4/tcp_comp.c @@ -45,7 +45,7 @@ struct tcp_comp_context_rx { struct strparser strp; void (*saved_data_ready)(struct sock *sk); struct sk_buff *pkt; - bool decompressed; + struct sk_buff *dpkt; }; struct tcp_comp_context { @@ -510,6 +510,24 @@ static bool comp_advance_skb(struct sock *sk, struct sk_buff *skb, return true; } +static bool comp_advance_dskb(struct sock *sk, struct sk_buff *skb, + unsigned int len) +{ + struct tcp_comp_context *ctx = comp_get_ctx(sk); + struct strp_msg *rxm = strp_msg(skb); + + if (len < rxm->full_len) { + rxm->offset += len; + rxm->full_len -= len; + return false; + } + + /* Finished with message */ + ctx->rx.dpkt = NULL; + kfree_skb(skb); + return true; +} + static int tcp_comp_rx_context_init(struct tcp_comp_context *ctx) { int dsize; @@ -566,13 +584,14 @@ static void *tcp_comp_get_rx_stream(struct sock *sk) return ctx->rx.plaintext_data; } -static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) +static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags) { struct tcp_comp_context *ctx = comp_get_ctx(sk); struct strp_msg *rxm = strp_msg(skb); const int plen = skb->len; ZSTD_outBuffer outbuf; ZSTD_inBuffer inbuf; + struct sk_buff *nskb; int len; void *to; @@ -586,6 +605,10 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) if (plen + ctx->rx.data_offset > TCP_COMP_MAX_CSIZE) return -ENOMEM; + nskb = skb_copy(skb, GFP_KERNEL); + if (!nskb) + return -ENOMEM; + if (ctx->rx.data_offset) memcpy(ctx->rx.compressed_data, ctx->rx.remaining_data, ctx->rx.data_offset); @@ -607,34 +630,38 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) to = outbuf.dst; ret = ZSTD_decompressStream(ctx->rx.dstream, &outbuf, &inbuf); - if (ZSTD_isError(ret)) + if (ZSTD_isError(ret)) { + kfree_skb(nskb); return -EIO; + } len = outbuf.pos - plen; - if (len > skb_tailroom(skb)) - len = skb_tailroom(skb); + if (len > skb_tailroom(nskb)) + len = skb_tailroom(nskb); - __skb_put(skb, len); - rxm->full_len += (len + rxm->offset); - rxm->offset = 0; + __skb_put(nskb, len); len += plen; - skb_copy_to_linear_data(skb, to, len); + skb_copy_to_linear_data(nskb, to, len); while ((to += len, outbuf.pos -= len) > 0) { struct page *pages; skb_frag_t *frag; - if (WARN_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) + if (WARN_ON(skb_shinfo(nskb)->nr_frags >= MAX_SKB_FRAGS)) { + kfree_skb(nskb); return -EMSGSIZE; + } - frag = skb_shinfo(skb)->frags + - skb_shinfo(skb)->nr_frags; + frag = skb_shinfo(nskb)->frags + + skb_shinfo(nskb)->nr_frags; pages = alloc_pages(__GFP_NOWARN | GFP_KERNEL | __GFP_COMP, TCP_COMP_ALLOC_ORDER); - if (!pages) + if (!pages) { + kfree_skb(nskb); return -ENOMEM; + } __skb_frag_set_page(frag, pages); len = PAGE_SIZE << TCP_COMP_ALLOC_ORDER; @@ -645,11 +672,10 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) skb_frag_size_set(frag, len); memcpy(skb_frag_address(frag), to, len); - skb->truesize += len; - skb->data_len += len; - skb->len += len; - rxm->full_len += len; - skb_shinfo(skb)->nr_frags++; + nskb->truesize += len; + nskb->data_len += len; + nskb->len += len; + skb_shinfo(nskb)->nr_frags++; } if (ret == 0) @@ -665,6 +691,13 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb) break; } } + + ctx->rx.dpkt = nskb; + rxm = strp_msg(nskb); + rxm->full_len = nskb->len; + rxm->offset = 0; + comp_advance_skb(sk, skb, plen - rxm->offset); + return 0; } @@ -689,21 +722,19 @@ static int tcp_comp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, do { int chunk = 0; - skb = comp_wait_data(sk, flags, timeo, &err); - if (!skb) - goto recv_end; + if (!ctx->rx.dpkt) { + skb = comp_wait_data(sk, flags, timeo, &err); + if (!skb) + goto recv_end; - if (!ctx->rx.decompressed) { - err = tcp_comp_decompress(sk, skb); + err = tcp_comp_decompress(sk, skb, flags); if (err < 0) { goto recv_end; } - ctx->rx.decompressed = true; } + skb = ctx->rx.dpkt; rxm = strp_msg(skb); - chunk = min_t(unsigned int, rxm->full_len, len); - err = skb_copy_datagram_msg(skb, rxm->offset, msg, chunk); if (err < 0) @@ -712,11 +743,11 @@ static int tcp_comp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, copied += chunk; len -= chunk; if (likely(!(flags & MSG_PEEK))) - comp_advance_skb(sk, skb, chunk); + comp_advance_dskb(sk, skb, chunk); else break; - if (copied >= target && !ctx->rx.pkt) + if (copied >= target && !ctx->rx.dpkt) break; } while (len > 0); @@ -732,7 +763,7 @@ bool comp_stream_read(struct sock *sk) if (!ctx) return false; - if (ctx->rx.pkt) + if (ctx->rx.pkt || ctx->rx.dpkt) return true; return false; @@ -749,7 +780,6 @@ static void comp_queue(struct strparser *strp, struct sk_buff *skb) { struct tcp_comp_context *ctx = comp_get_ctx(strp->sk); - ctx->rx.decompressed = false; ctx->rx.pkt = skb; strp_pause(strp); ctx->rx.saved_data_ready(strp->sk); @@ -885,6 +915,10 @@ void tcp_cleanup_compression(struct sock *sk) kfree_skb(ctx->rx.pkt); ctx->rx.pkt = NULL; } + if (ctx->rx.dpkt) { + kfree_skb(ctx->rx.dpkt); + ctx->rx.dpkt = NULL; + } strp_stop(&ctx->rx.strp); rcu_assign_pointer(icsk->icsk_ulp_data, NULL); -- 2.31.1

From: Wang Yufen <wangyufen@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I48H9Z?from=project-issue CVE: NA ------------------------------------------------- The compressed data and decompressed data is separated. There is no need to save the uncompressed data to remaining_data buffer, can directly read data from the uncompressed skb. Signed-off-by: Wang Yufen <wangyufen@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> Reviewed-by: Wei Yongjun <weiyongjun1@huawei.com> Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> --- net/ipv4/tcp_comp.c | 98 ++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 68 deletions(-) diff --git a/net/ipv4/tcp_comp.c b/net/ipv4/tcp_comp.c index 531c90210493..1c757a132a60 100644 --- a/net/ipv4/tcp_comp.c +++ b/net/ipv4/tcp_comp.c @@ -38,10 +38,7 @@ struct tcp_comp_context_rx { ZSTD_DStream *dstream; void *dworkspace; void *plaintext_data; - void *compressed_data; - void *remaining_data; - size_t data_offset; struct strparser strp; void (*saved_data_ready)(struct sock *sk); struct sk_buff *pkt; @@ -549,24 +546,8 @@ static int tcp_comp_rx_context_init(struct tcp_comp_context *ctx) if (!ctx->rx.plaintext_data) goto err_dstream; - ctx->rx.compressed_data = kvmalloc(TCP_COMP_MAX_CSIZE, GFP_KERNEL); - if (!ctx->rx.compressed_data) - goto err_compressed; - - ctx->rx.remaining_data = kvmalloc(TCP_COMP_MAX_CSIZE, GFP_KERNEL); - if (!ctx->rx.remaining_data) - goto err_remaining; - - ctx->rx.data_offset = 0; - return 0; -err_remaining: - kvfree(ctx->rx.compressed_data); - ctx->rx.compressed_data = NULL; -err_compressed: - kvfree(ctx->rx.plaintext_data); - ctx->rx.plaintext_data = NULL; err_dstream: kfree(ctx->rx.dworkspace); ctx->rx.dworkspace = NULL; @@ -588,11 +569,12 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags) { struct tcp_comp_context *ctx = comp_get_ctx(sk); struct strp_msg *rxm = strp_msg(skb); - const int plen = skb->len; + size_t ret, compressed_len = 0; + int nr_frags_over = 0; ZSTD_outBuffer outbuf; ZSTD_inBuffer inbuf; struct sk_buff *nskb; - int len; + int len, plen; void *to; to = tcp_comp_get_rx_stream(sk); @@ -602,62 +584,54 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags) if (skb_linearize_cow(skb)) return -ENOMEM; - if (plen + ctx->rx.data_offset > TCP_COMP_MAX_CSIZE) - return -ENOMEM; - nskb = skb_copy(skb, GFP_KERNEL); if (!nskb) return -ENOMEM; - if (ctx->rx.data_offset) - memcpy(ctx->rx.compressed_data, ctx->rx.remaining_data, - ctx->rx.data_offset); - - memcpy((char *)ctx->rx.compressed_data + ctx->rx.data_offset, - (char *)skb->data + rxm->offset, plen - rxm->offset); - - inbuf.src = ctx->rx.compressed_data; - inbuf.pos = 0; - inbuf.size = plen - rxm->offset + ctx->rx.data_offset; - ctx->rx.data_offset = 0; + while (compressed_len < (skb->len - rxm->offset)) { + len = 0; + plen = skb->len - rxm->offset - compressed_len; + if (plen > TCP_COMP_MAX_CSIZE) + plen = TCP_COMP_MAX_CSIZE; - outbuf.dst = ctx->rx.plaintext_data; - outbuf.pos = 0; - outbuf.size = TCP_COMP_MAX_CSIZE * 32; + inbuf.src = (char *)skb->data + rxm->offset + compressed_len; + inbuf.pos = 0; + inbuf.size = plen; - while (1) { - size_t ret; + outbuf.dst = ctx->rx.plaintext_data; + outbuf.pos = 0; + outbuf.size = TCP_COMP_MAX_CSIZE * 32; - to = outbuf.dst; ret = ZSTD_decompressStream(ctx->rx.dstream, &outbuf, &inbuf); if (ZSTD_isError(ret)) { kfree_skb(nskb); return -EIO; } - len = outbuf.pos - plen; - if (len > skb_tailroom(nskb)) - len = skb_tailroom(nskb); + if (!compressed_len) { + len = outbuf.pos - skb->len; + if (len > skb_tailroom(nskb)) + len = skb_tailroom(nskb); - __skb_put(nskb, len); + __skb_put(nskb, len); - len += plen; - skb_copy_to_linear_data(nskb, to, len); + len += skb->len; + skb_copy_to_linear_data(nskb, to, len); + } while ((to += len, outbuf.pos -= len) > 0) { struct page *pages; skb_frag_t *frag; - if (WARN_ON(skb_shinfo(nskb)->nr_frags >= MAX_SKB_FRAGS)) { - kfree_skb(nskb); - return -EMSGSIZE; + if (skb_shinfo(nskb)->nr_frags >= MAX_SKB_FRAGS) { + nr_frags_over = 1; + break; } frag = skb_shinfo(nskb)->frags + skb_shinfo(nskb)->nr_frags; pages = alloc_pages(__GFP_NOWARN | GFP_KERNEL | __GFP_COMP, TCP_COMP_ALLOC_ORDER); - if (!pages) { kfree_skb(nskb); return -ENOMEM; @@ -678,25 +652,17 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags) skb_shinfo(nskb)->nr_frags++; } - if (ret == 0) + if (nr_frags_over) break; - if (inbuf.pos >= plen || !inbuf.pos) { - if (inbuf.pos < inbuf.size) { - memcpy((char *)ctx->rx.remaining_data, - (char *)inbuf.src + inbuf.pos, - inbuf.size - inbuf.pos); - ctx->rx.data_offset = inbuf.size - inbuf.pos; - } - break; - } + compressed_len += inbuf.pos; } ctx->rx.dpkt = nskb; rxm = strp_msg(nskb); rxm->full_len = nskb->len; rxm->offset = 0; - comp_advance_skb(sk, skb, plen - rxm->offset); + comp_advance_skb(sk, skb, compressed_len); return 0; } @@ -732,6 +698,7 @@ static int tcp_comp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, goto recv_end; } } + skb = ctx->rx.dpkt; rxm = strp_msg(skb); chunk = min_t(unsigned int, rxm->full_len, len); @@ -883,12 +850,6 @@ static void tcp_comp_context_rx_free(struct tcp_comp_context *ctx) kvfree(ctx->rx.plaintext_data); ctx->rx.plaintext_data = NULL; - - kvfree(ctx->rx.compressed_data); - ctx->rx.compressed_data = NULL; - - kvfree(ctx->rx.remaining_data); - ctx->rx.remaining_data = NULL; } static void tcp_comp_context_free(struct rcu_head *head) @@ -915,6 +876,7 @@ void tcp_cleanup_compression(struct sock *sk) kfree_skb(ctx->rx.pkt); ctx->rx.pkt = NULL; } + if (ctx->rx.dpkt) { kfree_skb(ctx->rx.dpkt); ctx->rx.dpkt = NULL; -- 2.31.1

Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I60M9A ---------------------------------------- When tcp compression is uses, if server receives a large packet, which is larger than PAGE_SIZES * MAX_SKB_FRAGS bytes, it needs more than one skb to store the data since one skb can only store PAGE_SIZES * MAX_SKB_FRAGS bytes data. In function tcp_comp_decompress(), it breaks the while-loop which copy decompressed data to new skb when more than MAX_SKB_FRAGS pages is needed, causing part of data is copied into the new skb and received by user but the compressed_len is not added. In this case, the data will be decompressed infinitely. The patch limits the decompressed length so it can be copied into one skb. Moreover, once a skb is full, quit decompress process directly. Fixes: c31c696f9300 ("tcp_comp: Del compressed_data and remaining_data from tcp_comp_context_rx") Signed-off-by: Lu Wei <luwei32@huawei.com> Signed-off-by: Lu Wei <luwei32@huawei.com> --- net/ipv4/tcp_comp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_comp.c b/net/ipv4/tcp_comp.c index 1c757a132a60..dec62ef5c0ef 100644 --- a/net/ipv4/tcp_comp.c +++ b/net/ipv4/tcp_comp.c @@ -9,9 +9,10 @@ #include <linux/zstd.h> #define TCP_COMP_MAX_PADDING 64 -#define TCP_COMP_SCRATCH_SIZE 65535 +#define TCP_COMP_DATA_SIZE 65536 +#define TCP_COMP_SCRATCH_SIZE (TCP_COMP_DATA_SIZE - 1) #define TCP_COMP_MAX_CSIZE (TCP_COMP_SCRATCH_SIZE + TCP_COMP_MAX_PADDING) -#define TCP_COMP_ALLOC_ORDER get_order(65536) +#define TCP_COMP_ALLOC_ORDER get_order(TCP_COMP_DATA_SIZE) #define TCP_COMP_MAX_WINDOWLOG 17 #define TCP_COMP_MAX_INPUT (1 << TCP_COMP_MAX_WINDOWLOG) @@ -589,6 +590,9 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags) return -ENOMEM; while (compressed_len < (skb->len - rxm->offset)) { + if (skb_shinfo(nskb)->nr_frags >= MAX_SKB_FRAGS) + break; + len = 0; plen = skb->len - rxm->offset - compressed_len; if (plen > TCP_COMP_MAX_CSIZE) @@ -600,7 +604,8 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags) outbuf.dst = ctx->rx.plaintext_data; outbuf.pos = 0; - outbuf.size = TCP_COMP_MAX_CSIZE * 32; + outbuf.size = MAX_SKB_FRAGS * TCP_COMP_DATA_SIZE; + outbuf.size -= skb_shinfo(nskb)->nr_frags * TCP_COMP_DATA_SIZE; ret = ZSTD_decompressStream(ctx->rx.dstream, &outbuf, &inbuf); if (ZSTD_isError(ret)) { -- 2.31.1
participants (1)
-
Lu Wei