-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should verify that the max value is not too big #35
base: master
Are you sure you want to change the base?
Conversation
@vrothberg FYI |
ulimit.go
Outdated
var rlimit syscall.Rlimit | ||
if err := syscall.Getrlimit(limitType, &rlimit); err == nil { | ||
if *hard > int64(rlimit.Max) { | ||
return nil, fmt.Errorf("ulimit hard limit must be less than or equal to hard limit for the current process, hard: %d", *hard) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For debugging purposes, it could be helpful to print rlimit.Max
as well.
return nil, fmt.Errorf("ulimit hard limit (%d) must be less than or equal to hard limit for the current process (%d)", *hard, rlimit.Max)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🐯
There's been some discussion around validation in the "go" code versus delegating to the kernel itself; does Linux return an error in this case, or is it silently ignored? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think this will also cause problems in situations where this function is used on a different host than where the process itself lives (e.g. the docker CLI uses this function to parse values, but that would now make the wrong assumption)
For your use-case, would it be possible to perform this validation after parsing the value?
Sure, the reason I wanted to do this hear was to avoid duplicating the data. Perhaps if we add a different function. |
@thaJeztah Revamped this work, (Going through some old PR's) Now just added a verify function that will check against kernel. The problem is these values are just handed to different OCIs, and they can give you some useless information back to the user. This should make it easier to diagnose the error, with a better error message. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for updating! I noticed that the current version would still cause some issues (also still a bit on the fence if the check should be in this code, or only the parsing, but I'm ok with adding)
ulimit.go
Outdated
@@ -108,6 +109,17 @@ func ParseUlimit(val string) (*Ulimit, error) { | |||
return &Ulimit{Name: parts[0], Soft: soft, Hard: *hard}, nil | |||
} | |||
|
|||
// Verify that ulimit values work with current kernel | |||
func (u *Ulimit) Verify() error { | |||
var rlimit syscall.Rlimit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't compile on Windows (which would break the docker cli). Assuming we only need this on Linux/Unix-y systems (I guess just linux would do for now), could you move this to a _linux.go
file (with the right build-tags), and create a stub implementation for other platforms? It could take the same approach as we did for the go-selinux package, and keep the exported function here, and a platform-specific, non-exported function in other files.
ulimit_test.go
Outdated
@@ -21,6 +21,16 @@ func TestParseUlimitValid(t *testing.T) { | |||
} | |||
} | |||
|
|||
func TestParseUlimitTooBig(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one should then also be in a ulimit_linux_test.go
file
ulimit.go
Outdated
@@ -4,6 +4,7 @@ import ( | |||
"fmt" | |||
"strconv" | |||
"strings" | |||
"syscall" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably be golang.org/x/sys
, given that "syscall" is frozen/deprecated in favour of that package
579aaaf
to
850fcf1
Compare
@thaJeztah Decided to not wait 4 months again to update... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for updating! code changes look good to me, but unfortunately looks like the test may need some changes 😓 (see my comment inline)
ulimit_linux_test.go
Outdated
) | ||
|
||
func TestParseUlimitTooBig(t *testing.T) { | ||
u, err := ParseUlimit("nofile=512:1000024") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed CI isn't running on this repo (have to check why), but testing this locally in a container, the test failed.
--- FAIL: TestParseUlimitTooBig (0.00s)
ulimit_linux_test.go:15: expected invalid hard limit
I added a debug line to Verify()
(see below), which explains why it failed, because on this machine the limit is higher than what the test expects;
ulimit hard limit (1000024) is less than 1048576
Perhaps this test needs to dynamically set the value to make sure it's higher than the max. That's a bit ugly, so other suggestions welcome 😅)
diff --git a/ulimit_linux.go b/ulimit_linux.go
index a56f361..36a4b28 100644
--- a/ulimit_linux.go
+++ b/ulimit_linux.go
@@ -13,6 +13,7 @@ func (u *Ulimit) Verify() error {
if u.Hard > int64(rlimit.Max) {
return fmt.Errorf("ulimit hard limit (%d) must be less than or equal to hard limit for the current process %d",
u.Hard, rlimit.Max)
}
+ fmt.Printf("ulimit hard limit (%d) is less than %d\n", u.Hard, rlimit.Max)
}
return nil
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thaJeztah seems this issue was addressed -- the test case now gets the max value from the kernel.
When parsing the ulimit, we should check if the ulimit max value is greater then the processes max value. If yes then we should return an error. Signed-off-by: Daniel J Walsh <[email protected]>
Ah, forgot about this one. I'm still a bit on the fence if querying what the kernel supports, and validating against that is within scope of this module and/or if it should be more of a concern of the code using this module (so far the module was used to only parse values, and to validate a correct format, but no other assumptions) 🤔. What are your thoughts on that, @kolyshkin ? |
Two year old PR, that I totally forgot about. :^( |
I'm on the verge about it. True, this package is only about parsing, it does not talk to the kernel in any way etc. OTOH this package knows about ulimit, which is a UNIX concept, and adding Overall I think this should go in, with the only change that |
Another thing is, this raises the bar to how this should be tested -- at least we now need to compile this for various GOOS/GOARCH combinations. |
Yes it's a bit of a tough one; I can definitely see the convenience of having the |
When parsing the ulimit, we should check if the ulimit max value is greater then
the processes max value. If yes then we should return an error.
Signed-off-by: Daniel J Walsh [email protected]