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

Limit the amount of RAM that will be used #74

Merged
merged 2 commits into from
Jan 11, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions actions/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ const (
configPermissions = 0644
// Config file should be created for writing and not already exist
createFlags = os.O_CREATE | os.O_WRONLY | os.O_EXCL
// 128 MiB is a large enough amount of memory to make the password hash
// very difficult to brute force on specialized hardware, but small
// enough to work on most GNU/Linux systems.
maxMemoryBytes = 128 * 1024 * 1024
)

var (
Expand Down Expand Up @@ -163,15 +167,15 @@ func getHashingCosts(target time.Duration) (*metadata.HashingCosts, error) {
}

// Now we start doubling the costs until we reach the target.
maxMemory := ramLimit()
memoryKiBLimit := memoryBytesLimit() / 1024
for {
// Store a copy of the previous costs
costsPrev := *costs
tPrev := t

// Double the memory up to the max, then the double the time.
if costs.Memory < maxMemory {
costs.Memory = util.MinInt64(2*costs.Memory, maxMemory)
if costs.Memory < memoryKiBLimit {
costs.Memory = util.MinInt64(2*costs.Memory, memoryKiBLimit)
} else {
costs.Time *= 2
}
Expand All @@ -196,15 +200,17 @@ func getHashingCosts(target time.Duration) (*metadata.HashingCosts, error) {
}
}

// ramLimit returns the maximum amount of RAM (in kB) we will use for passphrase
// hashing. Right now it is simply half of the total RAM on the system.
func ramLimit() int64 {
// memoryBytesLimit returns the maximum amount of memory we will use for
// passphrase hashing. This will never be more than a reasonable maximum (for
// compatibility) or half the available system RAM.
func memoryBytesLimit() int64 {
// The sysinfo syscall only fails if given a bad address
var info unix.Sysinfo_t
err := unix.Sysinfo(&info)
// The sysinfo syscall only fails if given a bad address
util.NeverError(err)
// Use half the RAM and convert to kiB.
return int64(info.Totalram / 1024 / 2)

totalRAMBytes := int64(info.Totalram)
return util.MinInt64(totalRAMBytes/2, maxMemoryBytes)
}

// betweenCosts returns a cost between a and b. Specifically, it returns the
Expand Down