acl.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) International Business Machines Corp., 2002-2004
  4. * Copyright (C) Andreas Gruenbacher, 2001
  5. * Copyright (C) Linus Torvalds, 1991, 1992
  6. */
  7. #include <linux/sched.h>
  8. #include <linux/slab.h>
  9. #include <linux/fs.h>
  10. #include <linux/posix_acl_xattr.h>
  11. #include "jfs_incore.h"
  12. #include "jfs_txnmgr.h"
  13. #include "jfs_xattr.h"
  14. #include "jfs_acl.h"
  15. struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu)
  16. {
  17. struct posix_acl *acl;
  18. char *ea_name;
  19. int size;
  20. char *value = NULL;
  21. if (rcu)
  22. return ERR_PTR(-ECHILD);
  23. switch(type) {
  24. case ACL_TYPE_ACCESS:
  25. ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
  26. break;
  27. case ACL_TYPE_DEFAULT:
  28. ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  29. break;
  30. default:
  31. return ERR_PTR(-EINVAL);
  32. }
  33. size = __jfs_getxattr(inode, ea_name, NULL, 0);
  34. if (size > 0) {
  35. value = kmalloc(size, GFP_KERNEL);
  36. if (!value)
  37. return ERR_PTR(-ENOMEM);
  38. size = __jfs_getxattr(inode, ea_name, value, size);
  39. }
  40. if (size < 0) {
  41. if (size == -ENODATA)
  42. acl = NULL;
  43. else
  44. acl = ERR_PTR(size);
  45. } else {
  46. acl = posix_acl_from_xattr(&init_user_ns, value, size);
  47. }
  48. kfree(value);
  49. return acl;
  50. }
  51. static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
  52. struct posix_acl *acl)
  53. {
  54. char *ea_name;
  55. int rc;
  56. int size = 0;
  57. char *value = NULL;
  58. switch (type) {
  59. case ACL_TYPE_ACCESS:
  60. ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
  61. break;
  62. case ACL_TYPE_DEFAULT:
  63. ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
  64. break;
  65. default:
  66. return -EINVAL;
  67. }
  68. if (acl) {
  69. size = posix_acl_xattr_size(acl->a_count);
  70. value = kmalloc(size, GFP_KERNEL);
  71. if (!value)
  72. return -ENOMEM;
  73. rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
  74. if (rc < 0)
  75. goto out;
  76. }
  77. rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
  78. out:
  79. kfree(value);
  80. if (!rc)
  81. set_cached_acl(inode, type, acl);
  82. return rc;
  83. }
  84. int jfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
  85. struct posix_acl *acl, int type)
  86. {
  87. int rc;
  88. tid_t tid;
  89. int update_mode = 0;
  90. umode_t mode = inode->i_mode;
  91. tid = txBegin(inode->i_sb, 0);
  92. mutex_lock(&JFS_IP(inode)->commit_mutex);
  93. if (type == ACL_TYPE_ACCESS && acl) {
  94. rc = posix_acl_update_mode(&init_user_ns, inode, &mode, &acl);
  95. if (rc)
  96. goto end_tx;
  97. if (mode != inode->i_mode)
  98. update_mode = 1;
  99. }
  100. rc = __jfs_set_acl(tid, inode, type, acl);
  101. if (!rc) {
  102. if (update_mode) {
  103. inode->i_mode = mode;
  104. inode->i_ctime = current_time(inode);
  105. mark_inode_dirty(inode);
  106. }
  107. rc = txCommit(tid, 1, &inode, 0);
  108. }
  109. end_tx:
  110. txEnd(tid);
  111. mutex_unlock(&JFS_IP(inode)->commit_mutex);
  112. return rc;
  113. }
  114. int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
  115. {
  116. struct posix_acl *default_acl, *acl;
  117. int rc = 0;
  118. rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
  119. if (rc)
  120. return rc;
  121. if (default_acl) {
  122. rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
  123. posix_acl_release(default_acl);
  124. } else {
  125. inode->i_default_acl = NULL;
  126. }
  127. if (acl) {
  128. if (!rc)
  129. rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
  130. posix_acl_release(acl);
  131. } else {
  132. inode->i_acl = NULL;
  133. }
  134. JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
  135. inode->i_mode;
  136. return rc;
  137. }