github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/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/nicocha30/gvisor-ligolo/pkg/errors/linuxerr" 21 ) 22 23 // A UserNamespace represents a user namespace. See user_namespaces(7) for 24 // details. 25 // 26 // +stateify savable 27 type UserNamespace struct { 28 // parent is this namespace's parent. If this is the root namespace, parent 29 // is nil. The parent pointer is immutable. 30 parent *UserNamespace 31 32 // owner is the effective UID of the namespace's creator in the root 33 // namespace. owner is immutable. 34 owner KUID 35 36 // mu protects the following fields. 37 // 38 // If mu will be locked in multiple UserNamespaces, it must be locked in 39 // descendant namespaces before ancestors. 40 mu userNamespaceMutex `state:"nosave"` 41 42 // Mappings of user/group IDs between this namespace and its parent. 43 // 44 // All ID maps, once set, cannot be changed. This means that successful 45 // UID/GID translations cannot be racy. 46 uidMapFromParent idMapSet 47 uidMapToParent idMapSet 48 gidMapFromParent idMapSet 49 gidMapToParent idMapSet 50 51 // TODO(b/27454212): Support disabling setgroups(2). 52 } 53 54 // NewRootUserNamespace returns a UserNamespace that is appropriate for a 55 // system's root user namespace. Note that namespaces returned by separate calls 56 // to this function are *distinct* namespaces. Once a root namespace is created 57 // by this function, the returned value must be reused to refer to the same 58 // namespace. 59 func NewRootUserNamespace() *UserNamespace { 60 var ns UserNamespace 61 // """ 62 // The initial user namespace has no parent namespace, but, for 63 // consistency, the kernel provides dummy user and group ID mapping files 64 // for this namespace. Looking at the uid_map file (gid_map is the same) 65 // from a shell in the initial namespace shows: 66 // 67 // $ cat /proc/$$/uid_map 68 // 0 0 4294967295 69 // """ - user_namespaces(7) 70 for _, m := range []*idMapSet{ 71 &ns.uidMapFromParent, 72 &ns.uidMapToParent, 73 &ns.gidMapFromParent, 74 &ns.gidMapToParent, 75 } { 76 if !m.Add(idMapRange{0, math.MaxUint32}, 0) { 77 panic("Failed to insert into empty ID map") 78 } 79 } 80 return &ns 81 } 82 83 // Root returns the root of the user namespace tree containing ns. 84 func (ns *UserNamespace) Root() *UserNamespace { 85 for ns.parent != nil { 86 ns = ns.parent 87 } 88 return ns 89 } 90 91 // "The kernel imposes (since version 3.11) a limit of 32 nested levels of user 92 // namespaces." - user_namespaces(7) 93 const maxUserNamespaceDepth = 32 94 95 func (ns *UserNamespace) depth() int { 96 var i int 97 for ns != nil { 98 i++ 99 ns = ns.parent 100 } 101 return i 102 } 103 104 // NewChildUserNamespace returns a new user namespace created by a caller with 105 // credentials c. 106 func (c *Credentials) NewChildUserNamespace() (*UserNamespace, error) { 107 if c.UserNamespace.depth() >= maxUserNamespaceDepth { 108 // "... Calls to unshare(2) or clone(2) that would cause this limit to 109 // be exceeded fail with the error EUSERS." - user_namespaces(7) 110 return nil, linuxerr.EUSERS 111 } 112 // "EPERM: CLONE_NEWUSER was specified in flags, but either the effective 113 // user ID or the effective group ID of the caller does not have a mapping 114 // in the parent namespace (see user_namespaces(7))." - clone(2) 115 // "CLONE_NEWUSER requires that the user ID and group ID of the calling 116 // process are mapped to user IDs and group IDs in the user namespace of 117 // the calling process at the time of the call." - unshare(2) 118 if !c.EffectiveKUID.In(c.UserNamespace).Ok() { 119 return nil, linuxerr.EPERM 120 } 121 if !c.EffectiveKGID.In(c.UserNamespace).Ok() { 122 return nil, linuxerr.EPERM 123 } 124 return &UserNamespace{ 125 parent: c.UserNamespace, 126 owner: c.EffectiveKUID, 127 // "When a user namespace is created, it starts without a mapping of 128 // user IDs (group IDs) to the parent user namespace." - 129 // user_namespaces(7) 130 }, nil 131 }