4 * Copyright (c) International Business Machines Corp., 2003, 2007
5 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
23 #include <linux/posix_acl_xattr.h>
24 #include <linux/slab.h>
25 #include <linux/xattr.h>
29 #include "cifsproto.h"
30 #include "cifs_debug.h"
31 #include "cifs_fs_sb.h"
32 #include "cifs_unicode.h"
34 #define MAX_EA_VALUE_SIZE 65535
35 #define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
37 /* BB need to add server (Samba e.g) support for security and trusted prefix */
39 enum { XATTR_USER
, XATTR_CIFS_ACL
, XATTR_ACL_ACCESS
, XATTR_ACL_DEFAULT
};
41 static int cifs_xattr_set(const struct xattr_handler
*handler
,
42 struct dentry
*dentry
, const char *name
,
43 const void *value
, size_t size
, int flags
)
47 struct super_block
*sb
= dentry
->d_sb
;
48 struct cifs_sb_info
*cifs_sb
= CIFS_SB(sb
);
49 struct tcon_link
*tlink
;
50 struct cifs_tcon
*pTcon
;
53 tlink
= cifs_sb_tlink(cifs_sb
);
55 return PTR_ERR(tlink
);
56 pTcon
= tlink_tcon(tlink
);
60 full_path
= build_path_from_dentry(dentry
);
61 if (full_path
== NULL
) {
65 /* return dos attributes as pseudo xattr */
66 /* return alt name if available as pseudo attr */
68 /* if proc/fs/cifs/streamstoxattr is set then
69 search server for EAs or streams to
71 if (size
> MAX_EA_VALUE_SIZE
) {
72 cifs_dbg(FYI
, "size of EA value too large\n");
77 switch (handler
->flags
) {
79 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_NO_XATTR
)
82 if (pTcon
->ses
->server
->ops
->set_EA
)
83 rc
= pTcon
->ses
->server
->ops
->set_EA(xid
, pTcon
,
84 full_path
, name
, value
, (__u16
)size
,
85 cifs_sb
->local_nls
, cifs_remap(cifs_sb
));
88 case XATTR_CIFS_ACL
: {
89 #ifdef CONFIG_CIFS_ACL
90 struct cifs_ntsd
*pacl
;
94 pacl
= kmalloc(size
, GFP_KERNEL
);
98 memcpy(pacl
, value
, size
);
100 pTcon
->ses
->server
->ops
->set_acl
)
101 rc
= pTcon
->ses
->server
->ops
->set_acl(pacl
,
102 size
, d_inode(dentry
),
103 full_path
, CIFS_ACL_DACL
);
106 if (rc
== 0) /* force revalidate of the inode */
107 CIFS_I(d_inode(dentry
))->time
= 0;
110 #endif /* CONFIG_CIFS_ACL */
114 case XATTR_ACL_ACCESS
:
115 #ifdef CONFIG_CIFS_POSIX
118 if (sb
->s_flags
& MS_POSIXACL
)
119 rc
= CIFSSMBSetPosixACL(xid
, pTcon
, full_path
,
120 value
, (const int)size
,
121 ACL_TYPE_ACCESS
, cifs_sb
->local_nls
,
122 cifs_remap(cifs_sb
));
123 #endif /* CONFIG_CIFS_POSIX */
126 case XATTR_ACL_DEFAULT
:
127 #ifdef CONFIG_CIFS_POSIX
130 if (sb
->s_flags
& MS_POSIXACL
)
131 rc
= CIFSSMBSetPosixACL(xid
, pTcon
, full_path
,
132 value
, (const int)size
,
133 ACL_TYPE_DEFAULT
, cifs_sb
->local_nls
,
134 cifs_remap(cifs_sb
));
135 #endif /* CONFIG_CIFS_POSIX */
142 cifs_put_tlink(tlink
);
146 static int cifs_xattr_get(const struct xattr_handler
*handler
,
147 struct dentry
*dentry
, struct inode
*inode
,
148 const char *name
, void *value
, size_t size
)
150 ssize_t rc
= -EOPNOTSUPP
;
152 struct super_block
*sb
= dentry
->d_sb
;
153 struct cifs_sb_info
*cifs_sb
= CIFS_SB(sb
);
154 struct tcon_link
*tlink
;
155 struct cifs_tcon
*pTcon
;
158 tlink
= cifs_sb_tlink(cifs_sb
);
160 return PTR_ERR(tlink
);
161 pTcon
= tlink_tcon(tlink
);
165 full_path
= build_path_from_dentry(dentry
);
166 if (full_path
== NULL
) {
170 /* return dos attributes as pseudo xattr */
171 /* return alt name if available as pseudo attr */
172 switch (handler
->flags
) {
174 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_NO_XATTR
)
177 if (pTcon
->ses
->server
->ops
->query_all_EAs
)
178 rc
= pTcon
->ses
->server
->ops
->query_all_EAs(xid
, pTcon
,
179 full_path
, name
, value
, size
,
180 cifs_sb
->local_nls
, cifs_remap(cifs_sb
));
183 case XATTR_CIFS_ACL
: {
184 #ifdef CONFIG_CIFS_ACL
186 struct cifs_ntsd
*pacl
;
188 if (pTcon
->ses
->server
->ops
->get_acl
== NULL
)
189 goto out
; /* rc already EOPNOTSUPP */
191 pacl
= pTcon
->ses
->server
->ops
->get_acl(cifs_sb
,
192 inode
, full_path
, &acllen
);
195 cifs_dbg(VFS
, "%s: error %zd getting sec desc\n",
202 memcpy(value
, pacl
, acllen
);
207 #endif /* CONFIG_CIFS_ACL */
211 case XATTR_ACL_ACCESS
:
212 #ifdef CONFIG_CIFS_POSIX
213 if (sb
->s_flags
& MS_POSIXACL
)
214 rc
= CIFSSMBGetPosixACL(xid
, pTcon
, full_path
,
215 value
, size
, ACL_TYPE_ACCESS
,
217 cifs_remap(cifs_sb
));
218 #endif /* CONFIG_CIFS_POSIX */
221 case XATTR_ACL_DEFAULT
:
222 #ifdef CONFIG_CIFS_POSIX
223 if (sb
->s_flags
& MS_POSIXACL
)
224 rc
= CIFSSMBGetPosixACL(xid
, pTcon
, full_path
,
225 value
, size
, ACL_TYPE_DEFAULT
,
227 cifs_remap(cifs_sb
));
228 #endif /* CONFIG_CIFS_POSIX */
232 /* We could add an additional check for streams ie
233 if proc/fs/cifs/streamstoxattr is set then
234 search server for EAs or streams to
243 cifs_put_tlink(tlink
);
247 ssize_t
cifs_listxattr(struct dentry
*direntry
, char *data
, size_t buf_size
)
249 ssize_t rc
= -EOPNOTSUPP
;
251 struct cifs_sb_info
*cifs_sb
= CIFS_SB(direntry
->d_sb
);
252 struct tcon_link
*tlink
;
253 struct cifs_tcon
*pTcon
;
256 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_NO_XATTR
)
259 tlink
= cifs_sb_tlink(cifs_sb
);
261 return PTR_ERR(tlink
);
262 pTcon
= tlink_tcon(tlink
);
266 full_path
= build_path_from_dentry(direntry
);
267 if (full_path
== NULL
) {
271 /* return dos attributes as pseudo xattr */
272 /* return alt name if available as pseudo attr */
274 /* if proc/fs/cifs/streamstoxattr is set then
275 search server for EAs or streams to
278 if (pTcon
->ses
->server
->ops
->query_all_EAs
)
279 rc
= pTcon
->ses
->server
->ops
->query_all_EAs(xid
, pTcon
,
280 full_path
, NULL
, data
, buf_size
,
281 cifs_sb
->local_nls
, cifs_remap(cifs_sb
));
285 cifs_put_tlink(tlink
);
289 static const struct xattr_handler cifs_user_xattr_handler
= {
290 .prefix
= XATTR_USER_PREFIX
,
292 .get
= cifs_xattr_get
,
293 .set
= cifs_xattr_set
,
296 /* os2.* attributes are treated like user.* attributes */
297 static const struct xattr_handler cifs_os2_xattr_handler
= {
298 .prefix
= XATTR_OS2_PREFIX
,
300 .get
= cifs_xattr_get
,
301 .set
= cifs_xattr_set
,
304 static const struct xattr_handler cifs_cifs_acl_xattr_handler
= {
305 .name
= CIFS_XATTR_CIFS_ACL
,
306 .flags
= XATTR_CIFS_ACL
,
307 .get
= cifs_xattr_get
,
308 .set
= cifs_xattr_set
,
311 static const struct xattr_handler cifs_posix_acl_access_xattr_handler
= {
312 .name
= XATTR_NAME_POSIX_ACL_ACCESS
,
313 .flags
= XATTR_ACL_ACCESS
,
314 .get
= cifs_xattr_get
,
315 .set
= cifs_xattr_set
,
318 static const struct xattr_handler cifs_posix_acl_default_xattr_handler
= {
319 .name
= XATTR_NAME_POSIX_ACL_DEFAULT
,
320 .flags
= XATTR_ACL_DEFAULT
,
321 .get
= cifs_xattr_get
,
322 .set
= cifs_xattr_set
,
325 const struct xattr_handler
*cifs_xattr_handlers
[] = {
326 &cifs_user_xattr_handler
,
327 &cifs_os2_xattr_handler
,
328 &cifs_cifs_acl_xattr_handler
,
329 &cifs_posix_acl_access_xattr_handler
,
330 &cifs_posix_acl_default_xattr_handler
,