blob: ff9e1f8b16a4872158c05f688a9761a9a7a8781d [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;
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 struct cifs_sb_info *cifs_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;
Steve French79a58d12007-07-06 22:44:50 +000048 struct super_block *sb;
Jeff Layton7ffec372010-09-29 19:51:11 -040049 char *full_path = NULL;
Steve French79a58d12007-07-06 22:44:50 +000050
51 if (direntry == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 return -EIO;
David Howells2b0143b2015-03-17 22:25:59 +000053 if (d_really_is_negative(direntry))
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 return -EIO;
David Howells2b0143b2015-03-17 22:25:59 +000055 sb = d_inode(direntry)->i_sb;
Steve French79a58d12007-07-06 22:44:50 +000056 if (sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 return -EIO;
Steve French79a58d12007-07-06 22:44:50 +000058
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -040060 tlink = cifs_sb_tlink(cifs_sb);
61 if (IS_ERR(tlink))
62 return PTR_ERR(tlink);
63 pTcon = tlink_tcon(tlink);
64
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +040065 xid = get_xid();
Steve French79a58d12007-07-06 22:44:50 +000066
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +000068 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +053069 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -040070 goto remove_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 }
Steve French79a58d12007-07-06 22:44:50 +000072 if (ea_name == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -050073 cifs_dbg(FYI, "Null xattr names not supported\n");
Mimi Zoharf995e742011-08-11 16:00:47 -040074 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
75 && (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) {
Joe Perchesf96637b2013-05-04 22:12:25 -050076 cifs_dbg(FYI,
77 "illegal xattr request %s (only user namespace supported)\n",
78 ea_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 /* BB what if no namespace prefix? */
80 /* Should we just pass them to server, except for
81 system and perhaps security prefixes? */
82 } else {
Steve French79a58d12007-07-06 22:44:50 +000083 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 goto remove_ea_exit;
85
Mimi Zoharf995e742011-08-11 16:00:47 -040086 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
Steve French666753c2014-01-26 23:53:43 -060087 if (pTcon->ses->server->ops->set_EA)
88 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
89 full_path, ea_name, NULL, (__u16)0,
Steve French2baa2682014-09-27 02:19:01 -050090 cifs_sb->local_nls, cifs_remap(cifs_sb));
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 }
92remove_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -080093 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +040094 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -040095 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096#endif
97 return rc;
98}
99
Steve French79a58d12007-07-06 22:44:50 +0000100int cifs_setxattr(struct dentry *direntry, const char *ea_name,
101 const void *ea_value, size_t value_size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
103 int rc = -EOPNOTSUPP;
104#ifdef CONFIG_CIFS_XATTR
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400105 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -0400107 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000108 struct cifs_tcon *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000109 struct super_block *sb;
110 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Steve French79a58d12007-07-06 22:44:50 +0000112 if (direntry == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 return -EIO;
David Howells2b0143b2015-03-17 22:25:59 +0000114 if (d_really_is_negative(direntry))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 return -EIO;
David Howells2b0143b2015-03-17 22:25:59 +0000116 sb = d_inode(direntry)->i_sb;
Steve French79a58d12007-07-06 22:44:50 +0000117 if (sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
120 cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400121 tlink = cifs_sb_tlink(cifs_sb);
122 if (IS_ERR(tlink))
123 return PTR_ERR(tlink);
124 pTcon = tlink_tcon(tlink);
125
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400126 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000129 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530130 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400131 goto set_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 }
133 /* return dos attributes as pseudo xattr */
134 /* return alt name if available as pseudo attr */
135
136 /* if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000137 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 returns as xattrs */
Steve French79a58d12007-07-06 22:44:50 +0000139 if (value_size > MAX_EA_VALUE_SIZE) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500140 cifs_dbg(FYI, "size of EA value too large\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400141 rc = -EOPNOTSUPP;
142 goto set_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 }
144
Steve French79a58d12007-07-06 22:44:50 +0000145 if (ea_name == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500146 cifs_dbg(FYI, "Null xattr names not supported\n");
Mimi Zoharf995e742011-08-11 16:00:47 -0400147 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
148 == 0) {
Steve French79a58d12007-07-06 22:44:50 +0000149 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 goto set_ea_exit;
Steve Frenchad7a2922008-02-07 23:25:02 +0000151 if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0)
Joe Perchesf96637b2013-05-04 22:12:25 -0500152 cifs_dbg(FYI, "attempt to set cifs inode metadata\n");
Steve Frenchad7a2922008-02-07 23:25:02 +0000153
Mimi Zoharf995e742011-08-11 16:00:47 -0400154 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
Steve French666753c2014-01-26 23:53:43 -0600155 if (pTcon->ses->server->ops->set_EA)
156 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
157 full_path, ea_name, ea_value, (__u16)value_size,
Steve French2baa2682014-09-27 02:19:01 -0500158 cifs_sb->local_nls, cifs_remap(cifs_sb));
Mimi Zoharf995e742011-08-11 16:00:47 -0400159 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)
160 == 0) {
Steve French79a58d12007-07-06 22:44:50 +0000161 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 goto set_ea_exit;
163
Mimi Zoharf995e742011-08-11 16:00:47 -0400164 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
Steve French666753c2014-01-26 23:53:43 -0600165 if (pTcon->ses->server->ops->set_EA)
166 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
167 full_path, ea_name, ea_value, (__u16)value_size,
Steve French2baa2682014-09-27 02:19:01 -0500168 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve Frenchb73b9a42011-04-19 18:27:10 +0000169 } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
170 strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
Santosh Nayakb0f8ef22012-03-02 11:47:26 +0530171#ifdef CONFIG_CIFS_ACL
172 struct cifs_ntsd *pacl;
Steve Frenchb73b9a42011-04-19 18:27:10 +0000173 pacl = kmalloc(value_size, GFP_KERNEL);
174 if (!pacl) {
Steve Frenchb73b9a42011-04-19 18:27:10 +0000175 rc = -ENOMEM;
176 } else {
Steve Frenchb73b9a42011-04-19 18:27:10 +0000177 memcpy(pacl, ea_value, value_size);
Steve French83e3bc22014-02-02 23:31:47 -0600178 if (pTcon->ses->server->ops->set_acl)
179 rc = pTcon->ses->server->ops->set_acl(pacl,
David Howells2b0143b2015-03-17 22:25:59 +0000180 value_size, d_inode(direntry),
Steve French83e3bc22014-02-02 23:31:47 -0600181 full_path, CIFS_ACL_DACL);
182 else
183 rc = -EOPNOTSUPP;
Steve Frenchb73b9a42011-04-19 18:27:10 +0000184 if (rc == 0) /* force revalidate of the inode */
David Howells2b0143b2015-03-17 22:25:59 +0000185 CIFS_I(d_inode(direntry))->time = 0;
Steve Frenchb73b9a42011-04-19 18:27:10 +0000186 kfree(pacl);
Santosh Nayakb0f8ef22012-03-02 11:47:26 +0530187 }
Steve Frenchb73b9a42011-04-19 18:27:10 +0000188#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500189 cifs_dbg(FYI, "Set CIFS ACL not supported yet\n");
Steve Frenchb73b9a42011-04-19 18:27:10 +0000190#endif /* CONFIG_CIFS_ACL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 } else {
Steve French79a58d12007-07-06 22:44:50 +0000192 int temp;
193 temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 strlen(POSIX_ACL_XATTR_ACCESS));
195 if (temp == 0) {
196#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000197 if (sb->s_flags & MS_POSIXACL)
198 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
199 ea_value, (const int)value_size,
200 ACL_TYPE_ACCESS, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500201 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -0500202 cifs_dbg(FYI, "set POSIX ACL rc %d\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500204 cifs_dbg(FYI, "set POSIX ACL not supported\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205#endif
Steve French79a58d12007-07-06 22:44:50 +0000206 } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
207 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000209 if (sb->s_flags & MS_POSIXACL)
210 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
211 ea_value, (const int)value_size,
Steve French737b7582005-04-28 22:41:06 -0700212 ACL_TYPE_DEFAULT, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500213 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -0500214 cifs_dbg(FYI, "set POSIX default ACL rc %d\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500216 cifs_dbg(FYI, "set default POSIX ACL not supported\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217#endif
218 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -0500219 cifs_dbg(FYI, "illegal xattr request %s (only user namespace supported)\n",
220 ea_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 /* BB what if no namespace prefix? */
Steve French79a58d12007-07-06 22:44:50 +0000222 /* Should we just pass them to server, except for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 system and perhaps security prefixes? */
224 }
225 }
226
227set_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800228 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400229 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400230 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231#endif
232 return rc;
233}
234
Steve French79a58d12007-07-06 22:44:50 +0000235ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
236 void *ea_value, size_t buf_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
238 ssize_t rc = -EOPNOTSUPP;
239#ifdef CONFIG_CIFS_XATTR
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400240 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -0400242 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000243 struct cifs_tcon *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000244 struct super_block *sb;
245 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Steve French79a58d12007-07-06 22:44:50 +0000247 if (direntry == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 return -EIO;
David Howells2b0143b2015-03-17 22:25:59 +0000249 if (d_really_is_negative(direntry))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 return -EIO;
David Howells2b0143b2015-03-17 22:25:59 +0000251 sb = d_inode(direntry)->i_sb;
Steve French79a58d12007-07-06 22:44:50 +0000252 if (sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 return -EIO;
254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400256 tlink = cifs_sb_tlink(cifs_sb);
257 if (IS_ERR(tlink))
258 return PTR_ERR(tlink);
259 pTcon = tlink_tcon(tlink);
260
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400261 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000264 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530265 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400266 goto get_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 }
268 /* return dos attributes as pseudo xattr */
269 /* return alt name if available as pseudo attr */
Steve French79a58d12007-07-06 22:44:50 +0000270 if (ea_name == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500271 cifs_dbg(FYI, "Null xattr names not supported\n");
Mimi Zoharf995e742011-08-11 16:00:47 -0400272 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
273 == 0) {
Steve French79a58d12007-07-06 22:44:50 +0000274 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 goto get_ea_exit;
276
Steve French79a58d12007-07-06 22:44:50 +0000277 if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500278 cifs_dbg(FYI, "attempt to query cifs inode metadata\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 /* revalidate/getattr then populate from inode */
280 } /* BB add else when above is implemented */
Mimi Zoharf995e742011-08-11 16:00:47 -0400281 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
Steve French666753c2014-01-26 23:53:43 -0600282 if (pTcon->ses->server->ops->query_all_EAs)
283 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
284 full_path, ea_name, ea_value, buf_size,
Steve French2baa2682014-09-27 02:19:01 -0500285 cifs_sb->local_nls, cifs_remap(cifs_sb));
Mimi Zoharf995e742011-08-11 16:00:47 -0400286 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
Steve French79a58d12007-07-06 22:44:50 +0000287 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 goto get_ea_exit;
289
Mimi Zoharf995e742011-08-11 16:00:47 -0400290 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
Steve French666753c2014-01-26 23:53:43 -0600291 if (pTcon->ses->server->ops->query_all_EAs)
292 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
293 full_path, ea_name, ea_value, buf_size,
Steve French2baa2682014-09-27 02:19:01 -0500294 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French79a58d12007-07-06 22:44:50 +0000295 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
Steve French0a4b92c2006-01-12 15:44:21 -0800296 strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000298 if (sb->s_flags & MS_POSIXACL)
Steve French1da0c782005-04-28 22:41:04 -0700299 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
Steve French79a58d12007-07-06 22:44:50 +0000300 ea_value, buf_size, ACL_TYPE_ACCESS,
Steve French737b7582005-04-28 22:41:06 -0700301 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500302 cifs_remap(cifs_sb));
Steve French79a58d12007-07-06 22:44:50 +0000303#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500304 cifs_dbg(FYI, "Query POSIX ACL not supported yet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305#endif /* CONFIG_CIFS_POSIX */
Steve French79a58d12007-07-06 22:44:50 +0000306 } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
Steve French0a4b92c2006-01-12 15:44:21 -0800307 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000309 if (sb->s_flags & MS_POSIXACL)
Steve French1da0c782005-04-28 22:41:04 -0700310 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
Steve French79a58d12007-07-06 22:44:50 +0000311 ea_value, buf_size, ACL_TYPE_DEFAULT,
Steve French737b7582005-04-28 22:41:06 -0700312 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500313 cifs_remap(cifs_sb));
Steve French79a58d12007-07-06 22:44:50 +0000314#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500315 cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n");
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600316#endif /* CONFIG_CIFS_POSIX */
317 } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
318 strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
319#ifdef CONFIG_CIFS_ACL
320 u32 acllen;
321 struct cifs_ntsd *pacl;
322
Steve French83e3bc22014-02-02 23:31:47 -0600323 if (pTcon->ses->server->ops->get_acl == NULL)
324 goto get_ea_exit; /* rc already EOPNOTSUPP */
325
326 pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
David Howells2b0143b2015-03-17 22:25:59 +0000327 d_inode(direntry), full_path, &acllen);
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600328 if (IS_ERR(pacl)) {
329 rc = PTR_ERR(pacl);
Joe Perchesf96637b2013-05-04 22:12:25 -0500330 cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
331 __func__, rc);
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600332 } else {
333 if (ea_value) {
334 if (acllen > buf_size)
335 acllen = -ERANGE;
336 else
337 memcpy(ea_value, pacl, acllen);
338 }
339 rc = acllen;
340 kfree(pacl);
341 }
342#else
Joe Perchesf96637b2013-05-04 22:12:25 -0500343 cifs_dbg(FYI, "Query CIFS ACL not supported yet\n");
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600344#endif /* CONFIG_CIFS_ACL */
Steve French79a58d12007-07-06 22:44:50 +0000345 } else if (strncmp(ea_name,
Mimi Zoharf995e742011-08-11 16:00:47 -0400346 XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500347 cifs_dbg(FYI, "Trusted xattr namespace not supported yet\n");
Steve French79a58d12007-07-06 22:44:50 +0000348 } else if (strncmp(ea_name,
Mimi Zoharf995e742011-08-11 16:00:47 -0400349 XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500350 cifs_dbg(FYI, "Security xattr namespace not supported yet\n");
Steve Frenchad7a2922008-02-07 23:25:02 +0000351 } else
Joe Perchesf96637b2013-05-04 22:12:25 -0500352 cifs_dbg(FYI,
353 "illegal xattr request %s (only user namespace supported)\n",
354 ea_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Steve French79a58d12007-07-06 22:44:50 +0000356 /* We could add an additional check for streams ie
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000358 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 returns as xattrs */
360
Steve French79a58d12007-07-06 22:44:50 +0000361 if (rc == -EINVAL)
362 rc = -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
364get_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800365 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400366 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400367 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368#endif
369 return rc;
370}
371
Steve French79a58d12007-07-06 22:44:50 +0000372ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 ssize_t rc = -EOPNOTSUPP;
375#ifdef CONFIG_CIFS_XATTR
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400376 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -0400378 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000379 struct cifs_tcon *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000380 struct super_block *sb;
381 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
Steve French79a58d12007-07-06 22:44:50 +0000383 if (direntry == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 return -EIO;
David Howells2b0143b2015-03-17 22:25:59 +0000385 if (d_really_is_negative(direntry))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 return -EIO;
David Howells2b0143b2015-03-17 22:25:59 +0000387 sb = d_inode(direntry)->i_sb;
Steve French79a58d12007-07-06 22:44:50 +0000388 if (sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391 cifs_sb = CIFS_SB(sb);
Steve French79a58d12007-07-06 22:44:50 +0000392 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Steve Frenchea4c07d2006-08-16 19:44:25 +0000393 return -EOPNOTSUPP;
394
Jeff Layton7ffec372010-09-29 19:51:11 -0400395 tlink = cifs_sb_tlink(cifs_sb);
396 if (IS_ERR(tlink))
397 return PTR_ERR(tlink);
398 pTcon = tlink_tcon(tlink);
399
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400400 xid = get_xid();
Steve Frenchea4c07d2006-08-16 19:44:25 +0000401
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000403 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530404 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400405 goto list_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 }
407 /* return dos attributes as pseudo xattr */
408 /* return alt name if available as pseudo attr */
409
410 /* if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000411 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 returns as xattrs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Steve French666753c2014-01-26 23:53:43 -0600414 if (pTcon->ses->server->ops->query_all_EAs)
415 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
416 full_path, NULL, data, buf_size,
Steve French2baa2682014-09-27 02:19:01 -0500417 cifs_sb->local_nls, cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400418list_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800419 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400420 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400421 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422#endif
423 return rc;
424}