1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <Blub@users.noreply.github.com>
3 Date: Thu, 8 Mar 2018 00:40:42 +0100
4 Subject: [PATCH] Take user namespaces into account in policy checks
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 Change file related checks to use user namespaces and make
10 sure involved uids/gids are mappable in the current
13 Note that checks without file ownership information will
14 still not take user namespaces into account, as some of
15 these should be handled via 'zfs allow' (otherwise root in a
16 user namespace could issue commands such as `zpool export`).
18 This also adds an initial user namespace regression test
19 for the setgid bit loss, with a user_ns_exec helper usable
22 Additionally, configure checks for the required user
23 namespace related features are added for:
25 * kuid/kgid_has_mapping()
28 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
29 Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
32 (cherry picked from commit 3808006edfc46b18f0a40a2e9df54c6567bf52cc)
33 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
36 tests/zfs-tests/cmd/Makefile.am | 1 +
37 tests/zfs-tests/cmd/user_ns_exec/Makefile.am | 6 +
38 tests/zfs-tests/tests/functional/Makefile.am | 1 +
39 .../tests/functional/user_namespace/Makefile.am | 7 +
40 module/zfs/policy.c | 66 +++++++-
41 tests/zfs-tests/cmd/user_ns_exec/user_ns_exec.c | 179 +++++++++++++++++++++
42 config/kernel-userns-capabilities.m4 | 67 ++++++++
43 config/kernel.m4 | 1 +
44 tests/runfiles/linux.run | 4 +
45 tests/zfs-tests/cmd/user_ns_exec/.gitignore | 1 +
46 tests/zfs-tests/include/commands.cfg | 1 +
47 .../tests/functional/user_namespace/cleanup.ksh | 25 +++
48 .../tests/functional/user_namespace/setup.ksh | 32 ++++
49 .../functional/user_namespace/user_namespace.cfg | 23 +++
50 .../user_namespace/user_namespace_001.ksh | 89 ++++++++++
51 .../user_namespace/user_namespace_common.kshlib | 23 +++
52 17 files changed, 521 insertions(+), 7 deletions(-)
53 create mode 100644 tests/zfs-tests/cmd/user_ns_exec/Makefile.am
54 create mode 100644 tests/zfs-tests/tests/functional/user_namespace/Makefile.am
55 create mode 100644 tests/zfs-tests/cmd/user_ns_exec/user_ns_exec.c
56 create mode 100644 config/kernel-userns-capabilities.m4
57 create mode 100644 tests/zfs-tests/cmd/user_ns_exec/.gitignore
58 create mode 100755 tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh
59 create mode 100755 tests/zfs-tests/tests/functional/user_namespace/setup.ksh
60 create mode 100644 tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg
61 create mode 100755 tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh
62 create mode 100644 tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib
64 diff --git a/configure.ac b/configure.ac
65 index d71712e4c..77e5764fc 100644
68 @@ -153,6 +153,7 @@ AC_CONFIG_FILES([
69 tests/zfs-tests/callbacks/Makefile
70 tests/zfs-tests/cmd/Makefile
71 tests/zfs-tests/cmd/chg_usr_exec/Makefile
72 + tests/zfs-tests/cmd/user_ns_exec/Makefile
73 tests/zfs-tests/cmd/devname2devid/Makefile
74 tests/zfs-tests/cmd/dir_rd_update/Makefile
75 tests/zfs-tests/cmd/file_check/Makefile
76 @@ -284,6 +285,7 @@ AC_CONFIG_FILES([
77 tests/zfs-tests/tests/functional/threadsappend/Makefile
78 tests/zfs-tests/tests/functional/tmpfile/Makefile
79 tests/zfs-tests/tests/functional/truncate/Makefile
80 + tests/zfs-tests/tests/functional/user_namespace/Makefile
81 tests/zfs-tests/tests/functional/userquota/Makefile
82 tests/zfs-tests/tests/functional/upgrade/Makefile
83 tests/zfs-tests/tests/functional/vdev_zaps/Makefile
84 diff --git a/tests/zfs-tests/cmd/Makefile.am b/tests/zfs-tests/cmd/Makefile.am
85 index f55ff8ce2..1cce6947b 100644
86 --- a/tests/zfs-tests/cmd/Makefile.am
87 +++ b/tests/zfs-tests/cmd/Makefile.am
88 @@ -2,6 +2,7 @@ EXTRA_DIST = file_common.h
96 diff --git a/tests/zfs-tests/cmd/user_ns_exec/Makefile.am b/tests/zfs-tests/cmd/user_ns_exec/Makefile.am
98 index 000000000..5b4bc9aaa
100 +++ b/tests/zfs-tests/cmd/user_ns_exec/Makefile.am
102 +include $(top_srcdir)/config/Rules.am
104 +pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
106 +pkgexec_PROGRAMS = user_ns_exec
107 +user_ns_exec_SOURCES = user_ns_exec.c
108 diff --git a/tests/zfs-tests/tests/functional/Makefile.am b/tests/zfs-tests/tests/functional/Makefile.am
109 index d68f254ef..cd60324f3 100644
110 --- a/tests/zfs-tests/tests/functional/Makefile.am
111 +++ b/tests/zfs-tests/tests/functional/Makefile.am
112 @@ -58,6 +58,7 @@ SUBDIRS = \
120 diff --git a/tests/zfs-tests/tests/functional/user_namespace/Makefile.am b/tests/zfs-tests/tests/functional/user_namespace/Makefile.am
122 index 000000000..0c0f6887a
124 +++ b/tests/zfs-tests/tests/functional/user_namespace/Makefile.am
126 +pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/user_namespace
127 +dist_pkgdata_SCRIPTS = \
130 + user_namespace_common.kshlib \
131 + user_namespace.cfg \
132 + user_namespace_001.ksh
133 diff --git a/module/zfs/policy.c b/module/zfs/policy.c
134 index 03e8f748b..55c932747 100644
135 --- a/module/zfs/policy.c
136 +++ b/module/zfs/policy.c
138 * all other cases this function must fail and return the passed err.
141 -priv_policy(const cred_t *cr, int capability, boolean_t all, int err)
142 +priv_policy_ns(const cred_t *cr, int capability, boolean_t all, int err,
143 + struct user_namespace *ns)
145 ASSERT3S(all, ==, B_FALSE);
147 if (cr != CRED() && (cr != kcred))
150 +#if defined(CONFIG_USER_NS) && defined(HAVE_NS_CAPABLE)
151 + if (!(ns ? ns_capable(ns, capability) : capable(capability)))
153 if (!capable(capability))
161 +priv_policy(const cred_t *cr, int capability, boolean_t all, int err)
163 + return (priv_policy_ns(cr, capability, all, err, NULL));
167 +priv_policy_user(const cred_t *cr, int capability, boolean_t all, int err)
170 + * All priv_policy_user checks are preceeded by kuid/kgid_has_mapping()
171 + * checks. If we cannot do them, we shouldn't be using ns_capable()
172 + * since we don't know whether the affected files are valid in our
173 + * namespace. Note that kuid_has_mapping() came after cred->user_ns, so
174 + * we shouldn't need to re-check for HAVE_CRED_USER_NS
176 +#if defined(CONFIG_USER_NS) && defined(HAVE_KUID_HAS_MAPPING)
177 + return (priv_policy_ns(cr, capability, all, err, cr->user_ns));
179 + return (priv_policy_ns(cr, capability, all, err, NULL));
184 * Checks for operations that are either client-only or are used by
185 * both clients and servers.
186 @@ -102,10 +130,15 @@ secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner)
187 if (zpl_inode_owner_or_capable(ip))
190 - if (priv_policy(cr, CAP_DAC_OVERRIDE, B_FALSE, EPERM) == 0)
191 +#if defined(CONFIG_USER_NS) && defined(HAVE_KUID_HAS_MAPPING)
192 + if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner)))
196 + if (priv_policy_user(cr, CAP_DAC_OVERRIDE, B_FALSE, EPERM) == 0)
199 - if (priv_policy(cr, CAP_DAC_READ_SEARCH, B_FALSE, EPERM) == 0)
200 + if (priv_policy_user(cr, CAP_DAC_READ_SEARCH, B_FALSE, EPERM) == 0)
204 @@ -120,7 +153,12 @@ secpolicy_vnode_chown(const cred_t *cr, uid_t owner)
205 if (crgetfsuid(cr) == owner)
208 - return (priv_policy(cr, CAP_FOWNER, B_FALSE, EPERM));
209 +#if defined(CONFIG_USER_NS) && defined(HAVE_KUID_HAS_MAPPING)
210 + if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner)))
214 + return (priv_policy_user(cr, CAP_FOWNER, B_FALSE, EPERM));
218 @@ -152,7 +190,12 @@ secpolicy_vnode_setdac(const cred_t *cr, uid_t owner)
219 if (crgetfsuid(cr) == owner)
222 - return (priv_policy(cr, CAP_FOWNER, B_FALSE, EPERM));
223 +#if defined(CONFIG_USER_NS) && defined(HAVE_KUID_HAS_MAPPING)
224 + if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner)))
228 + return (priv_policy_user(cr, CAP_FOWNER, B_FALSE, EPERM));
232 @@ -175,8 +218,12 @@ secpolicy_vnode_setid_retain(const cred_t *cr, boolean_t issuidroot)
234 secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid)
236 +#if defined(CONFIG_USER_NS) && defined(HAVE_KUID_HAS_MAPPING)
237 + if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid)))
240 if (crgetfsgid(cr) != gid && !groupmember(gid, cr))
241 - return (priv_policy(cr, CAP_FSETID, B_FALSE, EPERM));
242 + return (priv_policy_user(cr, CAP_FSETID, B_FALSE, EPERM));
246 @@ -222,7 +269,12 @@ secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner)
247 if (crgetfsuid(cr) == owner)
250 - return (priv_policy(cr, CAP_FSETID, B_FALSE, EPERM));
251 +#if defined(CONFIG_USER_NS) && defined(HAVE_KUID_HAS_MAPPING)
252 + if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner)))
256 + return (priv_policy_user(cr, CAP_FSETID, B_FALSE, EPERM));
260 diff --git a/tests/zfs-tests/cmd/user_ns_exec/user_ns_exec.c b/tests/zfs-tests/cmd/user_ns_exec/user_ns_exec.c
262 index 000000000..cd46738bd
264 +++ b/tests/zfs-tests/cmd/user_ns_exec/user_ns_exec.c
267 + * CDDL HEADER START
269 + * The contents of this file are subject to the terms of the
270 + * Common Development and Distribution License (the "License").
271 + * You may not use this file except in compliance with the License.
273 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
274 + * or http://www.opensolaris.org/os/licensing.
275 + * See the License for the specific language governing permissions
276 + * and limitations under the License.
278 + * When distributing Covered Code, include this CDDL HEADER in each
279 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
280 + * If applicable, add the following below this CDDL HEADER, with the
281 + * fields enclosed by brackets "[]" replaced with your own identifying
282 + * information: Portions Copyright [yyyy] [name of copyright owner]
291 +#include <sys/types.h>
292 +#include <sys/types.h>
293 +#include <sys/socket.h>
294 +#include <sys/wait.h>
300 +#define EXECSHELL "/bin/sh"
301 +#define UIDMAP "0 100000 65536"
304 +child_main(int argc, char *argv[], int sync_pipe)
307 + char cmds[BUFSIZ] = { 0 };
311 + if (unshare(CLONE_NEWUSER | CLONE_NEWNS) != 0) {
316 + /* tell parent we entered the new namespace */
317 + if (write(sync_pipe, "1", 1) != 1) {
322 + /* wait for parent to setup the uid mapping */
323 + if (read(sync_pipe, &sync_buf, 1) != 1) {
324 + (void) fprintf(stderr, "user namespace setup failed\n");
330 + if (setuid(0) != 0) {
334 + if (setgid(0) != 0) {
340 + for (i = 1; i < argc; i++) {
341 + (void) snprintf(cmds+len, sizeof (cmds)-len,
342 + "%s%s", argv[i], sep);
343 + len += strlen(argv[i]) + strlen(sep);
346 + if (execl(EXECSHELL, "sh", "-c", cmds, (char *)NULL) != 0) {
347 + perror("execl: " EXECSHELL);
355 +set_idmap(pid_t pid, const char *file)
359 + char path[PATH_MAX];
361 + (void) snprintf(path, sizeof (path), "/proc/%d/%s", (int)pid, file);
363 + mapfd = open(path, O_WRONLY);
370 + if (write(mapfd, UIDMAP, sizeof (UIDMAP)-1) != sizeof (UIDMAP)-1) {
381 +main(int argc, char *argv[])
384 + int result, wstatus;
388 + if (argc < 2 || strlen(argv[1]) == 0) {
389 + (void) printf("\tUsage: %s <commands> ...\n", argv[0]);
393 + if (socketpair(AF_UNIX, SOCK_STREAM, 0, syncfd) != 0) {
394 + perror("socketpair");
399 + if (child == (pid_t)-1) {
406 + return (child_main(argc, argv, syncfd[1]));
412 + /* wait for the child to have unshared its namespaces */
413 + if (read(syncfd[0], &sync_buf, 1) != 1) {
415 + kill(child, SIGKILL);
420 + /* write uid mapping */
421 + if (set_idmap(child, "uid_map") != 0 ||
422 + set_idmap(child, "gid_map") != 0) {
424 + kill(child, SIGKILL);
428 + /* tell the child to proceed */
429 + if (write(syncfd[0], "1", 1) != 1) {
431 + kill(child, SIGKILL);
438 + while (waitpid(child, &wstatus, 0) != child)
439 + kill(child, SIGKILL);
441 + result = WEXITSTATUS(wstatus);
445 diff --git a/config/kernel-userns-capabilities.m4 b/config/kernel-userns-capabilities.m4
447 index 000000000..fa3381978
449 +++ b/config/kernel-userns-capabilities.m4
452 +dnl # 2.6.38 API change
453 +dnl # ns_capable() was introduced
455 +AC_DEFUN([ZFS_AC_KERNEL_NS_CAPABLE], [
456 + AC_MSG_CHECKING([whether ns_capable exists])
457 + ZFS_LINUX_TRY_COMPILE([
458 + #include <linux/capability.h>
460 + ns_capable((struct user_namespace *)NULL, CAP_SYS_ADMIN);
463 + AC_DEFINE(HAVE_NS_CAPABLE, 1,
464 + [ns_capable exists])
471 +dnl # 2.6.39 API change
472 +dnl # struct user_namespace was added to struct cred_t as
473 +dnl # cred->user_ns member
474 +dnl # Note that current_user_ns() was added in 2.6.28.
476 +AC_DEFUN([ZFS_AC_KERNEL_CRED_USER_NS], [
477 + AC_MSG_CHECKING([whether cred_t->user_ns exists])
478 + ZFS_LINUX_TRY_COMPILE([
479 + #include <linux/cred.h>
482 + cr.user_ns = (struct user_namespace *)NULL;
485 + AC_DEFINE(HAVE_CRED_USER_NS, 1,
486 + [cred_t->user_ns exists])
493 +dnl # 3.4 API change
494 +dnl # kuid_has_mapping() and kgid_has_mapping() were added to distinguish
495 +dnl # between internal kernel uids/gids and user namespace uids/gids.
497 +AC_DEFUN([ZFS_AC_KERNEL_KUID_HAS_MAPPING], [
498 + AC_MSG_CHECKING([whether kuid_has_mapping/kgid_has_mapping exist])
499 + ZFS_LINUX_TRY_COMPILE([
500 + #include <linux/uidgid.h>
502 + kuid_has_mapping((struct user_namespace *)NULL, KUIDT_INIT(0));
503 + kgid_has_mapping((struct user_namespace *)NULL, KGIDT_INIT(0));
506 + AC_DEFINE(HAVE_KUID_HAS_MAPPING, 1,
507 + [kuid_has_mapping/kgid_has_mapping exist])
513 +AC_DEFUN([ZFS_AC_KERNEL_USERNS_CAPABILITIES], [
514 + ZFS_AC_KERNEL_NS_CAPABLE
515 + ZFS_AC_KERNEL_CRED_USER_NS
516 + ZFS_AC_KERNEL_KUID_HAS_MAPPING
518 diff --git a/config/kernel.m4 b/config/kernel.m4
519 index 419ed1a2c..910d4ff25 100644
520 --- a/config/kernel.m4
521 +++ b/config/kernel.m4
522 @@ -126,6 +126,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
523 ZFS_AC_KERNEL_CURRENT_TIME
524 ZFS_AC_KERNEL_GLOBAL_PAGE_STATE
525 ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
526 + ZFS_AC_KERNEL_USERNS_CAPABILITIES
528 AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
529 KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
530 diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run
531 index 89c923db1..25ae3fe5e 100644
532 --- a/tests/runfiles/linux.run
533 +++ b/tests/runfiles/linux.run
534 @@ -648,6 +648,10 @@ tags = ['functional', 'truncate']
535 tests = [ 'upgrade_userobj_001_pos' ]
536 tags = ['functional', 'upgrade']
538 +[tests/functional/user_namespace]
539 +tests = ['user_namespace_001']
540 +tags = ['functional', 'user_namespace']
542 [tests/functional/userquota]
544 'userquota_001_pos', 'userquota_002_pos', 'userquota_003_pos',
545 diff --git a/tests/zfs-tests/cmd/user_ns_exec/.gitignore b/tests/zfs-tests/cmd/user_ns_exec/.gitignore
547 index 000000000..655867a64
549 +++ b/tests/zfs-tests/cmd/user_ns_exec/.gitignore
552 diff --git a/tests/zfs-tests/include/commands.cfg b/tests/zfs-tests/include/commands.cfg
553 index 936e54c1a..0d768a3cf 100644
554 --- a/tests/zfs-tests/include/commands.cfg
555 +++ b/tests/zfs-tests/include/commands.cfg
556 @@ -164,4 +164,5 @@ export ZFSTEST_FILES='chg_usr_exec
562 diff --git a/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh b/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh
564 index 000000000..61caf3910
566 +++ b/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh
572 +# The contents of this file are subject to the terms of the
573 +# Common Development and Distribution License (the "License").
574 +# You may not use this file except in compliance with the License.
576 +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
577 +# or http://www.opensolaris.org/os/licensing.
578 +# See the License for the specific language governing permissions
579 +# and limitations under the License.
581 +# When distributing Covered Code, include this CDDL HEADER in each
582 +# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
583 +# If applicable, add the following below this CDDL HEADER, with the
584 +# fields enclosed by brackets "[]" replaced with your own identifying
585 +# information: Portions Copyright [yyyy] [name of copyright owner]
590 +. $STF_SUITE/include/libtest.shlib
593 diff --git a/tests/zfs-tests/tests/functional/user_namespace/setup.ksh b/tests/zfs-tests/tests/functional/user_namespace/setup.ksh
595 index 000000000..354cc9a6b
597 +++ b/tests/zfs-tests/tests/functional/user_namespace/setup.ksh
603 +# The contents of this file are subject to the terms of the
604 +# Common Development and Distribution License (the "License").
605 +# You may not use this file except in compliance with the License.
607 +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
608 +# or http://www.opensolaris.org/os/licensing.
609 +# See the License for the specific language governing permissions
610 +# and limitations under the License.
612 +# When distributing Covered Code, include this CDDL HEADER in each
613 +# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
614 +# If applicable, add the following below this CDDL HEADER, with the
615 +# fields enclosed by brackets "[]" replaced with your own identifying
616 +# information: Portions Copyright [yyyy] [name of copyright owner]
621 +. $STF_SUITE/include/libtest.shlib
623 +if ! [ -f /proc/self/uid_map ]; then
624 + log_unsupported "The kernel doesn't support user namespaces."
627 +verify_runnable "both"
631 diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg b/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg
633 index 000000000..9e55398e2
635 +++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg
640 +# The contents of this file are subject to the terms of the
641 +# Common Development and Distribution License (the "License").
642 +# You may not use this file except in compliance with the License.
644 +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
645 +# or http://www.opensolaris.org/os/licensing.
646 +# See the License for the specific language governing permissions
647 +# and limitations under the License.
649 +# When distributing Covered Code, include this CDDL HEADER in each
650 +# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
651 +# If applicable, add the following below this CDDL HEADER, with the
652 +# fields enclosed by brackets "[]" replaced with your own identifying
653 +# information: Portions Copyright [yyyy] [name of copyright owner]
658 +export ROOT_UID=100000
659 +export OTHER_UID=101000
660 diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh
662 index 000000000..6be30ab4d
664 +++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh
670 +# The contents of this file are subject to the terms of the
671 +# Common Development and Distribution License (the "License").
672 +# You may not use this file except in compliance with the License.
674 +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
675 +# or http://www.opensolaris.org/os/licensing.
676 +# See the License for the specific language governing permissions
677 +# and limitations under the License.
679 +# When distributing Covered Code, include this CDDL HEADER in each
680 +# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
681 +# If applicable, add the following below this CDDL HEADER, with the
682 +# fields enclosed by brackets "[]" replaced with your own identifying
683 +# information: Portions Copyright [yyyy] [name of copyright owner]
688 +. $STF_SUITE/tests/functional/user_namespace/user_namespace_common.kshlib
693 +# Regression test for secpolicy_vnode_setids_setgids
697 +# 1. Create files with various owners.
698 +# 2. Try to set setgid bit.
701 +verify_runnable "both"
704 +# uroot: root within user namespace
705 +# uother: other user within user namespace
706 +set -A files rroot_rroot uroot_uroot uroot_other uother_uroot uother_uother
710 + for i in ${files[*]}; do
711 + log_must rm -f $TESTDIR/$i
717 +log_assert "Check root in user namespaces"
719 +TOUCH=$(readlink -e $(which touch))
720 +CHMOD=$(readlink -e $(which chmod))
722 +for i in ${files[*]}; do
723 + log_must $TOUCH $TESTDIR/$i
724 + log_must $CHMOD 0644 $TESTDIR/$i
727 +log_must chown 0:0 $TESTDIR/rroot_rroot
728 +log_must chown $ROOT_UID:$ROOT_UID $TESTDIR/uroot_uroot
729 +log_must chown $ROOT_UID:$OTHER_UID $TESTDIR/uroot_other
730 +log_must chown $OTHER_UID:$ROOT_UID $TESTDIR/uother_uroot
731 +log_must chown $OTHER_UID:$OTHER_UID $TESTDIR/uother_uother
733 +log_mustnot user_ns_exec $CHMOD 02755 $TESTDIR/rroot_rroot
734 +log_mustnot test -g $TESTDIR/rroot_rroot
736 +log_must user_ns_exec $CHMOD 02755 $TESTDIR/uroot_uroot
737 +log_must test -g $TESTDIR/uroot_uroot
739 +log_must user_ns_exec $CHMOD 02755 $TESTDIR/uroot_other
740 +log_must test -g $TESTDIR/uroot_other
742 +log_must user_ns_exec $CHMOD 02755 $TESTDIR/uother_uroot
743 +log_must test -g $TESTDIR/uother_uroot
745 +log_must user_ns_exec $CHMOD 02755 $TESTDIR/uother_uother
746 +log_must test -g $TESTDIR/uother_uother
748 +log_mustnot user_ns_exec $TOUCH $TESTDIR/rroot_rroot
749 +log_must $CHMOD 0666 $TESTDIR/rroot_rroot
750 +for i in ${files[*]}; do
751 + log_must user_ns_exec $TOUCH $TESTDIR/$i
754 +log_pass "Check root in user namespaces"
755 diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib
757 index 000000000..8577294d0
759 +++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib
764 +# The contents of this file are subject to the terms of the
765 +# Common Development and Distribution License (the "License").
766 +# You may not use this file except in compliance with the License.
768 +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
769 +# or http://www.opensolaris.org/os/licensing.
770 +# See the License for the specific language governing permissions
771 +# and limitations under the License.
773 +# When distributing Covered Code, include this CDDL HEADER in each
774 +# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
775 +# If applicable, add the following below this CDDL HEADER, with the
776 +# fields enclosed by brackets "[]" replaced with your own identifying
777 +# information: Portions Copyright [yyyy] [name of copyright owner]
782 +. $STF_SUITE/include/libtest.shlib
783 +. $STF_SUITE/tests/functional/user_namespace/user_namespace.cfg