0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/fs.h>
0010 #include <linux/posix_acl_xattr.h>
0011 #include <linux/slab.h>
0012 #include <linux/xattr.h>
0013 #include "cifsfs.h"
0014 #include "cifspdu.h"
0015 #include "cifsglob.h"
0016 #include "cifsproto.h"
0017 #include "cifs_debug.h"
0018 #include "cifs_fs_sb.h"
0019 #include "cifs_unicode.h"
0020 #include "cifs_ioctl.h"
0021
0022 #define MAX_EA_VALUE_SIZE CIFSMaxBufSize
0023 #define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
0024 #define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd"
0025 #define CIFS_XATTR_CIFS_NTSD_FULL "system.cifs_ntsd_full"
0026 #define CIFS_XATTR_ATTRIB "cifs.dosattrib"
0027 #define CIFS_XATTR_CREATETIME "cifs.creationtime"
0028
0029
0030
0031
0032
0033 #define SMB3_XATTR_CIFS_ACL "system.smb3_acl"
0034 #define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd"
0035 #define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full"
0036 #define SMB3_XATTR_ATTRIB "smb3.dosattrib"
0037 #define SMB3_XATTR_CREATETIME "smb3.creationtime"
0038
0039
0040 enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
0041 XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
0042
0043 static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
0044 struct inode *inode, const char *full_path,
0045 const void *value, size_t size)
0046 {
0047 ssize_t rc = -EOPNOTSUPP;
0048 __u32 *pattrib = (__u32 *)value;
0049 __u32 attrib;
0050 FILE_BASIC_INFO info_buf;
0051
0052 if ((value == NULL) || (size != sizeof(__u32)))
0053 return -ERANGE;
0054
0055 memset(&info_buf, 0, sizeof(info_buf));
0056 attrib = *pattrib;
0057 info_buf.Attributes = cpu_to_le32(attrib);
0058 if (pTcon->ses->server->ops->set_file_info)
0059 rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
0060 &info_buf, xid);
0061 if (rc == 0)
0062 CIFS_I(inode)->cifsAttrs = attrib;
0063
0064 return rc;
0065 }
0066
0067 static int cifs_creation_time_set(unsigned int xid, struct cifs_tcon *pTcon,
0068 struct inode *inode, const char *full_path,
0069 const void *value, size_t size)
0070 {
0071 ssize_t rc = -EOPNOTSUPP;
0072 __u64 *pcreation_time = (__u64 *)value;
0073 __u64 creation_time;
0074 FILE_BASIC_INFO info_buf;
0075
0076 if ((value == NULL) || (size != sizeof(__u64)))
0077 return -ERANGE;
0078
0079 memset(&info_buf, 0, sizeof(info_buf));
0080 creation_time = *pcreation_time;
0081 info_buf.CreationTime = cpu_to_le64(creation_time);
0082 if (pTcon->ses->server->ops->set_file_info)
0083 rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
0084 &info_buf, xid);
0085 if (rc == 0)
0086 CIFS_I(inode)->createtime = creation_time;
0087
0088 return rc;
0089 }
0090
0091 static int cifs_xattr_set(const struct xattr_handler *handler,
0092 struct user_namespace *mnt_userns,
0093 struct dentry *dentry, struct inode *inode,
0094 const char *name, const void *value,
0095 size_t size, int flags)
0096 {
0097 int rc = -EOPNOTSUPP;
0098 unsigned int xid;
0099 struct super_block *sb = dentry->d_sb;
0100 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
0101 struct tcon_link *tlink;
0102 struct cifs_tcon *pTcon;
0103 const char *full_path;
0104 void *page;
0105
0106 tlink = cifs_sb_tlink(cifs_sb);
0107 if (IS_ERR(tlink))
0108 return PTR_ERR(tlink);
0109 pTcon = tlink_tcon(tlink);
0110
0111 xid = get_xid();
0112 page = alloc_dentry_path();
0113
0114 full_path = build_path_from_dentry(dentry, page);
0115 if (IS_ERR(full_path)) {
0116 rc = PTR_ERR(full_path);
0117 goto out;
0118 }
0119
0120
0121
0122
0123
0124
0125 if (size > MAX_EA_VALUE_SIZE) {
0126 cifs_dbg(FYI, "size of EA value too large\n");
0127 rc = -EOPNOTSUPP;
0128 goto out;
0129 }
0130
0131 switch (handler->flags) {
0132 case XATTR_USER:
0133 cifs_dbg(FYI, "%s:setting user xattr %s\n", __func__, name);
0134 if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
0135 (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
0136 rc = cifs_attrib_set(xid, pTcon, inode, full_path,
0137 value, size);
0138 if (rc == 0)
0139 CIFS_I(inode)->time = 0;
0140 break;
0141 } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
0142 (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
0143 rc = cifs_creation_time_set(xid, pTcon, inode,
0144 full_path, value, size);
0145 if (rc == 0)
0146 CIFS_I(inode)->time = 0;
0147 break;
0148 }
0149
0150 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
0151 goto out;
0152
0153 if (pTcon->ses->server->ops->set_EA)
0154 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
0155 full_path, name, value, (__u16)size,
0156 cifs_sb->local_nls, cifs_sb);
0157 break;
0158
0159 case XATTR_CIFS_ACL:
0160 case XATTR_CIFS_NTSD:
0161 case XATTR_CIFS_NTSD_FULL: {
0162 struct cifs_ntsd *pacl;
0163
0164 if (!value)
0165 goto out;
0166 pacl = kmalloc(size, GFP_KERNEL);
0167 if (!pacl) {
0168 rc = -ENOMEM;
0169 } else {
0170 memcpy(pacl, value, size);
0171 if (pTcon->ses->server->ops->set_acl) {
0172 int aclflags = 0;
0173 rc = 0;
0174
0175 switch (handler->flags) {
0176 case XATTR_CIFS_NTSD_FULL:
0177 aclflags = (CIFS_ACL_OWNER |
0178 CIFS_ACL_GROUP |
0179 CIFS_ACL_DACL |
0180 CIFS_ACL_SACL);
0181 break;
0182 case XATTR_CIFS_NTSD:
0183 aclflags = (CIFS_ACL_OWNER |
0184 CIFS_ACL_GROUP |
0185 CIFS_ACL_DACL);
0186 break;
0187 case XATTR_CIFS_ACL:
0188 default:
0189 aclflags = CIFS_ACL_DACL;
0190 }
0191
0192 rc = pTcon->ses->server->ops->set_acl(pacl,
0193 size, inode, full_path, aclflags);
0194 } else {
0195 rc = -EOPNOTSUPP;
0196 }
0197 if (rc == 0)
0198 CIFS_I(inode)->time = 0;
0199 kfree(pacl);
0200 }
0201 break;
0202 }
0203
0204 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
0205 case XATTR_ACL_ACCESS:
0206 #ifdef CONFIG_CIFS_POSIX
0207 if (!value)
0208 goto out;
0209 if (sb->s_flags & SB_POSIXACL)
0210 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
0211 value, (const int)size,
0212 ACL_TYPE_ACCESS, cifs_sb->local_nls,
0213 cifs_remap(cifs_sb));
0214 #endif
0215 break;
0216
0217 case XATTR_ACL_DEFAULT:
0218 #ifdef CONFIG_CIFS_POSIX
0219 if (!value)
0220 goto out;
0221 if (sb->s_flags & SB_POSIXACL)
0222 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
0223 value, (const int)size,
0224 ACL_TYPE_DEFAULT, cifs_sb->local_nls,
0225 cifs_remap(cifs_sb));
0226 #endif
0227 break;
0228 #endif
0229 }
0230
0231 out:
0232 free_dentry_path(page);
0233 free_xid(xid);
0234 cifs_put_tlink(tlink);
0235 return rc;
0236 }
0237
0238 static int cifs_attrib_get(struct dentry *dentry,
0239 struct inode *inode, void *value,
0240 size_t size)
0241 {
0242 ssize_t rc;
0243 __u32 *pattribute;
0244
0245 rc = cifs_revalidate_dentry_attr(dentry);
0246
0247 if (rc)
0248 return rc;
0249
0250 if ((value == NULL) || (size == 0))
0251 return sizeof(__u32);
0252 else if (size < sizeof(__u32))
0253 return -ERANGE;
0254
0255
0256 pattribute = (__u32 *)value;
0257 *pattribute = CIFS_I(inode)->cifsAttrs;
0258
0259 return sizeof(__u32);
0260 }
0261
0262 static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
0263 void *value, size_t size)
0264 {
0265 ssize_t rc;
0266 __u64 *pcreatetime;
0267
0268 rc = cifs_revalidate_dentry_attr(dentry);
0269 if (rc)
0270 return rc;
0271
0272 if ((value == NULL) || (size == 0))
0273 return sizeof(__u64);
0274 else if (size < sizeof(__u64))
0275 return -ERANGE;
0276
0277
0278 pcreatetime = (__u64 *)value;
0279 *pcreatetime = CIFS_I(inode)->createtime;
0280 return sizeof(__u64);
0281 }
0282
0283
0284 static int cifs_xattr_get(const struct xattr_handler *handler,
0285 struct dentry *dentry, struct inode *inode,
0286 const char *name, void *value, size_t size)
0287 {
0288 ssize_t rc = -EOPNOTSUPP;
0289 unsigned int xid;
0290 struct super_block *sb = dentry->d_sb;
0291 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
0292 struct tcon_link *tlink;
0293 struct cifs_tcon *pTcon;
0294 const char *full_path;
0295 void *page;
0296
0297 tlink = cifs_sb_tlink(cifs_sb);
0298 if (IS_ERR(tlink))
0299 return PTR_ERR(tlink);
0300 pTcon = tlink_tcon(tlink);
0301
0302 xid = get_xid();
0303 page = alloc_dentry_path();
0304
0305 full_path = build_path_from_dentry(dentry, page);
0306 if (IS_ERR(full_path)) {
0307 rc = PTR_ERR(full_path);
0308 goto out;
0309 }
0310
0311
0312 switch (handler->flags) {
0313 case XATTR_USER:
0314 cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
0315 if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
0316 (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
0317 rc = cifs_attrib_get(dentry, inode, value, size);
0318 break;
0319 } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
0320 (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
0321 rc = cifs_creation_time_get(dentry, inode, value, size);
0322 break;
0323 }
0324
0325 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
0326 goto out;
0327
0328 if (pTcon->ses->server->ops->query_all_EAs)
0329 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
0330 full_path, name, value, size, cifs_sb);
0331 break;
0332
0333 case XATTR_CIFS_ACL:
0334 case XATTR_CIFS_NTSD:
0335 case XATTR_CIFS_NTSD_FULL: {
0336
0337
0338
0339
0340 u32 acllen, extra_info;
0341 struct cifs_ntsd *pacl;
0342
0343 if (pTcon->ses->server->ops->get_acl == NULL)
0344 goto out;
0345
0346 if (handler->flags == XATTR_CIFS_NTSD_FULL) {
0347 extra_info = SACL_SECINFO;
0348 } else {
0349 extra_info = 0;
0350 }
0351 pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
0352 inode, full_path, &acllen, extra_info);
0353 if (IS_ERR(pacl)) {
0354 rc = PTR_ERR(pacl);
0355 cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
0356 __func__, rc);
0357 } else {
0358 if (value) {
0359 if (acllen > size)
0360 acllen = -ERANGE;
0361 else
0362 memcpy(value, pacl, acllen);
0363 }
0364 rc = acllen;
0365 kfree(pacl);
0366 }
0367 break;
0368 }
0369 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
0370 case XATTR_ACL_ACCESS:
0371 #ifdef CONFIG_CIFS_POSIX
0372 if (sb->s_flags & SB_POSIXACL)
0373 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
0374 value, size, ACL_TYPE_ACCESS,
0375 cifs_sb->local_nls,
0376 cifs_remap(cifs_sb));
0377 #endif
0378 break;
0379
0380 case XATTR_ACL_DEFAULT:
0381 #ifdef CONFIG_CIFS_POSIX
0382 if (sb->s_flags & SB_POSIXACL)
0383 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
0384 value, size, ACL_TYPE_DEFAULT,
0385 cifs_sb->local_nls,
0386 cifs_remap(cifs_sb));
0387 #endif
0388 break;
0389 #endif
0390 }
0391
0392
0393
0394
0395
0396
0397 if (rc == -EINVAL)
0398 rc = -EOPNOTSUPP;
0399
0400 out:
0401 free_dentry_path(page);
0402 free_xid(xid);
0403 cifs_put_tlink(tlink);
0404 return rc;
0405 }
0406
0407 ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
0408 {
0409 ssize_t rc = -EOPNOTSUPP;
0410 unsigned int xid;
0411 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
0412 struct tcon_link *tlink;
0413 struct cifs_tcon *pTcon;
0414 const char *full_path;
0415 void *page;
0416
0417 if (unlikely(cifs_forced_shutdown(cifs_sb)))
0418 return -EIO;
0419
0420 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
0421 return -EOPNOTSUPP;
0422
0423 tlink = cifs_sb_tlink(cifs_sb);
0424 if (IS_ERR(tlink))
0425 return PTR_ERR(tlink);
0426 pTcon = tlink_tcon(tlink);
0427
0428 xid = get_xid();
0429 page = alloc_dentry_path();
0430
0431 full_path = build_path_from_dentry(direntry, page);
0432 if (IS_ERR(full_path)) {
0433 rc = PTR_ERR(full_path);
0434 goto list_ea_exit;
0435 }
0436
0437
0438
0439
0440
0441
0442
0443 if (pTcon->ses->server->ops->query_all_EAs)
0444 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
0445 full_path, NULL, data, buf_size, cifs_sb);
0446 list_ea_exit:
0447 free_dentry_path(page);
0448 free_xid(xid);
0449 cifs_put_tlink(tlink);
0450 return rc;
0451 }
0452
0453 static const struct xattr_handler cifs_user_xattr_handler = {
0454 .prefix = XATTR_USER_PREFIX,
0455 .flags = XATTR_USER,
0456 .get = cifs_xattr_get,
0457 .set = cifs_xattr_set,
0458 };
0459
0460
0461 static const struct xattr_handler cifs_os2_xattr_handler = {
0462 .prefix = XATTR_OS2_PREFIX,
0463 .flags = XATTR_USER,
0464 .get = cifs_xattr_get,
0465 .set = cifs_xattr_set,
0466 };
0467
0468 static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
0469 .name = CIFS_XATTR_CIFS_ACL,
0470 .flags = XATTR_CIFS_ACL,
0471 .get = cifs_xattr_get,
0472 .set = cifs_xattr_set,
0473 };
0474
0475
0476
0477
0478
0479
0480
0481 static const struct xattr_handler smb3_acl_xattr_handler = {
0482 .name = SMB3_XATTR_CIFS_ACL,
0483 .flags = XATTR_CIFS_ACL,
0484 .get = cifs_xattr_get,
0485 .set = cifs_xattr_set,
0486 };
0487
0488 static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = {
0489 .name = CIFS_XATTR_CIFS_NTSD,
0490 .flags = XATTR_CIFS_NTSD,
0491 .get = cifs_xattr_get,
0492 .set = cifs_xattr_set,
0493 };
0494
0495
0496
0497
0498
0499
0500
0501 static const struct xattr_handler smb3_ntsd_xattr_handler = {
0502 .name = SMB3_XATTR_CIFS_NTSD,
0503 .flags = XATTR_CIFS_NTSD,
0504 .get = cifs_xattr_get,
0505 .set = cifs_xattr_set,
0506 };
0507
0508 static const struct xattr_handler cifs_cifs_ntsd_full_xattr_handler = {
0509 .name = CIFS_XATTR_CIFS_NTSD_FULL,
0510 .flags = XATTR_CIFS_NTSD_FULL,
0511 .get = cifs_xattr_get,
0512 .set = cifs_xattr_set,
0513 };
0514
0515
0516
0517
0518
0519
0520
0521 static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
0522 .name = SMB3_XATTR_CIFS_NTSD_FULL,
0523 .flags = XATTR_CIFS_NTSD_FULL,
0524 .get = cifs_xattr_get,
0525 .set = cifs_xattr_set,
0526 };
0527
0528
0529 static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
0530 .name = XATTR_NAME_POSIX_ACL_ACCESS,
0531 .flags = XATTR_ACL_ACCESS,
0532 .get = cifs_xattr_get,
0533 .set = cifs_xattr_set,
0534 };
0535
0536 static const struct xattr_handler cifs_posix_acl_default_xattr_handler = {
0537 .name = XATTR_NAME_POSIX_ACL_DEFAULT,
0538 .flags = XATTR_ACL_DEFAULT,
0539 .get = cifs_xattr_get,
0540 .set = cifs_xattr_set,
0541 };
0542
0543 const struct xattr_handler *cifs_xattr_handlers[] = {
0544 &cifs_user_xattr_handler,
0545 &cifs_os2_xattr_handler,
0546 &cifs_cifs_acl_xattr_handler,
0547 &smb3_acl_xattr_handler,
0548 &cifs_cifs_ntsd_xattr_handler,
0549 &smb3_ntsd_xattr_handler,
0550 &cifs_cifs_ntsd_full_xattr_handler,
0551 &smb3_ntsd_full_xattr_handler,
0552 &cifs_posix_acl_access_xattr_handler,
0553 &cifs_posix_acl_default_xattr_handler,
0554 NULL
0555 };