사용자 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 가 있다.

Linux systemd essentials (출처: https://www.techsupportpk.com)

이 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 자원은 임의로 삭제하지 않는다.)

You may also like...

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x