Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305989
b: refs/heads/master
c: 1a48e2a
h: refs/heads/master
i:
  305987: 83aa864
v: v3
  • Loading branch information
Eric W. Biederman committed Apr 8, 2012
1 parent 12bea7a commit 50eb4e0
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 973c5914260d75292f71a4729753086b9e863d57
refs/heads/master: 1a48e2ac034d47ed843081c4523b63c46b46888b
6 changes: 2 additions & 4 deletions trunk/fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1732,11 +1732,9 @@ EXPORT_SYMBOL(inode_init_owner);
*/
bool inode_owner_or_capable(const struct inode *inode)
{
struct user_namespace *ns = inode_userns(inode);

if (current_user_ns() == ns && current_fsuid() == inode->i_uid)
if (current_fsuid() == inode->i_uid)
return true;
if (ns_capable(ns, CAP_FOWNER))
if (inode_capable(inode, CAP_FOWNER))
return true;
return false;
}
Expand Down
18 changes: 5 additions & 13 deletions trunk/fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,6 @@ static int acl_permission_check(struct inode *inode, int mask)
{
unsigned int mode = inode->i_mode;

if (current_user_ns() != inode_userns(inode))
goto other_perms;

if (likely(current_fsuid() == inode->i_uid))
mode >>= 6;
else {
Expand All @@ -244,7 +241,6 @@ static int acl_permission_check(struct inode *inode, int mask)
mode >>= 3;
}

other_perms:
/*
* If the DACs are ok we don't need any capability check.
*/
Expand Down Expand Up @@ -280,10 +276,10 @@ int generic_permission(struct inode *inode, int mask)

if (S_ISDIR(inode->i_mode)) {
/* DACs are overridable for directories */
if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
if (inode_capable(inode, CAP_DAC_OVERRIDE))
return 0;
if (!(mask & MAY_WRITE))
if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
if (inode_capable(inode, CAP_DAC_READ_SEARCH))
return 0;
return -EACCES;
}
Expand All @@ -293,15 +289,15 @@ int generic_permission(struct inode *inode, int mask)
* at least one exec bit set.
*/
if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
if (inode_capable(inode, CAP_DAC_OVERRIDE))
return 0;

/*
* Searching includes executable on directories, else just read.
*/
mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
if (mask == MAY_READ)
if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
if (inode_capable(inode, CAP_DAC_READ_SEARCH))
return 0;

return -EACCES;
Expand Down Expand Up @@ -1964,15 +1960,11 @@ 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;

other_userns:
return !ns_capable(inode_userns(inode), CAP_FOWNER);
return !inode_capable(inode, CAP_FOWNER);
}

/*
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/capability.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ struct cpu_vfs_cap_data {

#ifdef __KERNEL__

struct inode;
struct dentry;
struct user_namespace;

Expand Down Expand Up @@ -548,6 +549,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t,
extern bool capable(int cap);
extern bool ns_capable(struct user_namespace *ns, int cap);
extern bool nsown_capable(int cap);
extern bool inode_capable(const struct inode *inode, int cap);

/* audit system wants to get cap info from files as well */
extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
Expand Down
6 changes: 0 additions & 6 deletions trunk/include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1522,12 +1522,6 @@ enum {
#define vfs_check_frozen(sb, level) \
wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level)))

/*
* until VFS tracks user namespaces for inodes, just make all files
* belong to init_user_ns
*/
extern struct user_namespace init_user_ns;
#define inode_userns(inode) (&init_user_ns)
extern bool inode_owner_or_capable(const struct inode *inode);

/* not quite ready to be deprecated, but... */
Expand Down
19 changes: 19 additions & 0 deletions trunk/kernel/capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,22 @@ bool nsown_capable(int cap)
{
return ns_capable(current_user_ns(), cap);
}

/**
* inode_capable - Check superior capability over inode
* @inode: The inode in question
* @cap: The capability in question
*
* Return true if the current task has the given superior capability
* targeted at it's own user namespace and that the given inode is owned
* by the current user namespace or a child namespace.
*
* Currently inodes can only be owned by the initial user namespace.
*
*/
bool inode_capable(const struct inode *inode, int cap)
{
struct user_namespace *ns = current_user_ns();

return ns_capable(ns, cap) && (ns == &init_user_ns);
}

0 comments on commit 50eb4e0

Please sign in to comment.