Skip to content

Commit ee71ab0

Browse files
authored
Support selecting the cgroup (#25)
This change allows the runner to specify the cgroup path. This is a forwards-compatibility feature that allows the new version of omegajail (which is compatible with cgroup v1 and v2) to coexist with this version.
1 parent 3de12d9 commit ee71ab0

4 files changed

Lines changed: 86 additions & 23 deletions

File tree

args.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ ParseArgs(int argc, char* argv[], const std::string_view cwd) throw() {
107107
cxxopts::value<uint64_t>(), "bytes")
108108
("m,memory-limit", "sets the memory limit",
109109
cxxopts::value<int64_t>()->default_value("-1"), "bytes")
110+
("cgroup-path",
111+
"the path under the cgroup hierarchy where the jailed processes should "
112+
"be placed",
113+
cxxopts::value<std::string>()->default_value("/omegajail"), "cgroup path")
110114
("cgroup-memory-limit", "sets the memory limit with cgroups",
111115
cxxopts::value<ssize_t>(), "bytes")
112116
("disable-sandboxing",
@@ -146,6 +150,13 @@ bool Args::Parse(int argc, char* argv[], struct minijail* j) throw() {
146150
return false;
147151
}
148152

153+
cgroup_path = options["cgroup-path"].as<std::string>();
154+
if (!cgroup_path.empty() && cgroup_path.front() == '/') {
155+
// cgroup paths are normally expressed with a leading /, but that's not
156+
// conducive to path joining.
157+
cgroup_path = cgroup_path.substr(1);
158+
}
159+
149160
if (options.count("disable-sandboxing"))
150161
disable_sandboxing = options["disable-sandboxing"].as<bool>();
151162

args.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct Args {
2828
std::string stderr_redirect;
2929
std::string meta;
3030
std::string script_basename;
31+
std::string cgroup_path;
3132
ssize_t memory_limit_in_bytes = -1;
3233
size_t vm_memory_size_in_bytes = 0;
3334
uint64_t wall_time_limit_msec = kMaxWallTimeLimitMsec;

main.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct InitPayload {
5656
ScopedMinijail jail;
5757
std::string comm;
5858
std::string cgroup_path;
59+
std::string pid_cgroup_path;
5960
ssize_t memory_limit_in_bytes;
6061
size_t vm_memory_size_in_bytes;
6162
std::vector<ResourceLimit> rlimits;
@@ -354,8 +355,8 @@ int MetaInit(void* raw_payload) {
354355
return -errno;
355356
}
356357
} else if (payload->memory_limit_in_bytes >= 0) {
357-
memory_cgroup =
358-
std::make_unique<ScopedCgroup>("/sys/fs/cgroup/memory/omegajail");
358+
memory_cgroup = std::make_unique<ScopedCgroup>(
359+
PathJoin("/sys/fs/cgroup/memory", payload->cgroup_path));
359360
if (!*memory_cgroup) {
360361
{
361362
ScopedErrnoPreserver preserve_errno;
@@ -377,8 +378,8 @@ int MetaInit(void* raw_payload) {
377378
}
378379

379380
std::unique_ptr<ScopedCgroup> pid_cgroup;
380-
if (!payload->cgroup_path.empty()) {
381-
pid_cgroup = std::make_unique<ScopedCgroup>(payload->cgroup_path);
381+
if (!payload->pid_cgroup_path.empty()) {
382+
pid_cgroup = std::make_unique<ScopedCgroup>(payload->pid_cgroup_path);
382383
if (!*pid_cgroup) {
383384
{
384385
ScopedErrnoPreserver preserve_errno;
@@ -777,10 +778,12 @@ int main(int argc, char* argv[]) {
777778
"/mnt/stdio/stderr", true);
778779
}
779780

781+
std::string memory_cgroup_path =
782+
PathJoin("/sys/fs/cgroup/memory", args.cgroup_path);
780783
if (args.memory_limit_in_bytes >= 0 &&
781-
minijail_mount(j.get(), "/sys/fs/cgroup/memory/omegajail",
782-
"/sys/fs/cgroup/memory/omegajail", "", MS_BIND)) {
783-
LOG(ERROR) << "Failed to mount /sys/fs/cgroup/memory";
784+
minijail_mount(j.get(), memory_cgroup_path.c_str(),
785+
memory_cgroup_path.c_str(), "", MS_BIND)) {
786+
LOG(ERROR) << "Failed to mount " << memory_cgroup_path;
784787
return 1;
785788
}
786789
} else {
@@ -811,24 +814,25 @@ int main(int argc, char* argv[]) {
811814
MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS);
812815
}
813816

814-
std::string cgroup_path;
817+
std::string pid_cgroup_path;
815818
if (!args.script_basename.empty()) {
816-
cgroup_path = StringPrintf("/sys/fs/cgroup/pids/omegajail/%s",
817-
args.script_basename.c_str());
818-
if (access(cgroup_path.c_str(), W_OK) != 0) {
819-
cgroup_path.clear();
819+
pid_cgroup_path =
820+
PathJoin("/sys/fs/cgroup/pids", args.cgroup_path, args.script_basename);
821+
if (access(pid_cgroup_path.c_str(), W_OK) != 0) {
822+
pid_cgroup_path.clear();
820823
} else if (!args.disable_sandboxing &&
821-
minijail_mount(j.get(), "/sys/fs/cgroup/pids/omegajail",
822-
"/sys/fs/cgroup/pids/omegajail", "", MS_BIND)) {
823-
LOG(ERROR) << "Failed to mount /sys/fs/cgroup/pids";
824+
minijail_mount(j.get(), pid_cgroup_path.c_str(),
825+
pid_cgroup_path.c_str(), "", MS_BIND)) {
826+
LOG(ERROR) << "Failed to mount " << pid_cgroup_path.c_str();
824827
return 1;
825828
}
826829
}
827830

828831
InitPayload payload{
829832
.disable_sandboxing = args.disable_sandboxing,
830833
.comm = args.comm,
831-
.cgroup_path = cgroup_path,
834+
.cgroup_path = args.cgroup_path,
835+
.pid_cgroup_path = pid_cgroup_path,
832836
.memory_limit_in_bytes = args.memory_limit_in_bytes,
833837
.vm_memory_size_in_bytes = args.vm_memory_size_in_bytes,
834838
.rlimits = args.rlimits,

smoketest/test

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ def _check_call(args: List[str]) -> bool:
7373
return False
7474

7575

76-
def _omegajail_compile(root: str, lang: str, strace: bool) -> bool:
76+
def _omegajail_compile(
77+
root: str,
78+
lang: str,
79+
strace: bool,
80+
cgroup_path: str,
81+
) -> bool:
7782
lang_dir = os.path.join(_PWD, 'run', lang)
7883
if os.path.isdir(lang_dir):
7984
shutil.rmtree(lang_dir, True)
@@ -114,15 +119,23 @@ def _omegajail_compile(root: str, lang: str, strace: bool) -> bool:
114119
source,
115120
'--compile-target',
116121
target,
122+
'--cgroup-path',
123+
cgroup_path,
117124
]
118125
if lang == 'cs':
119126
os.symlink('/usr/share/dotnet/Main.runtimeconfig.json',
120127
os.path.join(lang_dir, 'Main.runtimeconfig.json'))
121128
return _check_call(args)
122129

123130

124-
def _omegajail_run(root: str, lang: str, strace: bool, input_file: str,
125-
output_file: str) -> bool:
131+
def _omegajail_run(
132+
root: str,
133+
lang: str,
134+
strace: bool,
135+
input_path: str,
136+
output_path: str,
137+
cgroup_path: str,
138+
) -> bool:
126139
lang_dir = os.path.join(_PWD, 'run', lang)
127140
if strace:
128141
args = [
@@ -137,7 +150,7 @@ def _omegajail_run(root: str, lang: str, strace: bool, input_file: str,
137150
'--homedir',
138151
lang_dir,
139152
'-0',
140-
os.path.join(_PWD, input_file),
153+
os.path.join(_PWD, input_path),
141154
'-1',
142155
os.path.join(lang_dir, 'run.out'),
143156
'-2',
@@ -156,14 +169,16 @@ def _omegajail_run(root: str, lang: str, strace: bool, input_file: str,
156169
root,
157170
'--run',
158171
lang,
172+
'--cgroup-path',
173+
cgroup_path,
159174
'--run-target',
160175
'Main',
161176
]
162177
if not _check_call(args):
163178
return False
164179
with open(os.path.join(lang_dir, 'run.out'), 'r') as run_out:
165180
got = run_out.read().strip()
166-
with open(os.path.join(_PWD, output_file), 'r') as output:
181+
with open(os.path.join(_PWD, output_path), 'r') as output:
167182
expected = output.read().strip()
168183
if got != expected:
169184
logging.error('Wrong answer when running \'%s\'. got %r, expected %r',
@@ -177,8 +192,28 @@ def _main() -> None:
177192
parser.add_argument('--strace', action='store_true')
178193
parser.add_argument('--verbose', action='store_true')
179194
parser.add_argument('--root', default='/var/lib/omegajail', type=str)
195+
parser.add_argument('--cgroup-path',
196+
default='/omegajail',
197+
type=str)
180198
args = parser.parse_args()
181199

200+
# Set this process up for cgroups v2, since it uses slightly different
201+
# rules.
202+
if os.path.isdir(os.path.join('/sys/fs/cgroup', args.cgroup_path[1:])):
203+
smoketest_cgroup = os.path.join('/sys/fs/cgroup', args.cgroup_path[1:],
204+
'smoketest')
205+
if not os.path.isdir(smoketest_cgroup):
206+
with open(
207+
os.path.join('/sys/fs/cgroup', args.cgroup_path[1:],
208+
'cgroup.subtree_control'), 'w') as f:
209+
f.write('+memory')
210+
os.makedirs(smoketest_cgroup, exist_ok=True)
211+
with open(os.path.join(smoketest_cgroup, 'cgroup.subtree_control'),
212+
'w') as f:
213+
f.write('+memory')
214+
with open(os.path.join(smoketest_cgroup, 'cgroup.procs'), 'w') as f:
215+
f.write(str(os.getpid()))
216+
182217
args.root = os.path.abspath(args.root)
183218

184219
languages = _LANGUAGES
@@ -192,15 +227,27 @@ def _main() -> None:
192227

193228
for lang in languages:
194229
print('%-20s' % lang, end='')
195-
if not _omegajail_compile(args.root, lang, args.strace):
230+
if not _omegajail_compile(
231+
root=args.root,
232+
lang=lang,
233+
strace=args.strace,
234+
cgroup_path=args.cgroup_path,
235+
):
196236
print('ERROR (COMPILE)')
197237
passed = False
198238
continue
199239
if lang in _KAREL_LANGUAGES:
200240
input_path, output_path = 'input-karel', 'output-karel'
201241
else:
202242
input_path, output_path = 'input', 'output'
203-
if _omegajail_run(args.root, lang, args.strace, input_path, output_path):
243+
if _omegajail_run(
244+
root=args.root,
245+
lang=lang,
246+
strace=args.strace,
247+
input_path=input_path,
248+
output_path=output_path,
249+
cgroup_path=args.cgroup_path,
250+
):
204251
print('OK')
205252
else:
206253
print('ERROR')

0 commit comments

Comments
 (0)