[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: O_NONBLOCK problems with an offline file
From: |
Paul Eggert |
Subject: |
Re: O_NONBLOCK problems with an offline file |
Date: |
Mon, 25 Feb 2013 11:31:58 -0800 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130219 Thunderbird/17.0.3 |
On 02/25/13 05:20, Vitezslav Cizek wrote:
> Dropping the O_NONBLOCK flag to open() solves the issue.
Doing that would have bad effects elsewhere, as it would allow
some denial of service attacks.
> A different fix was introduced to tar - dropping the flag with fcntl()
> after a subsequent read/write returns EAGAIN.
OK, I pushed the following patch into the gzip master; can
you please give it a try? Thanks.
Won't you folks have similar problems with other GNU utilities?
GNU 'touch', for example. Can you propose patches for all
these? Just look for O_NONBLOCK in the source code.
>From 14e047601b273b3a5d436a3f360d7c4b71c5ebe5 Mon Sep 17 00:00:00 2001
From: Paul Eggert <address@hidden>
Date: Mon, 25 Feb 2013 11:24:14 -0800
Subject: [PATCH] gzip: port to DMF file systems
* util.c (read_buffer): When reading a file with O_NONBLOCK, if
the read fails with errno==EAGAIN, clear O_NONBLOCK and try again.
Problem reported by Vitezslav Cizek in
<http://lists.gnu.org/archive/html/bug-gzip/2013-02/msg00030.html>.
---
util.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/util.c b/util.c
index cfd4e6c..c4c7f70 100644
--- a/util.c
+++ b/util.c
@@ -132,16 +132,35 @@ int fill_inbuf(eof_ok)
}
/* Like the standard read function, except do not attempt to read more
- than SSIZE_MAX bytes at a time. */
+ than INT_MAX bytes at a time. */
int
read_buffer (fd, buf, cnt)
int fd;
voidp buf;
unsigned int cnt;
{
+ int len;
if (INT_MAX < cnt)
cnt = INT_MAX;
- return read (fd, buf, cnt);
+ len = read (fd, buf, cnt);
+
+#if defined F_SETFL && O_NONBLOCK && defined EAGAIN
+ /* Input files are opened O_NONBLOCK for security reasons. On some
+ file systems this can cause read to fail with errno == EAGAIN. */
+ if (len < 0 && errno == EAGAIN)
+ {
+ int flags = fcntl (fd, F_GETFL);
+ if (0 <= flags)
+ {
+ if (! (flags & O_NONBLOCK))
+ errno = EAGAIN;
+ else if (fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
+ len = read (fd, buf, cnt);
+ }
+ }
+#endif
+
+ return len;
}
/* Likewise for 'write'. */
--
1.7.11.7