Skip to content

Commit 3867617

Browse files
authored
Merge pull request #43 from mikimasn/master
Added mremap tracing and fixed a bug in MemoryLimitListener
2 parents 4e9f89b + 65c5a25 commit 3867617

File tree

2 files changed

+54
-22
lines changed

2 files changed

+54
-22
lines changed

src/limits/MemoryLimitListener.cc

+53-22
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@
88
#include "seccomp/action/ActionTrace.h"
99
#include "seccomp/filter/LibSeccompFilter.h"
1010

11+
#include <sys/mman.h>
1112
#include <sys/resource.h>
1213
#include <sys/time.h>
1314

15+
#ifndef MREMAP_DONTUNMAP
16+
// Due to this flag being introduced in Linux 5.7 there are many system which do
17+
// not define it
18+
#define MREMAP_DONTUNMAP 4
19+
#endif
20+
1421
#include <csignal>
1522
#include <cstdint>
1623
#include <fstream>
@@ -40,33 +47,57 @@ MemoryLimitListener::MemoryLimitListener(uint64_t memoryLimitKb)
4047
if (!vmPeakValid_) {
4148
return tracer::TraceAction::CONTINUE;
4249
}
43-
44-
uint64_t memoryUsage = getMemoryUsageKb() +
45-
tracee.getSyscallArgument(1) / 1024;
46-
memoryPeakKb_ = std::max(memoryPeakKb_, memoryUsage);
47-
outputBuilder_->setMemoryPeak(memoryPeakKb_);
48-
logger::debug(
49-
"Memory usage after mmap ",
50-
VAR(memoryUsage),
51-
", ",
52-
VAR(memoryPeakKb_));
53-
54-
if (memoryUsage > memoryLimitKb_) {
55-
outputBuilder_->setKillReason(
56-
printer::OutputBuilder::KillReason::MLE,
57-
"memory limit exceeded");
58-
logger::debug(
59-
"Limit ",
60-
VAR(memoryLimitKb_),
61-
" exceeded, killing tracee");
62-
return tracer::TraceAction::KILL;
63-
}
64-
return tracer::TraceAction::CONTINUE;
50+
return handleMemoryAllocation(
51+
tracee.getSyscallArgument(1) / 1024);
6552
}),
6653
Arg(0) == 0 && Arg(1) > MEMORY_LIMIT_MARGIN / 2));
6754
}
55+
syscallRules_.emplace_back(seccomp::SeccompRule(
56+
"mremap",
57+
seccomp::action::ActionTrace([this](tracer::Tracee& tracee) {
58+
TRACE();
59+
uint64_t old_size = tracee.getSyscallArgument(1);
60+
uint64_t new_size = tracee.getSyscallArgument(2);
61+
uint64_t flags = tracee.getSyscallArgument(3);
62+
if (!vmPeakValid_) {
63+
return tracer::TraceAction::CONTINUE;
64+
}
65+
bool doesntUnmap =
66+
(flags & MREMAP_DONTUNMAP) == MREMAP_DONTUNMAP;
67+
// Allow user to shrink its memory
68+
if (!doesntUnmap && old_size >= new_size) {
69+
return tracer::TraceAction::CONTINUE;
70+
}
71+
uint64_t newMemoryAllocated = new_size;
72+
// Do not count already allocated memory
73+
if (!doesntUnmap)
74+
newMemoryAllocated -= old_size;
75+
newMemoryAllocated /= 1024;
76+
return handleMemoryAllocation(newMemoryAllocated);
77+
}),
78+
Arg(2) > MEMORY_LIMIT_MARGIN / 2));
6879
}
80+
tracer::TraceAction MemoryLimitListener::handleMemoryAllocation(
81+
uint64_t allocatedMemoryKb) {
82+
uint64_t memoryUsage = getMemoryUsageKb() + allocatedMemoryKb;
83+
memoryPeakKb_ = std::max(memoryPeakKb_, memoryUsage);
84+
outputBuilder_->setMemoryPeak(memoryPeakKb_);
85+
logger::debug(
86+
"Memory usage after allocation ",
87+
VAR(memoryUsage),
88+
", ",
89+
VAR(memoryPeakKb_));
6990

91+
if (memoryLimitKb_ > 0 && memoryUsage > memoryLimitKb_) {
92+
outputBuilder_->setKillReason(
93+
printer::OutputBuilder::KillReason::MLE,
94+
"memory limit exceeded");
95+
logger::debug(
96+
"Limit ", VAR(memoryLimitKb_), " exceeded, killing tracee");
97+
return tracer::TraceAction::KILL;
98+
}
99+
return tracer::TraceAction::CONTINUE;
100+
}
70101
void MemoryLimitListener::onPostForkChild() {
71102
TRACE();
72103

src/limits/MemoryLimitListener.h

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class MemoryLimitListener
4040
pid_t childPid_;
4141

4242
std::vector<seccomp::SeccompRule> syscallRules_;
43+
tracer::TraceAction handleMemoryAllocation(uint64_t allocatedMemoryKb);
4344
};
4445

4546
} // namespace limits

0 commit comments

Comments
 (0)