# 시그널을 받는 쪽에서 보이는 신원을 맞춥니다

v6.18.37 / kernel/signal.c

시그널은 번호 하나만 전달하는 일이 아닙니다. 보낸 쪽의 PID와 UID가 받는 태스크의 namespace에서 어떤 뜻인지도 맞춰야 합니다. 이 함수는 시그널 정보를 정리한 뒤 실제 큐 처리 함수로 넘깁니다. 여기서 사용자 핸들러를 바로 호출하는 것은 아닙니다.

## send_signal_locked

```c

int send_signal_locked(int sig, struct kernel_siginfo *info,
		       struct task_struct *t, enum pid_type type)
{
	/* Should SIGKILL or SIGSTOP be received by a pid namespace init? */
	bool force = false;

	if (info == SEND_SIG_NOINFO) {
		/* Force if sent from an ancestor pid namespace */
		force = !task_pid_nr_ns(current, task_active_pid_ns(t));
	} else if (info == SEND_SIG_PRIV) {
		/* Don't ignore kernel generated signals */
		force = true;
	} else if (has_si_pid_and_uid(info)) {
		/* SIGKILL and SIGSTOP is special or has ids */
		struct user_namespace *t_user_ns;

		rcu_read_lock();
		t_user_ns = task_cred_xxx(t, user_ns);
		if (current_user_ns() != t_user_ns) {
			kuid_t uid = make_kuid(current_user_ns(), info->si_uid);
			info->si_uid = from_kuid_munged(t_user_ns, uid);
		}
		rcu_read_unlock();

		/* A kernel generated signal? */
		force = (info->si_code == SI_KERNEL);

		/* From an ancestor pid namespace? */
		if (!task_pid_nr_ns(current, task_active_pid_ns(t))) {
			info->si_pid = 0;
			force = true;
		}
	}
	return __send_signal_locked(sig, info, t, type, force);
}

```

### 1183행

```c

int send_signal_locked(int sig, struct kernel_siginfo *info,

```

시그널 번호 sig와 정보 info를 받아 대상 t의 namespace에서 발신 정보가 올바르게 해석되도록 정리한 뒤 pending 처리 경로에 넘깁니다. 이름의 locked는 호출자가 시그널 상태를 보호하는 잠금 규칙을 지켜야 한다는 의미입니다.

### 1184행

```c

		       struct task_struct *t, enum pid_type type)

```

t는 신호를 받을 태스크이고 type은 개별 태스크인지 스레드 그룹 대상인지 등의 전달 범위를 구분합니다. 이 두 값도 지역변수가 아니라 함수 인자입니다. 포인터가 보관하는 것은 객체의 주소입니다. 이 선언만으로 대상 구조체나 문자열의 내용이 복사되지는 않습니다.

### 1187행

```c

	bool force = false;

```

시그널을 강제로 처리해야 하는 특별한 조건이 아직 없다고 초기화합니다.

### 1189행

```c

	if (info == SEND_SIG_NOINFO) {

```

일반 siginfo 객체 대신 정보 없음이라는 특별한 입력인지를 구분합니다.

### 1191행

```c

		force = !task_pid_nr_ns(current, task_active_pid_ns(t));

```

발신 태스크가 대상 PID namespace에서 보이지 않는지 검사하여 강제 처리 조건을 정합니다.

### 1192행

```c

	} else if (info == SEND_SIG_PRIV) {

```

커널이 지정하는 특별한 시그널 정보 유형으로 분기합니다.

### 1194행

```c

		force = true;

```

이 경로의 커널 요청 또는 namespace 조건 때문에 일반 처리와 다른 force 표시를 설정합니다.

### 1195행

```c

	} else if (has_si_pid_and_uid(info)) {

```

PID와 UID를 실제로 담는 siginfo 형식일 때만 신원 변환을 수행합니다.

### 1197행

```c

		struct user_namespace *t_user_ns;

```

수신 태스크가 속한 user namespace를 담습니다. 발신 UID 숫자를 수신자에게 보이는 번호로 바꾸는 데 사용합니다. 포인터가 보관하는 것은 객체의 주소입니다. 이 선언만으로 대상 구조체나 문자열의 내용이 복사되지는 않습니다.

### 1199행

```c

		rcu_read_lock();

```

참조하는 RCU 보호 객체의 수명이 읽기 도중 끝나지 않도록 읽기 구간을 시작합니다.

### 1200행

```c

		t_user_ns = task_cred_xxx(t, user_ns);

```

대상 태스크의 자격 정보에서 user namespace를 읽습니다. 주변 RCU 구간과 함께 봐야 합니다.

### 1201행

```c

		if (current_user_ns() != t_user_ns) {

```

발신 쪽과 수신 쪽 UID 번호 체계가 다른 경우에만 매핑을 변환합니다.

### 1202행

```c

			kuid_t uid = make_kuid(current_user_ns(), info->si_uid);

```

현재 user namespace의 UID 숫자를 커널 내부 UID 표현으로 바꿉니다.

### 1203행

```c

			info->si_uid = from_kuid_munged(t_user_ns, uid);

```

내부 UID를 받는 쪽 user namespace에서 보이는 번호로 바꿉니다. 매핑이 없을 때의 대체 표현도 처리합니다.

### 1205행

```c

		rcu_read_unlock();

```

RCU 보호 읽기 구간을 끝냅니다. 잠든 독자를 기다리는 일반 mutex unlock과는 다릅니다.

### 1208행

```c

		force = (info->si_code == SI_KERNEL);

```

명시적인 커널 기원 시그널인지 원인 코드를 검사합니다.

### 1211행

```c

		if (!task_pid_nr_ns(current, task_active_pid_ns(t))) {

```

발신자가 대상의 PID namespace에서 표현되지 않는 경우를 처리합니다.

### 1212행

```c

			info->si_pid = 0;

```

대상 namespace에서 나타낼 수 없는 발신 PID를 0으로 표기합니다.

### 1213행

```c

			force = true;

```

이 경로의 커널 요청 또는 namespace 조건 때문에 일반 처리와 다른 force 표시를 설정합니다.

### 1216행

```c

	return __send_signal_locked(sig, info, t, type, force);

```

정리된 시그널 정보와 force 여부를 실제 pending·대상 선택 경로로 넘기고 그 결과를 돌려줍니다.

