1
16
17 package fuzzer
18
19 import (
20 "reflect"
21 "strconv"
22 "time"
23
24 fuzz "github.com/google/gofuzz"
25
26 v1 "k8s.io/api/core/v1"
27 "k8s.io/apimachinery/pkg/api/resource"
28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29 "k8s.io/apimachinery/pkg/runtime"
30 "k8s.io/apimachinery/pkg/runtime/schema"
31 runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
32 "k8s.io/apimachinery/pkg/util/intstr"
33 "k8s.io/kubernetes/pkg/apis/core"
34 utilpointer "k8s.io/utils/pointer"
35 )
36
37
38 var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
39 return []interface{}{
40 func(q *resource.Quantity, c fuzz.Continue) {
41 *q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
42 },
43 func(j *core.ObjectReference, c fuzz.Continue) {
44
45
46 j.APIVersion = c.RandString()
47 j.Kind = c.RandString()
48 j.Namespace = c.RandString()
49 j.Name = c.RandString()
50 j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
51 j.FieldPath = c.RandString()
52 },
53 func(j *core.PodExecOptions, c fuzz.Continue) {
54 j.Stdout = true
55 j.Stderr = true
56 },
57 func(j *core.PodAttachOptions, c fuzz.Continue) {
58 j.Stdout = true
59 j.Stderr = true
60 },
61 func(j *core.PodPortForwardOptions, c fuzz.Continue) {
62 if c.RandBool() {
63 j.Ports = make([]int32, c.Intn(10))
64 for i := range j.Ports {
65 j.Ports[i] = c.Int31n(65535)
66 }
67 }
68 },
69 func(s *core.PodSpec, c fuzz.Continue) {
70 c.FuzzNoCustom(s)
71
72 ttl := int64(30)
73 if c.RandBool() {
74 ttl = int64(c.Uint32())
75 }
76 s.TerminationGracePeriodSeconds = &ttl
77
78 c.Fuzz(s.SecurityContext)
79
80 if s.SecurityContext == nil {
81 s.SecurityContext = new(core.PodSecurityContext)
82 }
83 if s.Affinity == nil {
84 s.Affinity = new(core.Affinity)
85 }
86 if s.SchedulerName == "" {
87 s.SchedulerName = v1.DefaultSchedulerName
88 }
89 if s.EnableServiceLinks == nil {
90 enableServiceLinks := v1.DefaultEnableServiceLinks
91 s.EnableServiceLinks = &enableServiceLinks
92 }
93 },
94 func(s *core.PodStatus, c fuzz.Continue) {
95 c.Fuzz(&s)
96 s.HostIPs = []core.HostIP{{IP: s.HostIP}}
97 },
98 func(j *core.PodPhase, c fuzz.Continue) {
99 statuses := []core.PodPhase{core.PodPending, core.PodRunning, core.PodFailed, core.PodUnknown}
100 *j = statuses[c.Rand.Intn(len(statuses))]
101 },
102 func(j *core.Binding, c fuzz.Continue) {
103 c.Fuzz(&j.ObjectMeta)
104 j.Target.Name = c.RandString()
105 },
106 func(j *core.ReplicationController, c fuzz.Continue) {
107 c.FuzzNoCustom(j)
108
109
110 if j.Spec.Template != nil {
111 if len(j.Labels) == 0 {
112 j.Labels = j.Spec.Template.Labels
113 }
114 if len(j.Spec.Selector) == 0 {
115 j.Spec.Selector = j.Spec.Template.Labels
116 }
117 }
118 },
119 func(j *core.ReplicationControllerSpec, c fuzz.Continue) {
120 c.FuzzNoCustom(j)
121
122 },
123 func(j *core.List, c fuzz.Continue) {
124 c.FuzzNoCustom(j)
125
126 if false {
127 j.Items = []runtime.Object{}
128 }
129 },
130 func(q *core.ResourceRequirements, c fuzz.Continue) {
131 randomQuantity := func() resource.Quantity {
132 var q resource.Quantity
133 c.Fuzz(&q)
134
135 _ = q.String()
136 return q
137 }
138 q.Limits = make(core.ResourceList)
139 q.Requests = make(core.ResourceList)
140 cpuLimit := randomQuantity()
141 q.Limits[core.ResourceCPU] = cpuLimit.DeepCopy()
142 q.Requests[core.ResourceCPU] = cpuLimit.DeepCopy()
143 memoryLimit := randomQuantity()
144 q.Limits[core.ResourceMemory] = memoryLimit.DeepCopy()
145 q.Requests[core.ResourceMemory] = memoryLimit.DeepCopy()
146 storageLimit := randomQuantity()
147 q.Limits[core.ResourceStorage] = storageLimit.DeepCopy()
148 q.Requests[core.ResourceStorage] = storageLimit.DeepCopy()
149 },
150 func(q *core.LimitRangeItem, c fuzz.Continue) {
151 var cpuLimit resource.Quantity
152 c.Fuzz(&cpuLimit)
153
154 q.Type = core.LimitTypeContainer
155 q.Default = make(core.ResourceList)
156 q.Default[core.ResourceCPU] = cpuLimit.DeepCopy()
157
158 q.DefaultRequest = make(core.ResourceList)
159 q.DefaultRequest[core.ResourceCPU] = cpuLimit.DeepCopy()
160
161 q.Max = make(core.ResourceList)
162 q.Max[core.ResourceCPU] = cpuLimit.DeepCopy()
163
164 q.Min = make(core.ResourceList)
165 q.Min[core.ResourceCPU] = cpuLimit.DeepCopy()
166
167 q.MaxLimitRequestRatio = make(core.ResourceList)
168 q.MaxLimitRequestRatio[core.ResourceCPU] = resource.MustParse("10")
169 },
170 func(p *core.PullPolicy, c fuzz.Continue) {
171 policies := []core.PullPolicy{core.PullAlways, core.PullNever, core.PullIfNotPresent}
172 *p = policies[c.Rand.Intn(len(policies))]
173 },
174 func(rp *core.RestartPolicy, c fuzz.Continue) {
175 policies := []core.RestartPolicy{core.RestartPolicyAlways, core.RestartPolicyNever, core.RestartPolicyOnFailure}
176 *rp = policies[c.Rand.Intn(len(policies))]
177 },
178
179
180 func(m *core.DownwardAPIVolumeFile, c fuzz.Continue) {
181 m.Path = c.RandString()
182 versions := []string{"v1"}
183 m.FieldRef = &core.ObjectFieldSelector{}
184 m.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))]
185 m.FieldRef.FieldPath = c.RandString()
186 c.Fuzz(m.Mode)
187 if m.Mode != nil {
188 *m.Mode &= 0777
189 }
190 },
191 func(s *core.SecretVolumeSource, c fuzz.Continue) {
192 c.FuzzNoCustom(s)
193
194 if c.RandBool() {
195 opt := c.RandBool()
196 s.Optional = &opt
197 }
198
199
200 var mode int32
201 c.Fuzz(&mode)
202 mode &= 0777
203 s.DefaultMode = &mode
204 },
205 func(cm *core.ConfigMapVolumeSource, c fuzz.Continue) {
206 c.FuzzNoCustom(cm)
207
208 if c.RandBool() {
209 opt := c.RandBool()
210 cm.Optional = &opt
211 }
212
213
214 var mode int32
215 c.Fuzz(&mode)
216 mode &= 0777
217 cm.DefaultMode = &mode
218 },
219 func(d *core.DownwardAPIVolumeSource, c fuzz.Continue) {
220 c.FuzzNoCustom(d)
221
222
223
224 var mode int32
225 c.Fuzz(&mode)
226 mode &= 0777
227 d.DefaultMode = &mode
228 },
229 func(s *core.ProjectedVolumeSource, c fuzz.Continue) {
230 c.FuzzNoCustom(s)
231
232
233
234 var mode int32
235 c.Fuzz(&mode)
236 mode &= 0777
237 s.DefaultMode = &mode
238 },
239 func(k *core.KeyToPath, c fuzz.Continue) {
240 c.FuzzNoCustom(k)
241 k.Key = c.RandString()
242 k.Path = c.RandString()
243
244
245
246 if k.Mode != nil {
247 *k.Mode &= 0777
248 }
249 },
250 func(vs *core.VolumeSource, c fuzz.Continue) {
251
252 v := reflect.ValueOf(vs).Elem()
253 i := int(c.RandUint64() % uint64(v.NumField()))
254 t := v.Field(i).Addr()
255 for v.Field(i).IsNil() {
256 c.Fuzz(t.Interface())
257 }
258 },
259 func(i *core.ISCSIVolumeSource, c fuzz.Continue) {
260 i.ISCSIInterface = c.RandString()
261 if i.ISCSIInterface == "" {
262 i.ISCSIInterface = "default"
263 }
264 },
265 func(i *core.ISCSIPersistentVolumeSource, c fuzz.Continue) {
266 i.ISCSIInterface = c.RandString()
267 if i.ISCSIInterface == "" {
268 i.ISCSIInterface = "default"
269 }
270 },
271 func(i *core.PersistentVolumeClaimSpec, c fuzz.Continue) {
272
273 volumeMode := core.PersistentVolumeMode(c.RandString())
274 if volumeMode == "" {
275 volumeMode = core.PersistentVolumeFilesystem
276 }
277 i.VolumeMode = &volumeMode
278 },
279 func(d *core.DNSPolicy, c fuzz.Continue) {
280 policies := []core.DNSPolicy{core.DNSClusterFirst, core.DNSDefault}
281 *d = policies[c.Rand.Intn(len(policies))]
282 },
283 func(p *core.Protocol, c fuzz.Continue) {
284 protocols := []core.Protocol{core.ProtocolTCP, core.ProtocolUDP, core.ProtocolSCTP}
285 *p = protocols[c.Rand.Intn(len(protocols))]
286 },
287 func(p *core.ServiceAffinity, c fuzz.Continue) {
288 types := []core.ServiceAffinity{core.ServiceAffinityClientIP, core.ServiceAffinityNone}
289 *p = types[c.Rand.Intn(len(types))]
290 },
291 func(p *core.ServiceType, c fuzz.Continue) {
292 types := []core.ServiceType{core.ServiceTypeClusterIP, core.ServiceTypeNodePort, core.ServiceTypeLoadBalancer}
293 *p = types[c.Rand.Intn(len(types))]
294 },
295 func(p *core.IPFamily, c fuzz.Continue) {
296 types := []core.IPFamily{core.IPv4Protocol, core.IPv6Protocol}
297 selected := types[c.Rand.Intn(len(types))]
298 *p = selected
299 },
300 func(p *core.ServiceExternalTrafficPolicy, c fuzz.Continue) {
301 types := []core.ServiceExternalTrafficPolicy{core.ServiceExternalTrafficPolicyCluster, core.ServiceExternalTrafficPolicyLocal}
302 *p = types[c.Rand.Intn(len(types))]
303 },
304 func(p *core.ServiceInternalTrafficPolicy, c fuzz.Continue) {
305 types := []core.ServiceInternalTrafficPolicy{core.ServiceInternalTrafficPolicyCluster, core.ServiceInternalTrafficPolicyLocal}
306 *p = types[c.Rand.Intn(len(types))]
307 },
308 func(ct *core.Container, c fuzz.Continue) {
309 c.FuzzNoCustom(ct)
310 ct.TerminationMessagePath = "/" + ct.TerminationMessagePath
311 ct.TerminationMessagePolicy = "File"
312 },
313 func(ep *core.EphemeralContainer, c fuzz.Continue) {
314 c.FuzzNoCustom(ep)
315 ep.EphemeralContainerCommon.TerminationMessagePath = "/" + ep.TerminationMessagePath
316 ep.EphemeralContainerCommon.TerminationMessagePolicy = "File"
317 },
318 func(p *core.Probe, c fuzz.Continue) {
319 c.FuzzNoCustom(p)
320
321 intFieldsWithDefaults := [...]string{"TimeoutSeconds", "PeriodSeconds", "SuccessThreshold", "FailureThreshold"}
322 v := reflect.ValueOf(p).Elem()
323 for _, field := range intFieldsWithDefaults {
324 f := v.FieldByName(field)
325 if f.Int() == 0 {
326 f.SetInt(1)
327 }
328 }
329 },
330 func(ev *core.EnvVar, c fuzz.Continue) {
331 ev.Name = c.RandString()
332 if c.RandBool() {
333 ev.Value = c.RandString()
334 } else {
335 ev.ValueFrom = &core.EnvVarSource{}
336 ev.ValueFrom.FieldRef = &core.ObjectFieldSelector{}
337
338 versions := []schema.GroupVersion{
339 {Group: "admission.k8s.io", Version: "v1alpha1"},
340 {Group: "apps", Version: "v1beta1"},
341 {Group: "apps", Version: "v1beta2"},
342 {Group: "foo", Version: "v42"},
343 }
344
345 ev.ValueFrom.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))].String()
346 ev.ValueFrom.FieldRef.FieldPath = c.RandString()
347 }
348 },
349 func(ev *core.EnvFromSource, c fuzz.Continue) {
350 if c.RandBool() {
351 ev.Prefix = "p_"
352 }
353 if c.RandBool() {
354 c.Fuzz(&ev.ConfigMapRef)
355 } else {
356 c.Fuzz(&ev.SecretRef)
357 }
358 },
359 func(cm *core.ConfigMapEnvSource, c fuzz.Continue) {
360 c.FuzzNoCustom(cm)
361 if c.RandBool() {
362 opt := c.RandBool()
363 cm.Optional = &opt
364 }
365 },
366 func(s *core.SecretEnvSource, c fuzz.Continue) {
367 c.FuzzNoCustom(s)
368 },
369 func(sc *core.SecurityContext, c fuzz.Continue) {
370 c.FuzzNoCustom(sc)
371 if c.RandBool() {
372 priv := c.RandBool()
373 sc.Privileged = &priv
374 }
375
376 if c.RandBool() {
377 sc.Capabilities = &core.Capabilities{
378 Add: make([]core.Capability, 0),
379 Drop: make([]core.Capability, 0),
380 }
381 c.Fuzz(&sc.Capabilities.Add)
382 c.Fuzz(&sc.Capabilities.Drop)
383 }
384 },
385 func(s *core.Secret, c fuzz.Continue) {
386 c.FuzzNoCustom(s)
387 s.Type = core.SecretTypeOpaque
388 },
389 func(r *core.RBDVolumeSource, c fuzz.Continue) {
390 r.RBDPool = c.RandString()
391 if r.RBDPool == "" {
392 r.RBDPool = "rbd"
393 }
394 r.RadosUser = c.RandString()
395 if r.RadosUser == "" {
396 r.RadosUser = "admin"
397 }
398 r.Keyring = c.RandString()
399 if r.Keyring == "" {
400 r.Keyring = "/etc/ceph/keyring"
401 }
402 },
403 func(r *core.RBDPersistentVolumeSource, c fuzz.Continue) {
404 r.RBDPool = c.RandString()
405 if r.RBDPool == "" {
406 r.RBDPool = "rbd"
407 }
408 r.RadosUser = c.RandString()
409 if r.RadosUser == "" {
410 r.RadosUser = "admin"
411 }
412 r.Keyring = c.RandString()
413 if r.Keyring == "" {
414 r.Keyring = "/etc/ceph/keyring"
415 }
416 },
417 func(obj *core.HostPathVolumeSource, c fuzz.Continue) {
418 c.FuzzNoCustom(obj)
419 types := []core.HostPathType{core.HostPathUnset, core.HostPathDirectoryOrCreate, core.HostPathDirectory,
420 core.HostPathFileOrCreate, core.HostPathFile, core.HostPathSocket, core.HostPathCharDev, core.HostPathBlockDev}
421 typeVol := types[c.Rand.Intn(len(types))]
422 if obj.Type == nil {
423 obj.Type = &typeVol
424 }
425 },
426 func(pv *core.PersistentVolume, c fuzz.Continue) {
427 c.FuzzNoCustom(pv)
428 types := []core.PersistentVolumePhase{core.VolumeAvailable, core.VolumePending, core.VolumeBound, core.VolumeReleased, core.VolumeFailed}
429 pv.Status.Phase = types[c.Rand.Intn(len(types))]
430 pv.Status.Message = c.RandString()
431 reclamationPolicies := []core.PersistentVolumeReclaimPolicy{core.PersistentVolumeReclaimRecycle, core.PersistentVolumeReclaimRetain}
432 pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))]
433 volumeModes := []core.PersistentVolumeMode{core.PersistentVolumeFilesystem, core.PersistentVolumeBlock}
434 pv.Spec.VolumeMode = &volumeModes[c.Rand.Intn(len(volumeModes))]
435 },
436 func(pvc *core.PersistentVolumeClaim, c fuzz.Continue) {
437 c.FuzzNoCustom(pvc)
438 types := []core.PersistentVolumeClaimPhase{core.ClaimBound, core.ClaimPending, core.ClaimLost}
439 pvc.Status.Phase = types[c.Rand.Intn(len(types))]
440 volumeModes := []core.PersistentVolumeMode{core.PersistentVolumeFilesystem, core.PersistentVolumeBlock}
441 pvc.Spec.VolumeMode = &volumeModes[c.Rand.Intn(len(volumeModes))]
442 },
443 func(obj *core.AzureDiskVolumeSource, c fuzz.Continue) {
444 if obj.CachingMode == nil {
445 obj.CachingMode = new(core.AzureDataDiskCachingMode)
446 *obj.CachingMode = core.AzureDataDiskCachingReadWrite
447 }
448 if obj.Kind == nil {
449 obj.Kind = new(core.AzureDataDiskKind)
450 *obj.Kind = core.AzureSharedBlobDisk
451 }
452 if obj.FSType == nil {
453 obj.FSType = new(string)
454 *obj.FSType = "ext4"
455 }
456 if obj.ReadOnly == nil {
457 obj.ReadOnly = new(bool)
458 *obj.ReadOnly = false
459 }
460 },
461 func(sio *core.ScaleIOVolumeSource, c fuzz.Continue) {
462 sio.StorageMode = c.RandString()
463 if sio.StorageMode == "" {
464 sio.StorageMode = "ThinProvisioned"
465 }
466 sio.FSType = c.RandString()
467 if sio.FSType == "" {
468 sio.FSType = "xfs"
469 }
470 },
471 func(sio *core.ScaleIOPersistentVolumeSource, c fuzz.Continue) {
472 sio.StorageMode = c.RandString()
473 if sio.StorageMode == "" {
474 sio.StorageMode = "ThinProvisioned"
475 }
476 sio.FSType = c.RandString()
477 if sio.FSType == "" {
478 sio.FSType = "xfs"
479 }
480 },
481 func(s *core.NamespaceSpec, c fuzz.Continue) {
482 s.Finalizers = []core.FinalizerName{core.FinalizerKubernetes}
483 },
484 func(s *core.Namespace, c fuzz.Continue) {
485 c.FuzzNoCustom(s)
486
487 if len(s.Name) > 0 {
488 if s.Labels == nil {
489 s.Labels = map[string]string{}
490 }
491 s.Labels["kubernetes.io/metadata.name"] = s.Name
492 }
493 },
494 func(s *core.NamespaceStatus, c fuzz.Continue) {
495 s.Phase = core.NamespaceActive
496 },
497 func(http *core.HTTPGetAction, c fuzz.Continue) {
498 c.FuzzNoCustom(http)
499 http.Path = "/" + http.Path
500 http.Scheme = "x" + http.Scheme
501 },
502 func(ss *core.ServiceSpec, c fuzz.Continue) {
503 c.FuzzNoCustom(ss)
504 if len(ss.Ports) == 0 {
505
506 ss.Ports = append(ss.Ports, core.ServicePort{})
507 c.Fuzz(&ss.Ports[0])
508 }
509 for i := range ss.Ports {
510 switch ss.Ports[i].TargetPort.Type {
511 case intstr.Int:
512 ss.Ports[i].TargetPort.IntVal = 1 + ss.Ports[i].TargetPort.IntVal%65535
513 case intstr.String:
514 ss.Ports[i].TargetPort.StrVal = "x" + ss.Ports[i].TargetPort.StrVal
515 }
516 }
517 types := []core.ServiceAffinity{core.ServiceAffinityNone, core.ServiceAffinityClientIP}
518 ss.SessionAffinity = types[c.Rand.Intn(len(types))]
519 switch ss.SessionAffinity {
520 case core.ServiceAffinityClientIP:
521 timeoutSeconds := int32(c.Rand.Intn(int(core.MaxClientIPServiceAffinitySeconds)))
522 ss.SessionAffinityConfig = &core.SessionAffinityConfig{
523 ClientIP: &core.ClientIPConfig{
524 TimeoutSeconds: &timeoutSeconds,
525 },
526 }
527 case core.ServiceAffinityNone:
528 ss.SessionAffinityConfig = nil
529 }
530 if ss.AllocateLoadBalancerNodePorts == nil {
531 ss.AllocateLoadBalancerNodePorts = utilpointer.Bool(true)
532 }
533 },
534 func(s *core.NodeStatus, c fuzz.Continue) {
535 c.FuzzNoCustom(s)
536 s.Allocatable = s.Capacity
537 },
538 func(e *core.Event, c fuzz.Continue) {
539 c.FuzzNoCustom(e)
540 e.EventTime = metav1.MicroTime{Time: time.Unix(1, 1000)}
541 if e.Series != nil {
542 e.Series.LastObservedTime = metav1.MicroTime{Time: time.Unix(3, 3000)}
543 }
544 },
545 func(j *core.GRPCAction, c fuzz.Continue) {
546 empty := ""
547 if j.Service == nil {
548 j.Service = &empty
549 }
550 },
551 func(j *core.LoadBalancerStatus, c fuzz.Continue) {
552 ipMode := core.LoadBalancerIPModeVIP
553 for i := range j.Ingress {
554 if j.Ingress[i].IPMode == nil {
555 j.Ingress[i].IPMode = &ipMode
556 }
557 }
558 },
559 }
560 }
561
View as plain text