8

カーネル モジュール (Linux では C) を作成していますが、その中の他のファイルのアクセス許可を変更したいと考えています。解決策はありますか?私はカーネルにいるので、chmod syscallを使用できません...助けてくれてありがとう

これは私の Makefile です:

> obj-m += ca.o
> 
>     all:
>       make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
>     
>     clean:
>       make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

そして、これは私のコードです:

> #include <linux/string.h>
> #include <linux/mm.h>
> /* Snip, tons of includes (all of them :))*/
> #include <linux/delay.h> .... int procfile_write(struct file *file,
> const char *buffer, unsigned long
> count,
>          void *data) { ...    sys_chmod(path, per); ... } ...

作るときに警告が表示されます:

WARNING: "sys_chmod" [file] undefiened

モジュールを「sudo insmod」でロードすると、次のエラーが発生します。

Unknown sybol in module

このエラーは、特にカーネル モジュールで発生するようです。何か案が?再びありがとう!

4

2 に答える 2

5

スタックオーバーフローへようこそ! あなたが望むIIRCsys_chmod()

Linux カーネルのメーリング リストから

2003 年 2 月 20 日木曜日、午後 11 時 10 分 27 秒 +0100 に、Andrea Arcangeli は次のように書いています。

2003 年 2 月 20 日木曜日、午後 11 時 4 分 37 秒 +0530 に、プラサードは次のように書いています。

カーネル空間でシステムコールを呼び出す方法はありますか? syscall は、別のプロセスとして偽装して実行されます。実際の

sys_whatever() を呼び出します。例については、カーネル コードを参照してください。

カーネルはすでにさまざまな場所でこれを行っています。sys_read、sys_write、open_filp、sys_close、およびその他の関数は、カーネル コードから安全に呼び出すことができますが、推奨されません。init/do_mounts.c は特に厄介なケースであり、klibc をマージする必要がある大きな理由です。システムコールは、カーネルではなくユーザー空間から行う必要があります。

これはカーネルで行うようなことではないため、人々は心配し始めています (慣れていない限り、何をしているのかわかっています)。特定のイベントの権限を変更したいだけの場合は、inotifyなどを使用してユーザー空間から行います。

免責事項:

これは、sys_* 呼び出しを使用する別のカーネル モジュールで見つけたコードです。

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/syscalls.h>
/* Snip */

int openflags = O_WRONLY|O_CREAT;
if (ml != 1)
        openflags |= O_TRUNC;
wfd = sys_open(collected, openflags, mode);

if (wfd >= 0) {
    sys_fchown(wfd, uid, gid);
    sys_fchmod(wfd, mode);
    state = CopyFile;
}

また見つけた:

asmlinkage long sys_rename(const char __user *oldname, const char __user *newname);
asmlinkage long sys_chmod(const char __user *filename, mode_t mode);
asmlinkage long sys_fchmod(unsigned int fd, mode_t mode);

include/linux/syscalls.h

気にしておいてください、私がカーネル関連の作業を行ってからしばらく経ちました。これが chmod 用の適切なインターフェイスであること、たとえばセキュリティ フックを実装する可能性のある他の呼び出しをショートカットしていないことを確認してください。

また、このリンクには、システムコールとそのシンボルに関する情報が含まれています。また、ここでは、ユーザー空間 API システム コールのクイック リファレンスと、それらがカーネルに実装されている場所を示します。

于 2009-08-28T17:48:22.760 に答える
3

システムコールはエクスポートされたシンボルではありません。それらが必要な場合は、少しハッキングする必要があります。

あなたはあなたの指を手に入れたいですsys_call_table。これには、すべてのシステムコールへのポインターが含まれています。古いカーネルを見てくださいarch/x86/kernel/syscall_table_32.Sarch/i386/kernel/entry.S

このテーブルのベースアドレスを見つけることができますgrep sys_call_table /usr/src/linux/System.map(または/proc/kallsymsシンボルがエクスポートされている場合)。このアドレスをモジュールのパラメーターとして使用できます (16 進文字列をポインターに変換する必要があります)。

arch/x86/include/asm/unistd_32.hで(またはinclude/asm-i386/unistd.h古いカーネルで)定義されたオフセットを使用して、適切なシステムコールを呼び出すことができます。次のようなものが得られます。#define __NR_chmod 15

マクロは役に立ちます:

#define DO_SYSCALL_2(sc, t1, a1, t2, a2)                       \
    (((asmlinkage long (*)(t1, t2)) sys_call_table[__NR_##sc]) (a1, a2));
#define USER_SYSCALL_2(sc, t1, a1, t2, a2)                     \
    static inline asmlinkage long syscall_##sc(t1 a1, t2 a2)   \
    { return DO_SYSCALL_2(sc, t1, a1, t2, a2) }

USER_SYSCALL_2(chmod, const char __user *, filename, mode_t, mode);
int my_code(void) { return syscall_chmod(arg1, arg2); }

また、ユーザー バッファーであるはずのカーネル バッファー (たとえば、ファイル名) を渡す場合は、データ セグメントを変更することを忘れないでください。

mm_segment_t oldfs = get_fs(); set_fs(KERNEL_DS);
ret = syscall_XXX(...);
set_fs(oldfd);
于 2009-08-30T07:34:16.880 に答える