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