fs/ntfs/attrib.c

Source file repositories/reference/linux-study-clean/fs/ntfs/attrib.c

File Facts

System
Linux kernel
Corpus path
fs/ntfs/attrib.c
Extension
.c
Size
171216 bytes
Lines
5700
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ntfs_resident_attr_value {
	const u8 *data;
	u32 len;
};

static bool ntfs_resident_attr_value_get(const struct attr_record *a,
					 struct ntfs_resident_attr_value *value)
{
	u32 attr_len;
	u16 value_offset;

	attr_len = le32_to_cpu(a->length);
	if (attr_len < offsetof(struct attr_record, data.resident.reserved) +
			sizeof(a->data.resident.reserved))
		return false;

	value->len = le32_to_cpu(a->data.resident.value_length);
	value_offset = le16_to_cpu(a->data.resident.value_offset);

	if (value->len > attr_len || value_offset > attr_len - value->len)
		return false;

	value->data = (const u8 *)a + value_offset;
	return true;
}

static bool ntfs_non_resident_attr_value_is_valid(const struct attr_record *a)
{
	u32 attr_len;
	u32 min_len;
	u16 mp_offset;

	attr_len = le32_to_cpu(a->length);
	min_len = offsetof(struct attr_record, data.non_resident.initialized_size) +
		  sizeof(a->data.non_resident.initialized_size);
	if (attr_len < min_len)
		return false;

	mp_offset = le16_to_cpu(a->data.non_resident.mapping_pairs_offset);
	return mp_offset >= min_len && mp_offset <= attr_len;
}

static bool ntfs_attr_value_is_valid(struct ntfs_volume *vol,
				     const struct attr_record *a,
				     const u64 mft_no)
{
	struct ntfs_resident_attr_value value;
	u32 min_len;

	if (a->non_resident) {
		if (ntfs_attr_type_is_resident_only(a->type))
			goto corrupt;
		if (!ntfs_non_resident_attr_value_is_valid(a))
			goto corrupt;
		return true;
	}

	if (!ntfs_resident_attr_value_get(a, &value))
		goto corrupt;

	min_len = ntfs_resident_attr_min_value_length(a->type);
	if (min_len && value.len < min_len)
		goto corrupt;

	switch (a->type) {
	case AT_FILE_NAME:
		if (!ntfs_file_name_attr_value_is_valid(value.data, value.len))
			goto corrupt;
		break;
	case AT_VOLUME_NAME:
		if (!ntfs_volume_name_attr_value_is_valid(value.len))
			goto corrupt;
		break;
	case AT_INDEX_ROOT:
		if (!ntfs_index_root_attr_value_is_valid(value.data, value.len))
			goto corrupt;
		break;
	}
	return true;

corrupt:
	ntfs_error(vol->sb,
		   "Corrupt %#x attribute in MFT record %llu\n",
		   le32_to_cpu(a->type), mft_no);
	return false;
}

/*
 * ntfs_attr_find - find (next) attribute in mft record
 * @type:	attribute type to find

Annotation

Implementation Notes