Skip to content

Commit 60e1f61

Browse files
authored
Merge pull request kubernetes#133511 from BenTheElder/no-md5
eliminate md5 usage, block new usage
2 parents 97702bb + a99a5c4 commit 60e1f61

File tree

12 files changed

+95
-35
lines changed

12 files changed

+95
-35
lines changed

cmd/kubeadm/app/util/staticpod/utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ package staticpod
1818

1919
import (
2020
"bytes"
21-
"crypto/md5"
2221
"fmt"
2322
"hash"
23+
"hash/fnv"
2424
"io"
2525
"math"
2626
"net/url"
@@ -373,7 +373,7 @@ func ManifestFilesAreEqual(path1, path2 string) (bool, string, error) {
373373
return false, "", err
374374
}
375375

376-
hasher := md5.New()
376+
hasher := fnv.New128a()
377377
DeepHashObject(hasher, pod1)
378378
hash1 := hasher.Sum(nil)[0:]
379379
DeepHashObject(hasher, pod2)

hack/golangci-hints.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,9 @@ linters:
385385
forbidigo:
386386
analyze-types: true
387387
forbid:
388+
- pattern: md5\.*
389+
# https://github.com/kubernetes/kubernetes/issues/129652
390+
msg: md5 is oudated, insecure, prefer a secure hash (such as sha256) or a non-cryptographic hash
388391
- pattern: ^managedfields\.ExtractInto$
389392
pkg: ^k8s\.io/apimachinery/pkg/util/managedfields$
390393
msg: should not be used because managedFields was removed

hack/golangci.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ linters:
394394
forbidigo:
395395
analyze-types: true
396396
forbid:
397+
- pattern: md5\.*
398+
# https://github.com/kubernetes/kubernetes/issues/129652
399+
msg: md5 is oudated, insecure, prefer a secure hash (such as sha256) or a non-cryptographic hash
397400
- pattern: ^managedfields\.ExtractInto$
398401
pkg: ^k8s\.io/apimachinery/pkg/util/managedfields$
399402
msg: should not be used because managedFields was removed

hack/golangci.yaml.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ linters:
214214
forbidigo:
215215
analyze-types: true
216216
forbid:
217+
- pattern: md5\.*
218+
# https://github.com/kubernetes/kubernetes/issues/129652
219+
msg: md5 is oudated, insecure, prefer a secure hash (such as sha256) or a non-cryptographic hash
217220
- pattern: ^managedfields\.ExtractInto$
218221
pkg: ^k8s\.io/apimachinery/pkg/util/managedfields$
219222
msg: should not be used because managedFields was removed

pkg/api/v1/endpoints/util.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ package endpoints
1818

1919
import (
2020
"bytes"
21-
"crypto/md5"
2221
"encoding/hex"
2322
"hash"
23+
"hash/fnv"
2424
"sort"
2525

26-
"k8s.io/api/core/v1"
26+
v1 "k8s.io/api/core/v1"
2727
"k8s.io/apimachinery/pkg/types"
2828
hashutil "k8s.io/kubernetes/pkg/util/hash"
2929
)
@@ -154,7 +154,7 @@ func hashAddresses(addrs addressSet) string {
154154
slice = append(slice, addrReady{k, ready})
155155
}
156156
sort.Sort(addrsReady(slice))
157-
hasher := md5.New()
157+
hasher := fnv.New128a()
158158
hashutil.DeepHashObject(hasher, slice)
159159
return hex.EncodeToString(hasher.Sum(nil)[0:])
160160
}
@@ -210,7 +210,7 @@ type subsetsByHash []v1.EndpointSubset
210210
func (sl subsetsByHash) Len() int { return len(sl) }
211211
func (sl subsetsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
212212
func (sl subsetsByHash) Less(i, j int) bool {
213-
hasher := md5.New()
213+
hasher := fnv.New128a()
214214
h1 := hashObject(hasher, sl[i])
215215
h2 := hashObject(hasher, sl[j])
216216
return bytes.Compare(h1, h2) < 0
@@ -229,7 +229,7 @@ type portsByHash []v1.EndpointPort
229229
func (sl portsByHash) Len() int { return len(sl) }
230230
func (sl portsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
231231
func (sl portsByHash) Less(i, j int) bool {
232-
hasher := md5.New()
232+
hasher := fnv.New128a()
233233
h1 := hashObject(hasher, sl[i])
234234
h2 := hashObject(hasher, sl[j])
235235
return bytes.Compare(h1, h2) < 0

pkg/controller/endpoint/endpoints_controller.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,10 @@ func (e *Controller) syncService(ctx context.Context, key string) error {
452452
// When comparing the subsets, we ignore the difference in ResourceVersion of Pod to avoid unnecessary Endpoints
453453
// updates caused by Pod updates that we don't care, e.g. annotation update.
454454
if !createEndpoints &&
455-
endpointSubsetsEqualIgnoreResourceVersion(currentEndpoints.Subsets, subsets) &&
455+
(endpointSubsetsEqualIgnoreResourceVersion(currentEndpoints.Subsets, subsets) ||
456+
// If the comparison fails, try again after repacking, it may be a difference in the hash algorithm
457+
// For more context: https://github.com/kubernetes/kubernetes/issues/129652#issuecomment-3264035333
458+
endpointSubsetsEqualIgnoreResourceVersion(endpoints.RepackSubsets(currentEndpoints.Subsets), subsets)) &&
456459
labelsCorrectForEndpoints(currentEndpoints.Labels, service.Labels) &&
457460
capacityAnnotationSetCorrectly(currentEndpoints.Annotations, currentEndpoints.Subsets) {
458461
logger.V(5).Info("endpoints are equal, skipping update", "service", klog.KObj(service))

pkg/controller/endpoint/endpoints_controller_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,63 @@ func TestSyncEndpointsItemsPreexistingIdentical(t *testing.T) {
10081008
endpointsHandler.ValidateRequestCount(t, 0)
10091009
}
10101010

1011+
func TestSyncEndpointsItemsPreexistingIdenticalUnsorted(t *testing.T) {
1012+
ns := metav1.NamespaceDefault
1013+
testServer, endpointsHandler := makeTestServer(t, ns)
1014+
defer testServer.Close()
1015+
tCtx := ktesting.Init(t)
1016+
endpoints := newController(tCtx, testServer.URL, 0*time.Second)
1017+
pod0 := testPod(ns, 0, 1, true, ipv4only)
1018+
pod1 := testPod(ns, 1, 1, true, ipv4only)
1019+
1020+
subsets := []v1.EndpointSubset{{
1021+
Addresses: []v1.EndpointAddress{
1022+
// known to not be packed correctly according to the current hash
1023+
{IP: pod1.Status.PodIPs[0].IP, NodeName: &emptyNodeName, TargetRef: &v1.ObjectReference{Kind: "Pod", Name: pod1.Name, Namespace: ns}},
1024+
{IP: pod0.Status.PodIPs[0].IP, NodeName: &emptyNodeName, TargetRef: &v1.ObjectReference{Kind: "Pod", Name: pod0.Name, Namespace: ns}},
1025+
},
1026+
Ports: []v1.EndpointPort{{Port: 8080, Protocol: "TCP"}},
1027+
}}
1028+
1029+
// Assert that endpoints are not repacked correctly according to the current hash.
1030+
// We want to prove that this does not cause a re-sync.
1031+
repacked := endptspkg.RepackSubsets(subsets)
1032+
if reflect.DeepEqual(subsets, repacked) {
1033+
t.Errorf("subsets were already in sorted order")
1034+
}
1035+
1036+
endpoints.endpointsStore.Add(&v1.Endpoints{
1037+
ObjectMeta: metav1.ObjectMeta{
1038+
ResourceVersion: "1",
1039+
Name: "foo",
1040+
Namespace: ns,
1041+
Labels: map[string]string{
1042+
LabelManagedBy: ControllerName,
1043+
},
1044+
},
1045+
Subsets: subsets,
1046+
})
1047+
1048+
endpoints.podStore.Add(pod0)
1049+
endpoints.podStore.Add(pod1)
1050+
1051+
endpoints.serviceStore.Add(&v1.Service{
1052+
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: metav1.NamespaceDefault},
1053+
Spec: v1.ServiceSpec{
1054+
Selector: map[string]string{"foo": "bar"},
1055+
Ports: []v1.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}},
1056+
IPFamilies: []v1.IPFamily{v1.IPv4Protocol},
1057+
},
1058+
})
1059+
err := endpoints.syncService(tCtx, ns+"/foo")
1060+
if err != nil {
1061+
t.Errorf("Unexpected error syncing service %v", err)
1062+
}
1063+
1064+
// syncing should've been a no-op
1065+
endpointsHandler.ValidateRequestCount(t, 0)
1066+
}
1067+
10111068
func TestSyncEndpointsItems(t *testing.T) {
10121069
ns := "other"
10131070
testServer, endpointsHandler := makeTestServer(t, ns)

pkg/kubelet/config/common.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ limitations under the License.
1717
package config
1818

1919
import (
20-
"crypto/md5"
2120
"encoding/hex"
2221
"errors"
2322
"fmt"
23+
"hash/fnv"
2424
"strings"
2525

2626
v1 "k8s.io/api/core/v1"
@@ -59,7 +59,7 @@ func generatePodName(name string, nodeName types.NodeName) string {
5959

6060
func applyDefaults(logger klog.Logger, pod *api.Pod, source string, isFile bool, nodeName types.NodeName) error {
6161
if len(pod.UID) == 0 {
62-
hasher := md5.New()
62+
hasher := fnv.New128a()
6363
hash.DeepHashObject(hasher, pod)
6464
// DeepHashObject resets the hash, so we should write the pod source
6565
// information AFTER it.

pkg/kubelet/volumemanager/reconciler/reconciler_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ package reconciler
1818

1919
import (
2020
"context"
21-
"crypto/md5"
2221
"fmt"
22+
"hash/fnv"
2323
"path/filepath"
2424
"sync"
2525
"testing"
@@ -1523,13 +1523,14 @@ func Test_UncertainDeviceGlobalMounts(t *testing.T) {
15231523

15241524
modes := []v1.PersistentVolumeMode{v1.PersistentVolumeBlock, v1.PersistentVolumeFilesystem}
15251525

1526+
hasher := fnv.New128a()
15261527
for modeIndex := range modes {
15271528
for tcIndex := range tests {
15281529
mode := modes[modeIndex]
15291530
tc := tests[tcIndex]
15301531
testName := fmt.Sprintf("%s [%s]", tc.name, mode)
15311532
uniqueTestString := fmt.Sprintf("global-mount-%s", testName)
1532-
uniquePodDir := fmt.Sprintf("%s-%x", kubeletPodsDir, md5.Sum([]byte(uniqueTestString)))
1533+
uniquePodDir := fmt.Sprintf("%s-%x", kubeletPodsDir, hasher.Sum([]byte(uniqueTestString)))
15331534
t.Run(testName+"[", func(t *testing.T) {
15341535
t.Parallel()
15351536
pv := &v1.PersistentVolume{
@@ -1736,13 +1737,14 @@ func Test_UncertainVolumeMountState(t *testing.T) {
17361737
}
17371738
modes := []v1.PersistentVolumeMode{v1.PersistentVolumeBlock, v1.PersistentVolumeFilesystem}
17381739

1740+
hasher := fnv.New128a()
17391741
for modeIndex := range modes {
17401742
for tcIndex := range tests {
17411743
mode := modes[modeIndex]
17421744
tc := tests[tcIndex]
17431745
testName := fmt.Sprintf("%s [%s]", tc.name, mode)
17441746
uniqueTestString := fmt.Sprintf("local-mount-%s", testName)
1745-
uniquePodDir := fmt.Sprintf("%s-%x", kubeletPodsDir, md5.Sum([]byte(uniqueTestString)))
1747+
uniquePodDir := fmt.Sprintf("%s-%x", kubeletPodsDir, hasher.Sum([]byte(uniqueTestString)))
17461748
t.Run(testName, func(t *testing.T) {
17471749
t.Parallel()
17481750
pv := &v1.PersistentVolume{

staging/src/k8s.io/endpointslice/util/controller_utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ limitations under the License.
1717
package util
1818

1919
import (
20-
"crypto/md5"
2120
"encoding/hex"
2221
"fmt"
2322
"hash"
23+
"hash/fnv"
2424
"reflect"
2525
"sort"
2626

@@ -165,7 +165,7 @@ func NewPortMapKey(endpointPorts []discovery.EndpointPort) PortMapKey {
165165

166166
// deepHashObjectToString creates a unique hash string from a go object.
167167
func deepHashObjectToString(objectToWrite interface{}) string {
168-
hasher := md5.New()
168+
hasher := fnv.New128a()
169169
deepHashObject(hasher, objectToWrite)
170170
return hex.EncodeToString(hasher.Sum(nil)[0:])
171171
}

0 commit comments

Comments
 (0)