debuggers.hg

annotate xen/common/unlzo.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents d8333666361d
children
rev   line source
keir@21663 1 /*
keir@21663 2 * LZO decompressor for the Linux kernel. Code borrowed from the lzo
keir@21663 3 * implementation by Markus Franz Xaver Johannes Oberhumer.
keir@21663 4 *
keir@21663 5 * Linux kernel adaptation:
keir@21663 6 * Copyright (C) 2009
keir@21663 7 * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
keir@21663 8 *
keir@21663 9 * Original code:
keir@21663 10 * Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer
keir@21663 11 * All Rights Reserved.
keir@21663 12 *
keir@21663 13 * lzop and the LZO library are free software; you can redistribute them
keir@21663 14 * and/or modify them under the terms of the GNU General Public License as
keir@21663 15 * published by the Free Software Foundation; either version 2 of
keir@21663 16 * the License, or (at your option) any later version.
keir@21663 17 *
keir@21663 18 * This program is distributed in the hope that it will be useful,
keir@21663 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
keir@21663 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
keir@21663 21 * GNU General Public License for more details.
keir@21663 22 *
keir@21663 23 * You should have received a copy of the GNU General Public License
keir@21663 24 * along with this program; see the file COPYING.
keir@21663 25 * If not, write to the Free Software Foundation, Inc.,
keir@21663 26 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
keir@21663 27 *
keir@21663 28 * Markus F.X.J. Oberhumer
keir@21663 29 * <markus@oberhumer.com>
keir@21663 30 * http://www.oberhumer.com/opensource/lzop/
keir@21663 31 */
keir@21663 32
keir@21663 33 #include "decompress.h"
keir@21663 34 #include <xen/lzo.h>
keir@21663 35 #include <asm/byteorder.h>
keir@21663 36
keir@21663 37 #if 1 /* ndef CONFIG_??? */
keir@21663 38 static inline u16 INIT get_unaligned_be16(void *p)
keir@21663 39 {
keir@21663 40 return be16_to_cpup(p);
keir@21663 41 }
keir@21663 42
keir@21663 43 static inline u32 INIT get_unaligned_be32(void *p)
keir@21663 44 {
keir@21663 45 return be32_to_cpup(p);
keir@21663 46 }
keir@21663 47 #else
keir@21663 48 #include <asm/unaligned.h>
keir@21663 49
keir@21663 50 static inline u16 INIT get_unaligned_be16(void *p)
keir@21663 51 {
keir@21663 52 return be16_to_cpu(__get_unaligned(p, 2));
keir@21663 53 }
keir@21663 54
keir@21663 55 static inline u32 INIT get_unaligned_be32(void *p)
keir@21663 56 {
keir@21663 57 return be32_to_cpu(__get_unaligned(p, 4));
keir@21663 58 }
keir@21663 59 #endif
keir@21663 60
keir@21663 61 static const unsigned char lzop_magic[] = {
keir@21663 62 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a };
keir@21663 63
keir@21663 64 #define LZO_BLOCK_SIZE (256*1024l)
keir@21663 65 #define HEADER_HAS_FILTER 0x00000800L
keir@21663 66
keir@21663 67 static int INIT parse_header(u8 *input, u8 *skip)
keir@21663 68 {
keir@21663 69 int l;
keir@21663 70 u8 *parse = input;
keir@21663 71 u8 level = 0;
keir@21663 72 u16 version;
keir@21663 73
keir@21663 74 /* read magic: 9 first bits */
keir@21663 75 for (l = 0; l < 9; l++) {
keir@21663 76 if (*parse++ != lzop_magic[l])
keir@21663 77 return 0;
keir@21663 78 }
keir@21663 79 /* get version (2bytes), skip library version (2),
keir@21663 80 * 'need to be extracted' version (2) and
keir@21663 81 * method (1) */
keir@21663 82 version = get_unaligned_be16(parse);
keir@21663 83 parse += 7;
keir@21663 84 if (version >= 0x0940)
keir@21663 85 level = *parse++;
keir@21663 86 if (get_unaligned_be32(parse) & HEADER_HAS_FILTER)
keir@21663 87 parse += 8; /* flags + filter info */
keir@21663 88 else
keir@21663 89 parse += 4; /* flags */
keir@21663 90
keir@21663 91 /* skip mode and mtime_low */
keir@21663 92 parse += 8;
keir@21663 93 if (version >= 0x0940)
keir@21663 94 parse += 4; /* skip mtime_high */
keir@21663 95
keir@21663 96 l = *parse++;
keir@21663 97 /* don't care about the file name, and skip checksum */
keir@21663 98 parse += l + 4;
keir@21663 99
keir@21663 100 *skip = parse - input;
keir@21663 101 return 1;
keir@21663 102 }
keir@21663 103
keir@21663 104 STATIC int INIT unlzo(u8 *input, unsigned int in_len,
keir@21663 105 int (*fill) (void *, unsigned int),
keir@21663 106 int (*flush) (void *, unsigned int),
keir@21663 107 u8 *output, unsigned int *posp,
keir@21663 108 void (*error_fn) (const char *x))
keir@21663 109 {
keir@21663 110 u8 skip = 0, r = 0;
keir@21663 111 u32 src_len, dst_len;
keir@21663 112 size_t tmp;
keir@21663 113 u8 *in_buf, *in_buf_save, *out_buf;
keir@21663 114 int ret = -1;
keir@21663 115
keir@21663 116 set_error_fn(error_fn);
keir@21663 117
keir@21663 118 if (output) {
keir@21663 119 out_buf = output;
keir@21663 120 } else if (!flush) {
keir@21663 121 error("NULL output pointer and no flush function provided");
keir@21663 122 goto exit;
keir@21663 123 } else {
keir@21663 124 out_buf = malloc(LZO_BLOCK_SIZE);
keir@21663 125 if (!out_buf) {
keir@21663 126 error("Could not allocate output buffer");
keir@21663 127 goto exit;
keir@21663 128 }
keir@21663 129 }
keir@21663 130
keir@21663 131 if (input && fill) {
keir@21663 132 error("Both input pointer and fill function provided, don't know what to do");
keir@21663 133 goto exit_1;
keir@21663 134 } else if (input) {
keir@21663 135 in_buf = input;
keir@21663 136 } else if (!fill || !posp) {
keir@21663 137 error("NULL input pointer and missing position pointer or fill function");
keir@21663 138 goto exit_1;
keir@21663 139 } else {
keir@21663 140 in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
keir@21663 141 if (!in_buf) {
keir@21663 142 error("Could not allocate input buffer");
keir@21663 143 goto exit_1;
keir@21663 144 }
keir@21663 145 }
keir@21663 146 in_buf_save = in_buf;
keir@21663 147
keir@21663 148 if (posp)
keir@21663 149 *posp = 0;
keir@21663 150
keir@21663 151 if (fill)
keir@21663 152 fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
keir@21663 153
keir@21663 154 if (!parse_header(input, &skip)) {
keir@21663 155 error("invalid header");
keir@21663 156 goto exit_2;
keir@21663 157 }
keir@21663 158 in_buf += skip;
keir@21663 159
keir@21663 160 if (posp)
keir@21663 161 *posp = skip;
keir@21663 162
keir@21663 163 for (;;) {
keir@21663 164 /* read uncompressed block size */
keir@21663 165 dst_len = get_unaligned_be32(in_buf);
keir@21663 166 in_buf += 4;
keir@21663 167
keir@21663 168 /* exit if last block */
keir@21663 169 if (dst_len == 0) {
keir@21663 170 if (posp)
keir@21663 171 *posp += 4;
keir@21663 172 break;
keir@21663 173 }
keir@21663 174
keir@21663 175 if (dst_len > LZO_BLOCK_SIZE) {
keir@21663 176 error("dest len longer than block size");
keir@21663 177 goto exit_2;
keir@21663 178 }
keir@21663 179
keir@21663 180 /* read compressed block size, and skip block checksum info */
keir@21663 181 src_len = get_unaligned_be32(in_buf);
keir@21663 182 in_buf += 8;
keir@21663 183
keir@21663 184 if (src_len <= 0 || src_len > dst_len) {
keir@21663 185 error("file corrupted");
keir@21663 186 goto exit_2;
keir@21663 187 }
keir@21663 188
keir@21663 189 /* decompress */
keir@21663 190 tmp = dst_len;
keir@21663 191
keir@21663 192 /* When the input data is not compressed at all,
keir@21663 193 * lzo1x_decompress_safe will fail, so call memcpy()
keir@21663 194 * instead */
keir@21663 195 if (unlikely(dst_len == src_len))
keir@21663 196 memcpy(out_buf, in_buf, src_len);
keir@21663 197 else {
keir@21663 198 r = lzo1x_decompress_safe(in_buf, src_len,
keir@21663 199 out_buf, &tmp);
keir@21663 200
keir@21663 201 if (r != LZO_E_OK || dst_len != tmp) {
keir@21663 202 error("Compressed data violation");
keir@21663 203 goto exit_2;
keir@21663 204 }
keir@21663 205 }
keir@21663 206
keir@21663 207 if (flush)
keir@21663 208 flush(out_buf, dst_len);
keir@21663 209 if (output)
keir@21663 210 out_buf += dst_len;
keir@21663 211 if (posp)
keir@21663 212 *posp += src_len + 12;
keir@21663 213 if (fill) {
keir@21663 214 in_buf = in_buf_save;
keir@21663 215 fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
keir@21663 216 } else
keir@21663 217 in_buf += src_len;
keir@21663 218 }
keir@21663 219
keir@21663 220 ret = 0;
keir@21663 221 exit_2:
keir@21663 222 if (!input)
keir@21663 223 free(in_buf);
keir@21663 224 exit_1:
keir@21663 225 if (!output)
keir@21663 226 free(out_buf);
keir@21663 227 exit:
keir@21663 228 return ret;
keir@21663 229 }