2012-05-01 15:17:58

by Andy Whitcroft

[permalink] [raw]
Subject: [PATCH 0/5] overlayfs v3.4-rc5 updates

I have been playing with getting overlayfs to work for v3.4, following
this email are the patches I am using on top of the stock overlayfs.v12
branch on the v3.4-rc5 base. The first two are yet another revamp of the
security permissions patch which I posted a few times (hopefully fixing
your remaining comments). The other three are porting issues for the
v3.2->v3.4 base.

These are also available as below:

git://git.kernel.org/pub/scm/linux/kernel/git/apw/overlayfs.git overlayfs.v12apw1

Thanks to Sedat Dilek for all their testing feedback and Jordi Pojol for
his test scripts.

Please consider.

-apw

Andy Whitcroft (5):
inode_only_permission: export inode level permissions checks
overlayfs: switch to use inode_only_permissions
overlayfs: follow header cleanup
overlayfs: switch from d_alloc_root() to d_make_root()
overlayfs: update touch_atime() usage

fs/namei.c | 48 +++++++++++++++++++++++++++++++-----------------
fs/overlayfs/copy_up.c | 1 +
fs/overlayfs/dir.c | 1 +
fs/overlayfs/inode.c | 14 ++------------
fs/overlayfs/readdir.c | 1 +
fs/overlayfs/super.c | 16 ++++++++--------
include/linux/fs.h | 1 +
7 files changed, 45 insertions(+), 37 deletions(-)

--
1.7.9.5


2012-05-01 15:17:59

by Andy Whitcroft

[permalink] [raw]
Subject: [PATCH 1/5] inode_only_permission: export inode level permissions checks

We need to be able to check inode permissions (but not filesystem implied
permissions) for stackable filesystems. Now that permissions involve
checking with the security LSM, cgroups and basic inode permissions it is
easy to miss a key permission check and introduce a security vunerability.
Expose a new interface for these checks.

Signed-off-by: Andy Whitcroft <[email protected]>
---
fs/namei.c | 48 +++++++++++++++++++++++++++++++-----------------
include/linux/fs.h | 1 +
2 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 0062dd1..744bd38 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -328,6 +328,36 @@ static inline int do_inode_permission(struct inode *inode, int mask)
}

/**
+ * inode_only_permission - check access rights to a given inode only
+ * @inode: inode to check permissions on
+ * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...)
+ *
+ * Uses to check read/write/execute permissions on an inode directly, we do
+ * not check filesystem permissions.
+ */
+int inode_only_permission(struct inode *inode, int mask)
+{
+ int retval;
+
+ /*
+ * Nobody gets write access to an immutable file.
+ */
+ if (unlikely(mask & MAY_WRITE) && IS_IMMUTABLE(inode))
+ return -EACCES;
+
+ retval = do_inode_permission(inode, mask);
+ if (retval)
+ return retval;
+
+ retval = devcgroup_inode_permission(inode, mask);
+ if (retval)
+ return retval;
+
+ return security_inode_permission(inode, mask);
+}
+EXPORT_SYMBOL(inode_only_permission);
+
+/**
* inode_permission - check for access rights to a given inode
* @inode: inode to check permission on
* @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...)
@@ -341,8 +371,6 @@ static inline int do_inode_permission(struct inode *inode, int mask)
*/
int inode_permission(struct inode *inode, int mask)
{
- int retval;
-
if (unlikely(mask & MAY_WRITE)) {
umode_t mode = inode->i_mode;

@@ -352,23 +380,9 @@ int inode_permission(struct inode *inode, int mask)
if (IS_RDONLY(inode) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS;
-
- /*
- * Nobody gets write access to an immutable file.
- */
- if (IS_IMMUTABLE(inode))
- return -EACCES;
}

- retval = do_inode_permission(inode, mask);
- if (retval)
- return retval;
-
- retval = devcgroup_inode_permission(inode, mask);
- if (retval)
- return retval;
-
- return security_inode_permission(inode, mask);
+ return inode_only_permission(inode, mask);
}

/**
diff --git a/include/linux/fs.h b/include/linux/fs.h
index fdd1d38..0b531ab 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2226,6 +2226,7 @@ extern sector_t bmap(struct inode *, sector_t);
#endif
extern int notify_change(struct dentry *, struct iattr *);
extern int inode_permission(struct inode *, int);
+extern int inode_only_permission(struct inode *, int);
extern int generic_permission(struct inode *, int);

static inline bool execute_ok(struct inode *inode)
--
1.7.9.5

2012-05-01 15:18:05

by Andy Whitcroft

[permalink] [raw]
Subject: [PATCH 4/5] overlayfs: switch from d_alloc_root() to d_make_root()

d_alloc_root() has been deprecated (and removed) in favour of
d_make_root(). Follow this new interface.

Signed-off-by: Andy Whitcroft <[email protected]>
---
fs/overlayfs/super.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index b679019..24bdcc5 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -538,13 +538,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
if (oe == NULL)
goto out_free_config;

- root_inode = ovl_new_inode(sb, S_IFDIR, oe);
- if (!root_inode)
- goto out_free_oe;
-
err = kern_path(ufs->config.upperdir, LOOKUP_FOLLOW, &upperpath);
if (err)
- goto out_put_root;
+ goto out_free_oe;

err = kern_path(ufs->config.lowerdir, LOOKUP_FOLLOW, &lowerpath);
if (err)
@@ -596,7 +592,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
}

err = -ENOMEM;
- root_dentry = d_alloc_root(root_inode);
+ root_inode = ovl_new_inode(sb, S_IFDIR, oe);
+ if (!root_inode)
+ goto out_drop_write;
+
+ root_dentry = d_make_root(root_inode);
if (!root_dentry)
goto out_drop_write;

@@ -626,8 +626,6 @@ out_put_lowerpath:
path_put(&lowerpath);
out_put_upperpath:
path_put(&upperpath);
-out_put_root:
- iput(root_inode);
out_free_oe:
kfree(oe);
out_free_config:
--
1.7.9.5

2012-05-01 15:18:03

by Andy Whitcroft

[permalink] [raw]
Subject: [PATCH 5/5] overlayfs: update touch_atime() usage

touch_atime() now has new parametarisation, follow this in overlayfs.

Signed-off-by: Andy Whitcroft <[email protected]>
---
fs/overlayfs/inode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index bc9178c..c63fd3f 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -176,7 +176,7 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
if (!realinode->i_op->readlink)
return -EINVAL;

- touch_atime(realpath.mnt, realpath.dentry);
+ touch_atime(&realpath);

return realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
}
--
1.7.9.5

2012-05-01 15:18:45

by Andy Whitcroft

[permalink] [raw]
Subject: [PATCH 3/5] overlayfs: follow header cleanup

The headers cleanup has removed a number of unnecessary includes from
various headers. Fix up the now missing headers in overlayfs.

Signed-off-by: Andy Whitcroft <[email protected]>
---
fs/overlayfs/copy_up.c | 1 +
fs/overlayfs/dir.c | 1 +
fs/overlayfs/readdir.c | 1 +
fs/overlayfs/super.c | 2 ++
4 files changed, 5 insertions(+)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 398fa1c..87dbeee 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -14,6 +14,7 @@
#include <linux/xattr.h>
#include <linux/security.h>
#include <linux/uaccess.h>
+#include <linux/sched.h>
#include "overlayfs.h"

#define OVL_COPY_UP_CHUNK_SIZE (1 << 20)
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 57bbb94..00aa6d9 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -11,6 +11,7 @@
#include <linux/namei.h>
#include <linux/xattr.h>
#include <linux/security.h>
+#include <linux/cred.h>
#include "overlayfs.h"

static const char *ovl_whiteout_symlink = "(overlay-whiteout)";
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index ed8fbad..0797efb 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -14,6 +14,7 @@
#include <linux/xattr.h>
#include <linux/rbtree.h>
#include <linux/security.h>
+#include <linux/cred.h>
#include "overlayfs.h"

struct ovl_cache_entry {
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 10cafe0..b679019 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -16,6 +16,8 @@
#include <linux/parser.h>
#include <linux/module.h>
#include <linux/seq_file.h>
+#include <linux/cred.h>
+#include <linux/sched.h>
#include "overlayfs.h"

MODULE_AUTHOR("Miklos Szeredi <[email protected]>");
--
1.7.9.5

2012-05-01 15:19:13

by Andy Whitcroft

[permalink] [raw]
Subject: [PATCH 2/5] overlayfs: switch to use inode_only_permissions

When checking permissions on an overlayfs inode we do not take into
account either device cgroup restrictions nor security permissions.
This allows a user to mount an overlayfs layer over a restricted device
directory and by pass those permissions to open otherwise restricted
files.

Switch over to the newly introduced inode_only_permissions.

Signed-off-by: Andy Whitcroft <[email protected]>
---
fs/overlayfs/inode.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index ba1a777..bc9178c 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -105,19 +105,9 @@ int ovl_permission(struct inode *inode, int mask)
if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
goto out_dput;
-
- /*
- * Nobody gets write access to an immutable file.
- */
- err = -EACCES;
- if (IS_IMMUTABLE(realinode))
- goto out_dput;
}

- if (realinode->i_op->permission)
- err = realinode->i_op->permission(realinode, mask);
- else
- err = generic_permission(realinode, mask);
+ err = inode_only_permission(realinode, mask);
out_dput:
dput(alias);
return err;
--
1.7.9.5

2012-05-14 11:20:13

by Miklos Szeredi

[permalink] [raw]
Subject: Re: [PATCH 0/5] overlayfs v3.4-rc5 updates

Andy Whitcroft <[email protected]> writes:

> I have been playing with getting overlayfs to work for v3.4, following
> this email are the patches I am using on top of the stock overlayfs.v12
> branch on the v3.4-rc5 base. The first two are yet another revamp of the
> security permissions patch which I posted a few times (hopefully fixing
> your remaining comments). The other three are porting issues for the
> v3.2->v3.4 base.
>
> These are also available as below:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/apw/overlayfs.git overlayfs.v12apw1
>
> Thanks to Sedat Dilek for all their testing feedback and Jordi Pojol for
> his test scripts.
>
> Please consider.

Thanks, applied. Should appear shortly at:

git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git overlayfs.v13

Thanks,
Miklos