zoukankan      html  css  js  c++  java
  • 文件权限

    一、文件信息结构

    图1 文件信息结构stat

    与文件有关的信息结构,如图1所示,结构的实际定义可能随具体实现会有所不同,但这是基本形式。本节中主要涉及的有st_modest_uidst_gid成员。

    图2 获取stat函数

    获取文件信息结构stat,有4个stat函数。

    stat通过pathname来获得文件相关信息结构stat;

    fstat通过文件描述符fd来获得文件相关信息结构stat;

    lstat类似于stat,但当命名文件是一个符号链接时,lstat返回该符号链接的有关信息,不是符号链接引用的文件信息【NOFOLLOW】。

    fstatat中,fd控制相对路径的起始目录,flag控制是否跟随符号链接【AT_SYMLINK_NOFOLLOW】。

    • 文件类型

    (1)普通文件(2)目录文件(3)块特殊文件(4)字符特殊文件(5)FIFO(6)套接字(7)符号链接

    文件类型信息包含在stat结构中的st_mode成员中,可用图3的文件类型宏判断,输入为st_mode,如S_ISREG(stat.st_mode)

    图3 文件类型宏

     二、与进程相关的ID

    与进程相关联的ID有6个或更多,如图4

    图4 与进程相关的ID

    1、实际用户ID和实际组ID,标识实际上我们是谁,这两个字段在登录时取自口令文件中的登录项。

    2、有效用户ID、有效组ID及附属组ID,这3个ID决定了进程的文件访问权限。

    即判断文件访问权限是根据进程有效ID文件的ID进行判断的。具体规则后续再展开。

    3、保存设置用户ID、保存设置组ID,分别是有效用户ID、有效组ID的副本。这个字段的用处,后续再展开。

     

    注意:一般情况下,有效用户ID=实际用户ID,有效组ID=实际组ID

    特殊情况下:st_modeset-user-ID位(设置用户位)set-group-ID位(设置组位) 会改变这种情况。

    如果文件的设置用户位被设置,那么执行该文件(exec)时,有效用户ID=文件用户ID,而不是有效用户ID=实际用户ID;

    如果文件的设置组位被设置,那么执行该文件(exec)时,有效组ID=文件组ID,而不是有效用户ID=实际用户ID。

     

    例1:passwd是一个设置用户ID程序,当普通用户进程执行passwd时,有效用户ID更改为文件的用户ID(root),这样就拥有了root特限,可以更改口令文件。

     

    • 保存设置ID的作用

    以用户ID为例,组ID效果类似,可推广。

    更改用户ID的方法,如图5所示。

    图5 更改用户ID的方法

    实际的用户ID在登录时获取,有效用户ID=实际用户ID;

    除非exec一个文件时,该文件设置了设置用户ID位,有效用户ID=文件的用户ID;

    保存设置用户ID从有效用户ID中复制。

    这些在前边都介绍过了。

     

    当程序需要增加特权或者降低特权时,需要对用户ID或组ID进行更改,以获取合适的访问权限。

    这里以用户ID为例,更改用户ID,可以用setuid进行。

    (1)若进程具有超级特权,setuid则会更改实际用户ID、有效用户ID、以及保存的设置用户ID为uid。

    (2)若没有超级特权,setuid只能更改有效用户ID,而且uid要么为实际用户ID,要么为设置用户ID

     

    例2:at程序,可用于调度在哪个时刻运行特定的命令。at文件是root用户所拥有的,且设置用户ID位被设置了。

     运行at程序,过程:

    (1)运行at程序,用户ID状态如下

    实际用户 ID = 我们的用户ID(未改变)

    有效用户ID = root(从at程序文件得来)

    保存的设置用户 ID = root(复制有效用户ID)

    (2)at先降低自己的特权,调用setuid更改为实际用户ID

    实际用户 ID = 我们的用户ID(未改变)

    有效用户ID = 我们的用户ID(uid=实际用户ID)

    保存的设置用户 ID = root(未改变)

    (3)直到需要特权时(更改命令何时的运行配置文件),调用setuid更改为root(uid = 保存的设置用户ID,这也是保存设置用户ID作用的体现)

    实际用户 ID = 我们的用户ID(未改变)

    有效用户ID = root(uid=保存的设置用户ID)

    保存的设置用户 ID = root(未改变)

    (4)降低特权,防止对特权的误用

    实际用户 ID = 我们的用户ID(未改变)

    有效用户ID = 我们的用户ID(uid=实际用户ID)

    保存的设置用户 ID = root(未改变)

    (5)时间到,守护进程开始用root特权运行,代表用户运行命令(用setuid,将所有用户ID设置为我们的用户ID)

    实际用户 ID = 我们的用户ID(root,setuid更改所有)

    有效用户ID = 我们的用户ID(root,setuid更改所有)

    保存的设置用户 ID = 我们的用户ID(root,setuid更改所有)

    总结:保存设置用户ID,很多部分是为了实现最小特权

    三、文件访问权限

    每个文件有9个访问权限位,可分为3类,用户读写执行、读写执行、其它读写执行,如图6所示(存储在st_mode)。

    图5 文件访问权限

     根据前边,知道访问权限测试,是根据进程有效ID(有效用户ID和有效组ID)和文件的ID进行判断的。

    (1)进程的有效用户ID是0(超级用户),具有所有访问权限;

    (2)进程的有效用户ID等于文件用户ID(stat.st_uid),且文件中用户适当的访问权限位(读写执行)被设置,则允许访问;

    (3)进程的有效组ID或附属组ID之一等于文件组ID(stat.st_gid),且文件中组适当的访问权限位(读写执行)被设置,则允许访问;

    (4)其它情况,若文件中其它用户适当的访问权限(读写执行)被设置,则允许访问;

    • access和faccessat

    access和faccessat函数,可根据进程实际ID来测试访问权限,而不是有效ID

    图6 access和faccessat函数

    四、新文件的所有权和权限

    所有权:

    新文件的用户ID设置为进程有效用户ID

    新文件的组ID,可以是进程有效组ID;也可以是所在目录的组ID

    注意:Linux3.2.0和Solaris 10,新文件的组ID取决于目录的设置组ID位是否被设置。若被设置,则新文件的组ID是所在目录的组ID。

    新文件的权限:

    umask为文件模式创建屏蔽字,在文件模式创建屏蔽字中位1的位,在文件mode中的相应位一定被关闭。

    还有,普通文件文件被创建时,不能拥有执行权限。

    常用值有002,022和027。

    002屏蔽其它用户的写权限,022屏蔽组成员和其它用户的写权限,027屏蔽组成员的写权限以及其它用户的所有权限。

    五、更改文件的权限位

    图7 chmod、fchmod和fchmodat函数

     只有进程的有效用户ID等于文件所有者ID,或者进程具有超级用户权限,才可以更改文件的权限位。

    参数mode是一下的常量按位或:

    图8 权限位总览

     粘着位作用:

    (1)可执行文件,第一次被执行后,程序正文部分还保留在交换区

    (2)扩展了使用范围,如果一个目录设置了粘着位,那么改目录下的文件删除有限制条件

    拥有此文件 or 拥有此目录 or 是超级用户才能删除。

    六、更改文件的用户ID和组ID

    图9 更改文件用户ID和组ID函数

    _POSIX_CHOWN_RESTRICTED限制生效:

    (1)只有超级用户可更改用户ID

    (2)非超级用户可以更改自己拥有文件的组ID,但只能更改到自己所属的组

    七、文件权限位总结

    图10 文件权限位总结

  • 相关阅读:

    bzoj3052: [wc2013]糖果公园
    莫队算法心得
    bzoj1104: [POI2007]洪水pow
    bzoj1102: [POI2007]山峰和山谷Grz
    bzoj1121: [POI2008]激光发射器SZK
    bzoj1113: [Poi2008]海报PLA
    bzoj1103: [POI2007]大都市meg
    bzoj1396: 识别子串
    bzoj3756: Pty的字符串
  • 原文地址:https://www.cnblogs.com/songdechiu/p/10264886.html
Copyright © 2011-2022 走看看