Commit | Line | Data |
---|---|---|
a793d79e CB |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _LINUX_MNT_IDMAPPING_H | |
3 | #define _LINUX_MNT_IDMAPPING_H | |
4 | ||
5 | #include <linux/types.h> | |
6 | #include <linux/uidgid.h> | |
7 | ||
8 | struct user_namespace; | |
1ac2a410 CB |
9 | /* |
10 | * Carries the initial idmapping of 0:0:4294967295 which is an identity | |
11 | * mapping. This means that {g,u}id 0 is mapped to {g,u}id 0, {g,u}id 1 is | |
12 | * mapped to {g,u}id 1, [...], {g,u}id 1000 to {g,u}id 1000, [...]. | |
13 | */ | |
a793d79e CB |
14 | extern struct user_namespace init_user_ns; |
15 | ||
1ac2a410 CB |
16 | /** |
17 | * initial_idmapping - check whether this is the initial mapping | |
18 | * @ns: idmapping to check | |
19 | * | |
20 | * Check whether this is the initial mapping, mapping 0 to 0, 1 to 1, | |
21 | * [...], 1000 to 1000 [...]. | |
22 | * | |
23 | * Return: true if this is the initial mapping, false if not. | |
24 | */ | |
25 | static inline bool initial_idmapping(const struct user_namespace *ns) | |
26 | { | |
27 | return ns == &init_user_ns; | |
28 | } | |
29 | ||
30 | /** | |
31 | * no_idmapping - check whether we can skip remapping a kuid/gid | |
32 | * @mnt_userns: the mount's idmapping | |
33 | * @fs_userns: the filesystem's idmapping | |
34 | * | |
35 | * This function can be used to check whether a remapping between two | |
36 | * idmappings is required. | |
37 | * An idmapped mount is a mount that has an idmapping attached to it that | |
38 | * is different from the filsystem's idmapping and the initial idmapping. | |
39 | * If the initial mapping is used or the idmapping of the mount and the | |
40 | * filesystem are identical no remapping is required. | |
41 | * | |
42 | * Return: true if remapping can be skipped, false if not. | |
43 | */ | |
44 | static inline bool no_idmapping(const struct user_namespace *mnt_userns, | |
45 | const struct user_namespace *fs_userns) | |
46 | { | |
47 | return initial_idmapping(mnt_userns) || mnt_userns == fs_userns; | |
48 | } | |
49 | ||
50 | /** | |
51 | * mapped_kuid_fs - map a filesystem kuid into a mnt_userns | |
52 | * @mnt_userns: the mount's idmapping | |
53 | * @fs_userns: the filesystem's idmapping | |
54 | * @kuid : kuid to be mapped | |
55 | * | |
56 | * Take a @kuid and remap it from @fs_userns into @mnt_userns. Use this | |
57 | * function when preparing a @kuid to be reported to userspace. | |
58 | * | |
59 | * If no_idmapping() determines that this is not an idmapped mount we can | |
60 | * simply return @kuid unchanged. | |
61 | * If initial_idmapping() tells us that the filesystem is not mounted with an | |
62 | * idmapping we know the value of @kuid won't change when calling | |
63 | * from_kuid() so we can simply retrieve the value via __kuid_val() | |
64 | * directly. | |
65 | * | |
66 | * Return: @kuid mapped according to @mnt_userns. | |
67 | * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is | |
68 | * returned. | |
69 | */ | |
70 | static inline kuid_t mapped_kuid_fs(struct user_namespace *mnt_userns, | |
71 | struct user_namespace *fs_userns, | |
72 | kuid_t kuid) | |
73 | { | |
74 | uid_t uid; | |
75 | ||
76 | if (no_idmapping(mnt_userns, fs_userns)) | |
77 | return kuid; | |
78 | if (initial_idmapping(fs_userns)) | |
79 | uid = __kuid_val(kuid); | |
80 | else | |
81 | uid = from_kuid(fs_userns, kuid); | |
82 | if (uid == (uid_t)-1) | |
83 | return INVALID_UID; | |
84 | return make_kuid(mnt_userns, uid); | |
85 | } | |
86 | ||
87 | /** | |
88 | * mapped_kgid_fs - map a filesystem kgid into a mnt_userns | |
89 | * @mnt_userns: the mount's idmapping | |
90 | * @fs_userns: the filesystem's idmapping | |
91 | * @kgid : kgid to be mapped | |
92 | * | |
93 | * Take a @kgid and remap it from @fs_userns into @mnt_userns. Use this | |
94 | * function when preparing a @kgid to be reported to userspace. | |
95 | * | |
96 | * If no_idmapping() determines that this is not an idmapped mount we can | |
97 | * simply return @kgid unchanged. | |
98 | * If initial_idmapping() tells us that the filesystem is not mounted with an | |
99 | * idmapping we know the value of @kgid won't change when calling | |
100 | * from_kgid() so we can simply retrieve the value via __kgid_val() | |
101 | * directly. | |
102 | * | |
103 | * Return: @kgid mapped according to @mnt_userns. | |
104 | * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is | |
105 | * returned. | |
106 | */ | |
107 | static inline kgid_t mapped_kgid_fs(struct user_namespace *mnt_userns, | |
108 | struct user_namespace *fs_userns, | |
109 | kgid_t kgid) | |
110 | { | |
111 | gid_t gid; | |
112 | ||
113 | if (no_idmapping(mnt_userns, fs_userns)) | |
114 | return kgid; | |
115 | if (initial_idmapping(fs_userns)) | |
116 | gid = __kgid_val(kgid); | |
117 | else | |
118 | gid = from_kgid(fs_userns, kgid); | |
119 | if (gid == (gid_t)-1) | |
120 | return INVALID_GID; | |
121 | return make_kgid(mnt_userns, gid); | |
122 | } | |
123 | ||
124 | /** | |
125 | * mapped_kuid_user - map a user kuid into a mnt_userns | |
126 | * @mnt_userns: the mount's idmapping | |
127 | * @fs_userns: the filesystem's idmapping | |
128 | * @kuid : kuid to be mapped | |
129 | * | |
130 | * Use the idmapping of @mnt_userns to remap a @kuid into @fs_userns. Use this | |
131 | * function when preparing a @kuid to be written to disk or inode. | |
132 | * | |
133 | * If no_idmapping() determines that this is not an idmapped mount we can | |
134 | * simply return @kuid unchanged. | |
135 | * If initial_idmapping() tells us that the filesystem is not mounted with an | |
136 | * idmapping we know the value of @kuid won't change when calling | |
137 | * make_kuid() so we can simply retrieve the value via KUIDT_INIT() | |
138 | * directly. | |
139 | * | |
140 | * Return: @kuid mapped according to @mnt_userns. | |
141 | * If @kuid has no mapping in either @mnt_userns or @fs_userns INVALID_UID is | |
142 | * returned. | |
143 | */ | |
144 | static inline kuid_t mapped_kuid_user(struct user_namespace *mnt_userns, | |
145 | struct user_namespace *fs_userns, | |
146 | kuid_t kuid) | |
147 | { | |
148 | uid_t uid; | |
149 | ||
150 | if (no_idmapping(mnt_userns, fs_userns)) | |
151 | return kuid; | |
152 | uid = from_kuid(mnt_userns, kuid); | |
153 | if (uid == (uid_t)-1) | |
154 | return INVALID_UID; | |
155 | if (initial_idmapping(fs_userns)) | |
156 | return KUIDT_INIT(uid); | |
157 | return make_kuid(fs_userns, uid); | |
158 | } | |
159 | ||
160 | /** | |
161 | * mapped_kgid_user - map a user kgid into a mnt_userns | |
162 | * @mnt_userns: the mount's idmapping | |
163 | * @fs_userns: the filesystem's idmapping | |
164 | * @kgid : kgid to be mapped | |
165 | * | |
166 | * Use the idmapping of @mnt_userns to remap a @kgid into @fs_userns. Use this | |
167 | * function when preparing a @kgid to be written to disk or inode. | |
168 | * | |
169 | * If no_idmapping() determines that this is not an idmapped mount we can | |
170 | * simply return @kgid unchanged. | |
171 | * If initial_idmapping() tells us that the filesystem is not mounted with an | |
172 | * idmapping we know the value of @kgid won't change when calling | |
173 | * make_kgid() so we can simply retrieve the value via KGIDT_INIT() | |
174 | * directly. | |
175 | * | |
176 | * Return: @kgid mapped according to @mnt_userns. | |
177 | * If @kgid has no mapping in either @mnt_userns or @fs_userns INVALID_GID is | |
178 | * returned. | |
179 | */ | |
180 | static inline kgid_t mapped_kgid_user(struct user_namespace *mnt_userns, | |
181 | struct user_namespace *fs_userns, | |
182 | kgid_t kgid) | |
183 | { | |
184 | gid_t gid; | |
185 | ||
186 | if (no_idmapping(mnt_userns, fs_userns)) | |
187 | return kgid; | |
188 | gid = from_kgid(mnt_userns, kgid); | |
189 | if (gid == (gid_t)-1) | |
190 | return INVALID_GID; | |
191 | if (initial_idmapping(fs_userns)) | |
192 | return KGIDT_INIT(gid); | |
193 | return make_kgid(fs_userns, gid); | |
194 | } | |
195 | ||
a793d79e CB |
196 | /** |
197 | * mapped_fsuid - return caller's fsuid mapped up into a mnt_userns | |
1ac2a410 | 198 | * @mnt_userns: the mount's idmapping |
209188ce | 199 | * @fs_userns: the filesystem's idmapping |
a793d79e CB |
200 | * |
201 | * Use this helper to initialize a new vfs or filesystem object based on | |
202 | * the caller's fsuid. A common example is initializing the i_uid field of | |
203 | * a newly allocated inode triggered by a creation event such as mkdir or | |
204 | * O_CREAT. Other examples include the allocation of quotas for a specific | |
205 | * user. | |
206 | * | |
207 | * Return: the caller's current fsuid mapped up according to @mnt_userns. | |
208 | */ | |
209188ce CB |
209 | static inline kuid_t mapped_fsuid(struct user_namespace *mnt_userns, |
210 | struct user_namespace *fs_userns) | |
a793d79e | 211 | { |
209188ce | 212 | return mapped_kuid_user(mnt_userns, fs_userns, current_fsuid()); |
a793d79e CB |
213 | } |
214 | ||
215 | /** | |
216 | * mapped_fsgid - return caller's fsgid mapped up into a mnt_userns | |
1ac2a410 | 217 | * @mnt_userns: the mount's idmapping |
209188ce | 218 | * @fs_userns: the filesystem's idmapping |
a793d79e CB |
219 | * |
220 | * Use this helper to initialize a new vfs or filesystem object based on | |
221 | * the caller's fsgid. A common example is initializing the i_gid field of | |
222 | * a newly allocated inode triggered by a creation event such as mkdir or | |
223 | * O_CREAT. Other examples include the allocation of quotas for a specific | |
224 | * user. | |
225 | * | |
226 | * Return: the caller's current fsgid mapped up according to @mnt_userns. | |
227 | */ | |
209188ce CB |
228 | static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns, |
229 | struct user_namespace *fs_userns) | |
a793d79e | 230 | { |
209188ce | 231 | return mapped_kgid_user(mnt_userns, fs_userns, current_fsgid()); |
a793d79e CB |
232 | } |
233 | ||
234 | #endif /* _LINUX_MNT_IDMAPPING_H */ |