/* * Hook in SELinux. This is not quite correct yet, what we really need * here (as we do for default ACLs) is a mechanism by which creation of * these attrs can be journalled at inode creation time (along with the * inode, of course, such that log replay can't cause these to be lost). */ STATIC int xfs_init_security( struct inode *inode, struct inode *dir) { struct xfs_inode *ip = XFS_I(inode); size_t length; void *value; unsigned char *name; int error; error = security_inode_init_security(inode, dir, (char **)&name, &value, &length); if (error) { if (error == -EOPNOTSUPP) return 0; return -error; } error = xfs_attr_set(ip, name, value, length, ATTR_SECURE); kfree(name); kfree(value); return error; }
STATIC int xfs_attrmulti_attr_set( struct inode *inode, char *name, const char __user *ubuf, __uint32_t len, __uint32_t flags) { char *kbuf; int error = EFAULT; if (IS_RDONLY(inode)) return -EROFS; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) return EPERM; if (len > XATTR_SIZE_MAX) return EINVAL; kbuf = memdup_user(ubuf, len); if (IS_ERR(kbuf)) return PTR_ERR(kbuf); error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); return error; }
int xfs_attrmulti_attr_set( struct inode *inode, unsigned char *name, const unsigned char __user *ubuf, __uint32_t len, __uint32_t flags) { unsigned char *kbuf; int error; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) return -EPERM; if (len > XFS_XATTR_SIZE_MAX) return -EINVAL; kbuf = memdup_user(ubuf, len); if (IS_ERR(kbuf)) return PTR_ERR(kbuf); error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); if (!error) xfs_forget_acl(inode, name, flags); kfree(kbuf); return error; }
/* * Hook in SELinux. This is not quite correct yet, what we really need * here (as we do for default ACLs) is a mechanism by which creation of * these attrs can be journalled at inode creation time (along with the * inode, of course, such that log replay can't cause these to be lost). */ STATIC int xfs_init_security( bhv_vnode_t *vp, struct inode *dir) { struct inode *ip = vn_to_inode(vp); size_t length; void *value; char *name; int error; error = security_inode_init_security(ip, dir, &name, &value, &length); if (error) { if (error == -EOPNOTSUPP) return 0; return -error; } error = xfs_attr_set(XFS_I(ip), name, value, length, ATTR_SECURE); if (!error) xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED); kfree(name); kfree(value); return error; }
static int xfs_xattr_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int xflags) { struct xfs_inode *ip = XFS_I(d_inode(dentry)); int error; if (strcmp(name, "") == 0) return -EINVAL; /* Convert Linux syscall to XFS internal ATTR flags */ if (flags & XATTR_CREATE) xflags |= ATTR_CREATE; if (flags & XATTR_REPLACE) xflags |= ATTR_REPLACE; if (!value) return xfs_attr_remove(ip, (unsigned char *)name, xflags); error = xfs_attr_set(ip, (unsigned char *)name, (void *)value, size, xflags); if (!error) xfs_forget_acl(d_inode(dentry), name, xflags); return error; }
STATIC int xfs_attrmulti_attr_set( struct inode *inode, char *name, const char __user *ubuf, __uint32_t len, __uint32_t flags) { char *kbuf; int error = EFAULT; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) return EPERM; if (len > XATTR_SIZE_MAX) return EINVAL; kbuf = kmalloc(len, GFP_KERNEL); if (!kbuf) return ENOMEM; if (copy_from_user(kbuf, ubuf, len)) goto out_kfree; error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); out_kfree: kfree(kbuf); return error; }
/* * Set the EA with the ACL and do endian conversion. */ STATIC void xfs_acl_set_attr( bhv_vnode_t *vp, xfs_acl_t *aclp, int kind, int *error) { xfs_acl_entry_t *ace, *newace, *end; xfs_acl_t *newacl; int len; if (!(_ACL_ALLOC(newacl))) { *error = ENOMEM; return; } len = sizeof(xfs_acl_t) - (sizeof(xfs_acl_entry_t) * (XFS_ACL_MAX_ENTRIES - aclp->acl_cnt)); end = &aclp->acl_entry[0]+aclp->acl_cnt; for (ace = &aclp->acl_entry[0], newace = &newacl->acl_entry[0]; ace < end; ace++, newace++) { INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag); INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id); INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); } INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); *error = xfs_attr_set(xfs_vtoi(vp), kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT, (char *)newacl, len, ATTR_ROOT); _ACL_FREE(newacl); }
STATIC int xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) { struct xfs_inode *ip = XFS_I(inode); unsigned char *ea_name; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; switch (type) { case ACL_TYPE_ACCESS: ea_name = SGI_ACL_FILE; break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; ea_name = SGI_ACL_DEFAULT; break; default: return -EINVAL; } if (acl) { struct xfs_acl *xfs_acl; int len = XFS_ACL_MAX_SIZE(ip->i_mount); xfs_acl = kzalloc(len, GFP_KERNEL); if (!xfs_acl) return -ENOMEM; xfs_acl_to_disk(xfs_acl, acl); /* subtract away the unused acl entries */ len -= sizeof(struct xfs_acl_entry) * (XFS_ACL_MAX_ENTRIES(ip->i_mount) - acl->a_count); error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, len, ATTR_ROOT); kfree(xfs_acl); } else { /* * A NULL ACL argument means we want to remove the ACL. */ error = -xfs_attr_remove(ip, ea_name, ATTR_ROOT); /* * If the attribute didn't exist to start with that's fine. */ if (error == -ENOATTR) error = 0; } if (!error) set_cached_acl(inode, type, acl); return error; }
int xfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, void *fs_info) { const struct xattr *xattr; struct xfs_inode *ip = XFS_I(inode); int error = 0; for (xattr = xattr_array; xattr->name != NULL; xattr++) { error = xfs_attr_set(ip, xattr->name, xattr->value, xattr->value_len, ATTR_SECURE); if (error < 0) break; } return error; }
static int xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused, struct inode *inode, const char *name, const void *value, size_t size, int flags) { int xflags = handler->flags; struct xfs_inode *ip = XFS_I(inode); int error; /* Convert Linux syscall to XFS internal ATTR flags */ if (flags & XATTR_CREATE) xflags |= ATTR_CREATE; if (flags & XATTR_REPLACE) xflags |= ATTR_REPLACE; if (!value) return xfs_attr_remove(ip, (unsigned char *)name, xflags); error = xfs_attr_set(ip, (unsigned char *)name, (void *)value, size, xflags); if (!error) xfs_forget_acl(inode, name, xflags); return error; }