On Wed, 2007-10-24 at 14:31 -0400, Eamon Walsh wrote: > This patch removes duplication in the AVC netlink code > by introducing helper functions. > > Did some basic testing and confirmed that messages are > received and processed. > > More patches to follow. > > Signed-off-by: Eamon Walsh <ewalsh@xxxxxxxxxxxxx> Merged. However, it occurs to me that this code may yield unaligned accesses (before and after this patch), just like the libsepol policy reading code until recently. > --- > > avc_internal.c | 289 +++++++++++++++++++++------------------------------------ > 1 file changed, 107 insertions(+), 182 deletions(-) > > > Index: libselinux/src/avc_internal.c > =================================================================== > --- libselinux/src/avc_internal.c (revision 2662) > +++ libselinux/src/avc_internal.c (working copy) > @@ -89,221 +89,146 @@ > close(fd); > } > > -int avc_netlink_check_nb(void) > +static int avc_netlink_receive(char *buf, unsigned buflen) > { > int rc; > struct sockaddr_nl nladdr; > socklen_t nladdrlen = sizeof nladdr; > - char buf[1024]; > - struct nlmsghdr *nlh; > + struct nlmsghdr *nlh = (struct nlmsghdr *)buf; > > - while (1) { > - rc = recvfrom(fd, buf, sizeof(buf), 0, > - (struct sockaddr *)&nladdr, &nladdrlen); > - if (rc < 0) { > - if (errno == EINTR) > - continue; > - if (errno != EAGAIN) { > - avc_log("%s: socket error during read: %d\n", > - avc_prefix, errno); > - } else { > - errno = 0; > - rc = 0; > - } > - goto out; > - } > + rc = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&nladdr, > + &nladdrlen); > + if (rc < 0) > + return rc; > > - if (nladdrlen != sizeof nladdr) { > - avc_log > - ("%s: warning: netlink address truncated, len %d?\n", > - avc_prefix, nladdrlen); > - rc = -1; > - goto out; > - } > + if (nladdrlen != sizeof nladdr) { > + avc_log("%s: warning: netlink address truncated, len %d?\n", > + avc_prefix, nladdrlen); > + return -1; > + } > > - if (nladdr.nl_pid) { > - avc_log > - ("%s: warning: received spoofed netlink packet from: %d\n", > - avc_prefix, nladdr.nl_pid); > - continue; > - } > + if (nladdr.nl_pid) { > + avc_log("%s: warning: received spoofed netlink packet from: %d\n", > + avc_prefix, nladdr.nl_pid); > + return -1; > + } > > - if (rc == 0) { > - avc_log("%s: warning: received EOF on socket\n", > - avc_prefix); > - goto out; > - } > + if (rc == 0) { > + avc_log("%s: warning: received EOF on netlink socket\n", > + avc_prefix); > + errno = EBADFD; > + return -1; > + } > > - nlh = (struct nlmsghdr *)buf; > + if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > (unsigned)rc) { > + avc_log("%s: warning: incomplete netlink message\n", > + avc_prefix); > + return -1; > + } > > - if (nlh->nlmsg_flags & MSG_TRUNC > - || nlh->nlmsg_len > (unsigned)rc) { > - avc_log("%s: warning: incomplete netlink message\n", > - avc_prefix); > - goto out; > - } > + return 0; > +} > > - rc = 0; > - switch (nlh->nlmsg_type) { > - case NLMSG_ERROR:{ > - struct nlmsgerr *err = NLMSG_DATA(nlh); > +static int avc_netlink_process(char *buf) > +{ > + int rc; > + struct nlmsghdr *nlh = (struct nlmsghdr *)buf; > > - /* Netlink ack */ > - if (err->error == 0) > - break; > + switch (nlh->nlmsg_type) { > + case NLMSG_ERROR:{ > + struct nlmsgerr *err = NLMSG_DATA(nlh); > > - errno = -err->error; > - avc_log("%s: netlink error: %d\n", avc_prefix, > - errno); > - rc = -1; > - goto out; > - } > + /* Netlink ack */ > + if (err->error == 0) > + break; > > - case SELNL_MSG_SETENFORCE:{ > - struct selnl_msg_setenforce *msg = > - NLMSG_DATA(nlh); > - avc_log > - ("%s: received setenforce notice (enforcing=%d)\n", > - avc_prefix, msg->val); > - avc_enforcing = msg->val; > - if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) { > - avc_log > - ("%s: cache reset returned %d (errno %d)\n", > - avc_prefix, rc, errno); > - goto out; > - } > - break; > - } > + errno = -err->error; > + avc_log("%s: netlink error: %d\n", avc_prefix, errno); > + return -1; > + } > > - case SELNL_MSG_POLICYLOAD:{ > - struct selnl_msg_policyload *msg = > - NLMSG_DATA(nlh); > - avc_log > - ("%s: received policyload notice (seqno=%d)\n", > - avc_prefix, msg->seqno); > - rc = avc_ss_reset(msg->seqno); > - if (rc < 0) { > - avc_log > - ("%s: cache reset returned %d (errno %d)\n", > - avc_prefix, rc, errno); > - goto out; > - } > - break; > - } > + case SELNL_MSG_SETENFORCE:{ > + struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh); > + avc_log("%s: received setenforce notice (enforcing=%d)\n", > + avc_prefix, msg->val); > + avc_enforcing = msg->val; > + if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) { > + avc_log("%s: cache reset returned %d (errno %d)\n", > + avc_prefix, rc, errno); > + return rc; > + } > + break; > + } > > - default: > - avc_log("%s: warning: unknown netlink message %d\n", > - avc_prefix, nlh->nlmsg_type); > + case SELNL_MSG_POLICYLOAD:{ > + struct selnl_msg_policyload *msg = NLMSG_DATA(nlh); > + avc_log("%s: received policyload notice (seqno=%d)\n", > + avc_prefix, msg->seqno); > + rc = avc_ss_reset(msg->seqno); > + if (rc < 0) { > + avc_log("%s: cache reset returned %d (errno %d)\n", > + avc_prefix, rc, errno); > + return rc; > } > + break; > } > - out: > - return rc; > + > + default: > + avc_log("%s: warning: unknown netlink message %d\n", > + avc_prefix, nlh->nlmsg_type); > + } > + return 0; > } > > -/* run routine for the netlink listening thread */ > -void avc_netlink_loop(void) > +int avc_netlink_check_nb(void) > { > - int ret; > - struct sockaddr_nl nladdr; > - socklen_t nladdrlen = sizeof nladdr; > + int rc; > char buf[1024]; > - struct nlmsghdr *nlh; > > while (1) { > - ret = > - recvfrom(fd, buf, sizeof(buf), 0, > - (struct sockaddr *)&nladdr, &nladdrlen); > - if (ret < 0) { > - if (errno == EINTR) > + errno = 0; > + rc = avc_netlink_receive(buf, sizeof(buf)); > + if (rc < 0) { > + if (errno == EWOULDBLOCK) > + return 0; > + if (errno == 0 || errno == EINTR) > continue; > - avc_log("%s: netlink thread: recvfrom: error %d\n", > - avc_prefix, errno); > - goto out; > + else { > + avc_log("%s: netlink recvfrom: error %d\n", > + avc_prefix, errno); > + return rc; > + } > } > > - if (nladdrlen != sizeof nladdr) { > - avc_log > - ("%s: warning: netlink address truncated, len %d?\n", > - avc_prefix, nladdrlen); > - ret = -1; > - goto out; > - } > + (void)avc_netlink_process(buf); > + } > + return 0; > +} > > - if (nladdr.nl_pid) { > - avc_log > - ("%s: warning: received spoofed netlink packet from: %d\n", > - avc_prefix, nladdr.nl_pid); > - continue; > - } > +/* run routine for the netlink listening thread */ > +void avc_netlink_loop(void) > +{ > + int rc; > + char buf[1024]; > > - if (ret == 0) { > - avc_log("%s: netlink thread: received EOF on socket\n", > - avc_prefix); > - goto out; > - } > - > - nlh = (struct nlmsghdr *)buf; > - > - if (nlh->nlmsg_flags & MSG_TRUNC > - || nlh->nlmsg_len > (unsigned)ret) { > - avc_log > - ("%s: netlink thread: incomplete netlink message\n", > - avc_prefix); > - goto out; > - } > - > - switch (nlh->nlmsg_type) { > - case NLMSG_ERROR:{ > - struct nlmsgerr *err = NLMSG_DATA(nlh); > - > - /* Netlink ack */ > - if (err->error == 0) > - break; > - > - avc_log("%s: netlink thread: msg: error %d\n", > - avc_prefix, -err->error); > - goto out; > - } > - > - case SELNL_MSG_SETENFORCE:{ > - struct selnl_msg_setenforce *msg = > - NLMSG_DATA(nlh); > - avc_log > - ("%s: received setenforce notice (enforcing=%d)\n", > - avc_prefix, msg->val); > - avc_enforcing = msg->val; > - if (avc_enforcing && (ret = avc_ss_reset(0)) < 0) { > - avc_log > - ("%s: cache reset returned %d (errno %d)\n", > - avc_prefix, ret, errno); > - goto out; > - } > + while (1) { > + errno = 0; > + rc = avc_netlink_receive(buf, sizeof(buf)); > + if (rc < 0) { > + if (errno == 0 || errno == EINTR) > + continue; > + else { > + avc_log("%s: netlink recvfrom: error %d\n", > + avc_prefix, errno); > break; > } > - > - case SELNL_MSG_POLICYLOAD:{ > - struct selnl_msg_policyload *msg = > - NLMSG_DATA(nlh); > - avc_log > - ("%s: received policyload notice (seqno=%d)\n", > - avc_prefix, msg->seqno); > - ret = avc_ss_reset(msg->seqno); > - if (ret < 0) { > - avc_log > - ("%s: netlink thread: cache reset returned %d (errno %d)\n", > - avc_prefix, ret, errno); > - goto out; > - } > - break; > - } > - > - default: > - avc_log > - ("%s: netlink thread: warning: unknown msg type %d\n", > - avc_prefix, nlh->nlmsg_type); > } > + > + rc = avc_netlink_process(buf); > + if (rc < 0) > + break; > } > - out: > + > close(fd); > avc_netlink_trouble = 1; > avc_log("%s: netlink thread: errors encountered, terminating\n", > -- Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with the words "unsubscribe selinux" without quotes as the message.