github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/kernel/auth/user_namespace.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package auth 16 17 import ( 18 "math" 19 20 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 21 "github.com/SagerNet/gvisor/pkg/sync" 22 ) 23 24 // A UserNamespace represents a user namespace. See user_namespaces(7) for 25 // details. 26 // 27 // +stateify savable 28 type UserNamespace struct { 29 // parent is this namespace's parent. If this is the root namespace, parent 30 // is nil. The parent pointer is immutable. 31 parent *UserNamespace 32 33 // owner is the effective UID of the namespace's creator in the root 34 // namespace. owner is immutable. 35 owner KUID 36 37 // mu protects the following fields. 38 // 39 // If mu will be locked in multiple UserNamespaces, it must be locked in 40 // descendant namespaces before ancestors. 41 mu sync.Mutex `state:"nosave"` 42 43 // Mappings of user/group IDs between this namespace and its parent. 44 // 45 // All ID maps, once set, cannot be changed. This means that successful 46 // UID/GID translations cannot be racy. 47 uidMapFromParent idMapSet 48 uidMapToParent idMapSet 49 gidMapFromParent idMapSet 50 gidMapToParent idMapSet 51 52 // TODO(b/27454212): Support disabling setgroups(2). 53 } 54 55 // NewRootUserNamespace returns a UserNamespace that is appropriate for a 56 // system's root user namespace. 57 func NewRootUserNamespace() *UserNamespace { 58 var ns UserNamespace 59 // """ 60 // The initial user namespace has no parent namespace, but, for 61 // consistency, the kernel provides dummy user and group ID mapping files 62 // for this namespace. Looking at the uid_map file (gid_map is the same) 63 // from a shell in the initial namespace shows: 64 // 65 // $ cat /proc/$$/uid_map 66 // 0 0 4294967295 67 // """ - user_namespaces(7) 68 for _, m := range []*idMapSet{ 69 &ns.uidMapFromParent, 70 &ns.uidMapToParent, 71 &ns.gidMapFromParent, 72 &ns.gidMapToParent, 73 } { 74 if !m.Add(idMapRange{0, math.MaxUint32}, 0) { 75 panic("Failed to insert into empty ID map") 76 } 77 } 78 return &ns 79 } 80 81 // Root returns the root of the user namespace tree containing ns. 82 func (ns *UserNamespace) Root() *UserNamespace { 83 for ns.parent != nil { 84 ns = ns.parent 85 } 86 return ns 87 } 88 89 // "The kernel imposes (since version 3.11) a limit of 32 nested levels of user 90 // namespaces." - user_namespaces(7) 91 const maxUserNamespaceDepth = 32 92 93 func (ns *UserNamespace) depth() int { 94 var i int 95 for ns != nil { 96 i++ 97 ns = ns.parent 98 } 99 return i 100 } 101 102 // NewChildUserNamespace returns a new user namespace created by a caller with 103 // credentials c. 104 func (c *Credentials) NewChildUserNamespace() (*UserNamespace, error) { 105 if c.UserNamespace.depth() >= maxUserNamespaceDepth { 106 // "... Calls to unshare(2) or clone(2) that would cause this limit to 107 // be exceeded fail with the error EUSERS." - user_namespaces(7) 108 return nil, linuxerr.EUSERS 109 } 110 // "EPERM: CLONE_NEWUSER was specified in flags, but either the effective 111 // user ID or the effective group ID of the caller does not have a mapping 112 // in the parent namespace (see user_namespaces(7))." - clone(2) 113 // "CLONE_NEWUSER requires that the user ID and group ID of the calling 114 // process are mapped to user IDs and group IDs in the user namespace of 115 // the calling process at the time of the call." - unshare(2) 116 if !c.EffectiveKUID.In(c.UserNamespace).Ok() { 117 return nil, linuxerr.EPERM 118 } 119 if !c.EffectiveKGID.In(c.UserNamespace).Ok() { 120 return nil, linuxerr.EPERM 121 } 122 return &UserNamespace{ 123 parent: c.UserNamespace, 124 owner: c.EffectiveKUID, 125 // "When a user namespace is created, it starts without a mapping of 126 // user IDs (group IDs) to the parent user namespace." - 127 // user_namespaces(7) 128 }, nil 129 }