0

I am new to kernel driver development and I am trying update kernel version of a legacy project.

Example code is below

#include <linux/uaccess.h>

struct file *file_open(const char *path, int flags, int rights)
{
    struct file *filptr = NULL;
    int err = 0;
    oldfs = get_fs();
    set_fs(get_ds());
    filptr = filp_open(path, flags, rights);
    if (IS_ERR(filptr)) {
        err = PTR_ERR(filptr);
        return NULL;
     }
    return filptr;
}

void file_close(struct file *file)
{
    int retval = filp_close(file, NULL);
    printk("file_close retval: %d\n",retval);
    set_fs(oldfs);
}

I am having below implicit declaration of get_fs() and set_fs() macros.

/driver.c: In function 'file_open':
/driver.c:593:27: error: implicit declaration of function 'get_fs'; did you mean 'get_bh'? [-Werror=implicit-function-declaration]
  593 |     oldfs = (mm_segment_t)get_fs();
      |                           ^~~~~~
      |                           get_bh
/driver.c:593:5: error: conversion to non-scalar type requested
  593 |     oldfs = (mm_segment_t)get_fs();
      |     ^~~~~
/driver.c:594:5: error: implicit declaration of function 'set_fs'; did you mean 'sget_fc'? [-Werror=implicit-function-declaration]
  594 |     set_fs(get_ds());
      |     ^~~~~~
      |     sget_fc
/driver.c:594:12: error: implicit declaration of function 'get_ds'; did you mean 'get_bh'? [-Werror=implicit-function-declaration]
  594 |     set_fs(get_ds());
      |            ^~~~~~

get_fs() and set_fs() macros have been removed from arm architecture <asm/uaccess.h> user access header file. But they are still defined in <asm-generic/uaccess.h> header. I couldn't find if it is proper to use generic user access apis in <asm-generic/uaccess.h> header file. If include both headers, I get redefinition warnings and errors.

./include/asm-generic/uaccess.h:129: warning: "access_ok" redefined
  129 | #define access_ok(addr, size) __access_ok((unsigned long)(addr),(size))
      | 
In file included from ./include/linux/uaccess.h:11,
                 from ./include/linux/sched/task.h:11,
                 from ./include/linux/sched/signal.h:9,
                 from ./include/linux/rcuwait.h:6,
                 from ./include/linux/percpu-rwsem.h:7,
                 from ./include/linux/fs.h:33,
                 from ./include/linux/highmem.h:5,
                 from ./include/linux/bvec.h:10,
                 from ./include/linux/blk_types.h:10,
                 from ./include/linux/genhd.h:19,
                 from ./include/linux/blkdev.h:8,
                 from driver.c:6:
./arch/arm/include/asm/uaccess.h:251: note: this is the location of the previous definition
  251 | #define access_ok(addr, size)   (__range_ok(addr, size) == 0)
      | 
./include/asm-generic/uaccess.h:148: warning: "__put_user" redefined
  148 | #define __put_user(x, ptr) \
      | 
./arch/arm/include/asm/uaccess.h:378: note: this is the location of the previous definition
  378 | #define __put_user(x, ptr) put_user(x, ptr)
      | 
./include/asm-generic/uaccess.h:168: warning: "put_user" redefined
  168 | #define put_user(x, ptr)                                        \
      | 
./arch/arm/include/asm/uaccess.h:366: note: this is the location of the previous definition
  366 | #define put_user(x, ptr)                                                \
      | 
./include/asm-generic/uaccess.h:190: warning: "__get_user" redefined
  190 | #define __get_user(x, ptr)                                      \
      | 
./arch/arm/include/asm/uaccess.h:260: note: this is the location of the previous definition
  260 | #define __get_user(x, ptr) get_user(x, ptr)
      | 
./include/asm-generic/uaccess.h:230: warning: "get_user" redefined
  230 | #define get_user(x, ptr)                                        \
      | 
./arch/arm/include/asm/uaccess.h:213: note: this is the location of the previous definition
  213 | #define get_user(x, p)                                                  \
      | 
./include/asm-generic/uaccess.h:256:1: error: redefinition of '__clear_user'
  256 | __clear_user(void __user *to, unsigned long n)
      | ^~~~~~~~~~~~
./arch/arm/include/asm/uaccess.h:562:1: note: previous definition of '__clear_user' with type 'long unsigned int(void *, long unsigned int)'
  562 | __clear_user(void __user *addr, unsigned long n)
      | ^~~~~~~~~~~~
./include/asm-generic/uaccess.h:264:1: error: redefinition of 'clear_user'
  264 | clear_user(void __user *to, unsigned long n)
      | ^~~~~~~~~~
./arch/arm/include/asm/uaccess.h:588:42: note: previous definition of 'clear_user' with type 'long unsigned int(void *, long unsigned int)'
  588 | static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
      |                                          ^~~~~~~~~~

So as I understood, for arm architecture only one header must be included. After kernel version 4.11 recommended way to include architecture specific headers is with <linux/uaccess.h> header. And this header includes <asm/uaccess.h>. So I infer <asm-generic/uaccess.h> should not included directly.

But other architectures still have get_fs() and set_fs() macros available in their headers.

As I understand these macros are setter/getter for thread address space defined in thread_info structure. But arm architecture's struct thread_info definition does not define this field.

I would like to ask if these macros usage is deprecated for arm arch. Is there any way to access thread adress space for arm architecture. Where should I look, any hint is appreciated.

selim
  • 11
  • 1
  • Opening a file from within the kernel is a big mistake. Fix that, and the rest become unneeded. – 0andriy Jun 04 '22 at 09:32
  • @0andriy thank you for answer, this file is xilinx character device to program its PL. And it has been deprecated since 2018.1 release. As you suggested, it seems right thing is fix file operations. Though I am looking for quick fix, as I understand there is no work around to use these macros. – selim Jun 06 '22 at 05:53

0 Answers0