Commit a18e6a186f53af06937a2c268c72443336f4ab56

Authored by Thomas Graf
Committed by David S. Miller
1 parent 4682a03586

netlink: Don't reorder loads/stores before marking mmap netlink frame as available

Each mmap Netlink frame contains a status field which indicates
whether the frame is unused, reserved, contains data or needs to
be skipped. Both loads and stores may not be reordeded and must
complete before the status field is changed and another CPU might
pick up the frame for use. Use an smp_mb() to cover needs of both
types of callers to netlink_set_status(), callers which have been
reading data frame from the frame, and callers which have been
filling or releasing and thus writing to the frame.

- Example code path requiring a smp_rmb():
  memcpy(skb->data, (void *)hdr + NL_MMAP_HDRLEN, hdr->nm_len);
  netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED);

- Example code path requiring a smp_wmb():
  hdr->nm_uid	= from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid);
  hdr->nm_gid	= from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid);
  netlink_frame_flush_dcache(hdr);
  netlink_set_status(hdr, NL_MMAP_STATUS_VALID);

Fixes: f9c228 ("netlink: implement memory mapped recvmsg()")
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 1 additions and 1 deletions Side-by-side Diff

net/netlink/af_netlink.c
... ... @@ -550,9 +550,9 @@
550 550 static void netlink_set_status(struct nl_mmap_hdr *hdr,
551 551 enum nl_mmap_status status)
552 552 {
  553 + smp_mb();
553 554 hdr->nm_status = status;
554 555 flush_dcache_page(pgvec_to_page(hdr));
555   - smp_wmb();
556 556 }
557 557  
558 558 static struct nl_mmap_hdr *