xattr.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  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. #define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */
  35. #define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */
  36. /* BB need to add server (Samba e.g) support for security and trusted prefix */
  37. enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT };
  38. static int cifs_xattr_set(const struct xattr_handler *handler,
  39. struct dentry *dentry, struct inode *inode,
  40. const char *name, const void *value,
  41. size_t size, int flags)
  42. {
  43. int rc = -EOPNOTSUPP;
  44. unsigned int xid;
  45. struct super_block *sb = dentry->d_sb;
  46. struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  47. struct tcon_link *tlink;
  48. struct cifs_tcon *pTcon;
  49. char *full_path;
  50. tlink = cifs_sb_tlink(cifs_sb);
  51. if (IS_ERR(tlink))
  52. return PTR_ERR(tlink);
  53. pTcon = tlink_tcon(tlink);
  54. xid = get_xid();
  55. full_path = build_path_from_dentry(dentry);
  56. if (full_path == NULL) {
  57. rc = -ENOMEM;
  58. goto out;
  59. }
  60. /* return dos attributes as pseudo xattr */
  61. /* return alt name if available as pseudo attr */
  62. /* if proc/fs/cifs/streamstoxattr is set then
  63. search server for EAs or streams to
  64. returns as xattrs */
  65. if (size > MAX_EA_VALUE_SIZE) {
  66. cifs_dbg(FYI, "size of EA value too large\n");
  67. rc = -EOPNOTSUPP;
  68. goto out;
  69. }
  70. switch (handler->flags) {
  71. case XATTR_USER:
  72. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  73. goto out;
  74. if (pTcon->ses->server->ops->set_EA)
  75. rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
  76. full_path, name, value, (__u16)size,
  77. cifs_sb->local_nls, cifs_remap(cifs_sb));
  78. break;
  79. case XATTR_CIFS_ACL: {
  80. #ifdef CONFIG_CIFS_ACL
  81. struct cifs_ntsd *pacl;
  82. if (!value)
  83. goto out;
  84. pacl = kmalloc(size, GFP_KERNEL);
  85. if (!pacl) {
  86. rc = -ENOMEM;
  87. } else {
  88. memcpy(pacl, value, size);
  89. if (value &&
  90. pTcon->ses->server->ops->set_acl)
  91. rc = pTcon->ses->server->ops->set_acl(pacl,
  92. size, inode,
  93. full_path, CIFS_ACL_DACL);
  94. else
  95. rc = -EOPNOTSUPP;
  96. if (rc == 0) /* force revalidate of the inode */
  97. CIFS_I(inode)->time = 0;
  98. kfree(pacl);
  99. }
  100. #endif /* CONFIG_CIFS_ACL */
  101. break;
  102. }
  103. case XATTR_ACL_ACCESS:
  104. #ifdef CONFIG_CIFS_POSIX
  105. if (!value)
  106. goto out;
  107. if (sb->s_flags & MS_POSIXACL)
  108. rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
  109. value, (const int)size,
  110. ACL_TYPE_ACCESS, cifs_sb->local_nls,
  111. cifs_remap(cifs_sb));
  112. #endif /* CONFIG_CIFS_POSIX */
  113. break;
  114. case XATTR_ACL_DEFAULT:
  115. #ifdef CONFIG_CIFS_POSIX
  116. if (!value)
  117. goto out;
  118. if (sb->s_flags & MS_POSIXACL)
  119. rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
  120. value, (const int)size,
  121. ACL_TYPE_DEFAULT, cifs_sb->local_nls,
  122. cifs_remap(cifs_sb));
  123. #endif /* CONFIG_CIFS_POSIX */
  124. break;
  125. }
  126. out:
  127. kfree(full_path);
  128. free_xid(xid);
  129. cifs_put_tlink(tlink);
  130. return rc;
  131. }
  132. static int cifs_attrib_get(struct dentry *dentry,
  133. struct inode *inode, void *value,
  134. size_t size)
  135. {
  136. ssize_t rc;
  137. __u32 *pattribute;
  138. rc = cifs_revalidate_dentry_attr(dentry);
  139. if (rc)
  140. return rc;
  141. if ((value == NULL) || (size == 0))
  142. return sizeof(__u32);
  143. else if (size < sizeof(__u32))
  144. return -ERANGE;
  145. /* return dos attributes as pseudo xattr */
  146. pattribute = (__u32 *)value;
  147. *pattribute = CIFS_I(inode)->cifsAttrs;
  148. return sizeof(__u32);
  149. }
  150. static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
  151. void *value, size_t size)
  152. {
  153. ssize_t rc;
  154. __u64 * pcreatetime;
  155. rc = cifs_revalidate_dentry_attr(dentry);
  156. if (rc)
  157. return rc;
  158. if ((value == NULL) || (size == 0))
  159. return sizeof(__u64);
  160. else if (size < sizeof(__u64))
  161. return -ERANGE;
  162. /* return dos attributes as pseudo xattr */
  163. pcreatetime = (__u64 *)value;
  164. *pcreatetime = CIFS_I(inode)->createtime;
  165. return sizeof(__u64);
  166. return rc;
  167. }
  168. static int cifs_xattr_get(const struct xattr_handler *handler,
  169. struct dentry *dentry, struct inode *inode,
  170. const char *name, void *value, size_t size)
  171. {
  172. ssize_t rc = -EOPNOTSUPP;
  173. unsigned int xid;
  174. struct super_block *sb = dentry->d_sb;
  175. struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  176. struct tcon_link *tlink;
  177. struct cifs_tcon *pTcon;
  178. char *full_path;
  179. tlink = cifs_sb_tlink(cifs_sb);
  180. if (IS_ERR(tlink))
  181. return PTR_ERR(tlink);
  182. pTcon = tlink_tcon(tlink);
  183. xid = get_xid();
  184. full_path = build_path_from_dentry(dentry);
  185. if (full_path == NULL) {
  186. rc = -ENOMEM;
  187. goto out;
  188. }
  189. /* return alt name if available as pseudo attr */
  190. switch (handler->flags) {
  191. case XATTR_USER:
  192. cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
  193. if (strcmp(name, CIFS_XATTR_ATTRIB) == 0) {
  194. rc = cifs_attrib_get(dentry, inode, value, size);
  195. break;
  196. } else if (strcmp(name, CIFS_XATTR_CREATETIME) == 0) {
  197. rc = cifs_creation_time_get(dentry, inode, value, size);
  198. break;
  199. }
  200. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  201. goto out;
  202. if (pTcon->ses->server->ops->query_all_EAs)
  203. rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
  204. full_path, name, value, size,
  205. cifs_sb->local_nls, cifs_remap(cifs_sb));
  206. break;
  207. case XATTR_CIFS_ACL: {
  208. #ifdef CONFIG_CIFS_ACL
  209. u32 acllen;
  210. struct cifs_ntsd *pacl;
  211. if (pTcon->ses->server->ops->get_acl == NULL)
  212. goto out; /* rc already EOPNOTSUPP */
  213. pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
  214. inode, full_path, &acllen);
  215. if (IS_ERR(pacl)) {
  216. rc = PTR_ERR(pacl);
  217. cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
  218. __func__, rc);
  219. } else {
  220. if (value) {
  221. if (acllen > size)
  222. acllen = -ERANGE;
  223. else
  224. memcpy(value, pacl, acllen);
  225. }
  226. rc = acllen;
  227. kfree(pacl);
  228. }
  229. #endif /* CONFIG_CIFS_ACL */
  230. break;
  231. }
  232. case XATTR_ACL_ACCESS:
  233. #ifdef CONFIG_CIFS_POSIX
  234. if (sb->s_flags & MS_POSIXACL)
  235. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  236. value, size, ACL_TYPE_ACCESS,
  237. cifs_sb->local_nls,
  238. cifs_remap(cifs_sb));
  239. #endif /* CONFIG_CIFS_POSIX */
  240. break;
  241. case XATTR_ACL_DEFAULT:
  242. #ifdef CONFIG_CIFS_POSIX
  243. if (sb->s_flags & MS_POSIXACL)
  244. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  245. value, size, ACL_TYPE_DEFAULT,
  246. cifs_sb->local_nls,
  247. cifs_remap(cifs_sb));
  248. #endif /* CONFIG_CIFS_POSIX */
  249. break;
  250. }
  251. /* We could add an additional check for streams ie
  252. if proc/fs/cifs/streamstoxattr is set then
  253. search server for EAs or streams to
  254. returns as xattrs */
  255. if (rc == -EINVAL)
  256. rc = -EOPNOTSUPP;
  257. out:
  258. kfree(full_path);
  259. free_xid(xid);
  260. cifs_put_tlink(tlink);
  261. return rc;
  262. }
  263. ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
  264. {
  265. ssize_t rc = -EOPNOTSUPP;
  266. unsigned int xid;
  267. struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
  268. struct tcon_link *tlink;
  269. struct cifs_tcon *pTcon;
  270. char *full_path;
  271. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  272. return -EOPNOTSUPP;
  273. tlink = cifs_sb_tlink(cifs_sb);
  274. if (IS_ERR(tlink))
  275. return PTR_ERR(tlink);
  276. pTcon = tlink_tcon(tlink);
  277. xid = get_xid();
  278. full_path = build_path_from_dentry(direntry);
  279. if (full_path == NULL) {
  280. rc = -ENOMEM;
  281. goto list_ea_exit;
  282. }
  283. /* return dos attributes as pseudo xattr */
  284. /* return alt name if available as pseudo attr */
  285. /* if proc/fs/cifs/streamstoxattr is set then
  286. search server for EAs or streams to
  287. returns as xattrs */
  288. if (pTcon->ses->server->ops->query_all_EAs)
  289. rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
  290. full_path, NULL, data, buf_size,
  291. cifs_sb->local_nls, cifs_remap(cifs_sb));
  292. list_ea_exit:
  293. kfree(full_path);
  294. free_xid(xid);
  295. cifs_put_tlink(tlink);
  296. return rc;
  297. }
  298. static const struct xattr_handler cifs_user_xattr_handler = {
  299. .prefix = XATTR_USER_PREFIX,
  300. .flags = XATTR_USER,
  301. .get = cifs_xattr_get,
  302. .set = cifs_xattr_set,
  303. };
  304. /* os2.* attributes are treated like user.* attributes */
  305. static const struct xattr_handler cifs_os2_xattr_handler = {
  306. .prefix = XATTR_OS2_PREFIX,
  307. .flags = XATTR_USER,
  308. .get = cifs_xattr_get,
  309. .set = cifs_xattr_set,
  310. };
  311. static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
  312. .name = CIFS_XATTR_CIFS_ACL,
  313. .flags = XATTR_CIFS_ACL,
  314. .get = cifs_xattr_get,
  315. .set = cifs_xattr_set,
  316. };
  317. static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
  318. .name = XATTR_NAME_POSIX_ACL_ACCESS,
  319. .flags = XATTR_ACL_ACCESS,
  320. .get = cifs_xattr_get,
  321. .set = cifs_xattr_set,
  322. };
  323. static const struct xattr_handler cifs_posix_acl_default_xattr_handler = {
  324. .name = XATTR_NAME_POSIX_ACL_DEFAULT,
  325. .flags = XATTR_ACL_DEFAULT,
  326. .get = cifs_xattr_get,
  327. .set = cifs_xattr_set,
  328. };
  329. const struct xattr_handler *cifs_xattr_handlers[] = {
  330. &cifs_user_xattr_handler,
  331. &cifs_os2_xattr_handler,
  332. &cifs_cifs_acl_xattr_handler,
  333. &cifs_posix_acl_access_xattr_handler,
  334. &cifs_posix_acl_default_xattr_handler,
  335. NULL
  336. };