412 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <linux/capability.h>3#include <linux/fs.h>4#include <linux/posix_acl.h>5#include "reiserfs.h"6#include <linux/errno.h>7#include <linux/pagemap.h>8#include <linux/xattr.h>9#include <linux/slab.h>10#include <linux/posix_acl_xattr.h>11#include "xattr.h"12#include "acl.h"13#include <linux/uaccess.h>14 15static int __reiserfs_set_acl(struct reiserfs_transaction_handle *th,16 struct inode *inode, int type,17 struct posix_acl *acl);18 19 20int21reiserfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,22 struct posix_acl *acl, int type)23{24 int error, error2;25 struct reiserfs_transaction_handle th;26 size_t jcreate_blocks;27 int size = acl ? posix_acl_xattr_size(acl->a_count) : 0;28 int update_mode = 0;29 struct inode *inode = d_inode(dentry);30 umode_t mode = inode->i_mode;31 32 /*33 * Pessimism: We can't assume that anything from the xattr root up34 * has been created.35 */36 37 jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +38 reiserfs_xattr_nblocks(inode, size) * 2;39 40 reiserfs_write_lock(inode->i_sb);41 error = journal_begin(&th, inode->i_sb, jcreate_blocks);42 reiserfs_write_unlock(inode->i_sb);43 if (error == 0) {44 if (type == ACL_TYPE_ACCESS && acl) {45 error = posix_acl_update_mode(&nop_mnt_idmap, inode,46 &mode, &acl);47 if (error)48 goto unlock;49 update_mode = 1;50 }51 error = __reiserfs_set_acl(&th, inode, type, acl);52 if (!error && update_mode)53 inode->i_mode = mode;54unlock:55 reiserfs_write_lock(inode->i_sb);56 error2 = journal_end(&th);57 reiserfs_write_unlock(inode->i_sb);58 if (error2)59 error = error2;60 }61 62 return error;63}64 65/*66 * Convert from filesystem to in-memory representation.67 */68static struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t size)69{70 const char *end = (char *)value + size;71 int n, count;72 struct posix_acl *acl;73 74 if (!value)75 return NULL;76 if (size < sizeof(reiserfs_acl_header))77 return ERR_PTR(-EINVAL);78 if (((reiserfs_acl_header *) value)->a_version !=79 cpu_to_le32(REISERFS_ACL_VERSION))80 return ERR_PTR(-EINVAL);81 value = (char *)value + sizeof(reiserfs_acl_header);82 count = reiserfs_acl_count(size);83 if (count < 0)84 return ERR_PTR(-EINVAL);85 if (count == 0)86 return NULL;87 acl = posix_acl_alloc(count, GFP_NOFS);88 if (!acl)89 return ERR_PTR(-ENOMEM);90 for (n = 0; n < count; n++) {91 reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value;92 if ((char *)value + sizeof(reiserfs_acl_entry_short) > end)93 goto fail;94 acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);95 acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);96 switch (acl->a_entries[n].e_tag) {97 case ACL_USER_OBJ:98 case ACL_GROUP_OBJ:99 case ACL_MASK:100 case ACL_OTHER:101 value = (char *)value +102 sizeof(reiserfs_acl_entry_short);103 break;104 105 case ACL_USER:106 value = (char *)value + sizeof(reiserfs_acl_entry);107 if ((char *)value > end)108 goto fail;109 acl->a_entries[n].e_uid = 110 make_kuid(&init_user_ns,111 le32_to_cpu(entry->e_id));112 break;113 case ACL_GROUP:114 value = (char *)value + sizeof(reiserfs_acl_entry);115 if ((char *)value > end)116 goto fail;117 acl->a_entries[n].e_gid =118 make_kgid(&init_user_ns,119 le32_to_cpu(entry->e_id));120 break;121 122 default:123 goto fail;124 }125 }126 if (value != end)127 goto fail;128 return acl;129 130fail:131 posix_acl_release(acl);132 return ERR_PTR(-EINVAL);133}134 135/*136 * Convert from in-memory to filesystem representation.137 */138static void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * size)139{140 reiserfs_acl_header *ext_acl;141 char *e;142 int n;143 144 *size = reiserfs_acl_size(acl->a_count);145 ext_acl = kmalloc(sizeof(reiserfs_acl_header) +146 acl->a_count *147 sizeof(reiserfs_acl_entry),148 GFP_NOFS);149 if (!ext_acl)150 return ERR_PTR(-ENOMEM);151 ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION);152 e = (char *)ext_acl + sizeof(reiserfs_acl_header);153 for (n = 0; n < acl->a_count; n++) {154 const struct posix_acl_entry *acl_e = &acl->a_entries[n];155 reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e;156 entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag);157 entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);158 switch (acl->a_entries[n].e_tag) {159 case ACL_USER:160 entry->e_id = cpu_to_le32(161 from_kuid(&init_user_ns, acl_e->e_uid));162 e += sizeof(reiserfs_acl_entry);163 break;164 case ACL_GROUP:165 entry->e_id = cpu_to_le32(166 from_kgid(&init_user_ns, acl_e->e_gid));167 e += sizeof(reiserfs_acl_entry);168 break;169 170 case ACL_USER_OBJ:171 case ACL_GROUP_OBJ:172 case ACL_MASK:173 case ACL_OTHER:174 e += sizeof(reiserfs_acl_entry_short);175 break;176 177 default:178 goto fail;179 }180 }181 return (char *)ext_acl;182 183fail:184 kfree(ext_acl);185 return ERR_PTR(-EINVAL);186}187 188/*189 * Inode operation get_posix_acl().190 *191 * inode->i_mutex: down192 * BKL held [before 2.5.x]193 */194struct posix_acl *reiserfs_get_acl(struct inode *inode, int type, bool rcu)195{196 char *name, *value;197 struct posix_acl *acl;198 int size;199 int retval;200 201 if (rcu)202 return ERR_PTR(-ECHILD);203 204 switch (type) {205 case ACL_TYPE_ACCESS:206 name = XATTR_NAME_POSIX_ACL_ACCESS;207 break;208 case ACL_TYPE_DEFAULT:209 name = XATTR_NAME_POSIX_ACL_DEFAULT;210 break;211 default:212 BUG();213 }214 215 size = reiserfs_xattr_get(inode, name, NULL, 0);216 if (size < 0) {217 if (size == -ENODATA || size == -ENOSYS)218 return NULL;219 return ERR_PTR(size);220 }221 222 value = kmalloc(size, GFP_NOFS);223 if (!value)224 return ERR_PTR(-ENOMEM);225 226 retval = reiserfs_xattr_get(inode, name, value, size);227 if (retval == -ENODATA || retval == -ENOSYS) {228 /*229 * This shouldn't actually happen as it should have230 * been caught above.. but just in case231 */232 acl = NULL;233 } else if (retval < 0) {234 acl = ERR_PTR(retval);235 } else {236 acl = reiserfs_posix_acl_from_disk(value, retval);237 }238 239 kfree(value);240 return acl;241}242 243/*244 * Inode operation set_posix_acl().245 *246 * inode->i_mutex: down247 * BKL held [before 2.5.x]248 */249static int250__reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,251 int type, struct posix_acl *acl)252{253 char *name;254 void *value = NULL;255 size_t size = 0;256 int error;257 258 switch (type) {259 case ACL_TYPE_ACCESS:260 name = XATTR_NAME_POSIX_ACL_ACCESS;261 break;262 case ACL_TYPE_DEFAULT:263 name = XATTR_NAME_POSIX_ACL_DEFAULT;264 if (!S_ISDIR(inode->i_mode))265 return acl ? -EACCES : 0;266 break;267 default:268 return -EINVAL;269 }270 271 if (acl) {272 value = reiserfs_posix_acl_to_disk(acl, &size);273 if (IS_ERR(value))274 return (int)PTR_ERR(value);275 }276 277 error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);278 279 /*280 * Ensure that the inode gets dirtied if we're only using281 * the mode bits and an old ACL didn't exist. We don't need282 * to check if the inode is hashed here since we won't get283 * called by reiserfs_inherit_default_acl().284 */285 if (error == -ENODATA) {286 error = 0;287 if (type == ACL_TYPE_ACCESS) {288 inode_set_ctime_current(inode);289 mark_inode_dirty(inode);290 }291 }292 293 kfree(value);294 295 if (!error)296 set_cached_acl(inode, type, acl);297 298 return error;299}300 301/*302 * dir->i_mutex: locked,303 * inode is new and not released into the wild yet304 */305int306reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,307 struct inode *dir, struct dentry *dentry,308 struct inode *inode)309{310 struct posix_acl *default_acl, *acl;311 int err = 0;312 313 /* ACLs only get applied to files and directories */314 if (S_ISLNK(inode->i_mode))315 return 0;316 317 /*318 * ACLs can only be used on "new" objects, so if it's an old object319 * there is nothing to inherit from320 */321 if (get_inode_sd_version(dir) == STAT_DATA_V1)322 goto apply_umask;323 324 /*325 * Don't apply ACLs to objects in the .reiserfs_priv tree.. This326 * would be useless since permissions are ignored, and a pain because327 * it introduces locking cycles328 */329 if (IS_PRIVATE(inode))330 goto apply_umask;331 332 err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);333 if (err)334 return err;335 336 if (default_acl) {337 err = __reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,338 default_acl);339 posix_acl_release(default_acl);340 }341 if (acl) {342 if (!err)343 err = __reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS,344 acl);345 posix_acl_release(acl);346 }347 348 return err;349 350apply_umask:351 /* no ACL, apply umask */352 inode->i_mode &= ~current_umask();353 return err;354}355 356/* This is used to cache the default acl before a new object is created.357 * The biggest reason for this is to get an idea of how many blocks will358 * actually be required for the create operation if we must inherit an ACL.359 * An ACL write can add up to 3 object creations and an additional file write360 * so we'd prefer not to reserve that many blocks in the journal if we can.361 * It also has the advantage of not loading the ACL with a transaction open,362 * this may seem silly, but if the owner of the directory is doing the363 * creation, the ACL may not be loaded since the permissions wouldn't require364 * it.365 * We return the number of blocks required for the transaction.366 */367int reiserfs_cache_default_acl(struct inode *inode)368{369 struct posix_acl *acl;370 int nblocks = 0;371 372 if (IS_PRIVATE(inode))373 return 0;374 375 acl = get_inode_acl(inode, ACL_TYPE_DEFAULT);376 377 if (acl && !IS_ERR(acl)) {378 int size = reiserfs_acl_size(acl->a_count);379 380 /* Other xattrs can be created during inode creation. We don't381 * want to claim too many blocks, so we check to see if we382 * need to create the tree to the xattrs, and then we383 * just want two files. */384 nblocks = reiserfs_xattr_jcreate_nblocks(inode);385 nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);386 387 REISERFS_I(inode)->i_flags |= i_has_xattr_dir;388 389 /* We need to account for writes + bitmaps for two files */390 nblocks += reiserfs_xattr_nblocks(inode, size) * 4;391 posix_acl_release(acl);392 }393 394 return nblocks;395}396 397/*398 * Called under i_mutex399 */400int reiserfs_acl_chmod(struct dentry *dentry)401{402 struct inode *inode = d_inode(dentry);403 404 if (IS_PRIVATE(inode))405 return 0;406 if (get_inode_sd_version(inode) == STAT_DATA_V1 ||407 !reiserfs_posixacl(inode->i_sb))408 return 0;409 410 return posix_acl_chmod(&nop_mnt_idmap, dentry, inode->i_mode);411}412