user101285
user101285

Reputation: 111

Dereferencing pointer to incomplete type in Linux Module

I encountered a compilation error "dereferencing pointer to incomplete type" while compiling a module in Linux. I have created an inode_operations table which I want to assign to proc_iops pointer in proc_dir_entry. I searched for the answers telling me to use procfs APIs. Using fs/proc/internal.h is not possible as it is not under include directory. I know about incomplete types but I am still not able to perform that assignment in init_module. Help needed.

Using Debian 8 with Linux Kernel 3.16 GCC Version 4.8

#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>

#define MESSAGE_LENGTH 80

#define PROC_ENTRY_FILENAME "sleep"

static char message[MESSAGE_LENGTH];

int already_open = 0;

static ssize_t module_output(struct file *file,
                 char *buf,
                 size_t len,
                 loff_t *offset)
{
    static int finished = 0;
    int i;
    char message[MESSAGE_LENGTH + 30];

    if (finished){
        finished = 0;
        return 0;
    }

    sprintf(message, "Last input: %s\n",message);

    for(i = 0;i < len && message[i]; i++)
        put_user(message[i], buf + i);

    finished = 1;
    return i;
}

static ssize_t module_input(struct file *file,
                const char *buf,
                size_t length,
                loff_t *offset)
{
    int i;

    for (i = 0; i < MESSAGE_LENGTH - 1 && i < length; i++)
        get_user(message[i], buf + i);

    message[i] = '\0';

    return i;
}

DECLARE_WAIT_QUEUE_HEAD(WaitQ);

static int module_open(struct inode *inode, struct file *file)
{
    int i;
    int is_sig = 0;

    if ((file->f_flags & O_NONBLOCK) && already_open )
        return -EAGAIN;

    try_module_get(THIS_MODULE);

    while(already_open){

        wait_event_interruptible(WaitQ, !already_open);

        for(i = 0; i < _NSIG_WORDS && !is_sig; i++)
            is_sig = current->pending.signal.sig[i] &
                 ~current->blocked.sig[i];

        if (is_sig){
            module_put(THIS_MODULE);
            return -EINTR;
        }   
    }

    already_open = 1;

    return 0;       
}

int module_close(struct inode *inode, struct file *file)
{
    already_open = 0;

    wake_up(&WaitQ);

    module_put(THIS_MODULE);

    return 0;
}

static int module_permission(struct inode *inode, int op)
{
    // Documentation/security/credentials.txt
    if (op==4 || (op == 2 && current_euid().val == 0))
        return 0;

    return -EACCES;
}

static struct file_operations fops = {
    .read = module_output,
    .write = module_input,
    .open = module_open,
    .release = module_close
};

static struct inode_operations iops = {
    .permission = module_permission
};

int init_module(void)
{
    struct proc_dir_entry *our_proc_file;

    our_proc_file = proc_create(PROC_ENTRY_FILENAME, 0, NULL, &fops);

    if( our_proc_file == NULL )
    {
        printk(KERN_ALERT "Error: Could not initialize /proc/sleep\n"); 
        return -ENOMEM;
    }

    // Line causing the error
    our_proc_file->proc_iops = &iops;

    printk(KERN_INFO "/proc/sleep file created.\n");

    return 0;
}

void cleanup_module(void)
{
    remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
    printk(KERN_INFO "/proc/sleep file removed.");
}

Upvotes: 0

Views: 2741

Answers (1)

Sourav Ghosh
Sourav Ghosh

Reputation: 134286

The definition of struct proc_dir_entry is available in fs/proc/internal.h file. You have to include it to get the definition into your source file.

Using fs/proc/internal.h is not possible as it is not under include directory.

In compilation time, you can provide the (custom) path to the include files you'll be using using -I option with gcc.

NOTE: I assume you have kernel-headerfiles and kernel-devel installed.

Upvotes: 0

Related Questions