From: Harsh Bora <harsh@linux.vnet.ibm.com>
To: Al Viro <viro@ZenIV.linux.org.uk>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.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: Sun, 19 Dec 2010 12:32:27 +0530 [thread overview]
Message-ID: <4D0DAE03.8000004@linux.vnet.ibm.com> (raw)
In-Reply-To: <20101216092422.f0db600c.kamezawa.hiroyu@jp.fujitsu.com>
On 12/16/2010 05:54 AM, KAMEZAWA Hiroyuki wrote:
> On Wed, 15 Dec 2010 09:50:24 +0000
> Al Viro<viro@ZenIV.linux.org.uk> wrote:
>
>> 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>
>
> This seems much easier to read. thank you.
>
> Acked-by: KAMEZAWA Hiroyuki<kamezawa.hiroyu@jp.fujitsu.com>
>
> and sorry for my 1st implemenation.
>
>> ---
>> 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 */
Yeah .. thats a better reorg of code, however I am not sure if we need a
typecast above for future portability reasons (as count and pos can be
of diff width somewhere/sometime). Also, I personally would like to keep
the function name as is_offset_unsigned().
Anyways, +1 for ACK !
Regards,
Harsh
>> + return -EOVERFLOW;
>> + } else if (unlikely((loff_t) (pos + count)< 0)) {
>> + if (!unsigned_offsets(file))
>> return retval;
>> }
>>
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
prev parent reply other threads:[~2010-12-19 7:02 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
2010-12-16 0:24 ` KAMEZAWA Hiroyuki
2010-12-19 7:02 ` Harsh Bora [this message]
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=4D0DAE03.8000004@linux.vnet.ibm.com \
--to=harsh@linux.vnet.ibm.com \
--cc=aneesh.kumar@linux.vnet.ibm.com \
--cc=fengguang.wu@intel.com \
--cc=jvrao@linux.vnet.ibm.com \
--cc=kamezawa.hiroyu@jp.fujitsu.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=viro@ZenIV.linux.org.uk \
/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.