1 /* -*- mode: c; c-basic-offset: 8; -*- 2 * vim: noexpandtab sw=8 ts=8 sts=0: 3 * 4 * acl.c 5 * 6 * Copyright (C) 2004, 2008 Oracle. All rights reserved. 7 * 8 * CREDITS: 9 * Lots of code in this file is copy from linux/fs/ext3/acl.c. 10 * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public 14 * License version 2 as published by the Free Software Foundation. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * General Public License for more details. 20 */ 21 22 #include <linux/init.h> 23 #include <linux/module.h> 24 #include <linux/slab.h> 25 #include <linux/string.h> 26 27 #include <cluster/masklog.h> 28 29 #include "ocfs2.h" 30 #include "alloc.h" 31 #include "dlmglue.h" 32 #include "file.h" 33 #include "inode.h" 34 #include "journal.h" 35 #include "ocfs2_fs.h" 36 37 #include "xattr.h" 38 #include "acl.h" 39 40 /* 41 * Convert from xattr value to acl struct. 42 */ 43 static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size) 44 { 45 int n, count; 46 struct posix_acl *acl; 47 48 if (!value) 49 return NULL; 50 if (size < sizeof(struct posix_acl_entry)) 51 return ERR_PTR(-EINVAL); 52 53 count = size / sizeof(struct posix_acl_entry); 54 55 acl = posix_acl_alloc(count, GFP_NOFS); 56 if (!acl) 57 return ERR_PTR(-ENOMEM); 58 for (n = 0; n < count; n++) { 59 struct ocfs2_acl_entry *entry = 60 (struct ocfs2_acl_entry *)value; 61 62 acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 63 acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 64 switch(acl->a_entries[n].e_tag) { 65 case ACL_USER: 66 acl->a_entries[n].e_uid = 67 make_kuid(&init_user_ns, 68 le32_to_cpu(entry->e_id)); 69 break; 70 case ACL_GROUP: 71 acl->a_entries[n].e_gid = 72 make_kgid(&init_user_ns, 73 le32_to_cpu(entry->e_id)); 74 break; 75 default: 76 break; 77 } 78 value += sizeof(struct posix_acl_entry); 79 80 } 81 return acl; 82 } 83 84 /* 85 * Convert acl struct to xattr value. 86 */ 87 static void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size) 88 { 89 struct ocfs2_acl_entry *entry = NULL; 90 char *ocfs2_acl; 91 size_t n; 92 93 *size = acl->a_count * sizeof(struct posix_acl_entry); 94 95 ocfs2_acl = kmalloc(*size, GFP_NOFS); 96 if (!ocfs2_acl) 97 return ERR_PTR(-ENOMEM); 98 99 entry = (struct ocfs2_acl_entry *)ocfs2_acl; 100 for (n = 0; n < acl->a_count; n++, entry++) { 101 entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 102 entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 103 switch(acl->a_entries[n].e_tag) { 104 case ACL_USER: 105 entry->e_id = cpu_to_le32( 106 from_kuid(&init_user_ns, 107 acl->a_entries[n].e_uid)); 108 break; 109 case ACL_GROUP: 110 entry->e_id = cpu_to_le32( 111 from_kgid(&init_user_ns, 112 acl->a_entries[n].e_gid)); 113 break; 114 default: 115 entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID); 116 break; 117 } 118 } 119 return ocfs2_acl; 120 } 121 122 static struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode, 123 int type, 124 struct buffer_head *di_bh) 125 { 126 int name_index; 127 char *value = NULL; 128 struct posix_acl *acl; 129 int retval; 130 131 switch (type) { 132 case ACL_TYPE_ACCESS: 133 name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; 134 break; 135 case ACL_TYPE_DEFAULT: 136 name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; 137 break; 138 default: 139 return ERR_PTR(-EINVAL); 140 } 141 142 retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, "", NULL, 0); 143 if (retval > 0) { 144 value = kmalloc(retval, GFP_NOFS); 145 if (!value) 146 return ERR_PTR(-ENOMEM); 147 retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, 148 "", value, retval); 149 } 150 151 if (retval > 0) 152 acl = ocfs2_acl_from_xattr(value, retval); 153 else if (retval == -ENODATA || retval == 0) 154 acl = NULL; 155 else 156 acl = ERR_PTR(retval); 157 158 kfree(value); 159 160 return acl; 161 } 162 163 164 /* 165 * Get posix acl. 166 */ 167 static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type) 168 { 169 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 170 struct buffer_head *di_bh = NULL; 171 struct posix_acl *acl; 172 int ret; 173 174 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 175 return NULL; 176 177 ret = ocfs2_inode_lock(inode, &di_bh, 0); 178 if (ret < 0) { 179 mlog_errno(ret); 180 acl = ERR_PTR(ret); 181 return acl; 182 } 183 184 acl = ocfs2_get_acl_nolock(inode, type, di_bh); 185 186 ocfs2_inode_unlock(inode, 0); 187 188 brelse(di_bh); 189 190 return acl; 191 } 192 193 /* 194 * Helper function to set i_mode in memory and disk. Some call paths 195 * will not have di_bh or a journal handle to pass, in which case it 196 * will create it's own. 197 */ 198 static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh, 199 handle_t *handle, umode_t new_mode) 200 { 201 int ret, commit_handle = 0; 202 struct ocfs2_dinode *di; 203 204 if (di_bh == NULL) { 205 ret = ocfs2_read_inode_block(inode, &di_bh); 206 if (ret) { 207 mlog_errno(ret); 208 goto out; 209 } 210 } else 211 get_bh(di_bh); 212 213 if (handle == NULL) { 214 handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), 215 OCFS2_INODE_UPDATE_CREDITS); 216 if (IS_ERR(handle)) { 217 ret = PTR_ERR(handle); 218 mlog_errno(ret); 219 goto out_brelse; 220 } 221 222 commit_handle = 1; 223 } 224 225 di = (struct ocfs2_dinode *)di_bh->b_data; 226 ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, 227 OCFS2_JOURNAL_ACCESS_WRITE); 228 if (ret) { 229 mlog_errno(ret); 230 goto out_commit; 231 } 232 233 inode->i_mode = new_mode; 234 inode->i_ctime = CURRENT_TIME; 235 di->i_mode = cpu_to_le16(inode->i_mode); 236 di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); 237 di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); 238 239 ocfs2_journal_dirty(handle, di_bh); 240 241 out_commit: 242 if (commit_handle) 243 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); 244 out_brelse: 245 brelse(di_bh); 246 out: 247 return ret; 248 } 249 250 /* 251 * Set the access or default ACL of an inode. 252 */ 253 static int ocfs2_set_acl(handle_t *handle, 254 struct inode *inode, 255 struct buffer_head *di_bh, 256 int type, 257 struct posix_acl *acl, 258 struct ocfs2_alloc_context *meta_ac, 259 struct ocfs2_alloc_context *data_ac) 260 { 261 int name_index; 262 void *value = NULL; 263 size_t size = 0; 264 int ret; 265 266 if (S_ISLNK(inode->i_mode)) 267 return -EOPNOTSUPP; 268 269 switch (type) { 270 case ACL_TYPE_ACCESS: 271 name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; 272 if (acl) { 273 umode_t mode = inode->i_mode; 274 ret = posix_acl_equiv_mode(acl, &mode); 275 if (ret < 0) 276 return ret; 277 else { 278 if (ret == 0) 279 acl = NULL; 280 281 ret = ocfs2_acl_set_mode(inode, di_bh, 282 handle, mode); 283 if (ret) 284 return ret; 285 286 } 287 } 288 break; 289 case ACL_TYPE_DEFAULT: 290 name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; 291 if (!S_ISDIR(inode->i_mode)) 292 return acl ? -EACCES : 0; 293 break; 294 default: 295 return -EINVAL; 296 } 297 298 if (acl) { 299 value = ocfs2_acl_to_xattr(acl, &size); 300 if (IS_ERR(value)) 301 return (int)PTR_ERR(value); 302 } 303 304 if (handle) 305 ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index, 306 "", value, size, 0, 307 meta_ac, data_ac); 308 else 309 ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0); 310 311 kfree(value); 312 313 return ret; 314 } 315 316 struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type) 317 { 318 struct ocfs2_super *osb; 319 struct buffer_head *di_bh = NULL; 320 struct posix_acl *acl; 321 int ret = -EAGAIN; 322 323 osb = OCFS2_SB(inode->i_sb); 324 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 325 return NULL; 326 327 ret = ocfs2_read_inode_block(inode, &di_bh); 328 if (ret < 0) 329 return ERR_PTR(ret); 330 331 acl = ocfs2_get_acl_nolock(inode, type, di_bh); 332 333 brelse(di_bh); 334 335 return acl; 336 } 337 338 int ocfs2_acl_chmod(struct inode *inode) 339 { 340 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 341 struct posix_acl *acl; 342 int ret; 343 344 if (S_ISLNK(inode->i_mode)) 345 return -EOPNOTSUPP; 346 347 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 348 return 0; 349 350 acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS); 351 if (IS_ERR(acl) || !acl) 352 return PTR_ERR(acl); 353 ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); 354 if (ret) 355 return ret; 356 ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS, 357 acl, NULL, NULL); 358 posix_acl_release(acl); 359 return ret; 360 } 361 362 /* 363 * Initialize the ACLs of a new inode. If parent directory has default ACL, 364 * then clone to new inode. Called from ocfs2_mknod. 365 */ 366 int ocfs2_init_acl(handle_t *handle, 367 struct inode *inode, 368 struct inode *dir, 369 struct buffer_head *di_bh, 370 struct buffer_head *dir_bh, 371 struct ocfs2_alloc_context *meta_ac, 372 struct ocfs2_alloc_context *data_ac) 373 { 374 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 375 struct posix_acl *acl = NULL; 376 int ret = 0, ret2; 377 umode_t mode; 378 379 if (!S_ISLNK(inode->i_mode)) { 380 if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { 381 acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT, 382 dir_bh); 383 if (IS_ERR(acl)) 384 return PTR_ERR(acl); 385 } 386 if (!acl) { 387 mode = inode->i_mode & ~current_umask(); 388 ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); 389 if (ret) { 390 mlog_errno(ret); 391 goto cleanup; 392 } 393 } 394 } 395 if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { 396 if (S_ISDIR(inode->i_mode)) { 397 ret = ocfs2_set_acl(handle, inode, di_bh, 398 ACL_TYPE_DEFAULT, acl, 399 meta_ac, data_ac); 400 if (ret) 401 goto cleanup; 402 } 403 mode = inode->i_mode; 404 ret = posix_acl_create(&acl, GFP_NOFS, &mode); 405 if (ret < 0) 406 return ret; 407 408 ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode); 409 if (ret2) { 410 mlog_errno(ret2); 411 ret = ret2; 412 goto cleanup; 413 } 414 if (ret > 0) { 415 ret = ocfs2_set_acl(handle, inode, 416 di_bh, ACL_TYPE_ACCESS, 417 acl, meta_ac, data_ac); 418 } 419 } 420 cleanup: 421 posix_acl_release(acl); 422 return ret; 423 } 424 425 static size_t ocfs2_xattr_list_acl_access(struct dentry *dentry, 426 char *list, 427 size_t list_len, 428 const char *name, 429 size_t name_len, 430 int type) 431 { 432 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); 433 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); 434 435 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 436 return 0; 437 438 if (list && size <= list_len) 439 memcpy(list, POSIX_ACL_XATTR_ACCESS, size); 440 return size; 441 } 442 443 static size_t ocfs2_xattr_list_acl_default(struct dentry *dentry, 444 char *list, 445 size_t list_len, 446 const char *name, 447 size_t name_len, 448 int type) 449 { 450 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); 451 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); 452 453 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 454 return 0; 455 456 if (list && size <= list_len) 457 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); 458 return size; 459 } 460 461 static int ocfs2_xattr_get_acl(struct dentry *dentry, const char *name, 462 void *buffer, size_t size, int type) 463 { 464 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); 465 struct posix_acl *acl; 466 int ret; 467 468 if (strcmp(name, "") != 0) 469 return -EINVAL; 470 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 471 return -EOPNOTSUPP; 472 473 acl = ocfs2_get_acl(dentry->d_inode, type); 474 if (IS_ERR(acl)) 475 return PTR_ERR(acl); 476 if (acl == NULL) 477 return -ENODATA; 478 ret = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); 479 posix_acl_release(acl); 480 481 return ret; 482 } 483 484 static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name, 485 const void *value, size_t size, int flags, int type) 486 { 487 struct inode *inode = dentry->d_inode; 488 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 489 struct posix_acl *acl; 490 int ret = 0; 491 492 if (strcmp(name, "") != 0) 493 return -EINVAL; 494 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 495 return -EOPNOTSUPP; 496 497 if (!inode_owner_or_capable(inode)) 498 return -EPERM; 499 500 if (value) { 501 acl = posix_acl_from_xattr(&init_user_ns, value, size); 502 if (IS_ERR(acl)) 503 return PTR_ERR(acl); 504 else if (acl) { 505 ret = posix_acl_valid(acl); 506 if (ret) 507 goto cleanup; 508 } 509 } else 510 acl = NULL; 511 512 ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL); 513 514 cleanup: 515 posix_acl_release(acl); 516 return ret; 517 } 518 519 const struct xattr_handler ocfs2_xattr_acl_access_handler = { 520 .prefix = POSIX_ACL_XATTR_ACCESS, 521 .flags = ACL_TYPE_ACCESS, 522 .list = ocfs2_xattr_list_acl_access, 523 .get = ocfs2_xattr_get_acl, 524 .set = ocfs2_xattr_set_acl, 525 }; 526 527 const struct xattr_handler ocfs2_xattr_acl_default_handler = { 528 .prefix = POSIX_ACL_XATTR_DEFAULT, 529 .flags = ACL_TYPE_DEFAULT, 530 .list = ocfs2_xattr_list_acl_default, 531 .get = ocfs2_xattr_get_acl, 532 .set = ocfs2_xattr_set_acl, 533 }; 534