Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/rainbow/rainbow/gc.py
blob: 219836717356ead190a4fdafd133a89012b3e851 (plain)
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
38
39
40
41
42
43
44
45
46
47
48
49
50
from subprocess import call, check_call, CalledProcessError
from os import listdir, unlink
from os.path import join, isdir, islink, exists
from rainbow.util import trace

def active_uid(uid):
    cmd = ['/usr/bin/pgrep', '-U', uid]
    ret = call(cmd, stdout=open('/dev/null'))
    if ret in (0, 1):
        return ret == 0
    raise CalledProcessError(ret, cmd)

def gc_uid(spool, uid):
    """This function conservatively attempts to garbage-collect stale uid
    reservations.
    """

    # XXX: D-Bus caches passwd-db data!
    # XXX: D-Bus uses a fixed 1k passwd buffer - be careful with long paths &
    #      comments

    reservation = join(spool, 'uid_pool', uid)
    assert not isdir(reservation) and not islink(reservation)

    # XXX: We perform several execv()'s as root based on strings derived from
    # this 'uid' parameter, which originates as a file-name in a user-writable
    # directory. Better ideas for input validation would be welcome.
    uid_num = int(uid)
    assert uid_num >= 1000 and uid_num <= 65534  # XXX: magic numbers from util/spool.py

    if active_uid(uid):
        return

    for table in ('uid_to_instance_dir', 'uid_to_home_dir', 'uid_to_gid'):
        row = join(spool, table, uid)
        # NB: it is important that rm -rf doesn't follow links. <MS>
        check_call(['/bin/rm', '-r', '-f', row])

    # So long as we unlink the reservation last, we run no risk of seeing inconsistency
    unlink(reservation)

def gc_spool(log, spool):
    uspool = join(spool, 'uid_pool')
    if exists(uspool) and isdir(uspool):
        for maybe_uid in listdir(uspool):
            try: gc_uid(spool, maybe_uid)
            except: trace()
    else:
        log(1, "Skipping spool %s", spool)