summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2020-05-06 10:28:50 -0700
committergVisor bot <gvisor-bot@google.com>2020-05-06 10:30:18 -0700
commit591ff0e424e3b30eb143bce06618cb8656784b90 (patch)
tree46b63f822864e51c6ecbbe909f986e19fc0033df /pkg
parent8416da33d25bf28cfcfdcbe658f696d6883eebcd (diff)
Add maximum memory limit.
PiperOrigin-RevId: 310179277
Diffstat (limited to 'pkg')
-rw-r--r--pkg/sentry/fs/proc/meminfo.go10
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_files.go10
-rw-r--r--pkg/sentry/syscalls/linux/sys_sysinfo.go7
-rw-r--r--pkg/sentry/usage/memory.go24
4 files changed, 36 insertions, 15 deletions
diff --git a/pkg/sentry/fs/proc/meminfo.go b/pkg/sentry/fs/proc/meminfo.go
index 465b47da9..91617267d 100644
--- a/pkg/sentry/fs/proc/meminfo.go
+++ b/pkg/sentry/fs/proc/meminfo.go
@@ -58,12 +58,16 @@ func (d *meminfoData) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle)
var buf bytes.Buffer
fmt.Fprintf(&buf, "MemTotal: %8d kB\n", totalSize/1024)
- memFree := (totalSize - totalUsage) / 1024
+ memFree := totalSize - totalUsage
+ if memFree > totalSize {
+ // Underflow.
+ memFree = 0
+ }
// We use MemFree as MemAvailable because we don't swap.
// TODO(rahat): When reclaim is implemented the value of MemAvailable
// should change.
- fmt.Fprintf(&buf, "MemFree: %8d kB\n", memFree)
- fmt.Fprintf(&buf, "MemAvailable: %8d kB\n", memFree)
+ fmt.Fprintf(&buf, "MemFree: %8d kB\n", memFree/1024)
+ fmt.Fprintf(&buf, "MemAvailable: %8d kB\n", memFree/1024)
fmt.Fprintf(&buf, "Buffers: 0 kB\n") // memory usage by block devices
fmt.Fprintf(&buf, "Cached: %8d kB\n", (file+snapshot.Tmpfs)/1024)
// Emulate a system with no swap, which disables inactivation of anon pages.
diff --git a/pkg/sentry/fsimpl/proc/tasks_files.go b/pkg/sentry/fsimpl/proc/tasks_files.go
index 92007df81..e5f13b69e 100644
--- a/pkg/sentry/fsimpl/proc/tasks_files.go
+++ b/pkg/sentry/fsimpl/proc/tasks_files.go
@@ -272,12 +272,16 @@ func (*meminfoData) Generate(ctx context.Context, buf *bytes.Buffer) error {
inactiveFile := file - activeFile
fmt.Fprintf(buf, "MemTotal: %8d kB\n", totalSize/1024)
- memFree := (totalSize - totalUsage) / 1024
+ memFree := totalSize - totalUsage
+ if memFree > totalSize {
+ // Underflow.
+ memFree = 0
+ }
// We use MemFree as MemAvailable because we don't swap.
// TODO(rahat): When reclaim is implemented the value of MemAvailable
// should change.
- fmt.Fprintf(buf, "MemFree: %8d kB\n", memFree)
- fmt.Fprintf(buf, "MemAvailable: %8d kB\n", memFree)
+ fmt.Fprintf(buf, "MemFree: %8d kB\n", memFree/1024)
+ fmt.Fprintf(buf, "MemAvailable: %8d kB\n", memFree/1024)
fmt.Fprintf(buf, "Buffers: 0 kB\n") // memory usage by block devices
fmt.Fprintf(buf, "Cached: %8d kB\n", (file+snapshot.Tmpfs)/1024)
// Emulate a system with no swap, which disables inactivation of anon pages.
diff --git a/pkg/sentry/syscalls/linux/sys_sysinfo.go b/pkg/sentry/syscalls/linux/sys_sysinfo.go
index a65b560c8..297de052a 100644
--- a/pkg/sentry/syscalls/linux/sys_sysinfo.go
+++ b/pkg/sentry/syscalls/linux/sys_sysinfo.go
@@ -29,13 +29,18 @@ func Sysinfo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
mf.UpdateUsage()
_, totalUsage := usage.MemoryAccounting.Copy()
totalSize := usage.TotalMemory(mf.TotalSize(), totalUsage)
+ memFree := totalSize - totalUsage
+ if memFree > totalSize {
+ // Underflow.
+ memFree = 0
+ }
// Only a subset of the fields in sysinfo_t make sense to return.
si := linux.Sysinfo{
Procs: uint16(len(t.PIDNamespace().Tasks())),
Uptime: t.Kernel().MonotonicClock().Now().Seconds(),
TotalRAM: totalSize,
- FreeRAM: totalSize - totalUsage,
+ FreeRAM: memFree,
Unit: 1,
}
_, err := t.CopyOut(addr, si)
diff --git a/pkg/sentry/usage/memory.go b/pkg/sentry/usage/memory.go
index 4320ad17f..ab1d140d2 100644
--- a/pkg/sentry/usage/memory.go
+++ b/pkg/sentry/usage/memory.go
@@ -252,18 +252,23 @@ func (m *MemoryLocked) Copy() (MemoryStats, uint64) {
return ms, m.totalLocked()
}
-// MinimumTotalMemoryBytes is the minimum reported total system memory.
-//
-// This can be configured through options provided to the Sentry at start.
-// This number is purely synthetic. This is only set before the application
-// starts executing, and must not be modified.
-var MinimumTotalMemoryBytes uint64 = 2 << 30 // 2 GB
+// These options control how much total memory the is reported to the application.
+// They may only be set before the application starts executing, and must not
+// be modified.
+var (
+ // MinimumTotalMemoryBytes is the minimum reported total system memory.
+ MinimumTotalMemoryBytes uint64 = 2 << 30 // 2 GB
+
+ // MaximumTotalMemoryBytes is the maximum reported total system memory.
+ // The 0 value indicates no maximum.
+ MaximumTotalMemoryBytes uint64
+)
// TotalMemory returns the "total usable memory" available.
//
// This number doesn't really have a true value so it's based on the following
-// inputs and further bounded to be above some minimum guaranteed value (2GB),
-// additionally ensuring that total memory reported is always less than used.
+// inputs and further bounded to be above the MinumumTotalMemoryBytes and below
+// MaximumTotalMemoryBytes.
//
// memSize should be the platform.Memory size reported by platform.Memory.TotalSize()
// used is the total memory reported by MemoryLocked.Total()
@@ -279,5 +284,8 @@ func TotalMemory(memSize, used uint64) uint64 {
memSize = uint64(1) << (uint(msb) + 1)
}
}
+ if MaximumTotalMemoryBytes > 0 && memSize > MaximumTotalMemoryBytes {
+ memSize = MaximumTotalMemoryBytes
+ }
return memSize
}