1. 16 6月, 2020 1 次提交
  2. 18 12月, 2019 1 次提交
    • A
      ovl: fix corner case of non-unique st_dev;st_ino · 3e929ddf
      Amir Goldstein 提交于
      commit 9c6d8f13e9da10a26ad7f0a020ef86e8ef142835 upstream.
      
      On non-samefs overlay without xino, non pure upper inodes should use a
      pseudo_dev assigned to each unique lower fs and pure upper inodes use the
      real upper st_dev.
      
      It is fine for an overlay pure upper inode to use the same st_dev;st_ino
      values as the real upper inode, because the content of those two different
      filesystem objects is always the same.
      
      In this case, however:
       - two filesystems, A and B
       - upper layer is on A
       - lower layer 1 is also on A
       - lower layer 2 is on B
      
      Non pure upper overlay inode, whose origin is in layer 1 will have the same
      st_dev;st_ino values as the real lower inode. This may result with a false
      positive results of 'diff' between the real lower and copied up overlay
      inode.
      
      Fix this by using the upper st_dev;st_ino values in this case.  This breaks
      the property of constant st_dev;st_ino across copy up of this case. This
      breakage will be fixed by a later patch.
      
      Fixes: 5148626b ("ovl: allocate anon bdev per unique lower fs")
      Cc: stable@vger.kernel.org # v4.17+
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      3e929ddf
  3. 05 10月, 2019 1 次提交
    • M
      ovl: filter of trusted xattr results in audit · 934243a7
      Mark Salyzyn 提交于
      commit 5c2e9f346b815841f9bed6029ebcb06415caf640 upstream.
      
      When filtering xattr list for reading, presence of trusted xattr
      results in a security audit log.  However, if there is other content
      no errno will be set, and if there isn't, the errno will be -ENODATA
      and not -EPERM as is usually associated with a lack of capability.
      The check does not block the request to list the xattrs present.
      
      Switch to ns_capable_noaudit to reflect a more appropriate check.
      Signed-off-by: NMark Salyzyn <salyzyn@android.com>
      Cc: linux-security-module@vger.kernel.org
      Cc: kernel-team@android.com
      Cc: stable@vger.kernel.org # v3.18+
      Fixes: a082c6f6 ("ovl: filter trusted xattr for non-admin")
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      934243a7
  4. 25 6月, 2019 2 次提交
    • A
      ovl: detect overlapping layers · f1c5aa5e
      Amir Goldstein 提交于
      [ Upstream commit 146d62e5a5867fbf84490d82455718bfb10fe824 ]
      
      Overlapping overlay layers are not supported and can cause unexpected
      behavior, but overlayfs does not currently check or warn about these
      configurations.
      
      User is not supposed to specify the same directory for upper and
      lower dirs or for different lower layers and user is not supposed to
      specify directories that are descendants of each other for overlay
      layers, but that is exactly what this zysbot repro did:
      
          https://syzkaller.appspot.com/x/repro.syz?x=12c7a94f400000
      
      Moving layer root directories into other layers while overlayfs
      is mounted could also result in unexpected behavior.
      
      This commit places "traps" in the overlay inode hash table.
      Those traps are dummy overlay inodes that are hashed by the layers
      root inodes.
      
      On mount, the hash table trap entries are used to verify that overlay
      layers are not overlapping.  While at it, we also verify that overlay
      layers are not overlapping with directories "in-use" by other overlay
      instances as upperdir/workdir.
      
      On lookup, the trap entries are used to verify that overlay layers
      root inodes have not been moved into other layers after mount.
      
      Some examples:
      
      $ ./run --ov --samefs -s
      ...
      ( mkdir -p base/upper/0/u base/upper/0/w base/lower lower upper mnt
        mount -o bind base/lower lower
        mount -o bind base/upper upper
        mount -t overlay none mnt ...
              -o lowerdir=lower,upperdir=upper/0/u,workdir=upper/0/w)
      
      $ umount mnt
      $ mount -t overlay none mnt ...
              -o lowerdir=base,upperdir=upper/0/u,workdir=upper/0/w
      
        [   94.434900] overlayfs: overlapping upperdir path
        mount: mount overlay on mnt failed: Too many levels of symbolic links
      
      $ mount -t overlay none mnt ...
              -o lowerdir=upper/0/u,upperdir=upper/0/u,workdir=upper/0/w
      
        [  151.350132] overlayfs: conflicting lowerdir path
        mount: none is already mounted or mnt busy
      
      $ mount -t overlay none mnt ...
              -o lowerdir=lower:lower/a,upperdir=upper/0/u,workdir=upper/0/w
      
        [  201.205045] overlayfs: overlapping lowerdir path
        mount: mount overlay on mnt failed: Too many levels of symbolic links
      
      $ mount -t overlay none mnt ...
              -o lowerdir=lower,upperdir=upper/0/u,workdir=upper/0/w
      $ mv base/upper/0/ base/lower/
      $ find mnt/0
        mnt/0
        mnt/0/w
        find: 'mnt/0/w/work': Too many levels of symbolic links
        find: 'mnt/0/u': Too many levels of symbolic links
      
      Reported-by: syzbot+9c69c282adc4edd2b540@syzkaller.appspotmail.com
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      Signed-off-by: NSasha Levin <sashal@kernel.org>
      f1c5aa5e
    • A
      ovl: make i_ino consistent with st_ino in more cases · a00f405e
      Amir Goldstein 提交于
      [ Upstream commit 6dde1e42f497b2d4e22466f23019016775607947 ]
      
      Relax the condition that overlayfs supports nfs export, to require
      that i_ino is consistent with st_ino/d_ino.
      
      It is enough to require that st_ino and d_ino are consistent.
      
      This fixes the failure of xfstest generic/504, due to mismatch of
      st_ino to inode number in the output of /proc/locks.
      
      Fixes: 12574a9f ("ovl: consistent i_ino for non-samefs with xino")
      Cc: <stable@vger.kernel.org> # v4.19
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      Signed-off-by: NSasha Levin <sashal@kernel.org>
      a00f405e
  5. 31 5月, 2019 1 次提交
    • A
      ovl: relax WARN_ON() for overlapping layers use case · 86c43c40
      Amir Goldstein 提交于
      commit acf3062a7e1ccf67c6f7e7c28671a6708fde63b0 upstream.
      
      This nasty little syzbot repro:
      https://syzkaller.appspot.com/x/repro.syz?x=12c7a94f400000
      
      Creates overlay mounts where the same directory is both in upper and lower
      layers. Simplified example:
      
        mkdir foo work
        mount -t overlay none foo -o"lowerdir=.,upperdir=foo,workdir=work"
      
      The repro runs several threads in parallel that attempt to chdir into foo
      and attempt to symlink/rename/exec/mkdir the file bar.
      
      The repro hits a WARN_ON() I placed in ovl_instantiate(), which suggests
      that an overlay inode already exists in cache and is hashed by the pointer
      of the real upper dentry that ovl_create_real() has just created. At the
      point of the WARN_ON(), for overlay dir inode lock is held and upper dir
      inode lock, so at first, I did not see how this was possible.
      
      On a closer look, I see that after ovl_create_real(), because of the
      overlapping upper and lower layers, a lookup by another thread can find the
      file foo/bar that was just created in upper layer, at overlay path
      foo/foo/bar and hash the an overlay inode with the new real dentry as lower
      dentry. This is possible because the overlay directory foo/foo is not
      locked and the upper dentry foo/bar is in dcache, so ovl_lookup() can find
      it without taking upper dir inode shared lock.
      
      Overlapping layers is considered a wrong setup which would result in
      unexpected behavior, but it shouldn't crash the kernel and it shouldn't
      trigger WARN_ON() either, so relax this WARN_ON() and leave a pr_warn()
      instead to cover all cases of failure to get an overlay inode.
      
      The error returned from failure to insert new inode to cache with
      inode_insert5() was changed to -EEXIST, to distinguish from the error
      -ENOMEM returned on failure to get/allocate inode with iget5_locked().
      
      Reported-by: syzbot+9c69c282adc4edd2b540@syzkaller.appspotmail.com
      Fixes: 01b39dcc ("ovl: use inode_insert5() to hash a newly...")
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      86c43c40
  6. 26 9月, 2018 1 次提交
  7. 30 8月, 2018 2 次提交
    • A
      ovl: fix GPF in swapfile_activate of file from overlayfs over xfs · 5b910bd6
      Amir Goldstein 提交于
      Since overlayfs implements stacked file operations, the underlying
      filesystems are not supposed to be exposed to the overlayfs file,
      whose f_inode is an overlayfs inode.
      
      Assigning an overlayfs file to swap_file results in an attempt of xfs
      code to dereference an xfs_inode struct from an ovl_inode pointer:
      
       CPU: 0 PID: 2462 Comm: swapon Not tainted
       4.18.0-xfstests-12721-g33e17876 #3402
       RIP: 0010:xfs_find_bdev_for_inode+0x23/0x2f
       Call Trace:
        xfs_iomap_swapfile_activate+0x1f/0x43
        __se_sys_swapon+0xb1a/0xee9
      
      Fix this by not assigning the real inode mapping to f_mapping, which
      will cause swapon() to return an error (-EINVAL). Although it makes
      sense not to allow setting swpafile on an overlayfs file, some users
      may depend on it, so we may need to fix this up in the future.
      
      Keeping f_mapping pointing to overlay inode mapping will cause O_DIRECT
      open to fail. Fix this by installing ovl_aops with noop_direct_IO in
      overlay inode mapping.
      
      Keeping f_mapping pointing to overlay inode mapping will cause other
      a_ops related operations to fail (e.g. readahead()). Those will be
      fixed by follow up patches.
      Suggested-by: NMiklos Szeredi <mszeredi@redhat.com>
      Fixes: f7c72396 ("ovl: add O_DIRECT support")
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      5b910bd6
    • A
      ovl: respect FIEMAP_FLAG_SYNC flag · 80d34810
      Amir Goldstein 提交于
      Stacked overlayfs fiemap operation broke xfstests that test delayed
      allocation (with "_test_generic_punch -d"), because ovl_fiemap()
      failed to write dirty pages when requested.
      
      Fixes: 9e142c41 ("ovl: add ovl_fiemap()")
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      80d34810
  8. 20 7月, 2018 8 次提交
  9. 18 7月, 2018 5 次提交
    • M
      ovl: add ovl_fiemap() · 9e142c41
      Miklos Szeredi 提交于
      Implement stacked fiemap().
      
      Need to split inode operations for regular file (which has fiemap) and
      special file (which doesn't have fiemap).
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      9e142c41
    • M
      ovl: stack file ops · d1d04ef8
      Miklos Szeredi 提交于
      Implement file operations on a regular overlay file.  The underlying file
      is opened separately and cached in ->private_data.
      
      It might be worth making an exception for such files when accounting in
      nr_file to confirm to userspace expectations.  We are only adding a small
      overhead (248bytes for the struct file) since the real inode and dentry are
      pinned by overlayfs anyway.
      
      This patch doesn't have any effect, since the vfs will use d_real() to find
      the real underlying file to open.  The patch at the end of the series will
      actually enable this functionality.
      
      AV: make it use open_with_fake_path(), don't mess with override_creds
      
      SzM: still need to mess with override_creds() until no fs uses
      current_cred() in their open method.
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      d1d04ef8
    • M
      ovl: copy up file size as well · 46e5d0a3
      Miklos Szeredi 提交于
      Copy i_size of the underlying inode to the overlay inode in ovl_copyattr().
      
      This is in preparation for stacking I/O operations on overlay files.
      
      This patch shouldn't have any observable effect.
      
      Remove stale comment from ovl_setattr() [spotted by Vivek Goyal].
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      46e5d0a3
    • M
      Revert "Revert "ovl: get_write_access() in truncate"" · 5812160e
      Miklos Szeredi 提交于
      This reverts commit 31c3a706.
      
      Re-add functionality dealing with i_writecount on truncate to overlayfs.
      This patch shouldn't have any observable effects, since we just re-assert
      the writecout that vfs_truncate() already got for us.
      
      This is in preparation for moving overlay functionality out of the VFS.
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      5812160e
    • M
      ovl: copy up times · d9854c87
      Miklos Szeredi 提交于
      Copy up mtime and ctime to overlay inode after times in real object are
      modified.  Be careful not to dirty cachelines when not necessary.
      
      This is in preparation for moving overlay functionality out of the VFS.
      
      This patch shouldn't have any observable effect.
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      d9854c87
  10. 06 6月, 2018 1 次提交
    • D
      vfs: change inode times to use struct timespec64 · 95582b00
      Deepa Dinamani 提交于
      struct timespec is not y2038 safe. Transition vfs to use
      y2038 safe struct timespec64 instead.
      
      The change was made with the help of the following cocinelle
      script. This catches about 80% of the changes.
      All the header file and logic changes are included in the
      first 5 rules. The rest are trivial substitutions.
      I avoid changing any of the function signatures or any other
      filesystem specific data structures to keep the patch simple
      for review.
      
      The script can be a little shorter by combining different cases.
      But, this version was sufficient for my usecase.
      
      virtual patch
      
      @ depends on patch @
      identifier now;
      @@
      - struct timespec
      + struct timespec64
        current_time ( ... )
        {
      - struct timespec now = current_kernel_time();
      + struct timespec64 now = current_kernel_time64();
        ...
      - return timespec_trunc(
      + return timespec64_trunc(
        ... );
        }
      
      @ depends on patch @
      identifier xtime;
      @@
       struct \( iattr \| inode \| kstat \) {
       ...
      -       struct timespec xtime;
      +       struct timespec64 xtime;
       ...
       }
      
      @ depends on patch @
      identifier t;
      @@
       struct inode_operations {
       ...
      int (*update_time) (...,
      -       struct timespec t,
      +       struct timespec64 t,
      ...);
       ...
       }
      
      @ depends on patch @
      identifier t;
      identifier fn_update_time =~ "update_time$";
      @@
       fn_update_time (...,
      - struct timespec *t,
      + struct timespec64 *t,
       ...) { ... }
      
      @ depends on patch @
      identifier t;
      @@
      lease_get_mtime( ... ,
      - struct timespec *t
      + struct timespec64 *t
        ) { ... }
      
      @te depends on patch forall@
      identifier ts;
      local idexpression struct inode *inode_node;
      identifier i_xtime =~ "^i_[acm]time$";
      identifier ia_xtime =~ "^ia_[acm]time$";
      identifier fn_update_time =~ "update_time$";
      identifier fn;
      expression e, E3;
      local idexpression struct inode *node1;
      local idexpression struct inode *node2;
      local idexpression struct iattr *attr1;
      local idexpression struct iattr *attr2;
      local idexpression struct iattr attr;
      identifier i_xtime1 =~ "^i_[acm]time$";
      identifier i_xtime2 =~ "^i_[acm]time$";
      identifier ia_xtime1 =~ "^ia_[acm]time$";
      identifier ia_xtime2 =~ "^ia_[acm]time$";
      @@
      (
      (
      - struct timespec ts;
      + struct timespec64 ts;
      |
      - struct timespec ts = current_time(inode_node);
      + struct timespec64 ts = current_time(inode_node);
      )
      
      <+... when != ts
      (
      - timespec_equal(&inode_node->i_xtime, &ts)
      + timespec64_equal(&inode_node->i_xtime, &ts)
      |
      - timespec_equal(&ts, &inode_node->i_xtime)
      + timespec64_equal(&ts, &inode_node->i_xtime)
      |
      - timespec_compare(&inode_node->i_xtime, &ts)
      + timespec64_compare(&inode_node->i_xtime, &ts)
      |
      - timespec_compare(&ts, &inode_node->i_xtime)
      + timespec64_compare(&ts, &inode_node->i_xtime)
      |
      ts = current_time(e)
      |
      fn_update_time(..., &ts,...)
      |
      inode_node->i_xtime = ts
      |
      node1->i_xtime = ts
      |
      ts = inode_node->i_xtime
      |
      <+... attr1->ia_xtime ...+> = ts
      |
      ts = attr1->ia_xtime
      |
      ts.tv_sec
      |
      ts.tv_nsec
      |
      btrfs_set_stack_timespec_sec(..., ts.tv_sec)
      |
      btrfs_set_stack_timespec_nsec(..., ts.tv_nsec)
      |
      - ts = timespec64_to_timespec(
      + ts =
      ...
      -)
      |
      - ts = ktime_to_timespec(
      + ts = ktime_to_timespec64(
      ...)
      |
      - ts = E3
      + ts = timespec_to_timespec64(E3)
      |
      - ktime_get_real_ts(&ts)
      + ktime_get_real_ts64(&ts)
      |
      fn(...,
      - ts
      + timespec64_to_timespec(ts)
      ,...)
      )
      ...+>
      (
      <... when != ts
      - return ts;
      + return timespec64_to_timespec(ts);
      ...>
      )
      |
      - timespec_equal(&node1->i_xtime1, &node2->i_xtime2)
      + timespec64_equal(&node1->i_xtime2, &node2->i_xtime2)
      |
      - timespec_equal(&node1->i_xtime1, &attr2->ia_xtime2)
      + timespec64_equal(&node1->i_xtime2, &attr2->ia_xtime2)
      |
      - timespec_compare(&node1->i_xtime1, &node2->i_xtime2)
      + timespec64_compare(&node1->i_xtime1, &node2->i_xtime2)
      |
      node1->i_xtime1 =
      - timespec_trunc(attr1->ia_xtime1,
      + timespec64_trunc(attr1->ia_xtime1,
      ...)
      |
      - attr1->ia_xtime1 = timespec_trunc(attr2->ia_xtime2,
      + attr1->ia_xtime1 =  timespec64_trunc(attr2->ia_xtime2,
      ...)
      |
      - ktime_get_real_ts(&attr1->ia_xtime1)
      + ktime_get_real_ts64(&attr1->ia_xtime1)
      |
      - ktime_get_real_ts(&attr.ia_xtime1)
      + ktime_get_real_ts64(&attr.ia_xtime1)
      )
      
      @ depends on patch @
      struct inode *node;
      struct iattr *attr;
      identifier fn;
      identifier i_xtime =~ "^i_[acm]time$";
      identifier ia_xtime =~ "^ia_[acm]time$";
      expression e;
      @@
      (
      - fn(node->i_xtime);
      + fn(timespec64_to_timespec(node->i_xtime));
      |
       fn(...,
      - node->i_xtime);
      + timespec64_to_timespec(node->i_xtime));
      |
      - e = fn(attr->ia_xtime);
      + e = fn(timespec64_to_timespec(attr->ia_xtime));
      )
      
      @ depends on patch forall @
      struct inode *node;
      struct iattr *attr;
      identifier i_xtime =~ "^i_[acm]time$";
      identifier ia_xtime =~ "^ia_[acm]time$";
      identifier fn;
      @@
      {
      + struct timespec ts;
      <+...
      (
      + ts = timespec64_to_timespec(node->i_xtime);
      fn (...,
      - &node->i_xtime,
      + &ts,
      ...);
      |
      + ts = timespec64_to_timespec(attr->ia_xtime);
      fn (...,
      - &attr->ia_xtime,
      + &ts,
      ...);
      )
      ...+>
      }
      
      @ depends on patch forall @
      struct inode *node;
      struct iattr *attr;
      struct kstat *stat;
      identifier ia_xtime =~ "^ia_[acm]time$";
      identifier i_xtime =~ "^i_[acm]time$";
      identifier xtime =~ "^[acm]time$";
      identifier fn, ret;
      @@
      {
      + struct timespec ts;
      <+...
      (
      + ts = timespec64_to_timespec(node->i_xtime);
      ret = fn (...,
      - &node->i_xtime,
      + &ts,
      ...);
      |
      + ts = timespec64_to_timespec(node->i_xtime);
      ret = fn (...,
      - &node->i_xtime);
      + &ts);
      |
      + ts = timespec64_to_timespec(attr->ia_xtime);
      ret = fn (...,
      - &attr->ia_xtime,
      + &ts,
      ...);
      |
      + ts = timespec64_to_timespec(attr->ia_xtime);
      ret = fn (...,
      - &attr->ia_xtime);
      + &ts);
      |
      + ts = timespec64_to_timespec(stat->xtime);
      ret = fn (...,
      - &stat->xtime);
      + &ts);
      )
      ...+>
      }
      
      @ depends on patch @
      struct inode *node;
      struct inode *node2;
      identifier i_xtime1 =~ "^i_[acm]time$";
      identifier i_xtime2 =~ "^i_[acm]time$";
      identifier i_xtime3 =~ "^i_[acm]time$";
      struct iattr *attrp;
      struct iattr *attrp2;
      struct iattr attr ;
      identifier ia_xtime1 =~ "^ia_[acm]time$";
      identifier ia_xtime2 =~ "^ia_[acm]time$";
      struct kstat *stat;
      struct kstat stat1;
      struct timespec64 ts;
      identifier xtime =~ "^[acmb]time$";
      expression e;
      @@
      (
      ( node->i_xtime2 \| attrp->ia_xtime2 \| attr.ia_xtime2 \) = node->i_xtime1  ;
      |
       node->i_xtime2 = \( node2->i_xtime1 \| timespec64_trunc(...) \);
      |
       node->i_xtime2 = node->i_xtime1 = node->i_xtime3 = \(ts \| current_time(...) \);
      |
       node->i_xtime1 = node->i_xtime3 = \(ts \| current_time(...) \);
      |
       stat->xtime = node2->i_xtime1;
      |
       stat1.xtime = node2->i_xtime1;
      |
      ( node->i_xtime2 \| attrp->ia_xtime2 \) = attrp->ia_xtime1  ;
      |
      ( attrp->ia_xtime1 \| attr.ia_xtime1 \) = attrp2->ia_xtime2;
      |
      - e = node->i_xtime1;
      + e = timespec64_to_timespec( node->i_xtime1 );
      |
      - e = attrp->ia_xtime1;
      + e = timespec64_to_timespec( attrp->ia_xtime1 );
      |
      node->i_xtime1 = current_time(...);
      |
       node->i_xtime2 = node->i_xtime1 = node->i_xtime3 =
      - e;
      + timespec_to_timespec64(e);
      |
       node->i_xtime1 = node->i_xtime3 =
      - e;
      + timespec_to_timespec64(e);
      |
      - node->i_xtime1 = e;
      + node->i_xtime1 = timespec_to_timespec64(e);
      )
      Signed-off-by: NDeepa Dinamani <deepa.kernel@gmail.com>
      Cc: <anton@tuxera.com>
      Cc: <balbi@kernel.org>
      Cc: <bfields@fieldses.org>
      Cc: <darrick.wong@oracle.com>
      Cc: <dhowells@redhat.com>
      Cc: <dsterba@suse.com>
      Cc: <dwmw2@infradead.org>
      Cc: <hch@lst.de>
      Cc: <hirofumi@mail.parknet.co.jp>
      Cc: <hubcap@omnibond.com>
      Cc: <jack@suse.com>
      Cc: <jaegeuk@kernel.org>
      Cc: <jaharkes@cs.cmu.edu>
      Cc: <jslaby@suse.com>
      Cc: <keescook@chromium.org>
      Cc: <mark@fasheh.com>
      Cc: <miklos@szeredi.hu>
      Cc: <nico@linaro.org>
      Cc: <reiserfs-devel@vger.kernel.org>
      Cc: <richard@nod.at>
      Cc: <sage@redhat.com>
      Cc: <sfrench@samba.org>
      Cc: <swhiteho@redhat.com>
      Cc: <tj@kernel.org>
      Cc: <trond.myklebust@primarydata.com>
      Cc: <tytso@mit.edu>
      Cc: <viro@zeniv.linux.org.uk>
      95582b00
  11. 31 5月, 2018 2 次提交
    • A
      ovl: use inode_insert5() to hash a newly created inode · 01b39dcc
      Amir Goldstein 提交于
      Currently, there is a small window where ovl_obtain_alias() can
      race with ovl_instantiate() and create two different overlay inodes
      with the same underlying real non-dir non-hardlink inode.
      
      The race requires an adversary to guess the file handle of the
      yet to be created upper inode and decode the guessed file handle
      after ovl_creat_real(), but before ovl_instantiate().
      This race does not affect overlay directory inodes, because those
      are decoded via ovl_lookup_real() and not with ovl_obtain_alias().
      
      This patch fixes the race, by using inode_insert5() to add a newly
      created inode to cache.
      
      If the newly created inode apears to already exist in cache (hashed
      by the same real upper inode), we instantiate the dentry with the old
      inode and drop the new inode, instead of silently not hashing the new
      inode.
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      01b39dcc
    • V
      ovl: Pass argument to ovl_get_inode() in a structure · ac6a52eb
      Vivek Goyal 提交于
      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: NVivek Goyal <vgoyal@redhat.com>
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      ac6a52eb
  12. 12 4月, 2018 8 次提交
  13. 16 2月, 2018 1 次提交
    • A
      ovl: hash non-dir by lower inode for fsnotify · 764baba8
      Amir Goldstein 提交于
      Commit 31747eda ("ovl: hash directory inodes for fsnotify")
      fixed an issue of inotify watch on directory that stops getting
      events after dropping dentry caches.
      
      A similar issue exists for non-dir non-upper files, for example:
      
      $ mkdir -p lower upper work merged
      $ touch lower/foo
      $ mount -t overlay -o
      lowerdir=lower,workdir=work,upperdir=upper none merged
      $ inotifywait merged/foo &
      $ echo 2 > /proc/sys/vm/drop_caches
      $ cat merged/foo
      
      inotifywait doesn't get the OPEN event, because ovl_lookup() called
      from 'cat' allocates a new overlay inode and does not reuse the
      watched inode.
      
      Fix this by hashing non-dir overlay inodes by lower real inode in
      the following cases that were not hashed before this change:
       - A non-upper overlay mount
       - A lower non-hardlink when index=off
      
      A helper ovl_hash_bylower() was added to put all the logic and
      documentation about which real inode an overlay inode is hashed by
      into one place.
      
      The issue dates back to initial version of overlayfs, but this
      patch depends on ovl_inode code that was introduced in kernel v4.13.
      
      Cc: <stable@vger.kernel.org> #v4.13
      Signed-off-by: NAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
      764baba8
  14. 24 1月, 2018 6 次提交