1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
From 1ef45eb31cacd58c4c62e1fd26aa63a1f3d031a7 Mon Sep 17 00:00:00 2001
From: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
Date: Thu, 29 Sep 2016 15:11:15 +0200
Subject: [PATCH] Add printk-based debugging to pivot_root
This patch changes pivot_root to make it obvious which error exit path
was taken. It might be useful to apply to debug and investigate how
undocumented requirements of pivot_root are not met.
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
---
fs/namespace.c | 70 ++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 53 insertions(+), 17 deletions(-)
diff --git a/fs/namespace.c b/fs/namespace.c
index 877fc2c..6e15d1d 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2993,57 +2993,93 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
return -EPERM;
error = user_path_dir(new_root, &new);
- if (error)
+ if (error) {
+ printk(KERN_ERR "user_path_dir(new_root, &new) returned an error\n");
goto out0;
+ }
error = user_path_dir(put_old, &old);
- if (error)
+ if (error) {
+ printk(KERN_ERR "user_path_dir(put_old, &old) returned an error\n");
goto out1;
+ }
error = security_sb_pivotroot(&old, &new);
- if (error)
+ if (error) {
+ printk(KERN_ERR "security_sb_pivotroot(&old, &new) returned an error\n");
goto out2;
+ }
get_fs_root(current->fs, &root);
old_mp = lock_mount(&old);
error = PTR_ERR(old_mp);
- if (IS_ERR(old_mp))
+ if (IS_ERR(old_mp)) {
+ printk(KERN_ERR "IS_ERR(old_mp)\n");
goto out3;
+ }
error = -EINVAL;
new_mnt = real_mount(new.mnt);
root_mnt = real_mount(root.mnt);
old_mnt = real_mount(old.mnt);
- if (IS_MNT_SHARED(old_mnt) ||
- IS_MNT_SHARED(new_mnt->mnt_parent) ||
- IS_MNT_SHARED(root_mnt->mnt_parent))
+ if (IS_MNT_SHARED(old_mnt)) {
+ printk(KERN_ERR "IS_MNT_SHARED(old_mnt)\n");
+ goto out4;
+ }
+ if (IS_MNT_SHARED(new_mnt->mnt_parent)) {
+ printk(KERN_ERR "IS_MNT_SHARED(new_mnt->mnt_parent)\n");
goto out4;
- if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
+ }
+ if (IS_MNT_SHARED(root_mnt->mnt_parent)) {
+ printk(KERN_ERR "IS_MNT_SHARED(root_mnt->mnt_parent)\n");
goto out4;
- if (new_mnt->mnt.mnt_flags & MNT_LOCKED)
+ }
+ if (!check_mnt(root_mnt) || !check_mnt(new_mnt)) {
+ printk(KERN_ERR "!check_mnt(root_mnt) || !check_mnt(new_mnt)\n");
+ goto out4;
+ }
+ if (new_mnt->mnt.mnt_flags & MNT_LOCKED) {
+ printk(KERN_ERR "new_mnt->mnt.mnt_flags & MNT_LOCKED\n");
goto out4;
+ }
error = -ENOENT;
- if (d_unlinked(new.dentry))
+ if (d_unlinked(new.dentry)) {
+ printk(KERN_ERR "d_unlinked(new.dentry)\n");
goto out4;
+ }
error = -EBUSY;
- if (new_mnt == root_mnt || old_mnt == root_mnt)
+ if (new_mnt == root_mnt || old_mnt == root_mnt) {
+ printk(KERN_ERR "new_mnt == root_mnt || old_mnt == root_mnt\n");
goto out4; /* loop, on the same file system */
+ }
error = -EINVAL;
- if (root.mnt->mnt_root != root.dentry)
+ if (root.mnt->mnt_root != root.dentry) {
+ printk(KERN_ERR "root.mnt->mnt_root != root.dentry\n");
goto out4; /* not a mountpoint */
- if (!mnt_has_parent(root_mnt))
+ }
+ if (!mnt_has_parent(root_mnt)) {
+ printk(KERN_ERR "!mnt_has_parent(root_mnt)\n");
goto out4; /* not attached */
+ }
root_mp = root_mnt->mnt_mp;
- if (new.mnt->mnt_root != new.dentry)
+ if (new.mnt->mnt_root != new.dentry) {
+ printk(KERN_ERR "new.mnt->mnt_root != new.dentry\n");
goto out4; /* not a mountpoint */
- if (!mnt_has_parent(new_mnt))
+ }
+ if (!mnt_has_parent(new_mnt)) {
+ printk(KERN_ERR "!mnt_has_parent(new_mnt)\n");
goto out4; /* not attached */
+ }
/* make sure we can reach put_old from new_root */
- if (!is_path_reachable(old_mnt, old.dentry, &new))
+ if (!is_path_reachable(old_mnt, old.dentry, &new)) {
+ printk(KERN_ERR "!is_path_reachable(old_mnt, old.dentry, &new)\n");
goto out4;
+ }
/* make certain new is below the root */
- if (!is_path_reachable(new_mnt, new.dentry, &root))
+ if (!is_path_reachable(new_mnt, new.dentry, &root)) {
+ printk(KERN_ERR "!is_path_reachable(new_mnt, new.dentry, &root)\n");
goto out4;
+ }
root_mp->m_count++; /* pin it so it won't go away */
lock_mount_hash();
detach_mnt(new_mnt, &parent_path);
--
2.7.4
|