/* Hash a block, writing the result to the next level's pending block buffer. */ staticint hash_one_block(struct inode *inode, conststruct merkle_tree_params *params, struct block_buffer *cur)
{ struct block_buffer *next = cur + 1;
/* Hash each data block, also hashing the tree blocks as they fill up */ for (offset = 0; offset < data_size; offset += params->block_size) {
ssize_t bytes_read;
loff_t pos = offset;
buffers[-1].filled = min_t(u64, params->block_size,
data_size - offset);
bytes_read = __kernel_read(filp, buffers[-1].data,
buffers[-1].filled, &pos); if (bytes_read < 0) {
err = bytes_read;
fsverity_err(inode, "Error %d reading file data", err); goto out;
} if (bytes_read != buffers[-1].filled) {
err = -EINVAL;
fsverity_err(inode, "Short read of file data"); goto out;
}
err = hash_one_block(inode, params, &buffers[-1]); if (err) goto out; for (level = 0; level < num_levels; level++) { if (buffers[level].filled + params->digest_size <=
params->block_size) { /* Next block at @level isn't full yet */ break;
} /* Next block at @level is full */
err = hash_one_block(inode, params, &buffers[level]); if (err) goto out;
err = write_merkle_tree_block(inode,
buffers[level].data,
level_offset[level],
params); if (err) goto out;
level_offset[level]++;
} if (fatal_signal_pending(current)) {
err = -EINTR; goto out;
}
cond_resched();
} /* Finish all nonempty pending tree blocks. */ for (level = 0; level < num_levels; level++) { if (buffers[level].filled != 0) {
err = hash_one_block(inode, params, &buffers[level]); if (err) goto out;
err = write_merkle_tree_block(inode,
buffers[level].data,
level_offset[level],
params); if (err) goto out;
}
} /* The root hash was filled by the last call to hash_one_block(). */ if (WARN_ON_ONCE(buffers[num_levels].filled != params->digest_size)) {
err = -EINVAL; goto out;
}
err = 0;
out: for (level = -1; level < num_levels; level++)
kfree(buffers[level].data); return err;
}
/* Get the salt if the user provided one */ if (arg->salt_size &&
copy_from_user(desc->salt, u64_to_user_ptr(arg->salt_ptr),
arg->salt_size)) {
err = -EFAULT; goto out;
}
desc->salt_size = arg->salt_size;
/* Get the builtin signature if the user provided one */ if (arg->sig_size &&
copy_from_user(desc->signature, u64_to_user_ptr(arg->sig_ptr),
arg->sig_size)) {
err = -EFAULT; goto out;
}
desc->sig_size = cpu_to_le32(arg->sig_size);
desc->data_size = cpu_to_le64(inode->i_size);
/* Prepare the Merkle tree parameters */
err = fsverity_init_merkle_tree_params(¶ms, inode,
arg->hash_algorithm,
desc->log_blocksize,
desc->salt, desc->salt_size); if (err) goto out;
/* *Startenablingverityonthisfile,serializedbytheinodelock. *Failifverityisalreadyenabledorisalreadybeingenabled.
*/
inode_lock(inode); if (IS_VERITY(inode))
err = -EEXIST; else
err = vops->begin_enable_verity(filp);
inode_unlock(inode); if (err) goto out;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.