| #!/bin/sh |
| # |
| # Copyright (c) 2017 FUJITSU LIMITED. All rights reserved. |
| # Author: Xiao Yang <yangx.jy@cn.fujitsu.com> |
| # |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| # the GNU General Public License for more details. |
| # |
| # Test unshare command with some basic options. |
| # 1) If we run unshare with "--user", UID in the newly created user namespace |
| # is set to 65534. |
| # 2) If we run unshare with "--user", GID in the newly created user namespace |
| # is set to 65534. |
| # 3) If we run with "--user --map-root-user", UID in the newly created user |
| # namespace is set to 0. |
| # 4) If we run with "--user --map-root-user", GID in the newly created user |
| # is set to 0. |
| # 5) If we run with "--mount", mount and unmount events do not propagate to |
| # its parent mount namespace. |
| # 6) If we run with "--mount --propagation shared", mount and unmount events |
| # propagate to its parent mount namespace. |
| # 7) If we run with "--user --map-root-user --mount", mount and unmount events |
| # do not propagate to its parent mount namespace. |
| # 8) Even if we run with "--user --map-root-user --mount --propagation shared", |
| # mount and unmount events do not propagate to its parent mount namespace |
| # because the shared mount is reduced to a slave mount. |
| # |
| # Please see the following URL for detailed information: |
| # http://man7.org/linux/man-pages/man7/user_namespaces.7.html |
| # http://man7.org/linux/man-pages/man7/mount_namespaces.7.html |
| # |
| |
| TST_CNT=8 |
| TST_SETUP=setup |
| TST_CLEANUP=cleanup |
| TST_TESTFUNC=do_test |
| TST_NEEDS_ROOT=1 |
| TST_NEEDS_TMPDIR=1 |
| TST_NEEDS_CMDS="unshare id mount umount" |
| . tst_test.sh |
| |
| max_userns_path="/proc/sys/user/max_user_namespaces" |
| max_mntns_path="/proc/sys/user/max_mnt_namespaces" |
| default_max_userns=-1 |
| default_max_mntns=-1 |
| |
| setup() |
| { |
| # On some distributions(e.g RHEL7.4), the default value of |
| # max_user_namespaces or max_mnt_namespaces is set to 0. |
| # We need to change the default value to run unshare command. |
| if [ -f "${max_userns_path}" ]; then |
| default_max_userns=$(cat "${max_userns_path}") |
| echo 1024 > "${max_userns_path}" |
| fi |
| |
| if [ -f "${max_mntns_path}" ]; then |
| default_max_mntns=$(cat "${max_mntns_path}") |
| echo 1024 > "${max_mntns_path}" |
| fi |
| |
| mkdir -p dir_A dir_B |
| touch dir_A/A dir_B/B |
| } |
| |
| cleanup() |
| { |
| # Restore the default value to 0. |
| [ ${default_max_userns} -ne -1 ] && \ |
| echo ${default_max_userns} > "${max_userns_path}" |
| [ ${default_max_mntns} -ne -1 ] && \ |
| echo ${default_max_mntns} > "${max_mntns_path}" |
| } |
| |
| check_id() |
| { |
| local act_id=$1 |
| local exp_id=$2 |
| local cmd=$3 |
| |
| if [ ${act_id} -ne ${exp_id} ]; then |
| tst_res TFAIL "$cmd got wrong uid/gid" |
| else |
| tst_res TPASS "$cmd got correct uid/gid" |
| fi |
| } |
| |
| check_mount() |
| { |
| local tst_dir=$1 |
| local exp_stat=$2 |
| local cmd=$3 |
| |
| case ${exp_stat} in |
| unmounted) |
| if ls "${tst_dir}" | grep -qw 'A'; then |
| tst_res TFAIL "$cmd got bind info" |
| umount ${tst_dir} |
| return |
| fi |
| ;; |
| mounted) |
| if ! ls "${tst_dir}" | grep -qw 'A'; then |
| tst_res TFAIL "$cmd did not get bind info" |
| return |
| fi |
| umount ${tst_dir} |
| ;; |
| esac |
| |
| tst_res TPASS "$cmd got bind info as expected" |
| } |
| |
| unshare_test() |
| { |
| local unshare_opts=$1 |
| local verify_cmd=$2 |
| local exp_result=$3 |
| |
| local unshare_cmd="unshare ${unshare_opts} ${verify_cmd}" |
| |
| eval ${unshare_cmd} > temp 2>&1 |
| if [ $? -ne 0 ]; then |
| # unrecognized option or invalid option is returned if the |
| # option is not supported by unshare command(e.g. RHEL6). |
| # Invalid argument or Operation not permitted is returned |
| # if the feature is not supported by kernel(e.g. RHEL7). |
| grep -q -E "unrecognized option|invalid option|Invalid argument|Operation not permitted" temp |
| if [ $? -eq 0 ]; then |
| tst_res TCONF "${unshare_cmd} not supported." |
| else |
| tst_res TFAIL "${unshare_cmd} failed." |
| fi |
| return |
| fi |
| |
| case ${verify_cmd} in |
| id*) |
| check_id "$(cat temp)" "${exp_result}" "${unshare_cmd}" |
| ;; |
| mount*) |
| check_mount "dir_B" "${exp_result}" "${unshare_cmd}" |
| ;; |
| esac |
| } |
| |
| do_test() |
| { |
| case $1 in |
| 1) unshare_test "--user" "id -u" "65534";; |
| 2) unshare_test "--user" "id -g" "65534";; |
| 3) unshare_test "--user --map-root-user" "id -u" "0";; |
| 4) unshare_test "--user --map-root-user" "id -g" "0";; |
| 5) unshare_test "--mount" "mount --bind dir_A dir_B" "unmounted";; |
| 6) unshare_test "--mount --propagation shared" \ |
| "mount --bind dir_A dir_B" "mounted";; |
| 7) unshare_test "--user --map-root-user --mount" \ |
| "mount --bind dir_A dir_B" "unmounted";; |
| 8) unshare_test "--user --map-root-user --mount --propagation shared" \ |
| "mount --bind dir_A dir_B" "unmounted";; |
| esac |
| } |
| |
| tst_run |