Skip to content
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

Support specifying block size for filesystem format #1452

Merged
merged 1 commit into from
Jan 5, 2023

Conversation

ConnorJC3
Copy link
Contributor

Is this a bug fix or adding new feature?

New feature

What is this PR about? / Why do we need it?

Adds support to specify the block size during filesystem format. Currently not supported on windows (or for NTFS volumes at all), that can change once the csi-proxy is replaced with privileged Windows containers.

What testing is done?

Manual/New unit tests/CI

@k8s-ci-robot k8s-ci-robot requested review from gtxu and rdpsin November 21, 2022 15:15
@k8s-ci-robot k8s-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Nov 21, 2022
@ConnorJC3
Copy link
Contributor Author

/hold we might want to wait to merge this for a non-RC release of mount-utils, hold for now

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Nov 21, 2022
@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Nov 21, 2022
@ConnorJC3 ConnorJC3 force-pushed the custom-block-sizes branch 2 times, most recently from b4f7aea to 992e69a Compare November 21, 2022 16:04
@rdpsin
Copy link
Contributor

rdpsin commented Nov 21, 2022

Different filesystems have different valid block sizes. E.g., ext4 will only accept 1K, 2K or 4K block sizes. Should the driver check for that?

docs/parameters.md Show resolved Hide resolved
pkg/driver/controller.go Outdated Show resolved Hide resolved
pkg/driver/controller.go Show resolved Hide resolved
pkg/driver/controller.go Outdated Show resolved Hide resolved
pkg/driver/controller.go Show resolved Hide resolved
blockSize, ok := context[BlockSizeKey]
if ok {
// This check is already performed on the controller side
// However, because it is potentially security-sensitive, we redo it here to be safe
Copy link
Contributor

Choose a reason for hiding this comment

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

Why?

Copy link
Contributor Author

@ConnorJC3 ConnorJC3 Nov 21, 2022

Choose a reason for hiding this comment

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

Shortly after this, the block size is directly inserted into formatOptions and passed to mount-utils. An attacker that could theoretically control blockSize here could use that on linux to insert arbitrary mkfs parameters (a potential security threat). On Windows, it's a complete takeover: formatOptions is concatenated into the command.

In theory, this value is checked in the controller, but I'm not 100% confident there's no way to induce a value here without going through the controller (on the contrary, I'm pretty confident it is possible by directly manipulating CSIVolume objects).

Checking that it looks like an integer here is practically free and makes 100% sure no malicious values ever get passed to formatOptions

Copy link
Contributor

Choose a reason for hiding this comment

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

It's not our interface, so I'm not sure how we can validate the input. Is it a number of bytes? Number of pages? Does the underlying command allow a "k" suffix? What about "Ki"? Does it allow negative values? mkfs.ext4 does, mkfs.xfs does not.

Unless you're saying that we should make it our interface, validate the input, and take on the job of converting it to whatever format is appropriate for the underlying file system. I don't think we should do that.

@torredil
Copy link
Member

torredil commented Nov 23, 2022

Different filesystems have different valid block sizes. E.g., ext4 will only accept 1K, 2K or 4K block sizes. Should the driver check for that?

mkfs rounds up to a valid block size.

StorageClass:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  blocksize: "3535"
  csi.storage.k8s.io/fstype: ext4
----------------------------------------

$ kubectl describe pv

Name:              pvc-bd9fc0a3-6481-4811-8ad4-b2022b8241c8
Labels:            <none>
Annotations:       pv.kubernetes.io/provisioned-by: ebs.csi.aws.com
Finalizers:        [kubernetes.io/pv-protection external-attacher/ebs-csi-aws-com]
StorageClass:      ebs-sc
Status:            Bound
Claim:             default/ebs-claim
Reclaim Policy:    Delete
Access Modes:      RWO
VolumeMode:        Filesystem
Capacity:          4Gi
Node Affinity:
  Required Terms:
    Term 0:        topology.ebs.csi.aws.com/zone in [us-east-1d]
Message:
Source:
    Type:              CSI (a Container Storage Interface (CSI) volume source)
    Driver:            ebs.csi.aws.com
    FSType:            ext4
    VolumeHandle:      vol-0d6ec6acb3bbdbdd7
    ReadOnly:          false
    VolumeAttributes:      blocksize=3535
                           storage.kubernetes.io/csiProvisionerIdentity=1669217011030-8081-ebs.csi.aws.com
Events:                <none>
----------------------------------------

$ kubectl logs ebs-csi-node-qtqpt -n kube-system -c ebs-plugin

I1123 19:07:54.622264       1 mount_linux.go:528] Disk "/dev/nvme1n1" appears to be unformatted, attempting to format as type: "ext4" with options: [-b 3535 -F -m0 /dev/nvme1n1]
I1123 19:07:55.111667       1 mount_linux.go:538] Disk successfully formatted (mkfs): ext4 - /dev/nvme1n1 /var/lib/kubelet/plugins/kubernetes.io/csi/ebs.csi.aws.com/20ca089c5b265bd40055b47b3b882793681fd817a59484c5f1bf70f8bd5a6523/globalmount 

$ root@app:/# tune2fs -l /dev/nvme0n1p1 |grep '^Block size:'
Block size:               4096

@andyzhangx
Copy link
Member

/test all

@rdpsin rdpsin mentioned this pull request Dec 19, 2022
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 19, 2022
pkg/driver/controller.go Outdated Show resolved Hide resolved
pkg/driver/controller_test.go Outdated Show resolved Hide resolved
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 19, 2022
@ConnorJC3 ConnorJC3 force-pushed the custom-block-sizes branch 2 times, most recently from c90b9b9 to ece3929 Compare December 19, 2022 20:28
@wmesard
Copy link
Contributor

wmesard commented Dec 20, 2022

Different filesystems have different valid block sizes. E.g., ext4 will only accept 1K, 2K or 4K block sizes. Should the driver check for that?

That seems like a violation of separation of concerns. Do these file systems have a stable interface to query their supported block sizes? Are we going to update the CSI driver when the FS or the underlying hardware adds support for new block sizes? How will we know if software and hardware on the node supports the new block size?

Also, that list only applies to x86. ext4 on ARM supports larger block sizes today.

Let components do its own input validation. As a caller, just make sure you are handling and reporting the errors correctly.

@ConnorJC3 ConnorJC3 force-pushed the custom-block-sizes branch 3 times, most recently from 4ccc119 to ea279fe Compare December 20, 2022 18:39
@ConnorJC3
Copy link
Contributor Author

/remove-hold

I believe I've addressed all the existing feedback, this PR is ready for a fresh round of review and otherwise ready to merge.

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Dec 20, 2022
Comment on lines +151 to +153
// This check is already performed on the controller side
// However, because it is potentially security-sensitive, we redo it here to be safe
_, err := strconv.Atoi(blockSize)
Copy link
Contributor

Choose a reason for hiding this comment

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

But really, neither place should be doing this, because it is not your interface. mkfs.xfs allows suffixes (e.g. "4k"), while this code will reject them. No big deal I guess. The user will figure out what's happening and work around it. But what about some future hypothetical file system that takes "small", "medium", and "large" instead of a number?

Copy link
Contributor Author

@ConnorJC3 ConnorJC3 Dec 21, 2022

Choose a reason for hiding this comment

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

I can try to make the validation smarter, but I'm of the opinion we should just leave it dumb. As explained above, we cannot accept arbitrary values here, because it leads to an RCE (and even when it doesn't, a significant security risk). We'd have to rebuild the validation for every filesystem ourselves, and getting it wrong means exposing our users/customers to security holes.

All existing filesystems I'm aware of accept this value as an integer. It's theoretically possible, but I strongly doubt any future filesystem will change that.

@torredil
Copy link
Member

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Dec 21, 2022
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: torredil, wmesard

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 5, 2023
@k8s-ci-robot k8s-ci-robot merged commit 862fe33 into kubernetes-sigs:master Jan 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants