Skip to content

Commit 391df45

Browse files
committed
linux: reject sysctl kernel.domainname when OCI knob domainname is set
Setting sysctl `kernel.domainname` directly by user is not environment agnostic, it shows either incorrect ( on non-working ) behaviour in `rootless` environment. It was decided to make this part of `runtime-spec` so the OCI runtime can itself handle this behaviour correctly. As a result a new field `domainname` was added to `runtime-spec`. Since crun already implementes this field therefore `sysctl` configured by user conflicts with the behaviour expected by the OCI runtime. Runtime-spec PR: opencontainers/runtime-spec#1156 Furthermore a similar `sysctl` `kernal.hostname` is blocked by crun explicitly to prevent this conflicting behaviour. https://github.com/containers/crun/blob/main/src/libcrun/linux.c#L3203 Following commit ensures that crun rejects sysctl `kernel.domainname` when OCI field `domainname` is already set. Signed-off-by: Aditya R <[email protected]>
1 parent a73a1d4 commit 391df45

File tree

2 files changed

+57
-6
lines changed

2 files changed

+57
-6
lines changed

src/libcrun/linux.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3161,7 +3161,7 @@ const char *sysctlRequiringIPC[] = {
31613161
};
31623162

31633163
static int
3164-
validate_sysctl (const char *original_value, const char *name, unsigned long namespaces_created, libcrun_error_t *err)
3164+
validate_sysctl (const char *original_key, const char *original_value, const char *name, unsigned long namespaces_created, runtime_spec_schema_config_schema *def, libcrun_error_t *err)
31653165
{
31663166
const char *namespace = "";
31673167

@@ -3192,6 +3192,13 @@ validate_sysctl (const char *original_value, const char *name, unsigned long nam
31923192

31933193
if (strcmp (name, "kernel/domainname") == 0)
31943194
{
3195+
// Value of sysctl `kernel/domainname` is going to
3196+
// conflict with already set field `domainname` in
3197+
// OCI spec, in such scenario crun will fail to prevent
3198+
// unexpected behaviour for end user.
3199+
if (! is_empty_string (def->domainname) && (strcmp (original_value, def->domainname) != 0))
3200+
return crun_make_error (err, 0, "the sysctl `%s` conflicts with OCI field `domainname`", original_key);
3201+
31953202
if (namespaces_created & CLONE_NEWUTS)
31963203
return 0;
31973204

@@ -3200,7 +3207,7 @@ validate_sysctl (const char *original_value, const char *name, unsigned long nam
32003207
}
32013208

32023209
if (strcmp (name, "kernel/hostname") == 0)
3203-
return crun_make_error (err, 0, "the sysctl `%s` conflicts with OCI field `hostname`", original_value);
3210+
return crun_make_error (err, 0, "the sysctl `%s` conflicts with OCI field `hostname`", original_key);
32043211
}
32053212
if (has_prefix (name, "net/"))
32063213
{
@@ -3211,10 +3218,10 @@ validate_sysctl (const char *original_value, const char *name, unsigned long nam
32113218
goto fail;
32123219
}
32133220

3214-
return crun_make_error (err, 0, "the sysctl `%s` is not namespaced", original_value);
3221+
return crun_make_error (err, 0, "the sysctl `%s` is not namespaced", original_key);
32153222

32163223
fail:
3217-
return crun_make_error (err, 0, "the sysctl `%s` requires a new %s namespace", original_value, namespace);
3224+
return crun_make_error (err, 0, "the sysctl `%s` requires a new %s namespace", original_key, namespace);
32183225
}
32193226

32203227
int
@@ -3256,7 +3263,7 @@ libcrun_set_sysctl (libcrun_container_t *container, libcrun_error_t *err)
32563263
if (*it == '.')
32573264
*it = '/';
32583265

3259-
ret = validate_sysctl (def->linux->sysctl->keys[i], name, namespaces_created, err);
3266+
ret = validate_sysctl (def->linux->sysctl->keys[i], def->linux->sysctl->values[i], name, namespaces_created, def, err);
32603267
if (UNLIKELY (ret < 0))
32613268
return ret;
32623269

tests/test_domainname.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,53 @@ def test_domainname():
4343
if cid is not None:
4444
run_crun_command(["delete", "-f", cid])
4545

46-
46+
def test_domainname_conflict_sysctl():
47+
# Setting sysctl `kernel.domainname` and OCI field `domainname` must fail
48+
# since it produces unexpected behaviour for the end-users.
49+
conf = base_config()
50+
conf['process']['args'] = ['/init', 'getdomainname']
51+
conf['domainname'] = "foomachine"
52+
add_all_namespaces(conf)
53+
conf['linux']['sysctl'] = {'kernel.domainname' : 'foo'}
54+
cid = None
55+
try:
56+
out, cid = run_and_get_output(conf)
57+
if out == "(none)\n":
58+
return 0
59+
sys.stderr.write("unexpected success\n")
60+
return -1
61+
except:
62+
return 0
63+
finally:
64+
if cid is not None:
65+
run_crun_command(["delete", "-f", cid])
66+
return 0
67+
68+
def test_domainname_with_sysctl():
69+
# Setting sysctl `kernel.domainname` and OCI field `domainname` must pass
70+
# when both have exact same value
71+
conf = base_config()
72+
conf['process']['args'] = ['/init', 'getdomainname']
73+
conf['domainname'] = "foo"
74+
add_all_namespaces(conf)
75+
conf['linux']['sysctl'] = {'kernel.domainname' : 'foo'}
76+
cid = None
77+
try:
78+
out, cid = run_and_get_output(conf)
79+
if out == "(none)\n":
80+
return 0
81+
return 0
82+
except:
83+
return -1
84+
finally:
85+
if cid is not None:
86+
run_crun_command(["delete", "-f", cid])
87+
return 0
88+
4789
all_tests = {
4890
"domainname" : test_domainname,
91+
"domainname conflict with syctl" : test_domainname_conflict_sysctl,
92+
"domainname with syctl" : test_domainname_with_sysctl,
4993
}
5094

5195
if __name__ == "__main__":

0 commit comments

Comments
 (0)