如何写入/proc/cmdline中的kernel启动参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何写入/proc/cmdline中的kernel启动参数相关的知识,希望对你有一定的参考价值。

参考技术A 参数是bootloader传来的,所以在那里修改,有些bootloader可以支持通过命令修改setenv
saveenv
可以修改,eg:uboot。但像lk
手机通常是它,只能在lk的code来修改了。当然如果单纯为了在proc/cmdline显示不同的话,在start_kernel也可以修改的

如何禁用 proc 文件的读取或写入功能?

【中文标题】如何禁用 proc 文件的读取或写入功能?【英文标题】:How to disable reading or writing functionality on a proc file? 【发布时间】:2021-07-11 21:37:54 【问题描述】:

我正在创建一个 proc 文件 (/proc/key),用户可以将其 decryption_key 写入该文件,然后该密钥将用于解密存储在内核模块中的缓冲区的内容。此外,我还有另一个 proc 条目(/proc/decrypted),用于读取存储解密文本的缓冲区的内容。

问题是我不希望用户能够向 (/proc/decrypted) 文件写入任何内容,也不希望他从 (/proc/key) 读取任何内容。如何实现?

我已经将file_operations结构中的相应函数指向NULL,但是很明显,一旦用户尝试它们,这将导致分段错误。

如何防止从 procfs 读取或写入?我应该只创建没有主体的函数并在需要时将 file_operations 结构指向它们吗?

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,
;  

【问题讨论】:

将它们指向一个返回错误代码的函数,例如EPERM 同样open()函数可以检查他们是否指定O_RDONLYO_WRONLYO_RDWR,并返回无效方向的错误。 @Barmar 如何将它们指向这些功能?能给我举个例子吗?另外,如何按照您的建议将权限设置为只读?这将完全按照我的意愿进行 什么意思?只需编写一个返回错误的函数key_proc_read,然后使用.read = key_proc_read 写一个函数key_proc_open检查打开模式。 【参考方案1】:

如果你想禁止读取,你可以省略显式设置struct file_operation.read 字段。如果结构体定义为static,因此初始化为0,所有没有显式覆盖的字段都将默认为NULL,内核将根本不做任何事情并返回错误(我相信-EINVAL)每当用户代码尝试在您打开的文件上调用 read 时。

或者,如果您想返回自定义错误,您可以定义一个只返回错误的虚拟函数(例如return -EFAULT;)。

你认为我将密钥“写入”缓冲区的方式是正确的吗?

这是错误的,原因有很多。

首先,您的copy_from_user() 盲目信任用户count,因此这会导致temp 变量上的内核缓冲区溢出,这非常糟糕。您需要先检查和/或限制大小。您也没有检查copy_from_user() 的返回值,这是您应该检查的(而且它不是int,而是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;

现在代码更有意义了,但是变量temp只在函数内部定义,因此在函数返回后会丢失,您将无法在其他文件操作函数中使用它。如果你想这样做,你可以使用filp->private_data,这是struct file的一个字段,正是为此目的。

您应该在open 上创建并初始化一个缓冲区,然后在您的release 函数中释放它,如下所示:

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;

然后,在您的write 中,您可以在将缓冲区转换为正确的类型后直接使用它:

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;

最后,我看到你在使用:

 .llseek = seq_lseek,
 .release = single_release,

不要这样做。您不需要使用预定义的操作。不要混合您创建的自定义函数和其他规范函数,例如用于序列文件的函数。序列文件需要执行一些初始化和拆卸,或者您使用 all seq_ 系列文件操作,或者您自己手动执行,或者您不使用这些函数。在您的情况下,最后一个选项适用。

您可以将.release 设置为我上面显示的hello_proc_release(),而不设置.llseek(默认为NULL)。

【讨论】:

以上是关于如何写入/proc/cmdline中的kernel启动参数的主要内容,如果未能解决你的问题,请参考以下文章

android设备/proc目录下都有什么?

如何访问proc/pid/mem

echo 3 > /proc/sys/vm/drop_caches linux大量重复进程 问题!

安卓如何查看进程信息,都说是用ps看到pid后根据pid去/proc/pid/maps中去看调用的

在linux环境下,我们使用C语言编程,如何正确计算CPU使用率?(不限/proc/stat)

linux下用程序读取某进程的状态信息(/proc/[pid]/stat)时,该进程结束了。怎么办