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:
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.
The dlv output below shows that we should no longer wait message if a
permission error is received.
(dlv)
> github.com/mdlayher/netlink.(*Conn).receive() /home/black_desk/Documents/go/pkg/mod/github.com/mdlayher/netlink@v1.7.2/conn.go:290 (PC: 0x4e9c58)
285: // drain all the messages from the socket.
286: var multi bool
287:
288: for _, m := range msgs {
289: if err := checkMessage(m); err != nil {
=> 290: return nil, err
291: }
292:
293: // Does this message indicate a multi-part message?
294: if m.Header.Flags&Multi == 0 {
295: // No, check the next messages.
(dlv) p msgs
[]github.com/mdlayher/netlink.Message len: 1, cap: 1, [
{
Header: (*"github.com/mdlayher/netlink.Header")(0xc00018a030),
Data: []uint8 len: 24, cap: 4080, [255,255,255,255,20,0,0,0,16,0,1,0,198,155,58,9,245,70,25,0,0,0,0,10],},
]
(dlv) bt
0 0x00000000004e9c58 in github.com/mdlayher/netlink.(*Conn).receive
at /home/black_desk/Documents/go/pkg/mod/github.com/mdlayher/netlink@v1.7.2/conn.go:290
1 0x00000000004e92c5 in github.com/mdlayher/netlink.(*Conn).lockedReceive
at /home/black_desk/Documents/go/pkg/mod/github.com/mdlayher/netlink@v1.7.2/conn.go:238
2 0x00000000004e90a5 in github.com/mdlayher/netlink.(*Conn).Receive
at /home/black_desk/Documents/go/pkg/mod/github.com/mdlayher/netlink@v1.7.2/conn.go:231
3 0x00000000004ff085 in github.com/google/nftables.receiveAckAware
at /home/black_desk/cgtproxy/nftables/conn.go:141
4 0x00000000005002d7 in github.com/google/nftables.(*Conn).Flush
at /home/black_desk/cgtproxy/nftables/conn.go:255
5 0x0000000000508290 in main.main
at ./main.go:23
6 0x000000000043eae7 in runtime.main
at /home/black_desk/.goenv/versions/1.21.3/src/runtime/proc.go:267
7 0x000000000046d8e1 in runtime.goexit
at /home/black_desk/.goenv/versions/1.21.3/src/runtime/asm_amd64.s:1650
(dlv) frame 4
> github.com/mdlayher/netlink.(*Conn).receive() /home/black_desk/Documents/go/pkg/mod/github.com/mdlayher/netlink@v1.7.2/conn.go:290 (PC: 0x4e9c58)
Frame 4: /home/black_desk/cgtproxy/nftables/conn.go:255 (PC: 5002d7)
250: }
251:
252: var errs error
253: // Fetch the requested acknowledgement for each message we sent.
254: for _, msg := range cc.messages {
=> 255: if _, err := receiveAckAware(conn, msg.Header.Flags); err != nil {
256: errs = errors.Join(errs, err)
257: }
258: }
259:
260: if errs != nil {
(dlv) p cc.messages
[]github.com/mdlayher/netlink.Message len: 3, cap: 4, [
{
Header: (*"github.com/mdlayher/netlink.Header")(0xc0001341e0),
Data: []uint8 len: 20, cap: 24, [0,0,0,0,5,0,1,0,0,0,0,0,8,0,2,0,0,0,0,0],},
{
Header: (*"github.com/mdlayher/netlink.Header")(0xc000134208),
Data: []uint8 len: 52, cap: 64, [0,0,0,0,5,0,1,0,0,0,0,0,5,0,2,0,0,0,0,0,8,0,3,0,0,0,0,0,8,0,4,0,0,0,0,0,8,0,5,0,0,0,0,0,8,0,10,0,0,0,0,1],},
{
Header: (*"github.com/mdlayher/netlink.Header")(0xc000134230),
Data: []uint8 len: 52, cap: 64, [0,0,0,0,5,0,1,0,0,0,0,0,5,0,2,0,0,0,0,0,8,0,3,0,0,0,0,0,8,0,4,0,0,0,0,0,8,0,5,0,0,0,0,0,8,0,10,0,0,0,0,2],},
]
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:
That's because that although we send multiple messages on netlink socket, kernel will only sends one permission error message as reply.
The dlv output below shows that we should no longer wait message if a permission error is received.
Signed-off-by: black-desk me@black-desk.cn