Skip to content

Commit

Permalink
Fix: check sum header fields for validity
Browse files Browse the repository at this point in the history
The rsync vulnerability CVE-2024-12084 also affected gokrazy/rsync
(before this commit): An attacker could send an invalid sum header
and thereby trigger a panic (but no heap buffer overflow!) like:

    panic: runtime error: slice bounds out of range [:512] with length 16
    goroutine 277 [running]:
    github.com/gokrazy/rsync/rsyncd.(*sendTransfer).receiveSums(0xc0000d7b68)
        /home/michael/go/src/github.com/gokrazy/rsync/rsyncd/sender.go:136 +0x339

After this commit, the code no longer panics but sends an error:

    gokr-rsync [sender]: invalid checksum length 512
  • Loading branch information
stapelberg committed Jan 24, 2025
1 parent 1b1fbf6 commit 178216f
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package rsync

import "github.com/gokrazy/rsync/internal/rsyncwire"
import (
"fmt"

"github.com/gokrazy/rsync/internal/rsyncwire"
)

// rsync/rsync.h:struct sum_buf
type SumBuf struct {
Expand Down Expand Up @@ -32,26 +36,43 @@ type SumHead struct {
}

func (sh *SumHead) ReadFrom(c *rsyncwire.Conn) error {
// TODO(protocol>=30): update maxBlockLen
const maxBlockLen = 1 << 29 // see rsync.h:OLD_MAX_BLOCK_SIZE

var err error
sh.ChecksumCount, err = c.ReadInt32()
if err != nil {
return err
}
if sh.ChecksumCount < 0 {
return fmt.Errorf("invalid checksum count %d", sh.ChecksumCount)
}

sh.BlockLength, err = c.ReadInt32()
if err != nil {
return err
}
if sh.BlockLength < 0 || sh.BlockLength > maxBlockLen {
return fmt.Errorf("invalid block length %d", sh.BlockLength)
}

sh.ChecksumLength, err = c.ReadInt32()
if err != nil {
return err
}
// TODO(protocol>=27): update max sh.ChecksumLength check
if sh.ChecksumLength < 0 || sh.ChecksumLength > 16 {
return fmt.Errorf("invalid checksum length %d", sh.ChecksumLength)
}

sh.RemainderLength, err = c.ReadInt32()
if err != nil {
return err
}
if sh.RemainderLength < 0 || sh.RemainderLength > sh.BlockLength {
return fmt.Errorf("invalid remainder length %d", sh.RemainderLength)
}

return nil
}

Expand Down

0 comments on commit 178216f

Please sign in to comment.