/* This is used to cache the default acl before a new object is created. * The biggest reason for this is to get an idea of how many blocks will * actually be required for the create operation if we must inherit an ACL. * An ACL write can add up to 3 object creations and an additional file write * so we'd prefer not to reserve that many blocks in the journal if we can. * It also has the advantage of not loading the ACL with a transaction open, * this may seem silly, but if the owner of the directory is doing the * creation, the ACL may not be loaded since the permissions wouldn't require * it. * We return the number of blocks required for the transaction. */ int reiserfs_cache_default_acl(struct inode *inode) { struct posix_acl *acl; int nblocks = 0; if (IS_PRIVATE(inode)) return 0; acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); if (acl && !IS_ERR(acl)) { int size = reiserfs_acl_size(acl->a_count); /* Other xattrs can be created during inode creation. We don't * want to claim too many blocks, so we check to see if we * we need to create the tree to the xattrs, and then we * just want two files. */ nblocks = reiserfs_xattr_jcreate_nblocks(inode); nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb); REISERFS_I(inode)->i_flags |= i_has_xattr_dir; /* We need to account for writes + bitmaps for two files */ nblocks += reiserfs_xattr_nblocks(inode, size) * 4; posix_acl_release(acl); } return nblocks; }
/* dir->i_mutex: locked, * inode is new and not released into the wild yet */ int reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, struct inode *dir, struct dentry *dentry, struct inode *inode) { struct posix_acl *acl; int err = 0; /* ACLs only get applied to files and directories */ if (S_ISLNK(inode->i_mode)) return 0; /* ACLs can only be used on "new" objects, so if it's an old object * there is nothing to inherit from */ if (get_inode_sd_version(dir) == STAT_DATA_V1) goto apply_umask; /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This * would be useless since permissions are ignored, and a pain because * it introduces locking cycles */ if (IS_PRIVATE(dir)) { inode->i_flags |= S_PRIVATE; goto apply_umask; } acl = reiserfs_get_acl(dir, ACL_TYPE_DEFAULT); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl) { /* Copy the default ACL to the default ACL of a new directory */ if (S_ISDIR(inode->i_mode)) { err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT, acl); if (err) goto cleanup; } /* Now we reconcile the new ACL and the mode, potentially modifying both */ err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode); if (err < 0) return err; /* If we need an ACL.. */ if (err > 0) err = reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, acl); cleanup: posix_acl_release(acl); } else { apply_umask: /* no ACL, apply umask */ inode->i_mode &= ~current_umask(); } return err; }
/* Looks up and caches the result of the default ACL. * We do this so that we don't need to carry the xattr_sem into * reiserfs_new_inode if we don't need to */ int reiserfs_cache_default_acl(struct inode *inode) { int ret = 0; if (reiserfs_posixacl(inode->i_sb) && !is_reiserfs_priv_object(inode)) { struct posix_acl *acl; reiserfs_read_lock_xattr_i(inode); reiserfs_read_lock_xattrs(inode->i_sb); acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); reiserfs_read_unlock_xattrs(inode->i_sb); reiserfs_read_unlock_xattr_i(inode); ret = (acl && !IS_ERR(acl)); if (ret) posix_acl_release(acl); } return ret; }
int reiserfs_acl_chmod(struct inode *inode) { struct posix_acl *acl, *clone; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (get_inode_sd_version(inode) == STAT_DATA_V1 || !reiserfs_posixacl(inode->i_sb)) { return 0; } reiserfs_write_unlock(inode->i_sb); acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); reiserfs_write_lock(inode->i_sb); if (!acl) return 0; if (IS_ERR(acl)) return PTR_ERR(acl); clone = posix_acl_clone(acl, GFP_NOFS); posix_acl_release(acl); if (!clone) return -ENOMEM; error = posix_acl_chmod_masq(clone, inode->i_mode); if (!error) { struct reiserfs_transaction_handle th; size_t size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(clone->a_count)); int depth; depth = reiserfs_write_lock_once(inode->i_sb); error = journal_begin(&th, inode->i_sb, size * 2); if (!error) { int error2; error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, clone); error2 = journal_end(&th, inode->i_sb, size * 2); if (error2) error = error2; } reiserfs_write_unlock_once(inode->i_sb, depth); } posix_acl_release(clone); return error; }
int reiserfs_acl_chmod (struct inode *inode) { struct posix_acl *acl, *clone; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (get_inode_sd_version (inode) == STAT_DATA_V1 || !reiserfs_posixacl(inode->i_sb)) { return 0; } reiserfs_read_lock_xattrs (inode->i_sb); acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); reiserfs_read_unlock_xattrs (inode->i_sb); if (!acl) return 0; if (IS_ERR(acl)) return PTR_ERR(acl); clone = posix_acl_clone(acl, GFP_NOFS); posix_acl_release(acl); if (!clone) return -ENOMEM; error = posix_acl_chmod_masq(clone, inode->i_mode); if (!error) { int lock = !has_xattr_dir (inode); reiserfs_write_lock_xattr_i (inode); if (lock) reiserfs_write_lock_xattrs (inode->i_sb); else reiserfs_read_lock_xattrs (inode->i_sb); error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); if (lock) reiserfs_write_unlock_xattrs (inode->i_sb); else reiserfs_read_unlock_xattrs (inode->i_sb); reiserfs_write_unlock_xattr_i (inode); } posix_acl_release(clone); return error; }
static int xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) { struct posix_acl *acl; int error; if (!reiserfs_posixacl(inode->i_sb)) return -EOPNOTSUPP; acl = reiserfs_get_acl (inode, type); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl == NULL) return -ENODATA; error = posix_acl_to_xattr(acl, buffer, size); posix_acl_release(acl); return error; }
static int posix_acl_get(struct dentry *dentry, const char *name, void *buffer, size_t size, int type) { struct posix_acl *acl; int error; if (!reiserfs_posixacl(dentry->d_sb)) return -EOPNOTSUPP; acl = reiserfs_get_acl(dentry->d_inode, type); if (IS_ERR(acl)) return PTR_ERR(acl); if (acl == NULL) return -ENODATA; error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); posix_acl_release(acl); return error; }
/* dir->i_sem: down, * inode is new and not released into the wild yet */ int reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode) { struct posix_acl *acl; int err = 0; /* ACLs only get applied to files and directories */ if (S_ISLNK (inode->i_mode)) return 0; /* ACLs can only be used on "new" objects, so if it's an old object * there is nothing to inherit from */ if (get_inode_sd_version (dir) == STAT_DATA_V1) goto apply_umask; /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This * would be useless since permissions are ignored, and a pain because * it introduces locking cycles */ if (is_reiserfs_priv_object (dir)) { reiserfs_mark_inode_private (inode); goto apply_umask; } acl = reiserfs_get_acl (dir, ACL_TYPE_DEFAULT); if (IS_ERR (acl)) { if (PTR_ERR (acl) == -ENODATA) goto apply_umask; return PTR_ERR (acl); } if (acl) { struct posix_acl *acl_copy; mode_t mode = inode->i_mode; int need_acl; /* Copy the default ACL to the default ACL of a new directory */ if (S_ISDIR (inode->i_mode)) { err = reiserfs_set_acl (inode, ACL_TYPE_DEFAULT, acl); if (err) goto cleanup; } /* Now we reconcile the new ACL and the mode, potentially modifying both */ acl_copy = posix_acl_clone (acl, GFP_NOFS); if (!acl_copy) { err = -ENOMEM; goto cleanup; } need_acl = posix_acl_create_masq (acl_copy, &mode); if (need_acl >= 0) { if (mode != inode->i_mode) { inode->i_mode = mode; } /* If we need an ACL.. */ if (need_acl > 0) { err = reiserfs_set_acl (inode, ACL_TYPE_ACCESS, acl_copy); if (err) goto cleanup_copy; } } cleanup_copy: posix_acl_release (acl_copy); cleanup: posix_acl_release (acl); } else { apply_umask: /* no ACL, apply umask */ inode->i_mode &= ~current->fs->umask; } return err; }
/* * Inode operation listxattr() * * We totally ignore the generic listxattr here because it would be stupid * not to. Since the xattrs are organized in a directory, we can just * readdir to find them. */ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) { struct dentry *dir; int err = 0; loff_t pos = 0; struct listxattr_buf buf = { .dentry = dentry, .buf = buffer, .size = buffer ? size : 0, }; if (!dentry->d_inode) return -EINVAL; if (!dentry->d_sb->s_xattr || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) return -EOPNOTSUPP; dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); if (IS_ERR(dir)) { err = PTR_ERR(dir); if (err == -ENODATA) err = 0; /* Not an error if there aren't any xattrs */ goto out; } mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); err = reiserfs_readdir_dentry(dir, &buf, listxattr_filler, &pos); mutex_unlock(&dir->d_inode->i_mutex); if (!err) err = buf.pos; dput(dir); out: return err; } static int reiserfs_check_acl(struct inode *inode, int mask, unsigned int flags) { struct posix_acl *acl; int error = -EAGAIN; /* do regular unix permission checks by default */ if (flags & IPERM_FLAG_RCU) return -ECHILD; acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); if (acl) { if (!IS_ERR(acl)) { error = posix_acl_permission(inode, acl, mask); posix_acl_release(acl); } else if (PTR_ERR(acl) != -ENODATA) error = PTR_ERR(acl); } return error; } static int create_privroot(struct dentry *dentry) { int err; struct inode *inode = dentry->d_parent->d_inode; WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); err = xattr_mkdir(inode, dentry, 0700); if (err || !dentry->d_inode) { reiserfs_warning(dentry->d_sb, "jdm-20006", "xattrs/ACLs enabled and couldn't " "find/create .reiserfs_priv. " "Failing mount."); return -EOPNOTSUPP; } dentry->d_inode->i_flags |= S_PRIVATE; reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " "storage.\n", PRIVROOT_NAME); return 0; }