1 // SPDX-License-Identifier: LGPL-2.1
5 * Copyright (c) International Business Machines Corp., 2003, 2007
6 * Author(s): Steve French (sfrench@us.ibm.com)
11 #include <linux/posix_acl_xattr.h>
12 #include <linux/slab.h>
13 #include <linux/xattr.h>
17 #include "cifsproto.h"
18 #include "cifs_debug.h"
19 #include "cifs_fs_sb.h"
20 #include "cifs_unicode.h"
21 #include "cifs_ioctl.h"
23 #define MAX_EA_VALUE_SIZE CIFSMaxBufSize
24 #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* DACL only */
25 #define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */
26 #define CIFS_XATTR_CIFS_NTSD_FULL "system.cifs_ntsd_full" /* owner/DACL/SACL */
27 #define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */
28 #define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */
30 * Although these three are just aliases for the above, need to move away from
31 * confusing users and using the 20+ year old term 'cifs' when it is no longer
32 * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago
34 #define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */
35 #define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */
36 #define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */
37 #define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */
38 #define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */
39 /* BB need to add server (Samba e.g) support for security and trusted prefix */
41 enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
42 XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
44 static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
45 struct inode *inode, const char *full_path,
46 const void *value, size_t size)
48 ssize_t rc = -EOPNOTSUPP;
49 __u32 *pattrib = (__u32 *)value;
51 FILE_BASIC_INFO info_buf;
53 if ((value == NULL) || (size != sizeof(__u32)))
56 memset(&info_buf, 0, sizeof(info_buf));
58 info_buf.Attributes = cpu_to_le32(attrib);
59 if (pTcon->ses->server->ops->set_file_info)
60 rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
63 CIFS_I(inode)->cifsAttrs = attrib;
68 static int cifs_creation_time_set(unsigned int xid, struct cifs_tcon *pTcon,
69 struct inode *inode, const char *full_path,
70 const void *value, size_t size)
72 ssize_t rc = -EOPNOTSUPP;
73 __u64 *pcreation_time = (__u64 *)value;
75 FILE_BASIC_INFO info_buf;
77 if ((value == NULL) || (size != sizeof(__u64)))
80 memset(&info_buf, 0, sizeof(info_buf));
81 creation_time = *pcreation_time;
82 info_buf.CreationTime = cpu_to_le64(creation_time);
83 if (pTcon->ses->server->ops->set_file_info)
84 rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
87 CIFS_I(inode)->createtime = creation_time;
92 static int cifs_xattr_set(const struct xattr_handler *handler,
93 struct user_namespace *mnt_userns,
94 struct dentry *dentry, struct inode *inode,
95 const char *name, const void *value,
96 size_t size, int flags)
100 struct super_block *sb = dentry->d_sb;
101 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
102 struct tcon_link *tlink;
103 struct cifs_tcon *pTcon;
104 const char *full_path;
107 tlink = cifs_sb_tlink(cifs_sb);
109 return PTR_ERR(tlink);
110 pTcon = tlink_tcon(tlink);
113 page = alloc_dentry_path();
115 full_path = build_path_from_dentry(dentry, page);
116 if (IS_ERR(full_path)) {
117 rc = PTR_ERR(full_path);
120 /* return dos attributes as pseudo xattr */
121 /* return alt name if available as pseudo attr */
123 /* if proc/fs/cifs/streamstoxattr is set then
124 search server for EAs or streams to
126 if (size > MAX_EA_VALUE_SIZE) {
127 cifs_dbg(FYI, "size of EA value too large\n");
132 switch (handler->flags) {
134 cifs_dbg(FYI, "%s:setting user xattr %s\n", __func__, name);
135 if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
136 (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
137 rc = cifs_attrib_set(xid, pTcon, inode, full_path,
139 if (rc == 0) /* force revalidate of the inode */
140 CIFS_I(inode)->time = 0;
142 } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
143 (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
144 rc = cifs_creation_time_set(xid, pTcon, inode,
145 full_path, value, size);
146 if (rc == 0) /* force revalidate of the inode */
147 CIFS_I(inode)->time = 0;
151 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
154 if (pTcon->ses->server->ops->set_EA)
155 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
156 full_path, name, value, (__u16)size,
157 cifs_sb->local_nls, cifs_sb);
161 case XATTR_CIFS_NTSD:
162 case XATTR_CIFS_NTSD_FULL: {
163 struct cifs_ntsd *pacl;
167 pacl = kmalloc(size, GFP_KERNEL);
171 memcpy(pacl, value, size);
172 if (pTcon->ses->server->ops->set_acl) {
176 switch (handler->flags) {
177 case XATTR_CIFS_NTSD_FULL:
178 aclflags = (CIFS_ACL_OWNER |
182 case XATTR_CIFS_NTSD:
183 aclflags = (CIFS_ACL_OWNER |
188 aclflags = CIFS_ACL_DACL;
191 rc = pTcon->ses->server->ops->set_acl(pacl,
192 size, inode, full_path, aclflags);
196 if (rc == 0) /* force revalidate of the inode */
197 CIFS_I(inode)->time = 0;
203 case XATTR_ACL_ACCESS:
204 #ifdef CONFIG_CIFS_POSIX
207 if (sb->s_flags & SB_POSIXACL)
208 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
209 value, (const int)size,
210 ACL_TYPE_ACCESS, cifs_sb->local_nls,
211 cifs_remap(cifs_sb));
212 #endif /* CONFIG_CIFS_POSIX */
215 case XATTR_ACL_DEFAULT:
216 #ifdef CONFIG_CIFS_POSIX
219 if (sb->s_flags & SB_POSIXACL)
220 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
221 value, (const int)size,
222 ACL_TYPE_DEFAULT, cifs_sb->local_nls,
223 cifs_remap(cifs_sb));
224 #endif /* CONFIG_CIFS_POSIX */
229 free_dentry_path(page);
231 cifs_put_tlink(tlink);
235 static int cifs_attrib_get(struct dentry *dentry,
236 struct inode *inode, void *value,
242 rc = cifs_revalidate_dentry_attr(dentry);
247 if ((value == NULL) || (size == 0))
248 return sizeof(__u32);
249 else if (size < sizeof(__u32))
252 /* return dos attributes as pseudo xattr */
253 pattribute = (__u32 *)value;
254 *pattribute = CIFS_I(inode)->cifsAttrs;
256 return sizeof(__u32);
259 static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
260 void *value, size_t size)
265 rc = cifs_revalidate_dentry_attr(dentry);
269 if ((value == NULL) || (size == 0))
270 return sizeof(__u64);
271 else if (size < sizeof(__u64))
274 /* return dos attributes as pseudo xattr */
275 pcreatetime = (__u64 *)value;
276 *pcreatetime = CIFS_I(inode)->createtime;
277 return sizeof(__u64);
281 static int cifs_xattr_get(const struct xattr_handler *handler,
282 struct dentry *dentry, struct inode *inode,
283 const char *name, void *value, size_t size)
285 ssize_t rc = -EOPNOTSUPP;
287 struct super_block *sb = dentry->d_sb;
288 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
289 struct tcon_link *tlink;
290 struct cifs_tcon *pTcon;
291 const char *full_path;
294 tlink = cifs_sb_tlink(cifs_sb);
296 return PTR_ERR(tlink);
297 pTcon = tlink_tcon(tlink);
300 page = alloc_dentry_path();
302 full_path = build_path_from_dentry(dentry, page);
303 if (IS_ERR(full_path)) {
304 rc = PTR_ERR(full_path);
308 /* return alt name if available as pseudo attr */
309 switch (handler->flags) {
311 cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
312 if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
313 (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
314 rc = cifs_attrib_get(dentry, inode, value, size);
316 } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
317 (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
318 rc = cifs_creation_time_get(dentry, inode, value, size);
322 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
325 if (pTcon->ses->server->ops->query_all_EAs)
326 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
327 full_path, name, value, size, cifs_sb);
331 case XATTR_CIFS_NTSD:
332 case XATTR_CIFS_NTSD_FULL: {
334 * fetch owner, DACL, and SACL if asked for full descriptor,
335 * fetch owner and DACL otherwise
337 u32 acllen, extra_info;
338 struct cifs_ntsd *pacl;
340 if (pTcon->ses->server->ops->get_acl == NULL)
341 goto out; /* rc already EOPNOTSUPP */
343 if (handler->flags == XATTR_CIFS_NTSD_FULL) {
344 extra_info = SACL_SECINFO;
348 pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
349 inode, full_path, &acllen, extra_info);
352 cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
359 memcpy(value, pacl, acllen);
367 case XATTR_ACL_ACCESS:
368 #ifdef CONFIG_CIFS_POSIX
369 if (sb->s_flags & SB_POSIXACL)
370 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
371 value, size, ACL_TYPE_ACCESS,
373 cifs_remap(cifs_sb));
374 #endif /* CONFIG_CIFS_POSIX */
377 case XATTR_ACL_DEFAULT:
378 #ifdef CONFIG_CIFS_POSIX
379 if (sb->s_flags & SB_POSIXACL)
380 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
381 value, size, ACL_TYPE_DEFAULT,
383 cifs_remap(cifs_sb));
384 #endif /* CONFIG_CIFS_POSIX */
388 /* We could add an additional check for streams ie
389 if proc/fs/cifs/streamstoxattr is set then
390 search server for EAs or streams to
397 free_dentry_path(page);
399 cifs_put_tlink(tlink);
403 ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
405 ssize_t rc = -EOPNOTSUPP;
407 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
408 struct tcon_link *tlink;
409 struct cifs_tcon *pTcon;
410 const char *full_path;
413 if (unlikely(cifs_forced_shutdown(cifs_sb)))
416 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
419 tlink = cifs_sb_tlink(cifs_sb);
421 return PTR_ERR(tlink);
422 pTcon = tlink_tcon(tlink);
425 page = alloc_dentry_path();
427 full_path = build_path_from_dentry(direntry, page);
428 if (IS_ERR(full_path)) {
429 rc = PTR_ERR(full_path);
432 /* return dos attributes as pseudo xattr */
433 /* return alt name if available as pseudo attr */
435 /* if proc/fs/cifs/streamstoxattr is set then
436 search server for EAs or streams to
439 if (pTcon->ses->server->ops->query_all_EAs)
440 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
441 full_path, NULL, data, buf_size, cifs_sb);
443 free_dentry_path(page);
445 cifs_put_tlink(tlink);
449 static const struct xattr_handler cifs_user_xattr_handler = {
450 .prefix = XATTR_USER_PREFIX,
452 .get = cifs_xattr_get,
453 .set = cifs_xattr_set,
456 /* os2.* attributes are treated like user.* attributes */
457 static const struct xattr_handler cifs_os2_xattr_handler = {
458 .prefix = XATTR_OS2_PREFIX,
460 .get = cifs_xattr_get,
461 .set = cifs_xattr_set,
464 static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
465 .name = CIFS_XATTR_CIFS_ACL,
466 .flags = XATTR_CIFS_ACL,
467 .get = cifs_xattr_get,
468 .set = cifs_xattr_set,
472 * Although this is just an alias for the above, need to move away from
473 * confusing users and using the 20 year old term 'cifs' when it is no
474 * longer secure and was replaced by SMB2/SMB3 a long time ago, and
475 * SMB3 and later are highly secure.
477 static const struct xattr_handler smb3_acl_xattr_handler = {
478 .name = SMB3_XATTR_CIFS_ACL,
479 .flags = XATTR_CIFS_ACL,
480 .get = cifs_xattr_get,
481 .set = cifs_xattr_set,
484 static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = {
485 .name = CIFS_XATTR_CIFS_NTSD,
486 .flags = XATTR_CIFS_NTSD,
487 .get = cifs_xattr_get,
488 .set = cifs_xattr_set,
492 * Although this is just an alias for the above, need to move away from
493 * confusing users and using the 20 year old term 'cifs' when it is no
494 * longer secure and was replaced by SMB2/SMB3 a long time ago, and
495 * SMB3 and later are highly secure.
497 static const struct xattr_handler smb3_ntsd_xattr_handler = {
498 .name = SMB3_XATTR_CIFS_NTSD,
499 .flags = XATTR_CIFS_NTSD,
500 .get = cifs_xattr_get,
501 .set = cifs_xattr_set,
504 static const struct xattr_handler cifs_cifs_ntsd_full_xattr_handler = {
505 .name = CIFS_XATTR_CIFS_NTSD_FULL,
506 .flags = XATTR_CIFS_NTSD_FULL,
507 .get = cifs_xattr_get,
508 .set = cifs_xattr_set,
512 * Although this is just an alias for the above, need to move away from
513 * confusing users and using the 20 year old term 'cifs' when it is no
514 * longer secure and was replaced by SMB2/SMB3 a long time ago, and
515 * SMB3 and later are highly secure.
517 static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
518 .name = SMB3_XATTR_CIFS_NTSD_FULL,
519 .flags = XATTR_CIFS_NTSD_FULL,
520 .get = cifs_xattr_get,
521 .set = cifs_xattr_set,
525 static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
526 .name = XATTR_NAME_POSIX_ACL_ACCESS,
527 .flags = XATTR_ACL_ACCESS,
528 .get = cifs_xattr_get,
529 .set = cifs_xattr_set,
532 static const struct xattr_handler cifs_posix_acl_default_xattr_handler = {
533 .name = XATTR_NAME_POSIX_ACL_DEFAULT,
534 .flags = XATTR_ACL_DEFAULT,
535 .get = cifs_xattr_get,
536 .set = cifs_xattr_set,
539 const struct xattr_handler *cifs_xattr_handlers[] = {
540 &cifs_user_xattr_handler,
541 &cifs_os2_xattr_handler,
542 &cifs_cifs_acl_xattr_handler,
543 &smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */
544 &cifs_cifs_ntsd_xattr_handler,
545 &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */
546 &cifs_cifs_ntsd_full_xattr_handler,
547 &smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */
548 &cifs_posix_acl_access_xattr_handler,
549 &cifs_posix_acl_default_xattr_handler,