Changing file permissions in kernel

Mehrdad picture Mehrdad · Aug 28, 2009 · Viewed 7.6k times · Source

I am writing kernel module(C in Linux) and I want to change the permission of the other files in it. any solution? since I am in kernel I can't use chmod syscall and ... thanks for your help

This is my 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

And this is my Code:

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

When Making it gives a warning:

WARNING: "sys_chmod" [file] undefiened

and when loading the module with "sudo insmod" it gives this error:

Unknown sybol in module

it seems that this error happens especialy in kernel modules. any idea? again thanks!

Answer

Aiden Bell picture Aiden Bell · Aug 28, 2009

Welcome to stackoverflow! IIRC you want sys_chmod()

From the Linux Kernel Mailing List

On Thu, Feb 20, 2003 at 11:10:27PM +0100, Andrea Arcangeli wrote: On Thu, Feb 20, 2003 at 12:40:43PM -0500, Jeff Garzik wrote:

On Thu, Feb 20, 2003 at 11:04:37PM +0530, Prasad wrote:

Is there a way using which i could invoke a syscall in the kernel space? The syscall is to be run disguised as another process. The actual

Call sys_whatever(). Look at the kernel code for examples.

The kernel already does this in various places. sys_read, sys_write, open_filp, sys_close, and other functions are safe to call from kernel code -- though this is discouraged. init/do_mounts.c is a particularly annoying case, and is a big reason why klibc needs to be merged. syscalls should be made from userspace, not the kernel.

People are starting to worry, as this isn't the kind of thing you might do in the kernel (unless you are use you know what you are doing). If you just want to change permissions on a certain event, do it from userspace with inotify or similar.

Disclaimer aside:

Here is some code I found in another kernel module, which uses the sys_* calls:

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

Also found:

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

in include/linux/syscalls.h

Mind you, it has been a while since I did any kernel stuff. Check that this is the appropriate interface for chmod stuff and that you arn't shortcutting any other call that might implement security hooks, for example.

Also, This link contains information on syscalls and their symbols. Also Here is a quick-reference of user-space API system calls and where they are implemented in the kernel.