1. 28 11月, 2018 1 次提交
  2. 19 9月, 2018 2 次提交
    • A
      ipmi: Change to ktime_get_ts64() · dd3535b9
      Arnd Bergmann 提交于
      getnstimeofday64() is deprecated because of the inconsistent naming,
      it is only a wrapper around ktime_get_real_ts64() now, which could be
      used as a direct replacement.
      
      However, it is generally better to use CLOCK_MONOTONIC timestamps
      where possible, to avoid glitches with a concurrent settimeofday()
      or leap second.
      
      The uses in ipmi are either for debugging prints or for comparing against
      a prior timestamp, so using a monotonic ktime_get_ts64() is probably
      best here.
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Signed-off-by: NCorey Minyard <cminyard@mvista.com>
      dd3535b9
    • J
      ipmi: Use more common logging styles · 25880f7d
      Joe Perches 提交于
      Add and use #define pr_fmt/dev_fmt, and remove #define PFX
      
      This also prefixes some messages that were not previously prefixed.
      
      Miscellanea:
      
      o Convert printk(KERN_<level> to pr_<level>(
      o Use %s, __func__ where appropriate
      Signed-off-by: NJoe Perches <joe@perches.com>
      Signed-off-by: NCorey Minyard <cminyard@mvista.com>
      25880f7d
  3. 31 8月, 2018 1 次提交
    • C
      ipmi: Rework SMI registration failure · 2512e40e
      Corey Minyard 提交于
      There were certain situations where ipmi_register_smi() would
      return a failure, but the interface would still be registered
      and would need to be unregistered.  This is obviously a bad
      design and resulted in an oops in certain failure cases.
      
      If the interface is started up in ipmi_register_smi(), then
      an error occurs, shut down the interface there so the
      cleanup can be done properly.
      
      Fix the various smi users, too.
      Signed-off-by: NCorey Minyard <cminyard@mvista.com>
      Reported-by: NJustin Ernst <justin.ernst@hpe.com>
      Tested-by: NJustin Ernst <justin.ernst@hpe.com>
      Cc: Andrew Banman <abanman@hpe.com>
      Cc: Russ Anderson <russ.anderson@hpe.com>
      Cc: <stable@vger.kernel.org> # 4.18.x
      2512e40e
  4. 25 6月, 2018 1 次提交
  5. 10 5月, 2018 1 次提交
  6. 18 4月, 2018 6 次提交
  7. 07 3月, 2018 4 次提交
  8. 27 2月, 2018 1 次提交
  9. 16 1月, 2018 1 次提交
    • M
      ipmi: Clear smi_info->thread to prevent use-after-free during module unload · bd1c06a4
      Masamitsu Yamazaki 提交于
      During code inspection, I found an use-after-free possibility during unloading
      ipmi_si in the polling mode.
      
      If start_new_msg() is called after kthread_stop(), the function will try to
      wake up non-existing kthread using the dangling pointer.
      
      Possible scenario is when a new internal message is generated after
      ipmi_unregister_smi()[*1] and remains after stop_timer_and_thread()
      in clenaup_one_si() [*2].
      Use-after-free could occur as follows depending on BMC replies.
      
        cleanup_one_si
          => ipmi_unregister_smi
             [*1]
          => stop_timer_and_thread
             => kthread_stop(smi_info->thread)
             [*2]
          => poll
             => smi_event_handler
                => start_new_msg
                   => if (smi_info->thread)
                          wake_up_process(smi_info->thread) <== use-after-free!!
      
      Although currently it seems no such message is generated in the polling mode,
      some changes might introduce that in thefuture. For example in the interrupt
      mode, disable_si_irq() does that at [*2].
      
      So let's prevent such a critical issue possibility now.
      Signed-off-by: NYamazaki Masamitsu <m-yamazaki@ah.jp.nec.com>
      Signed-off-by: NCorey Minyard <cminyard@mvista.com>
      bd1c06a4
  10. 12 12月, 2017 1 次提交
  11. 06 12月, 2017 1 次提交
    • M
      ipmi: Stop timers before cleaning up the module · 4f7f5551
      Masamitsu Yamazaki 提交于
      System may crash after unloading ipmi_si.ko module
      because a timer may remain and fire after the module cleaned up resources.
      
      cleanup_one_si() contains the following processing.
      
              /*
               * Make sure that interrupts, the timer and the thread are
               * stopped and will not run again.
               */
              if (to_clean->irq_cleanup)
                      to_clean->irq_cleanup(to_clean);
              wait_for_timer_and_thread(to_clean);
      
              /*
               * Timeouts are stopped, now make sure the interrupts are off
               * in the BMC.  Note that timers and CPU interrupts are off,
               * so no need for locks.
               */
              while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
                      poll(to_clean);
                      schedule_timeout_uninterruptible(1);
              }
      
      si_state changes as following in the while loop calling poll(to_clean).
      
        SI_GETTING_MESSAGES
          => SI_CHECKING_ENABLES
           => SI_SETTING_ENABLES
            => SI_GETTING_EVENTS
             => SI_NORMAL
      
      As written in the code comments above,
      timers are expected to stop before the polling loop and not to run again.
      But the timer is set again in the following process
      when si_state becomes SI_SETTING_ENABLES.
      
        => poll
           => smi_event_handler
             => handle_transaction_done
                // smi_info->si_state == SI_SETTING_ENABLES
               => start_getting_events
                 => start_new_msg
                  => smi_mod_timer
                    => mod_timer
      
      As a result, before the timer set in start_new_msg() expires,
      the polling loop may see si_state becoming SI_NORMAL
      and the module clean-up finishes.
      
      For example, hard LOCKUP and panic occurred as following.
      smi_timeout was called after smi_event_handler,
      kcs_event and hangs at port_inb()
      trying to access I/O port after release.
      
          [exception RIP: port_inb+19]
          RIP: ffffffffc0473053  RSP: ffff88069fdc3d80  RFLAGS: 00000006
          RAX: ffff8806800f8e00  RBX: ffff880682bd9400  RCX: 0000000000000000
          RDX: 0000000000000ca3  RSI: 0000000000000ca3  RDI: ffff8806800f8e40
          RBP: ffff88069fdc3d80   R8: ffffffff81d86dfc   R9: ffffffff81e36426
          R10: 00000000000509f0  R11: 0000000000100000  R12: 0000000000]:000000
          R13: 0000000000000000  R14: 0000000000000246  R15: ffff8806800f8e00
          ORIG_RAX: ffffffffffffffff  CS: 0010  SS: 0000
       --- <NMI exception stack> ---
      
      To fix the problem I defined a flag, timer_can_start,
      as member of struct smi_info.
      The flag is enabled immediately after initializing the timer
      and disabled immediately before waiting for timer deletion.
      
      Fixes: 0cfec916 ("ipmi: Start the timer and thread on internal msgs")
      Signed-off-by: NYamazaki Masamitsu <m-yamazaki@ah.jp.nec.com>
      [Adjusted for recent changes in the driver.]
      Signed-off-by: NCorey Minyard <cminyard@mvista.com>
      4f7f5551
  12. 22 11月, 2017 1 次提交
    • K
      treewide: setup_timer() -> timer_setup() · e99e88a9
      Kees Cook 提交于
      This converts all remaining cases of the old setup_timer() API into using
      timer_setup(), where the callback argument is the structure already
      holding the struct timer_list. These should have no behavioral changes,
      since they just change which pointer is passed into the callback with
      the same available pointers after conversion. It handles the following
      examples, in addition to some other variations.
      
      Casting from unsigned long:
      
          void my_callback(unsigned long data)
          {
              struct something *ptr = (struct something *)data;
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, ptr);
      
      and forced object casts:
      
          void my_callback(struct something *ptr)
          {
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, (unsigned long)ptr);
      
      become:
      
          void my_callback(struct timer_list *t)
          {
              struct something *ptr = from_timer(ptr, t, my_timer);
          ...
          }
          ...
          timer_setup(&ptr->my_timer, my_callback, 0);
      
      Direct function assignments:
      
          void my_callback(unsigned long data)
          {
              struct something *ptr = (struct something *)data;
          ...
          }
          ...
          ptr->my_timer.function = my_callback;
      
      have a temporary cast added, along with converting the args:
      
          void my_callback(struct timer_list *t)
          {
              struct something *ptr = from_timer(ptr, t, my_timer);
          ...
          }
          ...
          ptr->my_timer.function = (TIMER_FUNC_TYPE)my_callback;
      
      And finally, callbacks without a data assignment:
      
          void my_callback(unsigned long data)
          {
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, 0);
      
      have their argument renamed to verify they're unused during conversion:
      
          void my_callback(struct timer_list *unused)
          {
          ...
          }
          ...
          timer_setup(&ptr->my_timer, my_callback, 0);
      
      The conversion is done with the following Coccinelle script:
      
      spatch --very-quiet --all-includes --include-headers \
      	-I ./arch/x86/include -I ./arch/x86/include/generated \
      	-I ./include -I ./arch/x86/include/uapi \
      	-I ./arch/x86/include/generated/uapi -I ./include/uapi \
      	-I ./include/generated/uapi --include ./include/linux/kconfig.h \
      	--dir . \
      	--cocci-file ~/src/data/timer_setup.cocci
      
      @fix_address_of@
      expression e;
      @@
      
       setup_timer(
      -&(e)
      +&e
       , ...)
      
      // Update any raw setup_timer() usages that have a NULL callback, but
      // would otherwise match change_timer_function_usage, since the latter
      // will update all function assignments done in the face of a NULL
      // function initialization in setup_timer().
      @change_timer_function_usage_NULL@
      expression _E;
      identifier _timer;
      type _cast_data;
      @@
      
      (
      -setup_timer(&_E->_timer, NULL, _E);
      +timer_setup(&_E->_timer, NULL, 0);
      |
      -setup_timer(&_E->_timer, NULL, (_cast_data)_E);
      +timer_setup(&_E->_timer, NULL, 0);
      |
      -setup_timer(&_E._timer, NULL, &_E);
      +timer_setup(&_E._timer, NULL, 0);
      |
      -setup_timer(&_E._timer, NULL, (_cast_data)&_E);
      +timer_setup(&_E._timer, NULL, 0);
      )
      
      @change_timer_function_usage@
      expression _E;
      identifier _timer;
      struct timer_list _stl;
      identifier _callback;
      type _cast_func, _cast_data;
      @@
      
      (
      -setup_timer(&_E->_timer, _callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, &_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, &_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)&_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)&_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, &_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, &_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
       _E->_timer@_stl.function = _callback;
      |
       _E->_timer@_stl.function = &_callback;
      |
       _E->_timer@_stl.function = (_cast_func)_callback;
      |
       _E->_timer@_stl.function = (_cast_func)&_callback;
      |
       _E._timer@_stl.function = _callback;
      |
       _E._timer@_stl.function = &_callback;
      |
       _E._timer@_stl.function = (_cast_func)_callback;
      |
       _E._timer@_stl.function = (_cast_func)&_callback;
      )
      
      // callback(unsigned long arg)
      @change_callback_handle_cast
       depends on change_timer_function_usage@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _origtype;
      identifier _origarg;
      type _handletype;
      identifier _handle;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *t
       )
       {
      (
      	... when != _origarg
      	_handletype *_handle =
      -(_handletype *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle =
      -(void *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle;
      	... when != _handle
      	_handle =
      -(_handletype *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle;
      	... when != _handle
      	_handle =
      -(void *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      )
       }
      
      // callback(unsigned long arg) without existing variable
      @change_callback_handle_cast_no_arg
       depends on change_timer_function_usage &&
                           !change_callback_handle_cast@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _origtype;
      identifier _origarg;
      type _handletype;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *t
       )
       {
      +	_handletype *_origarg = from_timer(_origarg, t, _timer);
      +
      	... when != _origarg
      -	(_handletype *)_origarg
      +	_origarg
      	... when != _origarg
       }
      
      // Avoid already converted callbacks.
      @match_callback_converted
       depends on change_timer_function_usage &&
                  !change_callback_handle_cast &&
      	    !change_callback_handle_cast_no_arg@
      identifier change_timer_function_usage._callback;
      identifier t;
      @@
      
       void _callback(struct timer_list *t)
       { ... }
      
      // callback(struct something *handle)
      @change_callback_handle_arg
       depends on change_timer_function_usage &&
      	    !match_callback_converted &&
                  !change_callback_handle_cast &&
                  !change_callback_handle_cast_no_arg@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _handletype;
      identifier _handle;
      @@
      
       void _callback(
      -_handletype *_handle
      +struct timer_list *t
       )
       {
      +	_handletype *_handle = from_timer(_handle, t, _timer);
      	...
       }
      
      // If change_callback_handle_arg ran on an empty function, remove
      // the added handler.
      @unchange_callback_handle_arg
       depends on change_timer_function_usage &&
      	    change_callback_handle_arg@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _handletype;
      identifier _handle;
      identifier t;
      @@
      
       void _callback(struct timer_list *t)
       {
      -	_handletype *_handle = from_timer(_handle, t, _timer);
       }
      
      // We only want to refactor the setup_timer() data argument if we've found
      // the matching callback. This undoes changes in change_timer_function_usage.
      @unchange_timer_function_usage
       depends on change_timer_function_usage &&
                  !change_callback_handle_cast &&
                  !change_callback_handle_cast_no_arg &&
      	    !change_callback_handle_arg@
      expression change_timer_function_usage._E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type change_timer_function_usage._cast_data;
      @@
      
      (
      -timer_setup(&_E->_timer, _callback, 0);
      +setup_timer(&_E->_timer, _callback, (_cast_data)_E);
      |
      -timer_setup(&_E._timer, _callback, 0);
      +setup_timer(&_E._timer, _callback, (_cast_data)&_E);
      )
      
      // If we fixed a callback from a .function assignment, fix the
      // assignment cast now.
      @change_timer_function_assignment
       depends on change_timer_function_usage &&
                  (change_callback_handle_cast ||
                   change_callback_handle_cast_no_arg ||
                   change_callback_handle_arg)@
      expression change_timer_function_usage._E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type _cast_func;
      typedef TIMER_FUNC_TYPE;
      @@
      
      (
       _E->_timer.function =
      -_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -(_cast_func)_callback;
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -(_cast_func)&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -&_callback;
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -(_cast_func)_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -(_cast_func)&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      )
      
      // Sometimes timer functions are called directly. Replace matched args.
      @change_timer_function_calls
       depends on change_timer_function_usage &&
                  (change_callback_handle_cast ||
                   change_callback_handle_cast_no_arg ||
                   change_callback_handle_arg)@
      expression _E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type _cast_data;
      @@
      
       _callback(
      (
      -(_cast_data)_E
      +&_E->_timer
      |
      -(_cast_data)&_E
      +&_E._timer
      |
      -_E
      +&_E->_timer
      )
       )
      
      // If a timer has been configured without a data argument, it can be
      // converted without regard to the callback argument, since it is unused.
      @match_timer_function_unused_data@
      expression _E;
      identifier _timer;
      identifier _callback;
      @@
      
      (
      -setup_timer(&_E->_timer, _callback, 0);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, 0L);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, 0UL);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0L);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0UL);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0L);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0UL);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0);
      +timer_setup(_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0L);
      +timer_setup(_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0UL);
      +timer_setup(_timer, _callback, 0);
      )
      
      @change_callback_unused_data
       depends on match_timer_function_unused_data@
      identifier match_timer_function_unused_data._callback;
      type _origtype;
      identifier _origarg;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *unused
       )
       {
      	... when != _origarg
       }
      Signed-off-by: NKees Cook <keescook@chromium.org>
      e99e88a9
  13. 31 10月, 2017 1 次提交
    • K
      treewide: Fix function prototypes for module_param_call() · e4dca7b7
      Kees Cook 提交于
      Several function prototypes for the set/get functions defined by
      module_param_call() have a slightly wrong argument types. This fixes
      those in an effort to clean up the calls when running under type-enforced
      compiler instrumentation for CFI. This is the result of running the
      following semantic patch:
      
      @match_module_param_call_function@
      declarer name module_param_call;
      identifier _name, _set_func, _get_func;
      expression _arg, _mode;
      @@
      
       module_param_call(_name, _set_func, _get_func, _arg, _mode);
      
      @fix_set_prototype
       depends on match_module_param_call_function@
      identifier match_module_param_call_function._set_func;
      identifier _val, _param;
      type _val_type, _param_type;
      @@
      
       int _set_func(
      -_val_type _val
      +const char * _val
       ,
      -_param_type _param
      +const struct kernel_param * _param
       ) { ... }
      
      @fix_get_prototype
       depends on match_module_param_call_function@
      identifier match_module_param_call_function._get_func;
      identifier _val, _param;
      type _val_type, _param_type;
      @@
      
       int _get_func(
      -_val_type _val
      +char * _val
       ,
      -_param_type _param
      +const struct kernel_param * _param
       ) { ... }
      
      Two additional by-hand changes are included for places where the above
      Coccinelle script didn't notice them:
      
      	drivers/platform/x86/thinkpad_acpi.c
      	fs/lockd/svc.c
      Signed-off-by: NKees Cook <keescook@chromium.org>
      Signed-off-by: NJessica Yu <jeyu@kernel.org>
      e4dca7b7
  14. 18 10月, 2017 2 次提交
  15. 29 9月, 2017 9 次提交
  16. 28 9月, 2017 7 次提交