커널 안에서 파일을 여는 경우가 있을까?
다음 코드는 fs/open.c의 한 부분이다.
/**
* file_open_name - open file and return file pointer
*
* @name: struct filename containing path to open
* @flags: open flags as per the open(2) second argument
* @mode: mode for the new file if O_CREAT is set, else ignored
*
* This is the helper to open a file from kernelspace if you really
* have to. But in generally you should not do this, so please move
* along, nothing to see here..
*/
struct file *file_open_name(struct filename *name, int flags, umode_t mode)
{
struct open_flags op;
int err = build_open_flags(flags, mode, &op);
return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op);
}
kernel space에서 파일을 여는 것을 도와주는 함수라고 한다. 하지만 사용하지 않는 것을 추천한다고 주석에 나와있다. 아래에는 이 함수를 포함한 kernel space에서 파일을 다루기 위한 함수들의 예시가 나온 사이트이다. 아래 사이트에서는 vfs_write을 사용하지만 리눅스 버전이 업그레이드되면서 이는 read_write.c밖에서는 볼 수 없고 kernel_write이라는 rapper function을 사용하게 된다.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
loff_t *pos)
{
mm_segment_t old_fs;
ssize_t res;
old_fs = get_fs();
set_fs(KERNEL_DS);
/* The cast to a user pointer is valid due to the set_fs() */
res = vfs_write(file, (__force const char __user *)buf, count, pos);
set_fs(old_fs);
return res;
}
EXPORT_SYMBOL(kernel_write);
그리고 이 kernel_write을 export해준다. old_fs, set_fs 등은 Virtual memory에서 unpriveleged code들이 접근할 수 있는 범위를 설정하는 fs register의 값을 조정하는 함수들이다. access_ok라는 함수가 vfs_write에서 호출이 되는데 이는 buffer가 User영역에 있는지를 확인한다. 하지만 현재 우리는 kernel에서 buffer를 kmalloc 한 것이기 때문에 오류가 발생하는 것이다. 아무튼 이런 전처리와 vfs_write을 섞어서 사용할 수 있게 해 준다.
https://www.programmersought.com/article/80804111974/
Linux kernel space file operation function - Programmer Sought
The functions for manipulating files in the kernel are different from the user space, and a set of functions dedicated to the kernel space needs to be used, mainly filp_open(), filp_close(), vfs_read(), vsf_write(), set_fs(), get_fs(), etc. The functions a
www.programmersought.com
여기서 보면 모든 함수는 'struct file'을 인자로 받아서 무엇인가 처리를 한다. 즉 open file이어야 된다는 것이다. 또한 이러한 'struct file'은 file path를 인자로 받아 생성이 된다. 여기서 질문은, kernel은 거의 전지전능한 능력을 가졌으니 secondary storage의 inode위치만 알고 있다면, 정보를 읽어와서 'struct file', 'struct inode'를 만들 수 있지 않을까? Inode에는 보통 할당된 숫자가 있다. 이 숫자를 이용하면 더 빠르게 만들 수 있지 않을까? 이러한 함수들이 vfs영역에 있는지는 모르겠다. 아마 없을 것이다. 각각의 파일 시스템이 inode를 관리하는 방식도, 저장하는 공간도 다를 것이다. 이러한 것은 fs specific function에 포함될 것이다. NOVA 같은 경우에는
- nova_iget
- nova_get_inode
// fs/nova/inode.c
struct inode *nova_iget(struct super_block *sb, unsigned long ino)
{
struct nova_inode_info *si;
struct inode *inode;
u64 pi_addr;
int err;
inode = iget_locked(sb, ino);
if (unlikely(!inode))
return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW))
return inode;
si = NOVA_I(inode);
nova_dbgv("%s: inode %lu\n", __func__, ino);
err = nova_get_inode_address(sb, ino, 0, &pi_addr, 0, 0);
if (err) {
nova_dbg("%s: get inode %lu address failed %d\n",
__func__, ino, err);
goto fail;
}
if (pi_addr == 0) {
nova_dbg("%s: failed to get pi_addr for inode %lu\n",
__func__, ino);
err = -EACCES;
goto fail;
}
err = nova_read_inode(sb, inode, pi_addr);
if (unlikely(err)) {
nova_dbg("%s: failed to read inode %lu\n", __func__, ino);
goto fail;
}
inode->i_ino = ino;
unlock_new_inode(inode);
return inode;
fail:
iget_failed(inode);
return ERR_PTR(err);
}
// fs/nova/inode.h
static inline struct nova_inode *nova_get_inode(struct super_block *sb,
struct inode *inode)
{
struct nova_inode_info *si = NOVA_I(inode);
struct nova_inode_info_header *sih = &si->header;
struct nova_inode fake_pi;
void *addr;
int rc;
addr = nova_get_block(sb, sih->pi_addr);
rc = memcpy_mcsafe(&fake_pi, addr, sizeof(struct nova_inode));
if (rc)
return NULL;
return (struct nova_inode *)addr;
}
를 통해서 이를 지원해주었다. Inode number와 superblock을 인자로 넘겨주어 'struct inode'를 읽어올 수 있었고, 이를 통해서 'struct nova_inode'를 생성할 수 있었다. 'struct file'은 아직 생성해보지 않았만, 아마 가능할 것이다. 주의할 점은 삭제된 파일에 대한 참조를 하는 경우인데, 이럴 경우 예외처리 구문을 넣어주어 trap을 피했다. Kernel에서 trap은 reboot을 요구하기 때문에 귀찮은 과정이다. (kill -9를 해도, 바로 실행이 안될 가능성이 높다)
P.S - 직접 올린 질문
https://unix.stackexchange.com/q/662715/453092
How to Open a file in the kernel using only the inode
I am currently trying to open, read, write to a specific file in the (linux)kernel space. I know that filp_open, kernel_write functions could be used to perform the same effects as open, write in the
unix.stackexchange.com
'실험실 (커널 오류)' 카테고리의 다른 글
[kernel panic] not syncing: Real mode trampoline was not allocated (0) | 2021.11.24 |
---|---|
[kernel panic] unable to handle kernel paging request at ~~ (0) | 2021.07.21 |
[NOVA] write path - offset, pos 추적 (7/20) (0) | 2021.07.20 |
[kernel build error] VFS: Unable to mount root fs on unknown-block(0,0) (0) | 2021.07.19 |
[NOVA] system call argument 추가 오류(2) (0) | 2021.07.19 |