Skip to content

Commit 0d9ef08

Browse files
committed
netlink: do not pass writer to the Linux translation layer
Another flaw in the KPI between Netlink and Linuxulator is that we pass the on-stack writer structure. This structure belongs to someone, that we can't even identify inside nl_send() and we shall not tamper it. The Linux translation layer needs a writer, because it actually composes a new message. Instead of reusing someone's writer and trying to repair it in all possible cases where translation process tampers the writer, just let Linuxulator use its own writer. See also b977dd1. PR: 288892 Reviewed by: melifaro Differential Revision: https://reviews.freebsd.org/D51928
1 parent 554907b commit 0d9ef08

File tree

3 files changed

+21
-31
lines changed

3 files changed

+21
-31
lines changed

sys/compat/linux/linux_netlink.c

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -550,22 +550,15 @@ nlmsg_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_writer *nw)
550550
}
551551
}
552552

553-
static bool
554-
nlmsgs_to_linux(struct nl_writer *nw, struct nlpcb *nlp)
553+
static struct nl_buf *
554+
nlmsgs_to_linux(struct nl_buf *orig, struct nlpcb *nlp)
555555
{
556-
struct nl_buf *nb, *orig;
557-
u_int offset, msglen, orig_messages;
558-
559-
RT_LOG(LOG_DEBUG3, "%p: in %u bytes %u messages", __func__,
560-
nw->buf->datalen, nw->num_messages);
556+
struct nl_writer nw;
557+
u_int offset, msglen;
561558

562-
orig = nw->buf;
563-
nb = nl_buf_alloc(orig->datalen + SCRATCH_BUFFER_SIZE, M_NOWAIT);
564-
if (__predict_false(nb == NULL))
565-
return (false);
566-
nw->buf = nb;
567-
orig_messages = nw->num_messages;
568-
nw->num_messages = 0;
559+
if (__predict_false(!nl_writer_unicast(&nw,
560+
orig->datalen + SCRATCH_BUFFER_SIZE, nlp, false)))
561+
return (NULL);
569562

570563
/* Assume correct headers. Buffer IS mutable */
571564
for (offset = 0;
@@ -574,22 +567,18 @@ nlmsgs_to_linux(struct nl_writer *nw, struct nlpcb *nlp)
574567
struct nlmsghdr *hdr = (struct nlmsghdr *)&orig->data[offset];
575568

576569
msglen = NLMSG_ALIGN(hdr->nlmsg_len);
577-
if (!nlmsg_to_linux(hdr, nlp, nw)) {
570+
if (!nlmsg_to_linux(hdr, nlp, &nw)) {
578571
RT_LOG(LOG_DEBUG, "failed to process msg type %d",
579572
hdr->nlmsg_type);
580-
nl_buf_free(nb);
581-
nw->buf = orig;
582-
nw->num_messages = orig_messages;
583-
return (false);
573+
nl_buf_free(nw.buf);
574+
return (NULL);
584575
}
585576
}
586577

587-
MPASS(nw->num_messages == orig_messages);
588-
MPASS(nw->buf == nb);
589-
nl_buf_free(orig);
590-
RT_LOG(LOG_DEBUG3, "%p: out %u bytes", __func__, offset);
578+
RT_LOG(LOG_DEBUG3, "%p: in %u bytes %u messages", __func__,
579+
nw.buf->datalen, nw.num_messages);
591580

592-
return (true);
581+
return (nw.buf);
593582
}
594583

595584
static struct linux_netlink_provider linux_netlink_v1 = {

sys/netlink/netlink_io.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,16 +216,17 @@ nl_send(struct nl_writer *nw, struct nlpcb *nlp)
216216
hdr->nlmsg_len);
217217
}
218218

219-
if (nlp->nl_linux && linux_netlink_p != NULL &&
220-
__predict_false(!linux_netlink_p->msgs_to_linux(nw, nlp))) {
219+
if (nlp->nl_linux && linux_netlink_p != NULL) {
220+
nb = linux_netlink_p->msgs_to_linux(nw->buf, nlp);
221221
nl_buf_free(nw->buf);
222222
nw->buf = NULL;
223-
return (false);
223+
if (nb == NULL)
224+
return (false);
225+
} else {
226+
nb = nw->buf;
227+
nw->buf = NULL;
224228
}
225229

226-
nb = nw->buf;
227-
nw->buf = NULL;
228-
229230
SOCK_RECVBUF_LOCK(so);
230231
if (!nw->ignore_limit && __predict_false(sb->sb_hiwat <= sb->sb_ccc)) {
231232
SOCK_RECVBUF_UNLOCK(so);

sys/netlink/netlink_linux.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct nlpcb;
3737
struct nl_pstate;
3838
struct nl_writer;
3939

40-
typedef bool msgs_to_linux_cb_t(struct nl_writer *nw, struct nlpcb *nlp);
40+
typedef struct nl_buf * msgs_to_linux_cb_t(struct nl_buf *, struct nlpcb *);
4141
typedef int msg_from_linux_cb_t(int netlink_family, struct nlmsghdr **hdr,
4242
struct nl_pstate *npt);
4343

0 commit comments

Comments
 (0)