From 6df7a82bbd85a2712a5783d09df71f5be146a63b Mon Sep 17 00:00:00 2001 From: black-desk Date: Sun, 22 Oct 2023 04:11:55 +0800 Subject: [PATCH] fix: correct error handling in receiveAckAware (#243) Related: #242 After 7879d7ecf604316c0a7cc37c8a36dafe9b719545, it seems that any multi-message operation performed without CAP_SYS_ADMIN will leads to forever block inside nftables.Conn.Flush. For example: ```go package main import "github.com/google/nftables" func main() { conn, err := nftables.New() if err != nil { panic(err) } t := conn.AddTable(&nftables.Table{}) err = conn.AddSet(&nftables.Set{Table: t}, []nftables.SetElement{}) if err != nil { panic(err) } conn.AddSet(&nftables.Set{Table: t}, []nftables.SetElement{}) if err != nil { panic(err) } err = conn.Flush() if err != nil { panic(err) } return } ``` That's because that although we send multiple messages on netlink socket, kernel will only sends one permission error message as reply. Signed-off-by: black-desk --- conn.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conn.go b/conn.go index d78b09f..a9fbf2b 100644 --- a/conn.go +++ b/conn.go @@ -17,6 +17,7 @@ package nftables import ( "errors" "fmt" + "os" "sync" "github.com/google/nftables/binaryutil" @@ -253,6 +254,10 @@ func (cc *Conn) Flush() error { // Fetch the requested acknowledgement for each message we sent. for _, msg := range cc.messages { if _, err := receiveAckAware(conn, msg.Header.Flags); err != nil { + if errors.Is(err, os.ErrPermission) { + // Kernel will only send one permission error to user space. + return err + } errs = errors.Join(errs, err) } }