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 unreleased cache buffer in QUIC sniffing #3320

Merged

Conversation

Vigilans
Copy link
Contributor

@Vigilans Vigilans commented Feb 20, 2025

May address #3316

In the issue report, witness two byte slices's addresses provided toseal:

github.com/v2fly/v2ray-core/v5/common/crypto.(*AEADAuthenticator).Seal(0xc00b3f0240, {0xc001567012, 0x0, 0x7ee}, {0xc001567000, 0x168, 0x800})

The dst's address is 0xc001567012, the plain text's address is 0xc001567000.

The dst's code is:

eb := buf.New()
w.sizeParser.Encode(uint16(encryptedSize+paddingSize), eb.Extend(sizeBytes))
if _, err := w.auth.Seal(eb.Extend(encryptedSize)[:0], b); err != nil {
eb.Release()
return nil, err
}

The plain text's code is:

temp := buf.New()
defer temp.Release()
rawBytes := temp.Extend(payloadSize)
for {
nb, nBytes := buf.SplitBytes(mb, rawBytes)
mb = nb
eb, err := w.seal(rawBytes[:nBytes])

Apparently, eb and temp are pointing to the same buffer. It means buf.New() returns a buffer twice.

So I found issue in QUIC sniffing in this PR:

for len(b) > 0 {
	cache := buf.New()
	defer cache.Release()
}

All but last buffers assigned to cache will not be released if looping more than once. It may overflow the pool and make buf.New() works incorrectly.

@Vigilans
Copy link
Contributor Author

Btw, I found most of the sniffing payloads larger than 2048 falls in 2048~2500 range. Normally, 2500 is 2 QUIC packets (1250 * 2). For 3 QUIC packets it will be 3750 < 4096. So is it more appropriate to allocate 4096 bytes to sniffer payload initially?

@xiaokangwang
Copy link
Contributor

buf.New() returns a buffer twice looks like a double free bug to me. I will merge this and try to see if the issue persists.

@Vigilans
Copy link
Contributor Author

buf.New() returns a buffer twice looks like a double free bug to me.

Indeed, calling defer in for loop multiple times will cause cache.Release() to be called multiple times. But implementation of Release() will set inner data pointer to nil and return if nil next time.

@xiaokangwang
Copy link
Contributor

Yes, maybe the buffer got duplicated? I will merge this now and see if there any improvement.

@xiaokangwang xiaokangwang merged commit 3d54bec into v2fly:master Feb 20, 2025
41 checks passed
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.

2 participants