1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2024 Paulo Alcantara <pc@manguebit.com> 4 */ 5 6 #include <linux/fs.h> 7 #include <linux/stat.h> 8 #include <linux/slab.h> 9 #include "cifsglob.h" 10 #include "smb2proto.h" 11 #include "cifsproto.h" 12 #include "cifs_unicode.h" 13 #include "cifs_debug.h" 14 #include "fs_context.h" 15 #include "reparse.h" 16 17 static int mknod_nfs(unsigned int xid, struct inode *inode, 18 struct dentry *dentry, struct cifs_tcon *tcon, 19 const char *full_path, umode_t mode, dev_t dev, 20 const char *symname); 21 22 static int mknod_wsl(unsigned int xid, struct inode *inode, 23 struct dentry *dentry, struct cifs_tcon *tcon, 24 const char *full_path, umode_t mode, dev_t dev, 25 const char *symname); 26 27 static int create_native_symlink(const unsigned int xid, struct inode *inode, 28 struct dentry *dentry, struct cifs_tcon *tcon, 29 const char *full_path, const char *symname); 30 31 static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb, 32 const unsigned int xid, 33 const char *full_path, 34 const char *symname, 35 bool *directory); 36 37 int create_reparse_symlink(const unsigned int xid, struct inode *inode, 38 struct dentry *dentry, struct cifs_tcon *tcon, 39 const char *full_path, const char *symname) 40 { 41 switch (cifs_symlink_type(CIFS_SB(inode->i_sb))) { 42 case CIFS_SYMLINK_TYPE_NATIVE: 43 return create_native_symlink(xid, inode, dentry, tcon, full_path, symname); 44 case CIFS_SYMLINK_TYPE_NFS: 45 return mknod_nfs(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symname); 46 case CIFS_SYMLINK_TYPE_WSL: 47 return mknod_wsl(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symname); 48 default: 49 return -EOPNOTSUPP; 50 } 51 } 52 53 static int create_native_symlink(const unsigned int xid, struct inode *inode, 54 struct dentry *dentry, struct cifs_tcon *tcon, 55 const char *full_path, const char *symname) 56 { 57 struct reparse_symlink_data_buffer *buf = NULL; 58 struct cifs_sb_info *cifs_sb = CIFS_SB(inode); 59 const char *symroot = cifs_sb->ctx->symlinkroot; 60 struct cifs_open_info_data data = {}; 61 char sep = CIFS_DIR_SEP(cifs_sb); 62 char *symlink_target = NULL; 63 u16 len, plen, poff, slen; 64 unsigned int sbflags; 65 __le16 *path = NULL; 66 struct inode *new; 67 char *sym = NULL; 68 struct kvec iov; 69 bool directory; 70 int rc = 0; 71 72 if (strlen(symname) > REPARSE_SYM_PATH_MAX) 73 return -ENAMETOOLONG; 74 75 symlink_target = kstrdup(symname, GFP_KERNEL); 76 if (!symlink_target) { 77 rc = -ENOMEM; 78 goto out; 79 } 80 81 data = (struct cifs_open_info_data) { 82 .reparse_point = true, 83 .reparse = { .tag = IO_REPARSE_TAG_SYMLINK, }, 84 .symlink_target = symlink_target, 85 }; 86 87 sbflags = cifs_sb_flags(cifs_sb); 88 if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symroot && symname[0] == '/') { 89 /* 90 * This is a request to create an absolute symlink on the server 91 * which does not support POSIX paths, and expects symlink in 92 * NT-style path. So convert absolute Linux symlink target path 93 * to the absolute NT-style path. Root of the NT-style path for 94 * symlinks is specified in "symlinkroot" mount option. This will 95 * ensure compatibility of this symlink stored in absolute form 96 * on the SMB server. 97 */ 98 if (!strstarts(symname, symroot)) { 99 /* 100 * If the absolute Linux symlink target path is not 101 * inside "symlinkroot" location then there is no way 102 * to convert such Linux symlink to NT-style path. 103 */ 104 cifs_dbg(VFS, 105 "absolute symlink '%s' cannot be converted to NT format " 106 "because it is outside of symlinkroot='%s'\n", 107 symname, symroot); 108 rc = -EINVAL; 109 goto out; 110 } 111 len = strlen(symroot); 112 if (symroot[len - 1] != '/') 113 len++; 114 if (symname[len] >= 'a' && symname[len] <= 'z' && 115 (symname[len+1] == '/' || symname[len+1] == '\0')) { 116 /* 117 * Symlink points to Linux target /symlinkroot/x/path/... 118 * where 'x' is the lowercase local Windows drive. 119 * NT-style path for 'x' has common form \??\X:\path\... 120 * with uppercase local Windows drive. 121 */ 122 int common_path_len = strlen(symname+len+1)+1; 123 sym = kzalloc(6+common_path_len, GFP_KERNEL); 124 if (!sym) { 125 rc = -ENOMEM; 126 goto out; 127 } 128 memcpy(sym, "\\??\\", 4); 129 sym[4] = symname[len] - ('a'-'A'); 130 sym[5] = ':'; 131 memcpy(sym+6, symname+len+1, common_path_len); 132 } else { 133 /* Unhandled absolute symlink. Report an error. */ 134 cifs_dbg( 135 VFS, 136 "absolute symlink '%s' cannot be converted to NT format " 137 "because it points to unknown target\n", 138 symname); 139 rc = -EINVAL; 140 goto out; 141 } 142 } else { 143 /* 144 * This is request to either create an absolute symlink on 145 * server which expects POSIX paths or it is an request to 146 * create a relative symlink from the current directory. 147 * These paths have same format as relative SMB symlinks, 148 * so no conversion is needed. So just take symname as-is. 149 */ 150 sym = kstrdup(symname, GFP_KERNEL); 151 if (!sym) { 152 rc = -ENOMEM; 153 goto out; 154 } 155 } 156 157 if (sep == '\\') 158 convert_delimiter(sym, sep); 159 160 /* 161 * For absolute NT symlinks it is required to pass also leading 162 * backslash and to not mangle NT object prefix "\\??\\" and not to 163 * mangle colon in drive letter. But cifs_convert_path_to_utf16() 164 * removes leading backslash and replaces '?' and ':'. So temporary 165 * mask these characters in NT object prefix by '_' and then change 166 * them back. 167 */ 168 if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') 169 sym[0] = sym[1] = sym[2] = sym[5] = '_'; 170 171 path = cifs_convert_path_to_utf16(sym, cifs_sb); 172 if (!path) { 173 rc = -ENOMEM; 174 goto out; 175 } 176 177 if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') { 178 sym[0] = '\\'; 179 sym[1] = sym[2] = '?'; 180 sym[5] = ':'; 181 path[0] = cpu_to_le16('\\'); 182 path[1] = path[2] = cpu_to_le16('?'); 183 path[5] = cpu_to_le16(':'); 184 } 185 186 /* 187 * SMB distinguish between symlink to directory and symlink to file. 188 * They cannot be exchanged (symlink of file type which points to 189 * directory cannot be resolved and vice-versa). Try to detect if 190 * the symlink target could be a directory or not. When detection 191 * fails then treat symlink as a file (non-directory) symlink. 192 */ 193 directory = false; 194 rc = detect_directory_symlink_target(cifs_sb, xid, full_path, symname, &directory); 195 if (rc < 0) 196 goto out; 197 198 slen = 2 * UniStrnlen((wchar_t *)path, REPARSE_SYM_PATH_MAX); 199 poff = 0; 200 plen = slen; 201 if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') { 202 /* 203 * For absolute NT symlinks skip leading "\\??\\" in PrintName as 204 * PrintName is user visible location in DOS/Win32 format (not in NT format). 205 */ 206 poff = 4; 207 plen -= 2 * poff; 208 } 209 len = sizeof(*buf) + plen + slen; 210 buf = kzalloc(len, GFP_KERNEL); 211 if (!buf) { 212 rc = -ENOMEM; 213 goto out; 214 } 215 216 buf->ReparseTag = cpu_to_le32(IO_REPARSE_TAG_SYMLINK); 217 buf->ReparseDataLength = cpu_to_le16(len - sizeof(struct reparse_data_buffer)); 218 219 buf->SubstituteNameOffset = cpu_to_le16(plen); 220 buf->SubstituteNameLength = cpu_to_le16(slen); 221 memcpy(&buf->PathBuffer[plen], path, slen); 222 223 buf->PrintNameOffset = 0; 224 buf->PrintNameLength = cpu_to_le16(plen); 225 memcpy(buf->PathBuffer, path+poff, plen); 226 227 buf->Flags = cpu_to_le32(*symname != '/' ? SYMLINK_FLAG_RELATIVE : 0); 228 229 iov.iov_base = buf; 230 iov.iov_len = len; 231 new = tcon->ses->server->ops->create_reparse_inode( 232 &data, inode->i_sb, xid, 233 tcon, full_path, directory, 234 &iov, NULL); 235 if (!IS_ERR(new)) 236 d_instantiate(dentry, new); 237 else 238 rc = PTR_ERR(new); 239 out: 240 kfree(sym); 241 kfree(path); 242 cifs_free_open_info(&data); 243 kfree(buf); 244 return rc; 245 } 246 247 static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb, 248 const unsigned int xid, 249 const char *full_path, 250 const char *symname, 251 bool *directory) 252 { 253 char sep = CIFS_DIR_SEP(cifs_sb); 254 struct cifs_open_parms oparms; 255 struct tcon_link *tlink; 256 struct cifs_tcon *tcon; 257 const char *basename; 258 struct cifs_fid fid; 259 char *resolved_path; 260 int full_path_len; 261 int basename_len; 262 int symname_len; 263 char *path_sep; 264 __u32 oplock; 265 int open_rc; 266 267 /* 268 * First do some simple check. If the original Linux symlink target ends 269 * with slash, or last path component is dot or dot-dot then it is for 270 * sure symlink to the directory. 271 */ 272 basename = kbasename(symname); 273 basename_len = strlen(basename); 274 if (basename_len == 0 || /* symname ends with slash */ 275 (basename_len == 1 && basename[0] == '.') || /* last component is "." */ 276 (basename_len == 2 && basename[0] == '.' && basename[1] == '.')) { /* or ".." */ 277 *directory = true; 278 return 0; 279 } 280 281 /* 282 * For absolute symlinks it is not possible to determine 283 * if it should point to directory or file. 284 */ 285 if (symname[0] == '/') { 286 cifs_dbg(FYI, 287 "%s: cannot determinate if the symlink target path '%s' " 288 "is directory or not, creating '%s' as file symlink\n", 289 __func__, symname, full_path); 290 return 0; 291 } 292 293 /* 294 * If it was not detected as directory yet and the symlink is relative 295 * then try to resolve the path on the SMB server, check if the path 296 * exists and determinate if it is a directory or not. 297 */ 298 299 full_path_len = strlen(full_path); 300 symname_len = strlen(symname); 301 302 tlink = cifs_sb_tlink(cifs_sb); 303 if (IS_ERR(tlink)) 304 return PTR_ERR(tlink); 305 306 resolved_path = kzalloc(full_path_len + symname_len + 1, GFP_KERNEL); 307 if (!resolved_path) { 308 cifs_put_tlink(tlink); 309 return -ENOMEM; 310 } 311 312 /* 313 * Compose the resolved SMB symlink path from the SMB full path 314 * and Linux target symlink path. 315 */ 316 memcpy(resolved_path, full_path, full_path_len+1); 317 path_sep = strrchr(resolved_path, sep); 318 if (path_sep) 319 path_sep++; 320 else 321 path_sep = resolved_path; 322 memcpy(path_sep, symname, symname_len+1); 323 if (sep == '\\') 324 convert_delimiter(path_sep, sep); 325 326 tcon = tlink_tcon(tlink); 327 oparms = CIFS_OPARMS(cifs_sb, tcon, resolved_path, 328 FILE_READ_ATTRIBUTES, FILE_OPEN, 0, ACL_NO_MODE); 329 oparms.fid = &fid; 330 331 /* Try to open as a directory (NOT_FILE) */ 332 oplock = 0; 333 oparms.create_options = cifs_create_options(cifs_sb, 334 CREATE_NOT_FILE | OPEN_REPARSE_POINT); 335 open_rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); 336 if (open_rc == 0) { 337 /* Successful open means that the target path is definitely a directory. */ 338 *directory = true; 339 tcon->ses->server->ops->close(xid, tcon, &fid); 340 } else if (open_rc == -ENOTDIR) { 341 /* -ENOTDIR means that the target path is definitely a file. */ 342 *directory = false; 343 } else if (open_rc == -ENOENT) { 344 /* -ENOENT means that the target path does not exist. */ 345 cifs_dbg(FYI, 346 "%s: symlink target path '%s' does not exist, " 347 "creating '%s' as file symlink\n", 348 __func__, symname, full_path); 349 } else { 350 /* Try to open as a file (NOT_DIR) */ 351 oplock = 0; 352 oparms.create_options = cifs_create_options(cifs_sb, 353 CREATE_NOT_DIR | OPEN_REPARSE_POINT); 354 open_rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); 355 if (open_rc == 0) { 356 /* Successful open means that the target path is definitely a file. */ 357 *directory = false; 358 tcon->ses->server->ops->close(xid, tcon, &fid); 359 } else if (open_rc == -EISDIR) { 360 /* -EISDIR means that the target path is definitely a directory. */ 361 *directory = true; 362 } else { 363 /* 364 * This code branch is called when we do not have a permission to 365 * open the resolved_path or some other client/process denied 366 * opening the resolved_path. 367 * 368 * TODO: Try to use ops->query_dir_first on the parent directory 369 * of resolved_path, search for basename of resolved_path and 370 * check if the ATTR_DIRECTORY is set in fi.Attributes. In some 371 * case this could work also when opening of the path is denied. 372 */ 373 cifs_dbg(FYI, 374 "%s: cannot determinate if the symlink target path '%s' " 375 "is directory or not, creating '%s' as file symlink\n", 376 __func__, symname, full_path); 377 } 378 } 379 380 kfree(resolved_path); 381 cifs_put_tlink(tlink); 382 return 0; 383 } 384 385 static int create_native_socket(const unsigned int xid, struct inode *inode, 386 struct dentry *dentry, struct cifs_tcon *tcon, 387 const char *full_path) 388 { 389 struct reparse_data_buffer buf = { 390 .ReparseTag = cpu_to_le32(IO_REPARSE_TAG_AF_UNIX), 391 .ReparseDataLength = cpu_to_le16(0), 392 }; 393 struct cifs_open_info_data data = { 394 .reparse_point = true, 395 .reparse = { .tag = IO_REPARSE_TAG_AF_UNIX, .buf = &buf, }, 396 }; 397 struct kvec iov = { 398 .iov_base = &buf, 399 .iov_len = sizeof(buf), 400 }; 401 struct inode *new; 402 int rc = 0; 403 404 new = tcon->ses->server->ops->create_reparse_inode( 405 &data, inode->i_sb, xid, 406 tcon, full_path, false, &iov, NULL); 407 if (!IS_ERR(new)) 408 d_instantiate(dentry, new); 409 else 410 rc = PTR_ERR(new); 411 cifs_free_open_info(&data); 412 return rc; 413 } 414 415 static int nfs_set_reparse_buf(struct reparse_nfs_data_buffer *buf, 416 mode_t mode, dev_t dev, 417 __le16 *symname_utf16, 418 int symname_utf16_len, 419 struct kvec *iov) 420 { 421 u64 type; 422 u16 len, dlen; 423 424 len = sizeof(*buf); 425 426 switch ((type = reparse_mode_nfs_type(mode))) { 427 case NFS_SPECFILE_BLK: 428 case NFS_SPECFILE_CHR: 429 dlen = 2 * sizeof(__le32); 430 ((__le32 *)buf->DataBuffer)[0] = cpu_to_le32(MAJOR(dev)); 431 ((__le32 *)buf->DataBuffer)[1] = cpu_to_le32(MINOR(dev)); 432 break; 433 case NFS_SPECFILE_LNK: 434 dlen = symname_utf16_len; 435 memcpy(buf->DataBuffer, symname_utf16, symname_utf16_len); 436 break; 437 case NFS_SPECFILE_FIFO: 438 case NFS_SPECFILE_SOCK: 439 dlen = 0; 440 break; 441 default: 442 return -EOPNOTSUPP; 443 } 444 445 buf->ReparseTag = cpu_to_le32(IO_REPARSE_TAG_NFS); 446 buf->Reserved = 0; 447 buf->InodeType = cpu_to_le64(type); 448 buf->ReparseDataLength = cpu_to_le16(len + dlen - 449 sizeof(struct reparse_data_buffer)); 450 iov->iov_base = buf; 451 iov->iov_len = len + dlen; 452 return 0; 453 } 454 455 static int mknod_nfs(unsigned int xid, struct inode *inode, 456 struct dentry *dentry, struct cifs_tcon *tcon, 457 const char *full_path, umode_t mode, dev_t dev, 458 const char *symname) 459 { 460 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 461 struct cifs_open_info_data data; 462 struct reparse_nfs_data_buffer *p = NULL; 463 __le16 *symname_utf16 = NULL; 464 int symname_utf16_len = 0; 465 struct inode *new; 466 struct kvec iov; 467 __u8 buf[sizeof(*p) + sizeof(__le64)]; 468 int rc; 469 470 if (S_ISLNK(mode)) { 471 symname_utf16 = cifs_strndup_to_utf16(symname, strlen(symname), 472 &symname_utf16_len, 473 cifs_sb->local_nls, 474 NO_MAP_UNI_RSVD); 475 if (!symname_utf16) { 476 rc = -ENOMEM; 477 goto out; 478 } 479 symname_utf16_len -= 2; /* symlink is without trailing wide-nul */ 480 p = kzalloc(sizeof(*p) + symname_utf16_len, GFP_KERNEL); 481 if (!p) { 482 rc = -ENOMEM; 483 goto out; 484 } 485 } else { 486 p = (struct reparse_nfs_data_buffer *)buf; 487 } 488 rc = nfs_set_reparse_buf(p, mode, dev, symname_utf16, symname_utf16_len, &iov); 489 if (rc) 490 goto out; 491 492 data = (struct cifs_open_info_data) { 493 .reparse_point = true, 494 .reparse = { .tag = IO_REPARSE_TAG_NFS, .buf = (struct reparse_data_buffer *)p, }, 495 .symlink_target = kstrdup(symname, GFP_KERNEL), 496 }; 497 498 new = tcon->ses->server->ops->create_reparse_inode( 499 &data, inode->i_sb, xid, 500 tcon, full_path, false, &iov, NULL); 501 if (!IS_ERR(new)) 502 d_instantiate(dentry, new); 503 else 504 rc = PTR_ERR(new); 505 cifs_free_open_info(&data); 506 out: 507 if (S_ISLNK(mode)) { 508 kfree(symname_utf16); 509 kfree(p); 510 } 511 return rc; 512 } 513 514 static int wsl_set_reparse_buf(struct reparse_data_buffer **buf, 515 mode_t mode, const char *symname, 516 struct cifs_sb_info *cifs_sb, 517 struct kvec *iov) 518 { 519 struct reparse_wsl_symlink_data_buffer *symlink_buf; 520 __le16 *symname_utf16; 521 int symname_utf16_len; 522 int symname_utf8_maxlen; 523 int symname_utf8_len; 524 size_t buf_len; 525 u32 tag; 526 527 switch ((tag = reparse_mode_wsl_tag(mode))) { 528 case IO_REPARSE_TAG_LX_BLK: 529 case IO_REPARSE_TAG_LX_CHR: 530 case IO_REPARSE_TAG_LX_FIFO: 531 case IO_REPARSE_TAG_AF_UNIX: 532 buf_len = sizeof(struct reparse_data_buffer); 533 *buf = kzalloc(buf_len, GFP_KERNEL); 534 if (!*buf) 535 return -ENOMEM; 536 break; 537 case IO_REPARSE_TAG_LX_SYMLINK: 538 symname_utf16 = cifs_strndup_to_utf16(symname, strlen(symname), 539 &symname_utf16_len, 540 cifs_sb->local_nls, 541 NO_MAP_UNI_RSVD); 542 if (!symname_utf16) 543 return -ENOMEM; 544 symname_utf8_maxlen = symname_utf16_len/2*3; 545 symlink_buf = kzalloc(sizeof(struct reparse_wsl_symlink_data_buffer) + 546 symname_utf8_maxlen, GFP_KERNEL); 547 if (!symlink_buf) { 548 kfree(symname_utf16); 549 return -ENOMEM; 550 } 551 /* Version field must be set to 2 (MS-FSCC 2.1.2.7) */ 552 symlink_buf->Version = cpu_to_le32(2); 553 /* Target for Version 2 is in UTF-8 but without trailing null-term byte */ 554 symname_utf8_len = utf16s_to_utf8s((wchar_t *)symname_utf16, symname_utf16_len/2, 555 UTF16_LITTLE_ENDIAN, 556 symlink_buf->Target, 557 symname_utf8_maxlen); 558 *buf = (struct reparse_data_buffer *)symlink_buf; 559 buf_len = sizeof(struct reparse_wsl_symlink_data_buffer) + symname_utf8_len; 560 kfree(symname_utf16); 561 break; 562 default: 563 return -EOPNOTSUPP; 564 } 565 566 (*buf)->ReparseTag = cpu_to_le32(tag); 567 (*buf)->Reserved = 0; 568 (*buf)->ReparseDataLength = cpu_to_le16(buf_len - sizeof(struct reparse_data_buffer)); 569 iov->iov_base = *buf; 570 iov->iov_len = buf_len; 571 return 0; 572 } 573 574 static struct smb2_create_ea_ctx *ea_create_context(u32 dlen, size_t *cc_len) 575 { 576 struct smb2_create_ea_ctx *cc; 577 578 *cc_len = round_up(sizeof(*cc) + dlen, 8); 579 cc = kzalloc(*cc_len, GFP_KERNEL); 580 if (!cc) 581 return ERR_PTR(-ENOMEM); 582 583 cc->ctx.NameOffset = cpu_to_le16(offsetof(struct smb2_create_ea_ctx, 584 name)); 585 cc->ctx.NameLength = cpu_to_le16(4); 586 memcpy(cc->name, SMB2_CREATE_EA_BUFFER, strlen(SMB2_CREATE_EA_BUFFER)); 587 cc->ctx.DataOffset = cpu_to_le16(offsetof(struct smb2_create_ea_ctx, ea)); 588 cc->ctx.DataLength = cpu_to_le32(dlen); 589 return cc; 590 } 591 592 struct wsl_xattr { 593 const char *name; 594 __le64 value; 595 u16 size; 596 u32 next; 597 }; 598 599 static int wsl_set_xattrs(struct inode *inode, umode_t _mode, 600 dev_t _dev, struct kvec *iov) 601 { 602 struct smb2_file_full_ea_info *ea; 603 struct smb2_create_ea_ctx *cc; 604 struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx; 605 __le64 uid = cpu_to_le64(from_kuid(current_user_ns(), ctx->linux_uid)); 606 __le64 gid = cpu_to_le64(from_kgid(current_user_ns(), ctx->linux_gid)); 607 __le64 dev = cpu_to_le64(((u64)MINOR(_dev) << 32) | MAJOR(_dev)); 608 __le64 mode = cpu_to_le64(_mode); 609 struct wsl_xattr xattrs[] = { 610 { .name = SMB2_WSL_XATTR_UID, .value = uid, .size = SMB2_WSL_XATTR_UID_SIZE, }, 611 { .name = SMB2_WSL_XATTR_GID, .value = gid, .size = SMB2_WSL_XATTR_GID_SIZE, }, 612 { .name = SMB2_WSL_XATTR_MODE, .value = mode, .size = SMB2_WSL_XATTR_MODE_SIZE, }, 613 { .name = SMB2_WSL_XATTR_DEV, .value = dev, .size = SMB2_WSL_XATTR_DEV_SIZE, }, 614 }; 615 size_t cc_len; 616 u32 dlen = 0, next = 0; 617 int i, num_xattrs; 618 u8 name_size = SMB2_WSL_XATTR_NAME_LEN + 1; 619 620 memset(iov, 0, sizeof(*iov)); 621 622 /* Exclude $LXDEV xattr for non-device files */ 623 if (!S_ISBLK(_mode) && !S_ISCHR(_mode)) 624 num_xattrs = ARRAY_SIZE(xattrs) - 1; 625 else 626 num_xattrs = ARRAY_SIZE(xattrs); 627 628 for (i = 0; i < num_xattrs; i++) { 629 xattrs[i].next = ALIGN(sizeof(*ea) + name_size + 630 xattrs[i].size, 4); 631 dlen += xattrs[i].next; 632 } 633 634 cc = ea_create_context(dlen, &cc_len); 635 if (IS_ERR(cc)) 636 return PTR_ERR(cc); 637 638 ea = &cc->ea; 639 for (i = 0; i < num_xattrs; i++) { 640 ea = (void *)((u8 *)ea + next); 641 next = xattrs[i].next; 642 ea->next_entry_offset = cpu_to_le32(next); 643 644 ea->ea_name_length = name_size - 1; 645 ea->ea_value_length = cpu_to_le16(xattrs[i].size); 646 memcpy(ea->ea_data, xattrs[i].name, name_size); 647 memcpy(&ea->ea_data[name_size], 648 &xattrs[i].value, xattrs[i].size); 649 } 650 ea->next_entry_offset = 0; 651 652 iov->iov_base = cc; 653 iov->iov_len = cc_len; 654 return 0; 655 } 656 657 static int mknod_wsl(unsigned int xid, struct inode *inode, 658 struct dentry *dentry, struct cifs_tcon *tcon, 659 const char *full_path, umode_t mode, dev_t dev, 660 const char *symname) 661 { 662 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 663 struct cifs_open_info_data data; 664 struct reparse_data_buffer *buf; 665 struct smb2_create_ea_ctx *cc; 666 struct inode *new; 667 unsigned int len; 668 struct kvec reparse_iov, xattr_iov; 669 int rc; 670 671 rc = wsl_set_reparse_buf(&buf, mode, symname, cifs_sb, &reparse_iov); 672 if (rc) 673 return rc; 674 675 rc = wsl_set_xattrs(inode, mode, dev, &xattr_iov); 676 if (rc) { 677 kfree(buf); 678 return rc; 679 } 680 681 data = (struct cifs_open_info_data) { 682 .reparse_point = true, 683 .reparse = { .tag = le32_to_cpu(buf->ReparseTag), .buf = buf, }, 684 .symlink_target = kstrdup(symname, GFP_KERNEL), 685 }; 686 687 cc = xattr_iov.iov_base; 688 len = le32_to_cpu(cc->ctx.DataLength); 689 memcpy(data.wsl.eas, &cc->ea, len); 690 data.wsl.eas_len = len; 691 692 new = tcon->ses->server->ops->create_reparse_inode( 693 &data, inode->i_sb, 694 xid, tcon, full_path, false, 695 &reparse_iov, &xattr_iov); 696 if (!IS_ERR(new)) 697 d_instantiate(dentry, new); 698 else 699 rc = PTR_ERR(new); 700 cifs_free_open_info(&data); 701 kfree(xattr_iov.iov_base); 702 kfree(buf); 703 return rc; 704 } 705 706 int mknod_reparse(unsigned int xid, struct inode *inode, 707 struct dentry *dentry, struct cifs_tcon *tcon, 708 const char *full_path, umode_t mode, dev_t dev) 709 { 710 struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx; 711 712 if (S_ISSOCK(mode) && !ctx->nonativesocket && ctx->reparse_type != CIFS_REPARSE_TYPE_NONE) 713 return create_native_socket(xid, inode, dentry, tcon, full_path); 714 715 switch (ctx->reparse_type) { 716 case CIFS_REPARSE_TYPE_NFS: 717 return mknod_nfs(xid, inode, dentry, tcon, full_path, mode, dev, NULL); 718 case CIFS_REPARSE_TYPE_WSL: 719 return mknod_wsl(xid, inode, dentry, tcon, full_path, mode, dev, NULL); 720 default: 721 return -EOPNOTSUPP; 722 } 723 } 724 725 /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */ 726 static int parse_reparse_nfs(struct reparse_nfs_data_buffer *buf, 727 struct cifs_sb_info *cifs_sb, 728 struct cifs_open_info_data *data) 729 { 730 unsigned int len; 731 u64 type; 732 733 len = le16_to_cpu(buf->ReparseDataLength); 734 if (len < sizeof(buf->InodeType)) { 735 cifs_dbg(VFS, "srv returned malformed nfs buffer\n"); 736 return smb_EIO2(smb_eio_trace_reparse_nfs_too_short, 737 len, sizeof(buf->InodeType)); 738 } 739 740 len -= sizeof(buf->InodeType); 741 742 switch ((type = le64_to_cpu(buf->InodeType))) { 743 case NFS_SPECFILE_LNK: 744 if (len == 0 || (len % 2)) { 745 cifs_dbg(VFS, "srv returned malformed nfs symlink buffer\n"); 746 return smb_EIO1(smb_eio_trace_reparse_nfs_symbuf, len); 747 } 748 /* 749 * Check that buffer does not contain UTF-16 null codepoint 750 * because Linux cannot process symlink with null byte. 751 */ 752 if (UniStrnlen((wchar_t *)buf->DataBuffer, len/2) != len/2) { 753 cifs_dbg(VFS, "srv returned null byte in nfs symlink target location\n"); 754 return smb_EIO1(smb_eio_trace_reparse_nfs_nul, len); 755 } 756 data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer, 757 len, true, 758 cifs_sb->local_nls); 759 if (!data->symlink_target) 760 return -ENOMEM; 761 cifs_dbg(FYI, "%s: target path: %s\n", 762 __func__, data->symlink_target); 763 break; 764 case NFS_SPECFILE_CHR: 765 case NFS_SPECFILE_BLK: 766 /* DataBuffer for block and char devices contains two 32-bit numbers */ 767 if (len != 8) { 768 cifs_dbg(VFS, "srv returned malformed nfs buffer for type: 0x%llx\n", type); 769 return smb_EIO1(smb_eio_trace_reparse_nfs_dev, len); 770 } 771 break; 772 case NFS_SPECFILE_FIFO: 773 case NFS_SPECFILE_SOCK: 774 /* DataBuffer for fifos and sockets is empty */ 775 if (len != 0) { 776 cifs_dbg(VFS, "srv returned malformed nfs buffer for type: 0x%llx\n", type); 777 return smb_EIO1(smb_eio_trace_reparse_nfs_sockfifo, len); 778 } 779 break; 780 default: 781 cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n", 782 __func__, type); 783 return -EOPNOTSUPP; 784 } 785 return 0; 786 } 787 788 int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len, 789 bool relative, 790 const char *full_path, 791 struct cifs_sb_info *cifs_sb) 792 { 793 const char *symroot = cifs_sb->ctx->symlinkroot; 794 char sep = CIFS_DIR_SEP(cifs_sb); 795 char *linux_target = NULL; 796 char *smb_target = NULL; 797 int symlinkroot_len; 798 int abs_path_len; 799 char *abs_path; 800 int levels; 801 int rc, ulen; 802 int i; 803 804 /* Check that length it valid */ 805 if (!len || (len % 2)) { 806 cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); 807 rc = smb_EIO1(smb_eio_trace_reparse_native_nul, len); 808 goto out; 809 } 810 811 /* 812 * Check that buffer does not contain UTF-16 null codepoint 813 * because Linux cannot process symlink with null byte. 814 */ 815 ulen = UniStrnlen((wchar_t *)buf, len/2); 816 if (ulen != len/2) { 817 cifs_dbg(VFS, "srv returned null byte in native symlink target location\n"); 818 rc = smb_EIO2(smb_eio_trace_reparse_native_nul, ulen, len); 819 goto out; 820 } 821 822 smb_target = cifs_strndup_from_utf16(buf, len, true, cifs_sb->local_nls); 823 if (!smb_target) { 824 rc = -ENOMEM; 825 goto out; 826 } 827 828 if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS) && 829 symroot && !relative) { 830 /* 831 * This is an absolute symlink from the server which does not 832 * support POSIX paths, so the symlink is in NT-style path. 833 * So convert it to absolute Linux symlink target path. Root of 834 * the NT-style path for symlinks is specified in "symlinkroot" 835 * mount option. 836 * 837 * Root of the DOS and Win32 paths is at NT path \??\ 838 * It means that DOS/Win32 path C:\folder\file.txt is 839 * NT path \??\C:\folder\file.txt 840 * 841 * NT systems have some well-known object symlinks in their NT 842 * hierarchy, which is needed to take into account when resolving 843 * other symlinks. Most commonly used symlink paths are: 844 * \?? -> \GLOBAL?? 845 * \DosDevices -> \?? 846 * \GLOBAL??\GLOBALROOT -> \ 847 * \GLOBAL??\Global -> \GLOBAL?? 848 * \GLOBAL??\NUL -> \Device\Null 849 * \GLOBAL??\UNC -> \Device\Mup 850 * \GLOBAL??\PhysicalDrive0 -> \Device\Harddisk0\DR0 (for each harddisk) 851 * \GLOBAL??\A: -> \Device\Floppy0 (if A: is the first floppy) 852 * \GLOBAL??\C: -> \Device\HarddiskVolume1 (if C: is the first harddisk) 853 * \GLOBAL??\D: -> \Device\CdRom0 (if D: is first cdrom) 854 * \SystemRoot -> \Device\Harddisk0\Partition1\WINDOWS (or where is NT system installed) 855 * \Volume{...} -> \Device\HarddiskVolume1 (where ... is system generated guid) 856 * 857 * In most common cases, absolute NT symlinks points to path on 858 * DOS/Win32 drive letter, system-specific Volume or on UNC share. 859 * Here are few examples of commonly used absolute NT symlinks 860 * created by mklink.exe tool: 861 * \??\C:\folder\file.txt 862 * \??\\C:\folder\file.txt 863 * \??\UNC\server\share\file.txt 864 * \??\\UNC\server\share\file.txt 865 * \??\Volume{b75e2c83-0000-0000-0000-602f00000000}\folder\file.txt 866 * 867 * It means that the most common path prefix \??\ is also NT path 868 * symlink (to \GLOBAL??). It is less common that second path 869 * separator is double backslash, but it is valid. 870 * 871 * Volume guid is randomly generated by the target system and so 872 * only the target system knows the mapping between guid and the 873 * hardisk number. Over SMB it is not possible to resolve this 874 * mapping, therefore symlinks pointing to target location of 875 * volume guids are totally unusable over SMB. 876 * 877 * For now parse only symlink paths available for DOS and Win32. 878 * Those are paths with \??\ prefix or paths which points to \??\ 879 * via other NT symlink (\DosDevices\, \GLOBAL??\, ...). 880 */ 881 abs_path = smb_target; 882 globalroot: 883 if (strstarts(abs_path, "\\??\\")) 884 abs_path += sizeof("\\??\\")-1; 885 else if (strstarts(abs_path, "\\DosDevices\\")) 886 abs_path += sizeof("\\DosDevices\\")-1; 887 else if (strstarts(abs_path, "\\GLOBAL??\\")) 888 abs_path += sizeof("\\GLOBAL??\\")-1; 889 else 890 goto out_unhandled_target; 891 892 /* Sometimes path separator after \?? is double backslash */ 893 if (abs_path[0] == '\\') 894 abs_path++; 895 896 while (strstarts(abs_path, "Global\\")) 897 abs_path += sizeof("Global\\")-1; 898 899 if (strstarts(abs_path, "GLOBALROOT\\")) { 900 /* Label globalroot requires path with leading '\\', so do not trim '\\' */ 901 abs_path += sizeof("GLOBALROOT")-1; 902 goto globalroot; 903 } 904 905 /* For now parse only paths to drive letters */ 906 if (((abs_path[0] >= 'A' && abs_path[0] <= 'Z') || 907 (abs_path[0] >= 'a' && abs_path[0] <= 'z')) && 908 abs_path[1] == ':' && 909 (abs_path[2] == '\\' || abs_path[2] == '\0')) { 910 /* Convert drive letter to lowercase and drop colon */ 911 char drive_letter = abs_path[0]; 912 if (drive_letter >= 'A' && drive_letter <= 'Z') 913 drive_letter += 'a'-'A'; 914 abs_path++; 915 abs_path[0] = drive_letter; 916 } else { 917 goto out_unhandled_target; 918 } 919 920 abs_path_len = strlen(abs_path)+1; 921 symlinkroot_len = strlen(symroot); 922 if (symroot[symlinkroot_len - 1] == '/') 923 symlinkroot_len--; 924 linux_target = kmalloc(symlinkroot_len + 1 + abs_path_len, GFP_KERNEL); 925 if (!linux_target) { 926 rc = -ENOMEM; 927 goto out; 928 } 929 memcpy(linux_target, symroot, symlinkroot_len); 930 linux_target[symlinkroot_len] = '/'; 931 memcpy(linux_target + symlinkroot_len + 1, abs_path, abs_path_len); 932 } else if (smb_target[0] == sep && relative) { 933 /* 934 * This is a relative SMB symlink from the top of the share, 935 * which is the top level directory of the Linux mount point. 936 * Linux does not support such relative symlinks, so convert 937 * it to the relative symlink from the current directory. 938 * full_path is the SMB path to the symlink (from which is 939 * extracted current directory) and smb_target is the SMB path 940 * where symlink points, therefore full_path must always be on 941 * the SMB share. 942 */ 943 int smb_target_len = strlen(smb_target)+1; 944 levels = 0; 945 for (i = 1; full_path[i]; i++) { /* i=1 to skip leading sep */ 946 if (full_path[i] == sep) 947 levels++; 948 } 949 linux_target = kmalloc(levels*3 + smb_target_len, GFP_KERNEL); 950 if (!linux_target) { 951 rc = -ENOMEM; 952 goto out; 953 } 954 for (i = 0; i < levels; i++) { 955 linux_target[i*3 + 0] = '.'; 956 linux_target[i*3 + 1] = '.'; 957 linux_target[i*3 + 2] = sep; 958 } 959 memcpy(linux_target + levels*3, smb_target+1, smb_target_len); /* +1 to skip leading sep */ 960 } else { 961 /* 962 * This is either an absolute symlink in POSIX-style format 963 * or relative SMB symlink from the current directory. 964 * These paths have same format as Linux symlinks, so no 965 * conversion is needed. 966 */ 967 out_unhandled_target: 968 linux_target = smb_target; 969 smb_target = NULL; 970 } 971 972 if (sep == '\\') 973 convert_delimiter(linux_target, '/'); 974 975 rc = 0; 976 *target = linux_target; 977 978 cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, *target); 979 980 out: 981 if (rc != 0) 982 kfree(linux_target); 983 kfree(smb_target); 984 return rc; 985 } 986 987 static int parse_reparse_native_symlink(struct reparse_symlink_data_buffer *sym, 988 u32 plen, 989 struct cifs_sb_info *cifs_sb, 990 const char *full_path, 991 struct cifs_open_info_data *data) 992 { 993 unsigned int len; 994 unsigned int offs; 995 996 /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */ 997 998 offs = le16_to_cpu(sym->SubstituteNameOffset); 999 len = le16_to_cpu(sym->SubstituteNameLength); 1000 if (offs + 20 > plen || offs + len + 20 > plen) { 1001 cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); 1002 return smb_EIO2(smb_eio_trace_reparse_native_sym_len, 1003 offs << 16 | len, plen); 1004 } 1005 1006 return smb2_parse_native_symlink(&data->symlink_target, 1007 sym->PathBuffer + offs, 1008 len, 1009 le32_to_cpu(sym->Flags) & SYMLINK_FLAG_RELATIVE, 1010 full_path, 1011 cifs_sb); 1012 } 1013 1014 static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffer *buf, 1015 struct cifs_sb_info *cifs_sb, 1016 struct cifs_open_info_data *data) 1017 { 1018 int len = le16_to_cpu(buf->ReparseDataLength); 1019 int data_offset = offsetof(typeof(*buf), Target) - offsetof(typeof(*buf), Version); 1020 int symname_utf8_len; 1021 __le16 *symname_utf16; 1022 int symname_utf16_len; 1023 1024 if (len <= data_offset) { 1025 cifs_dbg(VFS, "srv returned malformed wsl symlink buffer\n"); 1026 return smb_EIO2(smb_eio_trace_reparse_wsl_symbuf, 1027 len, data_offset); 1028 } 1029 1030 /* MS-FSCC 2.1.2.7 defines layout of the Target field only for Version 2. */ 1031 u32 version = le32_to_cpu(buf->Version); 1032 1033 if (version != 2) { 1034 cifs_dbg(VFS, "srv returned unsupported wsl symlink version %u\n", version); 1035 return smb_EIO1(smb_eio_trace_reparse_wsl_ver, version); 1036 } 1037 1038 /* Target for Version 2 is in UTF-8 but without trailing null-term byte */ 1039 symname_utf8_len = len - data_offset; 1040 /* 1041 * Check that buffer does not contain null byte 1042 * because Linux cannot process symlink with null byte. 1043 */ 1044 size_t ulen = strnlen(buf->Target, symname_utf8_len); 1045 1046 if (ulen != symname_utf8_len) { 1047 cifs_dbg(VFS, "srv returned null byte in wsl symlink target location\n"); 1048 return smb_EIO2(smb_eio_trace_reparse_wsl_ver, 1049 ulen, symname_utf8_len); 1050 } 1051 symname_utf16 = kzalloc(symname_utf8_len * 2, GFP_KERNEL); 1052 if (!symname_utf16) 1053 return -ENOMEM; 1054 symname_utf16_len = utf8s_to_utf16s(buf->Target, symname_utf8_len, 1055 UTF16_LITTLE_ENDIAN, 1056 (wchar_t *) symname_utf16, symname_utf8_len * 2); 1057 if (symname_utf16_len < 0) { 1058 kfree(symname_utf16); 1059 return symname_utf16_len; 1060 } 1061 symname_utf16_len *= 2; /* utf8s_to_utf16s() returns number of u16 items, not byte length */ 1062 1063 data->symlink_target = cifs_strndup_from_utf16((u8 *)symname_utf16, 1064 symname_utf16_len, true, 1065 cifs_sb->local_nls); 1066 kfree(symname_utf16); 1067 if (!data->symlink_target) 1068 return -ENOMEM; 1069 1070 return 0; 1071 } 1072 1073 int parse_reparse_point(struct reparse_data_buffer *buf, 1074 u32 plen, struct cifs_sb_info *cifs_sb, 1075 const char *full_path, 1076 struct cifs_open_info_data *data) 1077 { 1078 data->reparse.buf = buf; 1079 1080 /* See MS-FSCC 2.1.2 */ 1081 switch (le32_to_cpu(buf->ReparseTag)) { 1082 case IO_REPARSE_TAG_NFS: 1083 return parse_reparse_nfs((struct reparse_nfs_data_buffer *)buf, 1084 cifs_sb, data); 1085 case IO_REPARSE_TAG_SYMLINK: 1086 return parse_reparse_native_symlink( 1087 (struct reparse_symlink_data_buffer *)buf, 1088 plen, cifs_sb, full_path, data); 1089 case IO_REPARSE_TAG_LX_SYMLINK: 1090 return parse_reparse_wsl_symlink( 1091 (struct reparse_wsl_symlink_data_buffer *)buf, 1092 cifs_sb, data); 1093 case IO_REPARSE_TAG_AF_UNIX: 1094 case IO_REPARSE_TAG_LX_FIFO: 1095 case IO_REPARSE_TAG_LX_CHR: 1096 case IO_REPARSE_TAG_LX_BLK: { 1097 u16 dlen = le16_to_cpu(buf->ReparseDataLength); 1098 1099 if (dlen != 0) { 1100 u32 rtag = le32_to_cpu(buf->ReparseTag); 1101 cifs_dbg(VFS, "srv returned malformed buffer for reparse point: 0x%08x\n", 1102 rtag); 1103 return smb_EIO2(smb_eio_trace_reparse_data_len, dlen, rtag); 1104 } 1105 return 0; 1106 } 1107 default: 1108 return -EOPNOTSUPP; 1109 } 1110 } 1111 1112 struct reparse_data_buffer *smb2_get_reparse_point_buffer(const struct kvec *rsp_iov, 1113 u32 *plen) 1114 { 1115 struct smb2_ioctl_rsp *io = rsp_iov->iov_base; 1116 *plen = le32_to_cpu(io->OutputCount); 1117 return (struct reparse_data_buffer *)((u8 *)io + 1118 le32_to_cpu(io->OutputOffset)); 1119 } 1120 1121 static bool wsl_to_fattr(struct cifs_open_info_data *data, 1122 struct cifs_sb_info *cifs_sb, 1123 u32 tag, struct cifs_fattr *fattr) 1124 { 1125 struct smb2_file_full_ea_info *ea; 1126 bool have_xattr_dev = false; 1127 u32 next = 0; 1128 1129 switch (tag) { 1130 case IO_REPARSE_TAG_LX_SYMLINK: 1131 fattr->cf_mode |= S_IFLNK; 1132 break; 1133 case IO_REPARSE_TAG_LX_FIFO: 1134 fattr->cf_mode |= S_IFIFO; 1135 break; 1136 case IO_REPARSE_TAG_AF_UNIX: 1137 fattr->cf_mode |= S_IFSOCK; 1138 break; 1139 case IO_REPARSE_TAG_LX_CHR: 1140 fattr->cf_mode |= S_IFCHR; 1141 break; 1142 case IO_REPARSE_TAG_LX_BLK: 1143 fattr->cf_mode |= S_IFBLK; 1144 break; 1145 } 1146 1147 if (!data->wsl.eas_len) 1148 goto out; 1149 1150 ea = (struct smb2_file_full_ea_info *)data->wsl.eas; 1151 do { 1152 const char *name; 1153 void *v; 1154 u8 nlen; 1155 1156 ea = (void *)((u8 *)ea + next); 1157 next = le32_to_cpu(ea->next_entry_offset); 1158 if (!le16_to_cpu(ea->ea_value_length)) 1159 continue; 1160 1161 name = ea->ea_data; 1162 nlen = ea->ea_name_length; 1163 v = (void *)((u8 *)ea->ea_data + ea->ea_name_length + 1); 1164 1165 if (!strncmp(name, SMB2_WSL_XATTR_UID, nlen)) 1166 fattr->cf_uid = wsl_make_kuid(cifs_sb, v); 1167 else if (!strncmp(name, SMB2_WSL_XATTR_GID, nlen)) 1168 fattr->cf_gid = wsl_make_kgid(cifs_sb, v); 1169 else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen)) { 1170 /* File type in reparse point tag and in xattr mode must match. */ 1171 if (S_DT(fattr->cf_mode) != S_DT(le32_to_cpu(*(__le32 *)v))) 1172 return false; 1173 fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v); 1174 } else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) { 1175 fattr->cf_rdev = reparse_mkdev(v); 1176 have_xattr_dev = true; 1177 } 1178 } while (next); 1179 out: 1180 1181 /* Major and minor numbers for char and block devices are mandatory. */ 1182 if (!have_xattr_dev && (tag == IO_REPARSE_TAG_LX_CHR || tag == IO_REPARSE_TAG_LX_BLK)) 1183 return false; 1184 1185 return true; 1186 } 1187 1188 static bool posix_reparse_to_fattr(struct cifs_sb_info *cifs_sb, 1189 struct cifs_fattr *fattr, 1190 struct cifs_open_info_data *data) 1191 { 1192 struct reparse_nfs_data_buffer *buf = (struct reparse_nfs_data_buffer *)data->reparse.buf; 1193 1194 if (buf == NULL) 1195 return true; 1196 1197 if (le16_to_cpu(buf->ReparseDataLength) < sizeof(buf->InodeType)) { 1198 WARN_ON_ONCE(1); 1199 return false; 1200 } 1201 1202 switch (le64_to_cpu(buf->InodeType)) { 1203 case NFS_SPECFILE_CHR: 1204 if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8) { 1205 WARN_ON_ONCE(1); 1206 return false; 1207 } 1208 fattr->cf_mode |= S_IFCHR; 1209 fattr->cf_rdev = reparse_mkdev(buf->DataBuffer); 1210 break; 1211 case NFS_SPECFILE_BLK: 1212 if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8) { 1213 WARN_ON_ONCE(1); 1214 return false; 1215 } 1216 fattr->cf_mode |= S_IFBLK; 1217 fattr->cf_rdev = reparse_mkdev(buf->DataBuffer); 1218 break; 1219 case NFS_SPECFILE_FIFO: 1220 fattr->cf_mode |= S_IFIFO; 1221 break; 1222 case NFS_SPECFILE_SOCK: 1223 fattr->cf_mode |= S_IFSOCK; 1224 break; 1225 case NFS_SPECFILE_LNK: 1226 fattr->cf_mode |= S_IFLNK; 1227 break; 1228 default: 1229 WARN_ON_ONCE(1); 1230 return false; 1231 } 1232 return true; 1233 } 1234 1235 bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, 1236 struct cifs_fattr *fattr, 1237 struct cifs_open_info_data *data) 1238 { 1239 u32 tag = data->reparse.tag; 1240 bool ok; 1241 1242 switch (tag) { 1243 case IO_REPARSE_TAG_LX_SYMLINK: 1244 case IO_REPARSE_TAG_LX_FIFO: 1245 case IO_REPARSE_TAG_AF_UNIX: 1246 case IO_REPARSE_TAG_LX_CHR: 1247 case IO_REPARSE_TAG_LX_BLK: 1248 ok = wsl_to_fattr(data, cifs_sb, tag, fattr); 1249 if (!ok) 1250 return false; 1251 break; 1252 case IO_REPARSE_TAG_NFS: 1253 ok = posix_reparse_to_fattr(cifs_sb, fattr, data); 1254 if (!ok) 1255 return false; 1256 break; 1257 case 0: /* SMB1 symlink */ 1258 case IO_REPARSE_TAG_SYMLINK: 1259 fattr->cf_mode |= S_IFLNK; 1260 break; 1261 default: 1262 if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY)) 1263 return false; 1264 if (!IS_REPARSE_TAG_NAME_SURROGATE(tag) && 1265 tag != IO_REPARSE_TAG_INTERNAL) 1266 return false; 1267 /* See cifs_create_junction_fattr() */ 1268 fattr->cf_mode = S_IFDIR | 0711; 1269 break; 1270 } 1271 1272 fattr->cf_dtype = S_DT(fattr->cf_mode); 1273 return true; 1274 } 1275