Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • commit_creds() 함수는 현재 프로세스에 새 자격 증명 설치, 다음과 같이 동작합니다.
    • current가 가지고 있는 현재 프로세스의 정보를 task에 저장합니다.
    • task 구조체를 이용하여 현재 프로세스가 사용중인 자격 증명 정보를 old 변수에 저장합니다.
    • BUG_ON() 함수를 이용하여 다음과 같은 사항을 확인합니다.
      • "task->cred"과 "old"의 자격증명이 다른지 확인합니다.
      • "&new→usage"에 저장된 값이 1 보다 작은지 확인합니다.
    • get_cred() 함수를 이용하여 new 변수에 저장된 자격 증명 집합에 대한 참조 가져 오기증명에 참조됨 정보를 가져옵니다.
    • uid_eq(), gid_eq() 함수를 이용하여 다음과 같은 구조체 내에 저장된 변수의 값을 확인 합니다.
      • euid,egid는 유효 사용자 식별자(effective user ID, euid)이라는 의미로 프로세스가 파일에 대해 가지는 권한을 뜻합니다.
      • fsuid는 리눅스에는 파일 시스템 접근 제어 용도로 사용되는 파일 시스템 사용자 ID(file system user ID, fsuid)를 뜻합니다.
        • old->euid, new→euid
        • old->egid, new→egid
        • old->fsuid, new→fsuid
        • old->fsgid, new→fsgid
    • cred_cap_issubset() 함수를 이용하여 두 자격 증명이 동일한 사용자 네임 스페이스에 있는지 확인 합니다.
    • 또다시 uid_eq(), gid_eq() 함수를 이용하여 다음과 같은 구조체 내에 저장된 변수의 값을 확인 합니다.
      • new→fsuid, old→fsuid
      • new→fsgid, old→fsgid
      • 값이 다를 경우 key_fsuid_changed(), key_fsgid_changed() 함수를 이용하여 현재 프로세스의 fsuid, fsgid으로 값을 갱신합니다.

Code Block
languagecpp
titlehttps://elixir.bootlin.com/linux/v4.18/source/kernel/cred.c#L423
int commit_creds(struct cred *new)
{
	struct task_struct *task = current;
	const struct cred *old = task->real_cred;

	kdebug("commit_creds(%p{%d,%d})", new,
	       atomic_read(&new->usage),
	       read_cred_subscribers(new));

	BUG_ON(task->cred != old);
#ifdef CONFIG_DEBUG_CREDENTIALS
	BUG_ON(read_cred_subscribers(old) < 2);
	validate_creds(old);
	validate_creds(new);
#endif
	BUG_ON(atomic_read(&new->usage) < 1);

	get_cred(new); /* we will require a ref for the subj creds too */

	/* dumpability changes */
	if (!uid_eq(old->euid, new->euid) ||
	    !gid_eq(old->egid, new->egid) ||
	    !uid_eq(old->fsuid, new->fsuid) ||
	    !gid_eq(old->fsgid, new->fsgid) ||
	    !cred_cap_issubset(old, new)) {
		if (task->mm)
			set_dumpable(task->mm, suid_dumpable);
		task->pdeath_signal = 0;
		smp_wmb();
	}

	/* alter the thread keyring */
	if (!uid_eq(new->fsuid, old->fsuid))
		key_fsuid_changed(task);
	if (!gid_eq(new->fsgid, old->fsgid))
		key_fsgid_changed(task);

	/* do it
	 * RLIMIT_NPROC limits on user->processes have already been checked
	 * in set_user().
	 */
	alter_cred_subscribers(new, 2);
	if (new->user != old->user)
		atomic_inc(&new->user->processes);
	rcu_assign_pointer(task->real_cred, new);
	rcu_assign_pointer(task->cred, new);
	if (new->user != old->user)
		atomic_dec(&old->user->processes);
	alter_cred_subscribers(old, -2);

	/* send notifications */
	if (!uid_eq(new->uid,   old->uid)  ||
	    !uid_eq(new->euid,  old->euid) ||
	    !uid_eq(new->suid,  old->suid) ||
	    !uid_eq(new->fsuid, old->fsuid))
		proc_id_connector(task, PROC_EVENT_UID);

	if (!gid_eq(new->gid,   old->gid)  ||
	    !gid_eq(new->egid,  old->egid) ||
	    !gid_eq(new->sgid,  old->sgid) ||
	    !gid_eq(new->fsgid, old->fsgid))
		proc_id_connector(task, PROC_EVENT_GID);

	/* release the old obj and subj refs both */
	put_cred(old);
	put_cred(old);
	return 0;
}
EXPORT_SYMBOL(commit_creds);

...