blob: 721c6db6fa8157610a57337a9728a52713cae1ec [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/xattr.c
3 *
Steve French79a58d12007-07-06 22:44:50 +00004 * Copyright (c) International Business Machines Corp., 2003, 2007
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * 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
22#include <linux/fs.h>
23#include <linux/posix_acl_xattr.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090024#include <linux/slab.h>
Mimi Zoharf995e742011-08-11 16:00:47 -040025#include <linux/xattr.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include "cifsfs.h"
27#include "cifspdu.h"
28#include "cifsglob.h"
29#include "cifsproto.h"
30#include "cifs_debug.h"
Steve French2baa2682014-09-27 02:19:01 -050031#include "cifs_fs_sb.h"
32#include "cifs_unicode.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#define MAX_EA_VALUE_SIZE 65535
35#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -060036#define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
Mimi Zoharf995e742011-08-11 16:00:47 -040037
Linus Torvalds1da177e2005-04-16 15:20:36 -070038/* BB need to add server (Samba e.g) support for security and trusted prefix */
Steve French50c2f752007-07-13 00:33:32 +000039
Steve French79a58d12007-07-06 22:44:50 +000040int cifs_removexattr(struct dentry *direntry, const char *ea_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -070041{
42 int rc = -EOPNOTSUPP;
43#ifdef CONFIG_CIFS_XATTR
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +040044 unsigned int xid;
Al Viro5fdccfe2016-04-10 17:07:33 -040045 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -040046 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +000047 struct cifs_tcon *pTcon;
Jeff Layton7ffec372010-09-29 19:51:11 -040048 char *full_path = NULL;
Steve French79a58d12007-07-06 22:44:50 +000049
Jeff Layton7ffec372010-09-29 19:51:11 -040050 tlink = cifs_sb_tlink(cifs_sb);
51 if (IS_ERR(tlink))
52 return PTR_ERR(tlink);
53 pTcon = tlink_tcon(tlink);
54
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +040055 xid = get_xid();
Steve French79a58d12007-07-06 22:44:50 +000056
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +000058 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +053059 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -040060 goto remove_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 }
Steve French79a58d12007-07-06 22:44:50 +000062 if (ea_name == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -050063 cifs_dbg(FYI, "Null xattr names not supported\n");
Andreas Gruenbacher534bb0c2016-04-14 00:30:15 +020064 } else if (!strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
Steve French79a58d12007-07-06 22:44:50 +000065 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 goto remove_ea_exit;
67
Mimi Zoharf995e742011-08-11 16:00:47 -040068 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
Steve French666753c2014-01-26 23:53:43 -060069 if (pTcon->ses->server->ops->set_EA)
70 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
71 full_path, ea_name, NULL, (__u16)0,
Steve French2baa2682014-09-27 02:19:01 -050072 cifs_sb->local_nls, cifs_remap(cifs_sb));
Andreas Gruenbacher534bb0c2016-04-14 00:30:15 +020073 } else if (!strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) {
74 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
75 goto remove_ea_exit;
76
77 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
78 if (pTcon->ses->server->ops->set_EA)
79 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
80 full_path, ea_name, NULL, (__u16)0,
81 cifs_sb->local_nls, cifs_remap(cifs_sb));
82 } else {
83 cifs_dbg(FYI,
84 "illegal xattr request %s (only user namespace supported)\n",
85 ea_name);
86 /* BB what if no namespace prefix? */
87 /* Should we just pass them to server, except for
88 system and perhaps security prefixes? */
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 }
90remove_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -080091 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +040092 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -040093 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094#endif
95 return rc;
96}
97
Steve French79a58d12007-07-06 22:44:50 +000098int cifs_setxattr(struct dentry *direntry, const char *ea_name,
99 const void *ea_value, size_t value_size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100{
101 int rc = -EOPNOTSUPP;
102#ifdef CONFIG_CIFS_XATTR
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400103 unsigned int xid;
Al Viro5fdccfe2016-04-10 17:07:33 -0400104 struct super_block *sb = direntry->d_sb;
105 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400106 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000107 struct cifs_tcon *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000108 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Jeff Layton7ffec372010-09-29 19:51:11 -0400110 tlink = cifs_sb_tlink(cifs_sb);
111 if (IS_ERR(tlink))
112 return PTR_ERR(tlink);
113 pTcon = tlink_tcon(tlink);
114
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400115 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000118 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530119 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400120 goto set_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 }
122 /* return dos attributes as pseudo xattr */
123 /* return alt name if available as pseudo attr */
124
125 /* if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000126 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 returns as xattrs */
Steve French79a58d12007-07-06 22:44:50 +0000128 if (value_size > MAX_EA_VALUE_SIZE) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500129 cifs_dbg(FYI, "size of EA value too large\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400130 rc = -EOPNOTSUPP;
131 goto set_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 }
133
Steve French79a58d12007-07-06 22:44:50 +0000134 if (ea_name == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500135 cifs_dbg(FYI, "Null xattr names not supported\n");
Mimi Zoharf995e742011-08-11 16:00:47 -0400136 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
137 == 0) {
Steve French79a58d12007-07-06 22:44:50 +0000138 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 goto set_ea_exit;
Andreas Gruenbacherd9a15482016-04-14 00:30:13 +0200140 if (strcmp(ea_name, CIFS_XATTR_DOS_ATTRIB) == 0)
Joe Perchesf96637b2013-05-04 22:12:25 -0500141 cifs_dbg(FYI, "attempt to set cifs inode metadata\n");
Steve Frenchad7a2922008-02-07 23:25:02 +0000142
Mimi Zoharf995e742011-08-11 16:00:47 -0400143 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
Steve French666753c2014-01-26 23:53:43 -0600144 if (pTcon->ses->server->ops->set_EA)
145 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
146 full_path, ea_name, ea_value, (__u16)value_size,
Steve French2baa2682014-09-27 02:19:01 -0500147 cifs_sb->local_nls, cifs_remap(cifs_sb));
Mimi Zoharf995e742011-08-11 16:00:47 -0400148 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)
149 == 0) {
Steve French79a58d12007-07-06 22:44:50 +0000150 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 goto set_ea_exit;
152
Mimi Zoharf995e742011-08-11 16:00:47 -0400153 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
Steve French666753c2014-01-26 23:53:43 -0600154 if (pTcon->ses->server->ops->set_EA)
155 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
156 full_path, ea_name, ea_value, (__u16)value_size,
Steve French2baa2682014-09-27 02:19:01 -0500157 cifs_sb->local_nls, cifs_remap(cifs_sb));
Andreas Gruenbacherd9a15482016-04-14 00:30:13 +0200158 } else if (strcmp(ea_name, CIFS_XATTR_CIFS_ACL) == 0) {
Santosh Nayakb0f8ef22012-03-02 11:47:26 +0530159#ifdef CONFIG_CIFS_ACL
160 struct cifs_ntsd *pacl;
Steve Frenchb73b9a42011-04-19 18:27:10 +0000161 pacl = kmalloc(value_size, GFP_KERNEL);
162 if (!pacl) {
Steve Frenchb73b9a42011-04-19 18:27:10 +0000163 rc = -ENOMEM;
164 } else {
Steve Frenchb73b9a42011-04-19 18:27:10 +0000165 memcpy(pacl, ea_value, value_size);
Steve French83e3bc22014-02-02 23:31:47 -0600166 if (pTcon->ses->server->ops->set_acl)
167 rc = pTcon->ses->server->ops->set_acl(pacl,
David Howells2b0143b2015-03-17 22:25:59 +0000168 value_size, d_inode(direntry),
Steve French83e3bc22014-02-02 23:31:47 -0600169 full_path, CIFS_ACL_DACL);
170 else
171 rc = -EOPNOTSUPP;
Steve Frenchb73b9a42011-04-19 18:27:10 +0000172 if (rc == 0) /* force revalidate of the inode */
David Howells2b0143b2015-03-17 22:25:59 +0000173 CIFS_I(d_inode(direntry))->time = 0;
Steve Frenchb73b9a42011-04-19 18:27:10 +0000174 kfree(pacl);
Santosh Nayakb0f8ef22012-03-02 11:47:26 +0530175 }
Steve Frenchb73b9a42011-04-19 18:27:10 +0000176#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500177 cifs_dbg(FYI, "Set CIFS ACL not supported yet\n");
Steve Frenchb73b9a42011-04-19 18:27:10 +0000178#endif /* CONFIG_CIFS_ACL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 } else {
Andreas Gruenbacherd9a15482016-04-14 00:30:13 +0200180 if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000182 if (sb->s_flags & MS_POSIXACL)
183 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
184 ea_value, (const int)value_size,
185 ACL_TYPE_ACCESS, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500186 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -0500187 cifs_dbg(FYI, "set POSIX ACL rc %d\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500189 cifs_dbg(FYI, "set POSIX ACL not supported\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190#endif
Andreas Gruenbacherd9a15482016-04-14 00:30:13 +0200191 } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000193 if (sb->s_flags & MS_POSIXACL)
194 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
195 ea_value, (const int)value_size,
Steve French737b7582005-04-28 22:41:06 -0700196 ACL_TYPE_DEFAULT, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500197 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -0500198 cifs_dbg(FYI, "set POSIX default ACL rc %d\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500200 cifs_dbg(FYI, "set default POSIX ACL not supported\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201#endif
202 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -0500203 cifs_dbg(FYI, "illegal xattr request %s (only user namespace supported)\n",
204 ea_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 /* BB what if no namespace prefix? */
Steve French79a58d12007-07-06 22:44:50 +0000206 /* Should we just pass them to server, except for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 system and perhaps security prefixes? */
208 }
209 }
210
211set_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800212 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400213 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400214 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215#endif
216 return rc;
217}
218
Al Viroce23e642016-04-11 00:48:00 -0400219ssize_t cifs_getxattr(struct dentry *direntry, struct inode *inode,
220 const char *ea_name, void *ea_value, size_t buf_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221{
222 ssize_t rc = -EOPNOTSUPP;
223#ifdef CONFIG_CIFS_XATTR
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400224 unsigned int xid;
Al Viro5fdccfe2016-04-10 17:07:33 -0400225 struct super_block *sb = direntry->d_sb;
226 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400227 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000228 struct cifs_tcon *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000229 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
Jeff Layton7ffec372010-09-29 19:51:11 -0400231 tlink = cifs_sb_tlink(cifs_sb);
232 if (IS_ERR(tlink))
233 return PTR_ERR(tlink);
234 pTcon = tlink_tcon(tlink);
235
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400236 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000239 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530240 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400241 goto get_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 }
243 /* return dos attributes as pseudo xattr */
244 /* return alt name if available as pseudo attr */
Steve French79a58d12007-07-06 22:44:50 +0000245 if (ea_name == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500246 cifs_dbg(FYI, "Null xattr names not supported\n");
Mimi Zoharf995e742011-08-11 16:00:47 -0400247 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
248 == 0) {
Steve French79a58d12007-07-06 22:44:50 +0000249 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 goto get_ea_exit;
251
Andreas Gruenbacherd9a15482016-04-14 00:30:13 +0200252 if (strcmp(ea_name, CIFS_XATTR_DOS_ATTRIB) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500253 cifs_dbg(FYI, "attempt to query cifs inode metadata\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 /* revalidate/getattr then populate from inode */
255 } /* BB add else when above is implemented */
Mimi Zoharf995e742011-08-11 16:00:47 -0400256 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
Steve French666753c2014-01-26 23:53:43 -0600257 if (pTcon->ses->server->ops->query_all_EAs)
258 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
259 full_path, ea_name, ea_value, buf_size,
Steve French2baa2682014-09-27 02:19:01 -0500260 cifs_sb->local_nls, cifs_remap(cifs_sb));
Mimi Zoharf995e742011-08-11 16:00:47 -0400261 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
Steve French79a58d12007-07-06 22:44:50 +0000262 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 goto get_ea_exit;
264
Mimi Zoharf995e742011-08-11 16:00:47 -0400265 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
Steve French666753c2014-01-26 23:53:43 -0600266 if (pTcon->ses->server->ops->query_all_EAs)
267 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
268 full_path, ea_name, ea_value, buf_size,
Steve French2baa2682014-09-27 02:19:01 -0500269 cifs_sb->local_nls, cifs_remap(cifs_sb));
Andreas Gruenbacherd9a15482016-04-14 00:30:13 +0200270 } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000272 if (sb->s_flags & MS_POSIXACL)
Steve French1da0c782005-04-28 22:41:04 -0700273 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
Steve French79a58d12007-07-06 22:44:50 +0000274 ea_value, buf_size, ACL_TYPE_ACCESS,
Steve French737b7582005-04-28 22:41:06 -0700275 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500276 cifs_remap(cifs_sb));
Steve French79a58d12007-07-06 22:44:50 +0000277#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500278 cifs_dbg(FYI, "Query POSIX ACL not supported yet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279#endif /* CONFIG_CIFS_POSIX */
Andreas Gruenbacherd9a15482016-04-14 00:30:13 +0200280 } else if (strcmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000282 if (sb->s_flags & MS_POSIXACL)
Steve French1da0c782005-04-28 22:41:04 -0700283 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
Steve French79a58d12007-07-06 22:44:50 +0000284 ea_value, buf_size, ACL_TYPE_DEFAULT,
Steve French737b7582005-04-28 22:41:06 -0700285 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500286 cifs_remap(cifs_sb));
Steve French79a58d12007-07-06 22:44:50 +0000287#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500288 cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n");
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600289#endif /* CONFIG_CIFS_POSIX */
Andreas Gruenbacherd9a15482016-04-14 00:30:13 +0200290 } else if (strcmp(ea_name, CIFS_XATTR_CIFS_ACL) == 0) {
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600291#ifdef CONFIG_CIFS_ACL
292 u32 acllen;
293 struct cifs_ntsd *pacl;
294
Steve French83e3bc22014-02-02 23:31:47 -0600295 if (pTcon->ses->server->ops->get_acl == NULL)
296 goto get_ea_exit; /* rc already EOPNOTSUPP */
297
298 pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
Al Viroce23e642016-04-11 00:48:00 -0400299 inode, full_path, &acllen);
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600300 if (IS_ERR(pacl)) {
301 rc = PTR_ERR(pacl);
Joe Perchesf96637b2013-05-04 22:12:25 -0500302 cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
303 __func__, rc);
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600304 } else {
305 if (ea_value) {
306 if (acllen > buf_size)
307 acllen = -ERANGE;
308 else
309 memcpy(ea_value, pacl, acllen);
310 }
311 rc = acllen;
312 kfree(pacl);
313 }
314#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500315 cifs_dbg(FYI, "Query CIFS ACL not supported yet\n");
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600316#endif /* CONFIG_CIFS_ACL */
Steve French79a58d12007-07-06 22:44:50 +0000317 } else if (strncmp(ea_name,
Mimi Zoharf995e742011-08-11 16:00:47 -0400318 XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500319 cifs_dbg(FYI, "Trusted xattr namespace not supported yet\n");
Steve French79a58d12007-07-06 22:44:50 +0000320 } else if (strncmp(ea_name,
Mimi Zoharf995e742011-08-11 16:00:47 -0400321 XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500322 cifs_dbg(FYI, "Security xattr namespace not supported yet\n");
Steve Frenchad7a2922008-02-07 23:25:02 +0000323 } else
Joe Perchesf96637b2013-05-04 22:12:25 -0500324 cifs_dbg(FYI,
325 "illegal xattr request %s (only user namespace supported)\n",
326 ea_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Steve French79a58d12007-07-06 22:44:50 +0000328 /* We could add an additional check for streams ie
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000330 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 returns as xattrs */
332
Steve French79a58d12007-07-06 22:44:50 +0000333 if (rc == -EINVAL)
334 rc = -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
336get_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800337 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400338 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400339 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340#endif
341 return rc;
342}
343
Steve French79a58d12007-07-06 22:44:50 +0000344ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345{
346 ssize_t rc = -EOPNOTSUPP;
347#ifdef CONFIG_CIFS_XATTR
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400348 unsigned int xid;
Al Viro5fdccfe2016-04-10 17:07:33 -0400349 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400350 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000351 struct cifs_tcon *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000352 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Steve French79a58d12007-07-06 22:44:50 +0000354 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Steve Frenchea4c07d2006-08-16 19:44:25 +0000355 return -EOPNOTSUPP;
356
Jeff Layton7ffec372010-09-29 19:51:11 -0400357 tlink = cifs_sb_tlink(cifs_sb);
358 if (IS_ERR(tlink))
359 return PTR_ERR(tlink);
360 pTcon = tlink_tcon(tlink);
361
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400362 xid = get_xid();
Steve Frenchea4c07d2006-08-16 19:44:25 +0000363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000365 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530366 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400367 goto list_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 }
369 /* return dos attributes as pseudo xattr */
370 /* return alt name if available as pseudo attr */
371
372 /* if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000373 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 returns as xattrs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Steve French666753c2014-01-26 23:53:43 -0600376 if (pTcon->ses->server->ops->query_all_EAs)
377 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
378 full_path, NULL, data, buf_size,
Steve French2baa2682014-09-27 02:19:01 -0500379 cifs_sb->local_nls, cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400380list_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800381 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400382 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400383 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384#endif
385 return rc;
386}