binary进程的selinux domain初始化过程(初稿,待整理)

binary进程的selinux domain初始化过程(初稿,待整理),第1张

概述虽然在各种context文件中声明了每个subject对应的domain,可是这个domain是如何与一个进程关联的呢? 把一个domain与一个进程关联分为两种: 1)fork出来进程以后,然后通过传递参数的方式动态的修改新进程的domain; 2)通过exec某个binary启动进程,该新启动进程的domain是由其对应的binary object的context决定。 但是无论是哪种启动方式 虽然在各种context文件中声明了每个subject对应的domain,可是这个domain是如何与一个进程关联的呢?
把一个domain与一个进程关联分为两种:
1)fork出来进程以后,然后通过传递参数的方式动态的修改新进程的domain;
2)通过exec某个binary启动进程,该新启动进程的domain是由其对应的binary object的context决定。
但是无论是哪种启动方式,最终的结果就是在内核中创建一个struct cred对象,然后与之关联到进程对应的task对象。
struct cred的定义如下,include/linux/cred.h:110

110 struct cred {111         atomic_t        usage;112 #ifdef CONfig_DEBUG_CREDENTIALS113         atomic_t        subscribers;    /* number of processes subscribed */114         voID            *put_addr;115         unsigned        magic;116 #define CRED_MAGIC      0x43736564117 #define CRED_MAGIC_DEAD 0x44656144118 #endif119         kuID_t          uID;            /* real UID of the task */120         kgID_t          gID;            /* real GID of the task */121         kuID_t          suID;           /* saved UID of the task */122         kgID_t          sgid;           /* saved GID of the task */123         kuID_t          euID;           /* effective UID of the task */124         kgID_t          egID;           /* effective GID of the task */125         kuID_t          fsuID;          /* UID for VFS ops */126         kgID_t          fsgid;          /* GID for VFS ops */127         unsigned        securebits;     /* SUID-less security management */128         kernel_cap_t    cap_inheritable; /* caps our children can inherit */129         kernel_cap_t    cap_permitted;  /* caps we‘re permitted */130         kernel_cap_t    cap_effective;  /* caps we can actually use */131         kernel_cap_t    cap_bset;       /* capability bounding set */132         kernel_cap_t    cap_ambIEnt;    /* AmbIEnt capability set */133 #ifdef CONfig_KEYS134         unsigned char   jit_keyring;    /* default keyring to attach requested135                                          * keys to */136         struct key __rcu *session_keyring; /* keyring inherited over fork */137         struct key      *process_keyring; /* keyring private to this process */138         struct key      *thread_keyring; /* keyring private to this thread */139         struct key      *request_key_auth; /* assumed request_key authority */140 #endif141 #ifdef CONfig_Security142         voID            *security;      /* subjective LSM security */143 #endif144         struct user_struct *user;       /* real user ID subscription */145         struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */146         struct group_info *group_info;  /* supplementary groups for euID/fsgid */147         struct rcu_head rcu;            /* RCU deletion hook */148 };

而我们比较关系的与selinux相关的部分,即对struct cred对象的中的voID *security成员变量的初始化

相对而言,第一种方式相对简单,再次不做重点介绍。重点介绍的是第二种方式,以系统调用exec作为入口,代码如下fs/exe.c所示:

1674 /*1675  * sys_execve() executes a new program.1676  */1677 static int do_execveat_common(int fd,struct filename *filename,1678                               struct user_arg_ptr argv,1679                               struct user_arg_ptr envp,1680                               int flags)1681 {1682         char *pathbuf = NulL;1683         struct linux_binprm *bprm;1684         struct file *file;1685         struct files_struct *displaced;1686         int retval;...1716         retval = prepare_bprm_creds(bprm);...1730         bprm->file = file;...1754         retval = bprm_mm_init(bprm);...1766         retval = prepare_binprm(bprm);...1785         retval = exec_binprm(bprm);

第一步:prepare_bprm_creds,创建struct cred对象,并创建struct task_security_struct对象赋予struct cred的security成员变量,并将struct cred对象与struct linux_binprm对象关联;
prepare_bprm_creds==> prepare_exec_creds==>prepare_creds==>selinux_cred_prepare
第二步:初始化struct linux_binprm中的file成员变量,将其对应真正的文件,用于从从file映射到inode,然后从node获取object的security context,然后从security context变成security ID;
第三步:prepare_binprm,真正初始化struct cred,将其所有成员变量都对应到正确的值;
prepare_binprm==>security_bprm_set_creds==>selinux_bprm_set_creds
第四步:exec_binprm,将新创建的struct cred对象与进程对应的task对象关联;
exec_binprm==> search_binary_handler==>load_elf_binary==>install_exec_creds==>commit_creds

通过上述四步,完成了将一个struct cred对象关联到一个实体的进程对应的task对象。完成对某个binary进程的selinux domain初始化。

因为exec的系统调用的caller是和新创建的进程可能属于不同domain,其中涉及到domain的Transition,在做Transition的过程中,必然会涉及到权限的检查。在上述的四个步骤中,涉及到权限检查的函数调用包括但不限于下面两个:
1)security_bprm_set_creds,完成struct cred的真正初始化;
security/selinux/hooks.c:2314

2314 static int selinux_bprm_set_creds(struct linux_binprm *bprm)2315 {2316         const struct task_security_struct *old_tsec;2317         struct task_security_struct *new_tsec;2318         struct inode_security_struct *isec;2319         struct common_audit_data ad;2320         struct inode *inode = file_inode(bprm->file);2321         int rc;2322 2323         /* SElinux context only depends on initial program or script and not2324          * the script interpreter */2325         if (bprm->cred_prepared)2326                 return 0;2327 2328         old_tsec = current_security();2329         new_tsec = bprm->cred->security;2330         isec = inode_security(inode);2331 2332         /* Default to the current task SID. */2333         new_tsec->sID = old_tsec->sID;2334         new_tsec->osID = old_tsec->sID;2335 2336         /* reset fs,key,and sock SIDs on execve. */2337         new_tsec->create_sID = 0;2338         new_tsec->keycreate_sID = 0;2339         new_tsec->sockcreate_sID = 0;2340 2341         if (old_tsec->exec_sID) {2342                 new_tsec->sID = old_tsec->exec_sID;2343                 /* reset exec SID on execve. */2344                 new_tsec->exec_sID = 0;2345 2346                 /* Fail on NNP or nosuID if not an allowed Transition. */2347                 rc = check_nnp_nosuID(bprm,old_tsec,new_tsec);2348                 if (rc)2349                         return rc;2350         } else {2351                 /* Check for a default Transition on this program. */2352                 rc = security_Transition_sID(old_tsec->sID,isec->sID,2353                                              SEcclASS_PROCESS,NulL,2354                                              &new_tsec->sID);2355                 if (rc)2356                         return rc;2357 2358                 /*2359                  * Fallback to old SID on NNP or nosuID if not an allowed2360                  * Transition.2361                  */2362                 rc = check_nnp_nosuID(bprm,new_tsec);2363                 if (rc)2364                         new_tsec->sID = old_tsec->sID;2365         }2366 2367         ad.type = LSM_AUDIT_DATA_file;2368         ad.u.file = bprm->file;2369 2370         if (new_tsec->sID == old_tsec->sID) {2371                 rc = avc_has_perm(old_tsec->sID,2372                                   SEcclASS_file,file__EXECUTE_NO_TRANS,&ad);2373                 if (rc)2374                         return rc;2375         } else {2376                 /* Check permissions for the Transition. */2377                 rc = avc_has_perm(old_tsec->sID,new_tsec->sID,2378                                   SEcclASS_PROCESS,PROCESS__Transition,&ad);2379                 if (rc)2380                         return rc;2381 2382                 rc = avc_has_perm(new_tsec->sID,2383                                   SEcclASS_file,file__ENTRYPOINT,&ad);2384                 if (rc)2385                         return rc;2386 2387                 /* Check for shared state */2388                 if (bprm->unsafe & LSM_UNSAFE_SHARE) {2389                         rc = avc_has_perm(old_tsec->sID,2390                                           SEcclASS_PROCESS,PROCESS__SHARE,2391                                           NulL);2392                         if (rc)2393                                 return -EPERM;2394                 }2395 2396                 /* Make sure that anyone attempting to ptrace over a task that2397                  * changes its SID has the appropriate permit */2398                 if (bprm->unsafe &2399                     (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {2400                         u32 ptsID = ptrace_parent_sID(current);2401                         if (ptsID != 0) {2402                                 rc = avc_has_perm(ptsID,2403                                                   SEcclASS_PROCESS,2404                                                   PROCESS__PTRACE,NulL);2405                                 if (rc)2406                                         return -EPERM;2407                         }2408                 }2409 2410                 /* Clear any possibly unsafe personality bits on exec: */2411                 bprm->per_clear |= PER_CLEAR_ON_SETID;2412         }2413 2414         return 0;2415 }

2)install_exec_creds,完成将一个struct cred对象关联到一个task对象中:
fs/exec.c:1409

1409 /*1410  * install the new credentials for this executable1411  */1412 voID install_exec_creds(struct linux_binprm *bprm)1413 {                                                                                                                                                                                                         1414         security_bprm_committing_creds(bprm);1415 1416         commit_creds(bprm->cred);1417         bprm->cred = NulL;1418 1419         /*1420          * disable monitoring for regular users1421          * when executing setuID binarIEs. Must1422          * wait until new credentials are committed1423          * by commit_creds() above1424          */1425         if (get_dumpable(current->mm) != SUID_DUMP_USER)1426                 perf_event_exit_task(current);1427         /*1428          * cred_guard_mutex must be held at least to this point to prevent1429          * ptrace_attach() from altering our determination of the task‘s1430          * credentials; any time after this it may be unlocked.1431          */1432         security_bprm_committed_creds(bprm);1433         mutex_unlock(&current->signal->cred_guard_mutex);1434 }

上述两个函数调用都会调用权限检查:avc_has_perm,该函数的定义如下:
security/selinux/avc.c:1126

1126 /**1127  * avc_has_perm - Check permissions and perform any appropriate auditing.1128  * @ssID: source security IDentifIEr1129  * @tsID: target security IDentifIEr1130  * @tclass: target security class1131  * @requested: requested permissions,interpreted based on @tclass1132  * @auditdata: auxiliary audit data1133  *1134  * Check the AVC to determine whether the @requested permissions are granted1135  * for the SID pair (@ssID,@tsID),interpreting the permissions1136  * based on @tclass,and call the security server on a cache miss to obtain1137  * a new decision and add it to the cache.  Audit the granting or denial of1138  * permissions in accordance with the policy.  Return %0 if all @requested1139  * permissions are granted,-%EACCES if any permissions are denIEd,or1140  * another -errno upon other errors.1141  */1142 int avc_has_perm(u32 ssID,u32 tsID,u16 tclass,1143                  u32 requested,struct common_audit_data *auditdata)1144 {1145         struct av_decision avd;1146         int rc,rc2;1147 1148         rc = avc_has_perm_noaudit(ssID,tsID,tclass,requested,&avd);1149 1150         rc2 = avc_audit(ssID,&avd,rc,auditdata,0);1151         if (rc2)1152                 return rc2;1153         return rc;1154 }

这个函数完成的功能即是,检查source subject所属的security ID有没有对target subject(object)所属的security ID拥有class参数和request参数声明的权限。

那么问题来了。。。。。。

那么security ID是什么?它与selinux的配置文件XXX_context和XXX.te文件有什么关系?class是什么?它和XXX_context和XXX.te文件有什么关系?kernel是如何决策的?决策过程和XXX_context和XXX.te文件有什么关系?

总结

以上是内存溢出为你收集整理的binary进程的selinux domain初始化过程(初稿,待整理)全部内容,希望文章能够帮你解决binary进程的selinux domain初始化过程(初稿,待整理)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/1030704.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存