Можно ли смонтировать устройство в пространстве имен процесса после unshare ()

Не бесконечный цикл, но лучший способ найти фактический предел даты:

#!/bin/bash

j=$((1<<61))
i=0
while ((j>0)); do
    if date +'%Y-%m-%d' -d "$((i+j)) days ago" >/dev/null 2>&1; then
    ((i+=j)) ; # printf 'running i %d 0x%x\n' "$i"{,}
    else
    ((j>>=1)); # printf 'new     j %d 0x%x\n' "$j"{,}
    fi
    ((k++))
    # ((k%10)) || printf 'still running %d 0x%x %d %d' "$i"{,} "$j" "$k"
done
printf "final value of limit %d 0x%x in %d loops\n" "$i"{,} "$k"

Таким образом, предел даты будет:

final value of limit 2147483649 0x80000001 in 64 loops

Удалите символ комментария # , чтобы увидеть, как это делается.

Это не 32-битное число.

Это похоже на 32-битное число:

$ printf '%d\n%d\n' "$(( (1<<31) + 1 ))" "0x80000001"
2147483649
2147483649

Фактически, это 2 ** 31 + номер дня месяца.
Если мы попробуем с последним днем ​​декабря (измените строку 5 в сценарии выше):

date +'%Y-%m-%d' -d "2017-12-31 $((i+j)) days ago"

Мы получим:

final value of limit 2147483679 0x8000001f in 68 loops

Это 31 выше 2 ** 31 :

$ printf '%d\n%d\n' "$(( (2**31) + 31 ))" "0x8000001f"
2147483679
2147483679

Это также зависит от часового пояса.

Арифметические примечания

Максимальное значение для целого числа оболочки - i меньше 2, увеличенное до 63:

$ echo $(( (2**63) - 1 ))
9223372036854775807

Мы можем получить десятичное и шестнадцатеричное представление следующим образом:

$ printf '%d %x\n' "$(( (2**63) - 1 ))"{,}
9223372036854775807 7fffffffffffffff

Это максимальное число, представимое в виде целого числа со знаком 64 бита (если ваша система, конечно, 64 бита). Следующее число (просто добавьте один) будет обернуто (переполнено) до отрицательного числа:

$ echo $(( (2**63) ))
-9223372036854775808

$ printf '%d %x\n' "$(( (2**63) ))"{,} 
-9223372036854775808 8000000000000000

Это самое отрицательное число для 64-битного целого числа со знаком.

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

$ printf '%d %x\n' "$(( (1<<63) - 1 ))"{,}
9223372036854775807 7fffffffffffffff
3
03.01.2016, 08:26
1 ответ

У меня был некоторый успех в этом - если не с контейнером lxc, то мне удалось заставить его работать для частного пространства имен монтирования. Поскольку lxc построен на базовых пространствах имен linux, которые я также использовал, я не вижу причин, почему это не должно работать у вас.

В первую очередь я настроил пространство имен следующим образом:

sudo unshare -m sh -c '
    mount -ttmpfs none /tmp
    echo x > /tmp/mytmp
    findmnt -o+PROPAGATION /tmp
    echo "$$"
    cd   /tmp
    exec "$0" -i

TARGET SOURCE FSTYPE OPTIONS     PROPAGATION
/tmp   tmpfs  tmpfs  rw          private
/tmp   none   tmpfs  rw,relatime private
29384
$ 

... и получил интерактивную оболочку. Следующее, что я сделал в отдельной терминальной сессии...

sudo sh -c ' { cd /dev/fd/0 ; mkdir mnt
               ls -l;         cat mytmp
             } 3<$0/ns/mnt  <$0/29384/cwd
' /proc/29384

drwxr-xr-x 2 root root 40 Jan  4 02:52 mnt
-rw-r--r-- 1 root root  2 Jan  4 02:38 mytmp
x

... что было очень обнадеживающе!

Но я не смог выполнить монтирование - каждый раз, когда я пытался смонтировать родительский ns каталог поверх одного из дочерних ns, он терпел неудачу. Некоторые исследования показывают, что это сделано специально (в частности: см. предостережения в man 7 user_namespaces относительно флагов PROPAGATION). Что сработало, так это (в новом пространстве имен):

sudo unshare --propagation slave -m sh -c '
     mount -ttmpfs none /tmp; cd /tmp
     exec "$0" -i'

А затем в сессии родительского пространства имен...

sudo mount --bind / /mnt
sudo mount --bind / /tmp
sudo mount --bind /tmp /mnt/img/tmp

Теперь вышеописанное работает в первом случае, но не во втором. Поскольку дочернее ns не распространяет изменения fs вверх, родительское не повлияет на изменения, внесенные в его представление fs. И так как у дочернего ns есть собственное монтирование на /tmp, все, что делает родитель, не имеет значения. Однако, если существует некоторая общая иерархия и дочерний ns настроен на получение изменений файловой системы, то он будет видеть изменения, которые родитель распространяет вниз.

В дочернем ns после выполнения вышеуказанного...

ls /tmp /mnt /mnt/tmp

/mnt:
bin   dev  etc   lib    mnt  proc  run   srv  tmp  var
boot  esp  home  lib64  opt  root  sbin  sys  usr

/mnt/tmp:
serverauth.FT3Z6IFyWW
systemd-private-...systemd-timesyncd.service-YUkVU6

/tmp:

И так, я полагаю, чтобы ответить на вопрос - да, я считаю, что это возможно. Но я также уверен, что вам потребуется организовать это заранее.

0
27.01.2020, 21:30

Теги

Похожие вопросы