Skip to content

Commit 0e28021

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 PosixProcRlimitsValueError 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]. The posixProcRef constant is cherry-picked from 27503c5 (complete spec errors of config.md, 2017-09-05, opencontainers#458). [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 Signed-off-by: W. Trevor King <[email protected]>
1 parent 894cae7 commit 0e28021

File tree

3 files changed

+116
-2
lines changed

3 files changed

+116
-2
lines changed

specerror/error.go

+8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ const (
4444
// ReadonlyOnWindows represents the error code of readonly setting test on Windows
4545
ReadonlyOnWindows
4646

47+
// PosixProcRlimitsValueError represents "valid values are defined in the ... man page"
48+
PosixProcRlimitsValueError
49+
4750
// DefaultFilesystems represents the error code of default filesystems test
4851
DefaultFilesystems
4952

@@ -79,6 +82,9 @@ var (
7982
rootRef = func(version string) (reference string, err error) {
8083
return fmt.Sprintf(referenceTemplate, version, "config.md#root"), nil
8184
}
85+
posixProcRef = func(version string) (reference string, err error) {
86+
return fmt.Sprintf(referenceTemplate, version, "config.md#posix-process"), nil
87+
}
8288
defaultFSRef = func(version string) (reference string, err error) {
8389
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#default-filesystems"), nil
8490
}
@@ -106,6 +112,8 @@ var ociErrors = map[Code]errorTemplate{
106112
ReadonlyFilesystem: {Level: rfc2119.Must, Reference: rootRef},
107113
ReadonlyOnWindows: {Level: rfc2119.Must, Reference: rootRef},
108114

115+
PosixProcRlimitsValueError: {Level: rfc2119.Should, Reference: posixProcRef},
116+
109117
// Config-Linux.md
110118
// Default Filesystems
111119
DefaultFilesystems: {Level: rfc2119.Should, Reference: defaultFSRef},

validate/validate.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ func (v *Validator) CheckCapabilities() (errs error) {
423423

424424
// CheckRlimits checks v.spec.Process.Rlimits
425425
func (v *Validator) CheckRlimits() (errs error) {
426+
if v.platform == "windows" {
427+
return
428+
}
429+
426430
process := v.spec.Process
427431
for index, rlimit := range process.Rlimits {
428432
for i := index + 1; i < len(process.Rlimits); i++ {
@@ -878,14 +882,14 @@ func (v *Validator) rlimitValid(rlimit rspec.POSIXRlimit) (errs error) {
878882
return
879883
}
880884
}
881-
errs = multierror.Append(errs, fmt.Errorf("rlimit type %q is invalid", rlimit.Type))
885+
errs = multierror.Append(errs, specerror.NewError(specerror.PosixProcRlimitsValueError, fmt.Errorf("rlimit type %q may not be valid", rlimit.Type), v.spec.Version))
882886
} else if v.platform == "solaris" {
883887
for _, val := range posixRlimits {
884888
if val == rlimit.Type {
885889
return
886890
}
887891
}
888-
errs = multierror.Append(errs, fmt.Errorf("rlimit type %q is invalid", rlimit.Type))
892+
errs = multierror.Append(errs, specerror.NewError(specerror.PosixProcRlimitsValueError, fmt.Errorf("rlimit type %q may not be valid", rlimit.Type), v.spec.Version))
889893
} else {
890894
logrus.Warnf("process.rlimits validation not yet implemented for platform %q", v.platform)
891895
}

validate/validate_test.go

+102
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,105 @@ func TestCheckSemVer(t *testing.T) {
154154
assert.Equal(t, c.expected, specerror.FindError(err, c.expected), "Fail to check SemVer "+c.val)
155155
}
156156
}
157+
158+
func TestCheckProcess(t *testing.T) {
159+
cases := []struct {
160+
val rspec.Spec
161+
platform string
162+
expected specerror.Code
163+
}{
164+
{
165+
val: rspec.Spec{
166+
Version: "1.0.0",
167+
Process: &rspec.Process{
168+
Args: []string{"sh"},
169+
Cwd: "/",
170+
},
171+
},
172+
platform: "linux",
173+
expected: specerror.NonError,
174+
},
175+
{
176+
val: rspec.Spec{
177+
Version: "1.0.0",
178+
Process: &rspec.Process{
179+
Args: []string{"sh"},
180+
Cwd: "/",
181+
Rlimits: []rspec.POSIXRlimit{
182+
{
183+
Type: "RLIMIT_NOFILE",
184+
Hard: 1024,
185+
Soft: 1024,
186+
},
187+
{
188+
Type: "RLIMIT_NPROC",
189+
Hard: 512,
190+
Soft: 512,
191+
},
192+
},
193+
},
194+
},
195+
platform: "linux",
196+
expected: specerror.NonError,
197+
},
198+
{
199+
val: rspec.Spec{
200+
Version: "1.0.0",
201+
Process: &rspec.Process{
202+
Args: []string{"sh"},
203+
Cwd: "/",
204+
Rlimits: []rspec.POSIXRlimit{
205+
{
206+
Type: "RLIMIT_NOFILE",
207+
Hard: 1024,
208+
Soft: 1024,
209+
},
210+
},
211+
},
212+
},
213+
platform: "solaris",
214+
expected: specerror.NonError,
215+
},
216+
{
217+
val: rspec.Spec{
218+
Version: "1.0.0",
219+
Process: &rspec.Process{
220+
Args: []string{"sh"},
221+
Cwd: "/",
222+
Rlimits: []rspec.POSIXRlimit{
223+
{
224+
Type: "RLIMIT_DOES_NOT_EXIST",
225+
Hard: 512,
226+
Soft: 512,
227+
},
228+
},
229+
},
230+
},
231+
platform: "linux",
232+
expected: specerror.PosixProcRlimitsValueError,
233+
},
234+
{
235+
val: rspec.Spec{
236+
Version: "1.0.0",
237+
Process: &rspec.Process{
238+
Args: []string{"sh"},
239+
Cwd: "/",
240+
Rlimits: []rspec.POSIXRlimit{
241+
{
242+
Type: "RLIMIT_NPROC",
243+
Hard: 512,
244+
Soft: 512,
245+
},
246+
},
247+
},
248+
},
249+
platform: "solaris",
250+
expected: specerror.PosixProcRlimitsValueError,
251+
},
252+
}
253+
for _, c := range cases {
254+
v := NewValidator(&c.val, ".", false, c.platform)
255+
err := v.CheckProcess()
256+
assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("failed CheckProcess: %v %d", err, c.expected))
257+
}
258+
}

0 commit comments

Comments
 (0)