Changeset 61d005b739f34b9471244428769a156d57358c9c
- 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
| r318748d |
r61d005b |
|
| 42 | 42 | to take ownership of it in application code. The |
|---|
| 43 | 43 | .I blocking |
|---|
| 44 | | argument specifies whether read operations on the socket will block. |
|---|
| | 44 | argument controls whether the O_NONBLOCK flag is set on the socket descriptor. |
|---|
| 45 | 45 | .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). |
|---|
| | 46 | calls this function internally, specifying non-blocking behavior. |
|---|
| 50 | 47 | |
|---|
| 51 | 48 | .B avc_netlink_close |
|---|
| … | … | |
| 67 | 64 | see |
|---|
| 68 | 65 | .BR selinux_set_callback (3). |
|---|
| 69 | | This function does not block unless |
|---|
| 70 | | .BR avc_netlink_open (3) |
|---|
| 71 | | specified blocking behavior. |
|---|
| | 66 | This function does not block. |
|---|
| 72 | 67 | |
|---|
| 73 | 68 | .B avc_netlink_loop |
|---|
| r0fc6c77 |
r61d005b |
|
| 223 | 223 | } |
|---|
| 224 | 224 | |
|---|
| 225 | | rc = avc_netlink_open(avc_using_threads); |
|---|
| | 225 | rc = avc_netlink_open(0); |
|---|
| 226 | 226 | if (rc < 0) { |
|---|
| 227 | 227 | avc_log(SELINUX_ERROR, |
|---|
| r318748d |
r61d005b |
|
| 16 | 16 | #include <fcntl.h> |
|---|
| 17 | 17 | #include <string.h> |
|---|
| | 18 | #include <poll.h> |
|---|
| 18 | 19 | #include <sys/types.h> |
|---|
| 19 | 20 | #include <sys/socket.h> |
|---|
| … | … | |
| 93 | 94 | } |
|---|
| 94 | 95 | |
|---|
| 95 | | static int avc_netlink_receive(char *buf, unsigned buflen) |
|---|
| 96 | | { |
|---|
| 97 | | int rc; |
|---|
| | 96 | static int avc_netlink_receive(char *buf, unsigned buflen, int blocking) |
|---|
| | 97 | { |
|---|
| | 98 | int rc; |
|---|
| | 99 | struct pollfd pfd = { fd, POLLIN | POLLPRI, 0 }; |
|---|
| 98 | 100 | struct sockaddr_nl nladdr; |
|---|
| 99 | 101 | socklen_t nladdrlen = sizeof nladdr; |
|---|
| 100 | 102 | 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 | } |
|---|
| 101 | 115 | |
|---|
| 102 | 116 | rc = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&nladdr, |
|---|
| … | … | |
| 209 | 223 | while (1) { |
|---|
| 210 | 224 | errno = 0; |
|---|
| 211 | | rc = avc_netlink_receive(buf, sizeof(buf)); |
|---|
| | 225 | rc = avc_netlink_receive(buf, sizeof(buf), 0); |
|---|
| 212 | 226 | if (rc < 0) { |
|---|
| 213 | 227 | if (errno == EWOULDBLOCK) |
|---|
| … | … | |
| 236 | 250 | while (1) { |
|---|
| 237 | 251 | errno = 0; |
|---|
| 238 | | rc = avc_netlink_receive(buf, sizeof(buf)); |
|---|
| | 252 | rc = avc_netlink_receive(buf, sizeof(buf), 1); |
|---|
| 239 | 253 | if (rc < 0) { |
|---|
| 240 | 254 | if (errno == 0 || errno == EINTR) |
|---|