Jastes 2022. 11. 13. 23:00

_rtld_global

๋ฆฌ๋ˆ…์Šค ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์— ๋ช…์‹œ๋œ ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๊ฐ’์ด ์šฐ๋ฆฌ์—๊ฒŒ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.
ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋˜์–ด ํ”„๋กœ์„ธ์Šค๋กœ ๋“ฑ๋ก ์‹œ ํ”„๋กœ๊ทธ๋žจ์— ๋ช…์‹œ๋œ ์ฝ”๋“œ๋ฟ๋งŒ ์•„๋‹Œ ํ”„๋กœ๊ทธ๋žจ์—์„œ
์‚ฌ์šฉ๋˜๋Š” ๋ณ€์ˆ˜ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์—ฌ์—ญ์„ ํ• ๋‹นํ•˜๋Š” ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ์ฝ”๋“œ๊ฐ€ ๋กœ๋”์— ์˜ํ•ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋“ฑ๋ก๋˜๊ฑฐ๋‚˜ ์ข…๋ฃŒ ์‹œ ์“ฐ์ด๋Š” ๋ณ€์ˆ˜์™€ ์˜์—ญ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์˜ ๊ณต๊ฒฉ ๊ธฐ๋ฒ• ๊ฐœ๋ฐœ!
๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ €ํฌ ๋ณด์•ˆ์ชฝ์—์„  ์ด๋Ÿฐ ๊ตฌ์กฐ์™€ ๊ตฌ๋™์„ ์ดํ•ดํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค ๊ฐ™์ด ์•Œ์•„๋ด…์‹œ๋‹ค.

1
2
3
4
5
// Name: rtld.c
// Compile: gcc -o rtld rtld.c
int main() {
  return 0;
}
cs

__GI_exit

์•ž์„œ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ๋ณด์‹œ๋ฉด ๋ณ„๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰X ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
์ข…๋ฃŒ์‹œ์— ์šฐ๋ฆฌ๊ฐ€ ๋ชจ๋ฅด๋Š” ๋งŽ์€ ์ฝ”๋“œ๋“ค์ด ๋‚ด๋ถ€์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š”๋ฐ, ํ•œ๋ฒˆ ์‚ดํŽด๋ด…์‹œ๋‹ค.

์ผ๋‹จ main ํ•จ์ˆ˜ ๋‚ด ๋ฆฌํ„ดํ•˜๋Š” ๋ช…๋ น์–ด์— ๋ธŒํฌ๋ฅผ ์„ค์ • si๋ฅผ ํ†ตํ•ด ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด..
๋””๋ฒ„๊น… ๊ฒฐ๊ณผ์—” main ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ฆฌํ„ด ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ ์‹œ ์Šคํƒ ์ตœ์ƒ๋‹จ์— ์žˆ๋Š” __lib_start_main+122์˜
์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ณ , ๋‚ด๋ถ€์—” exitํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ €์˜ ํ™˜๊ฒฝ์—์„  ์ด๋ ‡๊ฒŒ ๋‚˜์˜ค๋Š”๋ฐ Dreamhack์—์„  ๋‹ค๋ฅด๋„ค์š” ใ… 

์œ„์— ์˜ค๋ฅธ์ชฝ์— exitํ•จ์ˆ˜์˜ ๋‚ด๋ถ€ ๋ชจ์Šต์—, ๋˜ ๋‹ค๋ฅธ __run_exit_handlersํ•จ์ˆ˜๊ฐ€ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.
ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ์ฝ”๋“œ์˜ ํฌ๊ธฐ๊ฐ€ ํฌ๋ฏ€๋กœ, lib์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋ถ„์„ํ•ด๋ด…์‹œ๋‹ค.


__run_exit_handlers

์ด์ œ๋ถ€ํ„ด Dreamhack์˜ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•ฉ์‹œ๋‹ค..(์‹ค์Šต์ด ์•ˆ๋˜๊ฒ ๋„ค์š” ใ… )

__run_exit_handlers ํ•จ์ˆ˜
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void
attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp,
             bool run_list_atexit, bool run_dtors)
{
      const struct exit_function *const f = &cur->fns[--cur->idx];
      switch (f->flavor)
        {
          void (*atfct) (void);
          void (*onfct) (int status, void *arg);
          void (*cxafct) (void *arg, int status);
        case ef_free:
        case ef_us:
          break;
        case ef_on:
          onfct = f->func.on.fn;
#ifdef PTR_DEMANGLE
          PTR_DEMANGLE (onfct);
#endif
          onfct (status, f->func.on.arg);
          break;
        case ef_at:
          atfct = f->func.at;
#ifdef PTR_DEMANGLE
          PTR_DEMANGLE (atfct);
#endif
          atfct ();
          break;
        case ef_cxa:
          cxafct = f->func.cxa.fn;
#ifdef PTR_DEMANGLE
          PTR_DEMANGLE (cxafct);
#endif
          cxafct (f->func.cxa.arg, status);
          break;
        }
    }
cs

__run_exit_handlers ํ•จ์ˆ˜์˜ ์ฝ”๋“œ๋กœ, exit_function ๊ตฌ์กฐ์ฒด์˜ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์— ๋”ฐ๋ฅธ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ํ˜ธ์ถœ
ํ•ด๋‹น ๊ตฌ์กฐ์ฒด์˜ ๋ชจ์Šต์€ ์œ„์™€ ๊ฐ™์œผ๋ฉฐ, _dl_fini ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

exit_function ๊ตฌ์กฐ์ฒด
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct exit_function
{
/* `flavour' should be of type of the `enum' above but since we need
   this element in an atomic operation we have to use `long int'.  */
long int flavor;
union
  {
void (*at) (void);
struct
  {
    void (*fn) (int status, void *arg);
    void *arg;
  } on;
struct
{
    void (*fn) (void *arg, int status);
    void *arg;
    void *dso_handle;
  } cxa;
  } func;
};
cs

__dl_fini

__dl_fini ํ•จ์ˆ˜
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct exit_function
{
/* `flavour' should be of type of the `enum' above but since we need
   this element in an atomic operation we have to use `long int'.  */
long int flavor;
union
  {
void (*at) (void);
struct
  {
    void (*fn) (int status, void *arg);
    void *arg;
  } on;
struct
{
    void (*fn) (void *arg, int status);
    void *arg;
    void *dso_handle;
  } cxa;
  } func;
};
cs

_dl_fini ํ•จ์ˆ˜ ์ฝ”๋“œ์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ _dl_load_lock์„ ์ธ์ž๋กœ __rtld_lock_lock_recursive
ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งคํฌ๋กœ๋ฅผ ํ™”์ธํ•ด๋ณด๋ฉด, ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€..
dl_rtld_lock_recursive๋ผ๋Š” ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋Š” _rtld_global ๊ตฌ์กฐ์ฒด์˜ ๋งด๋ฒ„ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.
ํ•ด๋‹น ๊ตฌ์กฐ์ฒด๋Š” ๋งค์šฐ ๋ฐฉ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์™€ ์ „๋‹ฌ๋˜๋Š” ์ธ์ž์ธ dl_load_lock๋งŒ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


_rtld_global

gdb์—์„œ _rtld_global ๊ตฌ์กฐ์ฒด๋ฅผ ์ถœ๋ ฅํ•œ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค.
๊ตฌ์กฐ์ฒด ๋‚ด _dl_rtld_lock_recursive ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์—๋Š” rtld_lock_default_lock_recursive ํ•จ์ˆ˜ ์ฃผ์†Œ๋ฅผ ์ €์žฅํ•จ
๊ตฌ์กฐ์ฒด์˜ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๊ฐ€ ์ €์žฅ๋œ ์˜์—ญ์€ rw-๋กœ์จ ๋ฎ์–ด์“ฐ๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

_rtld_global ๊ตฌ์กฐ์ฒด


_rtld_global ์ดˆ๊ธฐํ™”

_rtld_global ํ•จ์ˆ˜ ํฌ์ธํ„ฐ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ
1
2
3
4
5
6
7
8
9
10
11
static void
dl_main (const ElfW(Phdr) *phdr,
     ElfW(Word) phnum,
     ElfW(Addr) *user_entry,
     ElfW(auxv_t) *auxv)
{
  GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
#if defined SHARED && defined _LIBC_REENTRANT \
    && defined __rtld_lock_default_lock_recursive
  GL(dl_rtld_lock_recursive) = rtld_lock_default_lock_recursive;
  GL(dl_rtld_unlock_recursive) = rtld_lock_default_unlock_recursive;
cs

ํ”„๋กœ์„ธ์Šค๋ฅผ ๋กœ๋“œํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” dl_main ์ฝ”๋“œ์˜ ์ผ๋ถ€๋กœ, _rtld_global ๊ตฌ์กฐ์ฒด์˜
dl_rtld_lock_recursive ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๋งˆ์น˜๋ฉฐ

๋ฆฌํ„ด ๋ช…๋ น์–ด๋Š” ์‹ค์ œ๋กœ ๋กœ๋”์—์„œ ๋‹ค์–‘ํ•œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜ ์ค‘ _rtld_global ๊ตฌ์กฐ์ฒด ๋‚ด ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ ์ดˆ๊ธฐํ™”๋˜๋ฉฐ,

์ด๋Š” ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ๋Š” ์˜์—ญ์— ์œ„์น˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž„์˜ ์ฃผ์†Œ์— ๊ฐ’์„ ์“ธ ์ˆ˜ ์žˆ๋Š” ์ทจ์•ฝ์ ์ด ์žˆ๋‹ค๋ฉด
์ด๋ฅผ ๋ฎ์–ด์„œ ์‹คํ–‰ ํ๋ฆ„์„ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


์ฐธ๊ณ  ์ž๋ฃŒ

 

Background: _rtld_global

์ด๋ฒˆ ์ฝ”์Šค์—์„œ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒ๋  ๋•Œ ์‹คํ–‰๋˜๋Š” ๋™์ž‘์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๊ณ , _rtld_global์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

dreamhack.io

์ฐธ๊ณ  ์ด๋ฏธ์ง€