1/* 2 * Copyright (c) 2008, Christoph Hellwig 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18#include "xfs.h" 19#include "xfs_acl.h" 20#include "xfs_attr.h" 21#include "xfs_bmap_btree.h" 22#include "xfs_inode.h" 23#include "xfs_vnodeops.h" 24#include "xfs_trace.h" 25#include <linux/slab.h> 26#include <linux/xattr.h> 27#include <linux/posix_acl_xattr.h> 28 29 30/* 31 * Locking scheme: 32 * - all ACL updates are protected by inode->i_mutex, which is taken before 33 * calling into this file. 34 */ 35 36STATIC struct posix_acl * 37xfs_acl_from_disk(struct xfs_acl *aclp) 38{ 39 struct posix_acl_entry *acl_e; 40 struct posix_acl *acl; 41 struct xfs_acl_entry *ace; 42 int count, i; 43 44 count = be32_to_cpu(aclp->acl_cnt); 45 46 acl = posix_acl_alloc(count, GFP_KERNEL); 47 if (!acl) 48 return ERR_PTR(-ENOMEM); 49 50 for (i = 0; i < count; i++) { 51 acl_e = &acl->a_entries[i]; 52 ace = &aclp->acl_entry[i]; 53 54 /* 55 * The tag is 32 bits on disk and 16 bits in core. 56 * 57 * Because every access to it goes through the core 58 * format first this is not a problem. 59 */ 60 acl_e->e_tag = be32_to_cpu(ace->ae_tag); 61 acl_e->e_perm = be16_to_cpu(ace->ae_perm); 62 63 switch (acl_e->e_tag) { 64 case ACL_USER: 65 case ACL_GROUP: 66 acl_e->e_id = be32_to_cpu(ace->ae_id); 67 break; 68 case ACL_USER_OBJ: 69 case ACL_GROUP_OBJ: 70 case ACL_MASK: 71 case ACL_OTHER: 72 acl_e->e_id = ACL_UNDEFINED_ID; 73 break; 74 default: 75 goto fail; 76 } 77 } 78 return acl; 79 80fail: 81 posix_acl_release(acl); 82 return ERR_PTR(-EINVAL); 83} 84 85STATIC void 86xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl) 87{ 88 const struct posix_acl_entry *acl_e; 89 struct xfs_acl_entry *ace; 90 int i; 91 92 aclp->acl_cnt = cpu_to_be32(acl->a_count); 93 for (i = 0; i < acl->a_count; i++) { 94 ace = &aclp->acl_entry[i]; 95 acl_e = &acl->a_entries[i]; 96 97 ace->ae_tag = cpu_to_be32(acl_e->e_tag); 98 ace->ae_id = cpu_to_be32(acl_e->e_id); 99 ace->ae_perm = cpu_to_be16(acl_e->e_perm); 100 } 101} 102 103struct posix_acl * 104xfs_get_acl(struct inode *inode, int type) 105{ 106 struct xfs_inode *ip = XFS_I(inode); 107 struct posix_acl *acl; 108 struct xfs_acl *xfs_acl; 109 int len = sizeof(struct xfs_acl); 110 unsigned char *ea_name; 111 int error; 112 113 acl = get_cached_acl(inode, type); 114 if (acl != ACL_NOT_CACHED) 115 return acl; 116 117 switch (type) { 118 case ACL_TYPE_ACCESS: 119 ea_name = SGI_ACL_FILE; 120 break; 121 case ACL_TYPE_DEFAULT: 122 ea_name = SGI_ACL_DEFAULT; 123 break; 124 default: 125 BUG(); 126 } 127 128 /* 129 * If we have a cached ACLs value just return it, not need to 130 * go out to the disk. 131 */ 132 133 xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); 134 if (!xfs_acl) 135 return ERR_PTR(-ENOMEM); 136 137 error = -xfs_attr_get(ip, ea_name, (unsigned char *)xfs_acl, 138 &len, ATTR_ROOT); 139 if (error) { 140 /* 141 * If the attribute doesn't exist make sure we have a negative 142 * cache entry, for any other error assume it is transient and 143 * leave the cache entry as ACL_NOT_CACHED. 144 */ 145 if (error == -ENOATTR) { 146 acl = NULL; 147 goto out_update_cache; 148 } 149 goto out; 150 } 151 152 acl = xfs_acl_from_disk(xfs_acl); 153 if (IS_ERR(acl)) 154 goto out; 155 156 out_update_cache: 157 set_cached_acl(inode, type, acl); 158 out: 159 kfree(xfs_acl); 160 return acl; 161} 162 163STATIC int 164xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) 165{ 166 struct xfs_inode *ip = XFS_I(inode); 167 unsigned char *ea_name; 168 int error; 169 170 if (S_ISLNK(inode->i_mode)) 171 return -EOPNOTSUPP; 172 173 switch (type) { 174 case ACL_TYPE_ACCESS: 175 ea_name = SGI_ACL_FILE; 176 break; 177 case ACL_TYPE_DEFAULT: 178 if (!S_ISDIR(inode->i_mode)) 179 return acl ? -EACCES : 0; 180 ea_name = SGI_ACL_DEFAULT; 181 break; 182 default: 183 return -EINVAL; 184 } 185 186 if (acl) { 187 struct xfs_acl *xfs_acl; 188 int len; 189 190 xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); 191 if (!xfs_acl) 192 return -ENOMEM; 193 194 xfs_acl_to_disk(xfs_acl, acl); 195 len = sizeof(struct xfs_acl) - 196 (sizeof(struct xfs_acl_entry) * 197 (XFS_ACL_MAX_ENTRIES - acl->a_count)); 198 199 error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, 200 len, ATTR_ROOT); 201 202 kfree(xfs_acl); 203 } else { 204 /* 205 * A NULL ACL argument means we want to remove the ACL. 206 */ 207 error = -xfs_attr_remove(ip, ea_name, ATTR_ROOT); 208 209 /* 210 * If the attribute didn't exist to start with that's fine. 211 */ 212 if (error == -ENOATTR) 213 error = 0; 214 } 215 216 if (!error) 217 set_cached_acl(inode, type, acl); 218 return error; 219} 220 221int 222xfs_check_acl(struct inode *inode, int mask) 223{ 224 struct xfs_inode *ip = XFS_I(inode); 225 struct posix_acl *acl; 226 int error = -EAGAIN; 227 228 trace_xfs_check_acl(ip); 229 230 /* 231 * If there is no attribute fork no ACL exists on this inode and 232 * we can skip the whole exercise. 233 */ 234 if (!XFS_IFORK_Q(ip)) 235 return -EAGAIN; 236 237 acl = xfs_get_acl(inode, ACL_TYPE_ACCESS); 238 if (IS_ERR(acl)) 239 return PTR_ERR(acl); 240 if (acl) { 241 error = posix_acl_permission(inode, acl, mask); 242 posix_acl_release(acl); 243 } 244 245 return error; 246} 247 248static int 249xfs_set_mode(struct inode *inode, mode_t mode) 250{ 251 int error = 0; 252 253 if (mode != inode->i_mode) { 254 struct iattr iattr; 255 256 iattr.ia_valid = ATTR_MODE | ATTR_CTIME; 257 iattr.ia_mode = mode; 258 iattr.ia_ctime = current_fs_time(inode->i_sb); 259 260 error = -xfs_setattr(XFS_I(inode), &iattr, XFS_ATTR_NOACL); 261 } 262 263 return error; 264} 265 266static int 267xfs_acl_exists(struct inode *inode, unsigned char *name) 268{ 269 int len = sizeof(struct xfs_acl); 270 271 return (xfs_attr_get(XFS_I(inode), name, NULL, &len, 272 ATTR_ROOT|ATTR_KERNOVAL) == 0); 273} 274 275int 276posix_acl_access_exists(struct inode *inode) 277{ 278 return xfs_acl_exists(inode, SGI_ACL_FILE); 279} 280 281int 282posix_acl_default_exists(struct inode *inode) 283{ 284 if (!S_ISDIR(inode->i_mode)) 285 return 0; 286 return xfs_acl_exists(inode, SGI_ACL_DEFAULT); 287} 288 289/* 290 * No need for i_mutex because the inode is not yet exposed to the VFS. 291 */ 292int 293xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl) 294{ 295 struct posix_acl *clone; 296 mode_t mode; 297 int error = 0, inherit = 0; 298 299 if (S_ISDIR(inode->i_mode)) { 300 error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl); 301 if (error) 302 return error; 303 } 304 305 clone = posix_acl_clone(default_acl, GFP_KERNEL); 306 if (!clone) 307 return -ENOMEM; 308 309 mode = inode->i_mode; 310 error = posix_acl_create_masq(clone, &mode); 311 if (error < 0) 312 goto out_release_clone; 313 314 /* 315 * If posix_acl_create_masq returns a positive value we need to 316 * inherit a permission that can't be represented using the Unix 317 * mode bits and we actually need to set an ACL. 318 */ 319 if (error > 0) 320 inherit = 1; 321 322 error = xfs_set_mode(inode, mode); 323 if (error) 324 goto out_release_clone; 325 326 if (inherit) 327 error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 328 329 out_release_clone: 330 posix_acl_release(clone); 331 return error; 332} 333 334int 335xfs_acl_chmod(struct inode *inode) 336{ 337 struct posix_acl *acl, *clone; 338 int error; 339 340 if (S_ISLNK(inode->i_mode)) 341 return -EOPNOTSUPP; 342 343 acl = xfs_get_acl(inode, ACL_TYPE_ACCESS); 344 if (IS_ERR(acl) || !acl) 345 return PTR_ERR(acl); 346 347 clone = posix_acl_clone(acl, GFP_KERNEL); 348 posix_acl_release(acl); 349 if (!clone) 350 return -ENOMEM; 351 352 error = posix_acl_chmod_masq(clone, inode->i_mode); 353 if (!error) 354 error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 355 356 posix_acl_release(clone); 357 return error; 358} 359 360static int 361xfs_xattr_acl_get(struct dentry *dentry, const char *name, 362 void *value, size_t size, int type) 363{ 364 struct posix_acl *acl; 365 int error; 366 367 acl = xfs_get_acl(dentry->d_inode, type); 368 if (IS_ERR(acl)) 369 return PTR_ERR(acl); 370 if (acl == NULL) 371 return -ENODATA; 372 373 error = posix_acl_to_xattr(acl, value, size); 374 posix_acl_release(acl); 375 376 return error; 377} 378 379static int 380xfs_xattr_acl_set(struct dentry *dentry, const char *name, 381 const void *value, size_t size, int flags, int type) 382{ 383 struct inode *inode = dentry->d_inode; 384 struct posix_acl *acl = NULL; 385 int error = 0; 386 387 if (flags & XATTR_CREATE) 388 return -EINVAL; 389 if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) 390 return value ? -EACCES : 0; 391 if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) 392 return -EPERM; 393 394 if (!value) 395 goto set_acl; 396 397 acl = posix_acl_from_xattr(value, size); 398 if (!acl) { 399 /* 400 * acl_set_file(3) may request that we set default ACLs with 401 * zero length -- defend (gracefully) against that here. 402 */ 403 goto out; 404 } 405 if (IS_ERR(acl)) { 406 error = PTR_ERR(acl); 407 goto out; 408 } 409 410 error = posix_acl_valid(acl); 411 if (error) 412 goto out_release; 413 414 error = -EINVAL; 415 if (acl->a_count > XFS_ACL_MAX_ENTRIES) 416 goto out_release; 417 418 if (type == ACL_TYPE_ACCESS) { 419 mode_t mode = inode->i_mode; 420 error = posix_acl_equiv_mode(acl, &mode); 421 422 if (error <= 0) { 423 posix_acl_release(acl); 424 acl = NULL; 425 426 if (error < 0) 427 return error; 428 } 429 430 error = xfs_set_mode(inode, mode); 431 if (error) 432 goto out_release; 433 } 434 435 set_acl: 436 error = xfs_set_acl(inode, type, acl); 437 out_release: 438 posix_acl_release(acl); 439 out: 440 return error; 441} 442 443const struct xattr_handler xfs_xattr_acl_access_handler = { 444 .prefix = POSIX_ACL_XATTR_ACCESS, 445 .flags = ACL_TYPE_ACCESS, 446 .get = xfs_xattr_acl_get, 447 .set = xfs_xattr_acl_set, 448}; 449 450const struct xattr_handler xfs_xattr_acl_default_handler = { 451 .prefix = POSIX_ACL_XATTR_DEFAULT, 452 .flags = ACL_TYPE_DEFAULT, 453 .get = xfs_xattr_acl_get, 454 .set = xfs_xattr_acl_set, 455}; 456