lkml.org 
[lkml]   [2007]   [Oct]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[AppArmor 33/45] Pass struct file down the inode_*xattr security LSM hooks
    This allows LSMs to also distinguish between file descriptor and path
    access for the xattr operations. (The other relevant operations are
    covered by the setattr hook.)

    Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
    Signed-off-by: John Johansen <jjohansen@suse.de>

    ---
    fs/xattr.c | 59 ++++++++++++++++++++++++-----------------------
    include/linux/security.h | 40 +++++++++++++++++++------------
    include/linux/xattr.h | 8 +++---
    security/commoncap.c | 4 +--
    security/dummy.c | 10 ++++---
    security/security.c | 18 +++++++-------
    security/selinux/hooks.c | 10 ++++---
    7 files changed, 83 insertions(+), 66 deletions(-)

    --- a/fs/xattr.c
    +++ b/fs/xattr.c
    @@ -68,7 +68,7 @@ xattr_permission(struct inode *inode, co

    int
    vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
    - void *value, size_t size, int flags)
    + void *value, size_t size, int flags, struct file *file)
    {
    struct inode *inode = dentry->d_inode;
    int error;
    @@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, stru
    return error;

    mutex_lock(&inode->i_mutex);
    - error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
    + error = security_inode_setxattr(dentry, mnt, name, value, size, flags, file);
    if (error)
    goto out;
    error = -EOPNOTSUPP;
    @@ -105,7 +105,7 @@ EXPORT_SYMBOL_GPL(vfs_setxattr);

    ssize_t
    vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
    - void *value, size_t size)
    + void *value, size_t size, struct file *file)
    {
    struct inode *inode = dentry->d_inode;
    int error;
    @@ -114,7 +114,7 @@ vfs_getxattr(struct dentry *dentry, stru
    if (error)
    return error;

    - error = security_inode_getxattr(dentry, mnt, name);
    + error = security_inode_getxattr(dentry, mnt, name, file);
    if (error)
    return error;

    @@ -142,12 +142,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr);

    ssize_t
    vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
    - size_t size)
    + size_t size, struct file *file)
    {
    struct inode *inode = dentry->d_inode;
    ssize_t error;

    - error = security_inode_listxattr(dentry, mnt);
    + error = security_inode_listxattr(dentry, mnt, file);
    if (error)
    return error;
    error = -EOPNOTSUPP;
    @@ -163,7 +163,8 @@ vfs_listxattr(struct dentry *dentry, str
    EXPORT_SYMBOL_GPL(vfs_listxattr);

    int
    -vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name)
    +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
    + struct file *file)
    {
    struct inode *inode = dentry->d_inode;
    int error;
    @@ -175,7 +176,7 @@ vfs_removexattr(struct dentry *dentry, s
    if (error)
    return error;

    - error = security_inode_removexattr(dentry, mnt, name);
    + error = security_inode_removexattr(dentry, mnt, name, file);
    if (error)
    return error;

    @@ -195,7 +196,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
    */
    static long
    setxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
    - void __user *value, size_t size, int flags)
    + void __user *value, size_t size, int flags, struct file *file)
    {
    int error;
    void *kvalue = NULL;
    @@ -222,7 +223,7 @@ setxattr(struct dentry *dentry, struct v
    }
    }

    - error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags);
    + error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file);
    kfree(kvalue);
    return error;
    }
    @@ -240,7 +241,7 @@ sys_setxattr(char __user *path, char __u
    error = mnt_want_write(nd.mnt);
    if (error)
    return error;
    - error = setxattr(nd.dentry, nd.mnt, name, value, size, flags);
    + error = setxattr(nd.dentry, nd.mnt, name, value, size, flags, NULL);
    mnt_drop_write(nd.mnt);
    path_release(&nd);
    return error;
    @@ -259,7 +260,7 @@ sys_lsetxattr(char __user *path, char __
    error = mnt_want_write(nd.mnt);
    if (error)
    return error;
    - error = setxattr(nd.dentry, nd.mnt, name, value, size, flags);
    + error = setxattr(nd.dentry, nd.mnt, name, value, size, flags, NULL);
    mnt_drop_write(nd.mnt);
    path_release(&nd);
    return error;
    @@ -281,7 +282,7 @@ sys_fsetxattr(int fd, char __user *name,
    goto out_fput;
    dentry = f->f_path.dentry;
    audit_inode(NULL, dentry);
    - error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags);
    + error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags, NULL);
    mnt_drop_write(f->f_vfsmnt);
    out_fput:
    fput(f);
    @@ -293,7 +294,7 @@ out_fput:
    */
    static ssize_t
    getxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
    - void __user *value, size_t size)
    + void __user *value, size_t size, struct file *file)
    {
    ssize_t error;
    void *kvalue = NULL;
    @@ -313,7 +314,7 @@ getxattr(struct dentry *dentry, struct v
    return -ENOMEM;
    }

    - error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
    + error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
    if (error > 0) {
    if (size && copy_to_user(value, kvalue, error))
    error = -EFAULT;
    @@ -336,7 +337,7 @@ sys_getxattr(char __user *path, char __u
    error = user_path_walk(path, &nd);
    if (error)
    return error;
    - error = getxattr(nd.dentry, nd.mnt, name, value, size);
    + error = getxattr(nd.dentry, nd.mnt, name, value, size, NULL);
    path_release(&nd);
    return error;
    }
    @@ -351,7 +352,7 @@ sys_lgetxattr(char __user *path, char __
    error = user_path_walk_link(path, &nd);
    if (error)
    return error;
    - error = getxattr(nd.dentry, nd.mnt, name, value, size);
    + error = getxattr(nd.dentry, nd.mnt, name, value, size, NULL);
    path_release(&nd);
    return error;
    }
    @@ -366,7 +367,8 @@ sys_fgetxattr(int fd, char __user *name,
    if (!f)
    return error;
    audit_inode(NULL, f->f_path.dentry);
    - error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
    + error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size,
    + NULL);
    fput(f);
    return error;
    }
    @@ -376,7 +378,7 @@ sys_fgetxattr(int fd, char __user *name,
    */
    static ssize_t
    listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
    - size_t size)
    + size_t size, struct file *file)
    {
    ssize_t error;
    char *klist = NULL;
    @@ -389,7 +391,7 @@ listxattr(struct dentry *dentry, struct
    return -ENOMEM;
    }

    - error = vfs_listxattr(dentry, mnt, klist, size);
    + error = vfs_listxattr(dentry, mnt, klist, size, file);
    if (error > 0) {
    if (size && copy_to_user(list, klist, error))
    error = -EFAULT;
    @@ -411,7 +413,7 @@ sys_listxattr(char __user *path, char __
    error = user_path_walk(path, &nd);
    if (error)
    return error;
    - error = listxattr(nd.dentry, nd.mnt, list, size);
    + error = listxattr(nd.dentry, nd.mnt, list, size, NULL);
    path_release(&nd);
    return error;
    }
    @@ -425,7 +427,7 @@ sys_llistxattr(char __user *path, char _
    error = user_path_walk_link(path, &nd);
    if (error)
    return error;
    - error = listxattr(nd.dentry, nd.mnt, list, size);
    + error = listxattr(nd.dentry, nd.mnt, list, size, NULL);
    path_release(&nd);
    return error;
    }
    @@ -440,7 +442,7 @@ sys_flistxattr(int fd, char __user *list
    if (!f)
    return error;
    audit_inode(NULL, f->f_path.dentry);
    - error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
    + error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, NULL);
    fput(f);
    return error;
    }
    @@ -449,7 +451,8 @@ sys_flistxattr(int fd, char __user *list
    * Extended attribute REMOVE operations
    */
    static long
    -removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name)
    +removexattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
    + struct file *file)
    {
    int error;
    char kname[XATTR_NAME_MAX + 1];
    @@ -460,7 +463,7 @@ removexattr(struct dentry *dentry, struc
    if (error < 0)
    return error;

    - return vfs_removexattr(dentry, mnt, kname);
    + return vfs_removexattr(dentry, mnt, kname, file);
    }

    asmlinkage long
    @@ -472,7 +475,7 @@ sys_removexattr(char __user *path, char
    error = user_path_walk(path, &nd);
    if (error)
    return error;
    - error = removexattr(nd.dentry, nd.mnt, name);
    + error = removexattr(nd.dentry, nd.mnt, name, NULL);
    path_release(&nd);
    return error;
    }
    @@ -486,7 +489,7 @@ sys_lremovexattr(char __user *path, char
    error = user_path_walk_link(path, &nd);
    if (error)
    return error;
    - error = removexattr(nd.dentry, nd.mnt, name);
    + error = removexattr(nd.dentry, nd.mnt, name, NULL);
    path_release(&nd);
    return error;
    }
    @@ -503,7 +506,7 @@ sys_fremovexattr(int fd, char __user *na
    return error;
    dentry = f->f_path.dentry;
    audit_inode(NULL, dentry);
    - error = removexattr(dentry, f->f_path.mnt, name);
    + error = removexattr(dentry, f->f_path.mnt, name, NULL);
    fput(f);
    return error;
    }
    --- a/include/linux/security.h
    +++ b/include/linux/security.h
    @@ -56,9 +56,9 @@ extern void cap_capset_set (struct task_
    extern int cap_bprm_set_security (struct linux_binprm *bprm);
    extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
    extern int cap_bprm_secureexec(struct linux_binprm *bprm);
    -extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags);
    +extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags, struct file *file);
    extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
    - char *name);
    + char *name, struct file *file);
    extern int cap_inode_need_killpriv(struct dentry *dentry);
    extern int cap_inode_killpriv(struct dentry *dentry);
    extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
    @@ -1274,16 +1274,18 @@ struct security_operations {
    int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
    void (*inode_delete) (struct inode *inode);
    int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
    - char *name, void *value, size_t size, int flags);
    + char *name, void *value, size_t size, int flags,
    + struct file *file);
    void (*inode_post_setxattr) (struct dentry *dentry,
    struct vfsmount *mnt,
    char *name, void *value,
    size_t size, int flags);
    int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
    - char *name);
    - int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
    + char *name, struct file *file);
    + int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
    + struct file *file);
    int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
    - char *name);
    + char *name, struct file *file);
    int (*inode_need_killpriv) (struct dentry *dentry);
    int (*inode_killpriv) (struct dentry *dentry);
    int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
    @@ -1540,15 +1542,17 @@ int security_inode_setattr(struct dentry
    int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
    void security_inode_delete(struct inode *inode);
    int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
    - char *name, void *value, size_t size, int flags);
    + char *name, void *value, size_t size, int flags,
    + struct file *file);
    void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
    char *name, void *value, size_t size,
    int flags);
    int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
    - char *name);
    -int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
    + char *name, struct file *file);
    +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
    + struct file *file);
    int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
    - char *name);
    + char *name, struct file *file);
    int security_inode_need_killpriv(struct dentry *dentry);
    int security_inode_killpriv(struct dentry *dentry);
    int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
    @@ -1934,9 +1938,10 @@ static inline void security_inode_delete

    static inline int security_inode_setxattr (struct dentry *dentry,
    struct vfsmount *mnt, char *name,
    - void *value, size_t size, int flags)
    + void *value, size_t size, int flags,
    + struct file *file)
    {
    - return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
    + return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
    }

    static inline void security_inode_post_setxattr (struct dentry *dentry,
    @@ -1947,21 +1952,24 @@ static inline void security_inode_post_s
    { }

    static inline int security_inode_getxattr (struct dentry *dentry,
    - struct vfsmount *mnt, char *name)
    + struct vfsmount *mnt, char *name,
    + struct file *file)
    {
    return 0;
    }

    static inline int security_inode_listxattr (struct dentry *dentry,
    - struct vfsmount *mnt)
    + struct vfsmount *mnt,
    + struct file *file)
    {
    return 0;
    }

    static inline int security_inode_removexattr (struct dentry *dentry,
    - struct vfsmount *mnt, char *name)
    + struct vfsmount *mnt, char *name,
    + struct file *file)
    {
    - return cap_inode_removexattr(dentry, mnt, name);
    + return cap_inode_removexattr(dentry, mnt, name, file);
    }

    static inline int security_inode_need_killpriv(struct dentry *dentry)
    --- a/include/linux/xattr.h
    +++ b/include/linux/xattr.h
    @@ -47,12 +47,12 @@ struct xattr_handler {
    };

    ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
    - size_t);
    + size_t, struct file *);
    ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
    - size_t size);
    + size_t size, struct file *);
    int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
    - int);
    -int vfs_removexattr(struct dentry *, struct vfsmount *, char *);
    + int, struct file *);
    +int vfs_removexattr(struct dentry *, struct vfsmount *, char *, struct file *);

    ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
    ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
    --- a/security/commoncap.c
    +++ b/security/commoncap.c
    @@ -362,7 +362,7 @@ int cap_bprm_secureexec (struct linux_bi
    }

    int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
    - void *value, size_t size, int flags)
    + void *value, size_t size, int flags, struct file *file)
    {
    if (!strcmp(name, XATTR_NAME_CAPS)) {
    if (!capable(CAP_SETFCAP))
    @@ -376,7 +376,7 @@ int cap_inode_setxattr(struct dentry *de
    }

    int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
    - char *name)
    + char *name, struct file *file)
    {
    if (!strcmp(name, XATTR_NAME_CAPS)) {
    if (!capable(CAP_SETFCAP))
    --- a/security/dummy.c
    +++ b/security/dummy.c
    @@ -349,7 +349,7 @@ static void dummy_inode_delete (struct i

    static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
    char *name, void *value, size_t size,
    - int flags)
    + int flags, struct file *file)
    {
    if (!strncmp(name, XATTR_SECURITY_PREFIX,
    sizeof(XATTR_SECURITY_PREFIX) - 1) &&
    @@ -366,18 +366,20 @@ static void dummy_inode_post_setxattr (s
    }

    static int dummy_inode_getxattr (struct dentry *dentry,
    - struct vfsmount *mnt, char *name)
    + struct vfsmount *mnt, char *name,
    + struct file *file)
    {
    return 0;
    }

    -static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
    +static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
    + struct file *file)
    {
    return 0;
    }

    static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
    - char *name)
    + char *name, struct file *file)
    {
    if (!strncmp(name, XATTR_SECURITY_PREFIX,
    sizeof(XATTR_SECURITY_PREFIX) - 1) &&
    --- a/security/security.c
    +++ b/security/security.c
    @@ -442,12 +442,13 @@ void security_inode_delete(struct inode
    }

    int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
    - char *name, void *value, size_t size, int flags)
    + char *name, void *value, size_t size, int flags,
    + struct file *file)
    {
    if (unlikely(IS_PRIVATE(dentry->d_inode)))
    return 0;
    return security_ops->inode_setxattr(dentry, mnt, name, value, size,
    - flags);
    + flags, file);
    }

    void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
    @@ -461,26 +462,27 @@ void security_inode_post_setxattr(struct
    }

    int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
    - char *name)
    + char *name, struct file *file)
    {
    if (unlikely(IS_PRIVATE(dentry->d_inode)))
    return 0;
    - return security_ops->inode_getxattr(dentry, mnt, name);
    + return security_ops->inode_getxattr(dentry, mnt, name, file);
    }

    -int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
    +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
    + struct file *file)
    {
    if (unlikely(IS_PRIVATE(dentry->d_inode)))
    return 0;
    - return security_ops->inode_listxattr(dentry, mnt);
    + return security_ops->inode_listxattr(dentry, mnt, file);
    }

    int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
    - char *name)
    + char *name, struct file *file)
    {
    if (unlikely(IS_PRIVATE(dentry->d_inode)))
    return 0;
    - return security_ops->inode_removexattr(dentry, mnt, name);
    + return security_ops->inode_removexattr(dentry, mnt, name, file);
    }

    int security_inode_need_killpriv(struct dentry *dentry)
    --- a/security/selinux/hooks.c
    +++ b/security/selinux/hooks.c
    @@ -2334,7 +2334,7 @@ static int selinux_inode_setotherxattr(s

    static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
    char *name, void *value, size_t size,
    - int flags)
    + int flags, struct file *file)
    {
    struct task_security_struct *tsec = current->security;
    struct inode *inode = dentry->d_inode;
    @@ -2410,18 +2410,20 @@ static void selinux_inode_post_setxattr(
    }

    static int selinux_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
    - char *name)
    + char *name, struct file *file)
    {
    return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
    }

    -static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt)
    +static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
    + struct file *file)
    {
    return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
    }

    static int selinux_inode_removexattr (struct dentry *dentry,
    - struct vfsmount *mnt, char *name)
    + struct vfsmount *mnt, char *name,
    + struct file *file)
    {
    if (strcmp(name, XATTR_NAME_SELINUX))
    return selinux_inode_setotherxattr(dentry, name);
    --

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-10-26 09:13    [W:0.049 / U:29.228 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site