Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: LGPL-2.1
0002 /*
0003  *
0004  *   Copyright (c) International Business Machines  Corp., 2003, 2007
0005  *   Author(s): Steve French (sfrench@us.ibm.com)
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" /* DACL only */
0024 #define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */
0025 #define CIFS_XATTR_CIFS_NTSD_FULL "system.cifs_ntsd_full" /* owner/DACL/SACL */
0026 #define CIFS_XATTR_ATTRIB "cifs.dosattrib"  /* full name: user.cifs.dosattrib */
0027 #define CIFS_XATTR_CREATETIME "cifs.creationtime"  /* user.cifs.creationtime */
0028 /*
0029  * Although these three are just aliases for the above, need to move away from
0030  * confusing users and using the 20+ year old term 'cifs' when it is no longer
0031  * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago
0032  */
0033 #define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */
0034 #define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */
0035 #define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */
0036 #define SMB3_XATTR_ATTRIB "smb3.dosattrib"  /* full name: user.smb3.dosattrib */
0037 #define SMB3_XATTR_CREATETIME "smb3.creationtime"  /* user.smb3.creationtime */
0038 /* BB need to add server (Samba e.g) support for security and trusted prefix */
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     /* return dos attributes as pseudo xattr */
0120     /* return alt name if available as pseudo attr */
0121 
0122     /* if proc/fs/cifs/streamstoxattr is set then
0123         search server for EAs or streams to
0124         returns as xattrs */
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) /* force revalidate of the inode */
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) /* force revalidate of the inode */
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) /* force revalidate of the inode */
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  /* CONFIG_CIFS_POSIX */
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  /* CONFIG_CIFS_POSIX */
0227         break;
0228 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
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     /* return dos attributes as pseudo xattr */
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     /* return dos attributes as pseudo xattr */
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     /* return alt name if available as pseudo attr */
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          * fetch owner, DACL, and SACL if asked for full descriptor,
0338          * fetch owner and DACL otherwise
0339          */
0340         u32 acllen, extra_info;
0341         struct cifs_ntsd *pacl;
0342 
0343         if (pTcon->ses->server->ops->get_acl == NULL)
0344             goto out; /* rc already EOPNOTSUPP */
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  /* CONFIG_CIFS_POSIX */
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  /* CONFIG_CIFS_POSIX */
0388         break;
0389 #endif /* ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
0390     }
0391 
0392     /* We could add an additional check for streams ie
0393         if proc/fs/cifs/streamstoxattr is set then
0394         search server for EAs or streams to
0395         returns as xattrs */
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     /* return dos attributes as pseudo xattr */
0437     /* return alt name if available as pseudo attr */
0438 
0439     /* if proc/fs/cifs/streamstoxattr is set then
0440         search server for EAs or streams to
0441         returns as xattrs */
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 /* os2.* attributes are treated like user.* attributes */
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  * Although this is just an alias for the above, need to move away from
0477  * confusing users and using the 20 year old term 'cifs' when it is no
0478  * longer secure and was replaced by SMB2/SMB3 a long time ago, and
0479  * SMB3 and later are highly secure.
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  * Although this is just an alias for the above, need to move away from
0497  * confusing users and using the 20 year old term 'cifs' when it is no
0498  * longer secure and was replaced by SMB2/SMB3 a long time ago, and
0499  * SMB3 and later are highly secure.
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  * Although this is just an alias for the above, need to move away from
0517  * confusing users and using the 20 year old term 'cifs' when it is no
0518  * longer secure and was replaced by SMB2/SMB3 a long time ago, and
0519  * SMB3 and later are highly secure.
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, /* alias for above since avoiding "cifs" */
0548     &cifs_cifs_ntsd_xattr_handler,
0549     &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */
0550     &cifs_cifs_ntsd_full_xattr_handler,
0551     &smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */
0552     &cifs_posix_acl_access_xattr_handler,
0553     &cifs_posix_acl_default_xattr_handler,
0554     NULL
0555 };