Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
784 views
in Technique[技术] by (71.8m points)

filesystems - Setting Immutable Flag using ioctl() in C

I have attempted to make a script that creates a file and then sets it as immutable similar to the chattr +i command for linux. The script compiles (with gcc), runs and the file is created. However the file itself is not immutable and can be removed with a simple rm -f. I have attempted to stacktrace where chattr is called and I found a function called ioctl. I then used what little information I could gather and came up with what I have below. I narrowed it down from ext2_fs.h but it just doesn't seem to work. I've clearly overlooked something.

Updates to previous entry: Compiles but returns -1 on ioctl() function. Bad address shown with perror().

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>

int main()
{
    FILE *fp;
    char shovel[16] = "I have a shovel!";
    fp = fopen("/shovel.txt", "w+");
    fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp);
    ioctl(fileno(fp), FS_IOC_SETFLAGS, 0x00000010);
    fclose(fp);
}

Any help appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are using the right ioctl command, but you're passing it the wrong arguments.

The manpage for ioctl_list(2) shows that FS_IOC_SETFLAGS expects to receive a pointer to int (an int *), yet you're passing it an integer literal (hence the Bad Address error).

The fact that you don't to any error checking whatsoever is also not helping.

The correct flag to pass to FS_IOC_SETFLAGS is a pointer holding the value EXT2_IMMUTABLE_FL, which is defined in ext2fs/ext2_fs.h (some older / different Linux distributions seem to have it under linux/ext2_fs.h), so you'll need to #include <ext2fs/etx2_fs.h>. Make sure to install e2fslibs-dev (and probably you'll need linux-headers too).

This code is working:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <ext2fs/ext2_fs.h>

int main()
{
    FILE *fp;
    char shovel[16] = "I have a shovel!";

    if ((fp = fopen("shovel.txt", "w+")) == NULL) {
        perror("fopen(3) error");
        exit(EXIT_FAILURE);
    }

    fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp);

    int val = EXT2_IMMUTABLE_FL;
    if (ioctl(fileno(fp), FS_IOC_SETFLAGS, &val) < 0)
        perror("ioctl(2) error");

    fclose(fp);

    return 0;
}

Remember to run this as root.

UPDATE:

As Giuseppe Guerrini suggests in his answer, you might want to use FS_IMMUTABLE_FL instead, and you won't need to include ext2_fs.h:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>

int main()
{
    FILE *fp;
    char shovel[16] = "I have a shovel!";

    if ((fp = fopen("shovel.txt", "w+")) == NULL) {
        perror("fopen(3) error");
        exit(EXIT_FAILURE);
    }

    fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp);

    int val = FS_IMMUTABLE_FL;
    if (ioctl(fileno(fp), FS_IOC_SETFLAGS, &val) < 0)
        perror("ioctl(2) error");

    fclose(fp);

    return 0;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...