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