{"record":{"id":"0d51bc1f3ee700a7","repo":"cilium/cilium","slug":"updating-link-s-for-program-s-w-0d51bc","errorCode":null,"errorMessage":"updating link %s for program %s: %w","messagePattern":"updating link (.+?) for program (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/datapath/loader/xdp.go","lineNumber":338,"sourceCode":"\tcase errors.Is(err, unix.ENOLINK):\n\t\tif err := os.Remove(pin); err != nil {\n\t\t\treturn fmt.Errorf(\"unpinning defunct link %s: %w\", pin, err)\n\t\t}\n\n\t\tlogger.Info(\"Unpinned defunct link for program\",\n\t\t\tlogfields.Link, pin,\n\t\t\tlogfields.ProgName, progName,\n\t\t)\n\n\t// No existing link found, continue trying to create one.\n\tcase errors.Is(err, os.ErrNotExist):\n\t\tlogger.Info(\"No existing link found for program\",\n\t\t\tlogfields.Link, pin,\n\t\t\tlogfields.ProgName, progName,\n\t\t)\n\n\tdefault:\n\t\treturn fmt.Errorf(\"updating link %s for program %s: %w\", pin, progName, err)\n\t}\n\n\tif err := bpf.MkdirBPF(bpffsDir); err != nil {\n\t\treturn fmt.Errorf(\"creating bpffs link dir for xdp attachment to device %s: %w\", iface.Attrs().Name, err)\n\t}\n\n\t// Create a new link. This will only succeed on nodes that support bpf_link\n\t// and don't have any XDP programs attached through netlink.\n\tl, err := link.AttachXDP(link.XDPOptions{\n\t\tProgram:   prog,\n\t\tInterface: iface.Attrs().Index,\n\t\tFlags:     flags,\n\t})\n\tif err == nil {\n\t\tdefer func() {\n\t\t\t// The program was successfully attached using bpf_link. Closing a link\n\t\t\t// does not detach the program if the link is pinned.\n\t\t\tif err := l.Close(); err != nil {","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/datapath/loader/xdp.go#L320-L356","documentation":"This is the default branch of the UpdateLink switch in attachXDPProgram: any error that is neither nil, ENOENT (no link yet), nor ENOLINK (defunct) is reported as a failure to update the existing bpf_link pin. It means Cilium found an existing pinned link but could not swap in the new program via link update.","triggerScenarios":"bpf.UpdateLink(pin, prog) returns EPERM (insufficient privileges), EINVAL (program type mismatch with existing link), EEXIST-class errors, or I/O errors on bpffs while updating an existing pinned link for progName.","commonSituations":"Older Cilium version pinned a link and the running process lacks capabilities to update it; pin file on bpffs corrupted or replaced by a non-link file; kernel version mismatch between the pinned link and the new program semantics.","solutions":["Unpin the offending link (rm <pin> under /sys/fs/bpf/cilium/links/) and restart so a fresh link is created","Grant required capabilities (CAP_BPF, CAP_NET_ADMIN, CAP_SYS_ADMIN) to the agent process","Check wrapped error for EPERM/EINVAL and align program versions — wipe /var/run/cilium state after upgrades","Verify the pin path contains an actual bpf_link (bpftool link show) not a leftover file"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure pin is a real link before update\nif _, err := os.Stat(pin); err == nil {\n    if fi, _ := os.Stat(pin); fi.Mode().IsRegular() {\n        os.Remove(pin) // wrong type; let a fresh link be created\n    }\n}","typeGuard":null,"tryCatchPattern":"// Go: on update failure, unpin and retry once\nif err := bpf.UpdateLink(pin, prog); err != nil {\n    os.Remove(pin)\n    err = bpf.UpdateLink(pin, prog)\n    if err != nil { return fmt.Errorf(\"updating link %s for program %s: %w\", pin, progName, err) }\n}","preventionTips":["Wipe pinned links after Cilium upgrades to avoid type/flag mismatches with old links","Grant CAP_BPF/CAP_SYS_ADMIN so link updates are permitted","Avoid sharing bpffs directories between different agent versions","Validate kernel supports bpf_link (kernel >= 5.7) before relying on pinned links"],"tags":["ebpf","bpf-link","xdp","permissions"],"backgroundTag":"bpf-link-update-failed","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}