Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=647bd61a5f3a51a38c670f91af9d861ad66149a3
Commit:     647bd61a5f3a51a38c670f91af9d861ad66149a3
Parent:     9c1729db3e6d738f872bcb090212af00473bf666
Author:     Cyrill Gorcunov <[EMAIL PROTECTED]>
AuthorDate: Sun Jul 15 23:39:47 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Mon Jul 16 09:05:41 2007 -0700

    UDF: check for allocated memory for inode data
    
    This patch adds checking for granted memory while filling up inode data to
    prevent possible NULL pointer usage.  If there is not enough memory to fill
    inode data we just mark it as "bad".  Also some whitespace cleanup.
    
    Signed-off-by: Cyrill Gorcunov <[EMAIL PROTECTED]>
    Cc: Jan Kara <[EMAIL PROTECTED]>
    Cc: Christoph Hellwig <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/udf/inode.c |   51 +++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index bf7de0b..5b82e48 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -49,6 +49,7 @@ MODULE_LICENSE("GPL");
 static mode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
+static int udf_alloc_i_data(struct inode *inode, size_t size);
 static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
        long *, int *);
 static int8_t udf_insert_aext(struct inode *, struct extent_position,
@@ -734,7 +735,7 @@ static void udf_split_extents(struct inode *inode, int *c, 
int offset, int newbl
                        (*c) ++;
                        (*endnum) ++;
                }
-               
+
                laarr[curr].extLocation.logicalBlockNum = newblocknum;
                if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
                        laarr[curr].extLocation.partitionReferenceNum =
@@ -836,7 +837,7 @@ static void udf_prealloc_extents(struct inode *inode, int 
c, int lastblock,
                                {
                                        numalloc -= elen;
                                        if (*endnum > (i+1))
-                                               memmove(&laarr[i], &laarr[i+1], 
+                                               memmove(&laarr[i], &laarr[i+1],
                                                        sizeof(long_ad) * 
(*endnum - (i+1)));
                                        i --;
                                        (*endnum) --;
@@ -1024,7 +1025,7 @@ void udf_truncate(struct inode * inode)
        {
                block_truncate_page(inode->i_mapping, inode->i_size, 
udf_get_block);
                udf_truncate_extents(inode);
-       }       
+       }
 
        inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
        if (IS_SYNC(inode))
@@ -1087,10 +1088,10 @@ __udf_read_inode(struct inode *inode)
                        {
                                kernel_lb_addr loc;
                                ie = (struct indirectEntry *)ibh->b_data;
-       
+
                                loc = lelb_to_cpu(ie->indirectICB.extLocation);
-       
-                               if (ie->indirectICB.extLength && 
+
+                               if (ie->indirectICB.extLength &&
                                        (nbh = udf_read_ptagged(inode->i_sb, 
loc, 0, &ident)))
                                {
                                        if (ident == TAG_IDENT_FE ||
@@ -1156,14 +1157,22 @@ static void udf_fill_inode(struct inode *inode, struct 
buffer_head *bh)
        {
                UDF_I_EFE(inode) = 1;
                UDF_I_USE(inode) = 0;
-               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - 
sizeof(struct extendedFileEntry), GFP_KERNEL);
+               if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - 
sizeof(struct extendedFileEntry)))
+               {
+                       make_bad_inode(inode);
+                       return;
+               }
                memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct 
extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct 
extendedFileEntry));
        }
        else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
        {
                UDF_I_EFE(inode) = 0;
                UDF_I_USE(inode) = 0;
-               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - 
sizeof(struct fileEntry), GFP_KERNEL);
+               if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - 
sizeof(struct fileEntry)))
+               {
+                       make_bad_inode(inode);
+                       return;
+               }
                memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct 
fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
        }
        else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
@@ -1173,7 +1182,11 @@ static void udf_fill_inode(struct inode *inode, struct 
buffer_head *bh)
                UDF_I_LENALLOC(inode) =
                        le32_to_cpu(
                                ((struct unallocSpaceEntry 
*)bh->b_data)->lengthAllocDescs);
-               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - 
sizeof(struct unallocSpaceEntry), GFP_KERNEL);
+               if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - 
sizeof(struct unallocSpaceEntry)))
+               {
+                       make_bad_inode(inode);
+                       return;
+               }
                memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct 
unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct 
unallocSpaceEntry));
                return;
        }
@@ -1191,7 +1204,7 @@ static void udf_fill_inode(struct inode *inode, struct 
buffer_head *bh)
        inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
        if (!inode->i_nlink)
                inode->i_nlink = 1;
-       
+
        inode->i_size = le64_to_cpu(fe->informationLength);
        UDF_I_LENEXTENTS(inode) = inode->i_size;
 
@@ -1243,7 +1256,7 @@ static void udf_fill_inode(struct inode *inode, struct 
buffer_head *bh)
        }
        else
        {
-               inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << 
+               inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
                        (inode->i_sb->s_blocksize_bits - 9);
 
                if ( udf_stamp_to_time(&convtime, &convtime_usec,
@@ -1374,6 +1387,20 @@ static void udf_fill_inode(struct inode *inode, struct 
buffer_head *bh)
        }
 }
 
+static int udf_alloc_i_data(struct inode *inode, size_t size)
+{
+       UDF_I_DATA(inode) = kmalloc(size, GFP_KERNEL);
+
+       if (!UDF_I_DATA(inode))
+       {
+               printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) no free 
memory\n",
+                      inode->i_ino);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
 static mode_t
 udf_convert_permissions(struct fileEntry *fe)
 {
@@ -2072,7 +2099,7 @@ int8_t udf_delete_aext(struct inode *inode, struct 
extent_position epos,
                        mark_buffer_dirty_inode(oepos.bh, inode);
                }
        }
-       
+
        brelse(epos.bh);
        brelse(oepos.bh);
        return (elen >> 30);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to