[systemd-commits] 2 commits - src/libsystemd src/libsystemd-network

Tom Gundersen tomegun at kemper.freedesktop.org
Thu Apr 10 15:51:52 PDT 2014


 src/libsystemd-network/sd-dhcp-client.c |    6 ++-
 src/libsystemd/sd-rtnl/rtnl-message.c   |   49 +++++++++++++++++++++++---------
 src/libsystemd/sd-rtnl/sd-rtnl.c        |    5 ++-
 3 files changed, 44 insertions(+), 16 deletions(-)

New commits:
commit 48a4612e6b67ae81b93ee8e8a4b3f8efa5324270
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri Apr 11 00:51:55 2014 +0200

    sd-dhcp-client: recevie_message - verify cmsg_len before reading

diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index da41c47..392e294 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1124,8 +1124,10 @@ static int client_receive_message_raw(sd_event_source *s, int fd,
                 return 0;
 
         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
-                if (cmsg->cmsg_level == SOL_PACKET && cmsg->cmsg_type == PACKET_AUXDATA) {
-                        struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
+                if (cmsg->cmsg_level == SOL_PACKET &&
+                    cmsg->cmsg_type == PACKET_AUXDATA &&
+                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
+                        struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
 
                         checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
                         break;

commit bc078e7163a826126e9ba03934978f510e9ef9e5
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri Apr 11 00:04:39 2014 +0200

    sd-rtnl: use SO_PASSCRED
    
    This unifies the socket handling with other sd-* libraries.

diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index edf5672..c9f3487 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -1019,12 +1019,17 @@ int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
  */
 int socket_read_message(sd_rtnl *rtnl) {
         _cleanup_free_ void *buffer = NULL;
+        uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
+        struct iovec iov = {};
+        struct msghdr msg = {
+                .msg_iov = &iov,
+                .msg_iovlen = 1,
+                .msg_control = cred_buffer,
+                .msg_controllen = sizeof(cred_buffer),
+        };
+        struct cmsghdr *cmsg;
+        bool auth = false;
         struct nlmsghdr *new_msg;
-        union {
-                struct sockaddr sa;
-                struct sockaddr_nl nl;
-        } addr;
-        socklen_t addr_len = sizeof(addr);
         size_t need, len;
         int r, ret = 0;
 
@@ -1038,19 +1043,37 @@ int socket_read_message(sd_rtnl *rtnl) {
         if (!buffer)
                 return -ENOMEM;
 
-        r = recvfrom(rtnl->fd, buffer, need, 0, &addr.sa, &addr_len);
+        iov.iov_base = buffer;
+        iov.iov_len = need;
+
+        r = recvmsg(rtnl->fd, &msg, 0);
         if (r < 0)
-                return (errno == EAGAIN) ? 0 : -errno; /* no data */
+                /* no data */
+                return (errno == EAGAIN) ? 0 : -errno;
         else if (r == 0)
-                return -ECONNRESET; /* connection was closed by the kernel */
-        else if (addr_len != sizeof(addr.nl) ||
-                        addr.nl.nl_family != AF_NETLINK)
-                return -EIO; /* not a netlink message */
-        else if (addr.nl.nl_pid != 0)
-                return 0; /* not from the kernel */
+                /* connection was closed by the kernel */
+                return -ECONNRESET;
         else
                 len = (size_t)r;
 
+        for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+                if (cmsg->cmsg_level == SOL_SOCKET &&
+                    cmsg->cmsg_type == SCM_CREDENTIALS &&
+                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+                        struct ucred *ucred = (void *)CMSG_DATA(cmsg);
+
+                        /* from the kernel */
+                        if (ucred->uid == 0 && ucred->pid == 0) {
+                                auth = true;
+                                break;
+                        }
+                }
+        }
+
+        if (!auth)
+                /* not from the kernel, ignore */
+                return 0;
+
         for (new_msg = buffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
                 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
                 const NLType *nl_type;
diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c
index 816018a..367f165 100644
--- a/src/libsystemd/sd-rtnl/sd-rtnl.c
+++ b/src/libsystemd/sd-rtnl/sd-rtnl.c
@@ -72,7 +72,7 @@ static bool rtnl_pid_changed(sd_rtnl *rtnl) {
 int sd_rtnl_open(sd_rtnl **ret, uint32_t groups) {
         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
         socklen_t addrlen;
-        int r;
+        int r, one = 1;
 
         assert_return(ret, -EINVAL);
 
@@ -84,6 +84,9 @@ int sd_rtnl_open(sd_rtnl **ret, uint32_t groups) {
         if (rtnl->fd < 0)
                 return -errno;
 
+        if (setsockopt(rtnl->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0)
+                return -errno;
+
         rtnl->sockaddr.nl.nl_groups = groups;
 
         addrlen = sizeof(rtnl->sockaddr);



More information about the systemd-commits mailing list