xattr.c 11 KB

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