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