LWN.net Logo

"Stable" kernel 2.6.25.7 released

"Stable" kernel 2.6.25.7 released

Posted Jun 17, 2008 16:10 UTC (Tue) by mhalcrow (guest, #17371)
In reply to: "Stable" kernel 2.6.25.7 released by spender
Parent article: Stable kernel 2.6.25.7 released

> We also have vendorsec sitting on a patch from Serge Hallyn fixing the
> vulnerability in TPM i alluded to in my previous posting.  One week on
> a one-line fix which has yet to make it upstream (which Serge requested
> be fixed ASAP).

rw_verify_area() makes certain that the size_t value fits in a signed
int, so this is actually not a problem that requires a security update
in the kernels shipping the driver. It is, at worst, sloppy code that
should be fixed in the next regular release.


(Log in to post comments)

"Stable" kernel 2.6.25.7 released

Posted Jun 17, 2008 16:49 UTC (Tue) by PaXTeam (subscriber, #24616) [Link]

not quite. on 64 bit archs

  count = (size_t)(2^32-1)

would pass the

  (ssize_t) count < 0

check whereas

  int in_size = size

would still make it -1 and trigger the bug. in other words, you had two bugs, one of using a
signed type for size and second, a truncation.

"Stable" kernel 2.6.25.7 released

Posted Jun 17, 2008 17:53 UTC (Tue) by mhalcrow (guest, #17371) [Link]

> not quite. on 64 bit archs
>
>  count = (size_t)(2^32-1)
>
> would pass the
>
>  (ssize_t) count < 0
>
> check whereas
>
>  int in_size = size
>
> would still make it -1 and trigger the bug.

This is the code:

---
#define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)

int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
)
{
        struct inode *inode;
        loff_t pos;

        inode = file->f_path.dentry->d_inode;
        if (unlikely((ssize_t) count < 0))
                goto Einval;
        pos = *ppos;
        if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
                goto Einval;

        if (unlikely(inode->i_flock && mandatory_lock(inode))) {
                int retval = locks_mandatory_area(
                        read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WR
ITE,
                        inode, file, pos, count);
                if (retval < 0)
                        return retval;
        }
        return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;

Einval:
        return -EINVAL;
}
---

This function pegs the value returned to MAX_RW_COUNT, which is at most 0x7FFFFFFF (it will
actually be reduced to a page boundary). If count = 0xFFFFFFFF, then 0xFFFFFFFF > 0x7FFFFFFF,
so 0x7FFFFFFF is the largest value that can be returned from this function. This is the value
that gets passed to tpm_write() as a size_t data type (see vfs_write()).

"Stable" kernel 2.6.25.7 released

Posted Jun 17, 2008 19:38 UTC (Tue) by PaXTeam (subscriber, #24616) [Link]

thanks, i missed the limiting at the end. still, this pattern is dangerous, someone had better
audit the code for it.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds