xattr.c 11 KB

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