标签:ring 对象 reset 调用 nali attach search err temp
虽然在各种context文件中声明了每个subject对应的domain,可是这个domain是如何与一个进程关联的呢?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对象关联;
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 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, old_tsec, 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, isec->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, isec->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, new_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, new_tsec->sid,
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 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,该函数的定义如下:
security/selinux/avc.c:1126
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, 0, &avd);
1149
1150 rc2 = avc_audit(ssid, tsid, tclass, requested, &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初始化过程(初稿,待整理)
标签:ring 对象 reset 调用 nali attach search err temp
原文地址:https://blog.51cto.com/2559640/2365791