1*38c8a9a5SSteve French // SPDX-License-Identifier: LGPL-2.1 2*38c8a9a5SSteve French /* 3*38c8a9a5SSteve French * 4*38c8a9a5SSteve French * Copyright (c) International Business Machines Corp., 2003, 2007 5*38c8a9a5SSteve French * Author(s): Steve French (sfrench@us.ibm.com) 6*38c8a9a5SSteve French * 7*38c8a9a5SSteve French */ 8*38c8a9a5SSteve French 9*38c8a9a5SSteve French #include <linux/fs.h> 10*38c8a9a5SSteve French #include <linux/posix_acl_xattr.h> 11*38c8a9a5SSteve French #include <linux/slab.h> 12*38c8a9a5SSteve French #include <linux/xattr.h> 13*38c8a9a5SSteve French #include "cifsfs.h" 14*38c8a9a5SSteve French #include "cifspdu.h" 15*38c8a9a5SSteve French #include "cifsglob.h" 16*38c8a9a5SSteve French #include "cifsproto.h" 17*38c8a9a5SSteve French #include "cifs_debug.h" 18*38c8a9a5SSteve French #include "cifs_fs_sb.h" 19*38c8a9a5SSteve French #include "cifs_unicode.h" 20*38c8a9a5SSteve French #include "cifs_ioctl.h" 21*38c8a9a5SSteve French 22*38c8a9a5SSteve French #define MAX_EA_VALUE_SIZE CIFSMaxBufSize 23*38c8a9a5SSteve French #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* DACL only */ 24*38c8a9a5SSteve French #define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */ 25*38c8a9a5SSteve French #define CIFS_XATTR_CIFS_NTSD_FULL "system.cifs_ntsd_full" /* owner/DACL/SACL */ 26*38c8a9a5SSteve French #define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */ 27*38c8a9a5SSteve French #define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */ 28*38c8a9a5SSteve French /* 29*38c8a9a5SSteve French * Although these three are just aliases for the above, need to move away from 30*38c8a9a5SSteve French * confusing users and using the 20+ year old term 'cifs' when it is no longer 31*38c8a9a5SSteve French * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago 32*38c8a9a5SSteve French */ 33*38c8a9a5SSteve French #define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */ 34*38c8a9a5SSteve French #define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */ 35*38c8a9a5SSteve French #define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */ 36*38c8a9a5SSteve French #define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */ 37*38c8a9a5SSteve French #define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */ 38*38c8a9a5SSteve French /* BB need to add server (Samba e.g) support for security and trusted prefix */ 39*38c8a9a5SSteve French 40*38c8a9a5SSteve French enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT, 41*38c8a9a5SSteve French XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL }; 42*38c8a9a5SSteve French 43*38c8a9a5SSteve French static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon, 44*38c8a9a5SSteve French struct inode *inode, const char *full_path, 45*38c8a9a5SSteve French const void *value, size_t size) 46*38c8a9a5SSteve French { 47*38c8a9a5SSteve French ssize_t rc = -EOPNOTSUPP; 48*38c8a9a5SSteve French __u32 *pattrib = (__u32 *)value; 49*38c8a9a5SSteve French __u32 attrib; 50*38c8a9a5SSteve French FILE_BASIC_INFO info_buf; 51*38c8a9a5SSteve French 52*38c8a9a5SSteve French if ((value == NULL) || (size != sizeof(__u32))) 53*38c8a9a5SSteve French return -ERANGE; 54*38c8a9a5SSteve French 55*38c8a9a5SSteve French memset(&info_buf, 0, sizeof(info_buf)); 56*38c8a9a5SSteve French attrib = *pattrib; 57*38c8a9a5SSteve French info_buf.Attributes = cpu_to_le32(attrib); 58*38c8a9a5SSteve French if (pTcon->ses->server->ops->set_file_info) 59*38c8a9a5SSteve French rc = pTcon->ses->server->ops->set_file_info(inode, full_path, 60*38c8a9a5SSteve French &info_buf, xid); 61*38c8a9a5SSteve French if (rc == 0) 62*38c8a9a5SSteve French CIFS_I(inode)->cifsAttrs = attrib; 63*38c8a9a5SSteve French 64*38c8a9a5SSteve French return rc; 65*38c8a9a5SSteve French } 66*38c8a9a5SSteve French 67*38c8a9a5SSteve French static int cifs_creation_time_set(unsigned int xid, struct cifs_tcon *pTcon, 68*38c8a9a5SSteve French struct inode *inode, const char *full_path, 69*38c8a9a5SSteve French const void *value, size_t size) 70*38c8a9a5SSteve French { 71*38c8a9a5SSteve French ssize_t rc = -EOPNOTSUPP; 72*38c8a9a5SSteve French __u64 *pcreation_time = (__u64 *)value; 73*38c8a9a5SSteve French __u64 creation_time; 74*38c8a9a5SSteve French FILE_BASIC_INFO info_buf; 75*38c8a9a5SSteve French 76*38c8a9a5SSteve French if ((value == NULL) || (size != sizeof(__u64))) 77*38c8a9a5SSteve French return -ERANGE; 78*38c8a9a5SSteve French 79*38c8a9a5SSteve French memset(&info_buf, 0, sizeof(info_buf)); 80*38c8a9a5SSteve French creation_time = *pcreation_time; 81*38c8a9a5SSteve French info_buf.CreationTime = cpu_to_le64(creation_time); 82*38c8a9a5SSteve French if (pTcon->ses->server->ops->set_file_info) 83*38c8a9a5SSteve French rc = pTcon->ses->server->ops->set_file_info(inode, full_path, 84*38c8a9a5SSteve French &info_buf, xid); 85*38c8a9a5SSteve French if (rc == 0) 86*38c8a9a5SSteve French CIFS_I(inode)->createtime = creation_time; 87*38c8a9a5SSteve French 88*38c8a9a5SSteve French return rc; 89*38c8a9a5SSteve French } 90*38c8a9a5SSteve French 91*38c8a9a5SSteve French static int cifs_xattr_set(const struct xattr_handler *handler, 92*38c8a9a5SSteve French struct mnt_idmap *idmap, 93*38c8a9a5SSteve French struct dentry *dentry, struct inode *inode, 94*38c8a9a5SSteve French const char *name, const void *value, 95*38c8a9a5SSteve French size_t size, int flags) 96*38c8a9a5SSteve French { 97*38c8a9a5SSteve French int rc = -EOPNOTSUPP; 98*38c8a9a5SSteve French unsigned int xid; 99*38c8a9a5SSteve French struct super_block *sb = dentry->d_sb; 100*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 101*38c8a9a5SSteve French struct tcon_link *tlink; 102*38c8a9a5SSteve French struct cifs_tcon *pTcon; 103*38c8a9a5SSteve French const char *full_path; 104*38c8a9a5SSteve French void *page; 105*38c8a9a5SSteve French 106*38c8a9a5SSteve French tlink = cifs_sb_tlink(cifs_sb); 107*38c8a9a5SSteve French if (IS_ERR(tlink)) 108*38c8a9a5SSteve French return PTR_ERR(tlink); 109*38c8a9a5SSteve French pTcon = tlink_tcon(tlink); 110*38c8a9a5SSteve French 111*38c8a9a5SSteve French xid = get_xid(); 112*38c8a9a5SSteve French page = alloc_dentry_path(); 113*38c8a9a5SSteve French 114*38c8a9a5SSteve French full_path = build_path_from_dentry(dentry, page); 115*38c8a9a5SSteve French if (IS_ERR(full_path)) { 116*38c8a9a5SSteve French rc = PTR_ERR(full_path); 117*38c8a9a5SSteve French goto out; 118*38c8a9a5SSteve French } 119*38c8a9a5SSteve French /* return dos attributes as pseudo xattr */ 120*38c8a9a5SSteve French /* return alt name if available as pseudo attr */ 121*38c8a9a5SSteve French 122*38c8a9a5SSteve French /* if proc/fs/cifs/streamstoxattr is set then 123*38c8a9a5SSteve French search server for EAs or streams to 124*38c8a9a5SSteve French returns as xattrs */ 125*38c8a9a5SSteve French if (size > MAX_EA_VALUE_SIZE) { 126*38c8a9a5SSteve French cifs_dbg(FYI, "size of EA value too large\n"); 127*38c8a9a5SSteve French rc = -EOPNOTSUPP; 128*38c8a9a5SSteve French goto out; 129*38c8a9a5SSteve French } 130*38c8a9a5SSteve French 131*38c8a9a5SSteve French switch (handler->flags) { 132*38c8a9a5SSteve French case XATTR_USER: 133*38c8a9a5SSteve French cifs_dbg(FYI, "%s:setting user xattr %s\n", __func__, name); 134*38c8a9a5SSteve French if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) || 135*38c8a9a5SSteve French (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) { 136*38c8a9a5SSteve French rc = cifs_attrib_set(xid, pTcon, inode, full_path, 137*38c8a9a5SSteve French value, size); 138*38c8a9a5SSteve French if (rc == 0) /* force revalidate of the inode */ 139*38c8a9a5SSteve French CIFS_I(inode)->time = 0; 140*38c8a9a5SSteve French break; 141*38c8a9a5SSteve French } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) || 142*38c8a9a5SSteve French (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) { 143*38c8a9a5SSteve French rc = cifs_creation_time_set(xid, pTcon, inode, 144*38c8a9a5SSteve French full_path, value, size); 145*38c8a9a5SSteve French if (rc == 0) /* force revalidate of the inode */ 146*38c8a9a5SSteve French CIFS_I(inode)->time = 0; 147*38c8a9a5SSteve French break; 148*38c8a9a5SSteve French } 149*38c8a9a5SSteve French 150*38c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 151*38c8a9a5SSteve French goto out; 152*38c8a9a5SSteve French 153*38c8a9a5SSteve French if (pTcon->ses->server->ops->set_EA) 154*38c8a9a5SSteve French rc = pTcon->ses->server->ops->set_EA(xid, pTcon, 155*38c8a9a5SSteve French full_path, name, value, (__u16)size, 156*38c8a9a5SSteve French cifs_sb->local_nls, cifs_sb); 157*38c8a9a5SSteve French break; 158*38c8a9a5SSteve French 159*38c8a9a5SSteve French case XATTR_CIFS_ACL: 160*38c8a9a5SSteve French case XATTR_CIFS_NTSD: 161*38c8a9a5SSteve French case XATTR_CIFS_NTSD_FULL: { 162*38c8a9a5SSteve French struct cifs_ntsd *pacl; 163*38c8a9a5SSteve French 164*38c8a9a5SSteve French if (!value) 165*38c8a9a5SSteve French goto out; 166*38c8a9a5SSteve French pacl = kmalloc(size, GFP_KERNEL); 167*38c8a9a5SSteve French if (!pacl) { 168*38c8a9a5SSteve French rc = -ENOMEM; 169*38c8a9a5SSteve French } else { 170*38c8a9a5SSteve French memcpy(pacl, value, size); 171*38c8a9a5SSteve French if (pTcon->ses->server->ops->set_acl) { 172*38c8a9a5SSteve French int aclflags = 0; 173*38c8a9a5SSteve French rc = 0; 174*38c8a9a5SSteve French 175*38c8a9a5SSteve French switch (handler->flags) { 176*38c8a9a5SSteve French case XATTR_CIFS_NTSD_FULL: 177*38c8a9a5SSteve French aclflags = (CIFS_ACL_OWNER | 178*38c8a9a5SSteve French CIFS_ACL_GROUP | 179*38c8a9a5SSteve French CIFS_ACL_DACL | 180*38c8a9a5SSteve French CIFS_ACL_SACL); 181*38c8a9a5SSteve French break; 182*38c8a9a5SSteve French case XATTR_CIFS_NTSD: 183*38c8a9a5SSteve French aclflags = (CIFS_ACL_OWNER | 184*38c8a9a5SSteve French CIFS_ACL_GROUP | 185*38c8a9a5SSteve French CIFS_ACL_DACL); 186*38c8a9a5SSteve French break; 187*38c8a9a5SSteve French case XATTR_CIFS_ACL: 188*38c8a9a5SSteve French default: 189*38c8a9a5SSteve French aclflags = CIFS_ACL_DACL; 190*38c8a9a5SSteve French } 191*38c8a9a5SSteve French 192*38c8a9a5SSteve French rc = pTcon->ses->server->ops->set_acl(pacl, 193*38c8a9a5SSteve French size, inode, full_path, aclflags); 194*38c8a9a5SSteve French } else { 195*38c8a9a5SSteve French rc = -EOPNOTSUPP; 196*38c8a9a5SSteve French } 197*38c8a9a5SSteve French if (rc == 0) /* force revalidate of the inode */ 198*38c8a9a5SSteve French CIFS_I(inode)->time = 0; 199*38c8a9a5SSteve French kfree(pacl); 200*38c8a9a5SSteve French } 201*38c8a9a5SSteve French break; 202*38c8a9a5SSteve French } 203*38c8a9a5SSteve French } 204*38c8a9a5SSteve French 205*38c8a9a5SSteve French out: 206*38c8a9a5SSteve French free_dentry_path(page); 207*38c8a9a5SSteve French free_xid(xid); 208*38c8a9a5SSteve French cifs_put_tlink(tlink); 209*38c8a9a5SSteve French return rc; 210*38c8a9a5SSteve French } 211*38c8a9a5SSteve French 212*38c8a9a5SSteve French static int cifs_attrib_get(struct dentry *dentry, 213*38c8a9a5SSteve French struct inode *inode, void *value, 214*38c8a9a5SSteve French size_t size) 215*38c8a9a5SSteve French { 216*38c8a9a5SSteve French ssize_t rc; 217*38c8a9a5SSteve French __u32 *pattribute; 218*38c8a9a5SSteve French 219*38c8a9a5SSteve French rc = cifs_revalidate_dentry_attr(dentry); 220*38c8a9a5SSteve French 221*38c8a9a5SSteve French if (rc) 222*38c8a9a5SSteve French return rc; 223*38c8a9a5SSteve French 224*38c8a9a5SSteve French if ((value == NULL) || (size == 0)) 225*38c8a9a5SSteve French return sizeof(__u32); 226*38c8a9a5SSteve French else if (size < sizeof(__u32)) 227*38c8a9a5SSteve French return -ERANGE; 228*38c8a9a5SSteve French 229*38c8a9a5SSteve French /* return dos attributes as pseudo xattr */ 230*38c8a9a5SSteve French pattribute = (__u32 *)value; 231*38c8a9a5SSteve French *pattribute = CIFS_I(inode)->cifsAttrs; 232*38c8a9a5SSteve French 233*38c8a9a5SSteve French return sizeof(__u32); 234*38c8a9a5SSteve French } 235*38c8a9a5SSteve French 236*38c8a9a5SSteve French static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode, 237*38c8a9a5SSteve French void *value, size_t size) 238*38c8a9a5SSteve French { 239*38c8a9a5SSteve French ssize_t rc; 240*38c8a9a5SSteve French __u64 *pcreatetime; 241*38c8a9a5SSteve French 242*38c8a9a5SSteve French rc = cifs_revalidate_dentry_attr(dentry); 243*38c8a9a5SSteve French if (rc) 244*38c8a9a5SSteve French return rc; 245*38c8a9a5SSteve French 246*38c8a9a5SSteve French if ((value == NULL) || (size == 0)) 247*38c8a9a5SSteve French return sizeof(__u64); 248*38c8a9a5SSteve French else if (size < sizeof(__u64)) 249*38c8a9a5SSteve French return -ERANGE; 250*38c8a9a5SSteve French 251*38c8a9a5SSteve French /* return dos attributes as pseudo xattr */ 252*38c8a9a5SSteve French pcreatetime = (__u64 *)value; 253*38c8a9a5SSteve French *pcreatetime = CIFS_I(inode)->createtime; 254*38c8a9a5SSteve French return sizeof(__u64); 255*38c8a9a5SSteve French } 256*38c8a9a5SSteve French 257*38c8a9a5SSteve French 258*38c8a9a5SSteve French static int cifs_xattr_get(const struct xattr_handler *handler, 259*38c8a9a5SSteve French struct dentry *dentry, struct inode *inode, 260*38c8a9a5SSteve French const char *name, void *value, size_t size) 261*38c8a9a5SSteve French { 262*38c8a9a5SSteve French ssize_t rc = -EOPNOTSUPP; 263*38c8a9a5SSteve French unsigned int xid; 264*38c8a9a5SSteve French struct super_block *sb = dentry->d_sb; 265*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 266*38c8a9a5SSteve French struct tcon_link *tlink; 267*38c8a9a5SSteve French struct cifs_tcon *pTcon; 268*38c8a9a5SSteve French const char *full_path; 269*38c8a9a5SSteve French void *page; 270*38c8a9a5SSteve French 271*38c8a9a5SSteve French tlink = cifs_sb_tlink(cifs_sb); 272*38c8a9a5SSteve French if (IS_ERR(tlink)) 273*38c8a9a5SSteve French return PTR_ERR(tlink); 274*38c8a9a5SSteve French pTcon = tlink_tcon(tlink); 275*38c8a9a5SSteve French 276*38c8a9a5SSteve French xid = get_xid(); 277*38c8a9a5SSteve French page = alloc_dentry_path(); 278*38c8a9a5SSteve French 279*38c8a9a5SSteve French full_path = build_path_from_dentry(dentry, page); 280*38c8a9a5SSteve French if (IS_ERR(full_path)) { 281*38c8a9a5SSteve French rc = PTR_ERR(full_path); 282*38c8a9a5SSteve French goto out; 283*38c8a9a5SSteve French } 284*38c8a9a5SSteve French 285*38c8a9a5SSteve French /* return alt name if available as pseudo attr */ 286*38c8a9a5SSteve French switch (handler->flags) { 287*38c8a9a5SSteve French case XATTR_USER: 288*38c8a9a5SSteve French cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name); 289*38c8a9a5SSteve French if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) || 290*38c8a9a5SSteve French (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) { 291*38c8a9a5SSteve French rc = cifs_attrib_get(dentry, inode, value, size); 292*38c8a9a5SSteve French break; 293*38c8a9a5SSteve French } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) || 294*38c8a9a5SSteve French (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) { 295*38c8a9a5SSteve French rc = cifs_creation_time_get(dentry, inode, value, size); 296*38c8a9a5SSteve French break; 297*38c8a9a5SSteve French } 298*38c8a9a5SSteve French 299*38c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 300*38c8a9a5SSteve French goto out; 301*38c8a9a5SSteve French 302*38c8a9a5SSteve French if (pTcon->ses->server->ops->query_all_EAs) 303*38c8a9a5SSteve French rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, 304*38c8a9a5SSteve French full_path, name, value, size, cifs_sb); 305*38c8a9a5SSteve French break; 306*38c8a9a5SSteve French 307*38c8a9a5SSteve French case XATTR_CIFS_ACL: 308*38c8a9a5SSteve French case XATTR_CIFS_NTSD: 309*38c8a9a5SSteve French case XATTR_CIFS_NTSD_FULL: { 310*38c8a9a5SSteve French /* 311*38c8a9a5SSteve French * fetch owner, DACL, and SACL if asked for full descriptor, 312*38c8a9a5SSteve French * fetch owner and DACL otherwise 313*38c8a9a5SSteve French */ 314*38c8a9a5SSteve French u32 acllen, extra_info; 315*38c8a9a5SSteve French struct cifs_ntsd *pacl; 316*38c8a9a5SSteve French 317*38c8a9a5SSteve French if (pTcon->ses->server->ops->get_acl == NULL) 318*38c8a9a5SSteve French goto out; /* rc already EOPNOTSUPP */ 319*38c8a9a5SSteve French 320*38c8a9a5SSteve French if (handler->flags == XATTR_CIFS_NTSD_FULL) { 321*38c8a9a5SSteve French extra_info = SACL_SECINFO; 322*38c8a9a5SSteve French } else { 323*38c8a9a5SSteve French extra_info = 0; 324*38c8a9a5SSteve French } 325*38c8a9a5SSteve French pacl = pTcon->ses->server->ops->get_acl(cifs_sb, 326*38c8a9a5SSteve French inode, full_path, &acllen, extra_info); 327*38c8a9a5SSteve French if (IS_ERR(pacl)) { 328*38c8a9a5SSteve French rc = PTR_ERR(pacl); 329*38c8a9a5SSteve French cifs_dbg(VFS, "%s: error %zd getting sec desc\n", 330*38c8a9a5SSteve French __func__, rc); 331*38c8a9a5SSteve French } else { 332*38c8a9a5SSteve French if (value) { 333*38c8a9a5SSteve French if (acllen > size) 334*38c8a9a5SSteve French acllen = -ERANGE; 335*38c8a9a5SSteve French else 336*38c8a9a5SSteve French memcpy(value, pacl, acllen); 337*38c8a9a5SSteve French } 338*38c8a9a5SSteve French rc = acllen; 339*38c8a9a5SSteve French kfree(pacl); 340*38c8a9a5SSteve French } 341*38c8a9a5SSteve French break; 342*38c8a9a5SSteve French } 343*38c8a9a5SSteve French } 344*38c8a9a5SSteve French 345*38c8a9a5SSteve French /* We could add an additional check for streams ie 346*38c8a9a5SSteve French if proc/fs/cifs/streamstoxattr is set then 347*38c8a9a5SSteve French search server for EAs or streams to 348*38c8a9a5SSteve French returns as xattrs */ 349*38c8a9a5SSteve French 350*38c8a9a5SSteve French if (rc == -EINVAL) 351*38c8a9a5SSteve French rc = -EOPNOTSUPP; 352*38c8a9a5SSteve French 353*38c8a9a5SSteve French out: 354*38c8a9a5SSteve French free_dentry_path(page); 355*38c8a9a5SSteve French free_xid(xid); 356*38c8a9a5SSteve French cifs_put_tlink(tlink); 357*38c8a9a5SSteve French return rc; 358*38c8a9a5SSteve French } 359*38c8a9a5SSteve French 360*38c8a9a5SSteve French ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) 361*38c8a9a5SSteve French { 362*38c8a9a5SSteve French ssize_t rc = -EOPNOTSUPP; 363*38c8a9a5SSteve French unsigned int xid; 364*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); 365*38c8a9a5SSteve French struct tcon_link *tlink; 366*38c8a9a5SSteve French struct cifs_tcon *pTcon; 367*38c8a9a5SSteve French const char *full_path; 368*38c8a9a5SSteve French void *page; 369*38c8a9a5SSteve French 370*38c8a9a5SSteve French if (unlikely(cifs_forced_shutdown(cifs_sb))) 371*38c8a9a5SSteve French return -EIO; 372*38c8a9a5SSteve French 373*38c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 374*38c8a9a5SSteve French return -EOPNOTSUPP; 375*38c8a9a5SSteve French 376*38c8a9a5SSteve French tlink = cifs_sb_tlink(cifs_sb); 377*38c8a9a5SSteve French if (IS_ERR(tlink)) 378*38c8a9a5SSteve French return PTR_ERR(tlink); 379*38c8a9a5SSteve French pTcon = tlink_tcon(tlink); 380*38c8a9a5SSteve French 381*38c8a9a5SSteve French xid = get_xid(); 382*38c8a9a5SSteve French page = alloc_dentry_path(); 383*38c8a9a5SSteve French 384*38c8a9a5SSteve French full_path = build_path_from_dentry(direntry, page); 385*38c8a9a5SSteve French if (IS_ERR(full_path)) { 386*38c8a9a5SSteve French rc = PTR_ERR(full_path); 387*38c8a9a5SSteve French goto list_ea_exit; 388*38c8a9a5SSteve French } 389*38c8a9a5SSteve French /* return dos attributes as pseudo xattr */ 390*38c8a9a5SSteve French /* return alt name if available as pseudo attr */ 391*38c8a9a5SSteve French 392*38c8a9a5SSteve French /* if proc/fs/cifs/streamstoxattr is set then 393*38c8a9a5SSteve French search server for EAs or streams to 394*38c8a9a5SSteve French returns as xattrs */ 395*38c8a9a5SSteve French 396*38c8a9a5SSteve French if (pTcon->ses->server->ops->query_all_EAs) 397*38c8a9a5SSteve French rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, 398*38c8a9a5SSteve French full_path, NULL, data, buf_size, cifs_sb); 399*38c8a9a5SSteve French list_ea_exit: 400*38c8a9a5SSteve French free_dentry_path(page); 401*38c8a9a5SSteve French free_xid(xid); 402*38c8a9a5SSteve French cifs_put_tlink(tlink); 403*38c8a9a5SSteve French return rc; 404*38c8a9a5SSteve French } 405*38c8a9a5SSteve French 406*38c8a9a5SSteve French static const struct xattr_handler cifs_user_xattr_handler = { 407*38c8a9a5SSteve French .prefix = XATTR_USER_PREFIX, 408*38c8a9a5SSteve French .flags = XATTR_USER, 409*38c8a9a5SSteve French .get = cifs_xattr_get, 410*38c8a9a5SSteve French .set = cifs_xattr_set, 411*38c8a9a5SSteve French }; 412*38c8a9a5SSteve French 413*38c8a9a5SSteve French /* os2.* attributes are treated like user.* attributes */ 414*38c8a9a5SSteve French static const struct xattr_handler cifs_os2_xattr_handler = { 415*38c8a9a5SSteve French .prefix = XATTR_OS2_PREFIX, 416*38c8a9a5SSteve French .flags = XATTR_USER, 417*38c8a9a5SSteve French .get = cifs_xattr_get, 418*38c8a9a5SSteve French .set = cifs_xattr_set, 419*38c8a9a5SSteve French }; 420*38c8a9a5SSteve French 421*38c8a9a5SSteve French static const struct xattr_handler cifs_cifs_acl_xattr_handler = { 422*38c8a9a5SSteve French .name = CIFS_XATTR_CIFS_ACL, 423*38c8a9a5SSteve French .flags = XATTR_CIFS_ACL, 424*38c8a9a5SSteve French .get = cifs_xattr_get, 425*38c8a9a5SSteve French .set = cifs_xattr_set, 426*38c8a9a5SSteve French }; 427*38c8a9a5SSteve French 428*38c8a9a5SSteve French /* 429*38c8a9a5SSteve French * Although this is just an alias for the above, need to move away from 430*38c8a9a5SSteve French * confusing users and using the 20 year old term 'cifs' when it is no 431*38c8a9a5SSteve French * longer secure and was replaced by SMB2/SMB3 a long time ago, and 432*38c8a9a5SSteve French * SMB3 and later are highly secure. 433*38c8a9a5SSteve French */ 434*38c8a9a5SSteve French static const struct xattr_handler smb3_acl_xattr_handler = { 435*38c8a9a5SSteve French .name = SMB3_XATTR_CIFS_ACL, 436*38c8a9a5SSteve French .flags = XATTR_CIFS_ACL, 437*38c8a9a5SSteve French .get = cifs_xattr_get, 438*38c8a9a5SSteve French .set = cifs_xattr_set, 439*38c8a9a5SSteve French }; 440*38c8a9a5SSteve French 441*38c8a9a5SSteve French static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = { 442*38c8a9a5SSteve French .name = CIFS_XATTR_CIFS_NTSD, 443*38c8a9a5SSteve French .flags = XATTR_CIFS_NTSD, 444*38c8a9a5SSteve French .get = cifs_xattr_get, 445*38c8a9a5SSteve French .set = cifs_xattr_set, 446*38c8a9a5SSteve French }; 447*38c8a9a5SSteve French 448*38c8a9a5SSteve French /* 449*38c8a9a5SSteve French * Although this is just an alias for the above, need to move away from 450*38c8a9a5SSteve French * confusing users and using the 20 year old term 'cifs' when it is no 451*38c8a9a5SSteve French * longer secure and was replaced by SMB2/SMB3 a long time ago, and 452*38c8a9a5SSteve French * SMB3 and later are highly secure. 453*38c8a9a5SSteve French */ 454*38c8a9a5SSteve French static const struct xattr_handler smb3_ntsd_xattr_handler = { 455*38c8a9a5SSteve French .name = SMB3_XATTR_CIFS_NTSD, 456*38c8a9a5SSteve French .flags = XATTR_CIFS_NTSD, 457*38c8a9a5SSteve French .get = cifs_xattr_get, 458*38c8a9a5SSteve French .set = cifs_xattr_set, 459*38c8a9a5SSteve French }; 460*38c8a9a5SSteve French 461*38c8a9a5SSteve French static const struct xattr_handler cifs_cifs_ntsd_full_xattr_handler = { 462*38c8a9a5SSteve French .name = CIFS_XATTR_CIFS_NTSD_FULL, 463*38c8a9a5SSteve French .flags = XATTR_CIFS_NTSD_FULL, 464*38c8a9a5SSteve French .get = cifs_xattr_get, 465*38c8a9a5SSteve French .set = cifs_xattr_set, 466*38c8a9a5SSteve French }; 467*38c8a9a5SSteve French 468*38c8a9a5SSteve French /* 469*38c8a9a5SSteve French * Although this is just an alias for the above, need to move away from 470*38c8a9a5SSteve French * confusing users and using the 20 year old term 'cifs' when it is no 471*38c8a9a5SSteve French * longer secure and was replaced by SMB2/SMB3 a long time ago, and 472*38c8a9a5SSteve French * SMB3 and later are highly secure. 473*38c8a9a5SSteve French */ 474*38c8a9a5SSteve French static const struct xattr_handler smb3_ntsd_full_xattr_handler = { 475*38c8a9a5SSteve French .name = SMB3_XATTR_CIFS_NTSD_FULL, 476*38c8a9a5SSteve French .flags = XATTR_CIFS_NTSD_FULL, 477*38c8a9a5SSteve French .get = cifs_xattr_get, 478*38c8a9a5SSteve French .set = cifs_xattr_set, 479*38c8a9a5SSteve French }; 480*38c8a9a5SSteve French 481*38c8a9a5SSteve French const struct xattr_handler *cifs_xattr_handlers[] = { 482*38c8a9a5SSteve French &cifs_user_xattr_handler, 483*38c8a9a5SSteve French &cifs_os2_xattr_handler, 484*38c8a9a5SSteve French &cifs_cifs_acl_xattr_handler, 485*38c8a9a5SSteve French &smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */ 486*38c8a9a5SSteve French &cifs_cifs_ntsd_xattr_handler, 487*38c8a9a5SSteve French &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */ 488*38c8a9a5SSteve French &cifs_cifs_ntsd_full_xattr_handler, 489*38c8a9a5SSteve French &smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */ 490*38c8a9a5SSteve French NULL 491*38c8a9a5SSteve French }; 492