Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   Copyright (C) International Business Machines  Corp., 2002-2004
0004  *   Copyright (C) Andreas Gruenbacher, 2001
0005  *   Copyright (C) Linus Torvalds, 1991, 1992
0006  */
0007 
0008 #include <linux/sched.h>
0009 #include <linux/slab.h>
0010 #include <linux/fs.h>
0011 #include <linux/posix_acl_xattr.h>
0012 #include "jfs_incore.h"
0013 #include "jfs_txnmgr.h"
0014 #include "jfs_xattr.h"
0015 #include "jfs_acl.h"
0016 
0017 struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu)
0018 {
0019     struct posix_acl *acl;
0020     char *ea_name;
0021     int size;
0022     char *value = NULL;
0023 
0024     if (rcu)
0025         return ERR_PTR(-ECHILD);
0026 
0027     switch(type) {
0028         case ACL_TYPE_ACCESS:
0029             ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
0030             break;
0031         case ACL_TYPE_DEFAULT:
0032             ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
0033             break;
0034         default:
0035             return ERR_PTR(-EINVAL);
0036     }
0037 
0038     size = __jfs_getxattr(inode, ea_name, NULL, 0);
0039 
0040     if (size > 0) {
0041         value = kmalloc(size, GFP_KERNEL);
0042         if (!value)
0043             return ERR_PTR(-ENOMEM);
0044         size = __jfs_getxattr(inode, ea_name, value, size);
0045     }
0046 
0047     if (size < 0) {
0048         if (size == -ENODATA)
0049             acl = NULL;
0050         else
0051             acl = ERR_PTR(size);
0052     } else {
0053         acl = posix_acl_from_xattr(&init_user_ns, value, size);
0054     }
0055     kfree(value);
0056     return acl;
0057 }
0058 
0059 static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
0060                struct posix_acl *acl)
0061 {
0062     char *ea_name;
0063     int rc;
0064     int size = 0;
0065     char *value = NULL;
0066 
0067     switch (type) {
0068     case ACL_TYPE_ACCESS:
0069         ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
0070         break;
0071     case ACL_TYPE_DEFAULT:
0072         ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
0073         break;
0074     default:
0075         return -EINVAL;
0076     }
0077 
0078     if (acl) {
0079         size = posix_acl_xattr_size(acl->a_count);
0080         value = kmalloc(size, GFP_KERNEL);
0081         if (!value)
0082             return -ENOMEM;
0083         rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
0084         if (rc < 0)
0085             goto out;
0086     }
0087     rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
0088 out:
0089     kfree(value);
0090 
0091     if (!rc)
0092         set_cached_acl(inode, type, acl);
0093 
0094     return rc;
0095 }
0096 
0097 int jfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
0098         struct posix_acl *acl, int type)
0099 {
0100     int rc;
0101     tid_t tid;
0102     int update_mode = 0;
0103     umode_t mode = inode->i_mode;
0104 
0105     tid = txBegin(inode->i_sb, 0);
0106     mutex_lock(&JFS_IP(inode)->commit_mutex);
0107     if (type == ACL_TYPE_ACCESS && acl) {
0108         rc = posix_acl_update_mode(&init_user_ns, inode, &mode, &acl);
0109         if (rc)
0110             goto end_tx;
0111         if (mode != inode->i_mode)
0112             update_mode = 1;
0113     }
0114     rc = __jfs_set_acl(tid, inode, type, acl);
0115     if (!rc) {
0116         if (update_mode) {
0117             inode->i_mode = mode;
0118             inode->i_ctime = current_time(inode);
0119             mark_inode_dirty(inode);
0120         }
0121         rc = txCommit(tid, 1, &inode, 0);
0122     }
0123 end_tx:
0124     txEnd(tid);
0125     mutex_unlock(&JFS_IP(inode)->commit_mutex);
0126     return rc;
0127 }
0128 
0129 int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
0130 {
0131     struct posix_acl *default_acl, *acl;
0132     int rc = 0;
0133 
0134     rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
0135     if (rc)
0136         return rc;
0137 
0138     if (default_acl) {
0139         rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
0140         posix_acl_release(default_acl);
0141     } else {
0142         inode->i_default_acl = NULL;
0143     }
0144 
0145     if (acl) {
0146         if (!rc)
0147             rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
0148         posix_acl_release(acl);
0149     } else {
0150         inode->i_acl = NULL;
0151     }
0152 
0153     JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
0154                    inode->i_mode;
0155 
0156     return rc;
0157 }