PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label linux-kernel. Show all posts
Showing posts with label linux-kernel. Show all posts

Friday, November 11, 2022

[FIXED] how to create /proc file inside kernel module?

 November 11, 2022     c, file, filesystems, linux-kernel, proc     No comments   

Issue

I want to save some information in a kernel module. I have seen similar question to mine here in stackoverflow, however mine is slightly different. Assuming I am using this code to write in a /proc file. How should I call it inside one of my kernel module? I have a custom kernel module called mymodule which is not the main file (does not have init_module()) inside it the below function is called. In this case what should be the input value to the function like value of file? Basically is it possible to create a /proc file inside a kernel module?

int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data)


Solution

It is definitely possible to add a proc entry in a kernel module but you might be misunderstanding how file handling works in the kernel.

When you create a file in proc, you're not actually 'creating' a file like you would in userspace. You're registering a few callbacks that are called when userspace programs request your file.

That means, when userspace programs request a read, your file read callback has to provide data. When a userspace program requests a write, your file write callback has to handle it.

If you want to use it like a conventional file to store information, you have to allocate the required space and have your read callback copy data from there.



Answered By - tangrs
Answer Checked By - Marie Seifert (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Thursday, November 10, 2022

[FIXED] How to disable reading or writing functionality on a proc file?

 November 10, 2022     c, linux-kernel, module, proc, procfs     No comments   

Issue

I am creating a proc file (/proc/key) that a user can write his decryption_key to it and then this key will be used to decrypt the contents of a buffer stored inside a kernel module. Also, I have another proc entry (/proc/decrypted) that will be used to read the contents of the buffer that stores the decrypted text.

The problem is that I don't want the user to be able to write anything to the (/proc/decrypted) file and I don't want him to read anything from the (/proc/key). How can this be implemented?

I have pointed the corresponding functions inside the file_operations struct to NULL, but obviously, this is going to cause segmentation faults once the user tries them.

How can I prevent reading or writing from a procfs? should I just create functions that have no body and point the file_operations struct to them when needed?

static ssize_t key_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
    char temp[128];
    memset(temp, 0, 128);
    int c; 
    c = copy_from_user(temp, buf, count);
 return count;
}


static const struct file_operations Proc_key_fops = {
 .owner = THIS_MODULE,
 .open = hello_proc_open,
 .read = NULL,
 .write = key_proc_write,
 .llseek = seq_lseek,
 .release = single_release,
};  

Solution

If you want to disallow reading, you can just omit explicitly setting the .read field of struct file_operation. If the structure is defined as static and therefore initialized to 0, all fields that are not explicitly overridden will default to NULL, and the kernel will simply not do anything and return an error (I believe -EINVAL) whenever user code tries to call read on your open file.

Alternatively, if you want to return a custom error, you can define a dummy function which only returns an error (like for example return -EFAULT;).

Do you think the way I am "writing" the key into the buffer is the right way to do it ?

This is wrong for multiple reasons.

First, your copy_from_user() is blindly trusting the user count, so this result in a kernel buffer overflow on the temp variable, which is pretty bad. You need to check and/or limit the size first. You are also not checking the return value of copy_from_user(), which you should (and it is not an int, but rather an unsigned long).

static ssize_t key_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
    char temp[128];
    memset(temp, 0, 128);

    if (count > 128)
        count = 128; // or alternatively return -EINVAL or another error

    if (copy_from_user(temp, buf, count))
        return -EFAULT;

    return count;
}

Now the code makes more sense, however the variable temp is defined only locally inside the function, and therefore will be lost after the function returns, you will not be able to use it in other file operation functions. If you want to do this, you can use filp->private_data, which is a field of struct file exactly meant for this purpose.

You should create and initialize a buffer on open, and then free it in your release function, something like this:

static int hello_proc_open(struct inode *ino, struct file *filp) 
{
    void *buf = kmalloc(128, GFP_KERNEL);
    if (!buf)
        return -ENOMEM;

    filp->private_data = buf;

    // ... whatever else you need to do

    return 0;
}

static int hello_proc_release(struct inode *ino, struct file *filp) 
{
    kfree(filp->private_data);

    // ... whatever else you need to do

    return 0;
}

Then, in your write you can directly use the buffer after casting it to the correct type:

static ssize_t key_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
    char *temp = filp->private_data;
    memset(temp, 0, 128);

    if (count > 128)
        count = 128; // or alternatively return -EINVAL or another error

    if (copy_from_user(temp, buf, count))
        return -EFAULT;

    return count;
}

Finally, I see you are using:

 .llseek = seq_lseek,
 .release = single_release,

Do not do this. You do not need to use pre-defined operations. Do not mix custom functions created by you and other canonical functions like for example those used for sequence files. Sequence files expect some initialization and teardown to be performed, either you use all the seq_ family of file operations, or you do it manually yourself OR you do not use the functions. In your case the last option applies.

You can just set .release to the hello_proc_release() I showed above, and leave .llseek not set (default to NULL).



Answered By - Marco Bonelli
Answer Checked By - Senaida (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Tuesday, October 18, 2022

[FIXED] Why can macos(x86) run docker arm container arm64v8/alpine?

 October 18, 2022     docker, emulation, linux-kernel, qemu     No comments   

Issue

I happened to find that my macos(x86) can run a docker container for an arm image arm64v8/alpine, but with the following warning:

docker run -it  arm64v8/alpine uname -a

WARNING: The requested image's platform (linux/arm64) does not match the detected host platform (linux/amd64) and no specific platform was requested
Linux d5509c57dd24 4.19.121-linuxkit #1 SMP Tue Dec 1 17:50:32 UTC 2020 aarch64 Linux

And I'm pretty sure the image is not a multi-arch image (docker manifest inspect --verbose arm64v8/alpine). Why can x86 run an arm container?


Solution

You are correct, the image is not multi architecture, yet, docker can run it. Reason behind this is a kernel subsystem called binfmt_misc which allows to set the magic numbers of a binary file to specific actions for their execution. You can read more in this nice wikipedia post about it.

Docker for Mac is arriving prepared for the binfmt magic, so there is nothing to be done to enable it. It will be enabled out-of-box with the installation, all you need to do is to fetch the image and run. The details of the mechanism can be found in repository of docker-for-mac project on this link.

To explain it simply, the binary images have the magic number that allows the kernel to decide how to handle the execution. When binfmt_misc intercepts a file for which it recognizes the magic numbers it will invoke the handler that is associated with the magic numbers.

This alone is not enough to run the container. The next part of the magic is QEMU which is the emulator for various CPU architectures. The kernel (binfmt_misc) will invoke the quemy for each of the binaries that are ARM64 and will emulate the ARM64v8.

This is not limited to docker nor to the virtual machine that is running the docker on macOS. Any linux system can be configured to do this.

You can use following to install it setup Ubuntu to run the emulation.

sudo apt-get install qemu binfmt-support qemu-user-static # Install the qemu packages
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes # This step will execute the registering scripts

docker run --rm -t arm64v8/ubuntu uname -m # Testing the emulation environment

More details about the whole process of the set-up can be found in the qemu-user-static repository

OP: If you are wondering what is the usefulness of this, from my personal experiance, I am using this functionality heavily when porting applications from X86 to other architectures (mainly ARM64). This allows me to run build systems for various architectures without having a physical machine on which I can run the build.



Answered By - jordanvrtanoski
Answer Checked By - Robin (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Sunday, September 18, 2022

[FIXED] How does the command 'echo "6" > /proc/sys/kernel/printk' work?

 September 18, 2022     file, linux, linux-kernel, printing, shell     No comments   

Issue

Please see an example in How can I show printk() message in console?,

$ cat /proc/sys/kernel/printk
4 4 1 7
$ echo "6" > /proc/sys/kernel/printk
$ cat /proc/sys/kernel/printk
6 4 1 7

If the /proc/sys/kernel/prink was a normal file, the file would have changed to just "6", a single number. But I know the proc file system is a file system in ram and I guess it works different. In what mechanism did the file changed that way? And if I wanted to change the content to 4 6 1 7, can I do it with echo command and redirection?


Solution

Filesystem entries under /proc behave somewhat like function calls. "Writing" a string to the file is like calling a function with the string as an argument. "Reading" from the file is like calling a function with no argument and getting back the return value. The behavior of each "function" is defined by the kernel (or at least, by the proc file system exposed by the filesystem entries).

See https://www.kernel.org/doc/html/latest/core-api/printk-basics.html for the details on how printk in particular works. In short, writing a number to the file changes the current logging level, while reading shows the current (if changed), default, minimum, and boot-time default logging levels.



Answered By - chepner
Answer Checked By - Pedro (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Tuesday, August 23, 2022

[FIXED] How to simulate press a key in linux kernel module?

 August 23, 2022     keypress, linux, linux-kernel, module     No comments   

Issue

How to simulate press a key in linux kernel module? I saw keybdev.c, but in my case I cant compile it `

error: implicit declaration of function ‘handle_scancode’

Maybe it's obsolete.


Solution

In the kernel, keyboards can call input_report_key which generates a keyboard event. The USB keyboard driver in /drivers/hid/usbhid/usbkbd.c is a good example of code to do both keyboard input and LED output.



Answered By - stark
Answer Checked By - Mildred Charles (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Sunday, May 15, 2022

[FIXED] What would make a printk not show up immediately in dmesg?

 May 15, 2022     c, kernel-module, linux-kernel, ubuntu     No comments   

Issue

I am making a Linux kernel module on Ubuntu 4.14.12.

My understanding of printk() is that it is guaranteed to output to console immediately before the next line of code is run, rather than having its output placed on a buffer that is eventually flushed at some point. Is this correct?

I was getting a crash that occurred several hundred lines after multiple printk calls whose output did not appear in dmesg using the -wH command or in dmesg sent through tee to a file which I read after rebooting.

Is there lag between the time a printk is sent to console and it shows up in dmesg that would allow my system to freeze up before I saw the output? Or is there something else occurring?

dmesg shows the printks in question after fixing the problematic line of code. The console log level was set higher than the console log level of the printks in question.


Solution

There are many layers between your module calls printk(...) and the output showing up on the console.

My understanding of printk() is that it is guaranteed to output to console immediately before the next line of code is run, rather than having its output placed on a buffer that is eventually flushed at some point. Is this correct?

No, this is not correct. There is no "console" in printk() implementation and there shouldn't be any. There's always a buffer, many layers of buffers. The line 1705 in printk.c answers your question. The printk_emit() function uses a statically allocated buffer static char textbuf[LOG_LINE_MAX]; and calls vscnprintf(textbuf, sizeof(textbuf), ...) on it to parse arguments. So it uses a buffer. I don't think it is possible to write a printf function without using an internal buffer, at least it's harder. And the __log_buf variable is a statically allocated buffer, an array of characters, and it is the kernel log buffer.

Is there lag between the time a printk is sent to console and it shows up in dmesg that would allow my system to freeze up before I saw the output?

Yes? There's always a lag. I don't know how to define a "lag" (one milisecond? A second? One nanosecond?) but the assembly instructions behind printk function has to execute, then all the layers up until they are placed in __log_buf static variable. Then dmesg which awaits on read() syscall is woken up I guess somewhere inside console_unlock. After the wakeup dmesg will finally call devkmsg_read() function which will return the buffer. Then dmesg() will call write() syscall on stdout after it has received the data. Then write() kernel syscall will try to write something onto your screen - so the data has to go all the way through console drivers and display drivers and graphics drivers. There's always a lag. But it should be minimal.

dmesg shows the printks in question after fixing the problematic line of code

Which just says that dmesg didn't get the output from kernel log. There is probably something else occurring. The simplest is dmesg process does not get cpu time, is blocked on reading syslog, your module executes inside with irq disabled, and so on.



Answered By - KamilCuk
Answer Checked By - Dawn Plyler (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home
View mobile version

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing