Проблема с ioctl () в простом модуле ядра

Я пытаюсь создать простой модуль ядра. Ниже приведено содержимое файла, связанного с ним:

module.c:

#include <linux/init.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/kernel.h> #include "header.h" static int device_open(struct inode *inode, struct file *file) { printk("\n Open \n"); return 0; } static int device_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long args) { switch(cmd) { case IOCTL_CMD: printk(KERN_ALERT "\n %s \n", (char *)args); break; } return 0; } static int device_release(struct inode *inode, struct file *file) { printk("\n Release \n"); return 0; } static struct class *my_class; static struct file_operations fops={ .open = device_open, .release = device_release, .compat_ioctl = device_ioctl }; static int hello_init(void) { major_no = register_chrdev(0, DEVICE_NAME, &fops); printk("\n Major_no : %d", major_no); my_class = class_create(THIS_MODULE, DEVICE_NAME); device_create(my_class, NULL, MKDEV(major_no,0), NULL, DEVICE_NAME); printk("\n Device Initialized in kernel ....!!!"); return 0; } static void hello_exit(void) { printk("\n Device is Released or closed \n"); device_destroy(my_class,MKDEV(major_no,0)); class_unregister(my_class); class_destroy(my_class); unregister_chrdev(major_no, DEVICE_NAME); printk("\n===============================================================\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL");

appln.c

#include <stdio.h> #include <fcntl.h> #include <string.h> #include "header.h" int main() { int fd; char * msg = "yahoooo"; fd = open(DEVICE_PATH, O_RDWR); ioctl(fd, IOCTL_CMD, msg); printf("ioctl executed\n"); close(fd); return 0; }

header.h:

#include <linux/ioctl.h> #include <linux/kdev_t.h> /* for MKDEV */ #define DEVICE_NAME "my_dev" #define DEVICE_PATH "/dev/my_dev" #define WRITE 0 static int major_no; #define MAGIC_NO '4' /* * Set the message of the device driver */ #define IOCTL_CMD _IOR(MAGIC_NO, 0, char *)

Мой модуль загружается отлично (я вижу функцию mesg в hello_init ()). Но когда я запускаю программу appln.c, даже когда она вызывает вызов ioctl (), я не вижу результата. Может кто-нибудь сказать, почему модуль игнорирует мой вызов ioctl.

Спасибо,

3
задан 23 July 2011 в 19:36

14 ответов

Несколько вещей:

Вы хотите использовать «unlocked_ioctl», а не «compat_ioctl». Функциональный интерфейс для «device_ioctl» неверен (см. [F2]), это должно быть:
    long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
Приложение appln.c не проверяет коды ошибок (open, ioctl).

После исправления кода код будет работать нормально.

2
ответ дан 25 May 2018 в 19:41
  • 1
    Kees Cook: Спасибо, еще одна вещь, в чем разница b / w unlocked_ioctl и device_ioctl. Есть ли обновленный источник ссылок для разработки модулей, в котором перечислены все такие изменения с кодом ядра. – gkt 25 July 2011 в 23:12

Несколько вещей:

Вы хотите использовать «unlocked_ioctl», а не «compat_ioctl». Функциональный интерфейс для «device_ioctl» неверен (см. [F2]), это должно быть: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); Приложение appln.c не проверяет коды ошибок (open, ioctl).

После исправления кода код будет работать нормально.

2
ответ дан 25 July 2018 в 21:33

Несколько вещей:

Вы хотите использовать «unlocked_ioctl», а не «compat_ioctl». Функциональный интерфейс для «device_ioctl» неверен (см. [F2]), это должно быть: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); Приложение appln.c не проверяет коды ошибок (open, ioctl).

После исправления кода код будет работать нормально.

2
ответ дан 31 July 2018 в 13:39

Несколько вещей:

Вы хотите использовать «unlocked_ioctl», а не «compat_ioctl». Функциональный интерфейс для «device_ioctl» неверен (см. [F2]), это должно быть: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); Приложение appln.c не проверяет коды ошибок (open, ioctl).

После исправления кода код будет работать нормально.

2
ответ дан 2 August 2018 в 03:10

Несколько вещей:

Вы хотите использовать «unlocked_ioctl», а не «compat_ioctl». Функциональный интерфейс для «device_ioctl» неверен (см. [F2]), это должно быть: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); Приложение appln.c не проверяет коды ошибок (open, ioctl).

После исправления кода код будет работать нормально.

2
ответ дан 4 August 2018 в 19:03

Несколько вещей:

Вы хотите использовать «unlocked_ioctl», а не «compat_ioctl». Функциональный интерфейс для «device_ioctl» неверен (см. [F2]), это должно быть: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); Приложение appln.c не проверяет коды ошибок (open, ioctl).

После исправления кода код будет работать нормально.

2
ответ дан 6 August 2018 в 03:22

Несколько вещей:

Вы хотите использовать «unlocked_ioctl», а не «compat_ioctl». Функциональный интерфейс для «device_ioctl» неверен (см. [F2]), это должно быть: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); Приложение appln.c не проверяет коды ошибок (open, ioctl).

После исправления кода код будет работать нормально.

2
ответ дан 7 August 2018 в 21:08

Минимальный runnable пример

Проверено в полностью воспроизводимой среде QEMU + Buildroot, поэтому может помочь другим получить работу ioctl. GitHub вверх по течению: модуль ядра | общий заголовок | user user.

Самой досадной частью было понимание того, что некоторые из слабых идентификаторов захвачены: модуль ядра , вы должны использовать макросы _IOx.

Модуль ядра :

#include <asm/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/printk.h> /* printk */

#include "ioctl.h"

MODULE_LICENSE("GPL");

static struct dentry *dir;

static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp)
{
    void __user *arg_user;
    union {
        int i;
        lkmc_ioctl_struct s;
    } arg_kernel;

    arg_user = (void __user *)argp;
    pr_info("cmd = %x\n", cmd);
    switch (cmd) {
        case LKMC_IOCTL_INC:
            if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) {
                return -EFAULT;
            }
            pr_info("0 arg = %d\n", arg_kernel.i);
            arg_kernel.i += 1;
            if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) {
                return -EFAULT;
            }
        break;
        case LKMC_IOCTL_INC_DEC:
            if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) {
                return -EFAULT;
            }
            pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j);
            arg_kernel.s.i += 1;
            arg_kernel.s.j -= 1;
            if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) {
                return -EFAULT;
            }
        break;
        default:
            return -EINVAL;
        break;
    }
    return 0;
}

static const struct file_operations fops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = unlocked_ioctl
};

static int myinit(void)
{
    dir = debugfs_create_dir("lkmc_ioctl", 0);
    /* ioctl permissions are not automatically restricted by rwx as for read / write,
     * but we could of course implement that ourselves:
     * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */
    debugfs_create_file("f", 0, dir, NULL, &fops);
    return 0;
}

static void myexit(void)
{
    debugfs_remove_recursive(dir);
}

module_init(myinit)
module_exit(myexit)

Общий заголовок:

#ifndef IOCTL_H
#define IOCTL_H

#include <linux/ioctl.h>

typedef struct {
    int i;
    int j;
} lkmc_ioctl_struct;
#define LKMC_IOCTL_MAGIC 0x33
#define LKMC_IOCTL_INC     _IOWR(LKMC_IOCTL_MAGIC, 0, int)
#define LKMC_IOCTL_INC_DEC _IOWR(LKMC_IOCTL_MAGIC, 1, lkmc_ioctl_struct)

#endif

Userland:

#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "../ioctl.h"

int main(int argc, char **argv)
{
    int fd, arg_int, ret;
    lkmc_ioctl_struct arg_struct;

    if (argc < 2) {
        puts("Usage: ./prog <ioctl-file>");
        return EXIT_FAILURE;
    }
    fd = open(argv[1], O_RDONLY);
    if (fd == -1) {
        perror("open");
        return EXIT_FAILURE;
    }
    /* 0 */
    {
        arg_int = 1;
        ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int);
        if (ret == -1) {
            perror("ioctl");
            return EXIT_FAILURE;
        }
        printf("arg = %d\n", arg_int);
        printf("ret = %d\n", ret);
        printf("errno = %d\n", errno);
    }
    puts("");
    /* 1 */
    {
        arg_struct.i = 1;
        arg_struct.j = 1;
        ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct);
        if (ret == -1) {
            perror("ioctl");
            return EXIT_FAILURE;
        }
        printf("arg = %d %d\n", arg_struct.i, arg_struct.j);
        printf("ret = %d\n", ret);
        printf("errno = %d\n", errno);
    }
    close(fd);
    return EXIT_SUCCESS;
}
0
ответ дан 25 May 2018 в 19:41

Минимальный runnable пример

Проверено в полностью воспроизводимой среде QEMU + Buildroot, поэтому может помочь другим получить работу ioctl. GitHub вверх по течению: модуль ядра | общий заголовок | user user.

Самой досадной частью было понимание того, что некоторые из слабых идентификаторов захвачены: модуль ядра , вы должны использовать макросы _IOx.

Модуль ядра :

#include <asm/uaccess.h> /* copy_from_user, copy_to_user */ #include <linux/debugfs.h> #include <linux/module.h> #include <linux/printk.h> /* printk */ #include "ioctl.h" MODULE_LICENSE("GPL"); static struct dentry *dir; static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp) { void __user *arg_user; union { int i; lkmc_ioctl_struct s; } arg_kernel; arg_user = (void __user *)argp; pr_info("cmd = %x\n", cmd); switch (cmd) { case LKMC_IOCTL_INC: if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) { return -EFAULT; } pr_info("0 arg = %d\n", arg_kernel.i); arg_kernel.i += 1; if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) { return -EFAULT; } break; case LKMC_IOCTL_INC_DEC: if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) { return -EFAULT; } pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j); arg_kernel.s.i += 1; arg_kernel.s.j -= 1; if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) { return -EFAULT; } break; default: return -EINVAL; break; } return 0; } static const struct file_operations fops = { .owner = THIS_MODULE, .unlocked_ioctl = unlocked_ioctl }; static int myinit(void) { dir = debugfs_create_dir("lkmc_ioctl", 0); /* ioctl permissions are not automatically restricted by rwx as for read / write, * but we could of course implement that ourselves: * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */ debugfs_create_file("f", 0, dir, NULL, &fops); return 0; } static void myexit(void) { debugfs_remove_recursive(dir); } module_init(myinit) module_exit(myexit)

Общий заголовок:

#ifndef IOCTL_H #define IOCTL_H #include <linux/ioctl.h> typedef struct { int i; int j; } lkmc_ioctl_struct; #define LKMC_IOCTL_MAGIC 0x33 #define LKMC_IOCTL_INC _IOWR(LKMC_IOCTL_MAGIC, 0, int) #define LKMC_IOCTL_INC_DEC _IOWR(LKMC_IOCTL_MAGIC, 1, lkmc_ioctl_struct) #endif

Userland:

#define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "../ioctl.h" int main(int argc, char **argv) { int fd, arg_int, ret; lkmc_ioctl_struct arg_struct; if (argc < 2) { puts("Usage: ./prog <ioctl-file>"); return EXIT_FAILURE; } fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); return EXIT_FAILURE; } /* 0 */ { arg_int = 1; ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d\n", arg_int); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } puts(""); /* 1 */ { arg_struct.i = 1; arg_struct.j = 1; ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d %d\n", arg_struct.i, arg_struct.j); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } close(fd); return EXIT_SUCCESS; }
0
ответ дан 25 July 2018 в 21:33

Минимальный runnable пример

Проверено в полностью воспроизводимой среде QEMU + Buildroot, поэтому может помочь другим получить работу ioctl. GitHub вверх по течению: модуль ядра | общий заголовок | user user.

Самой досадной частью было понимание того, что некоторые из слабых идентификаторов захвачены: модуль ядра , вы должны использовать макросы _IOx.

Модуль ядра :

#include <asm/uaccess.h> /* copy_from_user, copy_to_user */ #include <linux/debugfs.h> #include <linux/module.h> #include <linux/printk.h> /* printk */ #include "ioctl.h" MODULE_LICENSE("GPL"); static struct dentry *dir; static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp) { void __user *arg_user; union { int i; lkmc_ioctl_struct s; } arg_kernel; arg_user = (void __user *)argp; pr_info("cmd = %x\n", cmd); switch (cmd) { case LKMC_IOCTL_INC: if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) { return -EFAULT; } pr_info("0 arg = %d\n", arg_kernel.i); arg_kernel.i += 1; if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) { return -EFAULT; } break; case LKMC_IOCTL_INC_DEC: if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) { return -EFAULT; } pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j); arg_kernel.s.i += 1; arg_kernel.s.j -= 1; if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) { return -EFAULT; } break; default: return -EINVAL; break; } return 0; } static const struct file_operations fops = { .owner = THIS_MODULE, .unlocked_ioctl = unlocked_ioctl }; static int myinit(void) { dir = debugfs_create_dir("lkmc_ioctl", 0); /* ioctl permissions are not automatically restricted by rwx as for read / write, * but we could of course implement that ourselves: * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */ debugfs_create_file("f", 0, dir, NULL, &fops); return 0; } static void myexit(void) { debugfs_remove_recursive(dir); } module_init(myinit) module_exit(myexit)

Общий заголовок:

#ifndef IOCTL_H #define IOCTL_H #include <linux/ioctl.h> typedef struct { int i; int j; } lkmc_ioctl_struct; #define LKMC_IOCTL_MAGIC 0x33 #define LKMC_IOCTL_INC _IOWR(LKMC_IOCTL_MAGIC, 0, int) #define LKMC_IOCTL_INC_DEC _IOWR(LKMC_IOCTL_MAGIC, 1, lkmc_ioctl_struct) #endif

Userland:

#define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "../ioctl.h" int main(int argc, char **argv) { int fd, arg_int, ret; lkmc_ioctl_struct arg_struct; if (argc < 2) { puts("Usage: ./prog <ioctl-file>"); return EXIT_FAILURE; } fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); return EXIT_FAILURE; } /* 0 */ { arg_int = 1; ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d\n", arg_int); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } puts(""); /* 1 */ { arg_struct.i = 1; arg_struct.j = 1; ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d %d\n", arg_struct.i, arg_struct.j); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } close(fd); return EXIT_SUCCESS; }
0
ответ дан 31 July 2018 в 13:39

Минимальный runnable пример

Проверено в полностью воспроизводимой среде QEMU + Buildroot, поэтому может помочь другим получить работу ioctl. GitHub вверх по течению: модуль ядра | общий заголовок | user user.

Самой досадной частью было понимание того, что некоторые из слабых идентификаторов захвачены: модуль ядра , вы должны использовать макросы _IOx.

Модуль ядра :

#include <asm/uaccess.h> /* copy_from_user, copy_to_user */ #include <linux/debugfs.h> #include <linux/module.h> #include <linux/printk.h> /* printk */ #include "ioctl.h" MODULE_LICENSE("GPL"); static struct dentry *dir; static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp) { void __user *arg_user; union { int i; lkmc_ioctl_struct s; } arg_kernel; arg_user = (void __user *)argp; pr_info("cmd = %x\n", cmd); switch (cmd) { case LKMC_IOCTL_INC: if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) { return -EFAULT; } pr_info("0 arg = %d\n", arg_kernel.i); arg_kernel.i += 1; if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) { return -EFAULT; } break; case LKMC_IOCTL_INC_DEC: if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) { return -EFAULT; } pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j); arg_kernel.s.i += 1; arg_kernel.s.j -= 1; if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) { return -EFAULT; } break; default: return -EINVAL; break; } return 0; } static const struct file_operations fops = { .owner = THIS_MODULE, .unlocked_ioctl = unlocked_ioctl }; static int myinit(void) { dir = debugfs_create_dir("lkmc_ioctl", 0); /* ioctl permissions are not automatically restricted by rwx as for read / write, * but we could of course implement that ourselves: * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */ debugfs_create_file("f", 0, dir, NULL, &fops); return 0; } static void myexit(void) { debugfs_remove_recursive(dir); } module_init(myinit) module_exit(myexit)

Общий заголовок:

#ifndef IOCTL_H #define IOCTL_H #include <linux/ioctl.h> typedef struct { int i; int j; } lkmc_ioctl_struct; #define LKMC_IOCTL_MAGIC 0x33 #define LKMC_IOCTL_INC _IOWR(LKMC_IOCTL_MAGIC, 0, int) #define LKMC_IOCTL_INC_DEC _IOWR(LKMC_IOCTL_MAGIC, 1, lkmc_ioctl_struct) #endif

Userland:

#define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "../ioctl.h" int main(int argc, char **argv) { int fd, arg_int, ret; lkmc_ioctl_struct arg_struct; if (argc < 2) { puts("Usage: ./prog <ioctl-file>"); return EXIT_FAILURE; } fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); return EXIT_FAILURE; } /* 0 */ { arg_int = 1; ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d\n", arg_int); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } puts(""); /* 1 */ { arg_struct.i = 1; arg_struct.j = 1; ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d %d\n", arg_struct.i, arg_struct.j); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } close(fd); return EXIT_SUCCESS; }
0
ответ дан 2 August 2018 в 03:10

Минимальный runnable пример

Проверено в полностью воспроизводимой среде QEMU + Buildroot, поэтому может помочь другим получить работу ioctl. GitHub вверх по течению: модуль ядра | общий заголовок | user user.

Самой досадной частью было понимание того, что некоторые из слабых идентификаторов захвачены: модуль ядра , вы должны использовать макросы _IOx.

Модуль ядра :

#include <asm/uaccess.h> /* copy_from_user, copy_to_user */ #include <linux/debugfs.h> #include <linux/module.h> #include <linux/printk.h> /* printk */ #include "ioctl.h" MODULE_LICENSE("GPL"); static struct dentry *dir; static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp) { void __user *arg_user; union { int i; lkmc_ioctl_struct s; } arg_kernel; arg_user = (void __user *)argp; pr_info("cmd = %x\n", cmd); switch (cmd) { case LKMC_IOCTL_INC: if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) { return -EFAULT; } pr_info("0 arg = %d\n", arg_kernel.i); arg_kernel.i += 1; if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) { return -EFAULT; } break; case LKMC_IOCTL_INC_DEC: if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) { return -EFAULT; } pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j); arg_kernel.s.i += 1; arg_kernel.s.j -= 1; if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) { return -EFAULT; } break; default: return -EINVAL; break; } return 0; } static const struct file_operations fops = { .owner = THIS_MODULE, .unlocked_ioctl = unlocked_ioctl }; static int myinit(void) { dir = debugfs_create_dir("lkmc_ioctl", 0); /* ioctl permissions are not automatically restricted by rwx as for read / write, * but we could of course implement that ourselves: * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */ debugfs_create_file("f", 0, dir, NULL, &fops); return 0; } static void myexit(void) { debugfs_remove_recursive(dir); } module_init(myinit) module_exit(myexit)

Общий заголовок:

#ifndef IOCTL_H #define IOCTL_H #include <linux/ioctl.h> typedef struct { int i; int j; } lkmc_ioctl_struct; #define LKMC_IOCTL_MAGIC 0x33 #define LKMC_IOCTL_INC _IOWR(LKMC_IOCTL_MAGIC, 0, int) #define LKMC_IOCTL_INC_DEC _IOWR(LKMC_IOCTL_MAGIC, 1, lkmc_ioctl_struct) #endif

Userland:

#define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "../ioctl.h" int main(int argc, char **argv) { int fd, arg_int, ret; lkmc_ioctl_struct arg_struct; if (argc < 2) { puts("Usage: ./prog <ioctl-file>"); return EXIT_FAILURE; } fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); return EXIT_FAILURE; } /* 0 */ { arg_int = 1; ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d\n", arg_int); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } puts(""); /* 1 */ { arg_struct.i = 1; arg_struct.j = 1; ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d %d\n", arg_struct.i, arg_struct.j); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } close(fd); return EXIT_SUCCESS; }
0
ответ дан 4 August 2018 в 19:03

Минимальный runnable пример

Проверено в полностью воспроизводимой среде QEMU + Buildroot, поэтому может помочь другим получить работу ioctl. GitHub вверх по течению: модуль ядра | общий заголовок | user user.

Самой досадной частью было понимание того, что некоторые из слабых идентификаторов захвачены: модуль ядра , вы должны использовать макросы _IOx.

Модуль ядра :

#include <asm/uaccess.h> /* copy_from_user, copy_to_user */ #include <linux/debugfs.h> #include <linux/module.h> #include <linux/printk.h> /* printk */ #include "ioctl.h" MODULE_LICENSE("GPL"); static struct dentry *dir; static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp) { void __user *arg_user; union { int i; lkmc_ioctl_struct s; } arg_kernel; arg_user = (void __user *)argp; pr_info("cmd = %x\n", cmd); switch (cmd) { case LKMC_IOCTL_INC: if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) { return -EFAULT; } pr_info("0 arg = %d\n", arg_kernel.i); arg_kernel.i += 1; if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) { return -EFAULT; } break; case LKMC_IOCTL_INC_DEC: if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) { return -EFAULT; } pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j); arg_kernel.s.i += 1; arg_kernel.s.j -= 1; if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) { return -EFAULT; } break; default: return -EINVAL; break; } return 0; } static const struct file_operations fops = { .owner = THIS_MODULE, .unlocked_ioctl = unlocked_ioctl }; static int myinit(void) { dir = debugfs_create_dir("lkmc_ioctl", 0); /* ioctl permissions are not automatically restricted by rwx as for read / write, * but we could of course implement that ourselves: * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */ debugfs_create_file("f", 0, dir, NULL, &fops); return 0; } static void myexit(void) { debugfs_remove_recursive(dir); } module_init(myinit) module_exit(myexit)

Общий заголовок:

#ifndef IOCTL_H #define IOCTL_H #include <linux/ioctl.h> typedef struct { int i; int j; } lkmc_ioctl_struct; #define LKMC_IOCTL_MAGIC 0x33 #define LKMC_IOCTL_INC _IOWR(LKMC_IOCTL_MAGIC, 0, int) #define LKMC_IOCTL_INC_DEC _IOWR(LKMC_IOCTL_MAGIC, 1, lkmc_ioctl_struct) #endif

Userland:

#define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "../ioctl.h" int main(int argc, char **argv) { int fd, arg_int, ret; lkmc_ioctl_struct arg_struct; if (argc < 2) { puts("Usage: ./prog <ioctl-file>"); return EXIT_FAILURE; } fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); return EXIT_FAILURE; } /* 0 */ { arg_int = 1; ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d\n", arg_int); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } puts(""); /* 1 */ { arg_struct.i = 1; arg_struct.j = 1; ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d %d\n", arg_struct.i, arg_struct.j); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } close(fd); return EXIT_SUCCESS; }
0
ответ дан 6 August 2018 в 03:22

Минимальный runnable пример

Проверено в полностью воспроизводимой среде QEMU + Buildroot, поэтому может помочь другим получить работу ioctl. GitHub вверх по течению: модуль ядра | общий заголовок | user user.

Самой досадной частью было понимание того, что некоторые из слабых идентификаторов захвачены: модуль ядра , вы должны использовать макросы _IOx.

Модуль ядра :

#include <asm/uaccess.h> /* copy_from_user, copy_to_user */ #include <linux/debugfs.h> #include <linux/module.h> #include <linux/printk.h> /* printk */ #include "ioctl.h" MODULE_LICENSE("GPL"); static struct dentry *dir; static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp) { void __user *arg_user; union { int i; lkmc_ioctl_struct s; } arg_kernel; arg_user = (void __user *)argp; pr_info("cmd = %x\n", cmd); switch (cmd) { case LKMC_IOCTL_INC: if (copy_from_user(&arg_kernel.i, arg_user, sizeof(arg_kernel.i))) { return -EFAULT; } pr_info("0 arg = %d\n", arg_kernel.i); arg_kernel.i += 1; if (copy_to_user(arg_user, &arg_kernel.i, sizeof(arg_kernel.i))) { return -EFAULT; } break; case LKMC_IOCTL_INC_DEC: if (copy_from_user(&arg_kernel.s, arg_user, sizeof(arg_kernel.s))) { return -EFAULT; } pr_info("1 arg = %d %d\n", arg_kernel.s.i, arg_kernel.s.j); arg_kernel.s.i += 1; arg_kernel.s.j -= 1; if (copy_to_user(arg_user, &arg_kernel.s, sizeof(arg_kernel.s))) { return -EFAULT; } break; default: return -EINVAL; break; } return 0; } static const struct file_operations fops = { .owner = THIS_MODULE, .unlocked_ioctl = unlocked_ioctl }; static int myinit(void) { dir = debugfs_create_dir("lkmc_ioctl", 0); /* ioctl permissions are not automatically restricted by rwx as for read / write, * but we could of course implement that ourselves: * https://stackoverflow.com/questions/29891803/user-permission-check-on-ioctl-command */ debugfs_create_file("f", 0, dir, NULL, &fops); return 0; } static void myexit(void) { debugfs_remove_recursive(dir); } module_init(myinit) module_exit(myexit)

Общий заголовок:

#ifndef IOCTL_H #define IOCTL_H #include <linux/ioctl.h> typedef struct { int i; int j; } lkmc_ioctl_struct; #define LKMC_IOCTL_MAGIC 0x33 #define LKMC_IOCTL_INC _IOWR(LKMC_IOCTL_MAGIC, 0, int) #define LKMC_IOCTL_INC_DEC _IOWR(LKMC_IOCTL_MAGIC, 1, lkmc_ioctl_struct) #endif

Userland:

#define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "../ioctl.h" int main(int argc, char **argv) { int fd, arg_int, ret; lkmc_ioctl_struct arg_struct; if (argc < 2) { puts("Usage: ./prog <ioctl-file>"); return EXIT_FAILURE; } fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); return EXIT_FAILURE; } /* 0 */ { arg_int = 1; ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d\n", arg_int); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } puts(""); /* 1 */ { arg_struct.i = 1; arg_struct.j = 1; ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct); if (ret == -1) { perror("ioctl"); return EXIT_FAILURE; } printf("arg = %d %d\n", arg_struct.i, arg_struct.j); printf("ret = %d\n", ret); printf("errno = %d\n", errno); } close(fd); return EXIT_SUCCESS; }
0
ответ дан 7 August 2018 в 21:08

Другие вопросы по тегам:

Похожие вопросы: