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