1 // SPDX-License-Identifier: GPL-2.0-only
2 /* -*- mode: c; c-basic-offset: 8; -*-
3 * vim: noexpandtab sw=8 ts=8 sts=0:
7 * Copyright (C) 2004, 2008 Oracle. All rights reserved.
10 * Lots of code in this file is copy from linux/fs/ext3/acl.c.
11 * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/slab.h>
17 #include <linux/string.h>
19 #include <cluster/masklog.h>
33 * Convert from xattr value to acl struct.
35 static struct posix_acl
*ocfs2_acl_from_xattr(const void *value
, size_t size
)
38 struct posix_acl
*acl
;
42 if (size
< sizeof(struct posix_acl_entry
))
43 return ERR_PTR(-EINVAL
);
45 count
= size
/ sizeof(struct posix_acl_entry
);
47 acl
= posix_acl_alloc(count
, GFP_NOFS
);
49 return ERR_PTR(-ENOMEM
);
50 for (n
= 0; n
< count
; n
++) {
51 struct ocfs2_acl_entry
*entry
=
52 (struct ocfs2_acl_entry
*)value
;
54 acl
->a_entries
[n
].e_tag
= le16_to_cpu(entry
->e_tag
);
55 acl
->a_entries
[n
].e_perm
= le16_to_cpu(entry
->e_perm
);
56 switch(acl
->a_entries
[n
].e_tag
) {
58 acl
->a_entries
[n
].e_uid
=
59 make_kuid(&init_user_ns
,
60 le32_to_cpu(entry
->e_id
));
63 acl
->a_entries
[n
].e_gid
=
64 make_kgid(&init_user_ns
,
65 le32_to_cpu(entry
->e_id
));
70 value
+= sizeof(struct posix_acl_entry
);
77 * Convert acl struct to xattr value.
79 static void *ocfs2_acl_to_xattr(const struct posix_acl
*acl
, size_t *size
)
81 struct ocfs2_acl_entry
*entry
= NULL
;
85 *size
= acl
->a_count
* sizeof(struct posix_acl_entry
);
87 ocfs2_acl
= kmalloc(*size
, GFP_NOFS
);
89 return ERR_PTR(-ENOMEM
);
91 entry
= (struct ocfs2_acl_entry
*)ocfs2_acl
;
92 for (n
= 0; n
< acl
->a_count
; n
++, entry
++) {
93 entry
->e_tag
= cpu_to_le16(acl
->a_entries
[n
].e_tag
);
94 entry
->e_perm
= cpu_to_le16(acl
->a_entries
[n
].e_perm
);
95 switch(acl
->a_entries
[n
].e_tag
) {
97 entry
->e_id
= cpu_to_le32(
98 from_kuid(&init_user_ns
,
99 acl
->a_entries
[n
].e_uid
));
102 entry
->e_id
= cpu_to_le32(
103 from_kgid(&init_user_ns
,
104 acl
->a_entries
[n
].e_gid
));
107 entry
->e_id
= cpu_to_le32(ACL_UNDEFINED_ID
);
114 static struct posix_acl
*ocfs2_get_acl_nolock(struct inode
*inode
,
116 struct buffer_head
*di_bh
)
120 struct posix_acl
*acl
;
124 case ACL_TYPE_ACCESS
:
125 name_index
= OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS
;
127 case ACL_TYPE_DEFAULT
:
128 name_index
= OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT
;
131 return ERR_PTR(-EINVAL
);
134 retval
= ocfs2_xattr_get_nolock(inode
, di_bh
, name_index
, "", NULL
, 0);
136 value
= kmalloc(retval
, GFP_NOFS
);
138 return ERR_PTR(-ENOMEM
);
139 retval
= ocfs2_xattr_get_nolock(inode
, di_bh
, name_index
,
144 acl
= ocfs2_acl_from_xattr(value
, retval
);
145 else if (retval
== -ENODATA
|| retval
== 0)
148 acl
= ERR_PTR(retval
);
156 * Helper function to set i_mode in memory and disk. Some call paths
157 * will not have di_bh or a journal handle to pass, in which case it
158 * will create it's own.
160 static int ocfs2_acl_set_mode(struct inode
*inode
, struct buffer_head
*di_bh
,
161 handle_t
*handle
, umode_t new_mode
)
163 int ret
, commit_handle
= 0;
164 struct ocfs2_dinode
*di
;
167 ret
= ocfs2_read_inode_block(inode
, &di_bh
);
175 if (handle
== NULL
) {
176 handle
= ocfs2_start_trans(OCFS2_SB(inode
->i_sb
),
177 OCFS2_INODE_UPDATE_CREDITS
);
178 if (IS_ERR(handle
)) {
179 ret
= PTR_ERR(handle
);
187 di
= (struct ocfs2_dinode
*)di_bh
->b_data
;
188 ret
= ocfs2_journal_access_di(handle
, INODE_CACHE(inode
), di_bh
,
189 OCFS2_JOURNAL_ACCESS_WRITE
);
195 inode
->i_mode
= new_mode
;
196 inode
->i_ctime
= current_time(inode
);
197 di
->i_mode
= cpu_to_le16(inode
->i_mode
);
198 di
->i_ctime
= cpu_to_le64(inode
->i_ctime
.tv_sec
);
199 di
->i_ctime_nsec
= cpu_to_le32(inode
->i_ctime
.tv_nsec
);
200 ocfs2_update_inode_fsync_trans(handle
, inode
, 0);
202 ocfs2_journal_dirty(handle
, di_bh
);
206 ocfs2_commit_trans(OCFS2_SB(inode
->i_sb
), handle
);
214 * Set the access or default ACL of an inode.
216 static int ocfs2_set_acl(handle_t
*handle
,
218 struct buffer_head
*di_bh
,
220 struct posix_acl
*acl
,
221 struct ocfs2_alloc_context
*meta_ac
,
222 struct ocfs2_alloc_context
*data_ac
)
229 if (S_ISLNK(inode
->i_mode
))
233 case ACL_TYPE_ACCESS
:
234 name_index
= OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS
;
236 case ACL_TYPE_DEFAULT
:
237 name_index
= OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT
;
238 if (!S_ISDIR(inode
->i_mode
))
239 return acl
? -EACCES
: 0;
246 value
= ocfs2_acl_to_xattr(acl
, &size
);
248 return (int)PTR_ERR(value
);
252 ret
= ocfs2_xattr_set_handle(handle
, inode
, di_bh
, name_index
,
256 ret
= ocfs2_xattr_set(inode
, name_index
, "", value
, size
, 0);
263 int ocfs2_iop_set_acl(struct inode
*inode
, struct posix_acl
*acl
, int type
)
265 struct buffer_head
*bh
= NULL
;
266 int status
, had_lock
;
267 struct ocfs2_lock_holder oh
;
269 had_lock
= ocfs2_inode_lock_tracker(inode
, &bh
, 1, &oh
);
272 if (type
== ACL_TYPE_ACCESS
&& acl
) {
275 status
= posix_acl_update_mode(inode
, &mode
, &acl
);
279 status
= ocfs2_acl_set_mode(inode
, bh
, NULL
, mode
);
283 status
= ocfs2_set_acl(NULL
, inode
, bh
, type
, acl
, NULL
, NULL
);
285 ocfs2_inode_unlock_tracker(inode
, 1, &oh
, had_lock
);
290 struct posix_acl
*ocfs2_iop_get_acl(struct inode
*inode
, int type
)
292 struct ocfs2_super
*osb
;
293 struct buffer_head
*di_bh
= NULL
;
294 struct posix_acl
*acl
;
296 struct ocfs2_lock_holder oh
;
298 osb
= OCFS2_SB(inode
->i_sb
);
299 if (!(osb
->s_mount_opt
& OCFS2_MOUNT_POSIX_ACL
))
302 had_lock
= ocfs2_inode_lock_tracker(inode
, &di_bh
, 0, &oh
);
304 return ERR_PTR(had_lock
);
306 down_read(&OCFS2_I(inode
)->ip_xattr_sem
);
307 acl
= ocfs2_get_acl_nolock(inode
, type
, di_bh
);
308 up_read(&OCFS2_I(inode
)->ip_xattr_sem
);
310 ocfs2_inode_unlock_tracker(inode
, 0, &oh
, had_lock
);
315 int ocfs2_acl_chmod(struct inode
*inode
, struct buffer_head
*bh
)
317 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
318 struct posix_acl
*acl
;
321 if (S_ISLNK(inode
->i_mode
))
324 if (!(osb
->s_mount_opt
& OCFS2_MOUNT_POSIX_ACL
))
327 down_read(&OCFS2_I(inode
)->ip_xattr_sem
);
328 acl
= ocfs2_get_acl_nolock(inode
, ACL_TYPE_ACCESS
, bh
);
329 up_read(&OCFS2_I(inode
)->ip_xattr_sem
);
330 if (IS_ERR_OR_NULL(acl
))
331 return PTR_ERR_OR_ZERO(acl
);
332 ret
= __posix_acl_chmod(&acl
, GFP_KERNEL
, inode
->i_mode
);
335 ret
= ocfs2_set_acl(NULL
, inode
, NULL
, ACL_TYPE_ACCESS
,
337 posix_acl_release(acl
);
342 * Initialize the ACLs of a new inode. If parent directory has default ACL,
343 * then clone to new inode. Called from ocfs2_mknod.
345 int ocfs2_init_acl(handle_t
*handle
,
348 struct buffer_head
*di_bh
,
349 struct buffer_head
*dir_bh
,
350 struct ocfs2_alloc_context
*meta_ac
,
351 struct ocfs2_alloc_context
*data_ac
)
353 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
354 struct posix_acl
*acl
= NULL
;
358 if (!S_ISLNK(inode
->i_mode
)) {
359 if (osb
->s_mount_opt
& OCFS2_MOUNT_POSIX_ACL
) {
360 down_read(&OCFS2_I(dir
)->ip_xattr_sem
);
361 acl
= ocfs2_get_acl_nolock(dir
, ACL_TYPE_DEFAULT
,
363 up_read(&OCFS2_I(dir
)->ip_xattr_sem
);
368 mode
= inode
->i_mode
& ~current_umask();
369 ret
= ocfs2_acl_set_mode(inode
, di_bh
, handle
, mode
);
376 if ((osb
->s_mount_opt
& OCFS2_MOUNT_POSIX_ACL
) && acl
) {
377 if (S_ISDIR(inode
->i_mode
)) {
378 ret
= ocfs2_set_acl(handle
, inode
, di_bh
,
379 ACL_TYPE_DEFAULT
, acl
,
384 mode
= inode
->i_mode
;
385 ret
= __posix_acl_create(&acl
, GFP_NOFS
, &mode
);
389 ret2
= ocfs2_acl_set_mode(inode
, di_bh
, handle
, mode
);
396 ret
= ocfs2_set_acl(handle
, inode
,
397 di_bh
, ACL_TYPE_ACCESS
,
398 acl
, meta_ac
, data_ac
);
402 posix_acl_release(acl
);