File owner and file access permissions (8)

Directory

A file attribute

1.1 Effective User ID and Effective Group ID

1.2 chown() function

1.3 Functions getuid() and getgid()

Two file access permissions

2.1 General permissions

2.2 Directory permissions

Three check file permissions access

3.1 access system call()

3.2 Code Test

Four modify file permissions chmod

4.1 chmod function

4.2 fchmod function

4.3chmod code test


A file attribute

1.1 Effective User ID and Effective Group ID

First of all, for the effective user ID and effective group ID, this is the concept held by the process, and there is no such attribute for the file! The effective user ID and effective group ID are from the perspective of the operating system, and are used for the operating system to determine whether the user currently executing the process has the corresponding authority for a certain file in the current environment.

In the Linux system, when a process performs read and write operations on a file, the system will first determine whether the process has read and write permissions to the file, so how to judge? Naturally, it is judged by the permission bit of the file. The st_mode field in the struct stat structure records the permission bit and file type of the file. It was mentioned in the previous blog post.

When performing a permission check, it does not participate in the permission check through the actual user and actual group of the process, but participates in the file permission check through the effective user and effective group. In general, in most cases, the effective user of a process is equal to the real user (effective user ID is equal to the real user ID), and the effective group is equal to the real group (effective group ID is equal to the real group ID).

Tips: The “whether the process has xx permission to the file” referred to in the article is essentially whether the user currently executing the process has xx permission to the file.

1.2 chown() function

chown is a system call that can be used to change the owner (user ID) and group (group ID) of a file. In fact, there is also a chown command under the Linux system, which is also used to change the owner and group of the file. For example, testApp.c

Change the owner and group of the file to root: sudo chown root:root text.txt

The following figure uses the chown command to modify the file owner and group

This command can change the owner and group of the file. This command actually calls the chown function to realize the function. The prototype of the chown function is as follows (you can view it through the “man 2 chown” command):

#include <unistd.h>
 
int chown(const char *pathname, uid_t owner, gid_t group); 

Function parameters and return values are as follows:

  • pathname: used to specify a file path that needs to modify the owner and group.
  • owner: Change the owner of the file to the user specified by this parameter (described in the form of user ID);
  • group: Change the group to which the file belongs to the user group specified by this parameter (described in the form of user group ID);
  • Return value: 0 if successful; -1 if failed, and errno will be set.

The usage of this function is very simple, just specify the corresponding file path and the corresponding owner and group parameters

The method is very simple, just keep the ID (user ID or user group ID) that does not need to be modified consistent with the current ID (user ID or user group ID) of the file, that is, the user ID or user ID passed in when calling the chown function The group ID is the current user ID or user group ID of the file, and the current user ID or user group ID of the file can be obtained by querying the stat function.

Although the usage of this function is very simple, there are two restrictions:

  1. Only the superuser process can change the user ID of a file;
  2. A normal user process can change the group ID of a file to any of the subordinate group IDs it belongs to, provided that the effective user ID of the process is equal to the user ID of the file; whereas a superuser process can change the group ID of a file to any value.

Therefore, it can be seen that the user ID and group ID of the file cannot be changed casually. In fact, this design is for the sake of system security. If any ordinary user process in the system can change the user ID of the system file at will and group ID, it means that any ordinary user has arbitrary permissions on system files, which will be very unsafe for the operating system

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void main()
{
    int ret = chown("./test.txt", 100, 100);
        if(-1==ret)
        {
            perror("chown error:");
            exit(-1);
        }

        struct stat st1;
        int ret1 = stat("./test.txt", &st1);
        printf("gid :%d uid:%d",st1.st_gid,st1.st_uid);

}

gid is the group ID, uid is the user ID, and 0 is the root user ID

1.3 function getuid() and getgid()

Under the Linux system, two system calls, getuid and getgid, can be used to obtain the user ID and user group ID of the current process respectively. The user ID and user group ID of the process mentioned here refer to the actual user ID and actual group ID of the process. ID, the prototypes of these two system call functions are as follows:

#include <unistd.h>
#include <sys/types.h>
 
uid_t getuid(void);
gid_t getgid(void)

Use the functions getuid() and getgid() to get the ID number of the current process

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

void main()
{
        printf("gid :%d uid:%d",getuid(),getgid());
}

Two file access permissions

The st_mode (mentioned in Chapter 7) field in the struct stat structure records the access permission bit of the file. When referring to files, it refers to any type of file introduced earlier, not just ordinary files; all file types (directories, device files) have access permissions, not only Ordinary files only have access permissions

2.1 Ordinary authority

File permissions can be divided into two categories, which are ordinary permissions and special permissions (also called additional permissions). Common permissions include reading, writing, and executing files, while special permissions include some additional permissions on files, such as Set-User-ID, Set-Group-ID, and Sticky. Next, the common permissions and special permissions are introduced respectively.

Each file has 9 common access permission bits, which can be divided into 3 categories, as shown in the following table:

For example, use the ls command or the stat command to view the nine access rights of the file, as follows:

Use the ls command to view the 9 access permission bits of the file

In each line of printed information, the previous strings describe the 9 access rights and file types of the file.

For example “- rwx rwx -x”:

Figure : File Permission Bits

  • ” – ” indicates that the file is an ordinary file.
  • r means read permission;
  • w means write permission;
  • x indicates execution permission;
  • – Indicates no such permission.

Every time a process reads, writes, or executes a file, the kernel checks the access permission of the file to determine whether the process has the corresponding permission for the file. The permission check of the file involves the owner of the file (st_uid), the group to which the file belongs (st_gid) and other users. Of course, this refers to the perspective of the file; for the process, it is involved in the file permission check. The process’s effective user, effective user group, and process’s subordinate group users.

How to judge the permissions, first of all, it is necessary to figure out which type of “role” the process belongs to for the files that need to be operated:

  • If the effective user ID of the process is equal to the file owner ID (st_uid), it means that the process exists in the role of the file owner;
  • If the process’s effective user ID is not equal to the file’s owner ID, meaning that the process is not the file’s owner; but one of the process’s effective user group ID or the process’s subordinate group ID is equal to the file’s group ID (st_gid), then It means that the process exists in the role of a member of the group to which the file belongs, that is, a user member of the same group as the group to which the file belongs.
  • If the process’s effective user ID is not equal to the file’s owner ID, and the process’s effective user group ID or all of the process’s subordinate group IDs
  • are not equal to the group ID (st_gid) of the file, it means that the process exists in the role of other users.
  • If the effective user ID of the process is equal to 0 (root user), then no permission check is performed, and the file has the highest permission directly.

2.2 Directory permissions

Read, write, and execute permissions for files, do you need corresponding permissions for operations such as creating files and deleting files?

That means that operations such as deleting files and creating files also require corresponding permissions, so where are these permissions obtained? The answer is directories. A directory (folder) is also a kind of file under the Linux system, and has the same permission scheme (S/U/G/O) as a normal file, but the meaning of these permissions refers otherwise.

  1. The read permission of the directory: You can list (for example: through the ls command) the content under the directory (that is, which files are in the directory).
  2. Write permission of the directory: you can create and delete files in the directory.
  3. Execution permission of the directory: the files in the directory can be accessed, such as reading, writing, executing and other operations on the files in the directory.

With read permission to the directory, the user can only view the list of files in the directory, for example, use the ls command to view:

Through the “ls -l” command, you can view the relevant permissions of the directory file

To access files in a directory,

  • For example, to view information such as the inode node, size, and permissions of a file, you also need to have execute permissions on the directory.
  • Conversely, if you have execute permission on the directory but no read permission, as long as you know the name of the file in the directory, you can still access it, but you cannot list the contents of the directory (that is, the names of other files contained in the directory).
  • If you want to create a file or delete an existing file in a directory, you need to have both execute and write permissions on the directory.

So it can be seen that if you need to read, write or execute operations on a file, you not only need to have the read, write or execute permission of the file itself, but also need to have the execute permission of the directory where the file is located.

Three check file permissions access

The permission check of the file is not only about the permission of the file itself, but also the permission of the directory where the file is located. Only when both are satisfied, can the permission check of the operating system be passed, and then related operations can be performed on the file;So , before performing related operations on the file in the program, it is necessary to check whether the user executing the process has the corresponding permissions for the file.

How to check it?

3.1 access system call()

The function prototype is as follows:

#include <unistd.h>
 
int access(const char *pathname, int mode); 

Function parameters and return values have the following meanings:

pathname: The file path that needs to be checked for permissions.

mode: This parameter can take the following values:

  1. F_OK: Check if the file exists
  2. R_OK: Check if you have read permission
  3. W_OK: Check if you have write permission
  4. X_OK: Check if you have execute permission

In addition to being used alone, they can also be combined with the bitwise OR operator ” | “.

Return value: If the check item passes, it returns 0, indicating that it has the corresponding permission and the file exists; otherwise, it returns -1. If multiple check items are combined, as long as any one of them fails, it will return -1.

3.2 Code Test

Use the access function to check whether the file exists, and if it exists, continue to check whether the user executing the process has read, write, and execute permissions for the file.

#include "stdio.h"
#include <unistd.h>
#include <stdlib.h>

#define MY_FILE "./test.txt"
void main()
{
    int ret = access("./test.txt", F_OK);
    if (-1 == ret)
    {
        perror("");
        exit(-1);
    }else
    {
        printf("The file exists\\
");
        /* Check permissions */
    ret = access(MY_FILE, R_OK);
    if (!ret)
        printf("has read permission\\
");
    else
        printf("No read permission\\
");
 
    ret = access(MY_FILE, W_OK);
    if (!ret)
        printf("has write permission\\
");
    else
        printf("No write permission\\
");
        
    ret = access(MY_FILE, X_OK);
    if (!ret)
        printf("has execute permission\\
");
    else
        printf("No execute permission\\
");
        }
}

Therefore, the above code is to check the permissions that the user of the current process has on the file

Fourth modify file permissions chmod

Under the Linux system, you can use the chmod command to modify file permissions. The internal implementation method of this command is actually to call the chmod function.

4.1 chmod function

It is a system call, and the function prototype is as follows (can be viewed through the “man 2 chmod” command):

#include <sys/stat.h>
 
int chmod(const char *pathname, mode_t mode); 

First, the header file needs to be included to use this function.

Function parameters and return values are as follows:

  • pathname: The path of the file whose permissions need to be modified. If the parameter refers to a symbolic link, the file whose permissions are actually changed is the file pointed to by the symbolic link, not the symbolic link file itself.
  • mode: This parameter is used to describe the file permission. It is the same as the third parameter of the open function. It will not be repeated here. It can be described directly using octal data, or using the corresponding permission macro (single or through the bit OR operator \ ” | ” combination).
  • Return value: return 0 if successful; return -1 if failed, and set errno.

File permissions are very important attributes for files, and cannot be modified by any user casually. To change file permissions, either the superuser (root) process, or the effective user ID of the process and the file User ID (file owner) matches.

4.2 fchmod function

This function has the same function as chmod, with slightly different parameters. The difference between fchmod() and chmod() is that a file descriptor is used instead of a file path, just like the difference between fstat and stat. The function prototype looks like this:

#include <sys/stat.h>
 
int fchmod(int fd, mode_t mode); 

4.3chmod code test

#include <sys/stat.h>

void main()
{
    int ret = chmod("./test.txt", 0777);
}

After the code is executed, the permissions of the test.txt file change,

Before executing the program, the permission of the test_txt file is ——x–x. After the program is executed, check the file permission again as

rwxrwxrwx (0777), modified successfully!