1652ecc20SKaiGai Kohei /* 2652ecc20SKaiGai Kohei * JFFS2 -- Journalling Flash File System, Version 2. 3aa98d7cfSKaiGai Kohei * 4c00c310eSDavid Woodhouse * Copyright © 2006 NEC Corporation 5aa98d7cfSKaiGai Kohei * 6652ecc20SKaiGai Kohei * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 7652ecc20SKaiGai Kohei * 8652ecc20SKaiGai Kohei * For licensing information, see the file 'LICENCE' in this directory. 9652ecc20SKaiGai Kohei * 10652ecc20SKaiGai Kohei */ 11c00c310eSDavid Woodhouse 12aa98d7cfSKaiGai Kohei #include <linux/kernel.h> 13aa98d7cfSKaiGai Kohei #include <linux/slab.h> 14aa98d7cfSKaiGai Kohei #include <linux/fs.h> 15914e2637SAl Viro #include <linux/sched.h> 16aa98d7cfSKaiGai Kohei #include <linux/time.h> 17aa98d7cfSKaiGai Kohei #include <linux/crc32.h> 18aa98d7cfSKaiGai Kohei #include <linux/jffs2.h> 19aa98d7cfSKaiGai Kohei #include <linux/xattr.h> 20aa98d7cfSKaiGai Kohei #include <linux/posix_acl_xattr.h> 21aa98d7cfSKaiGai Kohei #include <linux/mtd/mtd.h> 22aa98d7cfSKaiGai Kohei #include "nodelist.h" 23aa98d7cfSKaiGai Kohei 24aa98d7cfSKaiGai Kohei static size_t jffs2_acl_size(int count) 25aa98d7cfSKaiGai Kohei { 26aa98d7cfSKaiGai Kohei if (count <= 4) { 27de1f72faSKaiGai Kohei return sizeof(struct jffs2_acl_header) 28de1f72faSKaiGai Kohei + count * sizeof(struct jffs2_acl_entry_short); 29aa98d7cfSKaiGai Kohei } else { 30de1f72faSKaiGai Kohei return sizeof(struct jffs2_acl_header) 31de1f72faSKaiGai Kohei + 4 * sizeof(struct jffs2_acl_entry_short) 32de1f72faSKaiGai Kohei + (count - 4) * sizeof(struct jffs2_acl_entry); 33aa98d7cfSKaiGai Kohei } 34aa98d7cfSKaiGai Kohei } 35aa98d7cfSKaiGai Kohei 36aa98d7cfSKaiGai Kohei static int jffs2_acl_count(size_t size) 37aa98d7cfSKaiGai Kohei { 38aa98d7cfSKaiGai Kohei size_t s; 39aa98d7cfSKaiGai Kohei 40de1f72faSKaiGai Kohei size -= sizeof(struct jffs2_acl_header); 41fc371a25SRoel Kluin if (size < 4 * sizeof(struct jffs2_acl_entry_short)) { 42de1f72faSKaiGai Kohei if (size % sizeof(struct jffs2_acl_entry_short)) 43aa98d7cfSKaiGai Kohei return -1; 44de1f72faSKaiGai Kohei return size / sizeof(struct jffs2_acl_entry_short); 45aa98d7cfSKaiGai Kohei } else { 46fc371a25SRoel Kluin s = size - 4 * sizeof(struct jffs2_acl_entry_short); 47de1f72faSKaiGai Kohei if (s % sizeof(struct jffs2_acl_entry)) 48aa98d7cfSKaiGai Kohei return -1; 49de1f72faSKaiGai Kohei return s / sizeof(struct jffs2_acl_entry) + 4; 50aa98d7cfSKaiGai Kohei } 51aa98d7cfSKaiGai Kohei } 52aa98d7cfSKaiGai Kohei 53dea80134SKaiGai Kohei static struct posix_acl *jffs2_acl_from_medium(void *value, size_t size) 54aa98d7cfSKaiGai Kohei { 55dea80134SKaiGai Kohei void *end = value + size; 56dea80134SKaiGai Kohei struct jffs2_acl_header *header = value; 57dea80134SKaiGai Kohei struct jffs2_acl_entry *entry; 58aa98d7cfSKaiGai Kohei struct posix_acl *acl; 59aa98d7cfSKaiGai Kohei uint32_t ver; 60aa98d7cfSKaiGai Kohei int i, count; 61aa98d7cfSKaiGai Kohei 62aa98d7cfSKaiGai Kohei if (!value) 63aa98d7cfSKaiGai Kohei return NULL; 64de1f72faSKaiGai Kohei if (size < sizeof(struct jffs2_acl_header)) 65aa98d7cfSKaiGai Kohei return ERR_PTR(-EINVAL); 66dea80134SKaiGai Kohei ver = je32_to_cpu(header->a_version); 67aa98d7cfSKaiGai Kohei if (ver != JFFS2_ACL_VERSION) { 68aa98d7cfSKaiGai Kohei JFFS2_WARNING("Invalid ACL version. (=%u)\n", ver); 69aa98d7cfSKaiGai Kohei return ERR_PTR(-EINVAL); 70aa98d7cfSKaiGai Kohei } 71aa98d7cfSKaiGai Kohei 72dea80134SKaiGai Kohei value += sizeof(struct jffs2_acl_header); 73aa98d7cfSKaiGai Kohei count = jffs2_acl_count(size); 74aa98d7cfSKaiGai Kohei if (count < 0) 75aa98d7cfSKaiGai Kohei return ERR_PTR(-EINVAL); 76aa98d7cfSKaiGai Kohei if (count == 0) 77aa98d7cfSKaiGai Kohei return NULL; 78aa98d7cfSKaiGai Kohei 79aa98d7cfSKaiGai Kohei acl = posix_acl_alloc(count, GFP_KERNEL); 80aa98d7cfSKaiGai Kohei if (!acl) 81aa98d7cfSKaiGai Kohei return ERR_PTR(-ENOMEM); 82aa98d7cfSKaiGai Kohei 83aa98d7cfSKaiGai Kohei for (i=0; i < count; i++) { 84dea80134SKaiGai Kohei entry = value; 85dea80134SKaiGai Kohei if (value + sizeof(struct jffs2_acl_entry_short) > end) 86aa98d7cfSKaiGai Kohei goto fail; 87aa98d7cfSKaiGai Kohei acl->a_entries[i].e_tag = je16_to_cpu(entry->e_tag); 88aa98d7cfSKaiGai Kohei acl->a_entries[i].e_perm = je16_to_cpu(entry->e_perm); 89aa98d7cfSKaiGai Kohei switch (acl->a_entries[i].e_tag) { 90aa98d7cfSKaiGai Kohei case ACL_USER_OBJ: 91aa98d7cfSKaiGai Kohei case ACL_GROUP_OBJ: 92aa98d7cfSKaiGai Kohei case ACL_MASK: 93aa98d7cfSKaiGai Kohei case ACL_OTHER: 94dea80134SKaiGai Kohei value += sizeof(struct jffs2_acl_entry_short); 95aa98d7cfSKaiGai Kohei acl->a_entries[i].e_id = ACL_UNDEFINED_ID; 96aa98d7cfSKaiGai Kohei break; 97aa98d7cfSKaiGai Kohei 98aa98d7cfSKaiGai Kohei case ACL_USER: 99aa98d7cfSKaiGai Kohei case ACL_GROUP: 100dea80134SKaiGai Kohei value += sizeof(struct jffs2_acl_entry); 101dea80134SKaiGai Kohei if (value > end) 102aa98d7cfSKaiGai Kohei goto fail; 103aa98d7cfSKaiGai Kohei acl->a_entries[i].e_id = je32_to_cpu(entry->e_id); 104aa98d7cfSKaiGai Kohei break; 105aa98d7cfSKaiGai Kohei 106aa98d7cfSKaiGai Kohei default: 107aa98d7cfSKaiGai Kohei goto fail; 108aa98d7cfSKaiGai Kohei } 109aa98d7cfSKaiGai Kohei } 110aa98d7cfSKaiGai Kohei if (value != end) 111aa98d7cfSKaiGai Kohei goto fail; 112aa98d7cfSKaiGai Kohei return acl; 113aa98d7cfSKaiGai Kohei fail: 114aa98d7cfSKaiGai Kohei posix_acl_release(acl); 115aa98d7cfSKaiGai Kohei return ERR_PTR(-EINVAL); 116aa98d7cfSKaiGai Kohei } 117aa98d7cfSKaiGai Kohei 118aa98d7cfSKaiGai Kohei static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size) 119aa98d7cfSKaiGai Kohei { 120dea80134SKaiGai Kohei struct jffs2_acl_header *header; 121dea80134SKaiGai Kohei struct jffs2_acl_entry *entry; 122dea80134SKaiGai Kohei void *e; 123aa98d7cfSKaiGai Kohei size_t i; 124aa98d7cfSKaiGai Kohei 125aa98d7cfSKaiGai Kohei *size = jffs2_acl_size(acl->a_count); 126dea80134SKaiGai Kohei header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL); 127dea80134SKaiGai Kohei if (!header) 128aa98d7cfSKaiGai Kohei return ERR_PTR(-ENOMEM); 129dea80134SKaiGai Kohei header->a_version = cpu_to_je32(JFFS2_ACL_VERSION); 130dea80134SKaiGai Kohei e = header + 1; 131aa98d7cfSKaiGai Kohei for (i=0; i < acl->a_count; i++) { 132dea80134SKaiGai Kohei entry = e; 133aa98d7cfSKaiGai Kohei entry->e_tag = cpu_to_je16(acl->a_entries[i].e_tag); 134aa98d7cfSKaiGai Kohei entry->e_perm = cpu_to_je16(acl->a_entries[i].e_perm); 135aa98d7cfSKaiGai Kohei switch(acl->a_entries[i].e_tag) { 136aa98d7cfSKaiGai Kohei case ACL_USER: 137aa98d7cfSKaiGai Kohei case ACL_GROUP: 138aa98d7cfSKaiGai Kohei entry->e_id = cpu_to_je32(acl->a_entries[i].e_id); 139de1f72faSKaiGai Kohei e += sizeof(struct jffs2_acl_entry); 140aa98d7cfSKaiGai Kohei break; 141aa98d7cfSKaiGai Kohei 142aa98d7cfSKaiGai Kohei case ACL_USER_OBJ: 143aa98d7cfSKaiGai Kohei case ACL_GROUP_OBJ: 144aa98d7cfSKaiGai Kohei case ACL_MASK: 145aa98d7cfSKaiGai Kohei case ACL_OTHER: 146de1f72faSKaiGai Kohei e += sizeof(struct jffs2_acl_entry_short); 147aa98d7cfSKaiGai Kohei break; 148aa98d7cfSKaiGai Kohei 149aa98d7cfSKaiGai Kohei default: 150aa98d7cfSKaiGai Kohei goto fail; 151aa98d7cfSKaiGai Kohei } 152aa98d7cfSKaiGai Kohei } 153dea80134SKaiGai Kohei return header; 154aa98d7cfSKaiGai Kohei fail: 155dea80134SKaiGai Kohei kfree(header); 156aa98d7cfSKaiGai Kohei return ERR_PTR(-EINVAL); 157aa98d7cfSKaiGai Kohei } 158aa98d7cfSKaiGai Kohei 159050416e9SAdrian Bunk static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) 160aa98d7cfSKaiGai Kohei { 161aa98d7cfSKaiGai Kohei struct posix_acl *acl; 162aa98d7cfSKaiGai Kohei char *value = NULL; 163aa98d7cfSKaiGai Kohei int rc, xprefix; 164aa98d7cfSKaiGai Kohei 165073aaa1bSAl Viro acl = get_cached_acl(inode, type); 166290c263bSAl Viro if (acl != ACL_NOT_CACHED) 167aa98d7cfSKaiGai Kohei return acl; 168073aaa1bSAl Viro 169073aaa1bSAl Viro switch (type) { 170073aaa1bSAl Viro case ACL_TYPE_ACCESS: 171aa98d7cfSKaiGai Kohei xprefix = JFFS2_XPREFIX_ACL_ACCESS; 172aa98d7cfSKaiGai Kohei break; 173aa98d7cfSKaiGai Kohei case ACL_TYPE_DEFAULT: 174aa98d7cfSKaiGai Kohei xprefix = JFFS2_XPREFIX_ACL_DEFAULT; 175aa98d7cfSKaiGai Kohei break; 176aa98d7cfSKaiGai Kohei default: 177073aaa1bSAl Viro BUG(); 178aa98d7cfSKaiGai Kohei } 179aa98d7cfSKaiGai Kohei rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0); 180aa98d7cfSKaiGai Kohei if (rc > 0) { 181aa98d7cfSKaiGai Kohei value = kmalloc(rc, GFP_KERNEL); 182aa98d7cfSKaiGai Kohei if (!value) 183aa98d7cfSKaiGai Kohei return ERR_PTR(-ENOMEM); 184aa98d7cfSKaiGai Kohei rc = do_jffs2_getxattr(inode, xprefix, "", value, rc); 185aa98d7cfSKaiGai Kohei } 186aa98d7cfSKaiGai Kohei if (rc > 0) { 187aa98d7cfSKaiGai Kohei acl = jffs2_acl_from_medium(value, rc); 188aa98d7cfSKaiGai Kohei } else if (rc == -ENODATA || rc == -ENOSYS) { 189aa98d7cfSKaiGai Kohei acl = NULL; 190aa98d7cfSKaiGai Kohei } else { 191aa98d7cfSKaiGai Kohei acl = ERR_PTR(rc); 192aa98d7cfSKaiGai Kohei } 193aa98d7cfSKaiGai Kohei if (value) 194aa98d7cfSKaiGai Kohei kfree(value); 195073aaa1bSAl Viro if (!IS_ERR(acl)) 196073aaa1bSAl Viro set_cached_acl(inode, type, acl); 197aa98d7cfSKaiGai Kohei return acl; 198aa98d7cfSKaiGai Kohei } 199aa98d7cfSKaiGai Kohei 200cfc8dc6fSKaiGai Kohei static int __jffs2_set_acl(struct inode *inode, int xprefix, struct posix_acl *acl) 201cfc8dc6fSKaiGai Kohei { 202cfc8dc6fSKaiGai Kohei char *value = NULL; 203cfc8dc6fSKaiGai Kohei size_t size = 0; 204cfc8dc6fSKaiGai Kohei int rc; 205cfc8dc6fSKaiGai Kohei 206cfc8dc6fSKaiGai Kohei if (acl) { 207cfc8dc6fSKaiGai Kohei value = jffs2_acl_to_medium(acl, &size); 208cfc8dc6fSKaiGai Kohei if (IS_ERR(value)) 209cfc8dc6fSKaiGai Kohei return PTR_ERR(value); 210cfc8dc6fSKaiGai Kohei } 211cfc8dc6fSKaiGai Kohei rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); 212cfc8dc6fSKaiGai Kohei if (!value && rc == -ENODATA) 213cfc8dc6fSKaiGai Kohei rc = 0; 214cfc8dc6fSKaiGai Kohei kfree(value); 215cfc8dc6fSKaiGai Kohei 216cfc8dc6fSKaiGai Kohei return rc; 217cfc8dc6fSKaiGai Kohei } 218cfc8dc6fSKaiGai Kohei 219aa98d7cfSKaiGai Kohei static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) 220aa98d7cfSKaiGai Kohei { 221aa98d7cfSKaiGai Kohei int rc, xprefix; 222aa98d7cfSKaiGai Kohei 223aa98d7cfSKaiGai Kohei if (S_ISLNK(inode->i_mode)) 224aa98d7cfSKaiGai Kohei return -EOPNOTSUPP; 225aa98d7cfSKaiGai Kohei 226aa98d7cfSKaiGai Kohei switch (type) { 227aa98d7cfSKaiGai Kohei case ACL_TYPE_ACCESS: 228aa98d7cfSKaiGai Kohei xprefix = JFFS2_XPREFIX_ACL_ACCESS; 229aa98d7cfSKaiGai Kohei if (acl) { 230aa98d7cfSKaiGai Kohei mode_t mode = inode->i_mode; 231aa98d7cfSKaiGai Kohei rc = posix_acl_equiv_mode(acl, &mode); 232aa98d7cfSKaiGai Kohei if (rc < 0) 233aa98d7cfSKaiGai Kohei return rc; 234aa98d7cfSKaiGai Kohei if (inode->i_mode != mode) { 2359ed437c5SDavid Woodhouse struct iattr attr; 2369ed437c5SDavid Woodhouse 2379ed437c5SDavid Woodhouse attr.ia_valid = ATTR_MODE; 2389ed437c5SDavid Woodhouse attr.ia_mode = mode; 2399ed437c5SDavid Woodhouse rc = jffs2_do_setattr(inode, &attr); 2409ed437c5SDavid Woodhouse if (rc < 0) 2419ed437c5SDavid Woodhouse return rc; 242aa98d7cfSKaiGai Kohei } 243aa98d7cfSKaiGai Kohei if (rc == 0) 244aa98d7cfSKaiGai Kohei acl = NULL; 245aa98d7cfSKaiGai Kohei } 246aa98d7cfSKaiGai Kohei break; 247aa98d7cfSKaiGai Kohei case ACL_TYPE_DEFAULT: 248aa98d7cfSKaiGai Kohei xprefix = JFFS2_XPREFIX_ACL_DEFAULT; 249aa98d7cfSKaiGai Kohei if (!S_ISDIR(inode->i_mode)) 250aa98d7cfSKaiGai Kohei return acl ? -EACCES : 0; 251aa98d7cfSKaiGai Kohei break; 252aa98d7cfSKaiGai Kohei default: 253aa98d7cfSKaiGai Kohei return -EINVAL; 254aa98d7cfSKaiGai Kohei } 255cfc8dc6fSKaiGai Kohei rc = __jffs2_set_acl(inode, xprefix, acl); 256073aaa1bSAl Viro if (!rc) 257073aaa1bSAl Viro set_cached_acl(inode, type, acl); 258aa98d7cfSKaiGai Kohei return rc; 259aa98d7cfSKaiGai Kohei } 260aa98d7cfSKaiGai Kohei 261aa98d7cfSKaiGai Kohei static int jffs2_check_acl(struct inode *inode, int mask) 262aa98d7cfSKaiGai Kohei { 263aa98d7cfSKaiGai Kohei struct posix_acl *acl; 264aa98d7cfSKaiGai Kohei int rc; 265aa98d7cfSKaiGai Kohei 266aa98d7cfSKaiGai Kohei acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS); 267aa98d7cfSKaiGai Kohei if (IS_ERR(acl)) 268aa98d7cfSKaiGai Kohei return PTR_ERR(acl); 269aa98d7cfSKaiGai Kohei if (acl) { 270aa98d7cfSKaiGai Kohei rc = posix_acl_permission(inode, acl, mask); 271aa98d7cfSKaiGai Kohei posix_acl_release(acl); 272aa98d7cfSKaiGai Kohei return rc; 273aa98d7cfSKaiGai Kohei } 274aa98d7cfSKaiGai Kohei return -EAGAIN; 275aa98d7cfSKaiGai Kohei } 276aa98d7cfSKaiGai Kohei 277e6305c43SAl Viro int jffs2_permission(struct inode *inode, int mask) 278aa98d7cfSKaiGai Kohei { 279aa98d7cfSKaiGai Kohei return generic_permission(inode, mask, jffs2_check_acl); 280aa98d7cfSKaiGai Kohei } 281aa98d7cfSKaiGai Kohei 282cfc8dc6fSKaiGai Kohei int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) 283aa98d7cfSKaiGai Kohei { 284cfc8dc6fSKaiGai Kohei struct posix_acl *acl, *clone; 285cfc8dc6fSKaiGai Kohei int rc; 286aa98d7cfSKaiGai Kohei 28772c04902SAl Viro cache_no_acl(inode); 2889ed437c5SDavid Woodhouse 289cfc8dc6fSKaiGai Kohei if (S_ISLNK(*i_mode)) 290cfc8dc6fSKaiGai Kohei return 0; /* Symlink always has no-ACL */ 291cfc8dc6fSKaiGai Kohei 292cfc8dc6fSKaiGai Kohei acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT); 293cfc8dc6fSKaiGai Kohei if (IS_ERR(acl)) 294cfc8dc6fSKaiGai Kohei return PTR_ERR(acl); 295cfc8dc6fSKaiGai Kohei 296cfc8dc6fSKaiGai Kohei if (!acl) { 297ce3b0f8dSAl Viro *i_mode &= ~current_umask(); 298cfc8dc6fSKaiGai Kohei } else { 299cfc8dc6fSKaiGai Kohei if (S_ISDIR(*i_mode)) 300073aaa1bSAl Viro set_cached_acl(inode, ACL_TYPE_DEFAULT, acl); 301cfc8dc6fSKaiGai Kohei 302aa98d7cfSKaiGai Kohei clone = posix_acl_clone(acl, GFP_KERNEL); 303aa98d7cfSKaiGai Kohei if (!clone) 304cfc8dc6fSKaiGai Kohei return -ENOMEM; 305cfc8dc6fSKaiGai Kohei rc = posix_acl_create_masq(clone, (mode_t *)i_mode); 30636f97bc6SJulia Lawall if (rc < 0) { 30736f97bc6SJulia Lawall posix_acl_release(clone); 308cfc8dc6fSKaiGai Kohei return rc; 30936f97bc6SJulia Lawall } 310aa98d7cfSKaiGai Kohei if (rc > 0) 311073aaa1bSAl Viro set_cached_acl(inode, ACL_TYPE_ACCESS, clone); 312cfc8dc6fSKaiGai Kohei 313aa98d7cfSKaiGai Kohei posix_acl_release(clone); 314aa98d7cfSKaiGai Kohei } 315cfc8dc6fSKaiGai Kohei return 0; 316cfc8dc6fSKaiGai Kohei } 317cfc8dc6fSKaiGai Kohei 318cfc8dc6fSKaiGai Kohei int jffs2_init_acl_post(struct inode *inode) 319cfc8dc6fSKaiGai Kohei { 320cfc8dc6fSKaiGai Kohei int rc; 321cfc8dc6fSKaiGai Kohei 322290c263bSAl Viro if (inode->i_default_acl) { 323290c263bSAl Viro rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, inode->i_default_acl); 324cfc8dc6fSKaiGai Kohei if (rc) 325cfc8dc6fSKaiGai Kohei return rc; 326cfc8dc6fSKaiGai Kohei } 327cfc8dc6fSKaiGai Kohei 328290c263bSAl Viro if (inode->i_acl) { 329290c263bSAl Viro rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, inode->i_acl); 330cfc8dc6fSKaiGai Kohei if (rc) 331cfc8dc6fSKaiGai Kohei return rc; 332cfc8dc6fSKaiGai Kohei } 333cfc8dc6fSKaiGai Kohei 3348d6ea587SDavid Woodhouse return 0; 335aa98d7cfSKaiGai Kohei } 336aa98d7cfSKaiGai Kohei 337aa98d7cfSKaiGai Kohei int jffs2_acl_chmod(struct inode *inode) 338aa98d7cfSKaiGai Kohei { 339aa98d7cfSKaiGai Kohei struct posix_acl *acl, *clone; 340aa98d7cfSKaiGai Kohei int rc; 341aa98d7cfSKaiGai Kohei 342aa98d7cfSKaiGai Kohei if (S_ISLNK(inode->i_mode)) 343aa98d7cfSKaiGai Kohei return -EOPNOTSUPP; 344aa98d7cfSKaiGai Kohei acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS); 345aa98d7cfSKaiGai Kohei if (IS_ERR(acl) || !acl) 346aa98d7cfSKaiGai Kohei return PTR_ERR(acl); 347aa98d7cfSKaiGai Kohei clone = posix_acl_clone(acl, GFP_KERNEL); 348aa98d7cfSKaiGai Kohei posix_acl_release(acl); 349aa98d7cfSKaiGai Kohei if (!clone) 350aa98d7cfSKaiGai Kohei return -ENOMEM; 351aa98d7cfSKaiGai Kohei rc = posix_acl_chmod_masq(clone, inode->i_mode); 352aa98d7cfSKaiGai Kohei if (!rc) 353aa98d7cfSKaiGai Kohei rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone); 354aa98d7cfSKaiGai Kohei posix_acl_release(clone); 355aa98d7cfSKaiGai Kohei return rc; 356aa98d7cfSKaiGai Kohei } 357aa98d7cfSKaiGai Kohei 358aa98d7cfSKaiGai Kohei static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size, 359aa98d7cfSKaiGai Kohei const char *name, size_t name_len) 360aa98d7cfSKaiGai Kohei { 361aa98d7cfSKaiGai Kohei const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS); 362aa98d7cfSKaiGai Kohei 363aa98d7cfSKaiGai Kohei if (list && retlen <= list_size) 364aa98d7cfSKaiGai Kohei strcpy(list, POSIX_ACL_XATTR_ACCESS); 365aa98d7cfSKaiGai Kohei return retlen; 366aa98d7cfSKaiGai Kohei } 367aa98d7cfSKaiGai Kohei 368aa98d7cfSKaiGai Kohei static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size, 369aa98d7cfSKaiGai Kohei const char *name, size_t name_len) 370aa98d7cfSKaiGai Kohei { 371aa98d7cfSKaiGai Kohei const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT); 372aa98d7cfSKaiGai Kohei 373aa98d7cfSKaiGai Kohei if (list && retlen <= list_size) 374aa98d7cfSKaiGai Kohei strcpy(list, POSIX_ACL_XATTR_DEFAULT); 375aa98d7cfSKaiGai Kohei return retlen; 376aa98d7cfSKaiGai Kohei } 377aa98d7cfSKaiGai Kohei 378aa98d7cfSKaiGai Kohei static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size) 379aa98d7cfSKaiGai Kohei { 380aa98d7cfSKaiGai Kohei struct posix_acl *acl; 381aa98d7cfSKaiGai Kohei int rc; 382aa98d7cfSKaiGai Kohei 383aa98d7cfSKaiGai Kohei acl = jffs2_get_acl(inode, type); 384aa98d7cfSKaiGai Kohei if (IS_ERR(acl)) 385aa98d7cfSKaiGai Kohei return PTR_ERR(acl); 386aa98d7cfSKaiGai Kohei if (!acl) 387aa98d7cfSKaiGai Kohei return -ENODATA; 388aa98d7cfSKaiGai Kohei rc = posix_acl_to_xattr(acl, buffer, size); 389aa98d7cfSKaiGai Kohei posix_acl_release(acl); 390aa98d7cfSKaiGai Kohei 391aa98d7cfSKaiGai Kohei return rc; 392aa98d7cfSKaiGai Kohei } 393aa98d7cfSKaiGai Kohei 394aa98d7cfSKaiGai Kohei static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size) 395aa98d7cfSKaiGai Kohei { 396aa98d7cfSKaiGai Kohei if (name[0] != '\0') 397aa98d7cfSKaiGai Kohei return -EINVAL; 398aa98d7cfSKaiGai Kohei return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size); 399aa98d7cfSKaiGai Kohei } 400aa98d7cfSKaiGai Kohei 401aa98d7cfSKaiGai Kohei static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size) 402aa98d7cfSKaiGai Kohei { 403aa98d7cfSKaiGai Kohei if (name[0] != '\0') 404aa98d7cfSKaiGai Kohei return -EINVAL; 405aa98d7cfSKaiGai Kohei return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size); 406aa98d7cfSKaiGai Kohei } 407aa98d7cfSKaiGai Kohei 408aa98d7cfSKaiGai Kohei static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size) 409aa98d7cfSKaiGai Kohei { 410aa98d7cfSKaiGai Kohei struct posix_acl *acl; 411aa98d7cfSKaiGai Kohei int rc; 412aa98d7cfSKaiGai Kohei 4133bd858abSSatyam Sharma if (!is_owner_or_cap(inode)) 414aa98d7cfSKaiGai Kohei return -EPERM; 415aa98d7cfSKaiGai Kohei 416aa98d7cfSKaiGai Kohei if (value) { 417aa98d7cfSKaiGai Kohei acl = posix_acl_from_xattr(value, size); 418aa98d7cfSKaiGai Kohei if (IS_ERR(acl)) 419aa98d7cfSKaiGai Kohei return PTR_ERR(acl); 420aa98d7cfSKaiGai Kohei if (acl) { 421aa98d7cfSKaiGai Kohei rc = posix_acl_valid(acl); 422aa98d7cfSKaiGai Kohei if (rc) 423aa98d7cfSKaiGai Kohei goto out; 424aa98d7cfSKaiGai Kohei } 425aa98d7cfSKaiGai Kohei } else { 426aa98d7cfSKaiGai Kohei acl = NULL; 427aa98d7cfSKaiGai Kohei } 428aa98d7cfSKaiGai Kohei rc = jffs2_set_acl(inode, type, acl); 429aa98d7cfSKaiGai Kohei out: 430aa98d7cfSKaiGai Kohei posix_acl_release(acl); 431aa98d7cfSKaiGai Kohei return rc; 432aa98d7cfSKaiGai Kohei } 433aa98d7cfSKaiGai Kohei 434aa98d7cfSKaiGai Kohei static int jffs2_acl_access_setxattr(struct inode *inode, const char *name, 435aa98d7cfSKaiGai Kohei const void *buffer, size_t size, int flags) 436aa98d7cfSKaiGai Kohei { 437aa98d7cfSKaiGai Kohei if (name[0] != '\0') 438aa98d7cfSKaiGai Kohei return -EINVAL; 439aa98d7cfSKaiGai Kohei return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size); 440aa98d7cfSKaiGai Kohei } 441aa98d7cfSKaiGai Kohei 442aa98d7cfSKaiGai Kohei static int jffs2_acl_default_setxattr(struct inode *inode, const char *name, 443aa98d7cfSKaiGai Kohei const void *buffer, size_t size, int flags) 444aa98d7cfSKaiGai Kohei { 445aa98d7cfSKaiGai Kohei if (name[0] != '\0') 446aa98d7cfSKaiGai Kohei return -EINVAL; 447aa98d7cfSKaiGai Kohei return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size); 448aa98d7cfSKaiGai Kohei } 449aa98d7cfSKaiGai Kohei 450aa98d7cfSKaiGai Kohei struct xattr_handler jffs2_acl_access_xattr_handler = { 451aa98d7cfSKaiGai Kohei .prefix = POSIX_ACL_XATTR_ACCESS, 452aa98d7cfSKaiGai Kohei .list = jffs2_acl_access_listxattr, 453aa98d7cfSKaiGai Kohei .get = jffs2_acl_access_getxattr, 454aa98d7cfSKaiGai Kohei .set = jffs2_acl_access_setxattr, 455aa98d7cfSKaiGai Kohei }; 456aa98d7cfSKaiGai Kohei 457aa98d7cfSKaiGai Kohei struct xattr_handler jffs2_acl_default_xattr_handler = { 458aa98d7cfSKaiGai Kohei .prefix = POSIX_ACL_XATTR_DEFAULT, 459aa98d7cfSKaiGai Kohei .list = jffs2_acl_default_listxattr, 460aa98d7cfSKaiGai Kohei .get = jffs2_acl_default_getxattr, 461aa98d7cfSKaiGai Kohei .set = jffs2_acl_default_setxattr, 462aa98d7cfSKaiGai Kohei }; 463