1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 25db11c21SMike Marshall /* 35db11c21SMike Marshall * (C) 2001 Clemson University and The University of Chicago 45db11c21SMike Marshall * 55db11c21SMike Marshall * See COPYING in top-level directory. 65db11c21SMike Marshall */ 75db11c21SMike Marshall 85db11c21SMike Marshall #include "protocol.h" 9575e9461SMike Marshall #include "orangefs-kernel.h" 10575e9461SMike Marshall #include "orangefs-bufmap.h" 115db11c21SMike Marshall #include <linux/posix_acl_xattr.h> 125db11c21SMike Marshall 130cad6246SMiklos Szeredi struct posix_acl *orangefs_get_acl(struct inode *inode, int type, bool rcu) 145db11c21SMike Marshall { 155db11c21SMike Marshall struct posix_acl *acl; 165db11c21SMike Marshall int ret; 175db11c21SMike Marshall char *key = NULL, *value = NULL; 185db11c21SMike Marshall 190cad6246SMiklos Szeredi if (rcu) 200cad6246SMiklos Szeredi return ERR_PTR(-ECHILD); 210cad6246SMiklos Szeredi 225db11c21SMike Marshall switch (type) { 235db11c21SMike Marshall case ACL_TYPE_ACCESS: 24972a7344SAndreas Gruenbacher key = XATTR_NAME_POSIX_ACL_ACCESS; 255db11c21SMike Marshall break; 265db11c21SMike Marshall case ACL_TYPE_DEFAULT: 27972a7344SAndreas Gruenbacher key = XATTR_NAME_POSIX_ACL_DEFAULT; 285db11c21SMike Marshall break; 295db11c21SMike Marshall default: 308bb8aefdSYi Liu gossip_err("orangefs_get_acl: bogus value of type %d\n", type); 315db11c21SMike Marshall return ERR_PTR(-EINVAL); 325db11c21SMike Marshall } 335db11c21SMike Marshall /* 345db11c21SMike Marshall * Rather than incurring a network call just to determine the exact 355db11c21SMike Marshall * length of the attribute, I just allocate a max length to save on 365db11c21SMike Marshall * the network call. Conceivably, we could pass NULL to 378bb8aefdSYi Liu * orangefs_inode_getxattr() to probe the length of the value, but 385db11c21SMike Marshall * I don't do that for now. 395db11c21SMike Marshall */ 408bb8aefdSYi Liu value = kmalloc(ORANGEFS_MAX_XATTR_VALUELEN, GFP_KERNEL); 410b08273cSMarkus Elfring if (!value) 425db11c21SMike Marshall return ERR_PTR(-ENOMEM); 435db11c21SMike Marshall 445db11c21SMike Marshall gossip_debug(GOSSIP_ACL_DEBUG, 455db11c21SMike Marshall "inode %pU, key %s, type %d\n", 465db11c21SMike Marshall get_khandle_from_ino(inode), 475db11c21SMike Marshall key, 485db11c21SMike Marshall type); 49d373a712SAndreas Gruenbacher ret = orangefs_inode_getxattr(inode, key, value, 508bb8aefdSYi Liu ORANGEFS_MAX_XATTR_VALUELEN); 515db11c21SMike Marshall /* if the key exists, convert it to an in-memory rep */ 525db11c21SMike Marshall if (ret > 0) { 535db11c21SMike Marshall acl = posix_acl_from_xattr(&init_user_ns, value, ret); 545db11c21SMike Marshall } else if (ret == -ENODATA || ret == -ENOSYS) { 555db11c21SMike Marshall acl = NULL; 565db11c21SMike Marshall } else { 575db11c21SMike Marshall gossip_err("inode %pU retrieving acl's failed with error %d\n", 585db11c21SMike Marshall get_khandle_from_ino(inode), 595db11c21SMike Marshall ret); 605db11c21SMike Marshall acl = ERR_PTR(ret); 615db11c21SMike Marshall } 625db11c21SMike Marshall /* kfree(NULL) is safe, so don't worry if value ever got used */ 635db11c21SMike Marshall kfree(value); 645db11c21SMike Marshall return acl; 655db11c21SMike Marshall } 665db11c21SMike Marshall 674053d250SChristian Brauner int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 685db11c21SMike Marshall { 695db11c21SMike Marshall int error = 0; 705db11c21SMike Marshall void *value = NULL; 715db11c21SMike Marshall size_t size = 0; 725db11c21SMike Marshall const char *name = NULL; 735db11c21SMike Marshall 745db11c21SMike Marshall switch (type) { 755db11c21SMike Marshall case ACL_TYPE_ACCESS: 76972a7344SAndreas Gruenbacher name = XATTR_NAME_POSIX_ACL_ACCESS; 775db11c21SMike Marshall break; 785db11c21SMike Marshall case ACL_TYPE_DEFAULT: 79972a7344SAndreas Gruenbacher name = XATTR_NAME_POSIX_ACL_DEFAULT; 805db11c21SMike Marshall break; 815db11c21SMike Marshall default: 825db11c21SMike Marshall gossip_err("%s: invalid type %d!\n", __func__, type); 835db11c21SMike Marshall return -EINVAL; 845db11c21SMike Marshall } 855db11c21SMike Marshall 865db11c21SMike Marshall gossip_debug(GOSSIP_ACL_DEBUG, 875db11c21SMike Marshall "%s: inode %pU, key %s type %d\n", 885db11c21SMike Marshall __func__, get_khandle_from_ino(inode), 895db11c21SMike Marshall name, 905db11c21SMike Marshall type); 915db11c21SMike Marshall 925db11c21SMike Marshall if (acl) { 935db11c21SMike Marshall size = posix_acl_xattr_size(acl->a_count); 945db11c21SMike Marshall value = kmalloc(size, GFP_KERNEL); 955db11c21SMike Marshall if (!value) 965db11c21SMike Marshall return -ENOMEM; 975db11c21SMike Marshall 985db11c21SMike Marshall error = posix_acl_to_xattr(&init_user_ns, acl, value, size); 995db11c21SMike Marshall if (error < 0) 1005db11c21SMike Marshall goto out; 1015db11c21SMike Marshall } 1025db11c21SMike Marshall 1035db11c21SMike Marshall gossip_debug(GOSSIP_ACL_DEBUG, 1045db11c21SMike Marshall "%s: name %s, value %p, size %zd, acl %p\n", 1055db11c21SMike Marshall __func__, name, value, size, acl); 1065db11c21SMike Marshall /* 1075db11c21SMike Marshall * Go ahead and set the extended attribute now. NOTE: Suppose acl 1085db11c21SMike Marshall * was NULL, then value will be NULL and size will be 0 and that 1095db11c21SMike Marshall * will xlate to a removexattr. However, we don't want removexattr 1105db11c21SMike Marshall * complain if attributes does not exist. 1115db11c21SMike Marshall */ 112d373a712SAndreas Gruenbacher error = orangefs_inode_setxattr(inode, name, value, size, 0); 1135db11c21SMike Marshall 1145db11c21SMike Marshall out: 1155db11c21SMike Marshall kfree(value); 1165db11c21SMike Marshall if (!error) 1175db11c21SMike Marshall set_cached_acl(inode, type, acl); 1185db11c21SMike Marshall return error; 1195db11c21SMike Marshall } 1205db11c21SMike Marshall 12113e83a49SChristian Brauner int orangefs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, 122549c7297SChristian Brauner struct posix_acl *acl, int type) 123b5accbb0SJan Kara { 124b5accbb0SJan Kara int error; 1254bef6900SMike Marshall struct iattr iattr; 1264bef6900SMike Marshall int rc; 127138060baSChristian Brauner struct inode *inode = d_inode(dentry); 128b5accbb0SJan Kara 129476af919SMike Marshall memset(&iattr, 0, sizeof iattr); 130476af919SMike Marshall 131b5accbb0SJan Kara if (type == ACL_TYPE_ACCESS && acl) { 1324bef6900SMike Marshall /* 1334bef6900SMike Marshall * posix_acl_update_mode checks to see if the permissions 1344bef6900SMike Marshall * described by the ACL can be encoded into the 1354bef6900SMike Marshall * object's mode. If so, it sets "acl" to NULL 1364bef6900SMike Marshall * and "mode" to the new desired value. It is up to 1374bef6900SMike Marshall * us to propagate the new mode back to the server... 1384bef6900SMike Marshall */ 139*700b7940SChristian Brauner error = posix_acl_update_mode(&nop_mnt_idmap, inode, 140e65ce2a5SChristian Brauner &iattr.ia_mode, &acl); 141b5accbb0SJan Kara if (error) { 142b5accbb0SJan Kara gossip_err("%s: posix_acl_update_mode err: %d\n", 143b5accbb0SJan Kara __func__, 144b5accbb0SJan Kara error); 145b5accbb0SJan Kara return error; 146b5accbb0SJan Kara } 147b5accbb0SJan Kara 148476af919SMike Marshall if (inode->i_mode != iattr.ia_mode) 1494bef6900SMike Marshall iattr.ia_valid = ATTR_MODE; 150476af919SMike Marshall 151b5accbb0SJan Kara } 1524bef6900SMike Marshall 153476af919SMike Marshall rc = __orangefs_set_acl(inode, acl, type); 154476af919SMike Marshall 155476af919SMike Marshall if (!rc && (iattr.ia_valid == ATTR_MODE)) 156138060baSChristian Brauner rc = __orangefs_setattr_mode(dentry, &iattr); 157476af919SMike Marshall 1584bef6900SMike Marshall return rc; 159b5accbb0SJan Kara } 160