27 Jun, 2024

1 commit

  • commit 004b8d1491b4bcbb7da1a3206d1e7e66822d47c6 upstream.

    ovl_check_encode_origin() should return a positive number if the lower
    dentry is to be encoded, zero otherwise. If there's no upper layer at all
    (read-only overlay), then it obviously needs to return positive.

    This was broken by commit 16aac5ad1fa9 ("ovl: support encoding
    non-decodable file handles"), which didn't take the lower-only
    configuration into account.

    Fix by checking the no-upper-layer case up-front.

    Reported-and-tested-by: Youzhong Yang
    Closes: https://lore.kernel.org/all/CADpNCvaBimi+zCYfRJHvCOhMih8OU0rmZkwLuh24MKKroRuT8Q@mail.gmail.com/
    Fixes: 16aac5ad1fa9 ("ovl: support encoding non-decodable file handles")
    Cc: # v6.6
    Signed-off-by: Miklos Szeredi
    Signed-off-by: Greg Kroah-Hartman

    Miklos Szeredi
     

03 Oct, 2023

1 commit


13 Aug, 2023

2 commits

  • Always use OVL_FS() to retrieve the corresponding struct ovl_fs from a
    struct super_block.

    Reviewed-by: Amir Goldstein
    Signed-off-by: Andrea Righi
    Signed-off-by: Amir Goldstein

    Andrea Righi
     
  • When all layers support file handles, we support encoding non-decodable
    file handles (a.k.a. fid) even with nfs_export=off.

    When file handles do not need to be decoded, we do not need to copy up
    redirected lower directories on encode, and we encode also non-indexed
    upper with lower file handle, so fid will not change on copy up.

    This enables reporting fanotify events with file handles on overlayfs
    with default config/mount options.

    Signed-off-by: Amir Goldstein

    Amir Goldstein
     

19 Jun, 2023

5 commits

  • The ovl_inode contains a copy of lowerpath in lowerstack[0], so the
    lowerpath member can be removed.

    Use accessor ovl_lowerpath() to get the lowerpath whereever the member
    was accessed directly.

    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • The lower stacks of all the ovl inode aliases should be identical
    and there is redundant information in ovl_entry and ovl_inode.

    Move lowerstack into ovl_inode and keep only the OVL_E_FLAGS
    per overlay dentry.

    Following patches will deduplicate redundant ovl_inode fields.

    Note that for pure upper and negative dentries, OVL_E(dentry) may be
    NULL now, so it is imporatnt to use the ovl_numlower() accessor.

    Reviewed-by: Alexander Larsson
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • This helps fortify against dereferencing a NULL ovl_entry,
    before we move the ovl_entry reference into ovl_inode.

    Reviewed-by: Alexander Larsson
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • Instead of open coded instances, because we are about to split
    the two apart.

    Reviewed-by: Alexander Larsson
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • After copy up, we may need to update d_flags if upper dentry is on a
    remote fs and lower dentries are not.

    Add helpers to allow incremental update of the revalidate flags.

    Fixes: bccece1ead36 ("ovl: allow remote upper")
    Reviewed-by: Gao Xiang
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     

19 Jan, 2023

1 commit

  • Convert to struct mnt_idmap.

    Last cycle we merged the necessary infrastructure in
    256c8aed2b42 ("fs: introduce dedicated idmap type for mounts").
    This is just the conversion to struct mnt_idmap.

    Currently we still pass around the plain namespace that was attached to a
    mount. This is in general pretty convenient but it makes it easy to
    conflate namespaces that are relevant on the filesystem with namespaces
    that are relevent on the mount level. Especially for non-vfs developers
    without detailed knowledge in this area this can be a potential source for
    bugs.

    Once the conversion to struct mnt_idmap is done all helpers down to the
    really low-level helpers will take a struct mnt_idmap argument instead of
    two namespace arguments. This way it becomes impossible to conflate the two
    eliminating the possibility of any bugs. All of the vfs and all filesystems
    only operate on struct mnt_idmap.

    Acked-by: Dave Chinner
    Reviewed-by: Christoph Hellwig
    Signed-off-by: Christian Brauner (Microsoft)

    Christian Brauner
     

08 Dec, 2022

3 commits

  • ovl_indexdir_cleanup() is called on mount of overayfs with nfs_export
    feature to cleanup stale index records for lower and upper files that have
    been deleted while overlayfs was offline.

    This has the side effect (good or bad) of pre populating inode cache with
    all the copied up upper inodes, while verifying the index entries.

    For copied up directories, the upper file handles are decoded to conncted
    upper dentries. This has the even bigger side effect of reading the
    content of all the parent upper directories which may take significantly
    more time and IO than just reading the upper inodes.

    Do not request connceted upper dentries for verifying upper directory index
    entries, because we have no use for the connected dentry.

    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • Fix two typos.

    Reported-by: k2ci
    Signed-off-by: Jiangshan Yi
    Signed-off-by: Miklos Szeredi

    Jiangshan Yi
     
  • The "buf" flexible array needs to be the memcpy() destination to avoid
    false positive run-time warning from the recent FORTIFY_SOURCE
    hardening:

    memcpy: detected field-spanning write (size 93) of single field "&fh->fb"
    at fs/overlayfs/export.c:799 (size 21)

    Reported-by: syzbot+9d14351a171d0d1c7955@syzkaller.appspotmail.com
    Link: https://lore.kernel.org/all/000000000000763a6c05e95a5985@google.com/
    Signed-off-by: Kees Cook
    Reviewed-by: Gustavo A. R. Silva
    Signed-off-by: Miklos Szeredi

    Kees Cook
     

28 Jul, 2022

1 commit

  • Some code paths cannot guarantee the inode have any dentry alias. So
    WARN_ON() all !dentry may flood the kernel logs.

    For example, when an overlayfs inode is watched by inotifywait (1), and
    someone is trying to read the /proc/$(pidof inotifywait)/fdinfo/INOTIFY_FD,
    at that time if the dentry has been reclaimed by kernel (such as
    echo 2 > /proc/sys/vm/drop_caches), there will be a WARN_ON(). The
    printed call stack would be like:

    ? show_mark_fhandle+0xf0/0xf0
    show_mark_fhandle+0x4a/0xf0
    ? show_mark_fhandle+0xf0/0xf0
    ? seq_vprintf+0x30/0x50
    ? seq_printf+0x53/0x70
    ? show_mark_fhandle+0xf0/0xf0
    inotify_fdinfo+0x70/0x90
    show_fdinfo.isra.4+0x53/0x70
    seq_show+0x130/0x170
    seq_read+0x153/0x440
    vfs_read+0x94/0x150
    ksys_read+0x5f/0xe0
    do_syscall_64+0x59/0x1e0
    entry_SYSCALL_64_after_hwframe+0x44/0xa9

    So let's drop WARN_ON() to avoid kernel log flooding.

    Reported-by: Hongbo Yin
    Signed-off-by: Jiachen Zhang
    Signed-off-by: Tianci Zhang
    Fixes: 8ed5eec9d6c4 ("ovl: encode pure upper file handles")
    Cc: # v4.16
    Signed-off-by: Miklos Szeredi

    Jiachen Zhang
     

28 Apr, 2022

1 commit

  • Make the two places where lookup helpers can be called either on lower
    or upper layers take the mount's idmapping into account. To this end we
    pass down the mount in struct ovl_lookup_data. It can later also be used
    to construct struct path for various other helpers. This is needed to
    support idmapped base layers with overlay.

    Cc:
    Tested-by: Giuseppe Scrivano
    Reviewed-by: Amir Goldstein
    Signed-off-by: Christian Brauner (Microsoft)
    Signed-off-by: Miklos Szeredi

    Christian Brauner
     

10 Aug, 2021

1 commit


12 Nov, 2020

1 commit


02 Sep, 2020

1 commit


16 Jul, 2020

1 commit

  • Decoding a lower directory file handle to overlay path with cold
    inode/dentry cache may go as follows:

    1. Decode real lower file handle to lower dir path
    2. Check if lower dir is indexed (was copied up)
    3. If indexed, get the upper dir path from index
    4. Lookup upper dir path in overlay
    5. If overlay path found, verify that overlay lower is the lower dir
    from step 1

    On failure to verify step 5 above, user will get an ESTALE error and a
    WARN_ON will be printed.

    A mismatch in step 5 could be a result of lower directory that was renamed
    while overlay was offline, after that lower directory has been copied up
    and indexed.

    This is a scripted reproducer based on xfstest overlay/052:

    # Create lower subdir
    create_dirs
    create_test_files $lower/lowertestdir/subdir
    mount_dirs
    # Copy up lower dir and encode lower subdir file handle
    touch $SCRATCH_MNT/lowertestdir
    test_file_handles $SCRATCH_MNT/lowertestdir/subdir -p -o $tmp.fhandle
    # Rename lower dir offline
    unmount_dirs
    mv $lower/lowertestdir $lower/lowertestdir.new/
    mount_dirs
    # Attempt to decode lower subdir file handle
    test_file_handles $SCRATCH_MNT -p -i $tmp.fhandle

    Since this WARN_ON() can be triggered by user we need to relax it.

    Fixes: 4b91c30a5a19 ("ovl: lookup connected ancestor of dir in inode cache")
    Cc: # v4.16+
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     

04 Jun, 2020

1 commit


13 May, 2020

2 commits

  • Overlayfs doesn't work well with the fanotify mechanism.

    Fanotify first probes for the required buffer size for the file handle,
    but overlayfs currently bails out without passing the size back.

    That results in errors in the kernel log, such as:

    [527944.485384] overlayfs: failed to encode file handle (/, err=-75, buflen=0, len=29, type=1)
    [527944.485386] fanotify: failed to encode fid (fsid=ae521e68.a434d95f, type=255, bytes=0, err=-2)

    Signed-off-by: Lubos Dolezel
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Lubos Dolezel
     
  • The "buflen" value comes from the user and there is a potential that it
    could be zero. In do_handle_to_path() we know that "handle->handle_bytes"
    is non-zero and we do:

    handle_dwords = handle->handle_bytes >> 2;

    So values 1-3 become zero. Then in ovl_fh_to_dentry() we do:

    int len = fh_len << 2;

    So now len is in the "0,4-128" range and a multiple of 4. But if
    "buflen" is zero it will try to copy negative bytes when we do the
    memcpy in ovl_fid_to_fh().

    memcpy(&fh->fb, fid, buflen - OVL_FH_WIRE_OFFSET);

    And that will lead to a crash. Thanks to Amir Goldstein for his help
    with this patch.

    Fixes: cbe7fba8edfc ("ovl: make sure that real fid is 32bit aligned in memory")
    Signed-off-by: Dan Carpenter
    Reviewed-by: Amir Goldstein
    Cc: # v5.5
    Signed-off-by: Miklos Szeredi

    Dan Carpenter
     

17 Mar, 2020

2 commits

  • The situation is the same as for __d_obtain_alias() (which is what that
    thing is parallel to) - if we find a preexisting alias, we want to grab it,
    drop the inode and return the alias we'd found.

    The only thing d_instantiate_anon() does compared to that is spurious
    security_d_instiate() that has already been done to that dentry with exact
    same arguments.

    Signed-off-by: Al Viro
    Signed-off-by: Miklos Szeredi

    Al Viro
     
  • Allow completely skipping ->revalidate() on a per-dentry basis, in case the
    underlying layers used for a dentry do not themselves have ->revalidate().

    E.g. negative overlay dentry has no underlying layers, hence revalidate is
    unnecessary. Or if lower layer is remote but overlay dentry is pure-upper,
    then can skip revalidate.

    The following places need to update whether the dentry needs revalidate or
    not:

    - fill-super (root dentry)
    - lookup
    - create
    - fh_to_dentry

    Signed-off-by: Miklos Szeredi

    Miklos Szeredi
     

24 Jan, 2020

1 commit


23 Jan, 2020

2 commits

  • Rename lower_layers[] array to layers[], extend its size by one and
    initialize layers[0] with upper layer values. Lower layers are now
    addressed with index 1..numlower. layers[0] is reserved even with lower
    only overlay.

    [SzM: replace ofs->numlower with ofs->numlayer, the latter's value is
    incremented by one]

    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • Use pr_fmt auto generate "overlayfs: " prefix.

    Signed-off-by: lijiazi
    Signed-off-by: Miklos Szeredi

    lijiazi
     

10 Dec, 2019

1 commit

  • Seprate on-disk encoding from in-memory and on-wire resresentation
    of overlay file handle.

    In-memory and on-wire we only ever pass around pointers to struct
    ovl_fh, which encapsulates at offset 3 the on-disk format struct
    ovl_fb. struct ovl_fb encapsulates at offset 21 the real file handle.
    That makes sure that the real file handle is always 32bit aligned
    in-memory when passed down to the underlying filesystem.

    On-disk format remains the same and store/load are done into
    correctly aligned buffer.

    New nfs exported file handles are exported with aligned real fid.
    Old nfs file handles are copied to an aligned buffer before being
    decoded.

    Reported-by: Al Viro
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     

11 Sep, 2019

1 commit

  • if ovl_encode_real_fh() fails, no memory was allocated
    and the error in the error-valued pointer should be returned.

    Fixes: 9b6faee07470 ("ovl: check ERR_PTR() return value from ovl_encode_fh()")
    Signed-off-by: Ding Xiang
    Cc: # v4.16+
    Signed-off-by: Miklos Szeredi

    Ding Xiang
     

19 Jun, 2019

1 commit

  • Based on 2 normalized pattern(s):

    this program is free software you can redistribute it and or modify
    it under the terms of the gnu general public license version 2 as
    published by the free software foundation

    this program is free software you can redistribute it and or modify
    it under the terms of the gnu general public license version 2 as
    published by the free software foundation #

    extracted by the scancode license scanner the SPDX license identifier

    GPL-2.0-only

    has been chosen to replace the boilerplate/reference in 4122 file(s).

    Signed-off-by: Thomas Gleixner
    Reviewed-by: Enrico Weigelt
    Reviewed-by: Kate Stewart
    Reviewed-by: Allison Randal
    Cc: linux-spdx@vger.kernel.org
    Link: https://lkml.kernel.org/r/20190604081206.933168790@linutronix.de
    Signed-off-by: Greg Kroah-Hartman

    Thomas Gleixner
     

27 Apr, 2019

1 commit


21 Nov, 2018

1 commit

  • When decoding a lower file handle, we first call ovl_check_origin_fh()
    with connected=false to get any real lower dentry for overlay inode
    cache lookup.

    If the real dentry is a disconnected dir dentry, ovl_check_origin_fh()
    is called again with connected=true to get a connected real dentry
    and find the lower layer the real dentry belongs to.

    If the first call returned a connected real dentry, we use it to
    lookup an overlay connected dentry, but the first ovl_check_origin_fh()
    call with connected=false did not check that the found dentry is under
    the root of the layer (see ovl_acceptable()), it only checked that
    the found dentry super block matches the uuid of the lower file handle.

    In case there are multiple lower layers on the same fs and the found
    dentry is not from the top most lower layer, using the layer index
    returned from the first ovl_check_origin_fh() is wrong and we end
    up failing to decode the file handle.

    Fix this by always calling ovl_check_origin_fh() with connected=true
    if we got a directory dentry in the first call.

    Fixes: 8b58924ad55c ("ovl: lookup in inode cache first when decoding...")
    Cc: # v4.17
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     

20 Jul, 2018

1 commit

  • This patch modifies ovl_lookup() and friends to lookup metacopy dentries.
    It also allows for presence of metacopy dentries in lower layer.

    During lookup, check for presence of OVL_XATTR_METACOPY and if not present,
    set OVL_UPPERDATA bit in flags.

    We don't support metacopy feature with nfs_export. So in nfs_export code,
    we set OVL_UPPERDATA flag set unconditionally if upper inode exists.

    Do not follow metacopy origin if we find a metacopy only inode and metacopy
    feature is not enabled for that mount. Like redirect, this can have
    security implications where an attacker could hand craft upper and try to
    gain access to file on lower which it should not have to begin with.

    Signed-off-by: Vivek Goyal
    Reviewed-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Vivek Goyal
     

31 May, 2018

1 commit

  • ovl_get_inode() right now has 5 parameters. Soon this patch series will
    add 2 more and suddenly argument list starts looking too long.

    Hence pass arguments to ovl_get_inode() in a structure and it looks
    little cleaner.

    Signed-off-by: Vivek Goyal
    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Vivek Goyal
     

12 Apr, 2018

5 commits

  • When overlay layers are not all on the same fs, but all inode numbers
    of underlying fs do not use the high 'xino' bits, overlay st_ino values
    are constant and persistent.

    In that case, set i_ino value to the same value as st_ino for nfsd
    readdirplus validator.

    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • Signed-off-by: Miklos Szeredi

    Vivek Goyal
     
  • When decoding a lower file handle, we need to check if lower file was
    copied up and indexed and if it has a whiteout index, we need to check
    if this is an unlinked but open non-dir before returning -ESTALE.

    To find out if this is an unlinked but open non-dir we need to lookup
    an overlay inode in inode cache by lower inode and that requires decoding
    the lower file handle before looking in inode cache.

    Before this change, if the lower inode turned out to be a directory, we
    may have paid an expensive cost to reconnect that lower directory for
    nothing.

    After this change, we start by decoding a disconnected lower dentry and
    using the lower inode for looking up an overlay inode in inode cache.
    If we find overlay inode and dentry in cache, we avoid the index lookup
    overhead. If we don't find an overlay inode and dentry in cache, then we
    only need to decode a connected lower dentry in case the lower dentry is
    a non-indexed directory.

    The xfstests group overlay/exportfs tests decoding overlayfs file
    handles after drop_caches with different states of the file at encode
    and decode time. Overall the tests in the group call ovl_lower_fh_to_d()
    89 times to decode a lower file handle.

    Before this change, the tests called ovl_get_index_fh() 75 times and
    reconnect_one() 61 times.
    After this change, the tests call ovl_get_index_fh() 70 times and
    reconnect_one() 59 times. The 2 cases where reconnect_one() was avoided
    are cases where a non-upper directory file handle was encoded, then the
    directory removed and then file handle was decoded.

    To demonstrate the affect on decoding file handles with hot inode/dentry
    cache, the drop_caches call in the tests was disabled. Without
    drop_caches, there are no reconnect_one() calls at all before or after
    the change. Before the change, there are 75 calls to ovl_get_index_fh(),
    exactly as the case with drop_caches. After the change, there are only
    10 calls to ovl_get_index_fh().

    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • On lookup of non directory, we try to decode the origin file handle
    stored in upper inode. The origin file handle is supposed to be decoded
    to a disconnected non-dir dentry, which is fine, because we only need
    the lower inode of a copy up origin.

    However, if the origin file handle somehow turns out to be a directory
    we pay the expensive cost of reconnecting the directory dentry, only to
    get a mismatch file type and drop the dentry.

    Optimize this case by explicitly opting out of reconnecting the dentry.
    Opting-out of reconnect is done by passing a NULL acceptable callback
    to exportfs_decode_fh().

    While the case described above is a strange corner case that does not
    really need to be optimized, the API added for this optimization will
    be used by a following patch to optimize a more common case of decoding
    an overlayfs file handle.

    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     
  • Rename ovl_encode_fh() to ovl_encode_real_fh() to differentiate from the
    exportfs function ovl_encode_inode_fh() and change the latter to
    ovl_encode_fh() to match the exportfs method name.

    Rename ovl_decode_fh() to ovl_decode_real_fh() for consistency.

    Signed-off-by: Amir Goldstein
    Signed-off-by: Miklos Szeredi

    Amir Goldstein
     

26 Feb, 2018

1 commit

  • fs/overlayfs/export.c:459:10-16: WARNING: PTR_ERR_OR_ZERO can be used

    Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR

    Generated by: scripts/coccinelle/api/ptr_ret.cocci

    Fixes: 4b91c30a5a19 ("ovl: lookup connected ancestor of dir in inode cache")
    CC: Amir Goldstein
    Signed-off-by: Fengguang Wu
    Signed-off-by: Miklos Szeredi

    Fengguang Wu