From: Al Viro <viro@ZenIV.linux.org.uk>
To: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>,
linux-fsdevel@vger.kernel.org, fengguang.wu@intel.com,
aneesh.kumar@linux.vnet.ibm.com, jvrao@linux.vnet.ibm.com
Subject: Re: [PATCH] Typecasting required for comparing unlike datatypes
Date: Wed, 15 Dec 2010 09:50:24 +0000 [thread overview]
Message-ID: <20101215095024.GH19804@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20101210171851.8f83f485.kamezawa.hiroyu@jp.fujitsu.com>
On Fri, Dec 10, 2010 at 05:18:51PM +0900, KAMEZAWA Hiroyuki wrote:
> On Wed, 8 Dec 2010 18:25:00 +0530
> Harsh Prateek Bora <harsh@linux.vnet.ibm.com> wrote:
>
> > The existing code causes the if condition to pass when it should fail
> > on a *64-bit kernel* because of implicit data type conversions. It can
> > be observed by passing pos = -1 and count = some positive number.
> > This results in function returning EOVERFLOW instead of EINVAL.
> >
> > With this patch, the function returns EINVAL when pos is -1 and count
> > is a positive number. This can be tested by calling sendfile with
> > offset = -1 and count = some positive number on a 64-bit kernel.
> >
> > Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
>
> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
>
> I'm sorry for annoying you.
NAK. Look at what's getting done there; this check is the _only_ place
in function that uses count, it is constantly false if count is zero
_and_ we have only one caller that passes non-zero. Moreover, in case of
count being zero we ignore offset as well.
Obvious things to do:
a) take the check in question into the only caller that would
pass non-zero count (i.e. rw_verify_area())
b) lose the second and the third arguments of __negative_fpos_check()
c) sort out what the hell should be done in that place.
Note that current logics is very convoluted. First of all, we rely on
loff_t being long long in the kernel and size_t being not bigger than
unsigned long long. See ((loff_t)(pos + count) < 0) in there - if count
gets wider than pos, we suddenly get all kinds of odd crap.
That's OK; if we run into ports with size_t wider than 64 bits, we'll have
more trouble anyway.
So what we have for signed offset case is pos >= 0, count <= max loff_t - pos.
Fair enough. For unsigned offset case it's more interesting - we want to
allow pos < 0, and we just want to prohibit wraparounds from negative to
positive. IOW, it's pos >= 0 || count < -pos; note that we already have
count <= max ssize_t, which we assume to be no more than max loff_t.
So what we need is this:
if (unlikely(pos < 0)) {
if it's signed
-EINVAL
if (count >= -pos) /* both values are in 0..LLONG_MAX */
-EOVERFLOW
} else if (unlikely((loff_t)(pos + count) < 0)) {
if it's signed
-EINVAL
}
and we are done with that. IOW, how about the patch below?
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
diff --git a/fs/read_write.c b/fs/read_write.c
index 5d431ba..5520f8a 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -30,18 +30,9 @@ const struct file_operations generic_ro_fops = {
EXPORT_SYMBOL(generic_ro_fops);
-static int
-__negative_fpos_check(struct file *file, loff_t pos, size_t count)
+static inline int unsigned_offsets(struct file *file)
{
- /*
- * pos or pos+count is negative here, check overflow.
- * too big "count" will be caught in rw_verify_area().
- */
- if ((pos < 0) && (pos + count < pos))
- return -EOVERFLOW;
- if (file->f_mode & FMODE_UNSIGNED_OFFSET)
- return 0;
- return -EINVAL;
+ return file->f_mode & FMODE_UNSIGNED_OFFSET;
}
/**
@@ -75,7 +66,7 @@ generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin)
break;
}
- if (offset < 0 && __negative_fpos_check(file, offset, 0))
+ if (offset < 0 && !unsigned_offsets(file))
return -EINVAL;
if (offset > inode->i_sb->s_maxbytes)
return -EINVAL;
@@ -152,7 +143,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
offset += file->f_pos;
}
retval = -EINVAL;
- if (offset >= 0 || !__negative_fpos_check(file, offset, 0)) {
+ if (offset >= 0 || unsigned_offsets(file)) {
if (offset != file->f_pos) {
file->f_pos = offset;
file->f_version = 0;
@@ -252,9 +243,13 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
if (unlikely((ssize_t) count < 0))
return retval;
pos = *ppos;
- if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) {
- retval = __negative_fpos_check(file, pos, count);
- if (retval)
+ if (unlikely(pos < 0)) {
+ if (!unsigned_offsets(file))
+ return retval;
+ if (count >= -pos) /* both values are in 0..LLONG_MAX */
+ return -EOVERFLOW;
+ } else if (unlikely((loff_t) (pos + count) < 0)) {
+ if (!unsigned_offsets(file))
return retval;
}
next prev parent reply other threads:[~2010-12-15 9:50 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-08 12:55 [PATCH] Typecasting required for comparing unlike datatypes Harsh Prateek Bora
2010-12-09 18:32 ` Harsh Bora
2010-12-10 0:06 ` KAMEZAWA Hiroyuki
2010-12-10 0:53 ` KAMEZAWA Hiroyuki
2010-12-10 6:39 ` Harsh Bora
2010-12-10 7:01 ` KAMEZAWA Hiroyuki
2010-12-10 7:18 ` Harsh Bora
2010-12-10 7:59 ` KAMEZAWA Hiroyuki
2010-12-10 8:13 ` Harsh Bora
2010-12-10 8:20 ` KAMEZAWA Hiroyuki
2010-12-10 8:18 ` KAMEZAWA Hiroyuki
2010-12-10 8:31 ` Harsh Bora
2010-12-15 9:50 ` Al Viro [this message]
2010-12-16 0:24 ` KAMEZAWA Hiroyuki
2010-12-19 7:02 ` Harsh Bora
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=20101215095024.GH19804@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=aneesh.kumar@linux.vnet.ibm.com \
--cc=fengguang.wu@intel.com \
--cc=harsh@linux.vnet.ibm.com \
--cc=jvrao@linux.vnet.ibm.com \
--cc=kamezawa.hiroyu@jp.fujitsu.com \
--cc=linux-fsdevel@vger.kernel.org \
/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.