binary进程的selinux domain初始化过程(初稿,待整理)
虽然在各种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_CREDENTIALS 113 atomic_t subscribers; /* number of processes subscribed */ 114 void *put_addr; 115 unsigned magic; 116 #define CRED_MAGIC 0x43736564 117 #define CRED_MAGIC_DEAD 0x44656144 118 #endif 119 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_KEYS 134 unsigned char jit_keyring; /* default keyring to attach requested 135 * 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 #endif 141 #ifdef CONFIG_SECURITY 142 void *security; /* subjective LSM security */ 143 #endif 144 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对象关联; 通过上述四步,完成了将一个struct cred对象关联到一个实体的进程对应的task对象。完成对某个binary进程的selinux domain初始化。 因为exec的系统调用的caller是和新创建的进程可能属于不同domain,其中涉及到domain的transition,在做transition的过程中,必然会涉及到权限的检查。在上述的四个步骤中,涉及到权限检查的函数调用包括但不限于下面两个: 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 not 2324 * 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 allowed 2360 * 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 that 2397 * 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对象中: 1409 /* 1410 * install the new credentials for this executable 1411 */ 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 users 1421 * when executing setuid binaries. Must 1422 * wait until new credentials are committed 1423 * by commit_creds() above 1424 */ 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 prevent 1429 * ptrace_attach() from altering our determination of the task‘s 1430 * credentials; any time after this it may be unlocked. 1431 */ 1432 security_bprm_committed_creds(bprm); 1433 mutex_unlock(¤t->signal->cred_guard_mutex); 1434 } 上述两个函数调用都会调用权限检查:avc_has_perm,该函数的定义如下: 1126 /** 1127 * avc_has_perm - Check permissions and perform any appropriate auditing. 1128 * @ssid: source security identifier 1129 * @tsid: target security identifier 1130 * @tclass: target security class 1131 * @requested: requested permissions,interpreted based on @tclass 1132 * @auditdata: auxiliary audit data 1133 * 1134 * Check the AVC to determine whether the @requested permissions are granted 1135 * for the SID pair (@ssid,@tsid),interpreting the permissions 1136 * based on @tclass,and call the security server on a cache miss to obtain 1137 * a new decision and add it to the cache. Audit the granting or denial of 1138 * permissions in accordance with the policy. Return %0 if all @requested 1139 * permissions are granted,-%EACCES if any permissions are denied,or 1140 * 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文件有什么关系? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |