Skip to content

Commit 7553161

Browse files
committed
validate: Soften unrecognized rlimit types to SHOULD violations
The spec isn't particuarly clear on this, saying [1]: * Linux: valid values are defined in the [`getrlimit(2)`][getrlimit.2] man page, such as `RLIMIT_MSGQUEUE`. * Solaris: valid values are defined in the [`getrlimit(3)`][getrlimit.3] man page, such as `RLIMIT_CORE`. and [2]: For each entry in `rlimits`, a [`getrlimit(3)`][getrlimit.3] on `type` MUST succeed. It doesn't say: Linux: The value MUST be listed in the getrlimit(2) man page... and it doesn't require the runtime to support the values listed in the man page [3,4]. So there are three sets: * Values listed in the man page * Values supported by the host kernel * Values supported by the runtime And as the spec stands, these sets are only weakly coupled, and any of them could be a sub- or superset of any other. In practice, I expect the sets to all coincide, with the kernel occasionally adding or removing values, and the man page and runtimes trailing along behind. To address that, this commit weakens the previous hard error to a SHOULD-level error. The PosixProcRlimitsTypeValueError constant is new to this commit, because the spec contains neither a MUST nor a SHOULD for this condition, although I expect a SHOULD-level suggestion was implied by [1]. Also make CheckRlimits a no-op on Windows, because the spec does not define process.rlimits for that OS [5]. [1]: https://github.com/opencontainers/runtime-spec/blame/v1.0.0/config.md#L168-L169 [2]: https://github.com/opencontainers/runtime-spec/blame/v1.0.0/config.md#L168-L169 [3]: opencontainers/runtime-spec#813 [4]: https://github.com/opencontainers/runtime-spec/blame/v1.0.0/config.md#L463 [5]: https://github.com/opencontainers/runtime-spec/blob/v1.0.0/config.md#posix-process Signed-off-by: W. Trevor King <[email protected]>
1 parent 6554add commit 7553161

File tree

3 files changed

+111
-2
lines changed

3 files changed

+111
-2
lines changed

specerror/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ const (
4646
PosixProcRlimitsTypeGeneError = "The runtime MUST [generate an error](runtime.md#errors) for any values which cannot be mapped to a relevant kernel interface."
4747
// PosixProcRlimitsTypeGet represents "For each entry in `rlimits`, a [`getrlimit(3)`][getrlimit.3] on `type` MUST succeed."
4848
PosixProcRlimitsTypeGet = "For each entry in `rlimits`, a [`getrlimit(3)`][getrlimit.3] on `type` MUST succeed."
49+
// PosixProcRlimitsTypeValueError represents "valid values are defined in the ... man page"
50+
PosixProcRlimitsTypeValueError = "valid values are defined in the ... man page"
4951
// PosixProcRlimitsSoftMatchCur represents "`rlim.rlim_cur` MUST match the configured value."
5052
PosixProcRlimitsSoftMatchCur = "`rlim.rlim_cur` MUST match the configured value."
5153
// PosixProcRlimitsHardMatchMax represents "`rlim.rlim_max` MUST match the configured value."
@@ -159,6 +161,7 @@ func init() {
159161
register(ProcArgsOneEntryRequired, rfc2119.Required, processRef)
160162
register(PosixProcRlimitsTypeGeneError, rfc2119.Must, posixProcessRef)
161163
register(PosixProcRlimitsTypeGet, rfc2119.Must, posixProcessRef)
164+
register(PosixProcRlimitsTypeValueError, rfc2119.Should, posixProcessRef)
162165
register(PosixProcRlimitsSoftMatchCur, rfc2119.Must, posixProcessRef)
163166
register(PosixProcRlimitsHardMatchMax, rfc2119.Must, posixProcessRef)
164167
register(PosixProcRlimitsErrorOnDup, rfc2119.Must, posixProcessRef)

validate/validate.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@ func (v *Validator) CheckCapabilities() (errs error) {
424424

425425
// CheckRlimits checks v.spec.Process.Rlimits
426426
func (v *Validator) CheckRlimits() (errs error) {
427+
if v.platform == "windows" {
428+
return
429+
}
430+
427431
process := v.spec.Process
428432
for index, rlimit := range process.Rlimits {
429433
for i := index + 1; i < len(process.Rlimits); i++ {
@@ -870,14 +874,14 @@ func (v *Validator) rlimitValid(rlimit rspec.POSIXRlimit) (errs error) {
870874
return
871875
}
872876
}
873-
errs = multierror.Append(errs, fmt.Errorf("rlimit type %q is invalid", rlimit.Type))
877+
errs = multierror.Append(errs, specerror.NewError(specerror.PosixProcRlimitsTypeValueError, fmt.Errorf("rlimit type %q may not be valid", rlimit.Type), v.spec.Version))
874878
} else if v.platform == "solaris" {
875879
for _, val := range posixRlimits {
876880
if val == rlimit.Type {
877881
return
878882
}
879883
}
880-
errs = multierror.Append(errs, fmt.Errorf("rlimit type %q is invalid", rlimit.Type))
884+
errs = multierror.Append(errs, specerror.NewError(specerror.PosixProcRlimitsTypeValueError, fmt.Errorf("rlimit type %q may not be valid", rlimit.Type), v.spec.Version))
881885
} else {
882886
logrus.Warnf("process.rlimits validation not yet implemented for platform %q", v.platform)
883887
}

validate/validate_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,105 @@ func TestCheckSemVer(t *testing.T) {
188188
assert.Equal(t, c.expected, specerror.FindError(err, c.expected), "Fail to check SemVer "+c.val)
189189
}
190190
}
191+
192+
func TestCheckProcess(t *testing.T) {
193+
cases := []struct {
194+
val rspec.Spec
195+
platform string
196+
expected specerror.Code
197+
}{
198+
{
199+
val: rspec.Spec{
200+
Version: "1.0.0",
201+
Process: &rspec.Process{
202+
Args: []string{"sh"},
203+
Cwd: "/",
204+
},
205+
},
206+
platform: "linux",
207+
expected: specerror.NonError,
208+
},
209+
{
210+
val: rspec.Spec{
211+
Version: "1.0.0",
212+
Process: &rspec.Process{
213+
Args: []string{"sh"},
214+
Cwd: "/",
215+
Rlimits: []rspec.POSIXRlimit{
216+
{
217+
Type: "RLIMIT_NOFILE",
218+
Hard: 1024,
219+
Soft: 1024,
220+
},
221+
{
222+
Type: "RLIMIT_NPROC",
223+
Hard: 512,
224+
Soft: 512,
225+
},
226+
},
227+
},
228+
},
229+
platform: "linux",
230+
expected: specerror.NonError,
231+
},
232+
{
233+
val: rspec.Spec{
234+
Version: "1.0.0",
235+
Process: &rspec.Process{
236+
Args: []string{"sh"},
237+
Cwd: "/",
238+
Rlimits: []rspec.POSIXRlimit{
239+
{
240+
Type: "RLIMIT_NOFILE",
241+
Hard: 1024,
242+
Soft: 1024,
243+
},
244+
},
245+
},
246+
},
247+
platform: "solaris",
248+
expected: specerror.NonError,
249+
},
250+
{
251+
val: rspec.Spec{
252+
Version: "1.0.0",
253+
Process: &rspec.Process{
254+
Args: []string{"sh"},
255+
Cwd: "/",
256+
Rlimits: []rspec.POSIXRlimit{
257+
{
258+
Type: "RLIMIT_DOES_NOT_EXIST",
259+
Hard: 512,
260+
Soft: 512,
261+
},
262+
},
263+
},
264+
},
265+
platform: "linux",
266+
expected: specerror.PosixProcRlimitsTypeValueError,
267+
},
268+
{
269+
val: rspec.Spec{
270+
Version: "1.0.0",
271+
Process: &rspec.Process{
272+
Args: []string{"sh"},
273+
Cwd: "/",
274+
Rlimits: []rspec.POSIXRlimit{
275+
{
276+
Type: "RLIMIT_NPROC",
277+
Hard: 512,
278+
Soft: 512,
279+
},
280+
},
281+
},
282+
},
283+
platform: "solaris",
284+
expected: specerror.PosixProcRlimitsTypeValueError,
285+
},
286+
}
287+
for _, c := range cases {
288+
v := NewValidator(&c.val, ".", false, c.platform)
289+
err := v.CheckProcess()
290+
assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("failed CheckProcess: %v %d", err, c.expected))
291+
}
292+
}

0 commit comments

Comments
 (0)