27 Mar, 2018

1 commit

  • Prefer the direct use of octal for permissions.

    Done with checkpatch -f --types=SYMBOLIC_PERMS --fix-inplace
    and some typing.

    Miscellanea:

    o Whitespace neatening around these conversions.

    Signed-off-by: Joe Perches
    Signed-off-by: David S. Miller

    Joe Perches
     

20 Feb, 2018

1 commit

  • We had one report from syzkaller [1]

    First issue is that INIT_WORK() should be done before mod_timer()
    or we risk timer being fired too soon, even with a 1 second timer.

    Second issue is that we need to reject too big info->timeout
    to avoid overflows in msecs_to_jiffies(info->timeout * 1000), or
    risk looping, if result after overflow is 0.

    [1]
    WARNING: CPU: 1 PID: 5129 at kernel/workqueue.c:1444 __queue_work+0xdf4/0x1230 kernel/workqueue.c:1444
    Kernel panic - not syncing: panic_on_warn set ...

    CPU: 1 PID: 5129 Comm: syzkaller159866 Not tainted 4.16.0-rc1+ #230
    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
    Call Trace:

    __dump_stack lib/dump_stack.c:17 [inline]
    dump_stack+0x194/0x257 lib/dump_stack.c:53
    panic+0x1e4/0x41c kernel/panic.c:183
    __warn+0x1dc/0x200 kernel/panic.c:547
    report_bug+0x211/0x2d0 lib/bug.c:184
    fixup_bug.part.11+0x37/0x80 arch/x86/kernel/traps.c:178
    fixup_bug arch/x86/kernel/traps.c:247 [inline]
    do_error_trap+0x2d7/0x3e0 arch/x86/kernel/traps.c:296
    do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:315
    invalid_op+0x22/0x40 arch/x86/entry/entry_64.S:988
    RIP: 0010:__queue_work+0xdf4/0x1230 kernel/workqueue.c:1444
    RSP: 0018:ffff8801db507538 EFLAGS: 00010006
    RAX: ffff8801aeb46080 RBX: ffff8801db530200 RCX: ffffffff81481404
    RDX: 0000000000000100 RSI: ffffffff86b42640 RDI: 0000000000000082
    RBP: ffff8801db507758 R08: 1ffff1003b6a0de5 R09: 000000000000000c
    R10: ffff8801db5073f0 R11: 0000000000000020 R12: 1ffff1003b6a0eb6
    R13: ffff8801b1067ae0 R14: 00000000000001f8 R15: dffffc0000000000
    queue_work_on+0x16a/0x1c0 kernel/workqueue.c:1488
    queue_work include/linux/workqueue.h:488 [inline]
    schedule_work include/linux/workqueue.h:546 [inline]
    idletimer_tg_expired+0x44/0x60 net/netfilter/xt_IDLETIMER.c:116
    call_timer_fn+0x228/0x820 kernel/time/timer.c:1326
    expire_timers kernel/time/timer.c:1363 [inline]
    __run_timers+0x7ee/0xb70 kernel/time/timer.c:1666
    run_timer_softirq+0x4c/0x70 kernel/time/timer.c:1692
    __do_softirq+0x2d7/0xb85 kernel/softirq.c:285
    invoke_softirq kernel/softirq.c:365 [inline]
    irq_exit+0x1cc/0x200 kernel/softirq.c:405
    exiting_irq arch/x86/include/asm/apic.h:541 [inline]
    smp_apic_timer_interrupt+0x16b/0x700 arch/x86/kernel/apic/apic.c:1052
    apic_timer_interrupt+0xa9/0xb0 arch/x86/entry/entry_64.S:829

    RIP: 0010:arch_local_irq_restore arch/x86/include/asm/paravirt.h:777 [inline]
    RIP: 0010:__raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:160 [inline]
    RIP: 0010:_raw_spin_unlock_irqrestore+0x5e/0xba kernel/locking/spinlock.c:184
    RSP: 0018:ffff8801c20173c8 EFLAGS: 00000282 ORIG_RAX: ffffffffffffff12
    RAX: dffffc0000000000 RBX: 0000000000000282 RCX: 0000000000000006
    RDX: 1ffffffff0d592cd RSI: 1ffff10035d68d23 RDI: 0000000000000282
    RBP: ffff8801c20173d8 R08: 1ffff10038402e47 R09: 0000000000000000
    R10: 0000000000000000 R11: 0000000000000000 R12: ffffffff8820e5c8
    R13: ffff8801b1067ad8 R14: ffff8801aea7c268 R15: ffff8801aea7c278
    __debug_object_init+0x235/0x1040 lib/debugobjects.c:378
    debug_object_init+0x17/0x20 lib/debugobjects.c:391
    __init_work+0x2b/0x60 kernel/workqueue.c:506
    idletimer_tg_create net/netfilter/xt_IDLETIMER.c:152 [inline]
    idletimer_tg_checkentry+0x691/0xb00 net/netfilter/xt_IDLETIMER.c:213
    xt_check_target+0x22c/0x7d0 net/netfilter/x_tables.c:850
    check_target net/ipv6/netfilter/ip6_tables.c:533 [inline]
    find_check_entry.isra.7+0x935/0xcf0 net/ipv6/netfilter/ip6_tables.c:575
    translate_table+0xf52/0x1690 net/ipv6/netfilter/ip6_tables.c:744
    do_replace net/ipv6/netfilter/ip6_tables.c:1160 [inline]
    do_ip6t_set_ctl+0x370/0x5f0 net/ipv6/netfilter/ip6_tables.c:1686
    nf_sockopt net/netfilter/nf_sockopt.c:106 [inline]
    nf_setsockopt+0x67/0xc0 net/netfilter/nf_sockopt.c:115
    ipv6_setsockopt+0x10b/0x130 net/ipv6/ipv6_sockglue.c:927
    udpv6_setsockopt+0x45/0x80 net/ipv6/udp.c:1422
    sock_common_setsockopt+0x95/0xd0 net/core/sock.c:2976
    SYSC_setsockopt net/socket.c:1850 [inline]
    SyS_setsockopt+0x189/0x360 net/socket.c:1829
    do_syscall_64+0x282/0x940 arch/x86/entry/common.c:287

    Fixes: 0902b469bd25 ("netfilter: xtables: idletimer target implementation")
    Signed-off-by: Eric Dumazet
    Reported-by: syzkaller
    Signed-off-by: Pablo Neira Ayuso

    Eric Dumazet
     

31 Jan, 2018

1 commit

  • Several netfilter matches and targets put kernel pointers into
    info objects, but don't set usersize in descriptors.
    This leads to kernel pointer leaks if a match/target is set
    and then read back to userspace.

    Properly set usersize for these matches/targets.

    Found with manual code inspection.

    Fixes: ec2318904965 ("xtables: extend matches and targets with .usersize")
    Signed-off-by: Dmitry Vyukov
    Signed-off-by: Pablo Neira Ayuso

    Dmitry Vyukov
     

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
     

29 Apr, 2016

1 commit


13 Jul, 2015

1 commit

  • Dynamically allocated sysfs attributes should be initialized with
    sysfs_attr_init() otherwise lockdep will be angry with us:

    [ 45.468653] BUG: key ffffffc030fad4e0 not in .data!
    [ 45.468655] ------------[ cut here ]------------
    [ 45.468666] WARNING: CPU: 0 PID: 1176 at /mnt/host/source/src/third_party/kernel/v3.18/kernel/locking/lockdep.c:2991 lockdep_init_map+0x12c/0x490()
    [ 45.468672] DEBUG_LOCKS_WARN_ON(1)
    [ 45.468672] CPU: 0 PID: 1176 Comm: iptables Tainted: G U W 3.18.0 #43
    [ 45.468674] Hardware name: XXX
    [ 45.468675] Call trace:
    [ 45.468680] [] dump_backtrace+0x0/0x10c
    [ 45.468683] [] show_stack+0x10/0x1c
    [ 45.468688] [] dump_stack+0x74/0x94
    [ 45.468692] [] warn_slowpath_common+0x84/0xb0
    [ 45.468694] [] warn_slowpath_fmt+0x4c/0x58
    [ 45.468697] [] lockdep_init_map+0x128/0x490
    [ 45.468701] [] __kernfs_create_file+0x80/0xe4
    [ 45.468704] [] sysfs_add_file_mode_ns+0x104/0x170
    [ 45.468706] [] sysfs_create_file_ns+0x58/0x64
    [ 45.468711] [] idletimer_tg_checkentry+0x14c/0x324
    [ 45.468714] [] xt_check_target+0x170/0x198
    [ 45.468717] [] check_target+0x58/0x6c
    [ 45.468720] [] translate_table+0x30c/0x424
    [ 45.468723] [] do_ipt_set_ctl+0x144/0x1d0
    [ 45.468728] [] nf_setsockopt+0x50/0x60
    [ 45.468732] [] ip_setsockopt+0x8c/0xb4
    [ 45.468735] [] raw_setsockopt+0x10/0x50
    [ 45.468739] [] sock_common_setsockopt+0x14/0x20
    [ 45.468742] [] SyS_setsockopt+0x88/0xb8
    [ 45.468744] ---[ end trace 41d156354d18c039 ]---

    Signed-off-by: Dmitry Torokhov
    Signed-off-by: Pablo Neira Ayuso

    Dmitry Torokhov
     

01 Nov, 2011

1 commit


18 Jan, 2011

1 commit


22 Jun, 2010

1 commit


15 Jun, 2010

1 commit

  • This patch implements an idletimer Xtables target that can be used to
    identify when interfaces have been idle for a certain period of time.

    Timers are identified by labels and are created when a rule is set with a new
    label. The rules also take a timeout value (in seconds) as an option. If
    more than one rule uses the same timer label, the timer will be restarted
    whenever any of the rules get a hit.

    One entry for each timer is created in sysfs. This attribute contains the
    timer remaining for the timer to expire. The attributes are located under
    the xt_idletimer class:

    /sys/class/xt_idletimer/timers/

    When the timer expires, the target module sends a sysfs notification to the
    userspace, which can then decide what to do (eg. disconnect to save power).

    Cc: Timo Teras
    Signed-off-by: Luciano Coelho
    Signed-off-by: Patrick McHardy

    Luciano Coelho