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