xattr.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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_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 & SB_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 & SB_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. }
  167. static int cifs_xattr_get(const struct xattr_handler *handler,
  168. struct dentry *dentry, struct inode *inode,
  169. const char *name, void *value, size_t size)
  170. {
  171. ssize_t rc = -EOPNOTSUPP;
  172. unsigned int xid;
  173. struct super_block *sb = dentry->d_sb;
  174. struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  175. struct tcon_link *tlink;
  176. struct cifs_tcon *pTcon;
  177. char *full_path;
  178. tlink = cifs_sb_tlink(cifs_sb);
  179. if (IS_ERR(tlink))
  180. return PTR_ERR(tlink);
  181. pTcon = tlink_tcon(tlink);
  182. xid = get_xid();
  183. full_path = build_path_from_dentry(dentry);
  184. if (full_path == NULL) {
  185. rc = -ENOMEM;
  186. goto out;
  187. }
  188. /* return alt name if available as pseudo attr */
  189. switch (handler->flags) {
  190. case XATTR_USER:
  191. cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
  192. if (strcmp(name, CIFS_XATTR_ATTRIB) == 0) {
  193. rc = cifs_attrib_get(dentry, inode, value, size);
  194. break;
  195. } else if (strcmp(name, CIFS_XATTR_CREATETIME) == 0) {
  196. rc = cifs_creation_time_get(dentry, inode, value, size);
  197. break;
  198. }
  199. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  200. goto out;
  201. if (pTcon->ses->server->ops->query_all_EAs)
  202. rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
  203. full_path, name, value, size, cifs_sb);
  204. break;
  205. case XATTR_CIFS_ACL: {
  206. #ifdef CONFIG_CIFS_ACL
  207. u32 acllen;
  208. struct cifs_ntsd *pacl;
  209. if (pTcon->ses->server->ops->get_acl == NULL)
  210. goto out; /* rc already EOPNOTSUPP */
  211. pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
  212. inode, full_path, &acllen);
  213. if (IS_ERR(pacl)) {
  214. rc = PTR_ERR(pacl);
  215. cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
  216. __func__, rc);
  217. } else {
  218. if (value) {
  219. if (acllen > size)
  220. acllen = -ERANGE;
  221. else
  222. memcpy(value, pacl, acllen);
  223. }
  224. rc = acllen;
  225. kfree(pacl);
  226. }
  227. #endif /* CONFIG_CIFS_ACL */
  228. break;
  229. }
  230. case XATTR_ACL_ACCESS:
  231. #ifdef CONFIG_CIFS_POSIX
  232. if (sb->s_flags & SB_POSIXACL)
  233. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  234. value, size, ACL_TYPE_ACCESS,
  235. cifs_sb->local_nls,
  236. cifs_remap(cifs_sb));
  237. #endif /* CONFIG_CIFS_POSIX */
  238. break;
  239. case XATTR_ACL_DEFAULT:
  240. #ifdef CONFIG_CIFS_POSIX
  241. if (sb->s_flags & SB_POSIXACL)
  242. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  243. value, size, ACL_TYPE_DEFAULT,
  244. cifs_sb->local_nls,
  245. cifs_remap(cifs_sb));
  246. #endif /* CONFIG_CIFS_POSIX */
  247. break;
  248. }
  249. /* We could add an additional check for streams ie
  250. if proc/fs/cifs/streamstoxattr is set then
  251. search server for EAs or streams to
  252. returns as xattrs */
  253. if (rc == -EINVAL)
  254. rc = -EOPNOTSUPP;
  255. out:
  256. kfree(full_path);
  257. free_xid(xid);
  258. cifs_put_tlink(tlink);
  259. return rc;
  260. }
  261. ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
  262. {
  263. ssize_t rc = -EOPNOTSUPP;
  264. unsigned int xid;
  265. struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
  266. struct tcon_link *tlink;
  267. struct cifs_tcon *pTcon;
  268. char *full_path;
  269. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  270. return -EOPNOTSUPP;
  271. tlink = cifs_sb_tlink(cifs_sb);
  272. if (IS_ERR(tlink))
  273. return PTR_ERR(tlink);
  274. pTcon = tlink_tcon(tlink);
  275. xid = get_xid();
  276. full_path = build_path_from_dentry(direntry);
  277. if (full_path == NULL) {
  278. rc = -ENOMEM;
  279. goto list_ea_exit;
  280. }
  281. /* return dos attributes as pseudo xattr */
  282. /* return alt name if available as pseudo attr */
  283. /* if proc/fs/cifs/streamstoxattr is set then
  284. search server for EAs or streams to
  285. returns as xattrs */
  286. if (pTcon->ses->server->ops->query_all_EAs)
  287. rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
  288. full_path, NULL, data, buf_size, cifs_sb);
  289. list_ea_exit:
  290. kfree(full_path);
  291. free_xid(xid);
  292. cifs_put_tlink(tlink);
  293. return rc;
  294. }
  295. static const struct xattr_handler cifs_user_xattr_handler = {
  296. .prefix = XATTR_USER_PREFIX,
  297. .flags = XATTR_USER,
  298. .get = cifs_xattr_get,
  299. .set = cifs_xattr_set,
  300. };
  301. /* os2.* attributes are treated like user.* attributes */
  302. static const struct xattr_handler cifs_os2_xattr_handler = {
  303. .prefix = XATTR_OS2_PREFIX,
  304. .flags = XATTR_USER,
  305. .get = cifs_xattr_get,
  306. .set = cifs_xattr_set,
  307. };
  308. static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
  309. .name = CIFS_XATTR_CIFS_ACL,
  310. .flags = XATTR_CIFS_ACL,
  311. .get = cifs_xattr_get,
  312. .set = cifs_xattr_set,
  313. };
  314. static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
  315. .name = XATTR_NAME_POSIX_ACL_ACCESS,
  316. .flags = XATTR_ACL_ACCESS,
  317. .get = cifs_xattr_get,
  318. .set = cifs_xattr_set,
  319. };
  320. static const struct xattr_handler cifs_posix_acl_default_xattr_handler = {
  321. .name = XATTR_NAME_POSIX_ACL_DEFAULT,
  322. .flags = XATTR_ACL_DEFAULT,
  323. .get = cifs_xattr_get,
  324. .set = cifs_xattr_set,
  325. };
  326. const struct xattr_handler *cifs_xattr_handlers[] = {
  327. &cifs_user_xattr_handler,
  328. &cifs_os2_xattr_handler,
  329. &cifs_cifs_acl_xattr_handler,
  330. &cifs_posix_acl_access_xattr_handler,
  331. &cifs_posix_acl_default_xattr_handler,
  332. NULL
  333. };