12335

Initializing a member of a struct to a function pointer without knowing the returned type

Question:

I have this struct:

typedef struct xyz_data { void *myfa; <------- correct void *myfb; <------- incorrect }

and this function definition:

asmlinkage ssize_t (*real_sys_read)(unsigned int fd, char __user *buf, size_t count); asmlinkage ssize_t hooked_sys_read(unsigned int fd, char __user *buf, size_t count);

(as you might be guessing, this will point to the kernel's __NR_read).

Saving hooked_sys_read to *myfa; is as simple as xyz_data_something->myfa = hooked_sys_read, but what about myfb? I'm not sure xyz_data_something->myfb = &real_sys_read will work.

I'm hijacking some syscalls (If you're interested in the project, everything is available in GitHub) and each hijacked syscall will use that struct to call the real syscall it belongs to (which will be accessed via *myfb), making use of the returned value.

Keep in mind that each syscall has it's own return type.

Answer1:

<h3>Scenario</h3> typedef struct xyz_data { void *myfa; void *myfb; } xyz_data; // Type name assumed — not specified in question asmlinkage ssize_t (*real_sys_read)(unsigned int fd, char __user *buf, size_t count); asmlinkage ssize_t hooked_sys_read(unsigned int fd, char __user *buf, size_t count); xyz_data *xyz_data_something = ...; xyz_data_something->myfa = hooked_sys_read; xyz_data_something->myfb = &real_sys_read; <h3>Analysis</h3>

What you wrote is not type-safe (so the compiler can't help you much), but you are taking the address of the variable that holds the pointer to the 'real sys read' function, not a copy of that pointer (because of the &). You can apply & (and *) to function names willy-nilly and they all end up the same:

reader->myfa = &hooked_sys_read; reader->myfa = hooked_sys_read; reader->myfa = *hooked_sys_read; reader->myfa = **hooked_sys_read; reader->myfa = ***hooked_sys_read; reader->myfa = ****hooked_sys_read;

You can't do that with pointers to functions. Note that the compiler cannot even diagnose a 'function pointer assigned to object pointer' problem when you do:

xyz_data_something->myfb = &real_sys_read;

You are assigning the address of a (function) pointer variable to a void *, so you are assigning an object pointer to a void pointer, which is legitimate — but incorrect.

<h3>Synthesis</h3>

You should have one of these two function-type typedefs:

typedef ssize_t ReadFunction(unsigned int fd, char __user *data, size_t size); typedef ssize_t (*ReadPointer)(unsigned int fd, char __user *data, size_t size);

Then your structure can be either:

typedef struct xyz_data { ReadFunction *myfa; ReadFunction *myfb; } xyz_data;

Or:

typedef struct xyz_data { ReadPointer myfa; ReadPointer myfb; } xyz_data;

Given a structure pointer:

xyz_data *reader = ...;

The following assignments will compile cleanly and work correctly (for both structure types):

reader->myfa = hooked_sys_read; reader->myfb = real_sys_read; <h3>Proof of Concept</h3> #include <sys/types.h> #define asmlinkage #define __user asmlinkage ssize_t (*real_sys_read)(unsigned int fd, char __user *buf, size_t count); asmlinkage ssize_t hooked_sys_read(unsigned int fd, char __user *buf, size_t count); typedef ssize_t (*ReadPointer)(unsigned int fd, char __user *data, size_t size); typedef struct xyz_data { ReadPointer myfa; ReadPointer myfb; } xyz_data; extern xyz_data getter(void); xyz_data getter(void) { xyz_data data; xyz_data *reader = &data; reader->myfa = hooked_sys_read; reader->myfb = real_sys_read; // The next line fails to compile: assignment from incompatible pointer type // reader->myfb = &real_sys_read; reader->myfa = &hooked_sys_read; reader->myfa = hooked_sys_read; reader->myfa = *hooked_sys_read; reader->myfa = **hooked_sys_read; reader->myfa = ***hooked_sys_read; reader->myfa = ****hooked_sys_read; return *reader; }

It compiles cleanly. It isn't good code, though — the repeated assignments alone are enough to make it bad.

Answer2:

You should not be assigning a function pointer to a void pointer.

See <a href="https://stackoverflow.com/a/5579907/1351983" rel="nofollow">https://stackoverflow.com/a/5579907/1351983</a>.

Recommend

  • Vanilla JS: delay click event to add animation
  • Inline YouTube video in Ionic/Cordova/PhoneGap app on iOS/iPhone
  • Restricted Function with libsandbox and pysandbox
  • How to get the file length in C on Linux?
  • C++ io streams versus mmap
  • Storing session data in cookies
  • how avoid Anaconda to hijack pip
  • In C on Unix, how can a process tell what permissions it has to a file without opening it?
  • Initializing a member of a struct to a function pointer without knowing the returned type
  • How to prevent row selection on tree_mode node collapse in free-jqgrid?
  • Why WIFSIGNALED(status) fail to detect signals while tracing a process with ptrace?
  • Adding new IOCTL's into kernel (number range)
  • What is the right approach to encapsulate platform specific code in Go?
  • filename of memory mapped libraries osx
  • What causes amqp.node to get ECONNRESET from a RabbitMQ server?
  • Keyboard setup for Eclipse on Mac
  • How I access HttpContext.GetGlobalResourceObject() in javascript(.js) file which is used in my appli
  • Avoid Inheriting Super Class Tests in ScalaTest
  • How to make stdcall from Go
  • CSS how to fix an element to scroll horizontally with the page but not vertically?
  • Can my PDF ping my server when it is opened?
  • Django Haystack Rebuild Index
  • Does Apportable support to build library binary (.a/.so)?
  • How to retrieve information from antrun back to maven?
  • Jenkins: FATAL: Could not initialize class hudson.util.ProcessTree$UnixReflection
  • Get history of file changes from TFS to implement custom “blame”-behaviour of exceptions
  • Switching to Release Build causes runtime error in Web Reference
  • Shallow update not allowed (git > 1.9)
  • QuartzCore.framework for Mono Develop
  • How do I rollback to a specific git commit
  • Revoking OAuth Access Token Results in 404 Not Found