Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix invalid hpack decoding #1874

Merged
merged 13 commits into from
May 26, 2023
Merged

Fix invalid hpack decoding #1874

merged 13 commits into from
May 26, 2023

Conversation

EvgeniiMekhanik
Copy link
Contributor

Continue decode hpack value same as we do it
if this value was not devide between several
frames.

@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch 2 times, most recently from add4f16 to 6dfe462 Compare April 25, 2023 13:39
@EvgeniiMekhanik EvgeniiMekhanik marked this pull request as draft April 25, 2023 13:39
@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch from 6dfe462 to 1715bb1 Compare April 26, 2023 14:58
@EvgeniiMekhanik EvgeniiMekhanik marked this pull request as ready for review April 26, 2023 20:58
@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch from 0c66f11 to 0b640b6 Compare May 3, 2023 11:25
@EvgeniiMekhanik EvgeniiMekhanik marked this pull request as draft May 3, 2023 13:20
@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch 4 times, most recently from bcfec45 to 76d1d7a Compare May 5, 2023 17:52
@EvgeniiMekhanik EvgeniiMekhanik marked this pull request as ready for review May 5, 2023 17:52
Copy link
Contributor

@const-t const-t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

fw/sock.c Show resolved Hide resolved
fw/sync_socket.h Outdated Show resolved Hide resolved
@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch 4 times, most recently from 45dbefd to a090214 Compare May 18, 2023 09:53
@EvgeniiMekhanik EvgeniiMekhanik requested a review from const-t May 18, 2023 10:01
@@ -393,6 +393,7 @@ __split_linear_data(struct sk_buff *skb_head, struct sk_buff *skb, char *pspt,
}
skb->tail -= tail_len;
skb->data_len += tail_len;
skb->truesize += tail_len;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please look for this place carefully! This code is necessary to prevent warning in kernel with small MTU and it makes akb truesize correct. But i don't fully understand why

Copy link
Contributor

@const-t const-t May 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I see it's correct fix. We need to adjust truesize when we move data from linear part to paged fragments.

Lat's see on truesize in kernel, it's consist of size of skb data + sizeof(sk_buff) + sizeof(skb_shared_info). It means size of reserved linear data will be included in truesize during skb allocating. Because we don't change preallocated size of skb head when we manipulate with it, we must not change truesize.
However, when we move data from head to paged we increase size of skb(data_len) by adding new fragment, even if it points to already allocated data within skb. Thus, we must increment truesize. Just for clarity, if we will realloc the skb, we can allocate less data to headroom and in this case we can not change truesize.

@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch from a090214 to 67b232a Compare May 18, 2023 11:59
Continue decode hpack value same as we do it
if this value was not devide between several
frames.
In case when skb_room is equal to zero and we
allocate a new skb, we should move some fragments
from the first skb only if it contains body.
Also we should allocate new skb if skb frags is
equal to MAX_SKB_FRAGS, not use next skb, because
next skb already contain headers!
In case when frame is not completely received
and first part of frame was prossed with error
we should not zero `ctx->to_read` value, since
we should read the remaining part of the frame.
@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch 3 times, most recently from f975347 to 6650f76 Compare May 19, 2023 16:42
fw/http_match.c Outdated Show resolved Hide resolved
@@ -393,6 +393,7 @@ __split_linear_data(struct sk_buff *skb_head, struct sk_buff *skb, char *pspt,
}
skb->tail -= tail_len;
skb->data_len += tail_len;
skb->truesize += tail_len;
Copy link
Contributor

@const-t const-t May 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I see it's correct fix. We need to adjust truesize when we move data from linear part to paged fragments.

Lat's see on truesize in kernel, it's consist of size of skb data + sizeof(sk_buff) + sizeof(skb_shared_info). It means size of reserved linear data will be included in truesize during skb allocating. Because we don't change preallocated size of skb head when we manipulate with it, we must not change truesize.
However, when we move data from head to paged we increase size of skb(data_len) by adding new fragment, even if it points to already allocated data within skb. Thus, we must increment truesize. Just for clarity, if we will realloc the skb, we can allocate less data to headroom and in this case we can not change truesize.

Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems there are several issues

fw/hpack.h Outdated Show resolved Hide resolved
@@ -1311,6 +1318,7 @@ ss_skb_init_for_xmit(struct sk_buff *skb)

skb_dst_drop(skb);
INIT_LIST_HEAD(&skb->tcp_tsorted_anchor);
skb->tail_lock = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ss_skb_init_for_xmit() is called for all skbs being sent via ss_do_send(), so a message, transformed splitting the linear part (and setting skb->tail_lock = 1), might go via this code and the kernel will try to amend the tail of the linear part.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently kernel can't work with tail_lock. If skb passed to the kernel code with tail_lock = 1 it leads to panic.

Copy link
Contributor

@krizhanovsky krizhanovsky May 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I understood you correctly. We have skb_is_nonlinear() and skb_tailroom_locked() working with tail_lock, which apparently must not crash. There is some bug around tail_lock, which we need to fix, or we should fix both the function to assert BUG_ON(skb->tail_lock).

Does this PR close #1860? If yes, then we need at least to add this issue to #1859 and make much better explanation what's wrong with tail_lock in the issue. I'm confused with the current state of tail_lock in our code.


Answer:
ss_skb_init_for_xmit is called before we pass skb to the kernel code. We can't pass skb to the kernel code with tail_lock = 1, because kernel can pass this skb to the __skb_put and it will lead to crash.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We agreed to add /* TODO #1859 #1860 ... */ comment and merge the PR.

fw/sock.c Outdated Show resolved Hide resolved
fw/sock.c Show resolved Hide resolved
fw/hpack.c Show resolved Hide resolved
fw/ss_skb.c Outdated Show resolved Hide resolved
fw/http_match.c Outdated Show resolved Hide resolved
@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch 2 times, most recently from 5c0a5f8 to 5b0caf5 Compare May 24, 2023 08:04
Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pull request looks good to merge with the cleanup and data layout improvement. The only topic to discuss, which stops me from approving, is the unclear tail_lock logic. Probably we just should move it to #1859 . Shouldn't we merge #1860 and #1859?

fw/hpack.h Outdated Show resolved Hide resolved
fw/http_parser.c Outdated Show resolved Hide resolved
@@ -1311,6 +1318,7 @@ ss_skb_init_for_xmit(struct sk_buff *skb)

skb_dst_drop(skb);
INIT_LIST_HEAD(&skb->tcp_tsorted_anchor);
skb->tail_lock = 0;
Copy link
Contributor

@krizhanovsky krizhanovsky May 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I understood you correctly. We have skb_is_nonlinear() and skb_tailroom_locked() working with tail_lock, which apparently must not crash. There is some bug around tail_lock, which we need to fix, or we should fix both the function to assert BUG_ON(skb->tail_lock).

Does this PR close #1860? If yes, then we need at least to add this issue to #1859 and make much better explanation what's wrong with tail_lock in the issue. I'm confused with the current state of tail_lock in our code.


Answer:
ss_skb_init_for_xmit is called before we pass skb to the kernel code. We can't pass skb to the kernel code with tail_lock = 1, because kernel can pass this skb to the __skb_put and it will lead to crash.

@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch 2 times, most recently from 090ea1b to 5082e1f Compare May 26, 2023 08:17
Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -1311,6 +1318,7 @@ ss_skb_init_for_xmit(struct sk_buff *skb)

skb_dst_drop(skb);
INIT_LIST_HEAD(&skb->tcp_tsorted_anchor);
skb->tail_lock = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We agreed to add /* TODO #1859 #1860 ... */ comment and merge the PR.

EvgeniiMekhanik and others added 10 commits May 26, 2023 18:33
We should set skb->tail_lock for the new skbs,
because it could be set previously during some
skb fragmentation. This field should be zero when
we pass skb to the kernel code.
Previously we sent FIN to remote peer during socket
closing, but didn't wait for ack to this FIN. Moreover
if we could not transmit pending skbs we closed socket
and lost these skbs. Now we don't drop connection until
last ACK is come.
We should abort and drop all server connections, which are
not closed gracefully.
After `skb_fragment` call we should upodate `skb` and `ptr`
values using new values from `it`.
Also improve work of `ss_skb_cutoff_data` function. If we deal
with single skb we should update pointers in TfwStr only when
new skb was allocated during `skb_fragment`.

Closes #1864
Function `tfw_http_search_host_forwarded` worked
incorrectly with TCP segmentation. We can't compare
chunk by chunk with "host=", because "host=" can be
separated between several chunks.
Before http request trailer headers check, we have to
make sure that requerst is fully parsed.
- Change `offset` size to 16 bit and move it
  before `index` field.
- Change `index` size to 32 bit because it is
  enough and it is better to struct layout.
- Remove checking that forwarded host and
  header host is equal.
- Copy `__extract_request_authority` function to unit tests
  and use to set req->host value in appropriate tests as we
  do it in tempesta.

- Fix unit tests according to changes in `match_host`
  function.
Moving body logic extracted to function and do it
only if we have the body. Pointer to body never be
NULL more safer not use it wthout check the body
length.
@EvgeniiMekhanik EvgeniiMekhanik force-pushed the MekhanikEvgenii-part-of-1867 branch from 69236c0 to 2417cda Compare May 26, 2023 15:33
@krizhanovsky krizhanovsky merged commit 9e3b4b4 into master May 26, 2023
@krizhanovsky krizhanovsky deleted the MekhanikEvgenii-part-of-1867 branch May 26, 2023 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants