11 Feb, 2020

1 commit

  • [ Upstream commit dfa7f709596be5ca46c070d4f8acbb344322056a ]

    Drop monitor uses a work item that takes care of constructing and
    sending netlink notifications to user space. In case drop monitor never
    started to monitor, then the work item is uninitialized and not
    associated with a function.

    Therefore, a stop command from user space results in canceling an
    uninitialized work item which leads to the following warning [1].

    Fix this by not processing a stop command if drop monitor is not
    currently monitoring.

    [1]
    [ 31.735402] ------------[ cut here ]------------
    [ 31.736470] WARNING: CPU: 0 PID: 143 at kernel/workqueue.c:3032 __flush_work+0x89f/0x9f0
    ...
    [ 31.738120] CPU: 0 PID: 143 Comm: dwdump Not tainted 5.5.0-custom-09491-g16d4077796b8 #727
    [ 31.741968] RIP: 0010:__flush_work+0x89f/0x9f0
    ...
    [ 31.760526] Call Trace:
    [ 31.771689] __cancel_work_timer+0x2a6/0x3b0
    [ 31.776809] net_dm_cmd_trace+0x300/0xef0
    [ 31.777549] genl_rcv_msg+0x5c6/0xd50
    [ 31.781005] netlink_rcv_skb+0x13b/0x3a0
    [ 31.784114] genl_rcv+0x29/0x40
    [ 31.784720] netlink_unicast+0x49f/0x6a0
    [ 31.787148] netlink_sendmsg+0x7cf/0xc80
    [ 31.790426] ____sys_sendmsg+0x620/0x770
    [ 31.793458] ___sys_sendmsg+0xfd/0x170
    [ 31.802216] __sys_sendmsg+0xdf/0x1a0
    [ 31.806195] do_syscall_64+0xa0/0x540
    [ 31.806885] entry_SYSCALL_64_after_hwframe+0x49/0xbe

    Fixes: 8e94c3bc922e ("drop_monitor: Allow user to start monitoring hardware drops")
    Signed-off-by: Ido Schimmel
    Reviewed-by: Jiri Pirko
    Signed-off-by: David S. Miller
    Signed-off-by: Greg Kroah-Hartman

    Ido Schimmel
     

17 Sep, 2019

1 commit

  • When working in 'packet' mode, drop monitor generates a notification
    with a potentially truncated payload of the dropped packet. The payload
    is copied from the MAC header, but I forgot to check that the MAC header
    was set, so do it now.

    Fixes: ca30707dee2b ("drop_monitor: Add packet alert mode")
    Fixes: 5e58109b1ea4 ("drop_monitor: Add support for packet alert mode for hardware drops")
    Acked-by: Jiri Pirko
    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     

24 Aug, 2019

1 commit

  • Timestamps are currently communicated to user space as 'struct
    timespec', which is not considered y2038 safe since it uses a 32-bit
    signed value for seconds.

    Fix this while the API is still not part of any official kernel release
    by using 64-bit nanoseconds timestamps instead.

    Fixes: ca30707dee2b ("drop_monitor: Add packet alert mode")
    Fixes: 5e58109b1ea4 ("drop_monitor: Add support for packet alert mode for hardware drops")
    Signed-off-by: Ido Schimmel
    Acked-by: Neil Horman
    Signed-off-by: David S. Miller

    Ido Schimmel
     

18 Aug, 2019

7 commits

  • Drop monitor has start and stop commands, but so far these were only
    used to start and stop monitoring of software drops.

    Now that drop monitor can also monitor hardware drops, we should allow
    the user to control these as well.

    Do that by adding SW and HW flags to these commands. If no flag is
    specified, then only start / stop monitoring software drops. This is
    done in order to maintain backward-compatibility with existing user
    space applications.

    Signed-off-by: Ido Schimmel
    Acked-by: Jiri Pirko
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • In summary alert mode a notification is sent with a list of recent drop
    reasons and a count of how many packets were dropped due to this reason.

    To avoid expensive operations in the context in which packets are
    dropped, each CPU holds an array whose number of entries is the maximum
    number of drop reasons that can be encoded in the netlink notification.
    Each entry stores the drop reason and a count. When a packet is dropped
    the array is traversed and a new entry is created or the count of an
    existing entry is incremented.

    Later, in process context, the array is replaced with a newly allocated
    copy and the old array is encoded in a netlink notification. To avoid
    breaking user space, the notification includes the ancillary header,
    which is 'struct net_dm_alert_msg' with number of entries set to '0'.

    Signed-off-by: Ido Schimmel
    Acked-by: Jiri Pirko
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • In a similar fashion to software drops, extend drop monitor to send
    netlink events when packets are dropped by the underlying hardware.

    The main difference is that instead of encoding the program counter (PC)
    from which kfree_skb() was called in the netlink message, we encode the
    hardware trap name. The two are mostly equivalent since they should both
    help the user understand why the packet was dropped.

    Signed-off-by: Ido Schimmel
    Acked-by: Jiri Pirko
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • The drop monitor configuration (e.g., alert mode) is global, but user
    will be able to enable monitoring of only software or hardware drops.

    Therefore, ensure that monitoring of both software and hardware drops are
    disabled before allowing drop monitor configuration to take place.

    Signed-off-by: Ido Schimmel
    Acked-by: Jiri Pirko
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • Export a function that can be invoked in order to report packets that
    were dropped by the underlying hardware along with metadata.

    Subsequent patches will add support for the different alert modes.

    Signed-off-by: Ido Schimmel
    Acked-by: Jiri Pirko
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • Like software drops, hardware drops also need the same type of per-CPU
    data. Therefore, initialize it during module initialization and
    de-initialize it during module exit.

    Signed-off-by: Ido Schimmel
    Acked-by: Jiri Pirko
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • Currently drop monitor only reports software drops to user space, but
    subsequent patches are going to add support for hardware drops.

    Like software drops, the per-CPU data of hardware drops needs to be
    initialized and de-initialized upon module initialization and exit. To
    avoid code duplication, break this code into separate functions, so that
    these could be re-used for hardware drops.

    No functional changes intended.

    Signed-off-by: Ido Schimmel
    Acked-by: Jiri Pirko
    Signed-off-by: David S. Miller

    Ido Schimmel
     

12 Aug, 2019

10 commits

  • Previous patch made the length of the per-CPU skb drop list
    configurable. Expose a counter that shows how many packets could not be
    enqueued to this list.

    This allows users determine the desired queue length.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • In packet alert mode, each CPU holds a list of dropped skbs that need to
    be processed in process context and sent to user space. To avoid
    exhausting the system's memory the maximum length of this queue is
    currently set to 1000.

    Allow users to tune the length of this queue according to their needs.
    The configured length is reported to user space when drop monitor
    configuration is queried.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • Users should be able to query the current configuration of drop monitor
    before they start using it. Add a command to query the existing
    configuration which currently consists of alert mode and packet
    truncation length.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • When sending dropped packets to user space it is not always necessary to
    copy the entire packet as usually only the headers are of interest.

    Allow user to specify the truncation length and add the original length
    of the packet as additional metadata to the netlink message.

    By default no truncation is performed.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • So far drop monitor supported only one alert mode in which a summary of
    locations in which packets were recently dropped was sent to user space.

    This alert mode is sufficient in order to understand that packets were
    dropped, but lacks information to perform a more detailed analysis.

    Add a new alert mode in which the dropped packet itself is passed to
    user space along with metadata: The drop location (as program counter
    and resolved symbol), ingress netdevice and drop timestamp. More
    metadata can be added in the future.

    To avoid performing expensive operations in the context in which
    kfree_skb() is invoked (can be hard IRQ), the dropped skb is cloned and
    queued on per-CPU skb drop list. Then, in process context the netlink
    message is allocated, prepared and finally sent to user space.

    The per-CPU skb drop list is limited to 1000 skbs to prevent exhausting
    the system's memory. Subsequent patches will make this limit
    configurable and also add a counter that indicates how many skbs were
    tail dropped.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • The next patch is going to add another alert mode in which the dropped
    packet is notified to user space, instead of only a summary of recent
    drops.

    Abstract the differences between the modes by adding alert mode
    operations. The operations are selected based on the currently
    configured mode and associated with the probes and the work item just
    before tracing starts.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • Currently, the configure command does not do anything but return an
    error. Subsequent patches will enable the command to change various
    configuration options such as alert mode and packet truncation.

    Similar to other netlink-based configuration channels, make sure only
    users with the CAP_NET_ADMIN capability set can execute this command.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • The function reset_per_cpu_data() allocates and prepares a new skb for
    the summary netlink alert message ('NET_DM_CMD_ALERT'). The new skb is
    stored in the per-CPU 'data' variable and the old is returned.

    The function is invoked during module initialization and from the
    workqueue, before an alert is sent. This means that it is possible to
    receive an alert with stale data, if we stopped tracing when the
    hysteresis timer ('data->send_timer') was pending.

    Instead of invoking the function during module initialization, invoke it
    just before we start tracing and ensure we get a fresh skb.

    This also allows us to remove the calls to initialize the timer and the
    work item from the module initialization path, since both could have
    been triggered by the error paths of reset_per_cpu_data().

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • The timer and work item are currently initialized once during module
    init, but subsequent patches will need to associate different functions
    with the work item, based on the configured alert mode.

    Allow subsequent patches to make that change by initializing and
    de-initializing these objects during tracing enable and disable.

    This also guarantees that once the request to disable tracing returns,
    no more netlink notifications will be generated.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • Subsequent patches will need to enable / disable tracing based on the
    configured alerting mode.

    Reduce the nesting level and prepare for the introduction of this
    functionality by splitting the tracing enable / disable operations into
    two different functions.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     

07 Aug, 2019

6 commits

  • Each operation from user space should be protected by the global drop
    monitor mutex. Use the pre_doit / post_doit hooks to take / release the
    lock instead of doing it explicitly in each function.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • Add various extack messages to make drop_monitor more user friendly.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • Remove multiple blank lines which are visually annoying and useless.

    This suppresses the "Please don't use multiple blank lines" checkpatch
    messages.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • While 'per_cpu_dm_data' is a per-CPU variable, its 'skb' and
    'send_timer' fields can be accessed concurrently by the CPU sending the
    netlink notification to user space from the workqueue and the CPU
    tracing kfree_skb(). This spinlock is meant to protect against that.

    Document its scope and suppress the checkpatch message "spinlock_t
    definition without comment".

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • The 'trace_state_mutex' does not only protect the global 'trace_state'
    variable, but also the global 'hw_stats_list'.

    Subsequent patches are going add more operations from user space to
    drop_monitor and these all need to be mutually exclusive.

    Rename 'trace_state_mutex' to the more fitting 'net_dm_mutex' name and
    document its scope.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     
  • The error code 'ENOTSUPP' is reserved for use with NFS. Use 'EOPNOTSUPP'
    instead.

    Signed-off-by: Ido Schimmel
    Signed-off-by: David S. Miller

    Ido Schimmel
     

21 May, 2019

1 commit

  • Add SPDX license identifiers to all files which:

    - Have no license information of any form

    - Have MODULE_LICENCE("GPL*") inside which was used in the initial
    scan/conversion to ignore the file

    These files fall under the project license, GPL v2 only. The resulting SPDX
    license identifier is:

    GPL-2.0-only

    Signed-off-by: Thomas Gleixner
    Signed-off-by: Greg Kroah-Hartman

    Thomas Gleixner
     

28 Apr, 2019

1 commit

  • Add options to strictly validate messages and dump messages,
    sometimes perhaps validating dump messages non-strictly may
    be required, so add an option for that as well.

    Since none of this can really be applied to existing commands,
    set the options everwhere using the following spatch:

    @@
    identifier ops;
    expression X;
    @@
    struct genl_ops ops[] = {
    ...,
    {
    .cmd = X,
    + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
    ...
    },
    ...
    };

    For new commands one should just not copy the .validate 'opt-out'
    flags and thus get strict validation.

    Signed-off-by: Johannes Berg
    Signed-off-by: David S. Miller

    Johannes Berg
     

22 Nov, 2017

1 commit

  • 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: Kees Cook

    Kees Cook
     

13 Mar, 2017

1 commit


04 Jan, 2017

1 commit


02 Jan, 2017

1 commit


28 Oct, 2016

3 commits

  • Now genl_register_family() is the only thing (other than the
    users themselves, perhaps, but I didn't find any doing that)
    writing to the family struct.

    In all families that I found, genl_register_family() is only
    called from __init functions (some indirectly, in which case
    I've add __init annotations to clarifly things), so all can
    actually be marked __ro_after_init.

    This protects the data structure from accidental corruption.

    Signed-off-by: Johannes Berg
    Signed-off-by: David S. Miller

    Johannes Berg
     
  • Instead of providing macros/inline functions to initialize
    the families, make all users initialize them statically and
    get rid of the macros.

    This reduces the kernel code size by about 1.6k on x86-64
    (with allyesconfig).

    Signed-off-by: Johannes Berg
    Signed-off-by: David S. Miller

    Johannes Berg
     
  • Static family IDs have never really been used, the only
    use case was the workaround I introduced for those users
    that assumed their family ID was also their multicast
    group ID.

    Additionally, because static family IDs would never be
    reserved by the generic netlink code, using a relatively
    low ID would only work for built-in families that can be
    registered immediately after generic netlink is started,
    which is basically only the control family (apart from
    the workaround code, which I also had to add code for so
    it would reserve those IDs)

    Thus, anything other than GENL_ID_GENERATE is flawed and
    luckily not used except in the cases I mentioned. Move
    those workarounds into a few lines of code, and then get
    rid of GENL_ID_GENERATE entirely, making it more robust.

    Signed-off-by: Johannes Berg
    Signed-off-by: David S. Miller

    Johannes Berg
     

02 Sep, 2016

1 commit


10 Jul, 2016

1 commit

  • An important information for the napi_poll tracepoint is knowing
    the work done (packets processed) by the napi_poll() call. Add
    both the work done and budget, as they are related.

    Handle trace_napi_poll() param change in dropwatch/drop_monitor
    and in python perf script netdev-times.py in backward compat way,
    as python fortunately supports optional parameter handling.

    Signed-off-by: Jesper Dangaard Brouer
    Signed-off-by: David S. Miller

    Jesper Dangaard Brouer
     

27 Aug, 2014

1 commit


16 Jul, 2014

1 commit


10 Dec, 2013

1 commit