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

Add Tool Trace2Syz #767

Merged
merged 22 commits into from Dec 6, 2018
Merged

Add Tool Trace2Syz #767

merged 22 commits into from Dec 6, 2018

Conversation

shankarapailoor
Copy link
Contributor

This PR is meant to review a new Syzkaller tool syz-trace2syz that converts outputs of strace to syzkaller programs.

@dvyukov
Copy link
Collaborator

dvyukov commented Oct 12, 2018

The buildbot has failed with:

go install ./...
# github.com/google/syzkaller/tools/syz-trace2syz/parser
tools/syz-trace2syz/parser/parser.go:42:9: undefined: newStraceLexer
tools/syz-trace2syz/parser/parser.go:43:9: undefined: StraceParse

We generally check-in all generated files to not require all users to install wide range of various tools. I think we need to do the same here.

Please extend make install_prerequisites to install goyacc and ragel.

And goyacc and ragel steps need to be moved to a separate generate_trace2syz target. See for example, generate_fidl target.

@shankarapailoor
Copy link
Contributor Author

shankarapailoor commented Oct 12, 2018

Ok Sounds good. Would it be nicer to put the generated files in their own package like parser/gen similar to how you do it for the targets?

Makefile Outdated
(cd tools/syz-trace2syz/parser; goyacc -o strace.go -p Strace strace.y)
GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-trace2syz github.com/google/syzkaller/tools/syz-trace2syz


Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove second new line.

Copy link
Collaborator

Choose a reason for hiding this comment

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

still holds

@@ -0,0 +1,36 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

This file is not needed, right?


// SpecialConsts contains values for flags found in strace. Some of these have different names in Syzkaller
// and others are not yet added to Syzkaller.
SpecialConsts = map[string]uint64{
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we need either eliminate this entirely, or at least try to minimize as much as possible and document exact reasons some of these consts are still needed.

I've looked at some consts:

  1. PROT_NONE and FALLOC_FL_ZERO_RANGE are present in syzkaller consts and have the same values.
  2. USR1/BUS/etc: if strace gives them different names it would be better to have a mapping from strace names to actual constant names as used in source code (and in syzkaller), e.g.
// strace invents own const names, map them to real const names.
constMap = map[string]string{
    "USR1": "SIGUSR1",
   ...
}

and then we could first apply this mapping and then lookup then in syzkaller consts. This will also help with the following point.
3. Lots of ioctl consts, e.g. FS_IOC_GETFLAGS have different values depending on arch. I guess your consts relate to amd64, but we don't want to limit this to amd64. Using syzkaller machinery would help with this.
4. Re missing consts, we should add them to syzkaller descriptions. E.g. you can do:

_ = FUTEX_WAIT_PRIVATE, FUTEX_WAKE_PRIVATE, ...

and them make extract should add these consts to .const files.


import (
"bufio"
"github.com/google/syzkaller/pkg/log"
Copy link
Collaborator

Choose a reason for hiding this comment

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

The common convention in Go and in syzkaller is to have:

import (
  ... standard packages ...
  [empty line]
  ... custom packages ...
)

Please do this here and in other files.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good. I don't need to add spaces between packages in trace2syz and other syzkaller packages correct?

`<... rt_sigtimedwait resumed> ) = 10 (SIGUSR1)` + "\n" +
`fstat() = 0`,
`open(0, SNDCTL_TMR_START or TCSETS,` +
`{c_cc[VMIN]=1, c_cc[VTIME]=0} <unfinished ...>` + "\n" +
Copy link
Collaborator

Choose a reason for hiding this comment

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

These:

` + "\n" +

look a bit clumsy. Raw string literals support new lines, so I would something like this:

		`
open(0, SNDCTL_TMR_START or TCSETS, {c_cc[VMIN]=1, c_cc[VTIME]=0} <unfinished ...>
<... open resumed> , FLAG|FLAG) = -1 FLAG (sdfjfjfjf)
fstat() = 0
`,

This allows to read and write the input as is, without additional escaping and manually added new lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wow i overthought that. Will fix!

}

func TestParseLoopPid(t *testing.T) {
/*
Copy link
Collaborator

Choose a reason for hiding this comment

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

No C++-style comments please:

// Parses two basic calls. Make sure the trace tree just has one entry with two calls

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah missed one. Why do you prefer not to have C++ style comments? Just curious :)

@@ -0,0 +1,150 @@
package proggen
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add the standard syzkaller copyright for all files.

return ctx
}

func testMatchingCallSequence(calls []*prog.Call, seq []string) error {
Copy link
Collaborator

Choose a reason for hiding this comment

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

prog.P has String method which returns concatenation of all calls.
So you can encode the expected result as "mmap-open-connect" and then just compare this with p.String().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That has simplified things. Thanks!

package proggen

import (
//"fmt"
Copy link
Collaborator

Choose a reason for hiding this comment

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

remove

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack

@dvyukov
Copy link
Collaborator

dvyukov commented Oct 12, 2018

Ok Sounds good. Would it be nicer to put the generated files in their own package like ```parser/gen`` similar to how you do it for the targets?

FWIW the only reason to do that is gomeralinter. Even parsing all generated files in sys/ is very slow and takes tons of memory, so adding generated files to exclude section did not work. Instead we put them into skip section which makes gomeralinter skip whole packages.

I don't see strong reasons for your files either way. If it's easy to move them to a separate package, I guess we could do that.

Makefile Outdated
@@ -305,6 +313,8 @@ install_prerequisites:
sudo apt-get install -y -q g++-aarch64-linux-gnu || true
sudo apt-get install -y -q g++-powerpc64le-linux-gnu || true
sudo apt-get install -y -q g++-arm-linux-gnueabihf || true
sudo apt-get install ragel
Copy link
Collaborator

Choose a reason for hiding this comment

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

add -y -q so that it does not ask questions

Makefile Outdated
(cd tools/syz-trace2syz/parser; goyacc -o strace.go -p Strace strace.y)
GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-trace2syz github.com/google/syzkaller/tools/syz-trace2syz


Copy link
Collaborator

Choose a reason for hiding this comment

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

still holds

SpecialConsts = map[string]uint64{
"SIG_0": 0,
"BUS": 10,
"USR1": 30,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I see that in *.const files we have SIGBUS=7 and SIGUSR1=10 and here you have BUS=10 and USR1=30. Why? Where these numbers come from?
If it's just a mistake, then it would be better to use Consts map more, i.e. map BUS to SIGBUS and USR1 to SIGUSR1, etc. And check out if we can use it for other consts too. This will save us from incorrect values, typos, differences between archs, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes this is a mistake. I will move BUS, USR1, IO, ALRM to Consts map. Additional question: the R_OK, W_OK flags are just for the access system call which is not in supported by Syzkaller. Is there a reason you don't support access or should I add the its description along with these flags?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I suspect we don't have it because it's effectively the same as faccessat that we have:

SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
{
	return do_faccessat(dfd, filename, mode);
}

SYSCALL_DEFINE2(access, const char __user *, filename, int, mode)
{
	return do_faccessat(AT_FDCWD, filename, mode);
}

So there is probably not much value in adding it separately. And there is actually some negative effect of adding it: arm64 kernels generally have only *at versions of syscalls and make libc emulate the non-*at versions via *at versions. So if syzkaller finds a crash with access call on amd64, it will not be possible to reuse the program on arm64.

"X_OK": 1,
"F_OK": 0,
"SCHED_OTHER": 0,
"FS_IOC_GETFLAGS": 26113,
Copy link
Collaborator

Choose a reason for hiding this comment

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

In the const files we have:

sys/linux/fs_ioctl_386.const:FS_IOC_GETFLAGS = 2147771905
sys/linux/fs_ioctl_amd64.const:FS_IOC_GETFLAGS = 2148034049
sys/linux/fs_ioctl_arm64.const:FS_IOC_GETFLAGS = 2148034049
sys/linux/fs_ioctl_arm.const:FS_IOC_GETFLAGS = 2147771905
sys/linux/fs_ioctl_ppc64le.const:FS_IOC_GETFLAGS = 1074292225

Where did 26113 come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a mistake :).

Copy link
Collaborator

Choose a reason for hiding this comment

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

So relying on automatic const extraction is already useful :)

"FS_IOC_GETFLAGS": 26113,
"FS_IOC_SETFLAGS": 26112,
"PHN_NOT_OH": 28676,
"SNDCTL_TMR_START": 21506,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please add these SNDCTL_TMR* consts to sys/linux/sndtimer.txt
Bonus points for adding real descriptions for this SNDCTL_TMR thing.

// ShouldSkip lists system calls that we should skip when parsing
// Some of these are unsupported or not worth executing
ShouldSkip = map[string]bool{
"brk": true,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would like to see exact reasons we ignore these calls, because in future we may want to enable more and it would be useful to know if there is some fundamental reason why it's ignored or if support is not implemented yet.
No need to comment each syscall independently, but at least do some groups of syscalls, e.g.:

// These don't give any interesting coverage:
getcpu
getcwd
// These something else...:
...
...

Also I see some syscalls here that are not even present in main descriptions (notably, "reboot" and ""). I think the first step should be to check target.SyscallMap and if it's not present there, then skip it. No need to duplicate such calls here (we never want to do reboot).

But I would expect that things like mprotect/mremap/futex we want to support in future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I agree. I'm thinking we could have a config file similar to mgr.cfg where you can specify "Disable Calls" or "Enable Calls". Users may have a set of traces and want to only generate programs that contain "open, ioctl, write" or only exclude a few like "execve, clone, etc".

Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's get the basic version working first ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure!

}
ctx.CurrentSyzCall = call

length := (parseLength(syscall.Args[1], ctx)/ctx.Target.PageSize + 1) * ctx.Target.PageSize //RoundUp PageSize
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks wrong. If the original value is multiple of PageSize, then the result will be 1 page larger.
I think we want: (x + PageSize - 1) / PageSize * PageSize

@dvyukov
Copy link
Collaborator

dvyukov commented Oct 15, 2018

I've tried to use it on a simple program and have 2 comments:

  1. Latest versions of strace already define -k flag, which means backtraces. It produces output like the one below which can't be parsed by syz-trace2syz. You need to use some other flag for kcov. I don't know if strace flag parser allows long flags, if yes, then -kcov would be more resilient for such changes in strace.
84737 access("\x2f\x65\x74\x63\x2f\x6c\x64\x2e\x73\x6f\x2e\x6e\x6f\x68\x77\x63\x61\x70", F_OK) = -1 
ENOENT (No such file or directory)
 > /lib/x86_64-linux-gnu/ld-2.24.so(__GI_access+0x7) [0x195a7]
 > /lib/x86_64-linux-gnu/ld-2.24.so(_dl_load_cache_lookup+0x66) [0x168e6]
  1. I've took a simple getpid() programs, converted it to C with:
syz-prog2c -prog /tmp/prog -threaded -collide -sandbox=namespace -segv -tmpdir -tun > /tmp/prog.c

Then:

strace -o tracefile -s 65500 -v -xx -f ./a.out

And tried to parse and it failed:

$ syz-trace2syz -file tracefile
2018/10/15 12:09:42 Parsing 1 traces
error: syntax error
2018/10/15 12:09:42 Error parsing line: 84069 recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=52, type=NLMSG_ERROR, flags=0, seq=0, pid=4}, {error=-ENODEV, msg={{len=32, type=0x10 /* NLMSG_??? */, flags=NLM_F_REQUEST|NLM_F_ACK, seq=0, pid=0}, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}}}, iov_len=16384}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 52

@shankarapailoor
Copy link
Contributor Author

I see the issue with that trace. It seems I didn't handle the unary minus operator during the parsing so -ENODEV breaks it. Fixed locally. More generally, do you think it is better to fail with Fatalf when we cannot parse a line or return an error, log it with verbosity 0, and then continue. With a verbosity of 0, users will see the error and report it and we can fix it, but they can still convert most of their trace.

@dvyukov
Copy link
Collaborator

dvyukov commented Oct 15, 2018

I think we should try to proceed with fatal errors as much as possible, and gave up to ignoring errors only if it turns out to be absolutely necessary.
If the thing completes successfully, 99% of users will report nothing and will not allow us to fix anything, they will just ignore the confusing output. Unfortunately that's how things work in real life.
In this case, error=-ENODEV is just a normal strace output that we need to handle, nothing that would suggest giving up on strict errors.

Makefile Outdated
@@ -176,6 +179,10 @@ ifeq ($(TARGETOS),fuchsia)
else
endif

generate_trace2syz:
(cd tools/syz-trace2syz/parser; ragel -Z -G2 -o lex.go straceLex.rl)
(cd tools/syz-trace2syz/parser; goyacc -o strace.go -p Strace strace.y)
Copy link
Collaborator

Choose a reason for hiding this comment

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

add -v="" flag, then it won't generate y.output and then you can revert .gitignore change

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack

prog/target.go Outdated
@@ -108,7 +108,7 @@ func (target *Target) lazyInit() {
target.SanitizeCall = func(c *Call) {}
target.initTarget()
target.initArch(target)
target.ConstMap = nil // currently used only by initArch
target.ConstMap = nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

add the comment back

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack

bpf_reg = BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5, BPF_REG_6, BPF_REG_7, BPF_REG_8, BPF_REG_9, BPF_REG_10
bpf_reg = BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5, BPF_REG_6, BPF_REG_7, BPF_REG_8, BPF_REG_9, BPF_REG_10, __MAX_BPF_REG

define MAX_BPF_REG __MAX_BPF_REG
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is MAX_BPF_REG used anywhere? I can't find where.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Or is MAX_BPF_REG what strace prints? If yes, then move this to your Const mapping. That's exactly what it is for -- mapping strace names to kernel names.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is in the kernel. It is defined to be equal to __MAX_BPF_REG. See here. I will remove the define and just add it to the list

@@ -12,6 +12,6 @@ IOCB_FLAG_RESFD = 1
__NR_io_cancel = 247
__NR_io_destroy = 244
__NR_io_getevents = 245
# __NR_io_pgetevents is not set
__NR_io_pgetevents = 399
Copy link
Collaborator

Choose a reason for hiding this comment

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

You need to rebase, this is already added here:
6ce1793

@@ -38,6 +38,8 @@
],
"exclude": [
"(sys/(akaros|freebsd|fuchsia|linux|netbsd|test|windows)/init.*|sys/targets/common.go).* don't use ALL_CAPS in Go names",
"(lex.go)",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use full path because these names are quite generic, they can appear in other dirs too:
tools/syz-trace2syz/parser/(lex|strace).go

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack

// ShouldSkip lists system calls that we should skip when parsing
// Some of these are unsupported or not worth executing
ShouldSkip = map[string]bool{
// execve terminates program execution. Although there is Syzkaller support
Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. We never spell syzkaller with a capital letter.
  2. I've noticed here and in some other places that you refer to syzkaller in third person form. It made sense while your code was a separate project, but this is a part of syzkaller now. So you should refer to it in first person form. It's not there now, it's here. This code is also part of syzkaller now. So referring to "some syzkaller" is not useful anymore. You could say something along the following lines "Although syscall descriptions contain execve ...".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack. Hopefully I got all of them...probably not.

i++
if arg.Address >= memAllocMaxMem {
return 0, fmt.Errorf("Unable to allocate space to store arg: %#v"+
"in Call: %v. Required memory is larger than what is allowed by Syzkaller."+
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here. This is syzkaller now, not something else.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack

arg.Res = nil
if arg.Address >= memAllocMaxMem || arg.Address+arg.VmaSize > memAllocMaxMem {
return fmt.Errorf("Unable to allocate space for vma Call: %#v "+
"Required memory is larger than what is allowed by Syzkaller."+
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack

fdArg,
prog.MakeConstArg(mmap.Args[5], 0),
}
//All mmaps have fixed mappings in syzkaller
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here. Referring to syzkaller is not useful anymore. "in prog package" for example refers to at least something.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack. Stale comment anyways since the calls get sanitized.

}

func parseShmat(shmat *prog.Syscall, syscall *parser.Syscall, ctx *Context) *prog.Call {
/*
Copy link
Collaborator

Choose a reason for hiding this comment

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

No C++ comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I swear they have a life of their own

Copy link
Collaborator

Choose a reason for hiding this comment

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

:)

@dvyukov
Copy link
Collaborator

dvyukov commented Oct 17, 2018

Is this ready for another look? Or somethings are still unresolved? At least github still shows "This branch cannot be rebased due to conflicts".

@shankarapailoor
Copy link
Contributor Author

I think this is ready for another look; I merged yesterday. I also see this as having no conflicts with the base branch.

@xairy
Copy link
Collaborator

xairy commented Oct 17, 2018

Please do not merge syzkaller master branch into yours, but rebase your commits onto syzkaller master instead.

@shankarapailoor
Copy link
Contributor Author

Super sorry. I merged out of habit. Just so I'm clear, if I make some updates but there are changes in master I need to incorporate I should just do git rebase and then git push -f my-origin master (my understanding following instructions here)

@xairy
Copy link
Collaborator

xairy commented Oct 18, 2018

Correct, rebase and then force push. Thanks!

@shankarapailoor
Copy link
Contributor Author

Hi @dvyukov and @xairy. I rebased and force pushed last night so I think everything should be ready for review. Whenever you have time take a look. Thanks!

@shankarapailoor
Copy link
Contributor Author

Hi @dvyukov! This is ready for review. Thanks!

@@ -692,5 +692,5 @@ erofs_options [

codepage_nums = "1250", "1251", "1255", "437", "737", "775", "850", "852", "855", "857", "860", "861", "862", "863", "864", "865", "866", "869", "874", "932", "936", "949", "950"
codepages_names = "macceltic", "maccenteuro", "maccroatian", "maccyrillic", "macgaelic", "macgreek", "maciceland", "macinuit", "macroman", "macromanian", "macturkish", "ascii", "default", "cp1250", "cp1251", "cp1255", "cp437", "cp737", "cp775", "cp850", "cp852", "cp855", "cp857", "cp860", "cp861", "cp862", "cp863", "cp864", "cp865", "cp866", "cp869", "cp874", "cp932", "cp936", "cp949", "cp950", "euc-jp", "iso8859-13", "iso8859-14", "iso8859-15", "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5", "iso8859-6", "iso8859-7", "iso8859-9", "koi8-r", "koi8-ru", "koi8-u", "utf8", "none"
mount_flags = MS_BIND, MS_DIRSYNC, MS_MANDLOCK, MS_MOVE, MS_NOATIME, MS_NODEV, MS_NODIRATIME, MS_NOEXEC, MS_NOSUID, MS_RDONLY, MS_RELATIME, MS_REMOUNT, MS_SILENT, MS_STRICTATIME, MS_SYNCHRONOUS, MS_REC, MS_POSIXACL, MS_UNBINDABLE, MS_PRIVATE, MS_SLAVE, MS_SHARED, MS_I_VERSION, MS_LAZYTIME
mount_flags = MS_BIND, MS_DIRSYNC, MS_MANDLOCK, MS_MOVE, MS_NOATIME, MS_NODEV, MS_NODIRATIME, MS_NOEXEC, MS_NOSUID, MS_RDONLY, MS_RELATIME, MS_REMOUNT, MS_SILENT, MS_STRICTATIME, MS_SYNCHRONOUS, MS_REC, MS_POSIXACL, MS_UNBINDABLE, MS_PRIVATE, MS_SLAVE, MS_SHARED, MS_I_VERSION, MS_LAZYTIME, MS_KERNMOUNT, MS_ACTIVE
Copy link
Collaborator

Choose a reason for hiding this comment

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

MS_KERNMOUNT, MS_ACTIVE does not seem to be used anywhere in kernel code. Do we really need them? And MS_KERNMOUNT looks like something that would be used as an internal flag, rather than something that is supposed to be passed from userspace.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it currently appears to be ignored. However, strace adds this flag in its output. E.g.

mount("...", "...", 0x7ffc3231a330, MS_NOEXEC|MS_SYNCHRONOUS|MS_NODIRATIME|MS_BIND|MS_MOVE|MS_SILENT|MS_UNBINDABLE|MS_PRIVATE|MS_SHARED|MS_KERNMOUNT|MS_I_VERSION|MS_ACTIVE|0xa6508ea300000300, 0x7ffc3231a390) = -1 EINVAL (Invalid argument)

What is the best way to handle this? This example is strace output from a Syzkaller program.

Copy link
Collaborator

Choose a reason for hiding this comment

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

How do you handle unknown consts? If you ignore them, then we can simply ignore MS_KERNMOUNT.
MS_KERNMOUNT is not supposed to be passed from user-space, so perhaps it's a bug in strace? Does it confuse it with some other const?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently if I cannot find the constant in the constant map I call log.Fatalf since it is possible that this is a constant that should be added. We could instead not panic and log a warning with low verbosity

Also, doesn't Syzkaller sometimes throw random values into the flag field like -1 so strace would naturally expand it to all possible flags?

@@ -0,0 +1,3 @@
include <uapi/linux/btrfs.h>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copyright header please.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack

@@ -14,6 +14,8 @@ include <uapi/linux/netfilter_ipv6/ip6t_REJECT.h>
include <uapi/linux/netfilter_ipv6/ip6t_NPT.h>
include <uapi/linux/netfilter_ipv6/ip6t_HL.h>

_ = IP6T_BASE_CTL, IP6T_SO_SET_REPLACE, IP6T_SO_SET_ADD_COUNTERS, IP6T_SO_SET_MAX, IP6T_SO_GET_INFO, IP6T_SO_GET_ENTRIES, IP6T_SO_GET_REVISION_MATCH, IP6T_SO_GET_REVISION_TARGET, IP6T_SO_GET_MAX
Copy link
Collaborator

Choose a reason for hiding this comment

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

IP6T_BASE_CTL, IP6T_SO_SET_MAX, IP6T_SO_GET_MAX are not ioctl commands afair
we already have IP6T_SO_SET_REPLACE, IP6T_SO_SET_ADD_COUNTERS, IP6T_SO_GET_INFO, IP6T_SO_GET_ENTRIES and the rest
do we need this at all?

@@ -43,8 +43,8 @@ socket_domain = AF_UNIX, AF_INET, AF_INET6, AF_IPX, AF_NETLINK, AF_X25, AF_AX25,
socket_type = SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_DCCP, SOCK_PACKET, SOCK_NONBLOCK, SOCK_CLOEXEC
accept_flags = SOCK_NONBLOCK, SOCK_CLOEXEC
shutdown_flags = SHUT_RD, SHUT_WR
send_flags = MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PROBE, MSG_BATCH, MSG_FASTOPEN, MSG_ZEROCOPY
recv_flags = MSG_CMSG_CLOEXEC, MSG_DONTWAIT, MSG_ERRQUEUE, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, MSG_WAITFORONE
send_flags = MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PROBE, MSG_BATCH, MSG_FASTOPEN, MSG_ZEROCOPY, MSG_CTRUNC, MSG_FIN, MSG_EOF, MSG_SYN, MSG_RST
Copy link
Collaborator

Choose a reason for hiding this comment

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

MSG_CTRUNC is output flag of recvmsg
the other flags seems to be unused, or output too
why do we need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I should have looked more carefully at the actual usage. I added it here because strace had the following output:

sendmsg(-1, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=20, type=0 /* NLMSG_??? */, flags=0, seq=0, pid=0}, "\x00\x00\x00\x00"}, iov_len=20}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_PEEK|MSG_CTRUNC|MSG_DONTWAIT|MSG_EOR|MSG_WAITALL|MSG_FIN|MSG_SYN|MSG_CONFIRM|MSG_ERRQUEUE|MSG_NOSIGNAL|MSG_WAITFORONE|MSG_BATCH|MSG_CMSG_COMPAT|0x1ba00000) = -1 EINVAL

send_flags = MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PROBE, MSG_BATCH, MSG_FASTOPEN, MSG_ZEROCOPY
recv_flags = MSG_CMSG_CLOEXEC, MSG_DONTWAIT, MSG_ERRQUEUE, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, MSG_WAITFORONE
send_flags = MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PROBE, MSG_BATCH, MSG_FASTOPEN, MSG_ZEROCOPY, MSG_CTRUNC, MSG_FIN, MSG_EOF, MSG_SYN, MSG_RST
recv_flags = MSG_CMSG_CLOEXEC, MSG_DONTWAIT, MSG_ERRQUEUE, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, MSG_WAITFORONE, MSG_SENDPAGE_NOTLAST, MSG_NO_SHARED_FRAGS, MSG_CMSG_COMPAT
Copy link
Collaborator

Choose a reason for hiding this comment

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

MSG_SENDPAGE_NOTLAST is an internal flag, not a part of api
why do we need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same reason as MS_KERNMOUNT.

@@ -199,7 +199,7 @@ ioctl$sock_SIOCINQ(fd sock, cmd const[SIOCINQ], arg ptr[out, int32])

ioctl$sock_SIOCGIFCONF(fd sock, cmd const[SIOCGIFNAME], arg ptr[inout, ifconf])

ifreq_ioctls = SIOCGIFNAME, SIOCSIFLINK, SIOCGIFFLAGS, SIOCSIFFLAGS, SIOCGIFADDR, SIOCSIFADDR, SIOCGIFDSTADDR, SIOCSIFDSTADDR, SIOCGIFBRDADDR, SIOCSIFBRDADDR, SIOCGIFNETMASK, SIOCSIFNETMASK, SIOCGIFMETRIC, SIOCSIFMETRIC, SIOCGIFMEM, SIOCSIFMEM, SIOCGIFMTU, SIOCSIFMTU, SIOCSIFNAME, SIOCSIFHWADDR, SIOCGIFENCAP, SIOCSIFENCAP, SIOCGIFHWADDR, SIOCGIFSLAVE, SIOCSIFSLAVE, SIOCADDMULTI, SIOCDELMULTI, SIOCGIFINDEX, SIOCSIFPFLAGS, SIOCGIFPFLAGS, SIOCDIFADDR, SIOCSIFHWBROADCAST, SIOCGIFCOUNT, SIOCGIFTXQLEN, SIOCSIFTXQLEN, SIOCETHTOOL, SIOCGMIIPHY, SIOCGMIIREG, SIOCSMIIREG, SIOCWANDEV, SIOCGIFMAP, SIOCSIFMAP, SIOCBONDENSLAVE, SIOCBONDRELEASE, SIOCBONDSETHWADDR, SIOCBONDSLAVEINFOQUERY, SIOCBONDINFOQUERY, SIOCBONDCHANGEACTIVE, SIOCBRADDIF, SIOCBRDELIF, SIOCSHWTSTAMP, SIOCGHWTSTAMP
ifreq_ioctls = SIOCGIFNAME, SIOCSIFLINK, SIOCGIFCONF, SIOCGIFFLAGS, SIOCSIFFLAGS, SIOCGIFADDR, SIOCSIFADDR, SIOCGIFDSTADDR, SIOCSIFDSTADDR, SIOCGIFBRDADDR, SIOCSIFBRDADDR, SIOCGIFNETMASK, SIOCSIFNETMASK, SIOCGIFMETRIC, SIOCSIFMETRIC, SIOCGIFMEM, SIOCSIFMEM, SIOCGIFMTU, SIOCSIFMTU, SIOCSIFNAME, SIOCSIFHWADDR, SIOCGIFENCAP, SIOCSIFENCAP, SIOCGIFHWADDR, SIOCGIFSLAVE, SIOCSIFSLAVE, SIOCADDMULTI, SIOCDELMULTI, SIOCGIFINDEX, SIOCSIFPFLAGS, SIOCGIFPFLAGS, SIOCDIFADDR, SIOCSIFHWBROADCAST, SIOCGIFCOUNT, SIOCGIFTXQLEN, SIOCSIFTXQLEN, SIOCETHTOOL, SIOCGMIIPHY, SIOCGMIIREG, SIOCSMIIREG, SIOCWANDEV, SIOCGIFMAP, SIOCSIFMAP, SIOCBONDENSLAVE, SIOCBONDRELEASE, SIOCBONDSETHWADDR, SIOCBONDSLAVEINFOQUERY, SIOCBONDINFOQUERY, SIOCBONDCHANGEACTIVE, SIOCBRADDIF, SIOCBRDELIF, SIOCSHWTSTAMP, SIOCGHWTSTAMP
Copy link
Collaborator

Choose a reason for hiding this comment

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

We have a description for SIOCGIFCONF, but there was a typo. I fixed the typo:
fe65cc8
So now this change is unnecessary.

@@ -849,8 +851,9 @@ kcmp_epoll_slot {
toff int32
}

open_flags = O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, FASYNC, O_CLOEXEC, O_CREAT, O_DIRECT, O_DIRECTORY, O_EXCL, O_LARGEFILE, O_NOATIME, O_NOCTTY, O_NOFOLLOW, O_NONBLOCK, O_PATH, O_SYNC, O_TRUNC, __O_TMPFILE
open_flags = O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, FASYNC, O_CLOEXEC, O_CREAT, O_DIRECT, O_DIRECTORY, O_EXCL, O_LARGEFILE, O_NOATIME, O_NOCTTY, O_NOFOLLOW, O_NONBLOCK, O_PATH, O_SYNC, O_TRUNC, __O_TMPFILE, O_ACCMODE, O_TMPFILE
Copy link
Collaborator

Choose a reason for hiding this comment

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

O_ACCMODE is an or of O_RDONLY, O_WRONLY, O_RDWR
Since we have these consts, no need to add O_ACCMODE.
Does strace produce O_ACCMODE? It would be pretty weird.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes it does for both.

7042  open("\x2e", O_ACCMODE|O_NOCTTY|O_TMPFILE, 000) = 4

_ = SIG_0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGIOT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGSTKFLT, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPOLL, SIGPWR, SIGSYS, SIGUNUSED, SIGRTMIN, SIGRTMAX
_ = RLIM64_INFINITY
_ = PHN_NOT_OH
_ = _IOC_NRBITS, _IOC_TYPEBITS, _IOC_SIZEBITS, _IOC_DIRBITS, _IOC_NRMASK, _IOC_TYPEMASK, _IOC_SIZEMASK, _IOC_DIRMASK, _IOC_NRSHIFT, _IOC_TYPESHIFT, _IOC_SIZESHIFT, _IOC_DIRSHIFT, _IOC_NONE, _IOC_READ, _IOC_WRITE
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does strace produce all these consts? In what context?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No it doesn't add all these constants but sometimes it will expand the ioctl command into _IOC(..,...,...). Eg.

ioctl(3, _IOC(_IOC_WRITE, 0x66, 0x8, 0x28), 0x20000040) = -1 EPERM (Operation not permitted)

I try and evaluate those and so I added the shifts. I was going to use CGO to evaluate but I read that you should avoid that if possible.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Then this is fine.
Just make sure that you check and fail if the consts are missing so that somebody does not remove them tomorrow because they don't understand why they are here.