|
@@ -183,6 +183,9 @@ static int acl_permission_check(struct inode *inode, int mask, unsigned int flag
|
|
|
|
|
|
mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
|
|
|
|
|
|
+ if (current_user_ns() != inode_userns(inode))
|
|
|
+ goto other_perms;
|
|
|
+
|
|
|
if (current_fsuid() == inode->i_uid)
|
|
|
mode >>= 6;
|
|
|
else {
|
|
@@ -196,6 +199,7 @@ static int acl_permission_check(struct inode *inode, int mask, unsigned int flag
|
|
|
mode >>= 3;
|
|
|
}
|
|
|
|
|
|
+other_perms:
|
|
|
/*
|
|
|
* If the DACs are ok we don't need any capability check.
|
|
|
*/
|
|
@@ -237,7 +241,7 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags,
|
|
|
* Executable DACs are overridable if at least one exec bit is set.
|
|
|
*/
|
|
|
if (!(mask & MAY_EXEC) || execute_ok(inode))
|
|
|
- if (capable(CAP_DAC_OVERRIDE))
|
|
|
+ if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
|
|
|
return 0;
|
|
|
|
|
|
/*
|
|
@@ -245,7 +249,7 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags,
|
|
|
*/
|
|
|
mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
|
|
|
if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
|
|
|
- if (capable(CAP_DAC_READ_SEARCH))
|
|
|
+ if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
|
|
|
return 0;
|
|
|
|
|
|
return -EACCES;
|
|
@@ -654,6 +658,7 @@ static inline int handle_reval_path(struct nameidata *nd)
|
|
|
static inline int exec_permission(struct inode *inode, unsigned int flags)
|
|
|
{
|
|
|
int ret;
|
|
|
+ struct user_namespace *ns = inode_userns(inode);
|
|
|
|
|
|
if (inode->i_op->permission) {
|
|
|
ret = inode->i_op->permission(inode, MAY_EXEC, flags);
|
|
@@ -666,7 +671,8 @@ static inline int exec_permission(struct inode *inode, unsigned int flags)
|
|
|
if (ret == -ECHILD)
|
|
|
return ret;
|
|
|
|
|
|
- if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH))
|
|
|
+ if (ns_capable(ns, CAP_DAC_OVERRIDE) ||
|
|
|
+ ns_capable(ns, CAP_DAC_READ_SEARCH))
|
|
|
goto ok;
|
|
|
|
|
|
return ret;
|
|
@@ -1842,11 +1848,15 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
|
|
|
|
|
|
if (!(dir->i_mode & S_ISVTX))
|
|
|
return 0;
|
|
|
+ if (current_user_ns() != inode_userns(inode))
|
|
|
+ goto other_userns;
|
|
|
if (inode->i_uid == fsuid)
|
|
|
return 0;
|
|
|
if (dir->i_uid == fsuid)
|
|
|
return 0;
|
|
|
- return !capable(CAP_FOWNER);
|
|
|
+
|
|
|
+other_userns:
|
|
|
+ return !ns_capable(inode_userns(inode), CAP_FOWNER);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2440,7 +2450,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
|
|
|
if (error)
|
|
|
return error;
|
|
|
|
|
|
- if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
|
|
|
+ if ((S_ISCHR(mode) || S_ISBLK(mode)) &&
|
|
|
+ !ns_capable(inode_userns(dir), CAP_MKNOD))
|
|
|
return -EPERM;
|
|
|
|
|
|
if (!dir->i_op->mknod)
|