1. 25 11月, 2019 6 次提交
    • P
      cifs: Fix use-after-free bug in cifs_reconnect() · 8354d88e
      Paulo Alcantara (SUSE) 提交于
      Ensure we grab an active reference in cifs superblock while doing
      failover to prevent automounts (DFS links) of expiring and then
      destroying the superblock pointer.
      
      This patch fixes the following KASAN report:
      
      [  464.301462] BUG: KASAN: use-after-free in
      cifs_reconnect+0x6ab/0x1350
      [  464.303052] Read of size 8 at addr ffff888155e580d0 by task
      cifsd/1107
      
      [  464.304682] CPU: 3 PID: 1107 Comm: cifsd Not tainted 5.4.0-rc4+ #13
      [  464.305552] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009),
      BIOS rel-1.12.1-0-ga5cab58-rebuilt.opensuse.org 04/01/2014
      [  464.307146] Call Trace:
      [  464.307875]  dump_stack+0x5b/0x90
      [  464.308631]  print_address_description.constprop.0+0x16/0x200
      [  464.309478]  ? cifs_reconnect+0x6ab/0x1350
      [  464.310253]  ? cifs_reconnect+0x6ab/0x1350
      [  464.311040]  __kasan_report.cold+0x1a/0x41
      [  464.311811]  ? cifs_reconnect+0x6ab/0x1350
      [  464.312563]  kasan_report+0xe/0x20
      [  464.313300]  cifs_reconnect+0x6ab/0x1350
      [  464.314062]  ? extract_hostname.part.0+0x90/0x90
      [  464.314829]  ? printk+0xad/0xde
      [  464.315525]  ? _raw_spin_lock+0x7c/0xd0
      [  464.316252]  ? _raw_read_lock_irq+0x40/0x40
      [  464.316961]  ? ___ratelimit+0xed/0x182
      [  464.317655]  cifs_readv_from_socket+0x289/0x3b0
      [  464.318386]  cifs_read_from_socket+0x98/0xd0
      [  464.319078]  ? cifs_readv_from_socket+0x3b0/0x3b0
      [  464.319782]  ? try_to_wake_up+0x43c/0xa90
      [  464.320463]  ? cifs_small_buf_get+0x4b/0x60
      [  464.321173]  ? allocate_buffers+0x98/0x1a0
      [  464.321856]  cifs_demultiplex_thread+0x218/0x14a0
      [  464.322558]  ? cifs_handle_standard+0x270/0x270
      [  464.323237]  ? __switch_to_asm+0x40/0x70
      [  464.323893]  ? __switch_to_asm+0x34/0x70
      [  464.324554]  ? __switch_to_asm+0x40/0x70
      [  464.325226]  ? __switch_to_asm+0x40/0x70
      [  464.325863]  ? __switch_to_asm+0x34/0x70
      [  464.326505]  ? __switch_to_asm+0x40/0x70
      [  464.327161]  ? __switch_to_asm+0x34/0x70
      [  464.327784]  ? finish_task_switch+0xa1/0x330
      [  464.328414]  ? __switch_to+0x363/0x640
      [  464.329044]  ? __schedule+0x575/0xaf0
      [  464.329655]  ? _raw_spin_lock_irqsave+0x82/0xe0
      [  464.330301]  kthread+0x1a3/0x1f0
      [  464.330884]  ? cifs_handle_standard+0x270/0x270
      [  464.331624]  ? kthread_create_on_node+0xd0/0xd0
      [  464.332347]  ret_from_fork+0x35/0x40
      
      [  464.333577] Allocated by task 1110:
      [  464.334381]  save_stack+0x1b/0x80
      [  464.335123]  __kasan_kmalloc.constprop.0+0xc2/0xd0
      [  464.335848]  cifs_smb3_do_mount+0xd4/0xb00
      [  464.336619]  legacy_get_tree+0x6b/0xa0
      [  464.337235]  vfs_get_tree+0x41/0x110
      [  464.337975]  fc_mount+0xa/0x40
      [  464.338557]  vfs_kern_mount.part.0+0x6c/0x80
      [  464.339227]  cifs_dfs_d_automount+0x336/0xd29
      [  464.339846]  follow_managed+0x1b1/0x450
      [  464.340449]  lookup_fast+0x231/0x4a0
      [  464.341039]  path_openat+0x240/0x1fd0
      [  464.341634]  do_filp_open+0x126/0x1c0
      [  464.342277]  do_sys_open+0x1eb/0x2c0
      [  464.342957]  do_syscall_64+0x5e/0x190
      [  464.343555]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
      
      [  464.344772] Freed by task 0:
      [  464.345347]  save_stack+0x1b/0x80
      [  464.345966]  __kasan_slab_free+0x12c/0x170
      [  464.346576]  kfree+0xa6/0x270
      [  464.347211]  rcu_core+0x39c/0xc80
      [  464.347800]  __do_softirq+0x10d/0x3da
      
      [  464.348919] The buggy address belongs to the object at
      ffff888155e58000
                      which belongs to the cache kmalloc-256 of size 256
      [  464.350222] The buggy address is located 208 bytes inside of
                      256-byte region [ffff888155e58000, ffff888155e58100)
      [  464.351575] The buggy address belongs to the page:
      [  464.352333] page:ffffea0005579600 refcount:1 mapcount:0
      mapping:ffff88815a803400 index:0x0 compound_mapcount: 0
      [  464.353583] flags: 0x200000000010200(slab|head)
      [  464.354209] raw: 0200000000010200 ffffea0005576200 0000000400000004
      ffff88815a803400
      [  464.355353] raw: 0000000000000000 0000000080100010 00000001ffffffff
      0000000000000000
      [  464.356458] page dumped because: kasan: bad access detected
      
      [  464.367005] Memory state around the buggy address:
      [  464.367787]  ffff888155e57f80: fc fc fc fc fc fc fc fc fc fc fc fc
      fc fc fc fc
      [  464.368877]  ffff888155e58000: fb fb fb fb fb fb fb fb fb fb fb fb
      fb fb fb fb
      [  464.369967] >ffff888155e58080: fb fb fb fb fb fb fb fb fb fb fb fb
      fb fb fb fb
      [  464.371111]                                                  ^
      [  464.371775]  ffff888155e58100: fc fc fc fc fc fc fc fc fc fc fc fc
      fc fc fc fc
      [  464.372893]  ffff888155e58180: fc fc fc fc fc fc fc fc fc fc fc fc
      fc fc fc fc
      [  464.373983] ==================================================================
      Signed-off-by: NPaulo Alcantara (SUSE) <pc@cjr.nz>
      Reviewed-by: NAurelien Aptel <aaptel@suse.com>
      Signed-off-by: NSteve French <stfrench@microsoft.com>
      8354d88e
    • A
      cifs: try opening channels after mounting · d70e9fa5
      Aurelien Aptel 提交于
      After doing mount() successfully we call cifs_try_adding_channels()
      which will open as many channels as it can.
      
      Channels are closed when the master session is closed.
      
      The master connection becomes the first channel.
      
      ,-------------> global cifs_tcp_ses_list <-------------------------.
      |                                                                  |
      '- TCP_Server_Info  <-->  TCP_Server_Info  <-->  TCP_Server_Info <-'
            (master con)           (chan#1 con)         (chan#2 con)
            |      ^                    ^                    ^
            v      '--------------------|--------------------'
         cifs_ses                       |
         - chan_count = 3               |
         - chans[] ---------------------'
         - smb3signingkey[]
            (master signing key)
      
      Note how channel connections don't have sessions. That's because
      cifs_ses can only be part of one linked list (list_head are internal
      to the elements).
      
      For signing keys, each channel has its own signing key which must be
      used only after the channel has been bound. While it's binding it must
      use the master session signing key.
      
      For encryption keys, since channel connections do not have sessions
      attached we must now find matching session by looping over all sessions
      in smb2_get_enc_key().
      
      Each channel is opened like a regular server connection but at the
      session setup request step it must set the
      SMB2_SESSION_REQ_FLAG_BINDING flag and use the session id to bind to.
      
      Finally, while sending in compound_send_recv() for requests that
      aren't negprot, ses-setup or binding related, use a channel by cycling
      through the available ones (round-robin).
      Signed-off-by: NAurelien Aptel <aaptel@suse.com>
      Signed-off-by: NSteve French <stfrench@microsoft.com>
      d70e9fa5
    • A
      cifs: switch servers depending on binding state · f6a6bf7c
      Aurelien Aptel 提交于
      Currently a lot of the code to initialize a connection & session uses
      the cifs_ses as input. But depending on if we are opening a new session
      or a new channel we need to use different server pointers.
      
      Add a "binding" flag in cifs_ses and a helper function that returns
      the server ptr a session should use (only in the sess establishment
      code path).
      Signed-off-by: NAurelien Aptel <aaptel@suse.com>
      Signed-off-by: NSteve French <stfrench@microsoft.com>
      f6a6bf7c
    • A
      cifs: add multichannel mount options and data structs · bcc88801
      Aurelien Aptel 提交于
      adds:
      - [no]multichannel to enable/disable multichannel
      - max_channels=N to control how many channels to create
      
      these options are then stored in the volume struct.
      
      - store channels and max_channels in cifs_ses
      Signed-off-by: NAurelien Aptel <aaptel@suse.com>
      Signed-off-by: NSteve French <stfrench@microsoft.com>
      bcc88801
    • P
      CIFS: Do not miss cancelled OPEN responses · 7b71843f
      Pavel Shilovsky 提交于
      When an OPEN command is cancelled we mark a mid as
      cancelled and let the demultiplex thread process it
      by closing an open handle. The problem is there is
      a race between a system call thread and the demultiplex
      thread and there may be a situation when the mid has
      been already processed before it is set as cancelled.
      
      Fix this by processing cancelled requests when mids
      are being destroyed which means that there is only
      one thread referencing a particular mid. Also set
      mids as cancelled unconditionally on their state.
      
      Cc: Stable <stable@vger.kernel.org>
      Tested-by: NFrank Sorenson <sorenson@redhat.com>
      Reviewed-by: NRonnie Sahlberg <lsahlber@redhat.com>
      Signed-off-by: NPavel Shilovsky <pshilov@microsoft.com>
      Signed-off-by: NSteve French <stfrench@microsoft.com>
      7b71843f
    • P
      CIFS: Fix NULL pointer dereference in mid callback · 86a7964b
      Pavel Shilovsky 提交于
      There is a race between a system call processing thread
      and the demultiplex thread when mid->resp_buf becomes NULL
      and later is being accessed to get credits. It happens when
      the 1st thread wakes up before a mid callback is called in
      the 2nd one but the mid state has already been set to
      MID_RESPONSE_RECEIVED. This causes NULL pointer dereference
      in mid callback.
      
      Fix this by saving credits from the response before we
      update the mid state and then use this value in the mid
      callback rather then accessing a response buffer.
      
      Cc: Stable <stable@vger.kernel.org>
      Fixes: ee258d79 ("CIFS: Move credit processing to mid callbacks for SMB3")
      Tested-by: NFrank Sorenson <sorenson@redhat.com>
      Reviewed-by: NRonnie Sahlberg <lsahlber@redhat.com>
      Signed-off-by: NPavel Shilovsky <pshilov@microsoft.com>
      Signed-off-by: NSteve French <stfrench@microsoft.com>
      86a7964b
  2. 25 10月, 2019 1 次提交
    • P
      CIFS: Fix retry mid list corruption on reconnects · abe57073
      Pavel Shilovsky 提交于
      When the client hits reconnect it iterates over the mid
      pending queue marking entries for retry and moving them
      to a temporary list to issue callbacks later without holding
      GlobalMid_Lock. In the same time there is no guarantee that
      mids can't be removed from the temporary list or even
      freed completely by another thread. It may cause a temporary
      list corruption:
      
      [  430.454897] list_del corruption. prev->next should be ffff98d3a8f316c0, but was 2e885cb266355469
      [  430.464668] ------------[ cut here ]------------
      [  430.466569] kernel BUG at lib/list_debug.c:51!
      [  430.468476] invalid opcode: 0000 [#1] SMP PTI
      [  430.470286] CPU: 0 PID: 13267 Comm: cifsd Kdump: loaded Not tainted 5.4.0-rc3+ #19
      [  430.473472] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
      [  430.475872] RIP: 0010:__list_del_entry_valid.cold+0x31/0x55
      ...
      [  430.510426] Call Trace:
      [  430.511500]  cifs_reconnect+0x25e/0x610 [cifs]
      [  430.513350]  cifs_readv_from_socket+0x220/0x250 [cifs]
      [  430.515464]  cifs_read_from_socket+0x4a/0x70 [cifs]
      [  430.517452]  ? try_to_wake_up+0x212/0x650
      [  430.519122]  ? cifs_small_buf_get+0x16/0x30 [cifs]
      [  430.521086]  ? allocate_buffers+0x66/0x120 [cifs]
      [  430.523019]  cifs_demultiplex_thread+0xdc/0xc30 [cifs]
      [  430.525116]  kthread+0xfb/0x130
      [  430.526421]  ? cifs_handle_standard+0x190/0x190 [cifs]
      [  430.528514]  ? kthread_park+0x90/0x90
      [  430.530019]  ret_from_fork+0x35/0x40
      
      Fix this by obtaining extra references for mids being retried
      and marking them as MID_DELETED which indicates that such a mid
      has been dequeued from the pending list.
      
      Also move mid cleanup logic from DeleteMidQEntry to
      _cifs_mid_q_entry_release which is called when the last reference
      to a particular mid is put. This allows to avoid any use-after-free
      of response buffers.
      
      The patch needs to be backported to stable kernels. A stable tag
      is not mentioned below because the patch doesn't apply cleanly
      to any actively maintained stable kernel.
      Reviewed-by: NRonnie Sahlberg <lsahlber@redhat.com>
      Reviewed-and-tested-by: NDavid Wysochanski <dwysocha@redhat.com>
      Signed-off-by: NPavel Shilovsky <pshilov@microsoft.com>
      Signed-off-by: NSteve French <stfrench@microsoft.com>
      abe57073
  3. 21 10月, 2019 1 次提交
  4. 09 10月, 2019 1 次提交
  5. 07 10月, 2019 1 次提交
  6. 17 9月, 2019 11 次提交
  7. 28 8月, 2019 3 次提交
  8. 19 8月, 2019 1 次提交
    • E
      signal: Allow cifs and drbd to receive their terminating signals · 33da8e7c
      Eric W. Biederman 提交于
      My recent to change to only use force_sig for a synchronous events
      wound up breaking signal reception cifs and drbd.  I had overlooked
      the fact that by default kthreads start out with all signals set to
      SIG_IGN.  So a change I thought was safe turned out to have made it
      impossible for those kernel thread to catch their signals.
      
      Reverting the work on force_sig is a bad idea because what the code
      was doing was very much a misuse of force_sig.  As the way force_sig
      ultimately allowed the signal to happen was to change the signal
      handler to SIG_DFL.  Which after the first signal will allow userspace
      to send signals to these kernel threads.  At least for
      wake_ack_receiver in drbd that does not appear actively wrong.
      
      So correct this problem by adding allow_kernel_signal that will allow
      signals whose siginfo reports they were sent by the kernel through,
      but will not allow userspace generated signals, and update cifs and
      drbd to call allow_kernel_signal in an appropriate place so that their
      thread can receive this signal.
      
      Fixing things this way ensures that userspace won't be able to send
      signals and cause problems, that it is clear which signals the
      threads are expecting to receive, and it guarantees that nothing
      else in the system will be affected.
      
      This change was partly inspired by similar cifs and drbd patches that
      added allow_signal.
      Reported-by: Nronnie sahlberg <ronniesahlberg@gmail.com>
      Reported-by: NChristoph Böhmwalder <christoph.boehmwalder@linbit.com>
      Tested-by: NChristoph Böhmwalder <christoph.boehmwalder@linbit.com>
      Cc: Steve French <smfrench@gmail.com>
      Cc: Philipp Reisner <philipp.reisner@linbit.com>
      Cc: David Laight <David.Laight@ACULAB.COM>
      Fixes: 247bc947 ("cifs: fix rmmod regression in cifs.ko caused by force_sig changes")
      Fixes: 72abe3bc ("signal/cifs: Fix cifs_put_tcp_session to call send_sig instead of force_sig")
      Fixes: fee10990 ("signal/drbd: Use send_sig not force_sig")
      Fixes: 3cf5d076 ("signal: Remove task parameter from force_sig")
      Signed-off-by: N"Eric W. Biederman" <ebiederm@xmission.com>
      33da8e7c
  9. 05 8月, 2019 1 次提交
  10. 14 7月, 2019 1 次提交
  11. 11 7月, 2019 1 次提交
  12. 08 7月, 2019 6 次提交
  13. 28 6月, 2019 1 次提交
    • D
      keys: Replace uid/gid/perm permissions checking with an ACL · 2e12256b
      David Howells 提交于
      Replace the uid/gid/perm permissions checking on a key with an ACL to allow
      the SETATTR and SEARCH permissions to be split.  This will also allow a
      greater range of subjects to represented.
      
      ============
      WHY DO THIS?
      ============
      
      The problem is that SETATTR and SEARCH cover a slew of actions, not all of
      which should be grouped together.
      
      For SETATTR, this includes actions that are about controlling access to a
      key:
      
       (1) Changing a key's ownership.
      
       (2) Changing a key's security information.
      
       (3) Setting a keyring's restriction.
      
      And actions that are about managing a key's lifetime:
      
       (4) Setting an expiry time.
      
       (5) Revoking a key.
      
      and (proposed) managing a key as part of a cache:
      
       (6) Invalidating a key.
      
      Managing a key's lifetime doesn't really have anything to do with
      controlling access to that key.
      
      Expiry time is awkward since it's more about the lifetime of the content
      and so, in some ways goes better with WRITE permission.  It can, however,
      be set unconditionally by a process with an appropriate authorisation token
      for instantiating a key, and can also be set by the key type driver when a
      key is instantiated, so lumping it with the access-controlling actions is
      probably okay.
      
      As for SEARCH permission, that currently covers:
      
       (1) Finding keys in a keyring tree during a search.
      
       (2) Permitting keyrings to be joined.
      
       (3) Invalidation.
      
      But these don't really belong together either, since these actions really
      need to be controlled separately.
      
      Finally, there are number of special cases to do with granting the
      administrator special rights to invalidate or clear keys that I would like
      to handle with the ACL rather than key flags and special checks.
      
      
      ===============
      WHAT IS CHANGED
      ===============
      
      The SETATTR permission is split to create two new permissions:
      
       (1) SET_SECURITY - which allows the key's owner, group and ACL to be
           changed and a restriction to be placed on a keyring.
      
       (2) REVOKE - which allows a key to be revoked.
      
      The SEARCH permission is split to create:
      
       (1) SEARCH - which allows a keyring to be search and a key to be found.
      
       (2) JOIN - which allows a keyring to be joined as a session keyring.
      
       (3) INVAL - which allows a key to be invalidated.
      
      The WRITE permission is also split to create:
      
       (1) WRITE - which allows a key's content to be altered and links to be
           added, removed and replaced in a keyring.
      
       (2) CLEAR - which allows a keyring to be cleared completely.  This is
           split out to make it possible to give just this to an administrator.
      
       (3) REVOKE - see above.
      
      
      Keys acquire ACLs which consist of a series of ACEs, and all that apply are
      unioned together.  An ACE specifies a subject, such as:
      
       (*) Possessor - permitted to anyone who 'possesses' a key
       (*) Owner - permitted to the key owner
       (*) Group - permitted to the key group
       (*) Everyone - permitted to everyone
      
      Note that 'Other' has been replaced with 'Everyone' on the assumption that
      you wouldn't grant a permit to 'Other' that you wouldn't also grant to
      everyone else.
      
      Further subjects may be made available by later patches.
      
      The ACE also specifies a permissions mask.  The set of permissions is now:
      
      	VIEW		Can view the key metadata
      	READ		Can read the key content
      	WRITE		Can update/modify the key content
      	SEARCH		Can find the key by searching/requesting
      	LINK		Can make a link to the key
      	SET_SECURITY	Can change owner, ACL, expiry
      	INVAL		Can invalidate
      	REVOKE		Can revoke
      	JOIN		Can join this keyring
      	CLEAR		Can clear this keyring
      
      
      The KEYCTL_SETPERM function is then deprecated.
      
      The KEYCTL_SET_TIMEOUT function then is permitted if SET_SECURITY is set,
      or if the caller has a valid instantiation auth token.
      
      The KEYCTL_INVALIDATE function then requires INVAL.
      
      The KEYCTL_REVOKE function then requires REVOKE.
      
      The KEYCTL_JOIN_SESSION_KEYRING function then requires JOIN to join an
      existing keyring.
      
      The JOIN permission is enabled by default for session keyrings and manually
      created keyrings only.
      
      
      ======================
      BACKWARD COMPATIBILITY
      ======================
      
      To maintain backward compatibility, KEYCTL_SETPERM will translate the
      permissions mask it is given into a new ACL for a key - unless
      KEYCTL_SET_ACL has been called on that key, in which case an error will be
      returned.
      
      It will convert possessor, owner, group and other permissions into separate
      ACEs, if each portion of the mask is non-zero.
      
      SETATTR permission turns on all of INVAL, REVOKE and SET_SECURITY.  WRITE
      permission turns on WRITE, REVOKE and, if a keyring, CLEAR.  JOIN is turned
      on if a keyring is being altered.
      
      The KEYCTL_DESCRIBE function translates the ACL back into a permissions
      mask to return depending on possessor, owner, group and everyone ACEs.
      
      It will make the following mappings:
      
       (1) INVAL, JOIN -> SEARCH
      
       (2) SET_SECURITY -> SETATTR
      
       (3) REVOKE -> WRITE if SETATTR isn't already set
      
       (4) CLEAR -> WRITE
      
      Note that the value subsequently returned by KEYCTL_DESCRIBE may not match
      the value set with KEYCTL_SETATTR.
      
      
      =======
      TESTING
      =======
      
      This passes the keyutils testsuite for all but a couple of tests:
      
       (1) tests/keyctl/dh_compute/badargs: The first wrong-key-type test now
           returns EOPNOTSUPP rather than ENOKEY as READ permission isn't removed
           if the type doesn't have ->read().  You still can't actually read the
           key.
      
       (2) tests/keyctl/permitting/valid: The view-other-permissions test doesn't
           work as Other has been replaced with Everyone in the ACL.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      2e12256b
  14. 18 6月, 2019 1 次提交
  15. 27 5月, 2019 1 次提交
    • E
      signal/cifs: Fix cifs_put_tcp_session to call send_sig instead of force_sig · 72abe3bc
      Eric W. Biederman 提交于
      The locking in force_sig_info is not prepared to deal with a task that
      exits or execs (as sighand may change).  The is not a locking problem
      in force_sig as force_sig is only built to handle synchronous
      exceptions.
      
      Further the function force_sig_info changes the signal state if the
      signal is ignored, or blocked or if SIGNAL_UNKILLABLE will prevent the
      delivery of the signal.  The signal SIGKILL can not be ignored and can
      not be blocked and SIGNAL_UNKILLABLE won't prevent it from being
      delivered.
      
      So using force_sig rather than send_sig for SIGKILL is confusing
      and pointless.
      
      Because it won't impact the sending of the signal and and because
      using force_sig is wrong, replace force_sig with send_sig.
      
      Cc: Namjae Jeon <namjae.jeon@samsung.com>
      Cc: Jeff Layton <jlayton@primarydata.com>
      Cc: Steve French <smfrench@gmail.com>
      Fixes: a5c3e1c7 ("Revert "cifs: No need to send SIGKILL to demux_thread during umount"")
      Fixes: e7ddee90 ("cifs: disable sharing session and tcon and add new TCP sharing code")
      Signed-off-by: N"Eric W. Biederman" <ebiederm@xmission.com>
      72abe3bc
  16. 16 5月, 2019 1 次提交
  17. 15 5月, 2019 1 次提交
  18. 08 5月, 2019 1 次提交