xref: /OK3568_Linux_fs/kernel/fs/f2fs/acl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * fs/f2fs/acl.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
6*4882a593Smuzhiyun  *             http://www.samsung.com/
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Portions of this code from linux/fs/ext2/acl.c
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun #include <linux/f2fs_fs.h>
13*4882a593Smuzhiyun #include "f2fs.h"
14*4882a593Smuzhiyun #include "xattr.h"
15*4882a593Smuzhiyun #include "acl.h"
16*4882a593Smuzhiyun 
f2fs_acl_size(int count)17*4882a593Smuzhiyun static inline size_t f2fs_acl_size(int count)
18*4882a593Smuzhiyun {
19*4882a593Smuzhiyun 	if (count <= 4) {
20*4882a593Smuzhiyun 		return sizeof(struct f2fs_acl_header) +
21*4882a593Smuzhiyun 			count * sizeof(struct f2fs_acl_entry_short);
22*4882a593Smuzhiyun 	} else {
23*4882a593Smuzhiyun 		return sizeof(struct f2fs_acl_header) +
24*4882a593Smuzhiyun 			4 * sizeof(struct f2fs_acl_entry_short) +
25*4882a593Smuzhiyun 			(count - 4) * sizeof(struct f2fs_acl_entry);
26*4882a593Smuzhiyun 	}
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
f2fs_acl_count(size_t size)29*4882a593Smuzhiyun static inline int f2fs_acl_count(size_t size)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	ssize_t s;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	size -= sizeof(struct f2fs_acl_header);
34*4882a593Smuzhiyun 	s = size - 4 * sizeof(struct f2fs_acl_entry_short);
35*4882a593Smuzhiyun 	if (s < 0) {
36*4882a593Smuzhiyun 		if (size % sizeof(struct f2fs_acl_entry_short))
37*4882a593Smuzhiyun 			return -1;
38*4882a593Smuzhiyun 		return size / sizeof(struct f2fs_acl_entry_short);
39*4882a593Smuzhiyun 	} else {
40*4882a593Smuzhiyun 		if (s % sizeof(struct f2fs_acl_entry))
41*4882a593Smuzhiyun 			return -1;
42*4882a593Smuzhiyun 		return s / sizeof(struct f2fs_acl_entry) + 4;
43*4882a593Smuzhiyun 	}
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
f2fs_acl_from_disk(const char * value,size_t size)46*4882a593Smuzhiyun static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	int i, count;
49*4882a593Smuzhiyun 	struct posix_acl *acl;
50*4882a593Smuzhiyun 	struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
51*4882a593Smuzhiyun 	struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
52*4882a593Smuzhiyun 	const char *end = value + size;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	if (size < sizeof(struct f2fs_acl_header))
55*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION))
58*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	count = f2fs_acl_count(size);
61*4882a593Smuzhiyun 	if (count < 0)
62*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
63*4882a593Smuzhiyun 	if (count == 0)
64*4882a593Smuzhiyun 		return NULL;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	acl = posix_acl_alloc(count, GFP_NOFS);
67*4882a593Smuzhiyun 	if (!acl)
68*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 		if ((char *)entry > end)
73*4882a593Smuzhiyun 			goto fail;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 		acl->a_entries[i].e_tag  = le16_to_cpu(entry->e_tag);
76*4882a593Smuzhiyun 		acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm);
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 		switch (acl->a_entries[i].e_tag) {
79*4882a593Smuzhiyun 		case ACL_USER_OBJ:
80*4882a593Smuzhiyun 		case ACL_GROUP_OBJ:
81*4882a593Smuzhiyun 		case ACL_MASK:
82*4882a593Smuzhiyun 		case ACL_OTHER:
83*4882a593Smuzhiyun 			entry = (struct f2fs_acl_entry *)((char *)entry +
84*4882a593Smuzhiyun 					sizeof(struct f2fs_acl_entry_short));
85*4882a593Smuzhiyun 			break;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 		case ACL_USER:
88*4882a593Smuzhiyun 			acl->a_entries[i].e_uid =
89*4882a593Smuzhiyun 				make_kuid(&init_user_ns,
90*4882a593Smuzhiyun 						le32_to_cpu(entry->e_id));
91*4882a593Smuzhiyun 			entry = (struct f2fs_acl_entry *)((char *)entry +
92*4882a593Smuzhiyun 					sizeof(struct f2fs_acl_entry));
93*4882a593Smuzhiyun 			break;
94*4882a593Smuzhiyun 		case ACL_GROUP:
95*4882a593Smuzhiyun 			acl->a_entries[i].e_gid =
96*4882a593Smuzhiyun 				make_kgid(&init_user_ns,
97*4882a593Smuzhiyun 						le32_to_cpu(entry->e_id));
98*4882a593Smuzhiyun 			entry = (struct f2fs_acl_entry *)((char *)entry +
99*4882a593Smuzhiyun 					sizeof(struct f2fs_acl_entry));
100*4882a593Smuzhiyun 			break;
101*4882a593Smuzhiyun 		default:
102*4882a593Smuzhiyun 			goto fail;
103*4882a593Smuzhiyun 		}
104*4882a593Smuzhiyun 	}
105*4882a593Smuzhiyun 	if ((char *)entry != end)
106*4882a593Smuzhiyun 		goto fail;
107*4882a593Smuzhiyun 	return acl;
108*4882a593Smuzhiyun fail:
109*4882a593Smuzhiyun 	posix_acl_release(acl);
110*4882a593Smuzhiyun 	return ERR_PTR(-EINVAL);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
f2fs_acl_to_disk(struct f2fs_sb_info * sbi,const struct posix_acl * acl,size_t * size)113*4882a593Smuzhiyun static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi,
114*4882a593Smuzhiyun 				const struct posix_acl *acl, size_t *size)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	struct f2fs_acl_header *f2fs_acl;
117*4882a593Smuzhiyun 	struct f2fs_acl_entry *entry;
118*4882a593Smuzhiyun 	int i;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	f2fs_acl = f2fs_kmalloc(sbi, sizeof(struct f2fs_acl_header) +
121*4882a593Smuzhiyun 			acl->a_count * sizeof(struct f2fs_acl_entry),
122*4882a593Smuzhiyun 			GFP_NOFS);
123*4882a593Smuzhiyun 	if (!f2fs_acl)
124*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION);
127*4882a593Smuzhiyun 	entry = (struct f2fs_acl_entry *)(f2fs_acl + 1);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	for (i = 0; i < acl->a_count; i++) {
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 		entry->e_tag  = cpu_to_le16(acl->a_entries[i].e_tag);
132*4882a593Smuzhiyun 		entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm);
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 		switch (acl->a_entries[i].e_tag) {
135*4882a593Smuzhiyun 		case ACL_USER:
136*4882a593Smuzhiyun 			entry->e_id = cpu_to_le32(
137*4882a593Smuzhiyun 					from_kuid(&init_user_ns,
138*4882a593Smuzhiyun 						acl->a_entries[i].e_uid));
139*4882a593Smuzhiyun 			entry = (struct f2fs_acl_entry *)((char *)entry +
140*4882a593Smuzhiyun 					sizeof(struct f2fs_acl_entry));
141*4882a593Smuzhiyun 			break;
142*4882a593Smuzhiyun 		case ACL_GROUP:
143*4882a593Smuzhiyun 			entry->e_id = cpu_to_le32(
144*4882a593Smuzhiyun 					from_kgid(&init_user_ns,
145*4882a593Smuzhiyun 						acl->a_entries[i].e_gid));
146*4882a593Smuzhiyun 			entry = (struct f2fs_acl_entry *)((char *)entry +
147*4882a593Smuzhiyun 					sizeof(struct f2fs_acl_entry));
148*4882a593Smuzhiyun 			break;
149*4882a593Smuzhiyun 		case ACL_USER_OBJ:
150*4882a593Smuzhiyun 		case ACL_GROUP_OBJ:
151*4882a593Smuzhiyun 		case ACL_MASK:
152*4882a593Smuzhiyun 		case ACL_OTHER:
153*4882a593Smuzhiyun 			entry = (struct f2fs_acl_entry *)((char *)entry +
154*4882a593Smuzhiyun 					sizeof(struct f2fs_acl_entry_short));
155*4882a593Smuzhiyun 			break;
156*4882a593Smuzhiyun 		default:
157*4882a593Smuzhiyun 			goto fail;
158*4882a593Smuzhiyun 		}
159*4882a593Smuzhiyun 	}
160*4882a593Smuzhiyun 	*size = f2fs_acl_size(acl->a_count);
161*4882a593Smuzhiyun 	return (void *)f2fs_acl;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun fail:
164*4882a593Smuzhiyun 	kfree(f2fs_acl);
165*4882a593Smuzhiyun 	return ERR_PTR(-EINVAL);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
__f2fs_get_acl(struct inode * inode,int type,struct page * dpage)168*4882a593Smuzhiyun static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type,
169*4882a593Smuzhiyun 						struct page *dpage)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
172*4882a593Smuzhiyun 	void *value = NULL;
173*4882a593Smuzhiyun 	struct posix_acl *acl;
174*4882a593Smuzhiyun 	int retval;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	if (type == ACL_TYPE_ACCESS)
177*4882a593Smuzhiyun 		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	retval = f2fs_getxattr(inode, name_index, "", NULL, 0, dpage);
180*4882a593Smuzhiyun 	if (retval > 0) {
181*4882a593Smuzhiyun 		value = f2fs_kmalloc(F2FS_I_SB(inode), retval, GFP_F2FS_ZERO);
182*4882a593Smuzhiyun 		if (!value)
183*4882a593Smuzhiyun 			return ERR_PTR(-ENOMEM);
184*4882a593Smuzhiyun 		retval = f2fs_getxattr(inode, name_index, "", value,
185*4882a593Smuzhiyun 							retval, dpage);
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	if (retval > 0)
189*4882a593Smuzhiyun 		acl = f2fs_acl_from_disk(value, retval);
190*4882a593Smuzhiyun 	else if (retval == -ENODATA)
191*4882a593Smuzhiyun 		acl = NULL;
192*4882a593Smuzhiyun 	else
193*4882a593Smuzhiyun 		acl = ERR_PTR(retval);
194*4882a593Smuzhiyun 	kfree(value);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	return acl;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
f2fs_get_acl(struct inode * inode,int type)199*4882a593Smuzhiyun struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	return __f2fs_get_acl(inode, type, NULL);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
f2fs_acl_update_mode(struct inode * inode,umode_t * mode_p,struct posix_acl ** acl)204*4882a593Smuzhiyun static int f2fs_acl_update_mode(struct inode *inode, umode_t *mode_p,
205*4882a593Smuzhiyun 			  struct posix_acl **acl)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	umode_t mode = inode->i_mode;
208*4882a593Smuzhiyun 	int error;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	if (is_inode_flag_set(inode, FI_ACL_MODE))
211*4882a593Smuzhiyun 		mode = F2FS_I(inode)->i_acl_mode;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	error = posix_acl_equiv_mode(*acl, &mode);
214*4882a593Smuzhiyun 	if (error < 0)
215*4882a593Smuzhiyun 		return error;
216*4882a593Smuzhiyun 	if (error == 0)
217*4882a593Smuzhiyun 		*acl = NULL;
218*4882a593Smuzhiyun 	if (!in_group_p(inode->i_gid) &&
219*4882a593Smuzhiyun 	    !capable_wrt_inode_uidgid(inode, CAP_FSETID))
220*4882a593Smuzhiyun 		mode &= ~S_ISGID;
221*4882a593Smuzhiyun 	*mode_p = mode;
222*4882a593Smuzhiyun 	return 0;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
__f2fs_set_acl(struct inode * inode,int type,struct posix_acl * acl,struct page * ipage)225*4882a593Smuzhiyun static int __f2fs_set_acl(struct inode *inode, int type,
226*4882a593Smuzhiyun 			struct posix_acl *acl, struct page *ipage)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	int name_index;
229*4882a593Smuzhiyun 	void *value = NULL;
230*4882a593Smuzhiyun 	size_t size = 0;
231*4882a593Smuzhiyun 	int error;
232*4882a593Smuzhiyun 	umode_t mode = inode->i_mode;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	switch (type) {
235*4882a593Smuzhiyun 	case ACL_TYPE_ACCESS:
236*4882a593Smuzhiyun 		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
237*4882a593Smuzhiyun 		if (acl && !ipage) {
238*4882a593Smuzhiyun 			error = f2fs_acl_update_mode(inode, &mode, &acl);
239*4882a593Smuzhiyun 			if (error)
240*4882a593Smuzhiyun 				return error;
241*4882a593Smuzhiyun 			set_acl_inode(inode, mode);
242*4882a593Smuzhiyun 		}
243*4882a593Smuzhiyun 		break;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	case ACL_TYPE_DEFAULT:
246*4882a593Smuzhiyun 		name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
247*4882a593Smuzhiyun 		if (!S_ISDIR(inode->i_mode))
248*4882a593Smuzhiyun 			return acl ? -EACCES : 0;
249*4882a593Smuzhiyun 		break;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	default:
252*4882a593Smuzhiyun 		return -EINVAL;
253*4882a593Smuzhiyun 	}
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (acl) {
256*4882a593Smuzhiyun 		value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size);
257*4882a593Smuzhiyun 		if (IS_ERR(value)) {
258*4882a593Smuzhiyun 			clear_inode_flag(inode, FI_ACL_MODE);
259*4882a593Smuzhiyun 			return PTR_ERR(value);
260*4882a593Smuzhiyun 		}
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	error = f2fs_setxattr(inode, name_index, "", value, size, ipage, 0);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	kfree(value);
266*4882a593Smuzhiyun 	if (!error)
267*4882a593Smuzhiyun 		set_cached_acl(inode, type, acl);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	clear_inode_flag(inode, FI_ACL_MODE);
270*4882a593Smuzhiyun 	return error;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
f2fs_set_acl(struct inode * inode,struct posix_acl * acl,int type)273*4882a593Smuzhiyun int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
276*4882a593Smuzhiyun 		return -EIO;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	return __f2fs_set_acl(inode, type, acl, NULL);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun /*
282*4882a593Smuzhiyun  * Most part of f2fs_acl_clone, f2fs_acl_create_masq, f2fs_acl_create
283*4882a593Smuzhiyun  * are copied from posix_acl.c
284*4882a593Smuzhiyun  */
f2fs_acl_clone(const struct posix_acl * acl,gfp_t flags)285*4882a593Smuzhiyun static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl,
286*4882a593Smuzhiyun 							gfp_t flags)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	struct posix_acl *clone = NULL;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	if (acl) {
291*4882a593Smuzhiyun 		int size = sizeof(struct posix_acl) + acl->a_count *
292*4882a593Smuzhiyun 				sizeof(struct posix_acl_entry);
293*4882a593Smuzhiyun 		clone = kmemdup(acl, size, flags);
294*4882a593Smuzhiyun 		if (clone)
295*4882a593Smuzhiyun 			refcount_set(&clone->a_refcount, 1);
296*4882a593Smuzhiyun 	}
297*4882a593Smuzhiyun 	return clone;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
f2fs_acl_create_masq(struct posix_acl * acl,umode_t * mode_p)300*4882a593Smuzhiyun static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	struct posix_acl_entry *pa, *pe;
303*4882a593Smuzhiyun 	struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
304*4882a593Smuzhiyun 	umode_t mode = *mode_p;
305*4882a593Smuzhiyun 	int not_equiv = 0;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	/* assert(atomic_read(acl->a_refcount) == 1); */
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	FOREACH_ACL_ENTRY(pa, acl, pe) {
310*4882a593Smuzhiyun 		switch (pa->e_tag) {
311*4882a593Smuzhiyun 		case ACL_USER_OBJ:
312*4882a593Smuzhiyun 			pa->e_perm &= (mode >> 6) | ~S_IRWXO;
313*4882a593Smuzhiyun 			mode &= (pa->e_perm << 6) | ~S_IRWXU;
314*4882a593Smuzhiyun 			break;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 		case ACL_USER:
317*4882a593Smuzhiyun 		case ACL_GROUP:
318*4882a593Smuzhiyun 			not_equiv = 1;
319*4882a593Smuzhiyun 			break;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 		case ACL_GROUP_OBJ:
322*4882a593Smuzhiyun 			group_obj = pa;
323*4882a593Smuzhiyun 			break;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 		case ACL_OTHER:
326*4882a593Smuzhiyun 			pa->e_perm &= mode | ~S_IRWXO;
327*4882a593Smuzhiyun 			mode &= pa->e_perm | ~S_IRWXO;
328*4882a593Smuzhiyun 			break;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 		case ACL_MASK:
331*4882a593Smuzhiyun 			mask_obj = pa;
332*4882a593Smuzhiyun 			not_equiv = 1;
333*4882a593Smuzhiyun 			break;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 		default:
336*4882a593Smuzhiyun 			return -EIO;
337*4882a593Smuzhiyun 		}
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	if (mask_obj) {
341*4882a593Smuzhiyun 		mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
342*4882a593Smuzhiyun 		mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
343*4882a593Smuzhiyun 	} else {
344*4882a593Smuzhiyun 		if (!group_obj)
345*4882a593Smuzhiyun 			return -EIO;
346*4882a593Smuzhiyun 		group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
347*4882a593Smuzhiyun 		mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
348*4882a593Smuzhiyun 	}
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	*mode_p = (*mode_p & ~S_IRWXUGO) | mode;
351*4882a593Smuzhiyun 	return not_equiv;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
f2fs_acl_create(struct inode * dir,umode_t * mode,struct posix_acl ** default_acl,struct posix_acl ** acl,struct page * dpage)354*4882a593Smuzhiyun static int f2fs_acl_create(struct inode *dir, umode_t *mode,
355*4882a593Smuzhiyun 		struct posix_acl **default_acl, struct posix_acl **acl,
356*4882a593Smuzhiyun 		struct page *dpage)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	struct posix_acl *p;
359*4882a593Smuzhiyun 	struct posix_acl *clone;
360*4882a593Smuzhiyun 	int ret;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	*acl = NULL;
363*4882a593Smuzhiyun 	*default_acl = NULL;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	if (S_ISLNK(*mode) || !IS_POSIXACL(dir))
366*4882a593Smuzhiyun 		return 0;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	p = __f2fs_get_acl(dir, ACL_TYPE_DEFAULT, dpage);
369*4882a593Smuzhiyun 	if (!p || p == ERR_PTR(-EOPNOTSUPP)) {
370*4882a593Smuzhiyun 		*mode &= ~current_umask();
371*4882a593Smuzhiyun 		return 0;
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun 	if (IS_ERR(p))
374*4882a593Smuzhiyun 		return PTR_ERR(p);
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	clone = f2fs_acl_clone(p, GFP_NOFS);
377*4882a593Smuzhiyun 	if (!clone) {
378*4882a593Smuzhiyun 		ret = -ENOMEM;
379*4882a593Smuzhiyun 		goto release_acl;
380*4882a593Smuzhiyun 	}
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	ret = f2fs_acl_create_masq(clone, mode);
383*4882a593Smuzhiyun 	if (ret < 0)
384*4882a593Smuzhiyun 		goto release_clone;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	if (ret == 0)
387*4882a593Smuzhiyun 		posix_acl_release(clone);
388*4882a593Smuzhiyun 	else
389*4882a593Smuzhiyun 		*acl = clone;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	if (!S_ISDIR(*mode))
392*4882a593Smuzhiyun 		posix_acl_release(p);
393*4882a593Smuzhiyun 	else
394*4882a593Smuzhiyun 		*default_acl = p;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	return 0;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun release_clone:
399*4882a593Smuzhiyun 	posix_acl_release(clone);
400*4882a593Smuzhiyun release_acl:
401*4882a593Smuzhiyun 	posix_acl_release(p);
402*4882a593Smuzhiyun 	return ret;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
f2fs_init_acl(struct inode * inode,struct inode * dir,struct page * ipage,struct page * dpage)405*4882a593Smuzhiyun int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage,
406*4882a593Smuzhiyun 							struct page *dpage)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	struct posix_acl *default_acl = NULL, *acl = NULL;
409*4882a593Smuzhiyun 	int error;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	error = f2fs_acl_create(dir, &inode->i_mode, &default_acl, &acl, dpage);
412*4882a593Smuzhiyun 	if (error)
413*4882a593Smuzhiyun 		return error;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	f2fs_mark_inode_dirty_sync(inode, true);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	if (default_acl) {
418*4882a593Smuzhiyun 		error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl,
419*4882a593Smuzhiyun 				       ipage);
420*4882a593Smuzhiyun 		posix_acl_release(default_acl);
421*4882a593Smuzhiyun 	} else {
422*4882a593Smuzhiyun 		inode->i_default_acl = NULL;
423*4882a593Smuzhiyun 	}
424*4882a593Smuzhiyun 	if (acl) {
425*4882a593Smuzhiyun 		if (!error)
426*4882a593Smuzhiyun 			error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl,
427*4882a593Smuzhiyun 					       ipage);
428*4882a593Smuzhiyun 		posix_acl_release(acl);
429*4882a593Smuzhiyun 	} else {
430*4882a593Smuzhiyun 		inode->i_acl = NULL;
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	return error;
434*4882a593Smuzhiyun }
435