예제 #1
0
/* Creates and appends a 'struct wim_image_metadata' for an empty image.
 *
 * The resulting image will be the last in the WIM, so its index will be
 * the new value of wim->hdr.image_count.  */
static int
add_empty_image_metadata(WIMStruct *wim)
{
	int ret;
	struct wim_lookup_table_entry *metadata_lte;
	struct wim_security_data *sd;
	struct wim_image_metadata *imd;

	/* Create lookup table entry for this metadata resource (for now really
	 * just a dummy entry).  */
	ret = WIMLIB_ERR_NOMEM;
	metadata_lte = new_lookup_table_entry();
	if (!metadata_lte)
		goto out;

	metadata_lte->flags = WIM_RESHDR_FLAG_METADATA;
	metadata_lte->unhashed = 1;

	/* Create empty security data (no security descriptors).  */
	sd = new_wim_security_data();
	if (!sd)
		goto out_free_metadata_lte;

	imd = new_image_metadata();
	if (!imd)
		goto out_free_security_data;

	/* A NULL root_dentry indicates a completely empty image, without even a
	 * root directory.  */
	imd->root_dentry = NULL;
	imd->metadata_lte = metadata_lte;
	imd->security_data = sd;
	imd->modified = 1;

	/* Append as next image index.  */
	ret = append_image_metadata(wim, imd);
	if (ret)
		put_image_metadata(imd, NULL);
	goto out;

out_free_security_data:
	free_wim_security_data(sd);
out_free_metadata_lte:
	free_lookup_table_entry(metadata_lte);
out:
	return ret;
}
예제 #2
0
파일: security.c 프로젝트: APBaltic/wimlib
/*
 * Reads the security data from the metadata resource of a WIM image.
 *
 * @buf
 *	Buffer containing an uncompressed WIM metadata resource.
 * @buf_len
 *	Length of the uncompressed metadata resource, in bytes.
 * @sd_ret
 *	On success, a pointer to the resulting security data structure will be
 *	returned here.
 *
 * Note: There is no `offset' argument because the security data is located at
 * the beginning of the metadata resource.
 *
 * Return values:
 *	WIMLIB_ERR_SUCCESS (0)
 *	WIMLIB_ERR_INVALID_METADATA_RESOURCE
 *	WIMLIB_ERR_NOMEM
 */
int
read_wim_security_data(const u8 *buf, size_t buf_len,
		       struct wim_security_data **sd_ret)
{
	struct wim_security_data *sd;
	int ret;
	u64 total_len;
	u64 sizes_size;
	u64 size_no_descriptors;
	const struct wim_security_data_disk *sd_disk;
	const u8 *p;

	if (buf_len < 8)
		return WIMLIB_ERR_INVALID_METADATA_RESOURCE;

	sd = new_wim_security_data();
	if (!sd)
		goto out_of_memory;

	sd_disk = (const struct wim_security_data_disk *)buf;
	sd->total_length = le32_to_cpu(sd_disk->total_length);
	sd->num_entries = le32_to_cpu(sd_disk->num_entries);

	DEBUG("Reading security data: num_entries=%u, total_length=%u",
	      sd->num_entries, sd->total_length);

	/* Length field of 0 is a special case that really means length
	 * of 8. */
	if (sd->total_length == 0)
		sd->total_length = 8;

	/* The security_id field of each dentry is a signed 32-bit integer, so
	 * the possible indices into the security descriptors table are 0
	 * through 0x7fffffff.  Which means 0x80000000 security descriptors
	 * maximum.  Not like you should ever have anywhere close to that many
	 * security descriptors! */
	if (sd->num_entries > 0x80000000)
		goto out_invalid_sd;

	/* Verify the listed total length of the security data is big enough to
	 * include the sizes array, verify that the file data is big enough to
	 * include it as well, then allocate the array of sizes.
	 *
	 * Note: The total length of the security data must fit in a 32-bit
	 * integer, even though each security descriptor size is a 64-bit
	 * integer.  This is stupid, and we need to be careful not to actually
	 * let the security descriptor sizes be over 0xffffffff.  */
	if (sd->total_length > buf_len)
		goto out_invalid_sd;

	sizes_size = (u64)sd->num_entries * sizeof(u64);
	size_no_descriptors = 8 + sizes_size;
	if (size_no_descriptors > sd->total_length)
		goto out_invalid_sd;

	total_len = size_no_descriptors;

	/* Return immediately if no security descriptors. */
	if (sd->num_entries == 0)
		goto out_align_total_length;

	/* Allocate a new buffer for the sizes array */
	sd->sizes = MALLOC(sizes_size);
	if (!sd->sizes)
		goto out_of_memory;

	/* Copy the sizes array into the new buffer */
	for (u32 i = 0; i < sd->num_entries; i++) {
		sd->sizes[i] = le64_to_cpu(sd_disk->sizes[i]);
		if (sd->sizes[i] > 0xffffffff)
			goto out_invalid_sd;
	}

	p = (const u8*)sd_disk + size_no_descriptors;

	/* Allocate the array of pointers to the security descriptors, then read
	 * them into separate buffers. */
	sd->descriptors = CALLOC(sd->num_entries, sizeof(sd->descriptors[0]));
	if (!sd->descriptors)
		goto out_of_memory;

	for (u32 i = 0; i < sd->num_entries; i++) {
		if (sd->sizes[i] == 0)
			continue;
		total_len += sd->sizes[i];
		if (total_len > (u64)sd->total_length)
			goto out_invalid_sd;
		sd->descriptors[i] = memdup(p, sd->sizes[i]);
		if (!sd->descriptors[i])
			goto out_of_memory;
		p += sd->sizes[i];
	}
out_align_total_length:
	total_len = (total_len + 7) & ~7;
	sd->total_length = (sd->total_length + 7) & ~7;
	if (total_len != sd->total_length) {
		WARNING("Expected WIM security data total length of "
			"%u bytes, but calculated %u bytes",
			sd->total_length, (unsigned)total_len);
	}
	*sd_ret = sd;
	ret = 0;
	goto out;
out_invalid_sd:
	ERROR("WIM security data is invalid!");
	ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
	goto out_free_sd;
out_of_memory:
	ERROR("Out of memory while reading WIM security data!");
	ret = WIMLIB_ERR_NOMEM;
out_free_sd:
	free_wim_security_data(sd);
out:
	return ret;
}