const EFI_DEVICE_PATH *end_node = device_path_find_end_node(dp);
size_t file_size = strsize16(file);
+ /* The node Length is a uint16_t, so refuse a path that would not fit. */
+ if (file_size > UINT16_MAX - sizeof(FILEPATH_DEVICE_PATH))
+ return EFI_INVALID_PARAMETER;
+
size_t dp_size = (uint8_t *) end_node - (uint8_t *) dp;
/* Make a copy that can also hold a file media device path. */
return EFI_INVALID_PARAMETER;
size_t l = strlen8(u);
+ /* The node Length is a uint16_t, so refuse a URL that would not fit. */
+ if (l > UINT16_MAX - offsetof(URI_DEVICE_PATH, Uri))
+ return EFI_INVALID_PARAMETER;
size_t t = offsetof(URI_DEVICE_PATH, Uri) + l + sizeof(EFI_DEVICE_PATH);
EFI_DEVICE_PATH *dp = xmalloc(t);
return ret;
}
+bool device_path_is_valid(const EFI_DEVICE_PATH *dp, size_t size) {
+ if (!dp)
+ return false;
+
+ /* Validate against the known size so a truncated/corrupt path can't make us read out of bounds. */
+ for (;;) {
+ if (size < sizeof(EFI_DEVICE_PATH))
+ return false;
+ if (dp->Length < sizeof(EFI_DEVICE_PATH) || dp->Length > size)
+ return false;
+ if (device_path_is_end(dp))
+ return true;
+ size -= dp->Length;
+ dp = (const EFI_DEVICE_PATH *) ((const uint8_t *) dp + dp->Length);
+ }
+}
+
size_t device_path_size(const EFI_DEVICE_PATH *dp) {
const EFI_DEVICE_PATH *i = ASSERT_PTR(dp);
static inline EFI_DEVICE_PATH *device_path_next_node(const EFI_DEVICE_PATH *dp) {
assert(dp);
+ /* The node Length includes the 4-byte header, so a well-formed node is at least that long. Paths
+ * coming from untrusted sources must be checked with device_path_is_valid() before being walked. */
+ assert(dp->Length >= sizeof(EFI_DEVICE_PATH));
return (EFI_DEVICE_PATH *) ((uint8_t *) dp + dp->Length);
}
size_t device_path_size(const EFI_DEVICE_PATH *dp);
+/* Validates that a device path is well-formed and fully contained within the given size, terminated by an
+ * end node. Use on paths from untrusted sources (e.g. EFI variables) before walking them. */
+bool device_path_is_valid(const EFI_DEVICE_PATH *dp, size_t size);
+
EFI_DEVICE_PATH *device_path_dup(const EFI_DEVICE_PATH *dp);