1

私はこの構造体を持っています:

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

そしてこの関数定義:

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);

(ご想像のとおり、これはカーネルの を指します__NR_read)。

への保存hooked_sys_read*myfa;と同じくらい簡単ですxyz_data_something->myfa = hooked_sys_readが、ではどうmyfbでしょうか? うまくいくかどうかわかりませんxyz_data_something->myfb = &real_sys_read

私はいくつかの syscall をハイジャックしています (プロジェクトに興味がある場合は、すべて GitHub で入手できます)。ハイジャックされた各 syscall は、その構造体を使用して、それが属する実際の syscall を呼び出します (これは 経由でアクセスされます*myfb)。戻り値。

各システムコールには独自の戻り値の型があることに注意してください。

4

2 に答える 2

2

シナリオ

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;

分析

あなたが書いたものはタイプセーフではありません(そのため、コンパイラはあまり役に立ちません)が、そのポインターのコピーではなく、「実際のsys read」関数へのポインターを保持する変数のアドレスを取得しています(の&)。&(and *) を関数名に無条件に適用でき、それらはすべて同じ結果になります。

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;

関数へのポインターではそれを行うことはできません。次の場合、コンパイラは「オブジェクトポインタに割り当てられた関数ポインタ」の問題を診断することさえできないことに注意してください。

xyz_data_something->myfb = &real_sys_read;

(関数) ポインター変数のアドレスを に割り当てているvoid *ため、オブジェクト ポインターを void ポインターに割り当てていますが、これは正当ですが、正しくありません。

合成

次の 2 つの関数型 typedef のいずれかが必要です。

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);

次に、構造は次のいずれかになります。

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

または:

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

構造体ポインターを指定すると、次のようになります。

xyz_data *reader = ...;

次の割り当ては、きれいにコンパイルされ、正しく動作します (両方の構造体タイプに対して)。

reader->myfa = hooked_sys_read;
reader->myfb = real_sys_read;

コンセプトの証明

#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;
}

きれいにコンパイルされます。ただし、これは良いコードではありません — 代入を繰り返すだけで、コードが悪くなります。

于 2013-09-15T19:16:20.143 に答える
1

関数ポインターを void ポインターに割り当てるべきではありません。

https://stackoverflow.com/a/5579907/1351983を参照してください。

于 2013-09-15T17:54:44.767 に答える