xattr.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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 "cifsfs.h"
  25. #include "cifspdu.h"
  26. #include "cifsglob.h"
  27. #include "cifsproto.h"
  28. #include "cifs_debug.h"
  29. #define MAX_EA_VALUE_SIZE 65535
  30. #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
  31. #define CIFS_XATTR_USER_PREFIX "user."
  32. #define CIFS_XATTR_SYSTEM_PREFIX "system."
  33. #define CIFS_XATTR_OS2_PREFIX "os2."
  34. #define CIFS_XATTR_SECURITY_PREFIX ".security"
  35. #define CIFS_XATTR_TRUSTED_PREFIX "trusted."
  36. #define XATTR_TRUSTED_PREFIX_LEN 8
  37. #define XATTR_SECURITY_PREFIX_LEN 9
  38. /* BB need to add server (Samba e.g) support for security and trusted prefix */
  39. int cifs_removexattr(struct dentry *direntry, const char *ea_name)
  40. {
  41. int rc = -EOPNOTSUPP;
  42. #ifdef CONFIG_CIFS_XATTR
  43. int xid;
  44. struct cifs_sb_info *cifs_sb;
  45. struct tcon_link *tlink;
  46. struct cifsTconInfo *pTcon;
  47. struct super_block *sb;
  48. char *full_path = NULL;
  49. if (direntry == NULL)
  50. return -EIO;
  51. if (direntry->d_inode == NULL)
  52. return -EIO;
  53. sb = direntry->d_inode->i_sb;
  54. if (sb == NULL)
  55. return -EIO;
  56. cifs_sb = CIFS_SB(sb);
  57. tlink = cifs_sb_tlink(cifs_sb);
  58. if (IS_ERR(tlink))
  59. return PTR_ERR(tlink);
  60. pTcon = tlink_tcon(tlink);
  61. xid = GetXid();
  62. full_path = build_path_from_dentry(direntry);
  63. if (full_path == NULL) {
  64. rc = -ENOMEM;
  65. goto remove_ea_exit;
  66. }
  67. if (ea_name == NULL) {
  68. cFYI(1, "Null xattr names not supported");
  69. } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
  70. && (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
  71. cFYI(1,
  72. "illegal xattr request %s (only user namespace supported)",
  73. ea_name);
  74. /* BB what if no namespace prefix? */
  75. /* Should we just pass them to server, except for
  76. system and perhaps security prefixes? */
  77. } else {
  78. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  79. goto remove_ea_exit;
  80. ea_name += 5; /* skip past user. prefix */
  81. rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
  82. (__u16)0, cifs_sb->local_nls,
  83. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  84. }
  85. remove_ea_exit:
  86. kfree(full_path);
  87. FreeXid(xid);
  88. cifs_put_tlink(tlink);
  89. #endif
  90. return rc;
  91. }
  92. int cifs_setxattr(struct dentry *direntry, const char *ea_name,
  93. const void *ea_value, size_t value_size, int flags)
  94. {
  95. int rc = -EOPNOTSUPP;
  96. #ifdef CONFIG_CIFS_XATTR
  97. int xid;
  98. struct cifs_sb_info *cifs_sb;
  99. struct tcon_link *tlink;
  100. struct cifsTconInfo *pTcon;
  101. struct super_block *sb;
  102. char *full_path;
  103. if (direntry == NULL)
  104. return -EIO;
  105. if (direntry->d_inode == NULL)
  106. return -EIO;
  107. sb = direntry->d_inode->i_sb;
  108. if (sb == NULL)
  109. return -EIO;
  110. cifs_sb = CIFS_SB(sb);
  111. tlink = cifs_sb_tlink(cifs_sb);
  112. if (IS_ERR(tlink))
  113. return PTR_ERR(tlink);
  114. pTcon = tlink_tcon(tlink);
  115. xid = GetXid();
  116. full_path = build_path_from_dentry(direntry);
  117. if (full_path == NULL) {
  118. rc = -ENOMEM;
  119. goto set_ea_exit;
  120. }
  121. /* return dos attributes as pseudo xattr */
  122. /* return alt name if available as pseudo attr */
  123. /* if proc/fs/cifs/streamstoxattr is set then
  124. search server for EAs or streams to
  125. returns as xattrs */
  126. if (value_size > MAX_EA_VALUE_SIZE) {
  127. cFYI(1, "size of EA value too large");
  128. rc = -EOPNOTSUPP;
  129. goto set_ea_exit;
  130. }
  131. if (ea_name == NULL) {
  132. cFYI(1, "Null xattr names not supported");
  133. } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
  134. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  135. goto set_ea_exit;
  136. if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0)
  137. cFYI(1, "attempt to set cifs inode metadata");
  138. ea_name += 5; /* skip past user. prefix */
  139. rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
  140. (__u16)value_size, cifs_sb->local_nls,
  141. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  142. } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
  143. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  144. goto set_ea_exit;
  145. ea_name += 4; /* skip past os2. prefix */
  146. rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
  147. (__u16)value_size, cifs_sb->local_nls,
  148. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  149. } else {
  150. int temp;
  151. temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
  152. strlen(POSIX_ACL_XATTR_ACCESS));
  153. if (temp == 0) {
  154. #ifdef CONFIG_CIFS_POSIX
  155. if (sb->s_flags & MS_POSIXACL)
  156. rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
  157. ea_value, (const int)value_size,
  158. ACL_TYPE_ACCESS, cifs_sb->local_nls,
  159. cifs_sb->mnt_cifs_flags &
  160. CIFS_MOUNT_MAP_SPECIAL_CHR);
  161. cFYI(1, "set POSIX ACL rc %d", rc);
  162. #else
  163. cFYI(1, "set POSIX ACL not supported");
  164. #endif
  165. } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
  166. strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
  167. #ifdef CONFIG_CIFS_POSIX
  168. if (sb->s_flags & MS_POSIXACL)
  169. rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
  170. ea_value, (const int)value_size,
  171. ACL_TYPE_DEFAULT, cifs_sb->local_nls,
  172. cifs_sb->mnt_cifs_flags &
  173. CIFS_MOUNT_MAP_SPECIAL_CHR);
  174. cFYI(1, "set POSIX default ACL rc %d", rc);
  175. #else
  176. cFYI(1, "set default POSIX ACL not supported");
  177. #endif
  178. } else {
  179. cFYI(1, "illegal xattr request %s (only user namespace"
  180. " supported)", ea_name);
  181. /* BB what if no namespace prefix? */
  182. /* Should we just pass them to server, except for
  183. system and perhaps security prefixes? */
  184. }
  185. }
  186. set_ea_exit:
  187. kfree(full_path);
  188. FreeXid(xid);
  189. cifs_put_tlink(tlink);
  190. #endif
  191. return rc;
  192. }
  193. ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
  194. void *ea_value, size_t buf_size)
  195. {
  196. ssize_t rc = -EOPNOTSUPP;
  197. #ifdef CONFIG_CIFS_XATTR
  198. int xid;
  199. struct cifs_sb_info *cifs_sb;
  200. struct tcon_link *tlink;
  201. struct cifsTconInfo *pTcon;
  202. struct super_block *sb;
  203. char *full_path;
  204. if (direntry == NULL)
  205. return -EIO;
  206. if (direntry->d_inode == NULL)
  207. return -EIO;
  208. sb = direntry->d_inode->i_sb;
  209. if (sb == NULL)
  210. return -EIO;
  211. cifs_sb = CIFS_SB(sb);
  212. tlink = cifs_sb_tlink(cifs_sb);
  213. if (IS_ERR(tlink))
  214. return PTR_ERR(tlink);
  215. pTcon = tlink_tcon(tlink);
  216. xid = GetXid();
  217. full_path = build_path_from_dentry(direntry);
  218. if (full_path == NULL) {
  219. rc = -ENOMEM;
  220. goto get_ea_exit;
  221. }
  222. /* return dos attributes as pseudo xattr */
  223. /* return alt name if available as pseudo attr */
  224. if (ea_name == NULL) {
  225. cFYI(1, "Null xattr names not supported");
  226. } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
  227. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  228. goto get_ea_exit;
  229. if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
  230. cFYI(1, "attempt to query cifs inode metadata");
  231. /* revalidate/getattr then populate from inode */
  232. } /* BB add else when above is implemented */
  233. ea_name += 5; /* skip past user. prefix */
  234. rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
  235. buf_size, cifs_sb->local_nls,
  236. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  237. } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
  238. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  239. goto get_ea_exit;
  240. ea_name += 4; /* skip past os2. prefix */
  241. rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
  242. buf_size, cifs_sb->local_nls,
  243. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  244. } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
  245. strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
  246. #ifdef CONFIG_CIFS_POSIX
  247. if (sb->s_flags & MS_POSIXACL)
  248. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  249. ea_value, buf_size, ACL_TYPE_ACCESS,
  250. cifs_sb->local_nls,
  251. cifs_sb->mnt_cifs_flags &
  252. CIFS_MOUNT_MAP_SPECIAL_CHR);
  253. #ifdef CONFIG_CIFS_EXPERIMENTAL
  254. else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
  255. __u16 fid;
  256. int oplock = 0;
  257. struct cifs_ntsd *pacl = NULL;
  258. __u32 buflen = 0;
  259. if (experimEnabled)
  260. rc = CIFSSMBOpen(xid, pTcon, full_path,
  261. FILE_OPEN, GENERIC_READ, 0, &fid,
  262. &oplock, NULL, cifs_sb->local_nls,
  263. cifs_sb->mnt_cifs_flags &
  264. CIFS_MOUNT_MAP_SPECIAL_CHR);
  265. /* else rc is EOPNOTSUPP from above */
  266. if (rc == 0) {
  267. rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl,
  268. &buflen);
  269. CIFSSMBClose(xid, pTcon, fid);
  270. }
  271. }
  272. #endif /* EXPERIMENTAL */
  273. #else
  274. cFYI(1, "query POSIX ACL not supported yet");
  275. #endif /* CONFIG_CIFS_POSIX */
  276. } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
  277. strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
  278. #ifdef CONFIG_CIFS_POSIX
  279. if (sb->s_flags & MS_POSIXACL)
  280. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  281. ea_value, buf_size, ACL_TYPE_DEFAULT,
  282. cifs_sb->local_nls,
  283. cifs_sb->mnt_cifs_flags &
  284. CIFS_MOUNT_MAP_SPECIAL_CHR);
  285. #else
  286. cFYI(1, "query POSIX default ACL not supported yet");
  287. #endif
  288. } else if (strncmp(ea_name,
  289. CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
  290. cFYI(1, "Trusted xattr namespace not supported yet");
  291. } else if (strncmp(ea_name,
  292. CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
  293. cFYI(1, "Security xattr namespace not supported yet");
  294. } else
  295. cFYI(1,
  296. "illegal xattr request %s (only user namespace supported)",
  297. ea_name);
  298. /* We could add an additional check for streams ie
  299. if proc/fs/cifs/streamstoxattr is set then
  300. search server for EAs or streams to
  301. returns as xattrs */
  302. if (rc == -EINVAL)
  303. rc = -EOPNOTSUPP;
  304. get_ea_exit:
  305. kfree(full_path);
  306. FreeXid(xid);
  307. cifs_put_tlink(tlink);
  308. #endif
  309. return rc;
  310. }
  311. ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
  312. {
  313. ssize_t rc = -EOPNOTSUPP;
  314. #ifdef CONFIG_CIFS_XATTR
  315. int xid;
  316. struct cifs_sb_info *cifs_sb;
  317. struct tcon_link *tlink;
  318. struct cifsTconInfo *pTcon;
  319. struct super_block *sb;
  320. char *full_path;
  321. if (direntry == NULL)
  322. return -EIO;
  323. if (direntry->d_inode == NULL)
  324. return -EIO;
  325. sb = direntry->d_inode->i_sb;
  326. if (sb == NULL)
  327. return -EIO;
  328. cifs_sb = CIFS_SB(sb);
  329. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  330. return -EOPNOTSUPP;
  331. tlink = cifs_sb_tlink(cifs_sb);
  332. if (IS_ERR(tlink))
  333. return PTR_ERR(tlink);
  334. pTcon = tlink_tcon(tlink);
  335. xid = GetXid();
  336. full_path = build_path_from_dentry(direntry);
  337. if (full_path == NULL) {
  338. rc = -ENOMEM;
  339. goto list_ea_exit;
  340. }
  341. /* return dos attributes as pseudo xattr */
  342. /* return alt name if available as pseudo attr */
  343. /* if proc/fs/cifs/streamstoxattr is set then
  344. search server for EAs or streams to
  345. returns as xattrs */
  346. rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
  347. buf_size, cifs_sb->local_nls,
  348. cifs_sb->mnt_cifs_flags &
  349. CIFS_MOUNT_MAP_SPECIAL_CHR);
  350. list_ea_exit:
  351. kfree(full_path);
  352. FreeXid(xid);
  353. cifs_put_tlink(tlink);
  354. #endif
  355. return rc;
  356. }