ssize_t vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) { struct inode *inode = dentry->d_inode; int error; error = xattr_permission(inode, name, MAY_READ); if (error) return error; error = security_inode_getxattr(dentry, name); if (error) return error; if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; int ret = xattr_getsecurity(inode, suffix, value, size); /* * Only overwrite the return value if a security module * is actually active. */ if (ret == -EOPNOTSUPP) goto nolsm; return ret; } nolsm: if (inode->i_op->getxattr) error = inode->i_op->getxattr(dentry, name, value, size); else error = -EOPNOTSUPP; return error; }
static struct posix_acl * _get_posix_acl(struct dentry *dentry, char *key) { struct inode *inode = dentry->d_inode; char *buf = NULL; int buflen, error = 0; struct posix_acl *pacl = NULL; error = -EOPNOTSUPP; if (inode->i_op == NULL) goto out_err; if (inode->i_op->getxattr == NULL) goto out_err; error = security_inode_getxattr(dentry, key); if (error) goto out_err; buflen = inode->i_op->getxattr(dentry, key, NULL, 0); if (buflen <= 0) { error = buflen < 0 ? buflen : -ENODATA; goto out_err; } buf = kmalloc(buflen, GFP_KERNEL); if (buf == NULL) { error = -ENOMEM; goto out_err; } error = inode->i_op->getxattr(dentry, key, buf, buflen); if (error < 0) goto out_err; pacl = posix_acl_from_xattr(buf, buflen); out: kfree(buf); return pacl; out_err: pacl = ERR_PTR(error); goto out; }
/* * Extended attribute GET operations */ static ssize_t getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) { ssize_t error; void *kvalue = NULL; char kname[XATTR_NAME_MAX + 1]; 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) size = XATTR_SIZE_MAX; kvalue = kmalloc(size, GFP_KERNEL); if (!kvalue) return -ENOMEM; } error = -EOPNOTSUPP; if (d->d_inode->i_op && d->d_inode->i_op->getxattr) { error = security_inode_getxattr(d, kname); if (error) goto out; error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); if (error > 0) { if (size && copy_to_user(value, kvalue, error)) error = -EFAULT; } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { /* The file system tried to returned a value bigger than XATTR_SIZE_MAX bytes. Not possible. */ error = -E2BIG; } } out: if (kvalue) kfree(kvalue); 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; }