1. 09 12月, 2022 2 次提交
    • J
      udf: Fix extending file within last block · 1f3868f0
      Jan Kara 提交于
      When extending file within last block it can happen that the extent is
      already rounded to the blocksize and thus contains the offset we want to
      grow up to. In such case we would mistakenly expand the last extent and
      make it one block longer than it should be, exposing unallocated block
      in a file and causing data corruption. Fix the problem by properly
      detecting this case and bailing out.
      
      CC: stable@vger.kernel.org
      Signed-off-by: NJan Kara <jack@suse.cz>
      1f3868f0
    • J
      udf: Discard preallocation before extending file with a hole · 16d05565
      Jan Kara 提交于
      When extending file with a hole, we tried to preserve existing
      preallocation for the file. However that is not very useful and
      complicates code because the previous extent may need to be rounded to
      block boundary as well (which we forgot to do thus causing data
      corruption for sequence like:
      
      xfs_io -f -c "pwrite 0x75e63 11008" -c "truncate 0x7b24b" \
        -c "truncate 0xabaa3" -c "pwrite 0xac70b 22954" \
        -c "pwrite 0x93a43 11358" -c "pwrite 0xb8e65 52211" file
      
      with 512-byte block size. Just discard preallocation before extending
      file to simplify things and also fix this data corruption.
      
      CC: stable@vger.kernel.org
      Signed-off-by: NJan Kara <jack@suse.cz>
      16d05565
  2. 21 11月, 2022 1 次提交
    • C
      udf: remove ->writepage · 36273e5b
      Christoph Hellwig 提交于
      ->writepage is a very inefficient method to write back data, and only
      used through write_cache_pages or as a fallback when no ->migrate_folio
      method is present.
      
      Set ->migrate_folio to the generic buffer_head based helper, and remove
      the ->writepage implementation in extfat.
      Signed-off-by: NChristoph Hellwig <hch@lst.de>
      Signed-off-by: NJan Kara <jack@suse.cz>
      36273e5b
  3. 12 9月, 2022 1 次提交
  4. 15 7月, 2022 1 次提交
  5. 10 5月, 2022 1 次提交
  6. 09 5月, 2022 2 次提交
  7. 17 3月, 2022 1 次提交
  8. 15 3月, 2022 1 次提交
  9. 24 1月, 2022 2 次提交
    • J
      udf: Restore i_lenAlloc when inode expansion fails · ea856919
      Jan Kara 提交于
      When we fail to expand inode from inline format to a normal format, we
      restore inode to contain the original inline formatting but we forgot to
      set i_lenAlloc back. The mismatch between i_lenAlloc and i_size was then
      causing further problems such as warnings and lost data down the line.
      Reported-by: Nbutt3rflyh4ck <butterflyhuangxx@gmail.com>
      CC: stable@vger.kernel.org
      Fixes: 7e49b6f2 ("udf: Convert UDF to new truncate calling sequence")
      Reviewed-by: NChristoph Hellwig <hch@lst.de>
      Signed-off-by: NJan Kara <jack@suse.cz>
      ea856919
    • J
      udf: Fix NULL ptr deref when converting from inline format · 7fc3b7c2
      Jan Kara 提交于
      udf_expand_file_adinicb() calls directly ->writepage to write data
      expanded into a page. This however misses to setup inode for writeback
      properly and so we can crash on inode->i_wb dereference when submitting
      page for IO like:
      
        BUG: kernel NULL pointer dereference, address: 0000000000000158
        #PF: supervisor read access in kernel mode
      ...
        <TASK>
        __folio_start_writeback+0x2ac/0x350
        __block_write_full_page+0x37d/0x490
        udf_expand_file_adinicb+0x255/0x400 [udf]
        udf_file_write_iter+0xbe/0x1b0 [udf]
        new_sync_write+0x125/0x1c0
        vfs_write+0x28e/0x400
      
      Fix the problem by marking the page dirty and going through the standard
      writeback path to write the page. Strictly speaking we would not even
      have to write the page but we want to catch e.g. ENOSPC errors early.
      Reported-by: Nbutt3rflyh4ck <butterflyhuangxx@gmail.com>
      CC: stable@vger.kernel.org
      Fixes: 52ebea74 ("writeback: make backing_dev_info host cgroup-specific bdi_writebacks")
      Reviewed-by: NChristoph Hellwig <hch@lst.de>
      Signed-off-by: NJan Kara <jack@suse.cz>
      7fc3b7c2
  10. 11 8月, 2021 1 次提交
  11. 30 6月, 2021 1 次提交
  12. 26 1月, 2021 1 次提交
  13. 29 9月, 2020 2 次提交
  14. 03 6月, 2020 1 次提交
  15. 08 1月, 2020 1 次提交
  16. 27 8月, 2019 1 次提交
    • S
      udf: augment UDF permissions on new inodes · c3367a1b
      Steven J. Magnani 提交于
      Windows presents files created within Linux as read-only, even when
      permissions in Linux indicate the file should be writable.
      
      UDF defines a slightly different set of basic file permissions than Linux.
      Specifically, UDF has "delete" and "change attribute" permissions for each
      access class (user/group/other). Linux has no equivalents for these.
      
      When the Linux UDF driver creates a file (or directory), no UDF delete or
      change attribute permissions are granted. The lack of delete permission
      appears to cause Windows to mark an item read-only when its permissions
      otherwise indicate that it should be read-write.
      
      Fix this by having UDF delete permissions track Linux write permissions.
      Also grant UDF change attribute permission to the owner when creating a
      new inode.
      
      Reported by: Ty Young
      Signed-off-by: NSteven J. Magnani <steve@digidescorp.com>
      Link: https://lore.kernel.org/r/20190827121359.9954-1-steve@digidescorp.comSigned-off-by: NJan Kara <jack@suse.cz>
      c3367a1b
  17. 26 8月, 2019 1 次提交
  18. 10 7月, 2019 1 次提交
  19. 18 3月, 2019 1 次提交
  20. 12 12月, 2018 1 次提交
  21. 27 6月, 2018 1 次提交
  22. 20 6月, 2018 1 次提交
  23. 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
  24. 26 5月, 2018 1 次提交
    • D
      udf: Simplify calls to udf_disk_stamp_to_time · 0220edda
      Deepa Dinamani 提交于
      Subsequent patches in the series convert inode timestamps
      to use struct timespec64 instead of struct timespec as
      part of solving the y2038 problem.
      
      commit fd3cfad3 ("udf: Convert udf_disk_stamp_to_time() to use mktime64()")
      eliminated the NULL return condition from udf_disk_stamp_to_time().
      udf_time_to_disk_time() is always called with a valid dest pointer and
      the return value is ignored.
      Further, caller can as well check the dest pointer being passed in rather
      than return argument.
      Make both the functions return void.
      
      This will make the inode timestamp conversion simpler.
      Signed-off-by: NDeepa Dinamani <deepa.kernel@gmail.com>
      Cc: jack@suse.com
      
      ----
      Changes from v1:
      * fixed the pointer error pointed by Jan
      0220edda
  25. 27 2月, 2018 2 次提交
    • J
      udf: Clean up handling of invalid uid/gid · 0c9850f4
      Jan Kara 提交于
      Current code relies on the fact that invalid uid/gid as defined by UDF
      2.60 3.3.3.1 and 3.3.3.2 coincides with invalid uid/gid as used by the
      user namespaces implementation. Since this is only lucky coincidence,
      clean this up to avoid future surprises in case user namespaces
      implementation changes. Also this is more robust in presence of valid
      (from UDF point of view) uids / gids which do not map into current user
      namespace.
      Reviewed-by: NPali Rohár <pali.rohar@gmail.com>
      Signed-off-by: NJan Kara <jack@suse.cz>
      0c9850f4
    • J
      udf: Ignore [ug]id=ignore mount options · 70260e44
      Jan Kara 提交于
      Currently uid=ignore and gid=ignore make no sense without uid=<number>
      and gid=<number> respectively as they result in all files having invalid
      uid / gid which then doesn't allow even root to modify files and thus
      causes confusion. And since commit ca76d2d8 "UDF: fix UID and GID
      mount option ignorance" (from over 10 years ago) uid=<number> overrides
      all uids on disk as uid=ignore does. So just silently ignore uid=ignore
      mount option.
      Reviewed-by: NPali Rohár <pali.rohar@gmail.com>
      Signed-off-by: NJan Kara <jack@suse.cz>
      70260e44
  26. 17 10月, 2017 3 次提交
    • S
      udf: Fix some sign-conversion warnings · 89a4d970
      Steve Magnani 提交于
      Fix some warnings that appear when compiling with -Wconversion.
      A sub-optimal choice of variable type leads to warnings about
      conversion in both directions between unsigned and signed.
      Signed-off-by: NSteven J. Magnani <steve@digidescorp.com>
      Signed-off-by: NJan Kara <jack@suse.cz>
      89a4d970
    • S
      udf: Fix signed/unsigned format specifiers · fcbf7637
      Steve Magnani 提交于
      Fix problems noted in compilion with -Wformat=2 -Wformat-signedness.
      In particular, a mismatch between the signedness of a value and the
      signedness of its format specifier can result in unsigned values being
      printed as negative numbers, e.g.:
      
        Partition (0 type 1511) starts at physical 460, block length -1779968542
      
      ...which occurs when mounting a large (> 1 TiB) UDF partition.
      
      Changes since V1:
      * Fixed additional issues noted in udf_bitmap_free_blocks(),
        udf_get_fileident(), udf_show_options()
      Signed-off-by: NSteven J. Magnani <steve@digidescorp.com>
      Signed-off-by: NJan Kara <jack@suse.cz>
      fcbf7637
    • S
      udf: Fix 64-bit sign extension issues affecting blocks > 0x7FFFFFFF · b490bdd6
      Steve Magnani 提交于
      Large (> 1 TiB) UDF filesystems appear subject to several problems when
      mounted on 64-bit systems:
      
      * readdir() can fail on a directory containing File Identifiers residing
        above 0x7FFFFFFF. This manifests as a 'ls' command failing with EIO.
      
      * FIBMAP on a file block located above 0x7FFFFFFF can return a negative
        value. The low 32 bits are correct, but applications that don't mask the
        high 32 bits of the result can perform incorrectly.
      
      Per suggestion by Jan Kara, introduce a udf_pblk_t type for representation
      of UDF block addresses. Ultimately, all driver functions that manipulate
      UDF block addresses should use this type; for now, deployment is limited
      to functions with actual or potential sign extension issues.
      
      Changes to udf_readdir() and udf_block_map() address the issues noted
      above; other changes address potential similar issues uncovered during
      audit of the driver code.
      Signed-off-by: NSteven J. Magnani <steve@digidescorp.com>
      Signed-off-by: NJan Kara <jack@suse.cz>
      b490bdd6
  27. 16 8月, 2017 2 次提交
  28. 14 6月, 2017 1 次提交
    • J
      udf: Fix deadlock between writeback and udf_setsize() · f2e95355
      Jan Kara 提交于
      udf_setsize() called truncate_setsize() with i_data_sem held. Thus
      truncate_pagecache() called from truncate_setsize() could lock a page
      under i_data_sem which can deadlock as page lock ranks below
      i_data_sem - e. g. writeback can hold page lock and try to acquire
      i_data_sem to map a block.
      
      Fix the problem by moving truncate_setsize() calls from under
      i_data_sem. It is safe for us to change i_size without holding
      i_data_sem as all the places that depend on i_size being stable already
      hold inode_lock.
      
      CC: stable@vger.kernel.org
      Fixes: 7e49b6f2Signed-off-by: NJan Kara <jack@suse.cz>
      f2e95355
  29. 24 4月, 2017 2 次提交
  30. 28 2月, 2017 1 次提交
  31. 10 1月, 2017 1 次提交