Changeset 61d005b739f34b9471244428769a156d57358c9c

Show
Ignore:
Timestamp:
03/08/10 17:15:53 (5 months ago)
Author:
Eamon Walsh <ewalsh@tycho.nsa.gov>
Committer:
Eamon Walsh <ewalsh@tycho.nsa.gov> 1268090153 -0500
Parent:

[a73f32c3e35093e5eaf9820954e56fdc1b327e8b]

Message:

libselinux: fix avc_netlink_loop() error caused by nonblocking mode.

avc_open() creates the netlink socket in nonblocking mode. If the
application later takes control of the netlink socket with
avc_netlink_acquire_fd() and then calls avc_netlink_loop(), it
will fail with EWOULDBLOCK.

To remedy this, remove the O_NONBLOCK flag from the netlink socket
at the start of avc_netlink_loop(). Also, with this fix, there is
no need for avc_open() to ever create a blocking socket, so change
that and update the man page.

-v2: use poll() in avc_netlink_check_nb(). This makes both
avc_netlink_loop() and avc_netlink_check_nb() independent of the
O_NONBLOCK flag.

-v3: move poll() to avc_receive() internal function; patch by
KaiGai? Kohei <kaigai@kaigai.gr.jp>

Signed-off-by: Eamon Walsh <ewalsh@tycho.nsa.gov>

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • libselinux/man/man3/avc_netlink_loop.3

    r318748d r61d005b  
    4242to take ownership of it in application code.  The 
    4343.I blocking 
    44 argument specifies whether read operations on the socket will block
     44argument controls whether the O_NONBLOCK flag is set on the socket descriptor
    4545.BR avc_open (3) 
    46 calls this function internally, specifying non-blocking behavior (unless 
    47 threading callbacks were explicitly set using the deprecated 
    48 .BR avc_init (3) 
    49 interface, in which case blocking behavior is set). 
     46calls this function internally, specifying non-blocking behavior. 
    5047 
    5148.B avc_netlink_close 
     
    6764see 
    6865.BR selinux_set_callback (3). 
    69 This function does not block unless 
    70 .BR avc_netlink_open (3) 
    71 specified blocking behavior. 
     66This function does not block. 
    7267 
    7368.B avc_netlink_loop 
  • libselinux/src/avc.c

    r0fc6c77 r61d005b  
    223223        } 
    224224 
    225         rc = avc_netlink_open(avc_using_threads); 
     225        rc = avc_netlink_open(0); 
    226226        if (rc < 0) { 
    227227                avc_log(SELINUX_ERROR, 
  • libselinux/src/avc_internal.c

    r318748d r61d005b  
    1616#include <fcntl.h> 
    1717#include <string.h> 
     18#include <poll.h> 
    1819#include <sys/types.h> 
    1920#include <sys/socket.h> 
     
    9394} 
    9495 
    95 static int avc_netlink_receive(char *buf, unsigned buflen) 
    96 
    97         int rc; 
     96static int avc_netlink_receive(char *buf, unsigned buflen, int blocking) 
     97
     98        int rc; 
     99        struct pollfd pfd = { fd, POLLIN | POLLPRI, 0 }; 
    98100        struct sockaddr_nl nladdr; 
    99101        socklen_t nladdrlen = sizeof nladdr; 
    100102        struct nlmsghdr *nlh = (struct nlmsghdr *)buf; 
     103 
     104        rc = poll(&pfd, 1, (blocking ? -1 : 0)); 
     105 
     106        if (rc == 0 && !blocking) { 
     107                errno = EWOULDBLOCK; 
     108                return -1; 
     109        } 
     110        else if (rc < 1) { 
     111                avc_log(SELINUX_ERROR, "%s:  netlink poll: error %d\n", 
     112                        avc_prefix, errno); 
     113                return rc; 
     114        } 
    101115 
    102116        rc = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&nladdr, 
     
    209223        while (1) { 
    210224                errno = 0; 
    211                 rc = avc_netlink_receive(buf, sizeof(buf)); 
     225                rc = avc_netlink_receive(buf, sizeof(buf), 0); 
    212226                if (rc < 0) { 
    213227                        if (errno == EWOULDBLOCK) 
     
    236250        while (1) { 
    237251                errno = 0; 
    238                 rc = avc_netlink_receive(buf, sizeof(buf)); 
     252                rc = avc_netlink_receive(buf, sizeof(buf), 1); 
    239253                if (rc < 0) { 
    240254                        if (errno == 0 || errno == EINTR)