Freebsd capability和privilege设计解读
2021-1-5 12:30:45 Author: mp.weixin.qq.com(查看原文) 阅读量:0 收藏

Freebsdcapability能力模型与linux的设计有很大不同, linuxcapabilityprivile权限混合到一起实现,而freebsd将其分离出来,使系统的访问控制模型更加精细。

Freebsd12定义了50多种能力类型,主要集中在文件系统和网络,这两个子系统的能力区分很精细: 

sys/capsicum.h
#define CAP_READ                CAPRIGHT(0, 0x0000000000000001ULL)#define CAP_WRITE               CAPRIGHT(0, 0x0000000000000002ULL)#define CAP_SEEK_TELL           CAPRIGHT(0, 0x0000000000000004ULL)#define CAP_SEEK                (CAP_SEEK_TELL | 0x0000000000000008ULL)#define CAP_PREAD               (CAP_SEEK | CAP_READ)#define CAP_PWRITE              (CAP_SEEK | CAP_WRITE)#define CAP_MMAP                CAPRIGHT(0, 0x0000000000000010ULL)#define CAP_MMAP_R              (CAP_MMAP | CAP_SEEK | CAP_READ)#define CAP_MMAP_W              (CAP_MMAP | CAP_SEEK | CAP_WRITE)#define CAP_MMAP_X              (CAP_MMAP | CAP_SEEK | 0x0000000000000020ULL)#define CAP_MMAP_RW             (CAP_MMAP_R | CAP_MMAP_W)#define CAP_MMAP_RX             (CAP_MMAP_R | CAP_MMAP_X)#define CAP_MMAP_WX             (CAP_MMAP_W | CAP_MMAP_X)#define CAP_MMAP_RWX            (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)#define CAP_CREATE              CAPRIGHT(0, 0x0000000000000040ULL)#define CAP_FEXECVE             CAPRIGHT(0, 0x0000000000000080ULL)#define CAP_FSYNC               CAPRIGHT(0, 0x0000000000000100ULL)#define CAP_FTRUNCATE           CAPRIGHT(0, 0x0000000000000200ULL)#define CAP_LOOKUP              CAPRIGHT(0, 0x0000000000000400ULL)#define CAP_FCHDIR              CAPRIGHT(0, 0x0000000000000800ULL)#define CAP_FCHFLAGS            CAPRIGHT(0, 0x0000000000001000ULL)#define CAP_CHFLAGSAT           (CAP_FCHFLAGS | CAP_LOOKUP)#define CAP_FCHMOD              CAPRIGHT(0, 0x0000000000002000ULL)#define CAP_FCHMODAT            (CAP_FCHMOD | CAP_LOOKUP)#define CAP_FCHOWN              CAPRIGHT(0, 0x0000000000004000ULL)#define CAP_FCHOWNAT            (CAP_FCHOWN | CAP_LOOKUP)#define CAP_FCNTL               CAPRIGHT(0, 0x0000000000008000ULL)#define CAP_FLOCK               CAPRIGHT(0, 0x0000000000010000ULL)#define CAP_FPATHCONF           CAPRIGHT(0, 0x0000000000020000ULL)#define CAP_FSCK                CAPRIGHT(0, 0x0000000000040000ULL)#define CAP_FSTAT               CAPRIGHT(0, 0x0000000000080000ULL)#define CAP_FSTATAT             (CAP_FSTAT | CAP_LOOKUP)#define CAP_FSTATFS             CAPRIGHT(0, 0x0000000000100000ULL)#define CAP_FUTIMES             CAPRIGHT(0, 0x0000000000200000ULL)#define CAP_FUTIMESAT           (CAP_FUTIMES | CAP_LOOKUP)#define CAP_LINKAT_TARGET       (CAP_LOOKUP | 0x0000000000400000ULL)#define CAP_MKDIRAT             (CAP_LOOKUP | 0x0000000000800000ULL)#define CAP_MKFIFOAT            (CAP_LOOKUP | 0x0000000001000000ULL)#define CAP_MKNODAT             (CAP_LOOKUP | 0x0000000002000000ULL)#define CAP_RENAMEAT_SOURCE     (CAP_LOOKUP | 0x0000000004000000ULL)#define CAP_SYMLINKAT           (CAP_LOOKUP | 0x0000000008000000ULL)#define CAP_UNLINKAT            (CAP_LOOKUP | 0x0000000010000000ULL)#define CAP_ACCEPT              CAPRIGHT(0, 0x0000000020000000ULL)#define CAP_BIND                CAPRIGHT(0, 0x0000000040000000ULL)#define CAP_CONNECT             CAPRIGHT(0, 0x0000000080000000ULL)#define CAP_GETPEERNAME         CAPRIGHT(0, 0x0000000100000000ULL)#define CAP_GETSOCKNAME         CAPRIGHT(0, 0x0000000200000000ULL)#define CAP_GETSOCKOPT          CAPRIGHT(0, 0x0000000400000000ULL)#define CAP_LISTEN              CAPRIGHT(0, 0x0000000800000000ULL)#define CAP_PEELOFF             CAPRIGHT(0, 0x0000001000000000ULL)#define CAP_RECV                CAP_READ#define CAP_SEND CAP_WRITE#define CAP_SETSOCKOPT          CAPRIGHT(0, 0x0000002000000000ULL)#define CAP_SHUTDOWN            CAPRIGHT(0, 0x0000004000000000ULL)#define CAP_BINDAT              (CAP_LOOKUP | 0x0000008000000000ULL)#define CAP_CONNECTAT           (CAP_LOOKUP | 0x0000010000000000ULL)#define CAP_LINKAT_SOURCE       (CAP_LOOKUP | 0x0000020000000000ULL)#define CAP_RENAMEAT_TARGET     (CAP_LOOKUP | 0x0000040000000000ULL)#define CAP_MAC_GET             CAPRIGHT(1, 0x0000000000000001ULL)#define CAP_MAC_SET             CAPRIGHT(1, 0x0000000000000002ULL)#define CAP_SEM_GETVALUE        CAPRIGHT(1, 0x0000000000000004ULL)#define CAP_SEM_POST            CAPRIGHT(1, 0x0000000000000008ULL)#define CAP_SEM_WAIT            CAPRIGHT(1, 0x0000000000000010ULL)#define CAP_EVENT               CAPRIGHT(1, 0x0000000000000020ULL)#define CAP_KQUEUE_EVENT        CAPRIGHT(1, 0x0000000000000040ULL)#define CAP_IOCTL               CAPRIGHT(1, 0x0000000000000080ULL)#define CAP_TTYHOOK             CAPRIGHT(1, 0x0000000000000100ULL)#define CAP_PDGETPID            CAPRIGHT(1, 0x0000000000000200ULL)#define CAP_PDWAIT              CAPRIGHT(1, 0x0000000000000400ULL)#define CAP_PDKILL              CAPRIGHT(1, 0x0000000000000800ULL)#define CAP_EXTATTR_DELETE      CAPRIGHT(1, 0x0000000000001000ULL)#define CAP_EXTATTR_GET         CAPRIGHT(1, 0x0000000000002000ULL)#define CAP_EXTATTR_LIST        CAPRIGHT(1, 0x0000000000004000ULL)#define CAP_EXTATTR_SET         CAPRIGHT(1, 0x0000000000008000ULL)#define CAP_ACL_CHECK           CAPRIGHT(1, 0x0000000000010000ULL)#define CAP_ACL_DELETE          CAPRIGHT(1, 0x0000000000020000ULL)#define CAP_ACL_GET             CAPRIGHT(1, 0x0000000000040000ULL)#define CAP_ACL_SET             CAPRIGHT(1, 0x0000000000080000ULL)#define CAP_KQUEUE_CHANGE       CAPRIGHT(1, 0x0000000000100000ULL)#define CAP_KQUEUE (CAP_KQUEUE_EVENT | CAP_KQUEUE_CHANGE)

比如对网络的能力控制,可以看到freebsdbind,listen,accept等网络操作都做了限制, 而linux却只有CAP_NET_BIND_SERVICECAP_NET_BROADCASTCAP_NET_ADMINCAP_NET_RAW四种能力,限制的主要是特权能力。Freebsd虽然没有在capability模型中对这些特权进行限制,但是它是在privilege权限模型中进行限制的,freebsd定义了500多个权限类型,对操作系统的每个子系统都做了更加精细的权限控制。

sys/priv.h:
#define PRIV_NET_BRIDGE         390     /* Administer bridge. */#define PRIV_NET_GRE            391     /* Administer GRE. */#define _PRIV_NET_PPP           392     /* Removed. */#define _PRIV_NET_SLIP          393     /* Removed. */#define PRIV_NET_BPF            394     /* Monitor BPF. */#define PRIV_NET_RAW            395     /* Open raw socket. */#define PRIV_NET_ROUTE 396 /* Administer routing. */#define PRIV_NET_TAP            397     /* Can open tap device. */#define PRIV_NET_SETIFMTU       398     /* Set interface MTU. */#define PRIV_NET_SETIFFLAGS     399     /* Set interface flags. */#define PRIV_NET_SETIFCAP       400     /* Set interface capabilities. */#define PRIV_NET_SETIFNAME      401     /* Set interface name. */#define PRIV_NET_SETIFMETRIC    402     /* Set interface metrics. */#define PRIV_NET_SETIFPHYS      403     /* Set interface physical layer prop. */#define PRIV_NET_SETIFMAC       404     /* Set interface MAC label. */#define PRIV_NET_ADDMULTI       405     /* Add multicast addr. to ifnet. */#define PRIV_NET_DELMULTI       406     /* Delete multicast addr. from ifnet. */#define PRIV_NET_HWIOCTL        407     /* Issue hardware ioctl on ifnet. */#define PRIV_NET_SETLLADDR      408     /* Set interface link-level address. */#define PRIV_NET_ADDIFGROUP     409     /* Add new interface group. */#define PRIV_NET_DELIFGROUP     410     /* Delete interface group. */#define PRIV_NET_IFCREATE       411     /* Create cloned interface. */#define PRIV_NET_IFDESTROY      412     /* Destroy cloned interface. */#define PRIV_NET_ADDIFADDR      413     /* Add protocol addr to interface. */#define PRIV_NET_DELIFADDR      414     /* Delete protocol addr on interface. */#define PRIV_NET_LAGG           415     /* Administer lagg interface. */#define PRIV_NET_GIF            416     /* Administer gif interface. */#define PRIV_NET_SETIFVNET      417     /* Move interface to vnet. */#define PRIV_NET_SETIFDESCR     418     /* Set interface description. */#define PRIV_NET_SETIFFIB       419     /* Set interface fib. */#define PRIV_NET_VXLAN          420     /* Administer vxlan. */#define PRIV_NET_SETLANPCP      421     /* Set LAN priority. */#define PRIV_NET_SETVLANPCP PRIV_NET_SETLANPCP /* Alias Set VLAN priority */#define PRIV_NET80211_GETKEY    440     /* Query 802.11 keys. */#define PRIV_NET80211_MANAGE    441     /* Administer 802.11. */#define _PRIV_NETATALK_RESERVEDPORT     450     /* Bind low port number. */#define PRIV_NETATM_CFG         460#define PRIV_NETATM_ADD         461#define PRIV_NETATM_DEL         462#define PRIV_NETATM_SET         463#define PRIV_NETBLUETOOTH_RAW   470     /* Open raw bluetooth socket. */#define PRIV_NETGRAPH_CONTROL   480     /* Open netgraph control socket. */#define PRIV_NETGRAPH_TTY       481     /* Configure tty for netgraph. */#define PRIV_NETINET_RESERVEDPORT       490     /* Bind low port number. */#define PRIV_NETINET_IPFW       491     /* Administer IPFW firewall. */#define PRIV_NETINET_DIVERT     492     /* Open IP divert socket. */#define PRIV_NETINET_PF         493     /* Administer pf firewall. */#define PRIV_NETINET_DUMMYNET   494     /* Administer DUMMYNET. */#define PRIV_NETINET_CARP       495     /* Administer CARP. */#define PRIV_NETINET_MROUTE     496     /* Administer multicast routing. */#define PRIV_NETINET_RAW        497     /* Open netinet raw socket. */#define PRIV_NETINET_GETCRED    498     /* Query netinet pcb credentials. */#define PRIV_NETINET_ADDRCTRL6  499     /* Administer IPv6 address scopes. */#define PRIV_NETINET_ND6        500     /* Administer IPv6 neighbor disc. */#define PRIV_NETINET_SCOPE6     501     /* Administer IPv6 address scopes. */#define PRIV_NETINET_ALIFETIME6 502     /* Administer IPv6 address lifetimes. */#define PRIV_NETINET_IPSEC      503     /* Administer IPSEC. */#define PRIV_NETINET_REUSEPORT  504     /* Allow [rapid] port/address reuse. */#define PRIV_NETINET_SETHDROPTS 505     /* Set certain IPv4/6 header options. */#define PRIV_NETINET_BINDANY    506     /* Allow bind to any address. */#define PRIV_NETINET_HASHKEY    507     /* Get and set hash keys for IPv4/6. */#define _PRIV_NETIPX_RESERVEDPORT       520     /* Bind low port number. */#define _PRIV_NETIPX_RAW                521     /* Open netipx raw socket.
#define _PRIV_NETIPX_RESERVEDPORT       520     /* Bind low port number. */#define _PRIV_NETIPX_RAW                521     /* Open netipx raw socket. */#define PRIV_NETNCP             530     /* Use another user's connection. */#define PRIV_NETSMB 540 /* Use another user's connection. */

在对capability的使用方式上,freebsd定义了一个系统调用sys_cap_enter需要进程主动进入能力模式,而linux从最初的init进程开始就始终处在能力模式之下。

kern/sys_capability.c:
intsys_cap_enter(struct thread *td, struct cap_enter_args *uap){        struct ucred *newcred, *oldcred;        struct proc *p;
        if (IN_CAPABILITY_MODE(td)) return (0);
        newcred = crget();        p = td->td_proc;        PROC_LOCK(p);        oldcred = crcopysafe(p, newcred);        newcred->cr_flags |= CRED_FLAG_CAPMODE;        proc_set_cred(p, newcred);        PROC_UNLOCK(p); crfree(oldcred);
        return (0);}

sys_cap_enter只是在进程的cred结构体里做了CRED_FLAG_CAPMODE标记。当进程处在capability模式下,进程所能使用的系统调用也是有限制的:

kern/subr_syscall.c
static inline intsyscallenter(struct thread *td){#ifdef CAPABILITY_MODE                if (IN_CAPABILITY_MODE(td) &&                    !(sa->callp->sy_flags & SYF_CAPENABLED)) {                        error = ECAPMODE;                        goto retval;                }#endif}

只能使用标记为SYF_CAPENABLED的系统调用。

在进程进入能力模式后,它不能执行磁盘二进制文件, 这也是与linux的另一个不同点。

kern/kern_exec.c:
static intdo_execve(struct thread *td, struct image_args *args, struct mac *mac_p){        if (args->fname != NULL) {#ifdef CAPABILITY_MODE                if (IN_CAPABILITY_MODE(td)) {                        error = ECAPMODE;                        goto exec_fail;                }#endif}

在看下linuxcapability能力,它与privilege是混合定义的,一共有三十几个:

#define CAP_CHOWN            0#define CAP_DAC_OVERRIDE     1#define CAP_DAC_READ_SEARCH  2#define CAP_FOWNER           3#define CAP_FSETID           4#define CAP_KILL             5#define CAP_SETGID           6#define CAP_SETUID           7#define CAP_SETPCAP          8#define CAP_LINUX_IMMUTABLE  9#define CAP_NET_BIND_SERVICE 10#define CAP_NET_BROADCAST    11#define CAP_NET_ADMIN        12#define CAP_NET_RAW          13#define CAP_IPC_LOCK         14#define CAP_IPC_OWNER        15#define CAP_SYS_MODULE       16#define CAP_SYS_RAWIO        17#define CAP_SYS_CHROOT       18#define CAP_SYS_PTRACE       19#define CAP_SYS_PACCT        20#define CAP_SYS_ADMIN        21#define CAP_SYS_BOOT         22#define CAP_SYS_NICE         23#define CAP_SYS_RESOURCE     24#define CAP_SYS_TIME         25#define CAP_SYS_TTY_CONFIG   26#define CAP_MKNOD            27#define CAP_LEASE            28#define CAP_AUDIT_WRITE      29#define CAP_AUDIT_CONTROL    30#define CAP_SETFCAP          31#define CAP_MAC_OVERRIDE     32#define CAP_MAC_ADMIN        33#define CAP_SYSLOG           34#define CAP_WAKE_ALARM            35#define CAP_BLOCK_SUSPEND    36#define CAP_AUDIT_READ          37

最后在看下windowsNT内核是没有capability模型的,但是它有privilege模型。

Winnt.h:
#define SE_CREATE_TOKEN_NAME                        #define SE_ASSIGNPRIMARYTOKEN_NAME                   #define SE_LOCK_MEMORY_NAME                        #define SE_INCREASE_QUOTA_NAME                      #define SE_UNSOLICITED_INPUT_NAME                    #define SE_MACHINE_ACCOUNT_NAME                      #define SE_TCB_NAME                                  #define SE_SECURITY_NAME                             #define SE_TAKE_OWNERSHIP_NAME                       #define SE_LOAD_DRIVER_NAME                         #define SE_SYSTEM_PROFILE_NAME                      #define SE_SYSTEMTIME_NAME                          #define SE_PROF_SINGLE_PROCESS_NAME                  #define SE_INC_BASE_PRIORITY_NAME #define SE_CREATE_PAGEFILE_NAME                      #define SE_CREATE_PERMANENT_NAME                    #define SE_BACKUP_NAME                              #define SE_RESTORE_NAME                             #define SE_SHUTDOWN_NAME #define SE_DEBUG_NAME                               #define SE_AUDIT_NAME                                #define SE_SYSTEM_ENVIRONMENT_NAME                   #define SE_CHANGE_NOTIFY_NAME                      #define SE_REMOTE_SHUTDOWN_NAME                      #define SE_UNDOCK_NAME                               #define SE_SYNC_AGENT_NAME                           #define SE_ENABLE_DELEGATION_NAME                    #define SE_MANAGE_VOLUME_NAME                        #define SE_IMPERSONATE_NAME                          #define SE_CREATE_GLOBAL_NAME                        #define SE_TRUSTED_CREDMAN_ACCESS_NAME               #define SE_RELABEL_NAME                              #define SE_INC_WORKING_SET_NAME                      #define SE_TIME_ZONE_NAME                            #define SE_CREATE_SYMBOLIC_LINK_NAME                 #define SE_DELEGATE_SESSION_USER_IMPERSONATE_NAME

文章来源: https://mp.weixin.qq.com/s?__biz=Mzg4NjU1NDU4MA==&mid=2247483694&idx=1&sn=e104a4df6dd698fce0fa40fccd6004e6&chksm=cf96ab95f8e12283ed6d5eddba19537914264794c87ba73c490f677f47f4bd5920991a708a77&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh