All of lore.kernel.org
 help / color / mirror / Atom feed
From: KaiGai Kohei <kaigai@ak.jp.nec.com>
To: Eamon Walsh <ewalsh@tycho.nsa.gov>
Cc: selinux@tycho.nsa.gov, Joshua Brindle <jbrindle@tresys.com>
Subject: Re: [PATCH] libselinux: fix avc_netlink_loop() error caused by nonblocking mode.
Date: Wed, 03 Mar 2010 09:30:18 +0900	[thread overview]
Message-ID: <4B8DAD9A.5020200@ak.jp.nec.com> (raw)
In-Reply-To: <4B8D4AED.80203@tycho.nsa.gov>

[-- Attachment #1: Type: text/plain, Size: 5706 bytes --]

(2010/03/03 2:29), Eamon Walsh wrote:
> On 03/01/2010 09:48 PM, KaiGai Kohei wrote:
>> (2010/02/27 5:56), Eamon Walsh wrote:
>>
>>> 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.
>>>
>> Apart from this design is sane, the libselinux allows applications to
>> call avc_netlink_check_nb() directly.
>> If we call the function although its worker thread calls avc_netlink_loop(),
>> the invocation of avc_netlink_check_nb() can be blocked, because it
>> assumes the internal netlink socket is non-blocking mode.
>> (Of course, we will not see the matter in most of sane applications.)
>>
>> I think a better approach is to put select(2) with zero or infinite
>> timeout just before avc_netlink_receive() calls to check whether the
>> unread message is in the netlink socket, or not.
>> And the 'blocking' argument of avc_netlink_open() shall be obsoleted,
>> because this design makes nonsense whether the socket has O_NONBLOCK
>> flag, or not.
>>
> 
> OK I see your point. How about the following:
> 
> 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.

It seems to me ok basically.

It is just my preference. Can you move the poll(2) at the head of
the avc_netlink_receive() call, like as the attachment?
How should I say...it seems to me itchy to change non-blocking mode
into blocking mode implicitly at avc_netlink_loop(), although we can
specify the mode at creation time (avc_netlink_open()).

Thanks,

> Signed-off-by: Eamon Walsh<ewalsh@tycho.nsa.gov>
> --
> 
>   man/man3/avc_netlink_loop.3 |   11 +++--------
>   src/avc.c                   |    2 +-
>   src/avc_internal.c          |   13 +++++++++++++
>   3 files changed, 17 insertions(+), 9 deletions(-)
> 
> 
> diff --git a/libselinux/man/man3/avc_netlink_loop.3 b/libselinux/man/man3/avc_netlink_loop.3
> index 67df6e4..785be4c 100644
> --- a/libselinux/man/man3/avc_netlink_loop.3
> +++ b/libselinux/man/man3/avc_netlink_loop.3
> @@ -41,12 +41,9 @@ descriptor is stored internally; use
>   .BR avc_netlink_acquire_fd (3)
>   to take ownership of it in application code.  The
>   .I blocking
> -argument specifies whether read operations on the socket will block.
> +argument controls whether the O_NONBLOCK flag is set on the socket descriptor.
>   .BR avc_open (3)
> -calls this function internally, specifying non-blocking behavior (unless
> -threading callbacks were explicitly set using the deprecated
> -.BR avc_init (3)
> -interface, in which case blocking behavior is set).
> +calls this function internally, specifying non-blocking behavior.
> 
>   .B avc_netlink_close
>   closes the netlink socket.  This function is called automatically by
> @@ -66,9 +63,7 @@ checks the netlink socket for pending messages and processes them.
>   Callbacks for policyload and enforcing changes will be called;
>   see
>   .BR selinux_set_callback (3).
> -This function does not block unless
> -.BR avc_netlink_open (3)
> -specified blocking behavior.
> +This function does not block.
> 
>   .B avc_netlink_loop
>   enters a loop blocking on the netlink socket and processing messages as they
> diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c
> index 881b915..5c8def0 100644
> --- a/libselinux/src/avc.c
> +++ b/libselinux/src/avc.c
> @@ -222,7 +222,7 @@ int avc_init(const char *prefix,
>   		avc_enforcing = rc;
>   	}
> 
> -	rc = avc_netlink_open(avc_using_threads);
> +	rc = avc_netlink_open(0);
>   	if (rc<  0) {
>   		avc_log(SELINUX_ERROR,
>   			"%s:  can't open netlink socket: %d (%s)\n",
> diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c
> index 8372f52..7a39c61 100644
> --- a/libselinux/src/avc_internal.c
> +++ b/libselinux/src/avc_internal.c
> @@ -15,6 +15,7 @@
>   #include<unistd.h>
>   #include<fcntl.h>
>   #include<string.h>
> +#include<poll.h>
>   #include<sys/types.h>
>   #include<sys/socket.h>
>   #include<linux/types.h>
> @@ -205,8 +206,18 @@ int avc_netlink_check_nb(void)
>   {
>   	int rc;
>   	char buf[1024] __attribute__ ((aligned));
> +	struct pollfd pfd = { fd, POLLIN | POLLPRI, 0 };
> 
>   	while (1) {
> +		rc = poll(&pfd, 1, 0);
> +		if (rc == 0)
> +			return 0;
> +		if (rc<  0) {
> +			avc_log(SELINUX_ERROR, "%s:  netlink poll: error %d\n",
> +				avc_prefix, errno);
> +			return rc;
> +		}
> +
>   		errno = 0;
>   		rc = avc_netlink_receive(buf, sizeof(buf));
>   		if (rc<  0) {
> @@ -233,6 +244,8 @@ void avc_netlink_loop(void)
>   	int rc;
>   	char buf[1024] __attribute__ ((aligned));
> 
> +	fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&  ~O_NONBLOCK);
> +
>   	while (1) {
>   		errno = 0;
>   		rc = avc_netlink_receive(buf, sizeof(buf));
> 
> 
> 


-- 
KaiGai Kohei <kaigai@ak.jp.nec.com>

[-- Attachment #2: avc-netlink-poll.2.patch --]
[-- Type: application/octect-stream, Size: 3488 bytes --]

  reply	other threads:[~2010-03-03  0:30 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-03  6:19 avc_open() and netlink_loop() KaiGai Kohei
2010-02-26 19:14 ` Eamon Walsh
2010-02-26 20:49   ` Eamon Walsh
2010-02-26 20:56     ` [PATCH] libselinux: fix avc_netlink_loop() error caused by nonblocking mode Eamon Walsh
2010-03-02  2:48       ` KaiGai Kohei
2010-03-02 17:29         ` Eamon Walsh
2010-03-03  0:30           ` KaiGai Kohei [this message]
2010-03-08 23:19             ` Eamon Walsh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B8DAD9A.5020200@ak.jp.nec.com \
    --to=kaigai@ak.jp.nec.com \
    --cc=ewalsh@tycho.nsa.gov \
    --cc=jbrindle@tresys.com \
    --cc=selinux@tycho.nsa.gov \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.