linux/fs/jfs/acl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *   Copyright (C) International Business Machines  Corp., 2002-2004
   4 *   Copyright (C) Andreas Gruenbacher, 2001
   5 *   Copyright (C) Linus Torvalds, 1991, 1992
   6 */
   7
   8#include <linux/sched.h>
   9#include <linux/slab.h>
  10#include <linux/fs.h>
  11#include <linux/posix_acl_xattr.h>
  12#include "jfs_incore.h"
  13#include "jfs_txnmgr.h"
  14#include "jfs_xattr.h"
  15#include "jfs_acl.h"
  16
  17struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu)
  18{
  19        struct posix_acl *acl;
  20        char *ea_name;
  21        int size;
  22        char *value = NULL;
  23
  24        if (rcu)
  25                return ERR_PTR(-ECHILD);
  26
  27        switch(type) {
  28                case ACL_TYPE_ACCESS:
  29                        ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
  30                        break;
  31                case ACL_TYPE_DEFAULT:
  32                        ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  33                        break;
  34                default:
  35                        return ERR_PTR(-EINVAL);
  36        }
  37
  38        size = __jfs_getxattr(inode, ea_name, NULL, 0);
  39
  40        if (size > 0) {
  41                value = kmalloc(size, GFP_KERNEL);
  42                if (!value)
  43                        return ERR_PTR(-ENOMEM);
  44                size = __jfs_getxattr(inode, ea_name, value, size);
  45        }
  46
  47        if (size < 0) {
  48                if (size == -ENODATA)
  49                        acl = NULL;
  50                else
  51                        acl = ERR_PTR(size);
  52        } else {
  53                acl = posix_acl_from_xattr(&init_user_ns, value, size);
  54        }
  55        kfree(value);
  56        return acl;
  57}
  58
  59static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
  60                       struct posix_acl *acl)
  61{
  62        char *ea_name;
  63        int rc;
  64        int size = 0;
  65        char *value = NULL;
  66
  67        switch (type) {
  68        case ACL_TYPE_ACCESS:
  69                ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
  70                break;
  71        case ACL_TYPE_DEFAULT:
  72                ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  73                break;
  74        default:
  75                return -EINVAL;
  76        }
  77
  78        if (acl) {
  79                size = posix_acl_xattr_size(acl->a_count);
  80                value = kmalloc(size, GFP_KERNEL);
  81                if (!value)
  82                        return -ENOMEM;
  83                rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
  84                if (rc < 0)
  85                        goto out;
  86        }
  87        rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
  88out:
  89        kfree(value);
  90
  91        if (!rc)
  92                set_cached_acl(inode, type, acl);
  93
  94        return rc;
  95}
  96
  97int jfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
  98                struct posix_acl *acl, int type)
  99{
 100        int rc;
 101        tid_t tid;
 102        int update_mode = 0;
 103        umode_t mode = inode->i_mode;
 104
 105        tid = txBegin(inode->i_sb, 0);
 106        mutex_lock(&JFS_IP(inode)->commit_mutex);
 107        if (type == ACL_TYPE_ACCESS && acl) {
 108                rc = posix_acl_update_mode(&init_user_ns, inode, &mode, &acl);
 109                if (rc)
 110                        goto end_tx;
 111                if (mode != inode->i_mode)
 112                        update_mode = 1;
 113        }
 114        rc = __jfs_set_acl(tid, inode, type, acl);
 115        if (!rc) {
 116                if (update_mode) {
 117                        inode->i_mode = mode;
 118                        inode->i_ctime = current_time(inode);
 119                        mark_inode_dirty(inode);
 120                }
 121                rc = txCommit(tid, 1, &inode, 0);
 122        }
 123end_tx:
 124        txEnd(tid);
 125        mutex_unlock(&JFS_IP(inode)->commit_mutex);
 126        return rc;
 127}
 128
 129int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 130{
 131        struct posix_acl *default_acl, *acl;
 132        int rc = 0;
 133
 134        rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
 135        if (rc)
 136                return rc;
 137
 138        if (default_acl) {
 139                rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
 140                posix_acl_release(default_acl);
 141        } else {
 142                inode->i_default_acl = NULL;
 143        }
 144
 145        if (acl) {
 146                if (!rc)
 147                        rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 148                posix_acl_release(acl);
 149        } else {
 150                inode->i_acl = NULL;
 151        }
 152
 153        JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
 154                               inode->i_mode;
 155
 156        return rc;
 157}
 158