Skip to content

add option to resolve symlinks in WithLinuxDevice#7523

Merged
kzys merged 1 commit intocontainerd:mainfrom
ginglis13:symlink-device
Nov 15, 2022
Merged

add option to resolve symlinks in WithLinuxDevice#7523
kzys merged 1 commit intocontainerd:mainfrom
ginglis13:symlink-device

Conversation

@ginglis13
Copy link
Copy Markdown
Contributor

@ginglis13 ginglis13 commented Oct 13, 2022

This change adds withLinuxDevice to take an option followSymlinks. An option
WithLinuxDeviceFollowSymlinks will call this unexported option to
follow a symlink, which will resolve a symlink before calling
DeviceFromPath. WithLinuxDevice has been changed to call
withLinuxDevice without following symlinks.

Previously DeviceFromPath used Lstat to get information about a device file, but Lstat will not follow symlinks; stat will. The use case could be using a tool like udev which will create symlinks to devices and wishing to attach one of these devices to a container.

It looks like DeviceFromPath is coming from runc, which does use Lstat instead of Stat but I didn't find any discussions as to why not resolve symlinks: opencontainers/runc/libcontainer/devices/device_unix.go

Docker is resolving symlinks themselves before calling this function:
moby/moby/oci/devices_linux.go

which they did after some previous discussions in these issues/PRs:

Fixes #7006

Signed-off-by: Gavin Inglis [email protected]

@k8s-ci-robot
Copy link
Copy Markdown

Hi @ginglis13. Thanks for your PR.

I'm waiting for a containerd member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Comment thread oci/utils_unix_test.go Outdated
Comment thread oci/utils_unix_test.go Outdated
@kzys
Copy link
Copy Markdown
Member

kzys commented Oct 13, 2022

/ok-to-test

@ginglis13 ginglis13 force-pushed the symlink-device branch 2 times, most recently from 04056f6 to 748ac11 Compare October 13, 2022 21:20
@ginglis13
Copy link
Copy Markdown
Contributor Author

/cc @cpuguy83 @thaJeztah

saw you folks had some work on related issues in containerd and docker, PTAL

@thaJeztah
Copy link
Copy Markdown
Member

As this is a change in behavior, and other project may be using the existing functions, I wonder if (for the containerd library code), it should be opt-in to follow symlinks (also see moby/moby#20684 (comment), which suggested at the time to have a user-facing option as well); this could be a separate (WithDevicesXXX) function, and an option added to getDevices() (even more because that non-exported function is shared between multiple exported functions. (thinking of, e.g., if that function would ever be used on untrusted paths, e.g. a path in the container's filesystem, that could lead to a malicious image controlling what device would be mounted).

Whatever decision we get to, at least this behavior should be included in the function documentation so that consumers of those functions are aware of it.

Happy to hear other's thoughts on that though.

@ginglis13
Copy link
Copy Markdown
Contributor Author

As this is a change in behavior, and other project may be using the existing functions, I wonder if (for the containerd library code), it should be opt-in to follow symlinks

... and an option added to getDevices() (even more because that non-exported function is shared between multiple exported functions. (thinking of, e.g., if that function would ever be used on untrusted paths, e.g. a path in the container's filesystem, that could lead to a malicious image controlling what device would be mounted).

Whatever decision we get to, at least this behavior should be included in the function documentation so that consumers of those functions are aware of it.

@thaJeztah Yea I agree that following device symlinks should be optional, I anticipated some security concerns, hence why I opened a PR for some feedback :) I'll rework this PR to provide an option WithDevicesSymlinked or similar so that following symlinks is opt-in

@ginglis13 ginglis13 changed the title resolve symlinks to devices in DeviceFromPath add option to resolve symlinks in WithLinuxDevice Oct 20, 2022
Comment thread oci/spec_opts.go Outdated
Comment thread oci/spec_opts_test.go Outdated
Comment thread oci/spec_opts.go Outdated
Comment thread oci/spec_opts.go Outdated
Comment thread oci/spec_opts.go Outdated
Comment thread oci/spec_opts_linux_test.go Outdated
Comment thread oci/spec_opts_linux_test.go Outdated
if tc.expectError {
assert.Error(t, err)
} else {
require.NoError(t, err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why require here and not assert?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thought here was if we expect an error, then assert and log that error. However, if we do not expect an error and encounter one, then fail fast with require. But I see that's mostly just assuming the happy path. Changed to have both assert for consistency.

Comment thread oci/spec_opts_linux_test.go Outdated
}
if len(tc.expectedLinuxDevices) != 0 {
require.NotNil(t, spec.Linux)
require.NotNil(t, spec.Linux.Devices)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want require.Len here instead.

@ginglis13 ginglis13 force-pushed the symlink-device branch 2 times, most recently from 7f6472e to 09d7507 Compare October 26, 2022 18:19
@ginglis13 ginglis13 requested review from samuelkarp and thaJeztah and removed request for cpuguy83, samuelkarp and thaJeztah November 3, 2022 17:46
@ginglis13 ginglis13 requested a review from samuelkarp November 3, 2022 17:47
This change modifies WithLinuxDevice to take an option `followSymlink`
and be unexported as `withLinuxDevice`. An option
`WithLinuxDeviceFollowSymlinks` will call this unexported option to
follow a symlink, which will resolve a symlink before calling
`DeviceFromPath`. `WithLinuxDevice` has been changed to call
`withLinuxDevice` without following symlinks.

Signed-off-by: Gavin Inglis <[email protected]>
Copy link
Copy Markdown
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kzys
Copy link
Copy Markdown
Member

kzys commented Nov 3, 2022

The tests are all green finally!

@samuelkarp Can you take a look again?

@kzys kzys merged commit 1e200b1 into containerd:main Nov 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resolve symlinks before lstat on a device file

6 participants