1. 24 9月, 2020 1 次提交
    • D
      xfrm: Provide API to register translator module · c9e7c76d
      Dmitry Safonov 提交于
      Add a skeleton for xfrm_compat module and provide API to register it in
      xfrm_state.ko. struct xfrm_translator will have function pointers to
      translate messages received from 32-bit userspace or to be sent to it
      from 64-bit kernel.
      module_get()/module_put() are used instead of rcu_read_lock() as the
      module will vmalloc() memory for translation.
      The new API is registered with xfrm_state module, not with xfrm_user as
      the former needs translator for user_policy set by setsockopt() and
      xfrm_user already uses functions from xfrm_state.
      Signed-off-by: NDmitry Safonov <dima@arista.com>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      c9e7c76d
  2. 25 7月, 2020 1 次提交
  3. 19 2月, 2020 1 次提交
  4. 09 12月, 2019 1 次提交
  5. 07 11月, 2019 1 次提交
  6. 01 7月, 2019 1 次提交
  7. 06 6月, 2019 2 次提交
  8. 05 6月, 2019 3 次提交
  9. 21 5月, 2019 1 次提交
  10. 23 4月, 2019 1 次提交
  11. 08 4月, 2019 4 次提交
  12. 26 3月, 2019 1 次提交
    • C
      xfrm: clean up xfrm protocol checks · dbb2483b
      Cong Wang 提交于
      In commit 6a53b759 ("xfrm: check id proto in validate_tmpl()")
      I introduced a check for xfrm protocol, but according to Herbert
      IPSEC_PROTO_ANY should only be used as a wildcard for lookup, so
      it should be removed from validate_tmpl().
      
      And, IPSEC_PROTO_ANY is expected to only match 3 IPSec-specific
      protocols, this is why xfrm_state_flush() could still miss
      IPPROTO_ROUTING, which leads that those entries are left in
      net->xfrm.state_all before exit net. Fix this by replacing
      IPSEC_PROTO_ANY with zero.
      
      This patch also extracts the check from validate_tmpl() to
      xfrm_id_proto_valid() and uses it in parse_ipsecrequest().
      With this, no other protocols should be added into xfrm.
      
      Fixes: 6a53b759 ("xfrm: check id proto in validate_tmpl()")
      Reported-by: syzbot+0bf0519d6e0de15914fe@syzkaller.appspotmail.com
      Cc: Steffen Klassert <steffen.klassert@secunet.com>
      Cc: Herbert Xu <herbert@gondor.apana.org.au>
      Signed-off-by: NCong Wang <xiyou.wangcong@gmail.com>
      Acked-by: NHerbert Xu <herbert@gondor.apana.org.au>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      dbb2483b
  13. 22 3月, 2019 1 次提交
  14. 05 2月, 2019 1 次提交
    • C
      xfrm: destroy xfrm_state synchronously on net exit path · f75a2804
      Cong Wang 提交于
      xfrm_state_put() moves struct xfrm_state to the GC list
      and schedules the GC work to clean it up. On net exit call
      path, xfrm_state_flush() is called to clean up and
      xfrm_flush_gc() is called to wait for the GC work to complete
      before exit.
      
      However, this doesn't work because one of the ->destructor(),
      ipcomp_destroy(), schedules the same GC work again inside
      the GC work. It is hard to wait for such a nested async
      callback. This is also why syzbot still reports the following
      warning:
      
       WARNING: CPU: 1 PID: 33 at net/ipv6/xfrm6_tunnel.c:351 xfrm6_tunnel_net_exit+0x2cb/0x500 net/ipv6/xfrm6_tunnel.c:351
       ...
        ops_exit_list.isra.0+0xb0/0x160 net/core/net_namespace.c:153
        cleanup_net+0x51d/0xb10 net/core/net_namespace.c:551
        process_one_work+0xd0c/0x1ce0 kernel/workqueue.c:2153
        worker_thread+0x143/0x14a0 kernel/workqueue.c:2296
        kthread+0x357/0x430 kernel/kthread.c:246
        ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352
      
      In fact, it is perfectly fine to bypass GC and destroy xfrm_state
      synchronously on net exit call path, because it is in process context
      and doesn't need a work struct to do any blocking work.
      
      This patch introduces xfrm_state_put_sync() which simply bypasses
      GC, and lets its callers to decide whether to use this synchronous
      version. On net exit path, xfrm_state_fini() and
      xfrm6_tunnel_net_exit() use it. And, as ipcomp_destroy() itself is
      blocking, it can use xfrm_state_put_sync() directly too.
      
      Also rename xfrm_state_gc_destroy() to ___xfrm_state_destroy() to
      reflect this change.
      
      Fixes: b48c05ab ("xfrm: Fix warning in xfrm6_tunnel_net_exit.")
      Reported-and-tested-by: syzbot+e9aebef558e3ed673934@syzkaller.appspotmail.com
      Cc: Steffen Klassert <steffen.klassert@secunet.com>
      Signed-off-by: NCong Wang <xiyou.wangcong@gmail.com>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      f75a2804
  15. 23 11月, 2018 1 次提交
  16. 06 11月, 2018 1 次提交
  17. 01 11月, 2018 1 次提交
    • D
      compat: Cleanup in_compat_syscall() callers · 98f76206
      Dmitry Safonov 提交于
      Now that in_compat_syscall() is consistent on all architectures and does
      not longer report true on native i686, the workarounds (ifdeffery and
      helpers) can be removed.
      Signed-off-by: NDmitry Safonov <dima@arista.com>
      Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
      Cc: Dmitry Safonov <0x7f454c46@gmail.com>
      Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
      Cc: Andy Lutomirsky <luto@kernel.org>
      Cc: "David S. Miller" <davem@davemloft.net>
      Cc: Herbert Xu <herbert@gondor.apana.org.au>
      Cc: "H. Peter Anvin" <hpa@zytor.com>
      Cc: John Stultz <john.stultz@linaro.org>
      Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
      Cc: Oleg Nesterov <oleg@redhat.com>
      Cc: Steffen Klassert <steffen.klassert@secunet.com>
      Cc: Stephen Boyd <sboyd@kernel.org>
      Cc: Steven Rostedt <rostedt@goodmis.org>
      Cc: linux-efi@vger.kernel.org
      Cc: netdev@vger.kernel.org
      Link: https://lkml.kernel.org/r/20181012134253.23266-3-dima@arista.com
      98f76206
  18. 20 7月, 2018 2 次提交
    • N
      xfrm: Allow xfrmi if_id to be updated by UPDSA · 5baf4f9c
      Nathan Harold 提交于
      Allow attaching an SA to an xfrm interface id after
      the creation of the SA, so that tasks such as keying
      which must be done as the SA is created, can remain
      separate from the decision on how to route traffic
      from an SA. This permits SA creation to be decomposed
      in to three separate steps:
      1) allocation of a SPI
      2) algorithm and key negotiation
      3) insertion into the data path
      Signed-off-by: NNathan Harold <nharold@google.com>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      5baf4f9c
    • B
      xfrm: Remove xfrmi interface ID from flowi · bc56b334
      Benedict Wong 提交于
      In order to remove performance impact of having the extra u32 in every
      single flowi, this change removes the flowi_xfrm struct, prefering to
      take the if_id as a method parameter where needed.
      
      In the inbound direction, if_id is only needed during the
      __xfrm_check_policy() function, and the if_id can be determined at that
      point based on the skb. As such, xfrmi_decode_session() is only called
      with the skb in __xfrm_check_policy().
      
      In the outbound direction, the only place where if_id is needed is the
      xfrm_lookup() call in xfrmi_xmit2(). With this change, the if_id is
      directly passed into the xfrm_lookup_with_ifid() call. All existing
      callers can still call xfrm_lookup(), which uses a default if_id of 0.
      
      This change does not change any behavior of XFRMIs except for improving
      overall system performance via flowi size reduction.
      
      This change has been tested against the Android Kernel Networking Tests:
      
      https://android.googlesource.com/kernel/tests/+/master/net/testSigned-off-by: NBenedict Wong <benedictwong@google.com>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      bc56b334
  19. 11 7月, 2018 1 次提交
    • A
      xfrm: use time64_t for in-kernel timestamps · 386c5680
      Arnd Bergmann 提交于
      The lifetime managment uses '__u64' timestamps on the user space
      interface, but 'unsigned long' for reading the current time in the kernel
      with get_seconds().
      
      While this is probably safe beyond y2038, it will still overflow in 2106,
      and the get_seconds() call is deprecated because fo that.
      
      This changes the xfrm time handling to use time64_t consistently, along
      with reading the time using the safer ktime_get_real_seconds(). It still
      suffers from problems that can happen from a concurrent settimeofday()
      call or (to a lesser degree) a leap second update, but since the time
      stamps are part of the user API, there is nothing we can do to prevent
      that.
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      386c5680
  20. 01 7月, 2018 1 次提交
    • N
      xfrm: Allow Set Mark to be Updated Using UPDSA · 6d8e85ff
      Nathan Harold 提交于
      Allow UPDSA to change "set mark" to permit
      policy separation of packet routing decisions from
      SA keying in systems that use mark-based routing.
      
      The set mark, used as a routing and firewall mark
      for outbound packets, is made update-able which
      allows routing decisions to be handled independently
      of keying/SA creation. To maintain consistency with
      other optional attributes, the set mark is only
      updated if sent with a non-zero value.
      
      The per-SA lock and the xfrm_state_lock are taken in
      that order to avoid a deadlock with
      xfrm_timer_handler(), which also takes the locks in
      that order.
      Signed-off-by: NNathan Harold <nharold@google.com>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      6d8e85ff
  21. 25 6月, 2018 1 次提交
    • F
      xfrm: policy: remove pcpu policy cache · e4db5b61
      Florian Westphal 提交于
      Kristian Evensen says:
        In a project I am involved in, we are running ipsec (Strongswan) on
        different mt7621-based routers. Each router is configured as an
        initiator and has around ~30 tunnels to different responders (running
        on misc. devices). Before the flow cache was removed (kernel 4.9), we
        got a combined throughput of around 70Mbit/s for all tunnels on one
        router. However, we recently switched to kernel 4.14 (4.14.48), and
        the total throughput is somewhere around 57Mbit/s (best-case). I.e., a
        drop of around 20%. Reverting the flow cache removal restores, as
        expected, performance levels to that of kernel 4.9.
      
      When pcpu xdst exists, it has to be validated first before it can be
      used.
      
      A negative hit thus increases cost vs. no-cache.
      
      As number of tunnels increases, hit rate decreases so this pcpu caching
      isn't a viable strategy.
      
      Furthermore, the xdst cache also needs to run with BH off, so when
      removing this the bh disable/enable pairs can be removed too.
      
      Kristian tested a 4.14.y backport of this change and reported
      increased performance:
      
        In our tests, the throughput reduction has been reduced from around -20%
        to -5%. We also see that the overall throughput is independent of the
        number of tunnels, while before the throughput was reduced as the number
        of tunnels increased.
      Reported-by: NKristian Evensen <kristian.evensen@gmail.com>
      Signed-off-by: NFlorian Westphal <fw@strlen.de>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      e4db5b61
  22. 23 6月, 2018 1 次提交
  23. 04 5月, 2018 1 次提交
    • M
      xfrm: use a dedicated slab cache for struct xfrm_state · 565f0fa9
      Mathias Krause 提交于
      struct xfrm_state is rather large (768 bytes here) and therefore wastes
      quite a lot of memory as it falls into the kmalloc-1024 slab cache,
      leaving 256 bytes of unused memory per XFRM state object -- a net waste
      of 25%.
      
      Using a dedicated slab cache for struct xfrm_state reduces the level of
      internal fragmentation to a minimum.
      
      On my configuration SLUB chooses to create a slab cache covering 4
      pages holding 21 objects, resulting in an average memory waste of ~13
      bytes per object -- a net waste of only 1.6%.
      
      In my tests this led to memory savings of roughly 2.3MB for 10k XFRM
      states.
      Signed-off-by: NMathias Krause <minipli@googlemail.com>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      565f0fa9
  24. 16 4月, 2018 1 次提交
  25. 02 2月, 2018 1 次提交
  26. 23 1月, 2018 1 次提交
  27. 18 1月, 2018 1 次提交
  28. 31 12月, 2017 1 次提交
  29. 30 12月, 2017 1 次提交
    • H
      xfrm: Forbid state updates from changing encap type · 257a4b01
      Herbert Xu 提交于
      Currently we allow state updates to competely replace the contents
      of x->encap.  This is bad because on the user side ESP only sets up
      header lengths depending on encap_type once when the state is first
      created.  This could result in the header lengths getting out of
      sync with the actual state configuration.
      
      In practice key managers will never do a state update to change the
      encapsulation type.  Only the port numbers need to be changed as the
      peer NAT entry is updated.
      
      Therefore this patch adds a check in xfrm_state_update to forbid
      any changes to the encap_type.
      Signed-off-by: NHerbert Xu <herbert@gondor.apana.org.au>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      257a4b01
  30. 08 12月, 2017 1 次提交
  31. 30 11月, 2017 1 次提交
    • L
      net: xfrm: allow clearing socket xfrm policies. · be8f8284
      Lorenzo Colitti 提交于
      Currently it is possible to add or update socket policies, but
      not clear them. Therefore, once a socket policy has been applied,
      the socket cannot be used for unencrypted traffic.
      
      This patch allows (privileged) users to clear socket policies by
      passing in a NULL pointer and zero length argument to the
      {IP,IPV6}_{IPSEC,XFRM}_POLICY setsockopts. This results in both
      the incoming and outgoing policies being cleared.
      
      The simple approach taken in this patch cannot clear socket
      policies in only one direction. If desired this could be added
      in the future, for example by continuing to pass in a length of
      zero (which currently is guaranteed to return EMSGSIZE) and
      making the policy be a pointer to an integer that contains one
      of the XFRM_POLICY_{IN,OUT} enum values.
      
      An alternative would have been to interpret the length as a
      signed integer and use XFRM_POLICY_IN (i.e., 0) to clear the
      input policy and -XFRM_POLICY_OUT (i.e., -1) to clear the output
      policy.
      
      Tested: https://android-review.googlesource.com/539816Signed-off-by: NLorenzo Colitti <lorenzo@google.com>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      be8f8284
  32. 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
  33. 26 10月, 2017 1 次提交
    • J
      xfrm: Clear sk_dst_cache when applying per-socket policy. · 2b06cdf3
      Jonathan Basseri 提交于
      If a socket has a valid dst cache, then xfrm_lookup_route will get
      skipped. However, the cache is not invalidated when applying policy to a
      socket (i.e. IPV6_XFRM_POLICY). The result is that new policies are
      sometimes ignored on those sockets. (Note: This was broken for IPv4 and
      IPv6 at different times.)
      
      This can be demonstrated like so,
      1. Create UDP socket.
      2. connect() the socket.
      3. Apply an outbound XFRM policy to the socket. (setsockopt)
      4. send() data on the socket.
      
      Packets will continue to be sent in the clear instead of matching an
      xfrm or returning a no-match error (EAGAIN). This affects calls to
      send() and not sendto().
      
      Invalidating the sk_dst_cache is necessary to correctly apply xfrm
      policies. Since we do this in xfrm_user_policy(), the sk_lock was
      already acquired in either do_ip_setsockopt() or do_ipv6_setsockopt(),
      and we may call __sk_dst_reset().
      
      Performance impact should be negligible, since this code is only called
      when changing xfrm policy, and only affects the socket in question.
      
      Fixes: 00bc0ef5 ("ipv6: Skip XFRM lookup if dst_entry in socket cache is valid")
      Tested: https://android-review.googlesource.com/517555
      Tested: https://android-review.googlesource.com/418659Signed-off-by: NJonathan Basseri <misterikkit@google.com>
      Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
      2b06cdf3