xref: /OK3568_Linux_fs/kernel/fs/jfs/acl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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