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 if (count < 0) 55 return ERR_PTR(-EINVAL); 56 if (count == 0) 57 return NULL; 58 59 acl = posix_acl_alloc(count, GFP_NOFS); 60 if (!acl) 61 return ERR_PTR(-ENOMEM); 62 for (n = 0; n < count; n++) { 63 struct ocfs2_acl_entry *entry = 64 (struct ocfs2_acl_entry *)value; 65 66 acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 67 acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 68 acl->a_entries[n].e_id = le32_to_cpu(entry->e_id); 69 value += sizeof(struct posix_acl_entry); 70 71 } 72 return acl; 73 } 74 75 /* 76 * Convert acl struct to xattr value. 77 */ 78 static void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size) 79 { 80 struct ocfs2_acl_entry *entry = NULL; 81 char *ocfs2_acl; 82 size_t n; 83 84 *size = acl->a_count * sizeof(struct posix_acl_entry); 85 86 ocfs2_acl = kmalloc(*size, GFP_NOFS); 87 if (!ocfs2_acl) 88 return ERR_PTR(-ENOMEM); 89 90 entry = (struct ocfs2_acl_entry *)ocfs2_acl; 91 for (n = 0; n < acl->a_count; n++, entry++) { 92 entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 93 entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 94 entry->e_id = cpu_to_le32(acl->a_entries[n].e_id); 95 } 96 return ocfs2_acl; 97 } 98 99 static struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode, 100 int type, 101 struct buffer_head *di_bh) 102 { 103 int name_index; 104 char *value = NULL; 105 struct posix_acl *acl; 106 int retval; 107 108 switch (type) { 109 case ACL_TYPE_ACCESS: 110 name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; 111 break; 112 case ACL_TYPE_DEFAULT: 113 name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; 114 break; 115 default: 116 return ERR_PTR(-EINVAL); 117 } 118 119 retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, "", NULL, 0); 120 if (retval > 0) { 121 value = kmalloc(retval, GFP_NOFS); 122 if (!value) 123 return ERR_PTR(-ENOMEM); 124 retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, 125 "", value, retval); 126 } 127 128 if (retval > 0) 129 acl = ocfs2_acl_from_xattr(value, retval); 130 else if (retval == -ENODATA || retval == 0) 131 acl = NULL; 132 else 133 acl = ERR_PTR(retval); 134 135 kfree(value); 136 137 return acl; 138 } 139 140 141 /* 142 * Get posix acl. 143 */ 144 static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type) 145 { 146 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 147 struct buffer_head *di_bh = NULL; 148 struct posix_acl *acl; 149 int ret; 150 151 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 152 return NULL; 153 154 ret = ocfs2_inode_lock(inode, &di_bh, 0); 155 if (ret < 0) { 156 mlog_errno(ret); 157 acl = ERR_PTR(ret); 158 return acl; 159 } 160 161 acl = ocfs2_get_acl_nolock(inode, type, di_bh); 162 163 ocfs2_inode_unlock(inode, 0); 164 165 brelse(di_bh); 166 167 return acl; 168 } 169 170 /* 171 * Helper function to set i_mode in memory and disk. Some call paths 172 * will not have di_bh or a journal handle to pass, in which case it 173 * will create it's own. 174 */ 175 static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh, 176 handle_t *handle, umode_t new_mode) 177 { 178 int ret, commit_handle = 0; 179 struct ocfs2_dinode *di; 180 181 if (di_bh == NULL) { 182 ret = ocfs2_read_inode_block(inode, &di_bh); 183 if (ret) { 184 mlog_errno(ret); 185 goto out; 186 } 187 } else 188 get_bh(di_bh); 189 190 if (handle == NULL) { 191 handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), 192 OCFS2_INODE_UPDATE_CREDITS); 193 if (IS_ERR(handle)) { 194 ret = PTR_ERR(handle); 195 mlog_errno(ret); 196 goto out_brelse; 197 } 198 199 commit_handle = 1; 200 } 201 202 di = (struct ocfs2_dinode *)di_bh->b_data; 203 ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, 204 OCFS2_JOURNAL_ACCESS_WRITE); 205 if (ret) { 206 mlog_errno(ret); 207 goto out_commit; 208 } 209 210 inode->i_mode = new_mode; 211 inode->i_ctime = CURRENT_TIME; 212 di->i_mode = cpu_to_le16(inode->i_mode); 213 di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); 214 di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); 215 216 ocfs2_journal_dirty(handle, di_bh); 217 218 out_commit: 219 if (commit_handle) 220 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); 221 out_brelse: 222 brelse(di_bh); 223 out: 224 return ret; 225 } 226 227 /* 228 * Set the access or default ACL of an inode. 229 */ 230 static int ocfs2_set_acl(handle_t *handle, 231 struct inode *inode, 232 struct buffer_head *di_bh, 233 int type, 234 struct posix_acl *acl, 235 struct ocfs2_alloc_context *meta_ac, 236 struct ocfs2_alloc_context *data_ac) 237 { 238 int name_index; 239 void *value = NULL; 240 size_t size = 0; 241 int ret; 242 243 if (S_ISLNK(inode->i_mode)) 244 return -EOPNOTSUPP; 245 246 switch (type) { 247 case ACL_TYPE_ACCESS: 248 name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; 249 if (acl) { 250 umode_t mode = inode->i_mode; 251 ret = posix_acl_equiv_mode(acl, &mode); 252 if (ret < 0) 253 return ret; 254 else { 255 if (ret == 0) 256 acl = NULL; 257 258 ret = ocfs2_acl_set_mode(inode, di_bh, 259 handle, mode); 260 if (ret) 261 return ret; 262 263 } 264 } 265 break; 266 case ACL_TYPE_DEFAULT: 267 name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; 268 if (!S_ISDIR(inode->i_mode)) 269 return acl ? -EACCES : 0; 270 break; 271 default: 272 return -EINVAL; 273 } 274 275 if (acl) { 276 value = ocfs2_acl_to_xattr(acl, &size); 277 if (IS_ERR(value)) 278 return (int)PTR_ERR(value); 279 } 280 281 if (handle) 282 ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index, 283 "", value, size, 0, 284 meta_ac, data_ac); 285 else 286 ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0); 287 288 kfree(value); 289 290 return ret; 291 } 292 293 struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type) 294 { 295 struct ocfs2_super *osb; 296 struct buffer_head *di_bh = NULL; 297 struct posix_acl *acl; 298 int ret = -EAGAIN; 299 300 osb = OCFS2_SB(inode->i_sb); 301 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 302 return NULL; 303 304 ret = ocfs2_read_inode_block(inode, &di_bh); 305 if (ret < 0) 306 return ERR_PTR(ret); 307 308 acl = ocfs2_get_acl_nolock(inode, type, di_bh); 309 310 brelse(di_bh); 311 312 return acl; 313 } 314 315 int ocfs2_acl_chmod(struct inode *inode) 316 { 317 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 318 struct posix_acl *acl; 319 int ret; 320 321 if (S_ISLNK(inode->i_mode)) 322 return -EOPNOTSUPP; 323 324 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 325 return 0; 326 327 acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS); 328 if (IS_ERR(acl) || !acl) 329 return PTR_ERR(acl); 330 ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); 331 if (ret) 332 return ret; 333 ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS, 334 acl, NULL, NULL); 335 posix_acl_release(acl); 336 return ret; 337 } 338 339 /* 340 * Initialize the ACLs of a new inode. If parent directory has default ACL, 341 * then clone to new inode. Called from ocfs2_mknod. 342 */ 343 int ocfs2_init_acl(handle_t *handle, 344 struct inode *inode, 345 struct inode *dir, 346 struct buffer_head *di_bh, 347 struct buffer_head *dir_bh, 348 struct ocfs2_alloc_context *meta_ac, 349 struct ocfs2_alloc_context *data_ac) 350 { 351 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 352 struct posix_acl *acl = NULL; 353 int ret = 0, ret2; 354 umode_t mode; 355 356 if (!S_ISLNK(inode->i_mode)) { 357 if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { 358 acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT, 359 dir_bh); 360 if (IS_ERR(acl)) 361 return PTR_ERR(acl); 362 } 363 if (!acl) { 364 mode = inode->i_mode & ~current_umask(); 365 ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); 366 if (ret) { 367 mlog_errno(ret); 368 goto cleanup; 369 } 370 } 371 } 372 if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { 373 if (S_ISDIR(inode->i_mode)) { 374 ret = ocfs2_set_acl(handle, inode, di_bh, 375 ACL_TYPE_DEFAULT, acl, 376 meta_ac, data_ac); 377 if (ret) 378 goto cleanup; 379 } 380 mode = inode->i_mode; 381 ret = posix_acl_create(&acl, GFP_NOFS, &mode); 382 if (ret < 0) 383 return ret; 384 385 ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode); 386 if (ret2) { 387 mlog_errno(ret2); 388 ret = ret2; 389 goto cleanup; 390 } 391 if (ret > 0) { 392 ret = ocfs2_set_acl(handle, inode, 393 di_bh, ACL_TYPE_ACCESS, 394 acl, meta_ac, data_ac); 395 } 396 } 397 cleanup: 398 posix_acl_release(acl); 399 return ret; 400 } 401 402 static size_t ocfs2_xattr_list_acl_access(struct dentry *dentry, 403 char *list, 404 size_t list_len, 405 const char *name, 406 size_t name_len, 407 int type) 408 { 409 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); 410 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); 411 412 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 413 return 0; 414 415 if (list && size <= list_len) 416 memcpy(list, POSIX_ACL_XATTR_ACCESS, size); 417 return size; 418 } 419 420 static size_t ocfs2_xattr_list_acl_default(struct dentry *dentry, 421 char *list, 422 size_t list_len, 423 const char *name, 424 size_t name_len, 425 int type) 426 { 427 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); 428 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); 429 430 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 431 return 0; 432 433 if (list && size <= list_len) 434 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); 435 return size; 436 } 437 438 static int ocfs2_xattr_get_acl(struct dentry *dentry, const char *name, 439 void *buffer, size_t size, int type) 440 { 441 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); 442 struct posix_acl *acl; 443 int ret; 444 445 if (strcmp(name, "") != 0) 446 return -EINVAL; 447 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 448 return -EOPNOTSUPP; 449 450 acl = ocfs2_get_acl(dentry->d_inode, type); 451 if (IS_ERR(acl)) 452 return PTR_ERR(acl); 453 if (acl == NULL) 454 return -ENODATA; 455 ret = posix_acl_to_xattr(acl, buffer, size); 456 posix_acl_release(acl); 457 458 return ret; 459 } 460 461 static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name, 462 const void *value, size_t size, int flags, int type) 463 { 464 struct inode *inode = dentry->d_inode; 465 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 466 struct posix_acl *acl; 467 int ret = 0; 468 469 if (strcmp(name, "") != 0) 470 return -EINVAL; 471 if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 472 return -EOPNOTSUPP; 473 474 if (!inode_owner_or_capable(inode)) 475 return -EPERM; 476 477 if (value) { 478 acl = posix_acl_from_xattr(value, size); 479 if (IS_ERR(acl)) 480 return PTR_ERR(acl); 481 else if (acl) { 482 ret = posix_acl_valid(acl); 483 if (ret) 484 goto cleanup; 485 } 486 } else 487 acl = NULL; 488 489 ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL); 490 491 cleanup: 492 posix_acl_release(acl); 493 return ret; 494 } 495 496 const struct xattr_handler ocfs2_xattr_acl_access_handler = { 497 .prefix = POSIX_ACL_XATTR_ACCESS, 498 .flags = ACL_TYPE_ACCESS, 499 .list = ocfs2_xattr_list_acl_access, 500 .get = ocfs2_xattr_get_acl, 501 .set = ocfs2_xattr_set_acl, 502 }; 503 504 const struct xattr_handler ocfs2_xattr_acl_default_handler = { 505 .prefix = POSIX_ACL_XATTR_DEFAULT, 506 .flags = ACL_TYPE_DEFAULT, 507 .list = ocfs2_xattr_list_acl_default, 508 .get = ocfs2_xattr_get_acl, 509 .set = ocfs2_xattr_set_acl, 510 }; 511