lkml.org 
[lkml]   [2015]   [Jun]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC v4 03/31] vfs: Add MAY_DELETE_SELF and MAY_DELETE_CHILD permission flags
    Date
    Normally, deleting a file requires write and execute access to the parent
    directory. With Richacls, a process with MAY_DELETE_SELF access to a file may
    delete the file even without write access to the parent directory.

    To support that, pass the MAY_DELETE_CHILD mask flag to inode_permission() when
    checking for delete access inside a directory, and MAY_DELETE_SELF when
    checking for delete access to a file itelf.

    The MAY_DELETE_SELF permission does not override the sticky directory check.
    It probably should.

    Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
    ---
    fs/namei.c | 15 +++++++++++----
    include/linux/fs.h | 2 ++
    2 files changed, 13 insertions(+), 4 deletions(-)

    diff --git a/fs/namei.c b/fs/namei.c
    index c6eac96..8f91790 100644
    --- a/fs/namei.c
    +++ b/fs/namei.c
    @@ -454,7 +454,7 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
    * changing the "normal" UIDs which are used for other things.
    *
    * When checking for MAY_APPEND, MAY_CREATE_FILE, MAY_CREATE_DIR,
    - * MAY_WRITE must also be set in @mask.
    + * MAY_DELETE_CHILD, MAY_DELETE_SELF, MAY_WRITE must also be set in @mask.
    */
    int inode_permission(struct inode *inode, int mask)
    {
    @@ -2459,7 +2459,7 @@ static int may_delete(struct inode *dir, struct dentry *victim,
    bool isdir, bool replace)
    {
    struct inode *inode = victim->d_inode;
    - int error, mask = MAY_WRITE | MAY_EXEC;
    + int error, mask = MAY_EXEC;

    if (d_is_negative(victim))
    return -ENOENT;
    @@ -2469,8 +2469,15 @@ static int may_delete(struct inode *dir, struct dentry *victim,
    audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);

    if (replace)
    - mask |= isdir ? MAY_CREATE_DIR : MAY_CREATE_FILE;
    - error = inode_permission(dir, mask);
    + mask |= MAY_WRITE | (isdir ? MAY_CREATE_DIR : MAY_CREATE_FILE);
    + error = inode_permission(dir, mask | MAY_WRITE | MAY_DELETE_CHILD);
    + if (error && IS_RICHACL(inode)) {
    + /* Deleting is also permitted with MAY_EXEC on the directory
    + * and MAY_DELETE_SELF on the inode. */
    + if (!inode_permission(inode, MAY_DELETE_SELF) &&
    + !inode_permission(dir, mask))
    + error = 0;
    + }
    if (error)
    return error;
    if (IS_APPEND(dir))
    diff --git a/include/linux/fs.h b/include/linux/fs.h
    index 8c78d91..96a9954 100644
    --- a/include/linux/fs.h
    +++ b/include/linux/fs.h
    @@ -82,6 +82,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
    #define MAY_NOT_BLOCK 0x00000080
    #define MAY_CREATE_FILE 0x00000100
    #define MAY_CREATE_DIR 0x00000200
    +#define MAY_DELETE_CHILD 0x00000400
    +#define MAY_DELETE_SELF 0x00000800

    /*
    * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond
    --
    2.4.2


    \
     
     \ /
      Last update: 2015-06-25 00:21    [W:4.049 / U:1.472 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site