Commit 53fbe4cb776d0d4ec981c0b1a9b0eca1c06d7753

Authored by Jan Kara
Committed by Greg Kroah-Hartman
1 parent a6a4afa5c4

udf: Verify symlink size before loading it

commit a1d47b262952a45aae62bd49cfaf33dd76c11a2c upstream.

UDF specification allows arbitrarily large symlinks. However we support
only symlinks at most one block large. Check the length of the symlink
so that we don't access memory beyond end of the symlink block.

Reported-by: Carl Henrik Lunde <chlunde@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 13 additions and 4 deletions Side-by-side Diff

... ... @@ -99,11 +99,17 @@
99 99 struct inode *inode = page->mapping->host;
100 100 struct buffer_head *bh = NULL;
101 101 unsigned char *symlink;
102   - int err = -EIO;
  102 + int err;
103 103 unsigned char *p = kmap(page);
104 104 struct udf_inode_info *iinfo;
105 105 uint32_t pos;
106 106  
  107 + /* We don't support symlinks longer than one block */
  108 + if (inode->i_size > inode->i_sb->s_blocksize) {
  109 + err = -ENAMETOOLONG;
  110 + goto out_unmap;
  111 + }
  112 +
107 113 iinfo = UDF_I(inode);
108 114 pos = udf_block_map(inode, 0);
109 115  
... ... @@ -113,8 +119,10 @@
113 119 } else {
114 120 bh = sb_bread(inode->i_sb, pos);
115 121  
116   - if (!bh)
117   - goto out;
  122 + if (!bh) {
  123 + err = -EIO;
  124 + goto out_unlock_inode;
  125 + }
118 126  
119 127 symlink = bh->b_data;
120 128 }
121 129  
... ... @@ -130,9 +138,10 @@
130 138 unlock_page(page);
131 139 return 0;
132 140  
133   -out:
  141 +out_unlock_inode:
134 142 up_read(&iinfo->i_data_sem);
135 143 SetPageError(page);
  144 +out_unmap:
136 145 kunmap(page);
137 146 unlock_page(page);
138 147 return err;