github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/vm/vm_test.go (about)

     1  // Copyright 2018 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package vm
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"fmt"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/google/syzkaller/pkg/mgrconfig"
    15  	"github.com/google/syzkaller/pkg/report"
    16  	"github.com/google/syzkaller/pkg/report/crash"
    17  	"github.com/google/syzkaller/sys/targets"
    18  	"github.com/google/syzkaller/vm/vmimpl"
    19  	"github.com/stretchr/testify/assert"
    20  )
    21  
    22  type testPool struct {
    23  }
    24  
    25  func (pool *testPool) Count() int {
    26  	return 1
    27  }
    28  
    29  func (pool *testPool) Create(_ context.Context, workdir string, index int) (vmimpl.Instance, error) {
    30  	return &testInstance{
    31  		outc: make(chan []byte, 10),
    32  		errc: make(chan error, 1),
    33  	}, nil
    34  }
    35  
    36  func (pool *testPool) Close() error {
    37  	return nil
    38  }
    39  
    40  type testInstance struct {
    41  	outc           chan []byte
    42  	errc           chan error
    43  	diagnoseBug    bool
    44  	diagnoseNoWait bool
    45  }
    46  
    47  func (inst *testInstance) Copy(hostSrc string) (string, error) {
    48  	return "", nil
    49  }
    50  
    51  func (inst *testInstance) Forward(port int) (string, error) {
    52  	return "", nil
    53  }
    54  
    55  func (inst *testInstance) Run(ctx context.Context, command string) (
    56  	outc <-chan []byte, errc <-chan error, err error) {
    57  	return inst.outc, inst.errc, nil
    58  }
    59  
    60  func (inst *testInstance) Diagnose(rep *report.Report) ([]byte, bool) {
    61  	var diag []byte
    62  	if inst.diagnoseBug {
    63  		diag = []byte("BUG: DIAGNOSE\n")
    64  	} else {
    65  		diag = []byte("DIAGNOSE\n")
    66  	}
    67  
    68  	if inst.diagnoseNoWait {
    69  		return diag, false
    70  	}
    71  
    72  	inst.outc <- diag
    73  	return nil, true
    74  }
    75  
    76  func (inst *testInstance) Close() error {
    77  	return nil
    78  }
    79  
    80  func init() {
    81  	vmimpl.WaitForOutputTimeout = 3 * time.Second
    82  	ctor := func(env *vmimpl.Env) (vmimpl.Pool, error) {
    83  		return &testPool{}, nil
    84  	}
    85  	vmimpl.Register("test", vmimpl.Type{
    86  		Ctor:        ctor,
    87  		Preemptible: true,
    88  	})
    89  }
    90  
    91  func withTestRunOptionsDefaults() func(*RunOptions) {
    92  	return func(opts *RunOptions) {
    93  		opts.beforeContext = maxErrorLength + 100
    94  		opts.tickerPeriod = 1 * time.Second
    95  	}
    96  }
    97  
    98  type Test struct {
    99  	Name           string
   100  	Exit           ExitCondition
   101  	DiagnoseBug    bool // Diagnose produces output that is detected as kernel crash.
   102  	DiagnoseNoWait bool // Diagnose returns output directly rather than to console.
   103  	Body           func(outc chan []byte, errc chan error)
   104  	BodyExecuting  func(outc chan []byte, errc chan error, inject chan<- bool)
   105  	Report         *report.Report
   106  }
   107  
   108  // nolint: goconst // "DIAGNOSE\n", "BUG: bad\n" and "other output\n"
   109  var tests = []*Test{
   110  	{
   111  		Name: "program-exits-normally",
   112  		Exit: ExitNormal,
   113  		Body: func(outc chan []byte, errc chan error) {
   114  			time.Sleep(time.Second)
   115  			errc <- nil
   116  		},
   117  	},
   118  	{
   119  		Name: "program-exits-when-it-should-not",
   120  		Body: func(outc chan []byte, errc chan error) {
   121  			time.Sleep(time.Second)
   122  			errc <- nil
   123  		},
   124  		Report: &report.Report{
   125  			Title: lostConnectionCrash,
   126  			Type:  crash.LostConnection,
   127  		},
   128  	},
   129  	{
   130  		Name:        "#875-diagnose-bugs",
   131  		Exit:        ExitNormal,
   132  		DiagnoseBug: true,
   133  		Body: func(outc chan []byte, errc chan error) {
   134  			errc <- nil
   135  		},
   136  	},
   137  	{
   138  		Name: "#875-diagnose-bugs-2",
   139  		Body: func(outc chan []byte, errc chan error) {
   140  			errc <- nil
   141  		},
   142  		Report: &report.Report{
   143  			Title: lostConnectionCrash,
   144  			Output: []byte(
   145  				"DIAGNOSE\n",
   146  			),
   147  			Type: crash.LostConnection,
   148  		},
   149  	},
   150  	{
   151  		Name: "diagnose-no-wait",
   152  		Body: func(outc chan []byte, errc chan error) {
   153  			errc <- nil
   154  		},
   155  		DiagnoseNoWait: true,
   156  		Report: &report.Report{
   157  			Title: lostConnectionCrash,
   158  			Output: []byte(
   159  				"\n" +
   160  					"VM DIAGNOSIS:\n" +
   161  					"DIAGNOSE\n",
   162  			),
   163  			Type: crash.LostConnection,
   164  		},
   165  	},
   166  	{
   167  		Name: "diagnose-bug-no-wait",
   168  		Body: func(outc chan []byte, errc chan error) {
   169  			outc <- []byte("BUG: bad\n")
   170  			time.Sleep(time.Second)
   171  			outc <- []byte("other output\n")
   172  		},
   173  		DiagnoseNoWait: true,
   174  		Report: &report.Report{
   175  			Title: "BUG: bad",
   176  			Report: []byte(
   177  				"BUG: bad\n" +
   178  					"other output\n",
   179  			),
   180  			Output: []byte(
   181  				"BUG: bad\n" +
   182  					"other output\n" +
   183  					"\n" +
   184  					"VM DIAGNOSIS:\n" +
   185  					"DIAGNOSE\n",
   186  			),
   187  		},
   188  	},
   189  	{
   190  		Name: "kernel-crashes",
   191  		Body: func(outc chan []byte, errc chan error) {
   192  			outc <- []byte("BUG: bad\n")
   193  			time.Sleep(time.Second)
   194  			outc <- []byte("other output\n")
   195  		},
   196  		Report: &report.Report{
   197  			Title: "BUG: bad",
   198  			Report: []byte(
   199  				"BUG: bad\n" +
   200  					"DIAGNOSE\n" +
   201  					"other output\n",
   202  			),
   203  		},
   204  	},
   205  	{
   206  		Name: "fuzzer-is-preempted",
   207  		Body: func(outc chan []byte, errc chan error) {
   208  			outc <- []byte("BUG: bad\n")
   209  			outc <- []byte(executorPreemptedStr + "\n")
   210  		},
   211  	},
   212  	{
   213  		Name: "program-exits-but-kernel-crashes-afterwards",
   214  		Exit: ExitNormal,
   215  		Body: func(outc chan []byte, errc chan error) {
   216  			errc <- nil
   217  			time.Sleep(time.Second)
   218  			outc <- []byte("BUG: bad\n")
   219  		},
   220  		Report: &report.Report{
   221  			Title: "BUG: bad",
   222  			Report: []byte(
   223  				"BUG: bad\n" +
   224  					"DIAGNOSE\n",
   225  			),
   226  		},
   227  	},
   228  	{
   229  		Name: "timeout",
   230  		Exit: ExitTimeout,
   231  		Body: func(outc chan []byte, errc chan error) {
   232  			errc <- vmimpl.ErrTimeout
   233  		},
   234  	},
   235  	{
   236  		Name: "bad-timeout",
   237  		Body: func(outc chan []byte, errc chan error) {
   238  			errc <- vmimpl.ErrTimeout
   239  		},
   240  		Report: &report.Report{
   241  			Title: timeoutCrash,
   242  		},
   243  	},
   244  	{
   245  		Name: "program-crashes",
   246  		Body: func(outc chan []byte, errc chan error) {
   247  			errc <- fmt.Errorf("error")
   248  		},
   249  		Report: &report.Report{
   250  			Title: lostConnectionCrash,
   251  			Type:  crash.LostConnection,
   252  		},
   253  	},
   254  	{
   255  		Name: "program-crashes-expected",
   256  		Exit: ExitError,
   257  		Body: func(outc chan []byte, errc chan error) {
   258  			errc <- fmt.Errorf("error")
   259  		},
   260  	},
   261  	{
   262  		Name: "no-output-1",
   263  		Body: func(outc chan []byte, errc chan error) {
   264  		},
   265  		Report: &report.Report{
   266  			Title: noOutputCrash,
   267  		},
   268  	},
   269  	{
   270  		Name: "no-output-2",
   271  		Body: func(outc chan []byte, errc chan error) {
   272  			for i := 0; i < 5; i++ {
   273  				time.Sleep(time.Second)
   274  				outc <- []byte("something\n")
   275  			}
   276  		},
   277  		Report: &report.Report{
   278  			Title: noOutputCrash,
   279  		},
   280  	},
   281  	{
   282  		Name: "no-no-output",
   283  		Exit: ExitNormal,
   284  		Body: func(outc chan []byte, errc chan error) {
   285  			for i := 0; i < 5; i++ {
   286  				time.Sleep(time.Second)
   287  				outc <- []byte(executedProgramsStart + "\n")
   288  			}
   289  			errc <- nil
   290  		},
   291  	},
   292  	{
   293  		Name: "outc-closed",
   294  		Exit: ExitTimeout,
   295  		Body: func(outc chan []byte, errc chan error) {
   296  			close(outc)
   297  			time.Sleep(time.Second)
   298  			errc <- vmimpl.ErrTimeout
   299  		},
   300  	},
   301  	{
   302  		Name: "lots-of-output",
   303  		Exit: ExitTimeout,
   304  		Body: func(outc chan []byte, errc chan error) {
   305  			for i := 0; i < 100; i++ {
   306  				outc <- []byte("something\n")
   307  			}
   308  			time.Sleep(time.Second)
   309  			errc <- vmimpl.ErrTimeout
   310  		},
   311  	},
   312  	{
   313  		Name: "split-line",
   314  		Exit: ExitNormal,
   315  		Body: func(outc chan []byte, errc chan error) {
   316  			// "ODEBUG:" lines should be ignored, however the curPos logic
   317  			// used to trim the lines so that we could see just "BUG:" later
   318  			// and detect it as crash.
   319  			buf := new(bytes.Buffer)
   320  			for i := 0; i < 50; i++ {
   321  				buf.WriteString("[ 2886.597572] ODEBUG: Out of memory. ODEBUG disabled\n")
   322  				buf.Write(bytes.Repeat([]byte{'-'}, i))
   323  				buf.WriteByte('\n')
   324  			}
   325  			output := buf.Bytes()
   326  			for i := range output {
   327  				outc <- output[i : i+1]
   328  			}
   329  			errc <- nil
   330  		},
   331  	},
   332  	{
   333  		Name: "inject-executing",
   334  		Exit: ExitNormal,
   335  		BodyExecuting: func(outc chan []byte, errc chan error, inject chan<- bool) {
   336  			for i := 0; i < 6; i++ {
   337  				time.Sleep(time.Second)
   338  				inject <- true
   339  			}
   340  			errc <- nil
   341  		},
   342  	},
   343  }
   344  
   345  func TestMonitorExecution(t *testing.T) {
   346  	for _, test := range tests {
   347  		t.Run(test.Name, func(t *testing.T) {
   348  			t.Parallel()
   349  			testMonitorExecution(t, test)
   350  		})
   351  	}
   352  }
   353  
   354  func makeLinuxAMD64Futex(t *testing.T) (*Instance, *report.Reporter) {
   355  	cfg := &mgrconfig.Config{
   356  		Derived: mgrconfig.Derived{
   357  			TargetOS:     targets.Linux,
   358  			TargetArch:   targets.AMD64,
   359  			TargetVMArch: targets.AMD64,
   360  			Timeouts: targets.Timeouts{
   361  				Scale:    1,
   362  				Slowdown: 1,
   363  				NoOutput: 5 * time.Second,
   364  			},
   365  			SysTarget: targets.Get(targets.Linux, targets.AMD64),
   366  		},
   367  		Workdir: t.TempDir(),
   368  		Type:    "test",
   369  	}
   370  	pool, err := Create(cfg, false)
   371  	if err != nil {
   372  		t.Fatal(err)
   373  	}
   374  	t.Cleanup(func() { pool.Close() })
   375  	reporter, err := report.NewReporter(cfg)
   376  	if err != nil {
   377  		t.Fatal(err)
   378  	}
   379  	inst, err := pool.Create(t.Context(), 0)
   380  	if err != nil {
   381  		t.Fatal(err)
   382  	}
   383  	t.Cleanup(func() { inst.Close() })
   384  	return inst, reporter
   385  }
   386  
   387  func testMonitorExecution(t *testing.T, test *Test) {
   388  	inst, reporter := makeLinuxAMD64Futex(t)
   389  	testInst := inst.impl.(*testInstance)
   390  	testInst.diagnoseBug = test.DiagnoseBug
   391  	testInst.diagnoseNoWait = test.DiagnoseNoWait
   392  	done := make(chan bool)
   393  	finishCalled := 0
   394  	var inject chan bool
   395  	injectExecuting := func(opts *RunOptions) {}
   396  	if test.BodyExecuting != nil {
   397  		inject = make(chan bool, 10)
   398  		injectExecuting = WithInjectExecuting(inject)
   399  	} else {
   400  		test.BodyExecuting = func(outc chan []byte, errc chan error, inject chan<- bool) {
   401  			test.Body(outc, errc)
   402  		}
   403  	}
   404  	go func() {
   405  		test.BodyExecuting(testInst.outc, testInst.errc, inject)
   406  		done <- true
   407  	}()
   408  	_, reps, err := inst.Run(context.Background(), reporter, "",
   409  		withTestRunOptionsDefaults(),
   410  		WithExitCondition(test.Exit),
   411  		WithEarlyFinishCb(func() { finishCalled++ }),
   412  		injectExecuting,
   413  	)
   414  	if err != nil {
   415  		t.Fatal(err)
   416  	}
   417  	<-done
   418  	if finishCalled != 1 {
   419  		t.Fatalf("finish callback is called %v times", finishCalled)
   420  	}
   421  	if test.Report != nil && len(reps) == 0 {
   422  		t.Fatalf("got no report")
   423  	}
   424  	if test.Report == nil && len(reps) != 0 {
   425  		t.Fatalf("got unexpected report: %v", reps[0].Title)
   426  	}
   427  	if test.Report == nil {
   428  		return
   429  	}
   430  	rep := reps[0]
   431  	if test.Report.Title != rep.Title {
   432  		t.Fatalf("want title %q, got title %q", test.Report.Title, rep.Title)
   433  	}
   434  	if !bytes.Equal(test.Report.Report, rep.Report) {
   435  		t.Fatalf("want report:\n%s\n\ngot report:\n%s", test.Report.Report, rep.Report)
   436  	}
   437  	if test.Report.Output != nil && !bytes.Equal(test.Report.Output, rep.Output) {
   438  		t.Fatalf("want output:\n%s\n\ngot output:\n%s", test.Report.Output, rep.Output)
   439  	}
   440  	if test.Report.Type != rep.Type {
   441  		t.Fatalf("want type %q, got type %q", test.Report.Type, rep.Type)
   442  	}
   443  }
   444  
   445  func TestVMType(t *testing.T) {
   446  	testCases := []struct {
   447  		in   string
   448  		want string
   449  	}{
   450  		{targets.GVisor, targets.GVisor},
   451  		{"proxyapp:android", "proxyapp"},
   452  	}
   453  
   454  	for _, tc := range testCases {
   455  		if got := vmType(tc.in); got != tc.want {
   456  			t.Errorf("vmType(%q) = %q, want %q", tc.in, got, tc.want)
   457  		}
   458  	}
   459  }
   460  
   461  func TestExtractMultipleErrors(t *testing.T) {
   462  	inst, reporter := makeLinuxAMD64Futex(t)
   463  	mon := &monitor{
   464  		RunOptions: &RunOptions{},
   465  		inst:       inst,
   466  		reporter:   reporter,
   467  		output:     []byte(validKASANReport + strings.Repeat(someLine, 10) + validKASANReport),
   468  	}
   469  	reps := mon.extractErrors("unknown error")
   470  	assert.Len(t, reps, 2, "expected to see 2 reports, got %v", len(reps))
   471  	assert.Equal(t, reps[0].Title, reps[1].Title)
   472  	assert.False(t, reps[0].Corrupted)
   473  	assert.False(t, reps[1].Corrupted)
   474  }
   475  
   476  const someLine = "[   96.999999] some message \n"
   477  const validKASANReport = `
   478  [   96.262735] BUG: KASAN: double-free or invalid-free in selinux_tun_dev_free_security+0x15/0x20
   479  [   96.271481] 
   480  [   96.273098] CPU: 0 PID: 11514 Comm: syz-executor5 Not tainted 4.12.0-rc7+ #2
   481  [   96.280268] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
   482  [   96.289602] Call Trace:
   483  [   96.292180]  dump_stack+0x194/0x257
   484  [   96.295796]  ? arch_local_irq_restore+0x53/0x53
   485  [   96.300454]  ? load_image_and_restore+0x10f/0x10f
   486  [   96.305299]  ? selinux_tun_dev_free_security+0x15/0x20
   487  [   96.310565]  print_address_description+0x7f/0x260
   488  [   96.315393]  ? selinux_tun_dev_free_security+0x15/0x20
   489  [   96.320656]  ? selinux_tun_dev_free_security+0x15/0x20
   490  [   96.325919]  kasan_report_double_free+0x55/0x80
   491  [   96.330577]  kasan_slab_free+0xa0/0xc0
   492  [   96.334450]  kfree+0xd3/0x260
   493  [   96.337545]  selinux_tun_dev_free_security+0x15/0x20
   494  [   96.342636]  security_tun_dev_free_security+0x48/0x80
   495  [   96.347822]  __tun_chr_ioctl+0x2cc1/0x3d60
   496  [   96.352054]  ? tun_chr_close+0x60/0x60
   497  [   96.355925]  ? lock_downgrade+0x990/0x990
   498  [   96.360059]  ? lock_release+0xa40/0xa40
   499  [   96.364025]  ? __lock_is_held+0xb6/0x140
   500  [   96.368213]  ? check_same_owner+0x320/0x320
   501  [   96.372530]  ? tun_chr_compat_ioctl+0x30/0x30
   502  [   96.377005]  tun_chr_ioctl+0x2a/0x40
   503  [   96.380701]  ? tun_chr_ioctl+0x2a/0x40
   504  [   96.385099]  do_vfs_ioctl+0x1b1/0x15c0
   505  [   96.388981]  ? ioctl_preallocate+0x2d0/0x2d0
   506  [   96.393378]  ? selinux_capable+0x40/0x40
   507  [   96.397430]  ? SyS_futex+0x2b0/0x3a0
   508  [   96.401147]  ? security_file_ioctl+0x89/0xb0
   509  [   96.405547]  SyS_ioctl+0x8f/0xc0
   510  [   96.408912]  entry_SYSCALL_64_fastpath+0x1f/0xbe
   511  [   96.413651] RIP: 0033:0x4512c9
   512  [   96.416824] RSP: 002b:00007fc65827bc08 EFLAGS: 00000216 ORIG_RAX: 0000000000000010
   513  [   96.424603] RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 00000000004512c9
   514  [   96.431863] RDX: 000000002053c000 RSI: 00000000400454ca RDI: 0000000000000005
   515  [   96.439133] RBP: 0000000000000082 R08: 0000000000000000 R09: 0000000000000000
   516  [   96.446389] R10: 0000000000000000 R11: 0000000000000216 R12: 00000000004baa97
   517  [   96.453647] R13: 00000000ffffffff R14: 0000000020124ff3 R15: 0000000000000000
   518  [   96.460931] 
   519  [   96.462552] Allocated by task 11514:
   520  [   96.466258]  save_stack_trace+0x16/0x20
   521  [   96.470212]  save_stack+0x43/0xd0
   522  [   96.473649]  kasan_kmalloc+0xaa/0xd0
   523  [   96.477347]  kmem_cache_alloc_trace+0x101/0x6f0
   524  [   96.481995]  selinux_tun_dev_alloc_security+0x49/0x170
   525  [   96.487250]  security_tun_dev_alloc_security+0x6d/0xa0
   526  [   96.492508]  __tun_chr_ioctl+0x16bc/0x3d60
   527  [   96.496722]  tun_chr_ioctl+0x2a/0x40
   528  [   96.500417]  do_vfs_ioctl+0x1b1/0x15c0
   529  [   96.504282]  SyS_ioctl+0x8f/0xc0
   530  [   96.507630]  entry_SYSCALL_64_fastpath+0x1f/0xbe
   531  [   96.512367] 
   532  [   96.513973] Freed by task 11514:
   533  [   96.517323]  save_stack_trace+0x16/0x20
   534  [   96.521276]  save_stack+0x43/0xd0
   535  [   96.524709]  kasan_slab_free+0x6e/0xc0
   536  [   96.528577]  kfree+0xd3/0x260
   537  [   96.531666]  selinux_tun_dev_free_security+0x15/0x20
   538  [   96.536747]  security_tun_dev_free_security+0x48/0x80
   539  [   96.541918]  tun_free_netdev+0x13b/0x1b0
   540  [   96.545959]  register_netdevice+0x8d0/0xee0
   541  [   96.550260]  __tun_chr_ioctl+0x1bae/0x3d60
   542  [   96.554475]  tun_chr_ioctl+0x2a/0x40
   543  [   96.558169]  do_vfs_ioctl+0x1b1/0x15c0
   544  [   96.562035]  SyS_ioctl+0x8f/0xc0
   545  [   96.565385]  entry_SYSCALL_64_fastpath+0x1f/0xbe
   546  [   96.570116] 
   547  [   96.571724] The buggy address belongs to the object at ffff8801d5961a40
   548  [   96.571724]  which belongs to the cache kmalloc-32 of size 32
   549  [   96.584186] The buggy address is located 0 bytes inside of
   550  [   96.584186]  32-byte region [ffff8801d5961a40, ffff8801d5961a60)
   551  [   96.595775] The buggy address belongs to the page:
   552  [   96.600686] page:ffffea00066b8d38 count:1 mapcount:0 mapping:ffff8801d5961000 index:0xffff8801d5961fc1
   553  [   96.610118] flags: 0x200000000000100(slab)
   554  [   96.614335] raw: 0200000000000100 ffff8801d5961000 ffff8801d5961fc1 000000010000003f
   555  [   96.622292] raw: ffffea0006723300 ffffea00066738b8 ffff8801dbc00100
   556  [   96.628675] page dumped because: kasan: bad access detected
   557  [   96.634373] 
   558  [   96.635978] Memory state around the buggy address:
   559  [   96.640884]  ffff8801d5961900: 00 00 01 fc fc fc fc fc 00 00 00 fc fc fc fc fc
   560  [   96.648222]  ffff8801d5961980: 00 00 00 00 fc fc fc fc fb fb fb fb fc fc fc fc
   561  [   96.655567] >ffff8801d5961a00: 00 00 00 fc fc fc fc fc fb fb fb fb fc fc fc fc
   562  [   96.663255]                                            ^
   563  [   96.668685]  ffff8801d5961a80: fb fb fb fb fc fc fc fc 00 00 00 fc fc fc fc fc
   564  [   96.676022]  ffff8801d5961b00: 04 fc fc fc fc fc fc fc fb fb fb fb fc fc fc fc
   565  [   96.683357] ==================================================================
   566  [   96.690692] Disabling lock debugging due to kernel taint
   567  [   96.696117] Kernel panic - not syncing: panic_on_warn set ...
   568  [   96.696117] 
   569  [   96.703470] CPU: 0 PID: 11514 Comm: syz-executor5 Tainted: G    B           4.12.0-rc7+ #2
   570  [   96.711847] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
   571  [   96.721354] Call Trace:
   572  [   96.723926]  dump_stack+0x194/0x257
   573  [   96.727539]  ? arch_local_irq_restore+0x53/0x53
   574  [   96.732366]  ? kasan_end_report+0x32/0x50
   575  [   96.736497]  ? lock_downgrade+0x990/0x990
   576  [   96.740631]  panic+0x1e4/0x3fb
   577  [   96.743807]  ? percpu_up_read_preempt_enable.constprop.38+0xae/0xae
   578  [   96.750194]  ? add_taint+0x40/0x50
   579  [   96.753723]  ? selinux_tun_dev_free_security+0x15/0x20
   580  [   96.758976]  ? selinux_tun_dev_free_security+0x15/0x20
   581  [   96.764233]  kasan_end_report+0x50/0x50
   582  [   96.768192]  kasan_report_double_free+0x72/0x80
   583  [   96.772843]  kasan_slab_free+0xa0/0xc0
   584  [   96.776711]  kfree+0xd3/0x260
   585  [   96.779802]  selinux_tun_dev_free_security+0x15/0x20
   586  [   96.784886]  security_tun_dev_free_security+0x48/0x80
   587  [   96.790061]  __tun_chr_ioctl+0x2cc1/0x3d60
   588  [   96.794285]  ? tun_chr_close+0x60/0x60
   589  [   96.798152]  ? lock_downgrade+0x990/0x990
   590  [   96.802803]  ? lock_release+0xa40/0xa40
   591  [   96.806763]  ? __lock_is_held+0xb6/0x140
   592  [   96.810829]  ? check_same_owner+0x320/0x320
   593  [   96.815137]  ? tun_chr_compat_ioctl+0x30/0x30
   594  [   96.819611]  tun_chr_ioctl+0x2a/0x40
   595  [   96.823306]  ? tun_chr_ioctl+0x2a/0x40
   596  [   96.827181]  do_vfs_ioctl+0x1b1/0x15c0
   597  [   96.831057]  ? ioctl_preallocate+0x2d0/0x2d0
   598  [   96.835450]  ? selinux_capable+0x40/0x40
   599  [   96.839494]  ? SyS_futex+0x2b0/0x3a0
   600  [   96.843200]  ? security_file_ioctl+0x89/0xb0
   601  [   96.847590]  SyS_ioctl+0x8f/0xc0
   602  [   96.850941]  entry_SYSCALL_64_fastpath+0x1f/0xbe
   603  [   96.855676] RIP: 0033:0x4512c9
   604  [   96.859020] RSP: 002b:00007fc65827bc08 EFLAGS: 00000216 ORIG_RAX: 0000000000000010
   605  [   96.866708] RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 00000000004512c9
   606  [   96.873956] RDX: 000000002053c000 RSI: 00000000400454ca RDI: 0000000000000005
   607  [   96.881208] RBP: 0000000000000082 R08: 0000000000000000 R09: 0000000000000000
   608  [   96.888461] R10: 0000000000000000 R11: 0000000000000216 R12: 00000000004baa97
   609  [   96.895708] R13: 00000000ffffffff R14: 0000000020124ff3 R15: 0000000000000000
   610  [   96.903943] Dumping ftrace buffer:
   611  [   96.907460]    (ftrace buffer empty)
   612  [   96.911148] Kernel Offset: disabled
   613  `