从内核中分配用户空间内存

5

我想调用

sys_readlink(const char __user *path, char __user *buf, int bufsiz)

直接使用指向内核空间的内存,会返回EFAULT错误代码。这个错误出现是因为buf指向来自内核空间的内存。

那么,是否有可能从内核分配用户空间内存呢?

kmalloc(size, GFP_USER)类似于kmalloc(size, GFP_KERNEL),并返回指向内核内存的指针。


1
为什么需要在内核中进行如此高级的操作? - Omnifarious
4
你已经在内核空间中了;你应该直接调用虚拟文件系统(VFS),而不是使用系统调用。 - Ignacio Vazquez-Abrams
1
我正在使用readlink("/proc/PID/exe")来获取当前进程映像文件的完整路径,是否有其他方法可以获取它?我不能使用d_path(),因为它使用了我已经挂钩的系统调用,所以它返回NULL。 - Makc
2
GFP_USER意味着它是内核空间内存,您可以允许用户访问(通常用作共享内核/用户页面的标记)。Readlink需要用户空间虚拟内存区域和该区域中的地址。我建议您采纳Ignacio的建议或重新考虑在内核中编写此程序。 - Jesus Ramos
1个回答

9

您可以使用set_fs临时禁用内存地址有效性检查

mm_segment_t old_fs;

old_fs = get_fs();
set_fs(KERNEL_DS);
/* Your syscall here */
set_fs(old_fs);

2
嗨,我有一个类似的问题。在我的情况下,我想要调用的系统调用是pread。所以我直接调用了vfs_read。我验证了这个set_fs(KERNEL_DS)正在发挥作用。然而,当我使用O_DIRECT标志打开文件并进行vfs_read时,我又再次收到了-EFAULT错误。你能否解释一下O_DIRECT问题? - Erben Mo
1
@ErbenMo:如果我没记错,O_DIRECT 带有一些严格的对齐要求(实际要求因文件系统和内核版本而异),这可能是你问题的原因。 - Hasturkun
1
我认为对齐要求是基于磁盘上数据的大小/地址,而不是存储读取后数据的缓冲区的大小/地址...所以我不确定这是否是问题,因为我在磁盘上读取的数据已经按4kb对齐了。看起来问题出在存储数据的内存缓冲区上。 - Erben Mo
1
@ErbenMo:如果我没记错的话,要求也在用户缓冲区上。非对齐缓冲区可能无法正常工作。 - Hasturkun
set_fs 对于新的 Linux 内核已经不再相关了。它已经被移除了 :( - Eytan Naim
@EytanNaim:关于set_fs()移除的相关LWN文章(这似乎是在5.18版本中完成的)。 - Hasturkun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接