Вложенные непривилегированные контейнеры lxc от выскочки, которые может остановить его владелец

4

В хосте под управлением Ubuntu 14.04.5 LTS У меня есть пользователь с именем ci , который может создавать стартовые непривилегированные контейнеры lxc, также запущенные Ubuntu 14.04.5 LTS . Пользователь имеет диапазон субада 200000-231071 . Конфигурационный файл такого контейнера:

# Distribution configuration
lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
lxc.arch = x86_64

# Nested
lxc.mount.auto = cgroup
lxc.aa_profile = lxc-container-default-with-nesting

# Container specific configuration
lxc.id_map = u 0 200000 65536
lxc.id_map = u 100000 265536 65536
lxc.id_map = g 0 200000 65536
lxc.id_map = g 100000 265536 65536
lxc.rootfs = /home/ci/.local/share/lxc/ci/rootfs
lxc.utsname = ci

# Network configuration
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = lxcbr0
lxc.network.hwaddr = 00:16:3e:dd:f1:99

Пользователь может создавать и запускать непривилегированный контейнер без проблем:

[email protected]:~$ lxc-create -t download -n ci -- -d ubuntu -r trusty -a amd64
[email protected]:~$ lxc-start -n ci -d
[email protected]:~$ lxc-ls --fancy
    NAME  STATE    IPV4                 IPV6  AUTOSTART
    ---------------------------------------------------
    ci    RUNNING  10.0.3.75, 10.0.4.1  -     NO

В хосте выполняется cgmanager :

[email protected] ~ # ps ax | grep cgmanager
    382 ?        Ss     0:01 /sbin/cgmanager --sigstop -m name=systemd

В непривилегированном контейнере ci выполняется cgproxy :

[email protected]:~# ps ax | grep cgproxy
    288 ?        Ss     0:00 /sbin/cgproxy --sigstop

В непривилегированном контейнере ci пользователь с именем jenkins с диапазонами субадов 100000-65535 может создавать и запускать в нем непривилегированные контейнеры, т. е. нерентифицированные вложенные контейнеры, но не без каких-либо трюков, которые:

  1. После входа в систему с ssh в качестве пользователя jenkins в непривилегированном контейнере ci результат cat /proc/self/cgroup :

    [email protected]:~$ cat /proc/self/cgroup
        12:hugetlb:/user/1012.user/11.session/lxc/ci
        11:net_prio:/user/1012.user/11.session/lxc/ci
        10:perf_event:/user/1012.user/11.session/lxc/ci
        9:net_cls:/user/1012.user/11.session/lxc/ci
        8:freezer:/user/1012.user/11.session/lxc/ci
        7:devices:/user/1012.user/11.session/lxc/ci
        6:memory:/user/1012.user/11.session/lxc/ci
        5:blkio:/user/1012.user/11.session/lxc/ci
        4:name=systemd:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        3:cpuacct:/user/1012.user/11.session/lxc/ci
        2:cpu:/user/1012.user/11.session/lxc/ci
        1:cpuset:/user/1012.user/11.session/lxc/ci
    
  2. В этот момент jenkins может создать контейнер, но не может его запустить:

    [email protected]:~$ lxc-create -t download -n test -- -d ubuntu -r trusty -a amd64
    [email protected]:~$ lxc-start -n test
        lxc_container: cgmanager.c: lxc_cgmanager_create: 301 call to cgmanager_create_sync failed: invalid request
        lxc_container: cgmanager.c: lxc_cgmanager_create: 303 Failed to create hugetlb:lxc/test
        lxc_container: cgmanager.c: cgm_create: 650 Error creating cgroup hugetlb:lxc/test
        lxc_container: start.c: lxc_spawn: 891 failed creating cgroups
        lxc_container: start.c: __lxc_start: 1121 failed to spawn 'test'
        lxc_container: lxc_start.c: main: 341 The container failed to start.
        lxc_container: lxc_start.c: main: 345 Additional information can be obtained by setting the --logfile and --logpriority options.
    
  3. Я вывожу в контейнер как root:

    restart systemd-logind
    
  4. Теперь в качестве пользователя jenkins в контейнере я выхожу из системы и снова войду в систему с помощью ssh . Группа изменилась, и теперь я могу создать и запустить контейнер:

    [email protected]:~$ cat /proc/self/cgroup
        12:hugetlb:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        11:net_prio:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        10:perf_event:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        9:net_cls:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        8:freezer:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        7:devices:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        6:memory:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        5:blkio:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        4:name=systemd:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        3:cpuacct:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        2:cpu:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
        1:cpuset:/user/1012.user/11.session/lxc/ci/user/1012.user/11.session/lxc/ci/user/107.user/c1.session
    [email protected]:~$ lxc-create -t download -n test -- -d ubuntu -r trusty -a amd64
    [email protected]:~$ lxc-start -n test -d
    [email protected]:~$ lxc-ls --fancy
        NAME     STATE    IPV4       IPV6  AUTOSTART
        --------------------------------------------
        test     RUNNING  10.0.4.64  -     NO
    

Первый вопрос : зачем мне restart systemd-logind и как я могу избежать ввода его как root, прежде чем создавать вложенные непривилегированные контейнеры?

В контейнере ci я создал файл конфигурации init (файл upstart conf в /etc/init/jenkins.conf ) для запуска программного обеспечения Jenkins как пользователь jenkins :

description "jenkins"

start on filesystem and static-network-up
stop on runlevel [016]

env USER="jenkins"
env GROUP="jenkins"
env HOME="/var/lib/jenkins"
env JENKINS_LOG="/var/log/jenkins"
env JENKINS_ROOT="/usr/share/jenkins"
env JENKINS_RUN="/var/run/jenkins"
env JENKINS_PIDFILE="jenkins.pid"

pre-start script
    test -f $JENKINS_ROOT/jenkins.war || { stop ; exit 0; }
    mkdir $JENKINS_RUN > /dev/null 2>&1  || true
    chown -R $USER:$GROUP $JENKINS_RUN || true
    mkdir $JENKINS_LOG > /dev/null 2>&1  || true
    chown -R $USER:$GROUP $JENKINS_LOG || true
end script

script
    . /etc/default/jenkins
    # export XDG_SESSION_ID="/run/user/'id -u $USER'"
    export HOME
    export USER
    export GROUP
    exec daemon --name=jenkins --foreground --inherit --user=$USER:$GROUP --pidfile=$JENKINS_RUN/$JENKINS_PIDFILE --output=$JENKINS_LOG -- $JAVA $JAVA_ARGS -jar $JENKINS_WAR $JENKINS_ARGS
end script

post-start script
    while [ ! -f $JENKINS_RUN/$JENKINS_PIDFILE ]; do sleep 1; done
    PID=$(cat $JENKINS_RUN/$JENKINS_PIDFILE)
    cgm create all $USER
    cgm chown all $USER $(id -u $USER) $(id -g $USER)
    # this need to be run in the jenkins job script:
    # cgm movepid all $USER $$
end script

# vim: ft=upstart

В сценарии, который запускается процесс Jenkins , чтобы запустить так называемую конструкцию Jenkins , если я добавлю строку:

cgm movepid all $USER $$

скрипт может создавать и запускать неграссифицированные вложенные контейнеры, являясь его группой:

+ cat /proc/self/cgroup
12:hugetlb:/user/1012.user/11.session/lxc/ci/jenkins
11:net_prio:/user/1012.user/11.session/lxc/ci/jenkins
10:perf_event:/user/1012.user/11.session/lxc/ci/jenkins
9:net_cls:/user/1012.user/11.session/lxc/ci/jenkins
8:freezer:/user/1012.user/11.session/lxc/ci/jenkins
7:devices:/user/1012.user/11.session/lxc/ci/jenkins
6:memory:/user/1012.user/11.session/lxc/ci/jenkins
5:blkio:/user/1012.user/11.session/lxc/ci/jenkins
4:name=systemd:/user/1012.user/11.session/lxc/ci/jenkins
3:cpuacct:/user/1012.user/11.session/lxc/ci/jenkins
2:cpu:/user/1012.user/11.session/lxc/ci/jenkins
1:cpuset:/user/1012.user/11.session/lxc/ci/jenkins

, но пользователь jenkins , входящий в ssh, не может остановить контейнер, созданный скриптом. Следующее никогда не заканчивается:

[email protected]:~$ lxc-stop -n test

Второй вопрос : как я могу достичь того, что пользователь jenkins может остановить любой контейнер, созданный пользователем jenkins , из сценария инициализации, такого как выше?     

задан Ivan Ogai 17.08.2016 в 15:38
источник

0 ответов