diff options
author | Thomas Haller <thaller@redhat.com> | 2018-12-23 14:39:22 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-01-09 16:46:41 +0100 |
commit | 2e48f6419ffaff960548f40e0a54303e35b9a7bb (patch) | |
tree | eb541636b01a7247a9b981f74ebe21983ecae204 | |
parent | e5fb1dd6e7fff3827eca0ec79e890b21ed96284d (diff) |
netlink: don't heap allocate struct ucred during nla_recv()
Instead, fill a preallocated output buffer provided by the caller.
-rw-r--r-- | src/platform/nm-linux-platform.c | 16 | ||||
-rw-r--r-- | src/platform/nm-netlink.c | 31 | ||||
-rw-r--r-- | src/platform/nm-netlink.h | 7 |
3 files changed, 32 insertions, 22 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index d9af54c2c3..45016ea50b 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -7367,13 +7367,13 @@ event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events) struct nlmsghdr *hdr; WaitForNlResponseResult seq_result; struct sockaddr_nl nla = {0}; - nm_auto_free struct ucred *creds = NULL; + struct ucred creds; + gboolean creds_has; nm_auto_free unsigned char *buf = NULL; continue_reading: g_clear_pointer (&buf, free); - g_clear_pointer (&creds, free); - n = nl_recv (sk, &nla, &buf, &creds); + n = nl_recv (sk, &nla, &buf, &creds, &creds_has); if (n <= 0) { @@ -7410,11 +7410,11 @@ continue_reading: nlmsg_set_proto (msg, NETLINK_ROUTE); nlmsg_set_src (msg, &nla); - if (!creds || creds->pid) { - if (creds) - _LOGT ("netlink: recvmsg: received non-kernel message (pid %d)", creds->pid); - else + if (!creds_has || creds.pid) { + if (!creds_has) _LOGT ("netlink: recvmsg: received message without credentials"); + else + _LOGT ("netlink: recvmsg: received non-kernel message (pid %d)", creds.pid); err = 0; goto stop; } @@ -7422,7 +7422,7 @@ continue_reading: _LOGt ("netlink: recvmsg: new message %s", nl_nlmsghdr_to_str (hdr, buf_nlmsghdr, sizeof (buf_nlmsghdr))); - nlmsg_set_creds (msg, creds); + nlmsg_set_creds (msg, &creds); if (hdr->nlmsg_flags & NLM_F_MULTI) multipart = TRUE; diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c index a4feee0564..72f7c73495 100644 --- a/src/platform/nm-netlink.c +++ b/src/platform/nm-netlink.c @@ -1084,10 +1084,11 @@ nl_recvmsgs (struct nl_sock *sk, const struct nl_cb *cb) gs_free unsigned char *buf = NULL; struct nlmsghdr *hdr; struct sockaddr_nl nla = { 0 }; - gs_free struct ucred *creds = NULL; + struct ucred creds; + gboolean creds_has; continue_reading: - n = nl_recv (sk, &nla, &buf, &creds); + n = nl_recv (sk, &nla, &buf, &creds, &creds_has); if (n <= 0) return n; @@ -1099,7 +1100,7 @@ continue_reading: nlmsg_set_proto (msg, sk->s_proto); nlmsg_set_src (msg, &nla); - nlmsg_set_creds (msg, creds); + nlmsg_set_creds (msg, creds_has ? &creds : NULL); nrecv++; @@ -1203,7 +1204,6 @@ skip: if (multipart) { /* Multipart message not yet complete, continue reading */ - nm_clear_g_free (&creds); nm_clear_g_free (&buf); goto continue_reading; @@ -1315,8 +1315,11 @@ int nl_send_auto (struct nl_sock *sk, struct nl_msg *msg) } int -nl_recv (struct nl_sock *sk, struct sockaddr_nl *nla, - unsigned char **buf, struct ucred **creds) +nl_recv (struct nl_sock *sk, + struct sockaddr_nl *nla, + unsigned char **buf, + struct ucred *out_creds, + gboolean *out_creds_has) { ssize_t n; int flags = 0; @@ -1327,12 +1330,13 @@ nl_recv (struct nl_sock *sk, struct sockaddr_nl *nla, .msg_iov = &iov, .msg_iovlen = 1, }; - gs_free struct ucred* tmpcreds = NULL; + struct ucred tmpcreds; + gboolean tmpcreds_has = FALSE; int retval; nm_assert (nla); nm_assert (buf && !*buf); - nm_assert (!creds || !*creds); + nm_assert (!out_creds_has == !out_creds); if ( (sk->s_flags & NL_MSG_PEEK) || ( !(sk->s_flags & NL_MSG_PEEK_EXPLICIT) @@ -1343,7 +1347,7 @@ nl_recv (struct nl_sock *sk, struct sockaddr_nl *nla, ?: (((size_t) nm_utils_getpagesize ()) * 4u); iov.iov_base = g_malloc (iov.iov_len); - if ( creds + if ( out_creds && (sk->s_flags & NL_SOCK_PASSCRED)) { msg.msg_controllen = CMSG_SPACE (sizeof (struct ucred)); msg.msg_control = g_malloc (msg.msg_controllen); @@ -1403,7 +1407,7 @@ retry: goto abort; } - if (creds && (sk->s_flags & NL_SOCK_PASSCRED)) { + if (out_creds && (sk->s_flags & NL_SOCK_PASSCRED)) { struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg)) { @@ -1411,7 +1415,8 @@ retry: continue; if (cmsg->cmsg_type != SCM_CREDENTIALS) continue; - tmpcreds = nm_memdup (CMSG_DATA (cmsg), sizeof (*tmpcreds)); + memcpy (&tmpcreds, CMSG_DATA (cmsg), sizeof (tmpcreds)); + tmpcreds_has = TRUE; break; } } @@ -1427,6 +1432,8 @@ abort: } *buf = iov.iov_base; - NM_SET_OUT (creds, g_steal_pointer (&tmpcreds)); + if (out_creds && tmpcreds_has) + *out_creds = tmpcreds; + NM_SET_OUT (out_creds_has, tmpcreds_has); return retval; } diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h index 2fbddff4cf..f1f8394052 100644 --- a/src/platform/nm-netlink.h +++ b/src/platform/nm-netlink.h @@ -416,8 +416,11 @@ int nl_socket_add_memberships (struct nl_sock *sk, int group, ...); int nl_connect (struct nl_sock *sk, int protocol); -int nl_recv (struct nl_sock *sk, struct sockaddr_nl *nla, - unsigned char **buf, struct ucred **creds); +int nl_recv (struct nl_sock *sk, + struct sockaddr_nl *nla, + unsigned char **buf, + struct ucred *out_creds, + gboolean *out_creds_has); int nl_send (struct nl_sock *sk, struct nl_msg *msg); |