29 Dec, 2020

4 commits

  • Although it isn't used directly by the ioctls,
    "struct fsverity_descriptor" is required by userspace programs that need
    to compute fs-verity file digests in a standalone way. Therefore
    it's also needed to sign files in a standalone way.

    Similarly, "struct fsverity_formatted_digest" (previously called
    "struct fsverity_signed_digest" which was misleading) is also needed to
    sign files if the built-in signature verification is being used.

    Therefore, move these structs to the UAPI header.

    While doing this, try to make it clear that the signature-related fields
    in fsverity_descriptor aren't used in the file digest computation.

    Acked-by: Luca Boccassi
    Link: https://lore.kernel.org/r/20201113211918.71883-5-ebiggers@kernel.org
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • I originally chose the name "file measurement" to refer to the fs-verity
    file digest to avoid confusion with traditional full-file digests or
    with the bare root hash of the Merkle tree.

    But the name "file measurement" hasn't caught on, and usually people are
    calling it something else, usually the "file digest". E.g. see
    "struct fsverity_digest" and "struct fsverity_formatted_digest", the
    libfsverity_compute_digest() and libfsverity_sign_digest() functions in
    libfsverity, and the "fsverity digest" command.

    Having multiple names for the same thing is always confusing.

    So to hopefully avoid confusion in the future, rename
    "fs-verity file measurement" to "fs-verity file digest".

    This leaves FS_IOC_MEASURE_VERITY as the only reference to "measure" in
    the kernel, which makes some amount of sense since the ioctl is actively
    "measuring" the file.

    I'll be renaming this in fsverity-utils too (though similarly the
    'fsverity measure' command, which is a wrapper for
    FS_IOC_MEASURE_VERITY, will stay).

    Acked-by: Luca Boccassi
    Link: https://lore.kernel.org/r/20201113211918.71883-4-ebiggers@kernel.org
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • The name "struct fsverity_signed_digest" is causing confusion because it
    isn't actually a signed digest, but rather it's the way that the digest
    is formatted in order to be signed. Rename it to
    "struct fsverity_formatted_digest" to prevent this confusion.

    Also update the struct's comment to clarify that it's specific to the
    built-in signature verification support and isn't a requirement for all
    fs-verity users.

    I'll be renaming this struct in fsverity-utils too.

    Acked-by: Luca Boccassi
    Link: https://lore.kernel.org/r/20201113211918.71883-3-ebiggers@kernel.org
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • Embedding the file path inside kernel source code files isn't
    particularly useful as often files are moved around and the paths become
    incorrect. checkpatch.pl warns about this since v5.10-rc1.

    Acked-by: Luca Boccassi
    Link: https://lore.kernel.org/r/20201113211918.71883-2-ebiggers@kernel.org
    Signed-off-by: Eric Biggers

    Eric Biggers
     

22 Jul, 2020

1 commit

  • Normally smp_store_release() or cmpxchg_release() is paired with
    smp_load_acquire(). Sometimes smp_load_acquire() can be replaced with
    the more lightweight READ_ONCE(). However, for this to be safe, all the
    published memory must only be accessed in a way that involves the
    pointer itself. This may not be the case if allocating the object also
    involves initializing a static or global variable, for example.

    fsverity_info::tree_params.hash_alg->tfm is a crypto_ahash object that's
    internal to and is allocated by the crypto subsystem. So by using
    READ_ONCE() for ->i_verity_info, we're relying on internal
    implementation details of the crypto subsystem.

    Remove this fragile assumption by using smp_load_acquire() instead.

    Also fix the cmpxchg logic to correctly execute an ACQUIRE barrier when
    losing the cmpxchg race, since cmpxchg doesn't guarantee a memory
    barrier on failure.

    (Note: I haven't seen any real-world problems here. This change is just
    fixing the code to be guaranteed correct and less fragile.)

    Fixes: fd2d1acfcadf ("fs-verity: add the hook for file ->open()")
    Link: https://lore.kernel.org/r/20200721225920.114347-6-ebiggers@kernel.org
    Signed-off-by: Eric Biggers

    Eric Biggers
     

13 May, 2020

2 commits

  • Remove the unnecessary 'extern' keywords from function declarations.
    This makes it so that we don't have a mix of both styles, so it won't be
    ambiguous what to use in new fs-verity patches. This also makes the
    code shorter and matches the 'checkpatch --strict' expectation.

    Link: https://lore.kernel.org/r/20200511192118.71427-3-ebiggers@kernel.org
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • Fix all kerneldoc warnings in fs/verity/ and include/linux/fsverity.h.
    Most of these were due to missing documentation for function parameters.

    Detected with:

    scripts/kernel-doc -v -none fs/verity/*.{c,h} include/linux/fsverity.h

    This cleanup makes it possible to check new patches for kerneldoc
    warnings without having to filter out all the existing ones.

    Link: https://lore.kernel.org/r/20200511192118.71427-2-ebiggers@kernel.org
    Signed-off-by: Eric Biggers

    Eric Biggers
     

15 Jan, 2020

4 commits

  • already provides a macro u64_to_user_ptr().
    Use it instead of open-coding the two casts.

    No change in behavior.

    Link: https://lore.kernel.org/r/20191231175408.20524-1-ebiggers@kernel.org
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • When initializing an fs-verity hash algorithm, also initialize a mempool
    that contains a single preallocated hash request object. Then replace
    the direct calls to ahash_request_alloc() and ahash_request_free() with
    allocating and freeing from this mempool.

    This eliminates the possibility of the allocation failing, which is
    desirable for the I/O path.

    This doesn't cause deadlocks because there's no case where multiple hash
    requests are needed at a time to make forward progress.

    Link: https://lore.kernel.org/r/20191231175545.20709-1-ebiggers@kernel.org
    Reviewed-by: Theodore Ts'o
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • When fs-verity verifies data pages, currently it reads each Merkle tree
    page synchronously using read_mapping_page().

    Therefore, when the Merkle tree pages aren't already cached, fs-verity
    causes an extra 4 KiB I/O request for every 512 KiB of data (assuming
    that the Merkle tree uses SHA-256 and 4 KiB blocks). This results in
    more I/O requests and performance loss than is strictly necessary.

    Therefore, implement readahead of the Merkle tree pages.

    For simplicity, we take advantage of the fact that the kernel already
    does readahead of the file's *data*, just like it does for any other
    file. Due to this, we don't really need a separate readahead state
    (struct file_ra_state) just for the Merkle tree, but rather we just need
    to piggy-back on the existing data readahead requests.

    We also only really need to bother with the first level of the Merkle
    tree, since the usual fan-out factor is 128, so normally over 99% of
    Merkle tree I/O requests are for the first level.

    Therefore, make fsverity_verify_bio() enable readahead of the first
    Merkle tree level, for up to 1/4 the number of pages in the bio, when it
    sees that the REQ_RAHEAD flag is set on the bio. The readahead size is
    then passed down to ->read_merkle_tree_page() for the filesystem to
    (optionally) implement if it sees that the requested page is uncached.

    While we're at it, also make build_merkle_tree_level() set the Merkle
    tree readahead size, since it's easy to do there.

    However, for now don't set the readahead size in fsverity_verify_page(),
    since currently it's only used to verify holes on ext4 and f2fs, and it
    would need parameters added to know how much to read ahead.

    This patch significantly improves fs-verity sequential read performance.
    Some quick benchmarks with 'cat'-ing a 250MB file after dropping caches:

    On an ARM64 phone (using sha256-ce):
    Before: 217 MB/s
    After: 263 MB/s
    (compare to sha256sum of non-verity file: 357 MB/s)

    In an x86_64 VM (using sha256-avx2):
    Before: 173 MB/s
    After: 215 MB/s
    (compare to sha256sum of non-verity file: 223 MB/s)

    Link: https://lore.kernel.org/r/20200106205533.137005-1-ebiggers@kernel.org
    Reviewed-by: Theodore Ts'o
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • When it builds the first level of the Merkle tree, FS_IOC_ENABLE_VERITY
    sequentially reads each page of the file using read_mapping_page().
    This works fine if the file's data is already in pagecache, which should
    normally be the case, since this ioctl is normally used immediately
    after writing out the file.

    But in any other case this implementation performs very poorly, since
    only one page is read at a time.

    Fix this by implementing readahead using the functions from
    mm/readahead.c.

    This improves performance in the uncached case by about 20x, as seen in
    the following benchmarks done on a 250MB file (on x86_64 with SHA-NI):

    FS_IOC_ENABLE_VERITY uncached (before) 3.299s
    FS_IOC_ENABLE_VERITY uncached (after) 0.160s
    FS_IOC_ENABLE_VERITY cached 0.147s
    sha256sum uncached 0.191s
    sha256sum cached 0.145s

    Note: we could instead switch to kernel_read(). But that would mean
    we'd no longer be hashing the data directly from the pagecache, which is
    a nice optimization of its own. And using kernel_read() would require
    allocating another temporary buffer, hashing the data and tree pages
    separately, and explicitly zero-padding the last page -- so it wouldn't
    really be any simpler than direct pagecache access, at least for now.

    Link: https://lore.kernel.org/r/20200106205410.136707-1-ebiggers@kernel.org
    Reviewed-by: Theodore Ts'o
    Signed-off-by: Eric Biggers

    Eric Biggers
     

10 Dec, 2019

1 commit

  • Replace all the occurrences of FIELD_SIZEOF() with sizeof_field() except
    at places where these are defined. Later patches will remove the unused
    definition of FIELD_SIZEOF().

    This patch is generated using following script:

    EXCLUDE_FILES="include/linux/stddef.h|include/linux/kernel.h"

    git grep -l -e "\bFIELD_SIZEOF\b" | while read file;
    do

    if [[ "$file" =~ $EXCLUDE_FILES ]]; then
    continue
    fi
    sed -i -e 's/\bFIELD_SIZEOF\b/sizeof_field/g' $file;
    done

    Signed-off-by: Pankaj Bharadiya
    Link: https://lore.kernel.org/r/20190924105839.110713-3-pankaj.laxminarayan.bharadiya@intel.com
    Co-developed-by: Kees Cook
    Signed-off-by: Kees Cook
    Acked-by: David Miller # for net

    Pankaj Bharadiya
     

13 Aug, 2019

4 commits

  • To meet some users' needs, add optional support for having fs-verity
    handle a portion of the authentication policy in the kernel. An
    ".fs-verity" keyring is created to which X.509 certificates can be
    added; then a sysctl 'fs.verity.require_signatures' can be set to cause
    the kernel to enforce that all fs-verity files contain a signature of
    their file measurement by a key in this keyring.

    See the "Built-in signature verification" section of
    Documentation/filesystems/fsverity.rst for the full documentation.

    Reviewed-by: Theodore Ts'o
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • Add SHA-512 support to fs-verity. This is primarily a demonstration of
    the trivial changes needed to support a new hash algorithm in fs-verity;
    most users will still use SHA-256, due to the smaller space required to
    store the hashes. But some users may prefer SHA-512.

    Reviewed-by: Theodore Ts'o
    Reviewed-by: Jaegeuk Kim
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • Add a function for filesystems to call to implement the
    FS_IOC_MEASURE_VERITY ioctl. This ioctl retrieves the file measurement
    that fs-verity calculated for the given file and is enforcing for reads;
    i.e., reads that don't match this hash will fail. This ioctl can be
    used for authentication or logging of file measurements in userspace.

    See the "FS_IOC_MEASURE_VERITY" section of
    Documentation/filesystems/fsverity.rst for the documentation.

    Reviewed-by: Theodore Ts'o
    Reviewed-by: Jaegeuk Kim
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • Add a function for filesystems to call to implement the
    FS_IOC_ENABLE_VERITY ioctl. This ioctl enables fs-verity on a file.

    See the "FS_IOC_ENABLE_VERITY" section of
    Documentation/filesystems/fsverity.rst for the documentation.

    Reviewed-by: Theodore Ts'o
    Reviewed-by: Jaegeuk Kim
    Signed-off-by: Eric Biggers

    Eric Biggers
     

29 Jul, 2019

4 commits

  • Add functions that verify data pages that have been read from a
    fs-verity file, against that file's Merkle tree. These will be called
    from filesystems' ->readpage() and ->readpages() methods.

    Since data verification can block, a workqueue is provided for these
    methods to enqueue verification work from their bio completion callback.

    See the "Verifying data" section of
    Documentation/filesystems/fsverity.rst for more information.

    Reviewed-by: Theodore Ts'o
    Reviewed-by: Jaegeuk Kim
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • Add a function fsverity_prepare_setattr() which filesystems that support
    fs-verity must call to deny truncates of verity files.

    Reviewed-by: Theodore Ts'o
    Reviewed-by: Jaegeuk Kim
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • Add the fsverity_file_open() function, which prepares an fs-verity file
    to be read from. If not already done, it loads the fs-verity descriptor
    from the filesystem and sets up an fsverity_info structure for the inode
    which describes the Merkle tree and contains the file measurement. It
    also denies all attempts to open verity files for writing.

    This commit also begins the include/linux/fsverity.h header, which
    declares the interface between fs/verity/ and filesystems.

    Reviewed-by: Theodore Ts'o
    Reviewed-by: Jaegeuk Kim
    Signed-off-by: Eric Biggers

    Eric Biggers
     
  • Add the beginnings of the fs/verity/ support layer, including the
    Kconfig option and various helper functions for hashing. To start, only
    SHA-256 is supported, but other hash algorithms can easily be added.

    Reviewed-by: Theodore Ts'o
    Reviewed-by: Jaegeuk Kim
    Signed-off-by: Eric Biggers

    Eric Biggers