Skip to content

Commit ad0c9d8

Browse files
committed
netlink: return stashed pid
There are three types of pid used in netlink interface: - the nl_pid on the source (app) side (part of sockaddr_nl) set before bind(); could be 0 to request kernel generating new one - the nl_pid on the destination (kernel) size set into dst_addr that always needs to be 0 if we communicate with kernel - the nlmsg_pid (sender port ID) that is part of the netlink message header sent to and received from kernel Some relevant information from Linux docs: " nlmsg_seq and nlmsg_pid are used to track messages. nlmsg_pid shows the origin of the message. Note that there isn't a 1:1 relationship between nlmsg_pid and the PID of the process if the message originated from a netlink socket. See the ADDRESS FORMATS section for further information. Both nlmsg_seq and nlmsg_pid are opaque to netlink core." and: " nl_pid is the unicast address of netlink socket. It's always 0 if the destination is in the kernel. For a user-space process, nl_pid is usually the PID of the process owning the destination socket. However, nl_pid identifies a netlink socket, not a process. If a process owns several netlink sockets, then nl_pid can be equal to the process ID only for at most one socket. There are two ways to assign nl_pid to a netlink socket. If the application sets nl_pid before calling bind(2), then it is up to the application to make sure that nl_pid is unique. If the application sets it to 0, the kernel takes care of assigning it. The kernel assigns the process ID to the first netlink socket the process opens and assigns a unique nl_pid to every netlink socket that the process subsequently creates." The 1st one needs to be stashed or generated (if 0) and then set on nlmsg_pid for each response so that the application receving it can distinguish it if necessary. Golang runtime actually calls sockname() and verifies that the nlmsg_pid in the replies matches the nl_pid on the source socket. The patch modifies relevant code that builds netlink responses to put the nl_pid stashed during socket attach process to set it as value of inlmsg_pid. It also re-implements the netlink_sockaddr() to make it return information including the source PID. Signed-off-by: Waldemar Kozaczuk <[email protected]>
1 parent aed2886 commit ad0c9d8

File tree

3 files changed

+35
-18
lines changed

3 files changed

+35
-18
lines changed

bsd/sys/compat/linux/linux_netlink.cc

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -436,10 +436,27 @@ netlink_shutdown(struct socket *so)
436436
return (raw_usrreqs.pru_shutdown(so));
437437
}
438438

439+
static pid_t
440+
get_socket_pid(struct socket *so)
441+
{
442+
struct rawcb *rp = sotorawcb(so);
443+
struct netlinkcb *ncb = (netlinkcb *)rp;
444+
return ncb->nl_pid;
445+
}
446+
439447
static int
440448
netlink_sockaddr(struct socket *so, struct bsd_sockaddr **nam)
441449
{
442-
return (raw_usrreqs.pru_sockaddr(so, nam));
450+
struct bsd_sockaddr_nl *sin;
451+
452+
sin = (bsd_sockaddr_nl*)malloc(sizeof *sin);
453+
bzero(sin, sizeof *sin);
454+
sin->nl_family = AF_NETLINK;
455+
sin->nl_len = sizeof(*sin);
456+
sin->nl_pid = get_socket_pid(so);
457+
458+
*nam = (bsd_sockaddr*)sin;
459+
return 0;
443460
}
444461

445462
static struct pr_usrreqs netlink_usrreqs = initialize_with([] (pr_usrreqs& x) {
@@ -474,7 +491,7 @@ netlink_senderr(struct socket *so, struct nlmsghdr *nlm, int error)
474491
}
475492

476493
if ((hdr = (struct nlmsghdr *)nlmsg_put(m,
477-
nlm ? nlm->nlmsg_pid : 0,
494+
get_socket_pid(so),
478495
nlm ? nlm->nlmsg_seq : 0,
479496
NLMSG_ERROR, sizeof(*err),
480497
nlm ? nlm->nlmsg_flags : 0)) == NULL) {
@@ -513,7 +530,7 @@ netlink_process_getlink_msg(struct socket *so, struct nlmsghdr *nlm)
513530
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
514531
IF_ADDR_RLOCK(ifp);
515532

516-
nlh = nlmsg_begin(m, nlm->nlmsg_pid, nlm->nlmsg_seq, LINUX_RTM_NEWLINK, sizeof(*ifm), nlm->nlmsg_flags);
533+
nlh = nlmsg_begin(m, get_socket_pid(so), nlm->nlmsg_seq, LINUX_RTM_NEWLINK, sizeof(*ifm), nlm->nlmsg_flags);
517534
if (!nlh) {
518535
error = ENOBUFS;
519536
goto done;
@@ -547,7 +564,7 @@ netlink_process_getlink_msg(struct socket *so, struct nlmsghdr *nlm)
547564
IF_ADDR_RUNLOCK(ifp);
548565
nlmsg_end(m, nlh);
549566
}
550-
nlh = nlmsg_put(m, nlm->nlmsg_pid, nlm->nlmsg_seq, NLMSG_DONE, 0, nlm->nlmsg_flags);
567+
nlh = nlmsg_put(m, get_socket_pid(so), nlm->nlmsg_seq, NLMSG_DONE, 0, nlm->nlmsg_flags);
551568

552569
done:
553570
if (ifp != NULL)
@@ -605,7 +622,7 @@ netlink_process_getaddr_msg(struct socket *so, struct nlmsghdr *nlm)
605622
if (!ifa->ifa_addr)
606623
continue;
607624

608-
nlh = nlmsg_begin(m, nlm->nlmsg_pid, nlm->nlmsg_seq, LINUX_RTM_NEWADDR, sizeof(*ifm), nlm->nlmsg_flags);
625+
nlh = nlmsg_begin(m, get_socket_pid(so), nlm->nlmsg_seq, LINUX_RTM_NEWADDR, sizeof(*ifm), nlm->nlmsg_flags);
609626
if (!nlh) {
610627
error = ENOBUFS;
611628
goto done;
@@ -663,7 +680,7 @@ netlink_process_getaddr_msg(struct socket *so, struct nlmsghdr *nlm)
663680

664681
IF_ADDR_RUNLOCK(ifp);
665682
}
666-
nlh = nlmsg_put(m, nlm->nlmsg_pid, nlm->nlmsg_seq, NLMSG_DONE, 0, nlm->nlmsg_flags);
683+
nlh = nlmsg_put(m, get_socket_pid(so), nlm->nlmsg_seq, NLMSG_DONE, 0, nlm->nlmsg_flags);
667684
done:
668685
if (ifp != NULL)
669686
IF_ADDR_RUNLOCK(ifp);
@@ -728,7 +745,7 @@ struct netlink_getneigh_lle_cbdata {
728745
};
729746

730747
static int
731-
netlink_getneigh_lle_cb(struct lltable *llt, struct llentry *lle, void *data)
748+
netlink_getneigh_lle_cb(struct socket *so, struct lltable *llt, struct llentry *lle, void *data)
732749
{
733750
struct netlink_getneigh_lle_cbdata *cbdata = (struct netlink_getneigh_lle_cbdata *) data;
734751
int ndm_family = netlink_bsd_to_linux_family(llt->llt_af);
@@ -743,7 +760,7 @@ netlink_getneigh_lle_cb(struct lltable *llt, struct llentry *lle, void *data)
743760
struct nlmsghdr *nlm = cbdata->nlm;
744761
struct mbuf *m = cbdata->m;
745762
struct ndmsg *ndm;
746-
struct nlmsghdr *nlh = nlmsg_begin(m, nlm->nlmsg_pid, nlm->nlmsg_seq, LINUX_RTM_NEWNEIGH, sizeof(*ndm), nlm->nlmsg_flags);
763+
struct nlmsghdr *nlh = nlmsg_begin(m, get_socket_pid(so), nlm->nlmsg_seq, LINUX_RTM_NEWNEIGH, sizeof(*ndm), nlm->nlmsg_flags);
747764

748765
if (!nlh) {
749766
return ENOBUFS;
@@ -788,7 +805,7 @@ netlink_getneigh_lle_cb(struct lltable *llt, struct llentry *lle, void *data)
788805

789806

790807
static int
791-
netlink_getneigh_lltable_cb(struct lltable *llt, void *cbdata)
808+
netlink_getneigh_lltable_cb(struct socket *so, struct lltable *llt, void *cbdata)
792809
{
793810
struct netlink_getneigh_lle_cbdata *data = (struct netlink_getneigh_lle_cbdata *) cbdata;
794811
int error = 0;
@@ -799,7 +816,7 @@ netlink_getneigh_lltable_cb(struct lltable *llt, void *cbdata)
799816
return 0;
800817

801818
IF_AFDATA_RLOCK(llt->llt_ifp);
802-
error = lltable_foreach_lle(llt, netlink_getneigh_lle_cb, data);
819+
error = lltable_foreach_lle(so, llt, netlink_getneigh_lle_cb, data);
803820
IF_AFDATA_RUNLOCK(llt->llt_ifp);
804821

805822
return error;
@@ -829,10 +846,10 @@ netlink_process_getneigh_msg(struct socket *so, struct nlmsghdr *nlm)
829846
cbdata.family = ndm->ndm_family;
830847
cbdata.state = ndm->ndm_state;
831848

832-
error = lltable_foreach(netlink_getneigh_lltable_cb, &cbdata);
849+
error = lltable_foreach(so, netlink_getneigh_lltable_cb, &cbdata);
833850

834851
if (!error) {
835-
nlh = nlmsg_put(m, nlm->nlmsg_pid, nlm->nlmsg_seq, NLMSG_DONE, 0, nlm->nlmsg_flags);
852+
nlh = nlmsg_put(m, get_socket_pid(so), nlm->nlmsg_seq, NLMSG_DONE, 0, nlm->nlmsg_flags);
836853
netlink_dispatch(so, m);
837854
} else {
838855
m_free(m);

bsd/sys/net/if_llatbl.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,14 +501,14 @@ DB_SHOW_ALL_COMMAND(lltables, db_show_all_lltables)
501501
/*
502502
* Iterate over all lltables
503503
*/
504-
int lltable_foreach(int (*func)(struct lltable *llt, void *cbdata), void *cbdata)
504+
int lltable_foreach(struct socket *so, int (*func)(struct socket *so, struct lltable *llt, void *cbdata), void *cbdata)
505505
{
506506
struct lltable *llt;
507507
int error = 0;
508508

509509
LLTABLE_RLOCK();
510510
SLIST_FOREACH(llt, &V_lltables, llt_link) {
511-
if ((error = func(llt, cbdata)) != 0)
511+
if ((error = func(so, llt, cbdata)) != 0)
512512
break;
513513
}
514514
LLTABLE_RUNLOCK();
@@ -519,7 +519,7 @@ int lltable_foreach(int (*func)(struct lltable *llt, void *cbdata), void *cbdata
519519
/*
520520
* Iterate over all llentries in the lltable
521521
*/
522-
int lltable_foreach_lle(struct lltable *llt, int (*func)(struct lltable *llt, struct llentry *lle, void *cbdata), void *cbdata)
522+
int lltable_foreach_lle(struct socket *so, struct lltable *llt, int (*func)(struct socket *so, struct lltable *llt, struct llentry *lle, void *cbdata), void *cbdata)
523523
{
524524
struct llentry *lle;
525525
int i;
@@ -530,7 +530,7 @@ int lltable_foreach_lle(struct lltable *llt, int (*func)(struct lltable *llt, st
530530
/* skip deleted entries */
531531
if ((lle->la_flags & LLE_DELETED) == LLE_DELETED)
532532
continue;
533-
if ((error = func(llt, lle, cbdata)) != 0)
533+
if ((error = func(so, llt, lle, cbdata)) != 0)
534534
break;
535535
}
536536
}

bsd/sys/net/if_llatbl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,12 @@ struct llentry *llentry_alloc(struct ifnet *, struct lltable *,
201201
/*
202202
* Iterate over all lltables
203203
*/
204-
int lltable_foreach(int (*func)(struct lltable *llt, void *cbdata), void *cbdata);
204+
int lltable_foreach(struct socket *so, int (*func)(struct socket *so, struct lltable *llt, void *cbdata), void *cbdata);
205205

206206
/*
207207
* Iterate over all llentries in the lltable
208208
*/
209-
int lltable_foreach_lle(struct lltable *llt, int (*func)(struct lltable *llt, struct llentry *lle, void *cbdata), void *cbdata);
209+
int lltable_foreach_lle(struct socket *so, struct lltable *llt, int (*func)(struct socket *so, struct lltable *llt, struct llentry *lle, void *cbdata), void *cbdata);
210210

211211
__END_DECLS
212212

0 commit comments

Comments
 (0)