sys_close 更改后发生内核恐慌

发布于 2024-08-11 04:40:48 字数 2978 浏览 6 评论 0原文

我正在学习操作系统课程,我们使用 Linux Red Hat 8.0 作为作业的一部分,我必须更改 sys close 和 sys open 。对 sys close 的更改顺利通过,但当我引入对 sys close 的更改时,操作系统突然在启动过程中遇到错误,声称无法挂载 root fs,并引发恐慌。据报道,当这种情况发生时,EIP 处于系统关闭状态。

以下是我所做的更改(查找“HW1 添加”评论): 在fs/open.c中:

asmlinkage long sys_open(const char * filename, int flags, int mode)
{
    char * tmp;
    int fd, error;
    event_t* new_event;

#if BITS_PER_LONG != 32
    flags |= O_LARGEFILE;
#endif
    tmp = getname(filename);
    fd = PTR_ERR(tmp);
    if (!IS_ERR(tmp)) {
        fd = get_unused_fd();
        if (fd >= 0) {
            struct file *f = filp_open(tmp, flags, mode);
            error = PTR_ERR(f);
            if (IS_ERR(f))
                goto out_error;
            fd_install(fd, f);
        }
        /* HW1 additions */
        if (current->record_flag==1){
            new_event=(event_t*)kmalloc(sizeof(event_t), GFP_KERNEL);
            if (!new_event){
                new_event->type=Open;
                strcpy(new_event->filename, tmp);
                file_queue_add(*new_event, current->queue);
            }
        }
        /* End HW1 additions */
out:
        putname(tmp);
    }
    return fd;

out_error:
    put_unused_fd(fd);
    fd = error;
    goto out;
}

asmlinkage long sys_close(unsigned int fd)
{
    struct file * filp;
    struct files_struct *files = current->files;
    event_t* new_event;
    char* tmp = files->fd[fd]->f_dentry->d_name.name;   

    write_lock(&files->file_lock);
    if (fd >= files->max_fds)
        goto out_unlock;
    filp = files->fd[fd];
    if (!filp)
        goto out_unlock;
    files->fd[fd] = NULL;
    FD_CLR(fd, files->close_on_exec);
    __put_unused_fd(files, fd);
    write_unlock(&files->file_lock);
    /* HW1 additions */    
    if(current->record_flag == 1){
        new_event=(event_t*)kmalloc(sizeof(event_t), GFP_KERNEL);
        if (!new_event){
            new_event->type=Close;
            strcpy(new_event->filename, tmp);
            file_queue_add(*new_event, current->queue);
        }
    }
    /* End HW1 additions */
    return filp_close(filp, files);

out_unlock:
    write_unlock(&files->file_lock);
    return -EBADF;
}

schedule.h中定义的task_struct在最后被更改为包括:

unsigned int record_flag; /* when zero: do not record. when one: record. */
file_queue* queue;

并且文件队列以及事件t在单独的文件中定义如下:

typedef enum {Open, Close} EventType;

typedef struct event_t{
    EventType type;
    char filename[256];
}event_t;

typedef struct file_quque_t{
    event_t queue[101];
    int head, tail; 
}file_queue;

文件队列添加的工作方式如下:

void file_queue_add(event_t event, file_queue* queue){ 
    queue->queue[queue->head]=event;
    queue->head = (queue->head+1) % 101;
    if (queue->head==queue->tail){
        queue->tail=(queue->tail+1) % 101;
    }
}

I'm doing a course on operating systems and we work in Linux Red Hat 8.0
AS part of an assignment I had to change sys close and sys open. Changes to sys close passed without an incident, but when I introduce the changes to sys close suddenly the OS encounters an error during booting, claiming it cannot mount root fs, and invokes panic. EIP is reportedly at sys close when this happens.

Here are the changes I made (look for the "HW1 additions" comment):
In fs/open.c:

asmlinkage long sys_open(const char * filename, int flags, int mode)
{
    char * tmp;
    int fd, error;
    event_t* new_event;

#if BITS_PER_LONG != 32
    flags |= O_LARGEFILE;
#endif
    tmp = getname(filename);
    fd = PTR_ERR(tmp);
    if (!IS_ERR(tmp)) {
        fd = get_unused_fd();
        if (fd >= 0) {
            struct file *f = filp_open(tmp, flags, mode);
            error = PTR_ERR(f);
            if (IS_ERR(f))
                goto out_error;
            fd_install(fd, f);
        }
        /* HW1 additions */
        if (current->record_flag==1){
            new_event=(event_t*)kmalloc(sizeof(event_t), GFP_KERNEL);
            if (!new_event){
                new_event->type=Open;
                strcpy(new_event->filename, tmp);
                file_queue_add(*new_event, current->queue);
            }
        }
        /* End HW1 additions */
out:
        putname(tmp);
    }
    return fd;

out_error:
    put_unused_fd(fd);
    fd = error;
    goto out;
}

asmlinkage long sys_close(unsigned int fd)
{
    struct file * filp;
    struct files_struct *files = current->files;
    event_t* new_event;
    char* tmp = files->fd[fd]->f_dentry->d_name.name;   

    write_lock(&files->file_lock);
    if (fd >= files->max_fds)
        goto out_unlock;
    filp = files->fd[fd];
    if (!filp)
        goto out_unlock;
    files->fd[fd] = NULL;
    FD_CLR(fd, files->close_on_exec);
    __put_unused_fd(files, fd);
    write_unlock(&files->file_lock);
    /* HW1 additions */    
    if(current->record_flag == 1){
        new_event=(event_t*)kmalloc(sizeof(event_t), GFP_KERNEL);
        if (!new_event){
            new_event->type=Close;
            strcpy(new_event->filename, tmp);
            file_queue_add(*new_event, current->queue);
        }
    }
    /* End HW1 additions */
    return filp_close(filp, files);

out_unlock:
    write_unlock(&files->file_lock);
    return -EBADF;
}

The task_struct defined in schedule.h was changed at the end to include:

unsigned int record_flag; /* when zero: do not record. when one: record. */
file_queue* queue;

And file queue as well as event t are defined in a separate file as follows:

typedef enum {Open, Close} EventType;

typedef struct event_t{
    EventType type;
    char filename[256];
}event_t;

typedef struct file_quque_t{
    event_t queue[101];
    int head, tail; 
}file_queue;

file queue add works like this:

void file_queue_add(event_t event, file_queue* queue){ 
    queue->queue[queue->head]=event;
    queue->head = (queue->head+1) % 101;
    if (queue->head==queue->tail){
        queue->tail=(queue->tail+1) % 101;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

偷得浮生 2024-08-18 04:40:48
if (!new_event) {
    new_event->type = …

这相当于 if (new_event == NULL)。我认为您的意思是 if (new_event != NULL),内核人员通常将其写为 if (new_event)

if (!new_event) {
    new_event->type = …

That's equivalent to if (new_event == NULL). I think you mean if (new_event != NULL), which the kernel folks typically write as if (new_event).

许久 2024-08-18 04:40:48

您能发布错误的堆栈转储吗?我没有看到queue_info结构分配内存的地方。另一件事是,如果在内核中未分配,您不能确定进程 record_flag 将始终为零,因为内核是一个长时间运行的程序,并且内存包含垃圾。

还可以通过查看堆栈跟踪来检查函数中发生的确切位置。

Can you please post the stackdump of the error. I don't see a place where queue_info structure is allocated memory. One more thing is you cannot be sure that process record_flag will be always zero if unassigned in kernel, because kernel is a long running program and memory contains garbage.

Its also possible to check the exact location in the function is occurring by looking at the stack trace.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文