From ad8b10a73fd8bd2587bcf967555bce2eaf54426e Mon Sep 17 00:00:00 2001 From: reederc42 Date: Fri, 14 Jun 2024 11:52:05 -0700 Subject: [PATCH] Fixes SAST issues --------- Co-authored-by: joe webster --- frontend/docker/plugin.go | 4 ++ storage_drivers/azure/azure_anf.go | 26 ++++++- storage_drivers/azure/azure_anf_subvolume.go | 27 +++++++- storage_drivers/gcp/gcp_cvs.go | 21 +++++- storage_drivers/gcp/gcp_cvs_test.go | 2 +- storage_drivers/ontap/api/abstraction_rest.go | 6 ++ storage_drivers/ontap/api/ontap_rest.go | 14 ++++ storage_drivers/ontap/ontap_nas_qtree.go | 69 +++++++++++-------- storage_drivers/ontap/ontap_nas_qtree_test.go | 4 +- storage_drivers/ontap/ontap_san_nvme.go | 16 +++-- storage_drivers/ontap/ontap_san_nvme_test.go | 2 +- storage_drivers/solidfire/solidfire_san.go | 18 +++-- 12 files changed, 157 insertions(+), 52 deletions(-) diff --git a/frontend/docker/plugin.go b/frontend/docker/plugin.go index f02daf80d..3dd5c9f81 100644 --- a/frontend/docker/plugin.go +++ b/frontend/docker/plugin.go @@ -7,6 +7,7 @@ import ( "crypto/tls" "encoding/json" "fmt" + "math" "os" "os/exec" "path/filepath" @@ -289,6 +290,9 @@ func (p *Plugin) Create(request *volume.CreateRequest) error { sizeBytes, err := utils.GetVolumeSizeBytes(ctx, request.Options, "0") if err != nil { return fmt.Errorf("error creating volume: %v", err) + } else if sizeBytes > math.MaxInt64 { + Logc(ctx).WithFields(fields).Error("Invalid volume size") + return errors.New("invalid volume size") } delete(request.Options, "size") diff --git a/storage_drivers/azure/azure_anf.go b/storage_drivers/azure/azure_anf.go index a29302f20..dddcea141 100644 --- a/storage_drivers/azure/azure_anf.go +++ b/storage_drivers/azure/azure_anf.go @@ -202,10 +202,15 @@ func (d *NASStorageDriver) Initialize( volumeCreateTimeout := d.defaultCreateTimeout() if config.VolumeCreateTimeout != "" { - if i, parseErr := strconv.ParseUint(d.Config.VolumeCreateTimeout, 10, 64); parseErr != nil { + i, parseErr := strconv.ParseInt(d.Config.VolumeCreateTimeout, 10, 64) + if parseErr != nil { Logc(ctx).WithField("interval", d.Config.VolumeCreateTimeout).WithError(parseErr).Error( "Invalid volume create timeout period.") return parseErr + } else if i < 0 { + Logc(ctx).WithField("interval", d.Config.VolumeCreateTimeout).WithError(parseErr).Error( + "Unsupported volume create timeout period.") + return errors.UnsupportedError("unsupported volume create timeout period") } else { volumeCreateTimeout = time.Duration(i) * time.Second } @@ -545,10 +550,15 @@ func (d *NASStorageDriver) initializeAzureSDKClient( sdkTimeout := api.DefaultSDKTimeout if config.SDKTimeout != "" { - if i, parseErr := strconv.ParseUint(d.Config.SDKTimeout, 10, 64); parseErr != nil { + i, parseErr := strconv.ParseInt(d.Config.SDKTimeout, 10, 64) + if parseErr != nil { Logc(ctx).WithField("interval", d.Config.SDKTimeout).WithError(parseErr).Error( "Invalid value for SDK timeout.") return parseErr + } else if i < 0 { + Logc(ctx).WithField("interval", d.Config.SDKTimeout).WithError(parseErr).Error( + "Unsupported value for SDK timeout.") + return errors.UnsupportedError("unsupported SDK timeout") } else { sdkTimeout = time.Duration(i) * time.Second } @@ -556,10 +566,15 @@ func (d *NASStorageDriver) initializeAzureSDKClient( maxCacheAge := api.DefaultMaxCacheAge if config.MaxCacheAge != "" { - if i, parseErr := strconv.ParseUint(d.Config.MaxCacheAge, 10, 64); parseErr != nil { + i, parseErr := strconv.ParseInt(d.Config.MaxCacheAge, 10, 64) + if parseErr != nil { Logc(ctx).WithField("interval", d.Config.MaxCacheAge).WithError(parseErr).Error( "Invalid value for max cache age.") return parseErr + } else if i < 0 { + Logc(ctx).WithField("interval", d.Config.MaxCacheAge).WithError(parseErr).Error( + "Unsupported value for max cache age.") + return errors.UnsupportedError("unsupported max cache age") } else { maxCacheAge = time.Duration(i) * time.Second } @@ -1988,6 +2003,11 @@ func (d *NASStorageDriver) Resize(ctx context.Context, volConfig *storage.Volume Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> Resize") defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< Resize") + if sizeBytes > math.MaxInt64 { + Logc(ctx).WithFields(fields).Error("Invalid volume size") + return errors.New("invalid volume size") + } + // Update resource cache as needed if err := d.SDK.RefreshAzureResources(ctx); err != nil { return fmt.Errorf("could not update ANF resource cache; %v", err) diff --git a/storage_drivers/azure/azure_anf_subvolume.go b/storage_drivers/azure/azure_anf_subvolume.go index eaef3b936..61035af05 100644 --- a/storage_drivers/azure/azure_anf_subvolume.go +++ b/storage_drivers/azure/azure_anf_subvolume.go @@ -7,6 +7,7 @@ import ( "crypto/sha256" "encoding/json" "fmt" + "math" "os" "reflect" "regexp" @@ -274,10 +275,15 @@ func (d *NASBlockStorageDriver) Initialize( volumeCreateTimeout := d.defaultCreateTimeout() if config.VolumeCreateTimeout != "" { - if i, parseErr := strconv.ParseUint(d.Config.VolumeCreateTimeout, 10, 64); parseErr != nil { + i, parseErr := strconv.ParseInt(d.Config.VolumeCreateTimeout, 10, 64) + if parseErr != nil { Logc(ctx).WithField("interval", d.Config.VolumeCreateTimeout).WithError(parseErr).Error( "Invalid volume create timeout period.") return parseErr + } else if i < 0 { + Logc(ctx).WithField("interval", d.Config.VolumeCreateTimeout).WithError(parseErr).Error( + "Unsupported volume create timeout period.") + return errors.UnsupportedError("unsupported volume create timeout period") } else { volumeCreateTimeout = time.Duration(i) * time.Second } @@ -532,10 +538,15 @@ func (d *NASBlockStorageDriver) initializeAzureSDKClient( sdkTimeout := api.DefaultSDKTimeout if config.SDKTimeout != "" { - if i, parseErr := strconv.ParseUint(d.Config.SDKTimeout, 10, 64); parseErr != nil { + i, parseErr := strconv.ParseInt(d.Config.SDKTimeout, 10, 64) + if parseErr != nil { Logc(ctx).WithField("interval", d.Config.SDKTimeout).WithError(parseErr).Error( "Invalid value for SDK timeout.") return parseErr + } else if i < 0 { + Logc(ctx).WithField("interval", d.Config.SDKTimeout).WithError(parseErr).Error( + "Unsupported value for SDK timeout.") + return errors.UnsupportedError("unsupported SDK timeout") } else { sdkTimeout = time.Duration(i) * time.Second } @@ -543,10 +554,15 @@ func (d *NASBlockStorageDriver) initializeAzureSDKClient( maxCacheAge := api.DefaultMaxCacheAge if config.MaxCacheAge != "" { - if i, parseErr := strconv.ParseUint(d.Config.MaxCacheAge, 10, 64); parseErr != nil { + i, parseErr := strconv.ParseInt(d.Config.MaxCacheAge, 10, 64) + if parseErr != nil { Logc(ctx).WithField("interval", d.Config.MaxCacheAge).WithError(parseErr).Error( "Invalid value for max cache age.") return parseErr + } else if i < 0 { + Logc(ctx).WithField("interval", d.Config.MaxCacheAge).WithError(parseErr).Error( + "Unsupported value for max cache age.") + return errors.UnsupportedError("unsupported max cache age") } else { maxCacheAge = time.Duration(i) * time.Second } @@ -1691,6 +1707,11 @@ func (d *NASBlockStorageDriver) Resize(ctx context.Context, volConfig *storage.V Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> Resize") defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< Resize") + if sizeBytes > math.MaxInt64 { + Logc(ctx).WithFields(fields).Error("Invalid volume size") + return errors.New("invalid volume size") + } + // Get the subvolume subvolumeWithMetadata, err := d.SDK.Subvolume(ctx, volConfig, true) if err != nil { diff --git a/storage_drivers/gcp/gcp_cvs.go b/storage_drivers/gcp/gcp_cvs.go index efebe3327..a37670d69 100644 --- a/storage_drivers/gcp/gcp_cvs.go +++ b/storage_drivers/gcp/gcp_cvs.go @@ -6,6 +6,7 @@ import ( "context" "encoding/json" "fmt" + "math" "net" "reflect" "regexp" @@ -281,11 +282,15 @@ func (d *NFSStorageDriver) populateConfigurationDefaults( // VolumeCreateTimeoutSeconds is the timeout value in seconds. volumeCreateTimeout := d.defaultCreateTimeout() if config.VolumeCreateTimeout != "" { - i, err := strconv.ParseUint(d.Config.VolumeCreateTimeout, 10, 64) + i, err := strconv.ParseInt(d.Config.VolumeCreateTimeout, 10, 64) if err != nil { - Logc(ctx).WithField("interval", d.Config.VolumeCreateTimeout).Errorf( - "Invalid volume create timeout period. %v", err) + Logc(ctx).WithField("interval", d.Config.VolumeCreateTimeout).WithError(err).Error( + "Invalid volume create timeout period.") return err + } else if i < 0 { + Logc(ctx).WithField("interval", d.Config.VolumeCreateTimeout).WithError(err).Error( + "Unsupported volume create timeout period.") + return errors.UnsupportedError("unsupported volume create timeout period") } volumeCreateTimeout = time.Duration(i) * time.Second } @@ -697,6 +702,11 @@ func (d *NFSStorageDriver) Create( sizeBytes = d.applyMinimumVolumeSizeHW(requestedSizeBytes) } + if sizeBytes > math.MaxInt64 { + Logc(ctx).WithFields(fields).Error("Invalid volume size") + return errors.New("invalid volume size") + } + if requestedSizeBytes < sizeBytes { Logc(ctx).WithFields(LogFields{ "name": name, @@ -1739,6 +1749,11 @@ func (d *NFSStorageDriver) Resize(ctx context.Context, volConfig *storage.Volume Logd(ctx, d.Config.StorageDriverName, d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> Resize") defer Logd(ctx, d.Config.StorageDriverName, d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< Resize") + if sizeBytes > math.MaxInt64 { + Logc(ctx).WithFields(fields).Error("Invalid volume size") + return errors.New("invalid volume size") + } + // Get the volume creationToken := name diff --git a/storage_drivers/gcp/gcp_cvs_test.go b/storage_drivers/gcp/gcp_cvs_test.go index b446157bf..e9fef8a43 100644 --- a/storage_drivers/gcp/gcp_cvs_test.go +++ b/storage_drivers/gcp/gcp_cvs_test.go @@ -909,7 +909,7 @@ func TestInitialize_InvalidVolumeCreateTimeout(t *testing.T) { d := newTestGCPDriver(nil) err := d.Initialize(ctx(), tridentconfig.ContextCSI, configJSON, commonConfig, map[string]string{}, "abcd") - assert.ErrorContains(t, err, "strconv.ParseUint", "Valid volume create timeout") + assert.ErrorContains(t, err, "strconv.ParseInt", "Valid volume create timeout") assert.False(t, d.initialized, "Driver initialized") } diff --git a/storage_drivers/ontap/api/abstraction_rest.go b/storage_drivers/ontap/api/abstraction_rest.go index 169104742..f388050ab 100644 --- a/storage_drivers/ontap/api/abstraction_rest.go +++ b/storage_drivers/ontap/api/abstraction_rest.go @@ -7,6 +7,7 @@ import ( "context" "encoding/json" "fmt" + "math" "runtime/debug" "sort" "strconv" @@ -2058,6 +2059,11 @@ func (d OntapAPIREST) LunCreate(ctx context.Context, lun Lun) error { sizeBytesStr, _ := utils.ConvertSizeToBytes(lun.Size) sizeBytes, _ := strconv.ParseUint(sizeBytesStr, 10, 64) + if sizeBytes > math.MaxInt64 { + Logc(ctx).WithField("sizeInBytes", sizeBytes).Error("Invalid volume size") + return errors.New("invalid volume size") + } + creationErr := d.api.LunCreate(ctx, lun.Name, int64(sizeBytes), lun.OsType, lun.Qos, *lun.SpaceReserved, *lun.SpaceAllocated) if creationErr != nil { diff --git a/storage_drivers/ontap/api/ontap_rest.go b/storage_drivers/ontap/api/ontap_rest.go index 0a2032738..15275d799 100644 --- a/storage_drivers/ontap/api/ontap_rest.go +++ b/storage_drivers/ontap/api/ontap_rest.go @@ -10,6 +10,7 @@ import ( "encoding/json" "fmt" "io" + "math" "net/http" "net/url" "os" @@ -642,6 +643,10 @@ func (c RestClient) setVolumeSizeByNameAndStyle(ctx context.Context, volumeName, sizeBytesStr, _ := utils.ConvertSizeToBytes(newSize) sizeBytes, _ := strconv.ParseUint(sizeBytesStr, 10, 64) + if sizeBytes > math.MaxInt64 { + Logc(ctx).WithField("sizeInBytes", sizeBytes).Error("Invalid volume size") + return errors.New("invalid volume size") + } volumeInfo := &models.Volume{ Size: utils.Ptr(int64(sizeBytes)), @@ -2923,6 +2928,11 @@ func (c RestClient) LunSetSize( sizeBytesStr, _ := utils.ConvertSizeToBytes(newSize) sizeBytes, _ := strconv.ParseUint(sizeBytesStr, 10, 64) + if sizeBytes > math.MaxInt64 { + Logc(ctx).WithField("sizeInBytes", sizeBytes).Error("Invalid volume size") + return 0, errors.New("invalid volume size") + } + spaceInfo := &models.LunInlineSpace{ Size: utils.Ptr(int64(sizeBytes)), } @@ -5740,6 +5750,10 @@ func (c RestClient) NVMeNamespaceCreate(ctx context.Context, ns NVMeNamespace) ( sizeBytesStr, _ := utils.ConvertSizeToBytes(ns.Size) sizeInBytes, _ := strconv.ParseUint(sizeBytesStr, 10, 64) + if sizeInBytes > math.MaxInt64 { + Logc(ctx).WithField("sizeInBytes", sizeInBytes).Error("Invalid volume size") + return "", errors.New("invalid volume size") + } nsInfo := &models.NvmeNamespace{ Name: &ns.Name, diff --git a/storage_drivers/ontap/ontap_nas_qtree.go b/storage_drivers/ontap/ontap_nas_qtree.go index af8480d58..0249cd987 100644 --- a/storage_drivers/ontap/ontap_nas_qtree.go +++ b/storage_drivers/ontap/ontap_nas_qtree.go @@ -5,6 +5,7 @@ package ontap import ( "context" "fmt" + "math" "reflect" "regexp" "strconv" @@ -31,16 +32,16 @@ import ( var QtreeInternalIDRegex = regexp.MustCompile(`^/svm/(?P[^/]+)/flexvol/(?P[^/]+)/qtree/(?P[^/]+)$`) const ( - deletedQtreeNamePrefix = "deleted_" - maxQtreeNameLength = 64 - minQtreesPerFlexvol = 50 - defaultQtreesPerFlexvol = 200 - maxQtreesPerFlexvol = 300 - defaultPruneFlexvolsPeriodSecs = uint64(600) // default to 10 minutes - defaultResizeQuotasPeriodSecs = uint64(60) // default to 1 minute - defaultEmptyFlexvolDeferredDeletePeriodSecs = uint64(28800) // default to 8 hours - pruneTask = "prune" - resizeTask = "resize" + deletedQtreeNamePrefix = "deleted_" + maxQtreeNameLength = 64 + minQtreesPerFlexvol = 50 + defaultQtreesPerFlexvol = 200 + maxQtreesPerFlexvol = 300 + defaultPruneFlexvolsPeriod = 10 * time.Minute // default to 10 minutes + defaultResizeQuotasPeriod = 1 * time.Minute // default to 1 minute + defaultEmptyFlexvolDeferredDeletePeriod = 8 * time.Hour // default to 8 hours + pruneTask = "prune" + resizeTask = "resize" ) // NASQtreeStorageDriver is for NFS and SMB storage provisioning of qtrees @@ -1998,35 +1999,41 @@ func (t *HousekeepingTask) run(ctx context.Context, tick time.Time) { func NewPruneTask(ctx context.Context, d *NASQtreeStorageDriver, tasks []func(context.Context)) *HousekeepingTask { // Read background task timings from config file, use defaults if missing or invalid - pruneFlexvolsPeriodSecs := defaultPruneFlexvolsPeriodSecs + pruneFlexvolsPeriod := defaultPruneFlexvolsPeriod if d.Config.QtreePruneFlexvolsPeriod != "" { - i, err := strconv.ParseUint(d.Config.QtreePruneFlexvolsPeriod, 10, 64) + i, err := strconv.ParseInt(d.Config.QtreePruneFlexvolsPeriod, 10, 64) + if i < 0 { + err = fmt.Errorf("negative interval") + } if err != nil { - Logc(ctx).WithField("interval", d.Config.QtreePruneFlexvolsPeriod).Warnf( - "Invalid Flexvol pruning interval. %v", err) + Logc(ctx).WithField("defaultInterval", pruneFlexvolsPeriod).WithError(err).Warnf( + "Invalid Flexvol pruning interval, using default interval.") } else { - pruneFlexvolsPeriodSecs = i + pruneFlexvolsPeriod = time.Duration(i) * time.Second } } - emptyFlexvolDeferredDeletePeriodSecs := defaultEmptyFlexvolDeferredDeletePeriodSecs + emptyFlexvolDeferredDeletePeriod := defaultEmptyFlexvolDeferredDeletePeriod if d.Config.EmptyFlexvolDeferredDeletePeriod != "" { - i, err := strconv.ParseUint(d.Config.EmptyFlexvolDeferredDeletePeriod, 10, 64) + i, err := strconv.ParseInt(d.Config.EmptyFlexvolDeferredDeletePeriod, 10, 64) + if i < 0 { + err = fmt.Errorf("negative interval") + } if err != nil { - Logc(ctx).WithField("interval", d.Config.EmptyFlexvolDeferredDeletePeriod).Warnf( - "Invalid Flexvol deferred delete period. %v", err) + Logc(ctx).WithField("defaultInterval", emptyFlexvolDeferredDeletePeriod).WithError(err).Warnf( + "Invalid Flexvol deferred delete period, using default interval.") } else { - emptyFlexvolDeferredDeletePeriodSecs = i + emptyFlexvolDeferredDeletePeriod = time.Duration(i) * time.Second } } - d.emptyFlexvolDeferredDeletePeriod = time.Duration(emptyFlexvolDeferredDeletePeriodSecs) * time.Second + d.emptyFlexvolDeferredDeletePeriod = emptyFlexvolDeferredDeletePeriod Logc(ctx).WithFields(LogFields{ - "IntervalSeconds": pruneFlexvolsPeriodSecs, - "EmptyFlexvolTTL": emptyFlexvolDeferredDeletePeriodSecs, + "IntervalSeconds": pruneFlexvolsPeriod, + "EmptyFlexvolTTL": emptyFlexvolDeferredDeletePeriod, }).Debug("Configured Flexvol pruning period.") task := &HousekeepingTask{ Name: pruneTask, - Ticker: time.NewTicker(time.Duration(pruneFlexvolsPeriodSecs) * time.Second), + Ticker: time.NewTicker(pruneFlexvolsPeriod), InitialDelay: HousekeepingStartupDelaySecs * time.Second, Done: make(chan struct{}), Tasks: tasks, @@ -2038,23 +2045,23 @@ func NewPruneTask(ctx context.Context, d *NASQtreeStorageDriver, tasks []func(co func NewResizeTask(ctx context.Context, d *NASQtreeStorageDriver, tasks []func(context.Context)) *HousekeepingTask { // Read background task timings from config file, use defaults if missing or invalid - resizeQuotasPeriodSecs := defaultResizeQuotasPeriodSecs + resizeQuotasPeriod := defaultResizeQuotasPeriod if d.Config.QtreeQuotaResizePeriod != "" { - i, err := strconv.ParseUint(d.Config.QtreeQuotaResizePeriod, 10, 64) + i, err := strconv.ParseInt(d.Config.QtreeQuotaResizePeriod, 10, 64) if err != nil { Logc(ctx).WithField("interval", d.Config.QtreeQuotaResizePeriod).Warnf( "Invalid quota resize interval. %v", err) } else { - resizeQuotasPeriodSecs = i + resizeQuotasPeriod = time.Duration(i) * time.Second } } Logc(ctx).WithFields(LogFields{ - "IntervalSeconds": resizeQuotasPeriodSecs, + "IntervalSeconds": resizeQuotasPeriod, }).Debug("Configured quota resize period.") task := &HousekeepingTask{ Name: resizeTask, - Ticker: time.NewTicker(time.Duration(resizeQuotasPeriodSecs) * time.Second), + Ticker: time.NewTicker(resizeQuotasPeriod), InitialDelay: HousekeepingStartupDelaySecs * time.Second, Done: make(chan struct{}), Tasks: tasks, @@ -2080,6 +2087,10 @@ func (d *NASQtreeStorageDriver) Resize(ctx context.Context, volConfig *storage.V return fmt.Errorf("resizing is not supported on a read-only volume") } + if sizeBytes > math.MaxInt64 { + return fmt.Errorf("invalid volume size") + } + // Ensure any Flexvol won't be pruned before resize is completed. utils.Lock(ctx, "resize", d.sharedLockID) defer utils.Unlock(ctx, "resize", d.sharedLockID) diff --git a/storage_drivers/ontap/ontap_nas_qtree_test.go b/storage_drivers/ontap/ontap_nas_qtree_test.go index d806fe583..5c6ae521d 100644 --- a/storage_drivers/ontap/ontap_nas_qtree_test.go +++ b/storage_drivers/ontap/ontap_nas_qtree_test.go @@ -3081,7 +3081,7 @@ func TestNewPruneTask_WithDefaultValues(t *testing.T) { assert.Equal(t, tasks, result.Tasks) assert.Equal(t, driver, result.Driver) - expectedEmptyFlexvolDeferredDeletePeriod := time.Duration(defaultEmptyFlexvolDeferredDeletePeriodSecs) * time.Second + expectedEmptyFlexvolDeferredDeletePeriod := defaultEmptyFlexvolDeferredDeletePeriod assert.Equal(t, expectedEmptyFlexvolDeferredDeletePeriod, driver.emptyFlexvolDeferredDeletePeriod, "emptyFlexvolDeferredDeletePeriod does not match") } @@ -3121,7 +3121,7 @@ func TestNewPruneTask_WithInValidConfigValues(t *testing.T) { assert.Equal(t, tasks, result.Tasks) assert.Equal(t, driver, result.Driver) - expectedFlexvolDeferredDeletePeriod := time.Duration(defaultEmptyFlexvolDeferredDeletePeriodSecs) * time.Second + expectedFlexvolDeferredDeletePeriod := defaultEmptyFlexvolDeferredDeletePeriod assert.Equal(t, expectedFlexvolDeferredDeletePeriod, driver.emptyFlexvolDeferredDeletePeriod, "emptyFlexvolDeferredDeletePeriod does not match") } diff --git a/storage_drivers/ontap/ontap_san_nvme.go b/storage_drivers/ontap/ontap_san_nvme.go index 2daabd7d7..2d5732913 100644 --- a/storage_drivers/ontap/ontap_san_nvme.go +++ b/storage_drivers/ontap/ontap_san_nvme.go @@ -7,6 +7,7 @@ import ( "context" "encoding/json" "fmt" + "math" "reflect" "regexp" "strconv" @@ -1260,6 +1261,11 @@ func (d *NVMeStorageDriver) Resize( defer Logd(ctx, d.Config.StorageDriverName, d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< Resize") + if requestedSizeBytes > math.MaxInt64 { + Logc(ctx).WithFields(fields).Error("Invalid volume size") + return fmt.Errorf("invalid volume size") + } + volExists, err := d.API.VolumeExists(ctx, name) if err != nil { Logc(ctx).WithFields(LogFields{ @@ -1287,12 +1293,14 @@ func (d *NVMeStorageDriver) Resize( return fmt.Errorf("error while checking namespace size, %v", err) } - nsSizeBytes, err := strconv.ParseUint(ns.Size, 10, 64) + nsSizeBytes, err := strconv.ParseInt(ns.Size, 10, 64) if err != nil { return fmt.Errorf("error while parsing namespace size, %v", err) + } else if nsSizeBytes < 0 { + return errors.UnsupportedCapacityRangeError(errors.New("unsupported namespace size")) } - if requestedSizeBytes < nsSizeBytes { + if int64(requestedSizeBytes) < nsSizeBytes { return fmt.Errorf("requested size %d is less than existing volume size %d", requestedSizeBytes, nsSizeBytes) } @@ -1304,7 +1312,7 @@ func (d *NVMeStorageDriver) Resize( newFlexVolSize := drivers.CalculateVolumeSizeBytes(ctx, name, requestedSizeBytes, snapshotReserveInt) newFlexVolSize = uint64(LUNMetadataBufferMultiplier * float64(newFlexVolSize)) - sameNamespaceSize := utils.VolumeSizeWithinTolerance(int64(requestedSizeBytes), int64(nsSizeBytes), + sameNamespaceSize := utils.VolumeSizeWithinTolerance(int64(requestedSizeBytes), nsSizeBytes, tridentconfig.SANResizeDelta) sameFlexVolSize := utils.VolumeSizeWithinTolerance(int64(newFlexVolSize), int64(currentFlexVolSize), @@ -1318,7 +1326,7 @@ func (d *NVMeStorageDriver) Resize( "delta": tridentconfig.SANResizeDelta, }).Info("Requested size and current namespace size are within the delta and therefore considered" + " the same size for SAN resize operations.") - volConfig.Size = strconv.FormatUint(nsSizeBytes, 10) + volConfig.Size = strconv.FormatInt(nsSizeBytes, 10) return nil } diff --git a/storage_drivers/ontap/ontap_san_nvme_test.go b/storage_drivers/ontap/ontap_san_nvme_test.go index eaf42ee7c..f495a744e 100644 --- a/storage_drivers/ontap/ontap_san_nvme_test.go +++ b/storage_drivers/ontap/ontap_san_nvme_test.go @@ -1545,7 +1545,7 @@ func TestNVMeResize_ParseNamespaceSizeError(t *testing.T) { err := d.Resize(ctx, volConfig, 100) - assert.ErrorContains(t, err, "error while parsing namespace size") + assert.ErrorContains(t, err, "unsupported namespace size") } func TestNVMeResize_LessRequestedSizeError(t *testing.T) { diff --git a/storage_drivers/solidfire/solidfire_san.go b/storage_drivers/solidfire/solidfire_san.go index 3ef2540e9..7a04e77f0 100644 --- a/storage_drivers/solidfire/solidfire_san.go +++ b/storage_drivers/solidfire/solidfire_san.go @@ -6,6 +6,7 @@ import ( "context" "encoding/json" "fmt" + "math" "net/url" "reflect" "regexp" @@ -813,20 +814,20 @@ func (d *SANStorageDriver) Create( if err != nil { return fmt.Errorf("could not convert volume size %s: %v", volConfig.Size, err) } - sizeBytes, err := strconv.ParseUint(requestedSize, 10, 64) + sizeBytes, err := strconv.ParseInt(requestedSize, 10, 64) if err != nil { return fmt.Errorf("%v is an invalid volume size: %v", volConfig.Size, err) } if sizeBytes == 0 { defaultSize, _ := utils.ConvertSizeToBytes(pool.InternalAttributes()[Size]) - sizeBytes, _ = strconv.ParseUint(defaultSize, 10, 64) + sizeBytes, _ = strconv.ParseInt(defaultSize, 10, 64) } - if checkMinVolumeSizeError := drivers.CheckMinVolumeSize(sizeBytes, + if checkMinVolumeSizeError := drivers.CheckMinVolumeSize(uint64(sizeBytes), MinimumVolumeSizeBytes); checkMinVolumeSizeError != nil { return checkMinVolumeSizeError } if _, _, checkVolumeSizeLimitsError := drivers.CheckVolumeSizeLimits( - ctx, sizeBytes, d.Config.CommonStorageDriverConfig, + ctx, uint64(sizeBytes), d.Config.CommonStorageDriverConfig, ); checkVolumeSizeLimitsError != nil { return checkVolumeSizeLimitsError } @@ -899,12 +900,12 @@ func (d *SANStorageDriver) Create( } // Update config to reflect values used to create volume - volConfig.Size = strconv.FormatUint(sizeBytes, 10) + volConfig.Size = strconv.FormatInt(sizeBytes, 10) volConfig.FileSystem = fstype volConfig.QosType = opts["type"] req.Qos = qos - req.TotalSize = int64(sizeBytes) + req.TotalSize = sizeBytes req.AccountID = d.AccountID req.Name = MakeSolidFireName(name) req.Attributes = meta @@ -1943,6 +1944,11 @@ func (d *SANStorageDriver) Resize(ctx context.Context, volConfig *storage.Volume Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> Resize") defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< Resize") + if sizeBytes > math.MaxInt64 { + Logc(ctx).WithFields(fields).Error("Invalid volume size") + return errors.New("invalid volume size") + } + volume, err := d.GetVolume(ctx, name) if err != nil { Logc(ctx).WithFields(LogFields{