사용자 Semaphore 의 자동 삭제 – RemoveIPC
Linux 에서 user 가 생성한 semaphore 를 system 에서 삭제해버리는 현상이 있다.
나도 모르게 내 허락도 안받고 과감하게 날려버린다. 이것들이... 부르르...
(Redhat 뿐 아니라 데스크탑 환경(CenOS7)에서도 재현된다.)
예전에 고객 앞에서 DBMS 검증 테스트를 진행하는 와중에 이러한 현상이 발생해서 DBMS Engine 이 갑자기 Fatal 로 죽어버려서 당황했던 기억이 있다.
이는 systemd 219 버전에서 이슈가 되는 문제이다.
Redhat 또는 CenOS 7 이상의 linux system 에는 user 의 login session 을 관리하는 systemd-logind 라는 process 가 있다.
이 process 가 관리하는 session list 에서 semaphore 를 생성한 user 로 로그인한 session 이 모두 logout 될 경우에 이러한 현상이 재현된다.
단순히 특정 user 로 로그인해서 semaphore 만들고 logout 하기만 하면 재현되는 것이 아니다.
systemd-logind 가 관리하는 session list 에서 해당 user 의 리스트가 모두 삭제될 경우를 만들어내야 재현할 수 있다.
systemd-logind 를 제어 및 모니터링할 수 있는 utility(loginctl)를 통해서 session list 를 확인해가며 재현해야 한다.
재현 조건은 다음과 같다.
- RemoveIPC = yes 일 것 (/etc/systemd/logind.conf)
- uuid 는 1000 보다 클 것
(system user 와 사용자 user 를 구분하는 기준 -> /etc/login.defs 에서 설정 가능) - IPC 를 생성한 user 의 login session 이 모두 logout 될 것
(systemd-logind 의 기준에서 logout 일 것 - loginctl list-sessions 목록에서 삭제되는 것
위의 조건 중에서 3 번 조건을 정확히 만들어내지 못해서 재현이 좀 어렵다.
코드를 간단하게 짜서 확실한 재현방법을 만들어 보았다.
--------------------------------------------------------------------------- 1. 최초에 semaphore 생성된 것이 없음을 확인한다. --------------------------------------------------------------------------- ╭─root@localhost ~ ╰─$ ipcs -s ------ Semaphore Arrays -------- key semid owner perms nsems --------------------------------------------------------------------------- 2. loginctl list-sessions 를 통해 현재 systemd-logind 가 인식하고 있는 session list 를 확인한다. (root 계정으로 한 session 이 login 되어 있음) --------------------------------------------------------------------------- ╭─dplee@localhost ~ ╰─$ loginctl list-sessions SESSION UID USER SEAT 1 0 root seat0 1 sessions listed. --------------------------------------------------------------------------- 3. RemoveIPC = yes 로 설정되어 있고, systemd-logind 데몬이 기동중인지 확인한다. (만약 RemoveIPC = yes 로 설정하고 이를 적용하려면 systemctl restart systemd-logind 실행) --------------------------------------------------------------------------- ╭─root@localhost ~ ╰─$ cat /etc/systemd/logind.conf | grep RemoveIPC RemoveIPC=yes ╭─root@localhost ~ ╰─$ ps -ef | grep systemd | grep login root 923 1 0 12:26 ? 00:00:00 /usr/lib/systemd/systemd-logind --------------------------------------------------------------------------- 4. 시험용 계정(dplee2)으로 전환하여 semaphore 생성 프로그램을 실행한다. --------------------------------------------------------------------------- ╭─root@localhost ~ ╰─$ su - dplee2 마지막 로그인: 금 3월 2 12:27:42 KST 2018 일시 pts/0 ╭─dplee2@localhost ~ ╰─$ cd work/test ╭─dplee2@localhost ~/work/test ╰─$ cat t.c #include <sys/types.h> #include <sys/sem.h> #include <sys/ipc.h> #include <stdio.h> #include <unistd.h> union semun { int val; struct semid_ds *buf; unsigned short int *array; }; static int semid; int main(int argc, char **argv) { FILE* fp; union semun sem_union; struct sembuf mysem_open = {0, -1, SEM_UNDO}; struct sembuf mysem_close = {0, 1, SEM_UNDO}; int sem_num; sem_num = 1; semid = semget(IPC_PRIVATE, sem_num, 0600|IPC_CREAT); if (semid == -1) { perror("semget error "); return -1; } sem_union.val = 1; if ( -1 == semctl( semid, 0, SETVAL, sem_union)) { printf( "semctl()-SETVAL 실행 오류\n"); return -1; } while(1) { sleep(1); } return 1; } ╭─dplee2@localhost ~/work/test ╰─$ nohup ./a.out & [1] 4602 nohup: ignoring input and appending output to `nohup.out' --------------------------------------------------------------------------- 5. dplee2 계정으로 semaphore 가 생성되고, process 가 기동중인지를 확인한다. --------------------------------------------------------------------------- ╭─dplee2@localhost ~/work/test ╰─$ ipcs -s ------ Semaphore Arrays -------- key semid owner perms nsems 0x00000000 229376 dplee2 600 1 ╭─dplee2@localhost ~/work/test ╰─$ ps -ef | grep dplee2 | grep a.out dplee2 4602 4537 0 12:30 pts/0 00:00:00 ./a.out --------------------------------------------------------------------------- 5. systemd-logind 가 아직은 최초 session(root) 하나만 접속하고 있는 것으로 인식하고 있다. (dplee2 세션이 아닌 것이 중요함) 즉, 아직까지 systemd-logind 데몬은 dplee2 session 은 하나도 없다고 인식하고 있다. --------------------------------------------------------------------------- ╭─dplee2@localhost ~/work/test ╰─$ loginctl list-sessions SESSION UID USER SEAT 1 0 root seat0 1 sessions listed. --------------------------------------------------------------------------- 6. 다른 창으로 시험 서버의 시험계정(dplee2 )으로 직접 접속한다. (dplee2 session 이 SESSION id 3 번으로 신규 생겼음을 list-sessions 에서 확인할 수 있다.) --------------------------------------------------------------------------- $ ssh dplee2@192.168.0.33 ╭─dplee2@localhost ~/work/test ╰─$ loginctl list-sessions SESSION UID USER SEAT 1 0 root seat0 3 1005 dplee2 2 sessions listed. --------------------------------------------------------------------------- 7. 아직 semaphore 는 생성된 채로 남아있고, process 도 기동 중임을 확인한다. --------------------------------------------------------------------------- ╭─dplee2@localhost ~/work/test ╰─$ ipcs -s ------ Semaphore Arrays -------- key semid owner perms nsems 0x00000000 229376 dplee2 600 1 ╭─dplee2@localhost ~/work/test ╰─$ ps -ef | grep dplee2 | grep a.out dplee2 4602 4537 0 12:30 pts/0 00:00:00 ./a.out --------------------------------------------------------------------------- 8. 두번째로 login 했던 dplee2 session 창을 닫거나 logout 해버린다. (loginctl terminate-session 3 명령을 통해서 강제로 끊을 수도 있다.) 최초의 root session 이외에 dplee2 session 은 사라졌다. --------------------------------------------------------------------------- ╭─root@localhost ~/work/test ╰─$ loginctl list-sessions SESSION UID USER SEAT 1 0 root seat0 1 sessions listed. --------------------------------------------------------------------------- 9. 아직 process 는 기동 중인 상태에서 semaphore 만 사라졌음을 확인한다. --------------------------------------------------------------------------- ╭─root@localhost ~/work/test ╰─$ ps -ef | grep dplee2 | grep a.out dplee2 4602 4537 0 12:30 pts/0 00:00:00 ./a.out ╭─root@localhost ~/work/test ╰─$ ipcs -s ------ Semaphore Arrays -------- key semid owner perms nsems
위의 현상을 회피하는 방법은 두가지라고 보면 되겠다.
이는 IPC 자원을 생성, 사용하는 Software 들에게 모두 해당되는 사안이라고 할 수 있다.
조심하고 기억하자.
- RemoveIPC=no 로 운영할 것
- /etc/login.defs 의 설정에서 UID_MIN, SYS_UID_MAX 를 변경하여 system user 의 경계를 변경하여, 사용자 user 를 system user 로 인식하도록 할 것. (system user 로 인식되는 user 가 생성한 IPC 자원은 임의로 삭제하지 않는다.)