linux内核setuid分析

最近在看linux内核文件系统的代码,发现有关权限管理的代码好多,最近索性一次性解决,一劳永逸。
我们先看一个我们在用户空间经常使用的一个setuid函数,这个函数就是变更当前进程的uid,对应的内核函数首先是sys_setuid,这个函数定义在kernel/sys.c,定义如下
asmlinkage long sys_setuid(uid_t uid)
{
	/*保存以前的euid,就是有效用户组ID*/
	int old_euid = current->euid;
	int old_ruid, old_suid, new_suid;
	int retval;
	/*安全检查,如果没有配置内核支持安全操作就是空,暂时不用管*/
	retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
	if (retval)
		return retval;
	/*保存旧的uid,suid*/
	old_ruid = current->uid;
	old_suid = current->suid;
	new_suid = old_suid;
	/*之前讲解过,检验有没有setuid的权限*/
	if (capable(CAP_SETUID)) {
		/*如果有对应的权限,变更进程的真实用户号*/
		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
			return -EAGAIN;
		new_suid = uid;
	} /*没有权限,并且设置的权限还和以前的不一样,(肯定不一样,一样还设置个卵子),就返回权限错误*/
	else if ((uid != current->uid) && (uid != new_suid))
		return -EPERM;
	/*euid改变时,不允许产生dump文件*/
	if (old_euid != uid) {
		current->mm->dumpable = suid_dumpable;
		smp_wmb();
	}
	/*更改进程结构体的fsuid和suid和euid*/
	current->fsuid = current->euid = uid;
	current->suid = new_suid;


	key_fsuid_changed(current);
	proc_id_connector(current, PROC_EVENT_UID);
	/*安全操作,暂不管*/
	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}

我们继续看set_user改变真实uid,set_user函数定义如下
static int set_user(uid_t new_ruid, int dumpclear)
{
	struct user_struct *new_user;
	/*由于user_struct都是按照hash值链接的,所以根据新的uid分配user_struct结构体*/
	new_user = alloc_uid(new_ruid);
	if (!new_user)
		return -EAGAIN;
	/*如果这个用户拥有的进程数目超出了限制就返回错误*/
	if (atomic_read(&new_user->processes) >=
				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
			new_user != &root_user) {
		free_uid(new_user);
		return -EAGAIN;
	}
	/*变更当前进程的user_struct结构体*/
	switch_uid(new_user);
	/*如果euid变,就不允许产生dump文件*/
	if (dumpclear) {
		current->mm->dumpable = suid_dumpable;
		smp_wmb();
	}
	/*当前进程的uid变*/
	current->uid = new_ruid;
	return 0;
}


我们继续看switch_uid函数,switch_uid函数定义如下
void switch_uid(struct user_struct *new_user)
{
	/*指针指向旧的user_struct结构体*/
	struct user_struct *old_user;


	/* What if a process setreuid()'s and this brings the
	 * new uid over his NPROC rlimit?  We can check this now
	 * cheaply with the new uid cache, so if it matters
	 * we should be checking for it.  -DaveM
	 */
	old_user = current->user;
	/*新的user_struct计数加一,旧的计数减一*/
	atomic_inc(&new_user->processes);
	atomic_dec(&old_user->processes);
	switch_uid_keyring(new_user);
	/*当前进程结构体的user_struct指向新的user_struct*/
	current->user = new_user;


	/*
	 * We need to synchronize with __sigqueue_alloc()
	 * doing a get_uid(p->user).. If that saw the old
	 * user value, we need to wait until it has exited
	 * its critical region before we can free the old
	 * structure.
	 */
	smp_mb();
	spin_unlock_wait(¤t->sighand->siglock);
	/*释放旧的结构体*/
	free_uid(old_user);
	suid_keys(current);
}

你可能感兴趣的:(文件系统)