提交 c31c696f 编写于 作者: W Wang Yufen 提交者: Zheng Zengkai

tcp_comp: Del compressed_data and remaining_data from tcp_comp_context_rx

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: NWang Yufen <wangyufen@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NLu Wei <luwei32@huawei.com>
Reviewed-by: NWei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 c5f3ee69
...@@ -38,10 +38,7 @@ struct tcp_comp_context_rx { ...@@ -38,10 +38,7 @@ struct tcp_comp_context_rx {
ZSTD_DStream *dstream; ZSTD_DStream *dstream;
void *dworkspace; void *dworkspace;
void *plaintext_data; void *plaintext_data;
void *compressed_data;
void *remaining_data;
size_t data_offset;
struct strparser strp; struct strparser strp;
void (*saved_data_ready)(struct sock *sk); void (*saved_data_ready)(struct sock *sk);
struct sk_buff *pkt; struct sk_buff *pkt;
...@@ -549,24 +546,8 @@ static int tcp_comp_rx_context_init(struct tcp_comp_context *ctx) ...@@ -549,24 +546,8 @@ static int tcp_comp_rx_context_init(struct tcp_comp_context *ctx)
if (!ctx->rx.plaintext_data) if (!ctx->rx.plaintext_data)
goto err_dstream; 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; 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: err_dstream:
kfree(ctx->rx.dworkspace); kfree(ctx->rx.dworkspace);
ctx->rx.dworkspace = NULL; ctx->rx.dworkspace = NULL;
...@@ -588,11 +569,12 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags) ...@@ -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 tcp_comp_context *ctx = comp_get_ctx(sk);
struct strp_msg *rxm = strp_msg(skb); 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_outBuffer outbuf;
ZSTD_inBuffer inbuf; ZSTD_inBuffer inbuf;
struct sk_buff *nskb; struct sk_buff *nskb;
int len; int len, plen;
void *to; void *to;
to = tcp_comp_get_rx_stream(sk); 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) ...@@ -602,62 +584,54 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags)
if (skb_linearize_cow(skb)) if (skb_linearize_cow(skb))
return -ENOMEM; return -ENOMEM;
if (plen + ctx->rx.data_offset > TCP_COMP_MAX_CSIZE)
return -ENOMEM;
nskb = skb_copy(skb, GFP_KERNEL); nskb = skb_copy(skb, GFP_KERNEL);
if (!nskb) if (!nskb)
return -ENOMEM; return -ENOMEM;
if (ctx->rx.data_offset) while (compressed_len < (skb->len - rxm->offset)) {
memcpy(ctx->rx.compressed_data, ctx->rx.remaining_data, len = 0;
ctx->rx.data_offset); plen = skb->len - rxm->offset - compressed_len;
if (plen > TCP_COMP_MAX_CSIZE)
memcpy((char *)ctx->rx.compressed_data + ctx->rx.data_offset, plen = TCP_COMP_MAX_CSIZE;
(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;
outbuf.dst = ctx->rx.plaintext_data; inbuf.src = (char *)skb->data + rxm->offset + compressed_len;
outbuf.pos = 0; inbuf.pos = 0;
outbuf.size = TCP_COMP_MAX_CSIZE * 32; inbuf.size = plen;
while (1) { outbuf.dst = ctx->rx.plaintext_data;
size_t ret; outbuf.pos = 0;
outbuf.size = TCP_COMP_MAX_CSIZE * 32;
to = outbuf.dst;
ret = ZSTD_decompressStream(ctx->rx.dstream, &outbuf, &inbuf); ret = ZSTD_decompressStream(ctx->rx.dstream, &outbuf, &inbuf);
if (ZSTD_isError(ret)) { if (ZSTD_isError(ret)) {
kfree_skb(nskb); kfree_skb(nskb);
return -EIO; return -EIO;
} }
len = outbuf.pos - plen; if (!compressed_len) {
if (len > skb_tailroom(nskb)) len = outbuf.pos - skb->len;
len = skb_tailroom(nskb); if (len > skb_tailroom(nskb))
len = skb_tailroom(nskb);
__skb_put(nskb, len); __skb_put(nskb, len);
len += plen; len += skb->len;
skb_copy_to_linear_data(nskb, to, len); skb_copy_to_linear_data(nskb, to, len);
}
while ((to += len, outbuf.pos -= len) > 0) { while ((to += len, outbuf.pos -= len) > 0) {
struct page *pages; struct page *pages;
skb_frag_t *frag; skb_frag_t *frag;
if (WARN_ON(skb_shinfo(nskb)->nr_frags >= MAX_SKB_FRAGS)) { if (skb_shinfo(nskb)->nr_frags >= MAX_SKB_FRAGS) {
kfree_skb(nskb); nr_frags_over = 1;
return -EMSGSIZE; break;
} }
frag = skb_shinfo(nskb)->frags + frag = skb_shinfo(nskb)->frags +
skb_shinfo(nskb)->nr_frags; skb_shinfo(nskb)->nr_frags;
pages = alloc_pages(__GFP_NOWARN | GFP_KERNEL | __GFP_COMP, pages = alloc_pages(__GFP_NOWARN | GFP_KERNEL | __GFP_COMP,
TCP_COMP_ALLOC_ORDER); TCP_COMP_ALLOC_ORDER);
if (!pages) { if (!pages) {
kfree_skb(nskb); kfree_skb(nskb);
return -ENOMEM; return -ENOMEM;
...@@ -678,25 +652,17 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags) ...@@ -678,25 +652,17 @@ static int tcp_comp_decompress(struct sock *sk, struct sk_buff *skb, int flags)
skb_shinfo(nskb)->nr_frags++; skb_shinfo(nskb)->nr_frags++;
} }
if (ret == 0) if (nr_frags_over)
break; break;
if (inbuf.pos >= plen || !inbuf.pos) { compressed_len += 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;
}
} }
ctx->rx.dpkt = nskb; ctx->rx.dpkt = nskb;
rxm = strp_msg(nskb); rxm = strp_msg(nskb);
rxm->full_len = nskb->len; rxm->full_len = nskb->len;
rxm->offset = 0; rxm->offset = 0;
comp_advance_skb(sk, skb, plen - rxm->offset); comp_advance_skb(sk, skb, compressed_len);
return 0; return 0;
} }
...@@ -734,6 +700,7 @@ static int tcp_comp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, ...@@ -734,6 +700,7 @@ static int tcp_comp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
goto recv_end; goto recv_end;
} }
} }
skb = ctx->rx.dpkt; skb = ctx->rx.dpkt;
rxm = strp_msg(skb); rxm = strp_msg(skb);
chunk = min_t(unsigned int, rxm->full_len, len); chunk = min_t(unsigned int, rxm->full_len, len);
...@@ -885,12 +852,6 @@ static void tcp_comp_context_rx_free(struct tcp_comp_context *ctx) ...@@ -885,12 +852,6 @@ static void tcp_comp_context_rx_free(struct tcp_comp_context *ctx)
kvfree(ctx->rx.plaintext_data); kvfree(ctx->rx.plaintext_data);
ctx->rx.plaintext_data = NULL; 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) static void tcp_comp_context_free(struct rcu_head *head)
...@@ -917,6 +878,7 @@ void tcp_cleanup_compression(struct sock *sk) ...@@ -917,6 +878,7 @@ void tcp_cleanup_compression(struct sock *sk)
kfree_skb(ctx->rx.pkt); kfree_skb(ctx->rx.pkt);
ctx->rx.pkt = NULL; ctx->rx.pkt = NULL;
} }
if (ctx->rx.dpkt) { if (ctx->rx.dpkt) {
kfree_skb(ctx->rx.dpkt); kfree_skb(ctx->rx.dpkt);
ctx->rx.dpkt = NULL; ctx->rx.dpkt = NULL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册