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)
  18{
  19        struct posix_acl *acl;
  20        char *ea_name;
  21        int size;
  22        char *value = NULL;
  23
  24        switch(type) {
  25                case ACL_TYPE_ACCESS:
  26                        ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
  27                        break;
  28                case ACL_TYPE_DEFAULT:
  29                        ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  30                        break;
  31                default:
  32                        return ERR_PTR(-EINVAL);
  33        }
  34
  35        size = __jfs_getxattr(inode, ea_name, NULL, 0);
  36
  37        if (size > 0) {
  38                value = kmalloc(size, GFP_KERNEL);
  39                if (!value)
  40                        return ERR_PTR(-ENOMEM);
  41                size = __jfs_getxattr(inode, ea_name, value, size);
  42        }
  43
  44        if (size < 0) {
  45                if (size == -ENODATA)
  46                        acl = NULL;
  47                else
  48                        acl = ERR_PTR(size);
  49        } else {
  50                acl = posix_acl_from_xattr(&init_user_ns, value, size);
  51        }
  52        kfree(value);
  53        return acl;
  54}
  55
  56static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
  57                       struct posix_acl *acl)
  58{
  59        char *ea_name;
  60        int rc;
  61        int size = 0;
  62        char *value = NULL;
  63
  64        switch (type) {
  65        case ACL_TYPE_ACCESS:
  66                ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
  67                break;
  68        case ACL_TYPE_DEFAULT:
  69                ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  70                break;
  71        default:
  72                return -EINVAL;
  73        }
  74
  75        if (acl) {
  76                size = posix_acl_xattr_size(acl->a_count);
  77                value = kmalloc(size, GFP_KERNEL);
  78                if (!value)
  79                        return -ENOMEM;
  80                rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
  81                if (rc < 0)
  82                        goto out;
  83        }
  84        rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
  85out:
  86        kfree(value);
  87
  88        if (!rc)
  89                set_cached_acl(inode, type, acl);
  90
  91        return rc;
  92}
  93
  94int jfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
  95                struct posix_acl *acl, int type)
  96{
  97        int rc;
  98        tid_t tid;
  99        int update_mode = 0;
 100        umode_t mode = inode->i_mode;
 101
 102        tid = txBegin(inode->i_sb, 0);
 103        mutex_lock(&JFS_IP(inode)->commit_mutex);
 104        if (type == ACL_TYPE_ACCESS && acl) {
 105                rc = posix_acl_update_mode(&init_user_ns, inode, &mode, &acl);
 106                if (rc)
 107                        goto end_tx;
 108                if (mode != inode->i_mode)
 109                        update_mode = 1;
 110        }
 111        rc = __jfs_set_acl(tid, inode, type, acl);
 112        if (!rc) {
 113                if (update_mode) {
 114                        inode->i_mode = mode;
 115                        inode->i_ctime = current_time(inode);
 116                        mark_inode_dirty(inode);
 117                }
 118                rc = txCommit(tid, 1, &inode, 0);
 119        }
 120end_tx:
 121        txEnd(tid);
 122        mutex_unlock(&JFS_IP(inode)->commit_mutex);
 123        return rc;
 124}
 125
 126int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 127{
 128        struct posix_acl *default_acl, *acl;
 129        int rc = 0;
 130
 131        rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
 132        if (rc)
 133                return rc;
 134
 135        if (default_acl) {
 136                rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
 137                posix_acl_release(default_acl);
 138        } else {
 139                inode->i_default_acl = NULL;
 140        }
 141
 142        if (acl) {
 143                if (!rc)
 144                        rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 145                posix_acl_release(acl);
 146        } else {
 147                inode->i_acl = NULL;
 148        }
 149
 150        JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
 151                               inode->i_mode;
 152
 153        return rc;
 154}
 155