static int set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key) { int len; size_t buflen; char *buf = NULL; int error = 0; struct inode *inode = dentry->d_inode; buflen = posix_acl_xattr_size(pacl->a_count); buf = kmalloc(buflen, GFP_KERNEL); error = -ENOMEM; if (buf == NULL) goto out; len = posix_acl_to_xattr(pacl, buf, buflen); if (len < 0) { error = len; goto out; } error = -EOPNOTSUPP; if (inode->i_op && inode->i_op->setxattr) { down(&inode->i_sem); security_inode_setxattr(dentry, key, buf, len, 0); error = inode->i_op->setxattr(dentry, key, buf, len, 0); if (!error) security_inode_post_setxattr(dentry, key, buf, len, 0); up(&inode->i_sem); } out: kfree(buf); return error; }
int vfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { struct inode *inode = dentry->d_inode; int error; error = xattr_permission(inode, name, MAY_WRITE); if (error) return error; mutex_lock(&inode->i_mutex); error = security_inode_setxattr(dentry, name, value, size, flags); if (error) goto out; error = -EOPNOTSUPP; if (inode->i_op->setxattr) { error = inode->i_op->setxattr(dentry, name, value, size, flags); if (!error) { fsnotify_xattr(dentry); security_inode_post_setxattr(dentry, name, value, size, flags); } } else if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; error = security_inode_setsecurity(inode, suffix, value, size, flags); if (!error) fsnotify_xattr(dentry); } out: mutex_unlock(&inode->i_mutex); return error; }
/* * Extended attribute SET operations */ static long setxattr(struct dentry *d, char __user *name, void __user *value, size_t size, int flags) { int error; void *kvalue = NULL; char kname[XATTR_NAME_MAX + 1]; if (flags & ~(XATTR_CREATE|XATTR_REPLACE)) return -EINVAL; error = strncpy_from_user(kname, name, sizeof(kname)); if (error == 0 || error == sizeof(kname)) error = -ERANGE; if (error < 0) return error; if (size) { if (size > XATTR_SIZE_MAX) return -E2BIG; kvalue = kmalloc(size, GFP_KERNEL); if (!kvalue) return -ENOMEM; if (copy_from_user(kvalue, value, size)) { kfree(kvalue); return -EFAULT; } } error = -EOPNOTSUPP; if (d->d_inode->i_op && d->d_inode->i_op->setxattr) { down(&d->d_inode->i_sem); audit_notify_watch(d->d_inode, MAY_WRITE); error = security_inode_setxattr(d, kname, kvalue, size, flags); if (error) goto out; error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags); if (!error) security_inode_post_setxattr(d, kname, kvalue, size, flags); out: up(&d->d_inode->i_sem); } if (kvalue) kfree(kvalue); return error; }
/** * __vfs_setxattr_noperm - perform setxattr operation without performing * permission checks. * * @dentry - object to perform setxattr on * @name - xattr name to set * @value - value to set @name to * @size - size of @value * @flags - flags to pass into filesystem operations * * returns the result of the internal setxattr or setsecurity operations. * * This function requires the caller to lock the inode's i_mutex before it * is executed. It also assumes that the caller will make the appropriate * permission checks. */ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { struct inode *inode = dentry->d_inode; int error = -EOPNOTSUPP; if (inode->i_op->setxattr) { error = inode->i_op->setxattr(dentry, name, value, size, flags); if (!error) { fsnotify_xattr(dentry); security_inode_post_setxattr(dentry, name, value, size, flags); } } else if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; error = security_inode_setsecurity(inode, suffix, value, size, flags); if (!error) fsnotify_xattr(dentry); } return error; }
/*Not Working Yet*/ static int copyup_xattrs(struct dentry *old_hidden_dentry, struct dentry *new_hidden_dentry) { int err = 0; ssize_t list_size = -1; char *name_list = NULL; char *attr_value = NULL; char *name_list_orig = NULL; print_entry_location(); PASSERT(old_hidden_dentry); PASSERT(old_hidden_dentry->d_inode); PASSERT(old_hidden_dentry->d_inode->i_op); PASSERT(new_hidden_dentry); PASSERT(new_hidden_dentry->d_inode); PASSERT(new_hidden_dentry->d_inode->i_op); if (!old_hidden_dentry->d_inode->i_op->getxattr || !old_hidden_dentry->d_inode->i_op->listxattr || !new_hidden_dentry->d_inode->i_op->setxattr) { err = -ENOTSUPP; goto out; } list_size = old_hidden_dentry->d_inode->i_op->listxattr(old_hidden_dentry, NULL, 0); if (list_size <= 0) { err = list_size; goto out; } name_list = xattr_alloc(list_size + 1, XATTR_LIST_MAX); if (!name_list || IS_ERR(name_list)) { err = PTR_ERR(name_list); goto out; } list_size = old_hidden_dentry->d_inode->i_op->listxattr(old_hidden_dentry, name_list, list_size); attr_value = xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX); if (!attr_value || IS_ERR(attr_value)) { err = PTR_ERR(name_list); goto out; } name_list_orig = name_list; while (*name_list) { ssize_t size; down(&old_hidden_dentry->d_inode->i_sem); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) err = security_inode_getxattr(old_hidden_dentry, name_list); if (err) size = err; else #endif size = old_hidden_dentry->d_inode->i_op-> getxattr(old_hidden_dentry, name_list, attr_value, XATTR_SIZE_MAX); up(&old_hidden_dentry->d_inode->i_sem); if (size < 0) { err = size; goto out; } if (size > XATTR_SIZE_MAX) { err = -E2BIG; goto out; } down(&new_hidden_dentry->d_inode->i_sem); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) err = security_inode_setxattr(old_hidden_dentry, name_list, attr_value, size, 0); if (!err) { #endif err = new_hidden_dentry->d_inode->i_op-> setxattr(new_hidden_dentry, name_list, attr_value, size, 0); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) if (!err) security_inode_post_setxattr(old_hidden_dentry, name_list, attr_value, size, 0); } #endif up(&new_hidden_dentry->d_inode->i_sem); if (err < 0) goto out; name_list += strlen(name_list) + 1; } out: name_list = name_list_orig; if (name_list) xattr_free(name_list, list_size + 1); if (attr_value) xattr_free(attr_value, XATTR_SIZE_MAX); /* It is no big deal if this fails, we just roll with the punches. */ if (err == -ENOTSUPP) err = 0; return err; }