Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys/openbsd: avoid using BIOCSETIF in causes "tun: read failed" #5016

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

blackgnezdo
Copy link
Collaborator

With luck this should prevent killing the executors with https://syzkaller.appspot.com/bug?extid=682dad6055938e287d19

if request.Val == arch.BIOCSETIF {
// Ideally this should also check Args[2] against "tap" as
// we only want to prevent the following from happening:
// ioctl$BIOCSETIF(-1, 0x8020426c, &(0x...)={'tap', 0x0})
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dvyukov could you recommend the incantation to tighten this check?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you interested in how exactly you could check for the tap string in the third argument or something more general, e.g. if there are other ways to restrict it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just want this ioctl to not happen to tap interfaces because we rely on them working for packet injection.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK there's currently to code that does something similar enough to this, but we could try to construct it from pieces.

  1. Cast c.Args[2] to *prog.PointerArg. Let it be ptrArg.
  2. Cast ptrArg.Res to *prog.GroupArg. Let it be groupArg.
  3. Cast groupArg.Inner[0] to *prog.DataArg. Let it be dataArg.
  4. Verify dataArg.Data() and patch it, if necessary. Like here:

syzkaller/sys/linux/init.go

Lines 241 to 253 in 32fcf98

dataArg, ok := unionArg.Option.(*prog.DataArg)
if !ok {
return
}
if dataArg.Dir() == prog.DirOut {
return
}
// Clear the first 16 bytes to prevent overcoming the limitation by squashing the struct.
data := append([]byte{}, dataArg.Data()...)
for i := 0; i < 16 && i < len(data); i++ {
data[i] = 0
}
dataArg.SetData(data)

One this to watch out for are ANY types -- in that case, syzkaller has squahed the whole struct into one binary blob. We cannot really build a good tight sanity check in that case, so I think we can check for ANY and boldly patch it like you've already done it in this PR.

Here's an example of a check for ANY. You can do it for c.Args[2].

if g.Target().ArgContainsAny(arg) {
return
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your guidance.

I implemented 1-4 but I'm not sure where to get a *prog.Gen to call .Target on.

Also not sure if there's an easy way to test this without pushing it to prod :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also not sure if there's an easy way to test this without pushing it to prod :)

We do have quite a lot of tests for call sanitization in Linux: https://github.com/google/syzkaller/blob/master/sys/linux/init_test.go

I'm not sure where to get a *prog.Gen to call .Target on.

At the very least we could remember it in the struct arch {} -- the prog.Target pointer is passed to InitTarget.

Copy link

codecov bot commented Jul 11, 2024

Codecov Report

Attention: Patch coverage is 14.28571% with 6 lines in your changes missing coverage. Please review.

Project coverage is 60.3%. Comparing base (c699c2e) to head (0f0fa60).

Additional details and impacted files
Files Coverage Δ
sys/openbsd/init.go 83.4% <14.3%> (-2.6%) ⬇️

... and 2 files with indirect coverage changes

@blackgnezdo
Copy link
Collaborator Author

I stared at https://syzkaller.appspot.com/bug?extid=682dad6055938e287d19 a bit more and came to the conclusion that I may not even be chasing the right problem. The last syz repro was from 2024/02/27.

If it is the right problem, then this PR effectively turns off this directive:

ioctl$BIOCSETIF(fd fd_bpf, cmd const[BIOCSETIF], arg ptr[in, ifreq_name])

If I wanted to do this I might as well remove this line completely, right?

@a-nogikh
Copy link
Collaborator

Yes, that should also work fine if syzkaller is unlikely to guess the BIOCSETIF const. I don't remember if we have the comparison argument substitution on OpenBSD - if yes, then it won't be too long until that happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants