On Fri, Oct 28, 2016 at 5:40 PM, Andrey Konovalov <andreyk...@google.com> wrote:
> Hi,
>
> I've got the following error report while running the syzkaller fuzzer:
>
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 4608 at kernel/sched/core.c:7724
> __might_sleep+0x14c/0x1a0 kernel/sched/core.c:7719
> do not call blocking ops when !TASK_RUNNING; state=1 set at
> [<ffffffff811f5a5c>] prepare_to_wait+0xbc/0x210
> kernel/sched/wait.c:178
> Modules linked in:
> CPU: 0 PID: 4608 Comm: syz-executor Not tainted 4.9.0-rc2+ #320
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
>  ffff88006625f7a0 ffffffff81b46914 ffff88006625f818 0000000000000000
>  ffffffff84052960 0000000000000000 ffff88006625f7e8 ffffffff81111237
>  ffff88006aceac00 ffffffff00001e2c ffffed000cc4beff ffffffff84052960
> Call Trace:
>  [<     inline     >] __dump_stack lib/dump_stack.c:15
>  [<ffffffff81b46914>] dump_stack+0xb3/0x10f lib/dump_stack.c:51
>  [<ffffffff81111237>] __warn+0x1a7/0x1f0 kernel/panic.c:550
>  [<ffffffff8111132c>] warn_slowpath_fmt+0xac/0xd0 kernel/panic.c:565
>  [<ffffffff811922fc>] __might_sleep+0x14c/0x1a0 kernel/sched/core.c:7719
>  [<     inline     >] slab_pre_alloc_hook mm/slab.h:393
>  [<     inline     >] slab_alloc_node mm/slub.c:2634
>  [<     inline     >] slab_alloc mm/slub.c:2716
>  [<ffffffff81508da0>] __kmalloc_track_caller+0x150/0x2a0 mm/slub.c:4240
>  [<ffffffff8146be14>] kmemdup+0x24/0x50 mm/util.c:113
>  [<ffffffff8388b2cf>] dccp_feat_clone_sp_val.part.5+0x4f/0xe0
> net/dccp/feat.c:374
>  [<     inline     >] dccp_feat_clone_sp_val net/dccp/feat.c:1141
>  [<     inline     >] dccp_feat_change_recv net/dccp/feat.c:1141
>  [<ffffffff8388d491>] dccp_feat_parse_options+0xaa1/0x13d0 
> net/dccp/feat.c:1411
>  [<ffffffff83894f01>] dccp_parse_options+0x721/0x1010 net/dccp/options.c:128
>  [<ffffffff83891280>] dccp_rcv_state_process+0x200/0x15b0 net/dccp/input.c:644
>  [<ffffffff838b8a94>] dccp_v4_do_rcv+0xf4/0x1a0 net/dccp/ipv4.c:681
>  [<     inline     >] sk_backlog_rcv ./include/net/sock.h:872
>  [<ffffffff82b7ceb6>] __release_sock+0x126/0x3a0 net/core/sock.c:2044
>  [<ffffffff82b7d189>] release_sock+0x59/0x1c0 net/core/sock.c:2502
>  [<     inline     >] inet_wait_for_connect net/ipv4/af_inet.c:547
>  [<ffffffff8316b2a2>] __inet_stream_connect+0x5d2/0xbb0 net/ipv4/af_inet.c:617
>  [<ffffffff8316b8d5>] inet_stream_connect+0x55/0xa0 net/ipv4/af_inet.c:656
>  [<ffffffff82b705e4>] SYSC_connect+0x244/0x2f0 net/socket.c:1533
>  [<ffffffff82b72dd4>] SyS_connect+0x24/0x30 net/socket.c:1514
>  [<ffffffff83fbf701>] entry_SYSCALL_64_fastpath+0x1f/0xc2
> arch/x86/entry/entry_64.S:209

Should be fixed the attached patch. I will verify it with your
reproducer tomorrow.

Thanks!
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 1704948..c90cb35 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -367,11 +367,11 @@ static inline int dccp_feat_must_be_understood(u8 
feat_num)
 }
 
 /* copy constructor, fval must not already contain allocated memory */
-static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len)
+static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len, 
gfp_t flags)
 {
        fval->sp.len = len;
        if (fval->sp.len > 0) {
-               fval->sp.vec = kmemdup(val, len, gfp_any());
+               fval->sp.vec = kmemdup(val, len, flags);
                if (fval->sp.vec == NULL) {
                        fval->sp.len = 0;
                        return -ENOBUFS;
@@ -404,7 +404,8 @@ static void dccp_feat_val_destructor(u8 feat_num, 
dccp_feat_val *val)
 
        if (type == FEAT_SP && dccp_feat_clone_sp_val(&new->val,
                                                      original->val.sp.vec,
-                                                     original->val.sp.len)) {
+                                                     original->val.sp.len,
+                                                     gfp_any())) {
                kfree(new);
                return NULL;
        }
@@ -735,7 +736,7 @@ static int __feat_register_sp(struct list_head *fn, u8 
feat, u8 is_local,
        if (feat == DCCPF_CCID && !ccid_support_check(sp_val, sp_len))
                return -EOPNOTSUPP;
 
-       if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len))
+       if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len, gfp_any()))
                return -ENOMEM;
 
        return dccp_feat_push_change(fn, feat, is_local, mandatory, &fval);
@@ -1138,7 +1139,7 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 
is_mandatory, u8 opt,
                 *   otherwise we accept the preferred value;
                 * - else if we are the client, we use the first list element.
                 */
-               if (dccp_feat_clone_sp_val(&fval, val, 1))
+               if (dccp_feat_clone_sp_val(&fval, val, 1, GFP_ATOMIC))
                        return DCCP_RESET_CODE_TOO_BUSY;
 
                if (len > 1 && server) {

Reply via email to