ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux在伪代码中有效,真实,保存,文件系统UID操作

2019-06-21 09:49:17  阅读:221  来源: 互联网

标签:unix linux setuid


我花了一些时间在Groovy中的一些代码来使Linux UID操作对我自己有点不那么困惑,因为手册页很乱.结果是一个TestCase,用于显示在setuid,seteuid,setfsuid,setreuid和setresuid调用的引擎下发生的事情.不考虑有关返回的错误代码(或不包含)的详细信息.

问题基本上是:我错过了什么吗?

/**
 * This is some Groovy code to explain Linux privilege handling
 * The manipulable data structure is "PermVector", and it is manipulated through a
 * TestCase.
 */

class PermissionTestCase extends GroovyTestCase {

  class PermVector {

    int ruid  // real UID; affects the permissions for sending signals 
    int euid  // effective UID; affects file creation and access
    int suid  // saved UID
    int fsuid // filesystem UID; access control to the file system for NFS in Linux

    /**
     * The permission vector of a process that is created from a parent process
     * having the given parent_euid, with its executable file having the given
     * exe_suid_bit and being owned by the given exe_uid  
     */

    PermVector(Map params) {
        ruid  = params.parent_euid // is this right??
        euid  = params.parent_euid
        suid  = params.exe_suid_bit ? params.exe_uid : params.parent_euid
        fsuid = params.parent_euid // is this right??
    }

    /**
     * What does it mean for a process to be "privileged"?
     */

    def isPrivileged() {
        return euid == 0
    }

    /**
     * Helper
     */

    private def euid_part(int new_euid) {
        if (isPrivileged() || 
            (new_euid == ruid || new_euid == euid || new_euid == suid)) {
            return new_euid
        }
        else {
            throw new IllegalStateException("Nixed euid ${euid} to ${new_euid}")
        }
    }

    /**
     * Helper
     */

    private def ruid_part(int new_ruid) {
        if (isPrivileged() || (new_ruid == ruid || new_ruid == euid)) {
            return new_ruid
        }
        else {
            throw new IllegalStateException("Nixed ruid ${ruid} to ${new_ruid}")
        }
    }

    /**
     * Helper
     */

    private def suid_part(int new_suid) {
        if (isPrivileged() || 
            (new_suid == ruid || new_suid == euid || new_suid == suid)) {
            return new_suid
        }
        else {
            throw new IllegalStateException("Nixed suid ${suid} to ${new_suid}")
        }
    }

    /**
     * Helper
     */

    private def ruid_part_for_setresuid(int new_ruid) {
        if (isPrivileged() || 
            (new_ruid == ruid || new_ruid == euid || new_ruid == suid)) {
            return new_ruid
        }
        else {
            throw new IllegalStateException("Nixed ruid ${ruid} to ${new_ruid}")
        }
    }

    /**
     * Behaviour of SETREUID(2)
     */

    def setreuid(int new_ruid, int new_euid) {
        int next_euid = euid_part(new_euid)
        int next_ruid = ruid_part(new_ruid)
        if (next_euid != euid || next_ruid != ruid) {
            suid = next_euid
        }
        euid = next_euid
        ruid = next_ruid
        fsuid = next_euid
    }

    /**
     * Behaviour of SETEUID(2)
     */

    def seteuid(int new_euid) {
        if (isPrivileged()) {
            euid = new_euid
            fsuid = new_euid
        }
        else {
            if (new_euid == ruid || new_euid == euid || new_euid == suid) {
                euid = new_euid
                fsuid = new_euid
                // glibc 2.1  and  later do not change the suid!
            }
            else {
                throw new IllegalStateException("Nixed euid ${euid} to ${new_euid}")
            }
        }
    }

    /**
     * Behaviour of SETUID(2)
     */

    def setuid(int new_euid) {
        if (isPrivileged()) {
            euid = new_euid
            ruid = new_euid
            suid = new_euid
            fsuid = new_euid
        }
        else {
            if (new_euid == ruid || new_euid == suid) {
                euid = new_euid
                fsuid = new_euid
            }
            else {
                throw new IllegalStateException("Nixed euid ${euid} to ${new_euid}")
            }
        }
    }

    /**
     * Behaviour of SETFSUID(2)
     */

    def setfsuid(int new_fsuid) {
        if (isPrivileged()) {
            fsuid = new_fsuid
        }
        else {
            if (new_fsuid == ruid || new_fsuid == euid || 
                new_fsuid == suid || new_fsuid == fsuid) {
                fsuid = new_fsuid
            }
            else {
                throw new IllegalStateException("Nixed fsuid ${fsuid} to ${new_fsuid}")
            }
        }
    }

    /**
     * Behaviour of SETRESUID(2)
     */

    def setresuid(int new_ruid, int new_euid, int new_suid) {
        int next_ruid = new_ruid==-1 ? ruid : ruid_part_for_setresuid(new_ruid)
        int next_euid = new_euid==-1 ? euid : euid_part(new_euid)
        int next_suid = new_suid==-1 ? suid : suid_part(new_suid)
        ruid = next_ruid
        euid = next_euid
        suid = next_suid
        fsuid = next_euid
    }

    /**
     * Printing
     */

    String toString() {
        return "[ruid:${ruid}, euid:${euid}, suid:${suid}, fsuid:${fsuid}]"
    }
}


/**
 * Use case: drop privileges for good
 */

void testDropPrivilegesFromRoot() {
    PermVector pv = 
         new PermVector(parent_euid : 0, exe_suid_bit : false, exe_uid : 500)        
    System.out << "Dropping privileges from ${pv} using setuid(1000) .... "
    pv.setuid(1000)
    System.out << "now at ${pv}\n"
    assertEquals(1000, pv.ruid)
    assertEquals(1000, pv.euid)
    assertEquals(1000, pv.suid)
    assertEquals(1000, pv.fsuid)

}

/**
 * Use case: elevate privileges, do some work, then drop privileges again
 */

void testElevatePrivilegesTemporarily() {
    PermVector pv = 
       new PermVector(parent_euid : 500, exe_suid_bit : true, exe_uid : 0)
    System.out << "Elevating privileges from ${pv} using setreuid(500,0) .... "
    pv.setreuid(500,0)        
    System.out << "now at ${pv}, doing privileged work .... "
    assertEquals(500, pv.ruid)
    assertEquals(0, pv.euid)
    assertEquals(0, pv.suid)
    assertEquals(0, pv.fsuid)
    System.out << "dropping back .... "        
    pv.setuid(500)
    System.out << "now at ${pv}\n"
    assertEquals(500, pv.ruid)
    assertEquals(500, pv.euid)
    assertEquals(500, pv.suid)
    assertEquals(500, pv.fsuid)

}

/**
 * Use case: drop privileges, do some work, then elevate privileges again
 */

void testDropPrivilegesTemporarily() {
    PermVector pv = 
       new PermVector(parent_euid : 0, exe_suid_bit : false, exe_uid : 500)
    System.out << "Dropping privileges from ${pv} using setreuid(0,500) .... "
    pv.setreuid(0, 500)
    System.out << "now at ${pv} ... doing unprivileged work safely .... "
    assertEquals(0, pv.ruid)
    assertEquals(500, pv.euid)
    assertEquals(500, pv.suid)
    assertEquals(500, pv.fsuid)
    System.out << "elevating .... "
    pv.setuid(0)
    System.out << "back at ${pv}\n"
    assertEquals(0, pv.ruid)
    assertEquals(0, pv.euid)
    assertEquals(500, pv.suid)
    assertEquals(0, pv.fsuid)

  }
}

解决方法:

对于实际和有效UID之间的差异,请阅读例如this – 这是UNIX UID的关键概念.你可以,例如有一个设置了UID位的进程,如果普通用户运行它,他将拥有root的有效UID(例如),但真正的UID仍然是他的UID.在你理解了这个例子后,它会变得更加清晰……

标签:unix,linux,setuid
来源: https://codeday.me/bug/20190621/1253849.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有