27 Feb, 2019

1 commit


31 Jan, 2019

1 commit

  • commit d95e674c01cfb5461e8b9fdeebf6d878c9b80b2f upstream.

    snap realm and corresponding inode have pointers to each other.
    The two pointer should get clear at the same time. Otherwise,
    snap realm's pointer may reference freed inode.

    Cc: stable@vger.kernel.org # 4.17+
    Signed-off-by: "Yan, Zheng"
    Reviewed-by: Luis Henriques
    Signed-off-by: Ilya Dryomov
    Signed-off-by: Greg Kroah-Hartman

    Yan, Zheng
     

13 Jan, 2019

1 commit

  • commit 3c1392d4c49962a31874af14ae9ff289cb2b3851 upstream.

    Updating mseq makes client think importer mds has accepted all prior
    cap messages and importer mds knows what caps client wants. Actually
    some cap messages may have been dropped because of mseq mismatch.

    If mseq is left untouched, importing cap's mds_wanted later will get
    reset by cap import message.

    Cc: stable@vger.kernel.org
    Signed-off-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov
    Signed-off-by: Greg Kroah-Hartman

    Yan, Zheng
     

27 Nov, 2018

1 commit

  • [ Upstream commit 71f2cc64d027d712f29bf8d09d3e123302d5f245 ]

    This patch fixes a possible null pointer dereference in
    check_quota_exceeded, detected by the static checker smatch, with the
    following warning:

       fs/ceph/quota.c:240 check_quota_exceeded()
        error: we previously assumed 'realm' could be null (see line 188)

    Fixes: b7a2921765cf ("ceph: quota: support for ceph.quota.max_files")
    Reported-by: Dan Carpenter
    Signed-off-by: Luis Henriques
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov
    Signed-off-by: Sasha Levin

    Luis Henriques
     

21 Nov, 2018

1 commit

  • commit efe328230dc01aa0b1269aad0b5fae73eea4677a upstream.

    This reverts commit 8b8f53af1ed9df88a4c0fbfdf3db58f62060edf3.

    splice_dentry() is used by three places. For two places, req->r_dentry
    is passed to splice_dentry(). In the case of error, req->r_dentry does
    not get updated. So splice_dentry() should not drop reference.

    Cc: stable@vger.kernel.org # 4.18+
    Signed-off-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov
    Signed-off-by: Greg Kroah-Hartman

    Yan, Zheng
     

06 Sep, 2018

1 commit

  • syzbot reported a use-after-free in ceph_destroy_options(), called from
    ceph_mount(). The problem was that create_fs_client() consumed the opt
    pointer on some errors, but not on all of them. Make sure it always
    consumes both libceph and ceph options.

    Reported-by: syzbot+8ab6f1042021b4eed062@syzkaller.appspotmail.com
    Signed-off-by: Ilya Dryomov
    Reviewed-by: "Yan, Zheng"

    Ilya Dryomov
     

21 Aug, 2018

1 commit

  • Pull ceph updates from Ilya Dryomov:
    "The main things are support for cephx v2 authentication protocol and
    basic support for rbd images within namespaces (myself).

    Also included are y2038 conversion patches from Arnd, a pile of
    miscellaneous fixes from Chengguang and Zheng's feature bit
    infrastructure for the filesystem"

    * tag 'ceph-for-4.19-rc1' of git://github.com/ceph/ceph-client: (40 commits)
    ceph: don't drop message if it contains more data than expected
    ceph: support cephfs' own feature bits
    crush: fix using plain integer as NULL warning
    libceph: remove unnecessary non NULL check for request_key
    ceph: refactor error handling code in ceph_reserve_caps()
    ceph: refactor ceph_unreserve_caps()
    ceph: change to void return type for __do_request()
    ceph: compare fsc->max_file_size and inode->i_size for max file size limit
    ceph: add additional size check in ceph_setattr()
    ceph: add additional offset check in ceph_write_iter()
    ceph: add additional range check in ceph_fallocate()
    ceph: add new field max_file_size in ceph_fs_client
    libceph: weaken sizeof check in ceph_x_verify_authorizer_reply()
    libceph: check authorizer reply/challenge length before reading
    libceph: implement CEPHX_V2 calculation mode
    libceph: add authorizer challenge
    libceph: factor out encrypt_authorizer()
    libceph: factor out __ceph_x_decrypt()
    libceph: factor out __prepare_write_connect()
    libceph: store ceph_auth_handshake pointer in ceph_connection
    ...

    Linus Torvalds
     

14 Aug, 2018

1 commit

  • Pull vfs open-related updates from Al Viro:

    - "do we need fput() or put_filp()" rules are gone - it's always fput()
    now. We keep track of that state where it belongs - in ->f_mode.

    - int *opened mess killed - in finish_open(), in ->atomic_open()
    instances and in fs/namei.c code around do_last()/lookup_open()/atomic_open().

    - alloc_file() wrappers with saner calling conventions are introduced
    (alloc_file_clone() and alloc_file_pseudo()); callers converted, with
    much simplification.

    - while we are at it, saner calling conventions for path_init() and
    link_path_walk(), simplifying things inside fs/namei.c (both on
    open-related paths and elsewhere).

    * 'work.open3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (40 commits)
    few more cleanups of link_path_walk() callers
    allow link_path_walk() to take ERR_PTR()
    make path_init() unconditionally paired with terminate_walk()
    document alloc_file() changes
    make alloc_file() static
    do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone()
    new helper: alloc_file_clone()
    create_pipe_files(): switch the first allocation to alloc_file_pseudo()
    anon_inode_getfile(): switch to alloc_file_pseudo()
    hugetlb_file_setup(): switch to alloc_file_pseudo()
    ocxlflash_getfile(): switch to alloc_file_pseudo()
    cxl_getfile(): switch to alloc_file_pseudo()
    ... and switch shmem_file_setup() to alloc_file_pseudo()
    __shmem_file_setup(): reorder allocations
    new wrapper: alloc_file_pseudo()
    kill FILE_{CREATED,OPENED}
    switch atomic_open() and lookup_open() to returning 0 in all success cases
    document ->atomic_open() changes
    ->atomic_open(): return 0 in all success cases
    get rid of 'opened' in path_openat() and the helpers downstream
    ...

    Linus Torvalds
     

13 Aug, 2018

7 commits


03 Aug, 2018

16 commits

  • If the offset is larger or equal to both real file size and
    max file size, then return -EFBIG.

    Signed-off-by: Chengguang Xu
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Chengguang Xu
     
  • If the range is larger than both real file size and limit of
    max file size, then return -EFBIG.

    Signed-off-by: Chengguang Xu
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Chengguang Xu
     
  • In order to not bother to VFS and other specific filesystems,
    we decided to do offset validation inside ceph kernel client,
    so just simply set sb->s_maxbytes to MAX_LFS_FILESIZE so that
    it can successfully pass VFS check. We add new field max_file_size
    in ceph_fs_client to store real file size limit and doing proper
    check based on it.

    Signed-off-by: Chengguang Xu
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Chengguang Xu
     
  • When a client authenticates with a service, an authorizer is sent with
    a nonce to the service (ceph_x_authorize_[ab]) and the service responds
    with a mutation of that nonce (ceph_x_authorize_reply). This lets the
    client verify the service is who it says it is but it doesn't protect
    against a replay: someone can trivially capture the exchange and reuse
    the same authorizer to authenticate themselves.

    Allow the service to reject an initial authorizer with a random
    challenge (ceph_x_authorize_challenge). The client then has to respond
    with an updated authorizer proving they are able to decrypt the
    service's challenge and that the new authorizer was produced for this
    specific connection instance.

    The accepting side requires this challenge and response unconditionally
    if the client side advertises they have CEPHX_V2 feature bit.

    This addresses CVE-2018-1128.

    Link: http://tracker.ceph.com/issues/24836
    Signed-off-by: Ilya Dryomov
    Reviewed-by: Sage Weil

    Ilya Dryomov
     
  • Use new return type vm_fault_t for page_mkwrite
    and fault handler.

    Signed-off-by: Souptick Joarder
    Reviewed-by: Matthew Wilcox
    Signed-off-by: Ilya Dryomov

    Souptick Joarder
     
  • The ceph_mds_request stamp still uses the deprecated timespec structure,
    this converts it over as well.

    Signed-off-by: Arnd Bergmann
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Arnd Bergmann
     
  • The request mtime field is used all over ceph, and is currently
    represented as a 'timespec' structure in Linux. This changes it to
    timespec64 to allow times beyond 2038, modifying all users at the
    same time.

    [ Remove now redundant ts variable in writepage_nounlock(). ]

    Signed-off-by: Arnd Bergmann
    Reviewed-by: Ilya Dryomov
    Signed-off-by: Ilya Dryomov

    Arnd Bergmann
     
  • Since the vfs structures are all using timespec64, we can now
    change the internal representation, using ceph_encode_timespec64 and
    ceph_decode_timespec64.

    In case of ceph_aux_inode however, we need to avoid doing a memcmp()
    on uninitialized padding data, so the members of the i_mtime field get
    copied individually into 64-bit integers.

    Signed-off-by: Arnd Bergmann
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Arnd Bergmann
     
  • ceph_mdsc_create_request() is one of the last callers of the
    deprecated current_kernel_time() as well as timespec_trunc().

    This changes it to use the timespec64 based interfaces instead,
    though we still need to convert the result until we are ready to
    change over req->r_stamp.

    The output of the two functions, ktime_get_coarse_real_ts64() and
    current_kernel_time() is the same coarse-granular timestamp,
    the only difference here is that ktime_get_coarse_real_ts64()
    doesn't overflow in 2038.

    Signed-off-by: Arnd Bergmann
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Arnd Bergmann
     
  • When file num exceeds quota limit, should call d_drop to drop
    dentry from cache as well.

    Signed-off-by: Chengguang Xu
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Chengguang Xu
     
  • When file num exceeds quota limit or fails from ceph_per_init_acls()
    should call d_drop to drop dentry from cache as well.

    Signed-off-by: Chengguang Xu
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Chengguang Xu
     
  • In order to return correct error code should replace variable ret
    using err in error case.

    Signed-off-by: Chengguang Xu
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Chengguang Xu
     
  • GCC8 prints following warning:

    fs/ceph/mds_client.c:3683:2: warning: ‘strncpy’ output may be truncated
    copying 64 bytes from a string of length 64 [-Wstringop-truncation]

    [ Change to strscpy() while at it. ]

    Signed-off-by: "Yan, Zheng"
    Reviewed-by: Ilya Dryomov
    Signed-off-by: Ilya Dryomov

    Yan, Zheng
     
  • Don't mention "mount" -- in the rbd case it is "mapping".

    Signed-off-by: Ilya Dryomov

    Ilya Dryomov
     
  • It's better to restore ctime as well in the case of restoring old mode
    in ceph_set_acl().

    Signed-off-by: Chengguang Xu
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Chengguang Xu
     
  • When the size of acl extended attribution is larger than pre-allocated
    value buffer size, we will hit error '-ERANGE' and it's probabaly caused
    by concurrent get/set acl from different clients. In this case, current
    logic just sets acl to NULL so that we cannot get proper information but
    the operation looks successful.

    This patch adds retry logic for error -ERANGE and return -EIO if fail
    from the retry. Additionally, print real errno when failing from
    __ceph_getxattr().

    Signed-off-by: Chengguang Xu
    Reviewed-by: "Yan, Zheng"
    Signed-off-by: Ilya Dryomov

    Chengguang Xu
     

12 Jul, 2018

3 commits


27 Jun, 2018

1 commit


15 Jun, 2018

2 commits

  • Pull inode timestamps conversion to timespec64 from Arnd Bergmann:
    "This is a late set of changes from Deepa Dinamani doing an automated
    treewide conversion of the inode and iattr structures from 'timespec'
    to 'timespec64', to push the conversion from the VFS layer into the
    individual file systems.

    As Deepa writes:

    'The series aims to switch vfs timestamps to use struct timespec64.
    Currently vfs uses struct timespec, which is not y2038 safe.

    The series involves the following:
    1. Add vfs helper functions for supporting struct timepec64
    timestamps.
    2. Cast prints of vfs timestamps to avoid warnings after the switch.
    3. Simplify code using vfs timestamps so that the actual replacement
    becomes easy.
    4. Convert vfs timestamps to use struct timespec64 using a script.
    This is a flag day patch.

    Next steps:
    1. Convert APIs that can handle timespec64, instead of converting
    timestamps at the boundaries.
    2. Update internal data structures to avoid timestamp conversions'

    Thomas Gleixner adds:

    'I think there is no point to drag that out for the next merge
    window. The whole thing needs to be done in one go for the core
    changes which means that you're going to play that catchup game
    forever. Let's get over with it towards the end of the merge window'"

    * tag 'vfs-timespec64' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground:
    pstore: Remove bogus format string definition
    vfs: change inode times to use struct timespec64
    pstore: Convert internal records to timespec64
    udf: Simplify calls to udf_disk_stamp_to_time
    fs: nfs: get rid of memcpys for inode times
    ceph: make inode time prints to be long long
    lustre: Use long long type to print inode time
    fs: add timespec64_truncate()

    Linus Torvalds
     
  • Pull ceph updates from Ilya Dryomov:
    "The main piece is a set of libceph changes that revamps how OSD
    requests are aborted, improving CephFS ENOSPC handling and making
    "umount -f" actually work (Zheng and myself).

    The rest is mostly mount option handling cleanups from Chengguang and
    assorted fixes from Zheng, Luis and Dongsheng.

    * tag 'ceph-for-4.18-rc1' of git://github.com/ceph/ceph-client: (31 commits)
    rbd: flush rbd_dev->watch_dwork after watch is unregistered
    ceph: update description of some mount options
    ceph: show ino32 if the value is different with default
    ceph: strengthen rsize/wsize/readdir_max_bytes validation
    ceph: fix alignment of rasize
    ceph: fix use-after-free in ceph_statfs()
    ceph: prevent i_version from going back
    ceph: fix wrong check for the case of updating link count
    libceph: allocate the locator string with GFP_NOFAIL
    libceph: make abort_on_full a per-osdc setting
    libceph: don't abort reads in ceph_osdc_abort_on_full()
    libceph: avoid a use-after-free during map check
    libceph: don't warn if req->r_abort_on_full is set
    libceph: use for_each_request() in ceph_osdc_abort_on_full()
    libceph: defer __complete_request() to a workqueue
    libceph: move more code into __complete_request()
    libceph: no need to call flush_workqueue() before destruction
    ceph: flush pending works before shutdown super
    ceph: abort osd requests on force umount
    libceph: introduce ceph_osdc_abort_requests()
    ...

    Linus Torvalds
     

13 Jun, 2018

1 commit

  • The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
    patch replaces cases of:

    kmalloc(a * b, gfp)

    with:
    kmalloc_array(a * b, gfp)

    as well as handling cases of:

    kmalloc(a * b * c, gfp)

    with:

    kmalloc(array3_size(a, b, c), gfp)

    as it's slightly less ugly than:

    kmalloc_array(array_size(a, b), c, gfp)

    This does, however, attempt to ignore constant size factors like:

    kmalloc(4 * 1024, gfp)

    though any constants defined via macros get caught up in the conversion.

    Any factors with a sizeof() of "unsigned char", "char", and "u8" were
    dropped, since they're redundant.

    The tools/ directory was manually excluded, since it has its own
    implementation of kmalloc().

    The Coccinelle script used for this was:

    // Fix redundant parens around sizeof().
    @@
    type TYPE;
    expression THING, E;
    @@

    (
    kmalloc(
    - (sizeof(TYPE)) * E
    + sizeof(TYPE) * E
    , ...)
    |
    kmalloc(
    - (sizeof(THING)) * E
    + sizeof(THING) * E
    , ...)
    )

    // Drop single-byte sizes and redundant parens.
    @@
    expression COUNT;
    typedef u8;
    typedef __u8;
    @@

    (
    kmalloc(
    - sizeof(u8) * (COUNT)
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(__u8) * (COUNT)
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(char) * (COUNT)
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(unsigned char) * (COUNT)
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(u8) * COUNT
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(__u8) * COUNT
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(char) * COUNT
    + COUNT
    , ...)
    |
    kmalloc(
    - sizeof(unsigned char) * COUNT
    + COUNT
    , ...)
    )

    // 2-factor product with sizeof(type/expression) and identifier or constant.
    @@
    type TYPE;
    expression THING;
    identifier COUNT_ID;
    constant COUNT_CONST;
    @@

    (
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * (COUNT_ID)
    + COUNT_ID, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * COUNT_ID
    + COUNT_ID, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * (COUNT_CONST)
    + COUNT_CONST, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * COUNT_CONST
    + COUNT_CONST, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * (COUNT_ID)
    + COUNT_ID, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * COUNT_ID
    + COUNT_ID, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * (COUNT_CONST)
    + COUNT_CONST, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * COUNT_CONST
    + COUNT_CONST, sizeof(THING)
    , ...)
    )

    // 2-factor product, only identifiers.
    @@
    identifier SIZE, COUNT;
    @@

    - kmalloc
    + kmalloc_array
    (
    - SIZE * COUNT
    + COUNT, SIZE
    , ...)

    // 3-factor product with 1 sizeof(type) or sizeof(expression), with
    // redundant parens removed.
    @@
    expression THING;
    identifier STRIDE, COUNT;
    type TYPE;
    @@

    (
    kmalloc(
    - sizeof(TYPE) * (COUNT) * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE) * (COUNT) * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE) * COUNT * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE) * COUNT * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    kmalloc(
    - sizeof(THING) * (COUNT) * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    kmalloc(
    - sizeof(THING) * (COUNT) * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    kmalloc(
    - sizeof(THING) * COUNT * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    kmalloc(
    - sizeof(THING) * COUNT * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    )

    // 3-factor product with 2 sizeof(variable), with redundant parens removed.
    @@
    expression THING1, THING2;
    identifier COUNT;
    type TYPE1, TYPE2;
    @@

    (
    kmalloc(
    - sizeof(TYPE1) * sizeof(TYPE2) * COUNT
    + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
    , ...)
    |
    kmalloc(
    - sizeof(THING1) * sizeof(THING2) * COUNT
    + array3_size(COUNT, sizeof(THING1), sizeof(THING2))
    , ...)
    |
    kmalloc(
    - sizeof(THING1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(THING1), sizeof(THING2))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE1) * sizeof(THING2) * COUNT
    + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
    , ...)
    |
    kmalloc(
    - sizeof(TYPE1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
    , ...)
    )

    // 3-factor product, only identifiers, with redundant parens removed.
    @@
    identifier STRIDE, SIZE, COUNT;
    @@

    (
    kmalloc(
    - (COUNT) * STRIDE * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - COUNT * (STRIDE) * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - COUNT * STRIDE * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - (COUNT) * (STRIDE) * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - COUNT * (STRIDE) * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - (COUNT) * STRIDE * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - (COUNT) * (STRIDE) * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    kmalloc(
    - COUNT * STRIDE * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    )

    // Any remaining multi-factor products, first at least 3-factor products,
    // when they're not all constants...
    @@
    expression E1, E2, E3;
    constant C1, C2, C3;
    @@

    (
    kmalloc(C1 * C2 * C3, ...)
    |
    kmalloc(
    - (E1) * E2 * E3
    + array3_size(E1, E2, E3)
    , ...)
    |
    kmalloc(
    - (E1) * (E2) * E3
    + array3_size(E1, E2, E3)
    , ...)
    |
    kmalloc(
    - (E1) * (E2) * (E3)
    + array3_size(E1, E2, E3)
    , ...)
    |
    kmalloc(
    - E1 * E2 * E3
    + array3_size(E1, E2, E3)
    , ...)
    )

    // And then all remaining 2 factors products when they're not all constants,
    // keeping sizeof() as the second factor argument.
    @@
    expression THING, E1, E2;
    type TYPE;
    constant C1, C2, C3;
    @@

    (
    kmalloc(sizeof(THING) * C2, ...)
    |
    kmalloc(sizeof(TYPE) * C2, ...)
    |
    kmalloc(C1 * C2 * C3, ...)
    |
    kmalloc(C1 * C2, ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * (E2)
    + E2, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(TYPE) * E2
    + E2, sizeof(TYPE)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * (E2)
    + E2, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - sizeof(THING) * E2
    + E2, sizeof(THING)
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - (E1) * E2
    + E1, E2
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - (E1) * (E2)
    + E1, E2
    , ...)
    |
    - kmalloc
    + kmalloc_array
    (
    - E1 * E2
    + E1, E2
    , ...)
    )

    Signed-off-by: Kees Cook

    Kees Cook
     

06 Jun, 2018

1 commit

  • 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);
    )

    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
    |
    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)
    ,...)
    )
    ...+>
    (

    )
    |
    - 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;
    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;
    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: Deepa Dinamani
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:
    Cc:

    Deepa Dinamani
     

05 Jun, 2018

1 commit