xattr.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. * fs/cifs/xattr.c
  3. *
  4. * Copyright (c) International Business Machines Corp., 2003, 2007
  5. * Author(s): Steve French (sfrench@us.ibm.com)
  6. *
  7. * This library is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as published
  9. * by the Free Software Foundation; either version 2.1 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  15. * the GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include <linux/fs.h>
  22. #include <linux/posix_acl_xattr.h>
  23. #include <linux/slab.h>
  24. #include <linux/xattr.h>
  25. #include "cifsfs.h"
  26. #include "cifspdu.h"
  27. #include "cifsglob.h"
  28. #include "cifsproto.h"
  29. #include "cifs_debug.h"
  30. #include "cifs_fs_sb.h"
  31. #include "cifs_unicode.h"
  32. #define MAX_EA_VALUE_SIZE 65535
  33. #define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
  34. /* BB need to add server (Samba e.g) support for security and trusted prefix */
  35. enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT };
  36. static int cifs_xattr_set(const struct xattr_handler *handler,
  37. struct dentry *dentry, struct inode *inode,
  38. const char *name, const void *value,
  39. size_t size, int flags)
  40. {
  41. int rc = -EOPNOTSUPP;
  42. unsigned int xid;
  43. struct super_block *sb = dentry->d_sb;
  44. struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  45. struct tcon_link *tlink;
  46. struct cifs_tcon *pTcon;
  47. char *full_path;
  48. tlink = cifs_sb_tlink(cifs_sb);
  49. if (IS_ERR(tlink))
  50. return PTR_ERR(tlink);
  51. pTcon = tlink_tcon(tlink);
  52. xid = get_xid();
  53. full_path = build_path_from_dentry(dentry);
  54. if (full_path == NULL) {
  55. rc = -ENOMEM;
  56. goto out;
  57. }
  58. /* return dos attributes as pseudo xattr */
  59. /* return alt name if available as pseudo attr */
  60. /* if proc/fs/cifs/streamstoxattr is set then
  61. search server for EAs or streams to
  62. returns as xattrs */
  63. if (size > MAX_EA_VALUE_SIZE) {
  64. cifs_dbg(FYI, "size of EA value too large\n");
  65. rc = -EOPNOTSUPP;
  66. goto out;
  67. }
  68. switch (handler->flags) {
  69. case XATTR_USER:
  70. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  71. goto out;
  72. if (pTcon->ses->server->ops->set_EA)
  73. rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
  74. full_path, name, value, (__u16)size,
  75. cifs_sb->local_nls, cifs_remap(cifs_sb));
  76. break;
  77. case XATTR_CIFS_ACL: {
  78. #ifdef CONFIG_CIFS_ACL
  79. struct cifs_ntsd *pacl;
  80. if (!value)
  81. goto out;
  82. pacl = kmalloc(size, GFP_KERNEL);
  83. if (!pacl) {
  84. rc = -ENOMEM;
  85. } else {
  86. memcpy(pacl, value, size);
  87. if (value &&
  88. pTcon->ses->server->ops->set_acl)
  89. rc = pTcon->ses->server->ops->set_acl(pacl,
  90. size, inode,
  91. full_path, CIFS_ACL_DACL);
  92. else
  93. rc = -EOPNOTSUPP;
  94. if (rc == 0) /* force revalidate of the inode */
  95. CIFS_I(inode)->time = 0;
  96. kfree(pacl);
  97. }
  98. #endif /* CONFIG_CIFS_ACL */
  99. break;
  100. }
  101. case XATTR_ACL_ACCESS:
  102. #ifdef CONFIG_CIFS_POSIX
  103. if (!value)
  104. goto out;
  105. if (sb->s_flags & MS_POSIXACL)
  106. rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
  107. value, (const int)size,
  108. ACL_TYPE_ACCESS, cifs_sb->local_nls,
  109. cifs_remap(cifs_sb));
  110. #endif /* CONFIG_CIFS_POSIX */
  111. break;
  112. case XATTR_ACL_DEFAULT:
  113. #ifdef CONFIG_CIFS_POSIX
  114. if (!value)
  115. goto out;
  116. if (sb->s_flags & MS_POSIXACL)
  117. rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
  118. value, (const int)size,
  119. ACL_TYPE_DEFAULT, cifs_sb->local_nls,
  120. cifs_remap(cifs_sb));
  121. #endif /* CONFIG_CIFS_POSIX */
  122. break;
  123. }
  124. out:
  125. kfree(full_path);
  126. free_xid(xid);
  127. cifs_put_tlink(tlink);
  128. return rc;
  129. }
  130. static int cifs_xattr_get(const struct xattr_handler *handler,
  131. struct dentry *dentry, struct inode *inode,
  132. const char *name, void *value, size_t size)
  133. {
  134. ssize_t rc = -EOPNOTSUPP;
  135. unsigned int xid;
  136. struct super_block *sb = dentry->d_sb;
  137. struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  138. struct tcon_link *tlink;
  139. struct cifs_tcon *pTcon;
  140. char *full_path;
  141. tlink = cifs_sb_tlink(cifs_sb);
  142. if (IS_ERR(tlink))
  143. return PTR_ERR(tlink);
  144. pTcon = tlink_tcon(tlink);
  145. xid = get_xid();
  146. full_path = build_path_from_dentry(dentry);
  147. if (full_path == NULL) {
  148. rc = -ENOMEM;
  149. goto out;
  150. }
  151. /* return dos attributes as pseudo xattr */
  152. /* return alt name if available as pseudo attr */
  153. switch (handler->flags) {
  154. case XATTR_USER:
  155. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  156. goto out;
  157. if (pTcon->ses->server->ops->query_all_EAs)
  158. rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
  159. full_path, name, value, size,
  160. cifs_sb->local_nls, cifs_remap(cifs_sb));
  161. break;
  162. case XATTR_CIFS_ACL: {
  163. #ifdef CONFIG_CIFS_ACL
  164. u32 acllen;
  165. struct cifs_ntsd *pacl;
  166. if (pTcon->ses->server->ops->get_acl == NULL)
  167. goto out; /* rc already EOPNOTSUPP */
  168. pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
  169. inode, full_path, &acllen);
  170. if (IS_ERR(pacl)) {
  171. rc = PTR_ERR(pacl);
  172. cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
  173. __func__, rc);
  174. } else {
  175. if (value) {
  176. if (acllen > size)
  177. acllen = -ERANGE;
  178. else
  179. memcpy(value, pacl, acllen);
  180. }
  181. rc = acllen;
  182. kfree(pacl);
  183. }
  184. #endif /* CONFIG_CIFS_ACL */
  185. break;
  186. }
  187. case XATTR_ACL_ACCESS:
  188. #ifdef CONFIG_CIFS_POSIX
  189. if (sb->s_flags & MS_POSIXACL)
  190. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  191. value, size, ACL_TYPE_ACCESS,
  192. cifs_sb->local_nls,
  193. cifs_remap(cifs_sb));
  194. #endif /* CONFIG_CIFS_POSIX */
  195. break;
  196. case XATTR_ACL_DEFAULT:
  197. #ifdef CONFIG_CIFS_POSIX
  198. if (sb->s_flags & MS_POSIXACL)
  199. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  200. value, size, ACL_TYPE_DEFAULT,
  201. cifs_sb->local_nls,
  202. cifs_remap(cifs_sb));
  203. #endif /* CONFIG_CIFS_POSIX */
  204. break;
  205. }
  206. /* We could add an additional check for streams ie
  207. if proc/fs/cifs/streamstoxattr is set then
  208. search server for EAs or streams to
  209. returns as xattrs */
  210. if (rc == -EINVAL)
  211. rc = -EOPNOTSUPP;
  212. out:
  213. kfree(full_path);
  214. free_xid(xid);
  215. cifs_put_tlink(tlink);
  216. return rc;
  217. }
  218. ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
  219. {
  220. ssize_t rc = -EOPNOTSUPP;
  221. unsigned int xid;
  222. struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
  223. struct tcon_link *tlink;
  224. struct cifs_tcon *pTcon;
  225. char *full_path;
  226. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  227. return -EOPNOTSUPP;
  228. tlink = cifs_sb_tlink(cifs_sb);
  229. if (IS_ERR(tlink))
  230. return PTR_ERR(tlink);
  231. pTcon = tlink_tcon(tlink);
  232. xid = get_xid();
  233. full_path = build_path_from_dentry(direntry);
  234. if (full_path == NULL) {
  235. rc = -ENOMEM;
  236. goto list_ea_exit;
  237. }
  238. /* return dos attributes as pseudo xattr */
  239. /* return alt name if available as pseudo attr */
  240. /* if proc/fs/cifs/streamstoxattr is set then
  241. search server for EAs or streams to
  242. returns as xattrs */
  243. if (pTcon->ses->server->ops->query_all_EAs)
  244. rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
  245. full_path, NULL, data, buf_size,
  246. cifs_sb->local_nls, cifs_remap(cifs_sb));
  247. list_ea_exit:
  248. kfree(full_path);
  249. free_xid(xid);
  250. cifs_put_tlink(tlink);
  251. return rc;
  252. }
  253. static const struct xattr_handler cifs_user_xattr_handler = {
  254. .prefix = XATTR_USER_PREFIX,
  255. .flags = XATTR_USER,
  256. .get = cifs_xattr_get,
  257. .set = cifs_xattr_set,
  258. };
  259. /* os2.* attributes are treated like user.* attributes */
  260. static const struct xattr_handler cifs_os2_xattr_handler = {
  261. .prefix = XATTR_OS2_PREFIX,
  262. .flags = XATTR_USER,
  263. .get = cifs_xattr_get,
  264. .set = cifs_xattr_set,
  265. };
  266. static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
  267. .name = CIFS_XATTR_CIFS_ACL,
  268. .flags = XATTR_CIFS_ACL,
  269. .get = cifs_xattr_get,
  270. .set = cifs_xattr_set,
  271. };
  272. static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
  273. .name = XATTR_NAME_POSIX_ACL_ACCESS,
  274. .flags = XATTR_ACL_ACCESS,
  275. .get = cifs_xattr_get,
  276. .set = cifs_xattr_set,
  277. };
  278. static const struct xattr_handler cifs_posix_acl_default_xattr_handler = {
  279. .name = XATTR_NAME_POSIX_ACL_DEFAULT,
  280. .flags = XATTR_ACL_DEFAULT,
  281. .get = cifs_xattr_get,
  282. .set = cifs_xattr_set,
  283. };
  284. const struct xattr_handler *cifs_xattr_handlers[] = {
  285. &cifs_user_xattr_handler,
  286. &cifs_os2_xattr_handler,
  287. &cifs_cifs_acl_xattr_handler,
  288. &cifs_posix_acl_access_xattr_handler,
  289. &cifs_posix_acl_default_xattr_handler,
  290. NULL
  291. };