116f7e0fe2ecc30f30652e8185e1772cdebe39109Randy Dunlap#include <linux/capability.h> 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/posix_acl.h> 4f466c6fdb3b1f043ff1977a8d2a1d0cd4dc164faAl Viro#include "reiserfs.h" 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pagemap.h> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/xattr.h> 85a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 99a59f452abe11f569e13ec16c51e6d61c54b9838Christoph Hellwig#include <linux/posix_acl_xattr.h> 10c45ac8887e778c4fa2b572c51a94a681a0955d4dAl Viro#include "xattr.h" 11a3063ab88fcbe5249f841cb95dfd626b8bf2674fAl Viro#include "acl.h" 1217093991af4995c4b93f6d8ac63aab68fcd9e1beFabian Frederick#include <linux/uaccess.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1447f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwigstatic int __reiserfs_set_acl(struct reiserfs_transaction_handle *th, 150ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney struct inode *inode, int type, 16bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct posix_acl *acl); 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1847f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig 1947f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwigint 2047f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwigreiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 220ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney int error, error2; 230ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney struct reiserfs_transaction_handle th; 240ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney size_t jcreate_blocks; 2547f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig int size = acl ? posix_acl_xattr_size(acl->a_count) : 0; 2647f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney /* 29098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * Pessimism: We can't assume that anything from the xattr root up 30098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * has been created. 31098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney */ 320ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney 330ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) + 340ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney reiserfs_xattr_nblocks(inode, size) * 2; 350ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney 360ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney reiserfs_write_lock(inode->i_sb); 370ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney error = journal_begin(&th, inode->i_sb, jcreate_blocks); 384c05141df57f4ffc1a9a28f1925434924179bfe4Jeff Mahoney reiserfs_write_unlock(inode->i_sb); 390ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney if (error == 0) { 4047f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig error = __reiserfs_set_acl(&th, inode, type, acl); 414c05141df57f4ffc1a9a28f1925434924179bfe4Jeff Mahoney reiserfs_write_lock(inode->i_sb); 4258d854265c4c7d9792ecb5aa5ef67ba79b1a4c12Jeff Mahoney error2 = journal_end(&th); 434c05141df57f4ffc1a9a28f1925434924179bfe4Jeff Mahoney reiserfs_write_unlock(inode->i_sb); 440ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney if (error2) 450ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney error = error2; 460ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney } 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert from filesystem to in-memory representation. 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 549dad943ae7d4a01da6bb18e1a157ab1bfe6186cdChristoph Hellwigstatic struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t size) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *end = (char *)value + size; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n, count; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct posix_acl *acl; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!value) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (size < sizeof(reiserfs_acl_header)) 63bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return ERR_PTR(-EINVAL); 64bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (((reiserfs_acl_header *) value)->a_version != 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_to_le32(REISERFS_ACL_VERSION)) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = (char *)value + sizeof(reiserfs_acl_header); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = reiserfs_acl_count(size); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count < 0) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = posix_acl_alloc(count, GFP_NOFS); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acl) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 76bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds for (n = 0; n < count; n++) { 77bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((char *)value + sizeof(reiserfs_acl_entry_short) > end) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 80bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 82bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds switch (acl->a_entries[n].e_tag) { 83bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_USER_OBJ: 84bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_GROUP_OBJ: 85bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_MASK: 86bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_OTHER: 87bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds value = (char *)value + 88bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds sizeof(reiserfs_acl_entry_short); 89bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 90bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 91bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_USER: 92df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman value = (char *)value + sizeof(reiserfs_acl_entry); 93df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman if ((char *)value > end) 94df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman goto fail; 95df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman acl->a_entries[n].e_uid = 96df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman make_kuid(&init_user_ns, 97df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman le32_to_cpu(entry->e_id)); 98df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman break; 99bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_GROUP: 100bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds value = (char *)value + sizeof(reiserfs_acl_entry); 101bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if ((char *)value > end) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 103df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman acl->a_entries[n].e_gid = 104df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman make_kgid(&init_user_ns, 105df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman le32_to_cpu(entry->e_id)); 106bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 107bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 108bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds default: 109bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto fail; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (value != end) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return acl; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 116cf776a7a4dafa330dd371a6a301ddf9e38747d93Jeff Mahoneyfail: 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds posix_acl_release(acl); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert from in-memory to filesystem representation. 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1249dad943ae7d4a01da6bb18e1a157ab1bfe6186cdChristoph Hellwigstatic void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * size) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reiserfs_acl_header *ext_acl; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *e; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *size = reiserfs_acl_size(acl->a_count); 1315cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day ext_acl = kmalloc(sizeof(reiserfs_acl_header) + 132bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl->a_count * 133bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds sizeof(reiserfs_acl_entry), 134bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds GFP_NOFS); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ext_acl) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds e = (char *)ext_acl + sizeof(reiserfs_acl_header); 139bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds for (n = 0; n < acl->a_count; n++) { 140df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman const struct posix_acl_entry *acl_e = &acl->a_entries[n]; 141bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e; 142bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 144bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds switch (acl->a_entries[n].e_tag) { 145bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_USER: 146df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman entry->e_id = cpu_to_le32( 147df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman from_kuid(&init_user_ns, acl_e->e_uid)); 148df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman e += sizeof(reiserfs_acl_entry); 149df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman break; 150bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_GROUP: 151df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman entry->e_id = cpu_to_le32( 152df814654f364369dfb2fe3c870f3544ce69aa78cEric W. Biederman from_kgid(&init_user_ns, acl_e->e_gid)); 153bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds e += sizeof(reiserfs_acl_entry); 154bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 155bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 156bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_USER_OBJ: 157bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_GROUP_OBJ: 158bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_MASK: 159bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_OTHER: 160bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds e += sizeof(reiserfs_acl_entry_short); 161bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 162bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 163bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds default: 164bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto fail; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (char *)ext_acl; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 169cf776a7a4dafa330dd371a6a301ddf9e38747d93Jeff Mahoneyfail: 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ext_acl); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EINVAL); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inode operation get_posix_acl(). 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1771b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen * inode->i_mutex: down 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BKL held [before 2.5.x] 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 180bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsstruct posix_acl *reiserfs_get_acl(struct inode *inode, int type) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *name, *value; 183073aaa1b142461d91f83da66db1184d7c1b1edeaAl Viro struct posix_acl *acl; 1843cdc409c169c9f2155151eea82cb9868e4d62788Adrian Bunk int size; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 186bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 187bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds switch (type) { 188bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_TYPE_ACCESS: 189bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds name = POSIX_ACL_XATTR_ACCESS; 190bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 191bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_TYPE_DEFAULT: 192bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds name = POSIX_ACL_XATTR_DEFAULT; 193bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 194bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds default: 195073aaa1b142461d91f83da66db1184d7c1b1edeaAl Viro BUG(); 196bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 197bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 198bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds size = reiserfs_xattr_get(inode, name, NULL, 0); 1993cdc409c169c9f2155151eea82cb9868e4d62788Adrian Bunk if (size < 0) { 200bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (size == -ENODATA || size == -ENOSYS) { 201073aaa1b142461d91f83da66db1184d7c1b1edeaAl Viro set_cached_acl(inode, type, NULL); 202bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return NULL; 203bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 204bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return ERR_PTR(size); 205bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 207bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds value = kmalloc(size, GFP_NOFS); 208bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!value) 209bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return ERR_PTR(-ENOMEM); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = reiserfs_xattr_get(inode, name, value, size); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval == -ENODATA || retval == -ENOSYS) { 213098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney /* 214098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * This shouldn't actually happen as it should have 215098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * been caught above.. but just in case 216098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney */ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = NULL; 218bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } else if (retval < 0) { 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acl = ERR_PTR(retval); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2219dad943ae7d4a01da6bb18e1a157ab1bfe6186cdChristoph Hellwig acl = reiserfs_posix_acl_from_disk(value, retval); 222bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 223073aaa1b142461d91f83da66db1184d7c1b1edeaAl Viro if (!IS_ERR(acl)) 224073aaa1b142461d91f83da66db1184d7c1b1edeaAl Viro set_cached_acl(inode, type, acl); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(value); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return acl; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inode operation set_posix_acl(). 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2331b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen * inode->i_mutex: down 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BKL held [before 2.5.x] 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 23747f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig__reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, 2380ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney int type, struct posix_acl *acl) 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 240bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds char *name; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *value = NULL; 24248b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney size_t size = 0; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 245bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds switch (type) { 246bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_TYPE_ACCESS: 247bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds name = POSIX_ACL_XATTR_ACCESS; 248bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (acl) { 249d6952123b53cc8b334df69bba2cd0063b0d88f68Al Viro error = posix_acl_equiv_mode(acl, &inode->i_mode); 250bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (error < 0) 251bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return error; 252bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds else { 253bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (error == 0) 254bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds acl = NULL; 255bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 256bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 257bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 258bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds case ACL_TYPE_DEFAULT: 259bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds name = POSIX_ACL_XATTR_DEFAULT; 260bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (!S_ISDIR(inode->i_mode)) 261bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return acl ? -EACCES : 0; 262bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds break; 263bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds default: 264bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return -EINVAL; 265bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 266bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 267bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (acl) { 2689dad943ae7d4a01da6bb18e1a157ab1bfe6186cdChristoph Hellwig value = reiserfs_posix_acl_to_disk(acl, &size); 269bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (IS_ERR(value)) 270bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return (int)PTR_ERR(value); 27148b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney } 27248b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney 2730ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0); 27448b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney 27548b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney /* 27648b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney * Ensure that the inode gets dirtied if we're only using 27748b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney * the mode bits and an old ACL didn't exist. We don't need 27848b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney * to check if the inode is hashed here since we won't get 27948b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney * called by reiserfs_inherit_default_acl(). 28048b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney */ 28148b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney if (error == -ENODATA) { 28248b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney error = 0; 28348b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney if (type == ACL_TYPE_ACCESS) { 28448b32a3553a54740d236b79a90f20147a25875e3Jeff Mahoney inode->i_ctime = CURRENT_TIME_SEC; 285bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds mark_inode_dirty(inode); 286bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 287bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289833d304b22edff5cc687ab7e5549c2f0dcdd951aJames Lamanna kfree(value); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291d984561b326cd0fe0d1183d11b9b4fa1d011d21dJeff Mahoney if (!error) 292073aaa1b142461d91f83da66db1184d7c1b1edeaAl Viro set_cached_acl(inode, type, acl); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 297098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney/* 298098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * dir->i_mutex: locked, 299098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * inode is new and not released into the wild yet 300098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney */ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 3020ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoneyreiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, 3030ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney struct inode *dir, struct dentry *dentry, 304bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds struct inode *inode) 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 30647f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig struct posix_acl *default_acl, *acl; 307bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds int err = 0; 308bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 309bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds /* ACLs only get applied to files and directories */ 310bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (S_ISLNK(inode->i_mode)) 311bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 312bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 313098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney /* 314098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * ACLs can only be used on "new" objects, so if it's an old object 315098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * there is nothing to inherit from 316098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney */ 317bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (get_inode_sd_version(dir) == STAT_DATA_V1) 318bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto apply_umask; 319bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 320098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney /* 321098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * Don't apply ACLs to objects in the .reiserfs_priv tree.. This 322bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds * would be useless since permissions are ignored, and a pain because 323098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney * it introduces locking cycles 324098297b27d23ad9d0fc302e3417474d9342c6c14Jeff Mahoney */ 3256dfede696391133eadd7ce90b61c9573ee6e5a90Jeff Mahoney if (IS_PRIVATE(dir)) { 3266dfede696391133eadd7ce90b61c9573ee6e5a90Jeff Mahoney inode->i_flags |= S_PRIVATE; 327bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds goto apply_umask; 328bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 329bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 33047f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); 33147f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig if (err) 33247f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig return err; 333bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 33447f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig if (default_acl) { 33547f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig err = __reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT, 33647f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig default_acl); 33747f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig posix_acl_release(default_acl); 33847f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig } 339bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (acl) { 34047f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig if (!err) 34147f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig err = __reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, 34247f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig acl); 343bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds posix_acl_release(acl); 344bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 345bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 346bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return err; 34747f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig 348cf776a7a4dafa330dd371a6a301ddf9e38747d93Jeff Mahoneyapply_umask: 34947f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig /* no ACL, apply umask */ 35047f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig inode->i_mode &= ~current_umask(); 35147f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig return err; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3540ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney/* This is used to cache the default acl before a new object is created. 3550ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * The biggest reason for this is to get an idea of how many blocks will 3560ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * actually be required for the create operation if we must inherit an ACL. 3570ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * An ACL write can add up to 3 object creations and an additional file write 3580ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * so we'd prefer not to reserve that many blocks in the journal if we can. 3590ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * It also has the advantage of not loading the ACL with a transaction open, 3600ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * this may seem silly, but if the owner of the directory is doing the 3610ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * creation, the ACL may not be loaded since the permissions wouldn't require 3620ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * it. 3630ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * We return the number of blocks required for the transaction. 3640ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney */ 365bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsint reiserfs_cache_default_acl(struct inode *inode) 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3670ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney struct posix_acl *acl; 3680ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney int nblocks = 0; 3690ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney 3700ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney if (IS_PRIVATE(inode)) 3710ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney return 0; 3720ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney 3730ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); 3740ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney 3750ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney if (acl && !IS_ERR(acl)) { 3760ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney int size = reiserfs_acl_size(acl->a_count); 3770ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney 3780ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney /* Other xattrs can be created during inode creation. We don't 3790ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * want to claim too many blocks, so we check to see if we 3800ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * we need to create the tree to the xattrs, and then we 3810ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney * just want two files. */ 3820ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney nblocks = reiserfs_xattr_jcreate_nblocks(inode); 3830ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb); 3840ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney 3850ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney REISERFS_I(inode)->i_flags |= i_has_xattr_dir; 3860ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney 3870ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney /* We need to account for writes + bitmaps for two files */ 3880ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney nblocks += reiserfs_xattr_nblocks(inode, size) * 4; 3890ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney posix_acl_release(acl); 390bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds } 391bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds 3920ab2621ebd9a28bf7a524ecd50d492a10579dfccJeff Mahoney return nblocks; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3954c05141df57f4ffc1a9a28f1925434924179bfe4Jeff Mahoney/* 3964c05141df57f4ffc1a9a28f1925434924179bfe4Jeff Mahoney * Called under i_mutex 3974c05141df57f4ffc1a9a28f1925434924179bfe4Jeff Mahoney */ 398bd4c625c061c2a38568d0add3478f59172455159Linus Torvaldsint reiserfs_acl_chmod(struct inode *inode) 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4004a8570112b76a63ad21cfcbe2783f98f7fd5ba1bJeff Mahoney if (IS_PRIVATE(inode)) 4014a8570112b76a63ad21cfcbe2783f98f7fd5ba1bJeff Mahoney return 0; 402bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds if (get_inode_sd_version(inode) == STAT_DATA_V1 || 40347f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig !reiserfs_posixacl(inode->i_sb)) 404bd4c625c061c2a38568d0add3478f59172455159Linus Torvalds return 0; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40647f70d08facf288a9faad6e6c36ac2e670be8195Christoph Hellwig return posix_acl_chmod(inode, inode->i_mode); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 408