Browse Source

[bzimage] Align initrd images to page boundary

Some versions of Linux apparently complain if initrds are not aligned
to a page boundary.  Fix by changing INITRD_ALIGN from 4 bytes to 4096
bytes.

The amount of padding at the end of each initrd will now often be
sufficient to allow the cpio header to be prepended without crossing
an alignment boundary.  The final location of the initrd may therefore
end up being slightly higher than the post-shuffle location.
bzimage_load_initrd() must therefore now copy the initrd body prior to
copying the cpio header, otherwise the start of the initrd body may be
overwritten by the cpio header.  (Note that the guarantee that an
initrd will never need to overwrite an initrd at a higher location
still holds, since the overall length of each initrd cannot decrease
as a result of adding a cpio header.)

Reported-by: Dave Hansen <dave@sr71.net>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
c825a9b39d
2 changed files with 16 additions and 19 deletions
  1. 13
    17
      src/arch/i386/image/bzimage.c
  2. 3
    2
      src/arch/i386/include/initrd.h

+ 13
- 17
src/arch/i386/image/bzimage.c View File

360
 	char *filename = initrd->cmdline;
360
 	char *filename = initrd->cmdline;
361
 	char *cmdline;
361
 	char *cmdline;
362
 	struct cpio_header cpio;
362
 	struct cpio_header cpio;
363
-        size_t offset = 0;
363
+	size_t offset;
364
 	size_t name_len;
364
 	size_t name_len;
365
 	size_t pad_len;
365
 	size_t pad_len;
366
 
366
 
368
 	if ( initrd == image )
368
 	if ( initrd == image )
369
 		return 0;
369
 		return 0;
370
 
370
 
371
-	/* Create cpio header before non-prebuilt images */
371
+	/* Create cpio header for non-prebuilt images */
372
 	if ( filename && filename[0] ) {
372
 	if ( filename && filename[0] ) {
373
 		cmdline = strchr ( filename, ' ' );
373
 		cmdline = strchr ( filename, ' ' );
374
 		name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) )
374
 		name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) )
383
 			bzimage_parse_cpio_cmdline ( image, &cpio,
383
 			bzimage_parse_cpio_cmdline ( image, &cpio,
384
 						     ( cmdline + 1 /* ' ' */ ));
384
 						     ( cmdline + 1 /* ' ' */ ));
385
 		}
385
 		}
386
-		if ( address ) {
387
-			copy_to_user ( address, offset, &cpio,
388
-				       sizeof ( cpio ) );
389
-		}
390
-		offset += sizeof ( cpio );
391
-		if ( address ) {
392
-			memset_user ( address, offset, 0, name_len );
393
-			copy_to_user ( address, offset, filename,
394
-				       ( name_len - 1 /* NUL (or space) */ ) );
395
-		}
396
-		offset += name_len;
397
-		offset = ( ( offset + 0x03 ) & ~0x03 );
386
+		offset = ( ( sizeof ( cpio ) + name_len + 0x03 ) & ~0x03 );
387
+	} else {
388
+		offset = 0;
398
 	}
389
 	}
399
 
390
 
400
-	/* Copy in initrd image body */
401
-	if ( address )
402
-		memmove_user ( address, offset, initrd->data, 0, initrd->len );
391
+	/* Copy in initrd image body (and cpio header if applicable) */
403
 	if ( address ) {
392
 	if ( address ) {
393
+		memmove_user ( address, offset, initrd->data, 0, initrd->len );
394
+		if ( offset ) {
395
+			memset_user ( address, 0, 0, offset );
396
+			copy_to_user ( address, 0, &cpio, sizeof ( cpio ) );
397
+			copy_to_user ( address, sizeof ( cpio ), filename,
398
+				       ( name_len - 1 /* NUL (or space) */ ) );
399
+		}
404
 		DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)"
400
 		DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)"
405
 		       "%s%s\n", image, initrd, user_to_phys ( address, 0 ),
401
 		       "%s%s\n", image, initrd, user_to_phys ( address, 0 ),
406
 		       user_to_phys ( address, offset ),
402
 		       user_to_phys ( address, offset ),

+ 3
- 2
src/arch/i386/include/initrd.h View File

13
 
13
 
14
 /** Minimum alignment for initrds
14
 /** Minimum alignment for initrds
15
  *
15
  *
16
- * Chosen to maximise memcpy() speeds
16
+ * Some versions of Linux complain about initrds that are not
17
+ * page-aligned.
17
  */
18
  */
18
-#define INITRD_ALIGN 4
19
+#define INITRD_ALIGN 4096
19
 
20
 
20
 /** Minimum free space required to reshuffle initrds
21
 /** Minimum free space required to reshuffle initrds
21
  *
22
  *

Loading…
Cancel
Save