Reason for mutliple syscall in Linux - linux

I was wondering, what is the reason for having _syscall0 to _syscall6 in Linux to handle different number of parameters. Are there any security/performance issues with having just _syscall6 alone and letting calling code pass in null values for unused parameters?

It is needed to decrease number of needed register copy and improve performance.
Each parameter needs to be moved form user's ABI into parameter-passing convention inside the kernel.
Also, some of such syscalls behaves differently with address parameters. But such conversion is needed on little number of archs.

Related

How do different commands get executed in CPU x86-64 registers?

Years ago a teacher once said to class that 'everything that gets parsed through the CPU can also be exploited'.
Back then I didn't know too much about the topic, but now the statement is nagging on me and I
lack the correct vocabulary to find an answer to this question in the internet myself, so I kindly ask you for help.
We had the lesson about 'cat', 'grep' and 'less' and she said that in the worst case even those commands can cause harm if we parse the wrong content through it.
I don't really understand how she meant that. I do know how CPU registers work, we also had to write an educational buffer overflow so I have seen assembly code in the registers aswell.
I still don't get the following:
How do commands get executed in the CPU at all? e.g. I use 'cat' so somehwere there will be a call of the command. But how does the data I enter get parsed to the CPU? If I 'cat' a .txt file which contains 'hello world' - can I find that string in HEX somewhere in the CPU registers? And if yes:
How does the CPU know that said string is NOT to be executed?
Could you think of any scencario where the above commands could get exploited? Afaik only text gets parsed through it, how could that be exploitable? What do I have to be careful about?
Thanks alot!
Machine code executes by being fetched by the instruction-fetch part of the CPU, at the address pointed to by RIP, the instruction-pointer. CPUs can only execute machine code from memory.
General-purpose registers get loaded with data from data load/store instructions, like mov eax, [rdi]. Having data in registers is totally unrelated to having it execute as machine code. Remember that RIP is a pointer, not actual machine-code bytes. (RIP can be set with jump instructions, including indirect jump to copy a GP register into it, or ret to pop the stack into it).
It would help to learn some basics of assembly language, because you seem to be missing some key concepts there. It's kind of hard to answer the security part of this question when the entire premise seems to be built on some misunderstanding of how computers work. (Which I don't think I can easily clear up here without writing a book on assembly language.) All I can really do is point you at CPU-architecture stuff that answers part of the title question of how instructions get executed. (Not from registers).
Related:
How does a computer distinguish between Data and Instructions?
How instructions are differentiated from data?
Modern Microprocessors
A 90-Minute Guide! covers the basic fetch/decode/execute cycle of simple pipelines. Modern CPUs might have more complex internals, but from a correctness / security POV are equivalent. (Except for exploits like Spectre and Meltdown that depend on speculative execution).
https://www.realworldtech.com/sandy-bridge/3/ is a deep-dive on Intel's Sandybridge microarchitecture. That page covering instruction-fetch shows how things really work under the hood in real CPUs. (AMD Zen is fairly similar.)
You keep using the word "parse", but I think you just mean "pass". You don't "parse content through" something, but you can "pass content through". Anyway no, cat usually doesn't involve copying or looking-at data in user-space, unless you run cat -n to add line numbers.
See Race condition when piping through x86-64 assembly program for an x86-64 Linux asm implementation of plain cat using read and write system calls. Nothing in it is data-dependent, except for the command-line arg. The data being copied is never loaded into CPU registers in user-space.
Inside the kernel, copy_to_user inside Linux's implementation of a read() system call on x86-64 will normally use rep movsb for the copy, not a loop with separate load/store, so even in kernel the data gets copied from the page-cache, pipe buffer, or whatever, to user-space without actually being in a register. (Same for write copying it to whatever stdout is connected to.)
Other commands, like less and grep, would load data into registers, but that doesn't directly introduce any risk of it being executed as code.
Most of the things have already been answered by Peter. However i would like to add a few things.
How do commands get executed in the CPU at all? e.g. I use 'cat' so somehwere there will be a call of the command. But how does the data I enter get parsed to the CPU? If I 'cat' a .txt file which contains 'hello world' - can I find that string in HEX somewhere in the CPU registers?
cat is not directly executed by the CPU cat.c. You could check the source code and get and in-depth view. .
What actually happens is that each instruction is converted to assembly instruction and they get executed by the CPU. The instructions are not vulnerable because what they do is just move some data and switch some bits. Most of the vulnerability are due to memory management and cat has been vulnerable in the past Check this for more detail
How does the CPU know that said string is NOT to be executed?
It does not. Its the job of the operating system to tell what is to be executed and what not.
Could you think of any scencario where the above commands could get exploited? Afaik only text gets parsed through it, how could that be exploitable? What do I have to be careful about?
You have to be careful about how you are passing the text file to the memory. You could even make your own interpreter that would execute txt file and then the interpreter will be telling the CPU about how to execute that instruction.

Source of clock_gettime

I've tried to understand the behavior of the function clock_gettime by looking at the source code of the linux kernel.
I'm currently using a 4.4.0-83-lowlatency but I only could get the 4.4.76 source files (but it should be close enough).
My first issue is that there is several occurrence of the function. I chose pc_clock_gettime which appears to be the closest and the only one handling CLOCK_MONOTONIC_RAW but if I'm wrong, please correct me.
I tracked back the execution flow of the function and came to a mysterious ravb_ptp_gettime64 and ravb_ptp_time_read which is related to the Ethernet driver.
So... If I understand correctly when I ask the system to give me the time, it ask to the Ethernet driver ?
This is the first time I looked into kernel code so I'm not used to it. If someone could give me an explanation of "how" and "why", it would be marvelous.
clock_gettime use a mechanism named vDSO (Virutal Dynamic Shared Object). It's a shared library which is mapped in the user space by the kernel.
vDSO allow the use of syscall frequently without a drawback on performances. So the kernel "puts" time informations into memory which user programm can access. In the end, it won't be a system call but only a simple function call.

Can I say copy_to_user()/copy_from_user() is a memcpy with access_ok()?

We knew that for secure issues, we should use copy_to_user()/copy_from_user() if we want to do memory copy between user space and kernel space.
My question is, so the memcpy() should have better performance than copy_to_user()/copy_from_user()? Because memcpy() didn't do anything to try to protect the system, am I right?
If we don't care about secure issues, can we use memcpy() instead of copy_to_user()/copy_from_user() to get better performance? (it's a bad idea, I know, just ask if it's right)
One answer: No, because security issues are never irrelevant in the kernel.
memcpy() in particular is a bad function to use because the third argument is a signed integer. If the user can in any way influence the value of this third parameter, you open yourself up to serious liability issues if someone attempts to copy a negative number of bytes.
Many a serious buffer overflow bugs have been due to the signed-ness of memcpy()
Another answer: No, because copy_to_user() and copy_from_user() don't just do access_ok(). Those first two functions make sure that the copy you are currently trying to achieve right now will succeed, or fail appropriately. This is not what access_ok() does for you. The documentation for access_ok() specifically says that this function doesn't guarantee that memory accesses will actually succeed:
Note that, depending on architecture, this function probably just
checks that the pointer is in the user space range - after calling
this function, memory access functions may still return -EFAULT.
For example, my most recent source code has, for x86, runtime checking that goes beyond access_ok(): https://lwn.net/Articles/612153/
Yet a third answer: memcpy() probably isn't much more efficient. You might save a few instructions here and there in principle, but those setup and checking instructions are going to be negligible once you're copying anything more than the smallest quantities of data.

Identifying taint sources in a program for taint propagation

In taint analysis, a taint source is a program location or statement that may produce an untrusted or external input.
My Goal : Identify all external user inputs to the program such as cmdline-input , file reading , environment and network variables using dynamic analysis(preferably) and propagate the taint.
I read this tutorial- http://shell-storm.org/blog/Taint-analysis-and-pattern-matching-with-Pin/ which intercepts read syscalls using Intel PIN and propagates the taint. I want to extend the same to include various external inputs mentioned as above.( To start out , for C - scanf , gets , fopen ,etc )
Is there any dynamic analysis tool which would help me with the identification of generic external inputs? Any other approaches with specific goals is also appreciated. Thanks
I'm assuming you only target Linux.
In general, the way for a program to get outside inputs is through contact with the operating system, using system calls. You're talking about libc functions. This is a higher level of abstraction. I would recommend looking at inputs at the system call level.
Additionally, another input for the program is environment variables and command line arguments, that are found on the stack when the program starts.
One more thing to consider is shared memory in all its shapes and forms.

Using user-space functions like sprintf in the kernel, or not?

I am making a /proc entry for my driver. So, in the read callback function the first argument is the location into which we write the data intended for the user. I searched on how to write the data in it and i could see that everybody is using sprintf for this purpose. I am surprised to see that it works in kernel space. However this should be wrong to use a user space function in kernel space. Also i cant figure out how to write in that location without using any user space function like strcpy, sprintf, etc. I am using kernel version 3.9.10. Please suggest me how i should do this without using sprintf or any other user space function.
Most of the 'normal' user-space functions would make no sense in kernel code, so they are not available in the kernel.
However, some functions like sprintf, strcpy, or memcpy are useful in kernel code, so the kernel implements them (more or less completely) and makes them available for drivers.
See include/linux/kernel.h and string.h.
sprintf is a kernel-space function in Linux. It is totally separate from its user-space namesake and may or may not work identically to it.
Just because a function in user-space exist, it does not mean an identically named function in kernel-space cannot.

Resources