static int ext2_xattr_security_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name, value, size, flags); }
static int ext2_xattr_security_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { if (strcmp(name, "") == 0) return -EINVAL; return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name, value, size, flags); }
static int ext2_xattr_trusted_set(struct inode *inode, const char *name, const void *value, size_t size, int flags) { if (strcmp(name, "") == 0) return -EINVAL; return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name, value, size, flags); }
void ext2_delete_from_parent(struct inode * inode) { int *value, *new_value, retval, count, *temp, *temp1; unsigned long parent_ino; struct inode * parent_inode; // ext2_debug("%lu: Looking for parent\n", inode->i_ino); retval = ext2_xattr_get(inode, 10, "parent", NULL, 0); if(retval > 0) { // ext2_debug("%lu: retval > 0\n", inode->i_ino); retval = ext2_xattr_get(inode, 10, "parent", &parent_ino, sizeof(unsigned long)); // ext2_debug("%lu: Found parent %lu\n", inode->i_ino, parent_ino); parent_inode = iget(inode->i_sb, parent_ino); if(!parent_inode) return; retval = ext2_xattr_get(parent_inode, 11, "children", NULL, 0); if (retval > 0) { value = (int *)kmalloc(retval, GFP_KERNEL); new_value = (int *)kmalloc(retval, GFP_KERNEL); temp = value; temp1 = new_value; retval = ext2_xattr_get(parent_inode, 11, "children", value, retval); count = 0; while(*value) { if(*value != (int)(inode->i_ino)) { *new_value = *value; new_value++; count++; } else { // ext2_debug("%lu: deleting %d from parent list\n", parent_inode->i_ino, *value); } value++; } // ext2_debug("%lu: parent has %d children left\n", parent_inode->i_ino, count); *new_value = 0; ext2_xattr_set(parent_inode, 11, "children", temp1, (count+1)*sizeof(int), 0); if(!count) { // delete inode } cleanup: kfree(temp); kfree(temp1); iput(parent_inode); /* This should take care of dropping root when it has no children */ } } else { // ext2_debug("no parent found\n"); return; } }
static int ext2_xattr_trusted_set(const struct xattr_handler *handler, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { if (strcmp(name, "") == 0) return -EINVAL; return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name, value, size, flags); }
static int ext2_xattr_user_set(struct inode *inode, const char *name, const void *value, size_t size, int flags) { if (strcmp(name, "") == 0) return -EINVAL; if (!test_opt(inode->i_sb, XATTR_USER)) return -EOPNOTSUPP; return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name, value, size, flags); }
/* * inode->i_mutex: down */ static int ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) { int name_index; void *value = NULL; size_t size = 0; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; switch(type) { case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { mode_t mode = inode->i_mode; error = posix_acl_equiv_mode(acl, &mode); if (error < 0) return error; else { inode->i_mode = mode; inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); if (error == 0) acl = NULL; } } break; case ACL_TYPE_DEFAULT: name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { value = ext2_acl_to_disk(acl, &size); if (IS_ERR(value)) return (int)PTR_ERR(value); } error = ext2_xattr_set(inode, name_index, "", value, size, 0); kfree(value); if (!error) set_cached_acl(inode, type, acl); return error; }
static int ext2_initxattrs(struct inode *inode, const struct xattr *xattr_array, void *fs_info) { const struct xattr *xattr; int err = 0; for (xattr = xattr_array; xattr->name != NULL; xattr++) { err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, xattr->name, xattr->value, xattr->value_len, 0); if (err < 0) break; } return err; }
/* * inode->i_mutex: down */ int ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int name_index; void *value = NULL; size_t size = 0; int error; switch(type) { case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { error = posix_acl_update_mode(inode, &inode->i_mode, &acl); if (error) return error; inode->i_ctime = current_time(inode); mark_inode_dirty(inode); } break; case ACL_TYPE_DEFAULT: name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { value = ext2_acl_to_disk(acl, &size); if (IS_ERR(value)) return (int)PTR_ERR(value); } error = ext2_xattr_set(inode, name_index, "", value, size, 0); kfree(value); if (!error) set_cached_acl(inode, type, acl); return error; }
static int ext2_xattr_user_set(struct inode *inode, const char *name, const void *value, size_t size, int flags) { int error; if (strcmp(name, "") == 0) return -EINVAL; if (!test_opt(inode->i_sb, XATTR_USER)) return -EOPNOTSUPP; if ( !S_ISREG(inode->i_mode) && (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) return -EPERM; error = permission(inode, MAY_WRITE, NULL); if (error) return error; return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name, value, size, flags); }
int ext2_init_security(struct inode *inode, struct inode *dir) { int err; size_t len; void *value; char *name; err = security_inode_init_security(inode, dir, &name, &value, &len); if (err) { if (err == -EOPNOTSUPP) return 0; return err; } err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name, value, len, 0); kfree(name); kfree(value); return err; }
/* * inode->i_sem: down */ static int ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) { struct ext2_inode_info *ei = EXT2_I(inode); int name_index; void *value = NULL; size_t size; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; switch(type) { case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { mode_t mode = inode->i_mode; error = posix_acl_equiv_mode(acl, &mode); if (error < 0) return error; else { inode->i_mode = mode; mark_inode_dirty(inode); if (error == 0) acl = NULL; } } break; case ACL_TYPE_DEFAULT: name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { if (acl->a_count > EXT2_ACL_MAX_ENTRIES) return -EINVAL; value = ext2_acl_to_disk(acl, &size); if (IS_ERR(value)) return (int)PTR_ERR(value); } error = ext2_xattr_set(inode, name_index, "", value, size, 0); if (value) kfree(value); if (!error) { switch(type) { case ACL_TYPE_ACCESS: ext2_iset_acl(inode, &ei->i_acl, acl); break; case ACL_TYPE_DEFAULT: ext2_iset_acl(inode, &ei->i_default_acl, acl); break; } } return error; }