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 detect_directory_symlink_target(struct cifs_sb_info *cifs_sb, 18 const unsigned int xid, 19 const char *full_path, 20 const char *symname, 21 bool *directory); 22 23 int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode, 24 struct dentry *dentry, struct cifs_tcon *tcon, 25 const char *full_path, const char *symname) 26 { 27 struct reparse_symlink_data_buffer *buf = NULL; 28 struct cifs_open_info_data data; 29 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 30 struct inode *new; 31 struct kvec iov; 32 __le16 *path; 33 bool directory; 34 char *sym, sep = CIFS_DIR_SEP(cifs_sb); 35 u16 len, plen; 36 int rc = 0; 37 38 if (strlen(symname) > REPARSE_SYM_PATH_MAX) 39 return -ENAMETOOLONG; 40 41 sym = kstrdup(symname, GFP_KERNEL); 42 if (!sym) 43 return -ENOMEM; 44 45 data = (struct cifs_open_info_data) { 46 .reparse_point = true, 47 .reparse = { .tag = IO_REPARSE_TAG_SYMLINK, }, 48 .symlink_target = sym, 49 }; 50 51 convert_delimiter(sym, sep); 52 path = cifs_convert_path_to_utf16(sym, cifs_sb); 53 if (!path) { 54 rc = -ENOMEM; 55 goto out; 56 } 57 58 /* 59 * SMB distinguish between symlink to directory and symlink to file. 60 * They cannot be exchanged (symlink of file type which points to 61 * directory cannot be resolved and vice-versa). Try to detect if 62 * the symlink target could be a directory or not. When detection 63 * fails then treat symlink as a file (non-directory) symlink. 64 */ 65 directory = false; 66 rc = detect_directory_symlink_target(cifs_sb, xid, full_path, symname, &directory); 67 if (rc < 0) 68 goto out; 69 70 plen = 2 * UniStrnlen((wchar_t *)path, REPARSE_SYM_PATH_MAX); 71 len = sizeof(*buf) + plen * 2; 72 buf = kzalloc(len, GFP_KERNEL); 73 if (!buf) { 74 rc = -ENOMEM; 75 goto out; 76 } 77 78 buf->ReparseTag = cpu_to_le32(IO_REPARSE_TAG_SYMLINK); 79 buf->ReparseDataLength = cpu_to_le16(len - sizeof(struct reparse_data_buffer)); 80 buf->SubstituteNameOffset = cpu_to_le16(plen); 81 buf->SubstituteNameLength = cpu_to_le16(plen); 82 memcpy(&buf->PathBuffer[plen], path, plen); 83 buf->PrintNameOffset = 0; 84 buf->PrintNameLength = cpu_to_le16(plen); 85 memcpy(buf->PathBuffer, path, plen); 86 buf->Flags = cpu_to_le32(*symname != '/' ? SYMLINK_FLAG_RELATIVE : 0); 87 if (*sym != sep) 88 buf->Flags = cpu_to_le32(SYMLINK_FLAG_RELATIVE); 89 90 convert_delimiter(sym, '/'); 91 iov.iov_base = buf; 92 iov.iov_len = len; 93 new = smb2_get_reparse_inode(&data, inode->i_sb, xid, 94 tcon, full_path, directory, 95 &iov, NULL); 96 if (!IS_ERR(new)) 97 d_instantiate(dentry, new); 98 else 99 rc = PTR_ERR(new); 100 out: 101 kfree(path); 102 cifs_free_open_info(&data); 103 kfree(buf); 104 return rc; 105 } 106 107 static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb, 108 const unsigned int xid, 109 const char *full_path, 110 const char *symname, 111 bool *directory) 112 { 113 char sep = CIFS_DIR_SEP(cifs_sb); 114 struct cifs_open_parms oparms; 115 struct tcon_link *tlink; 116 struct cifs_tcon *tcon; 117 const char *basename; 118 struct cifs_fid fid; 119 char *resolved_path; 120 int full_path_len; 121 int basename_len; 122 int symname_len; 123 char *path_sep; 124 __u32 oplock; 125 int open_rc; 126 127 /* 128 * First do some simple check. If the original Linux symlink target ends 129 * with slash, or last path component is dot or dot-dot then it is for 130 * sure symlink to the directory. 131 */ 132 basename = kbasename(symname); 133 basename_len = strlen(basename); 134 if (basename_len == 0 || /* symname ends with slash */ 135 (basename_len == 1 && basename[0] == '.') || /* last component is "." */ 136 (basename_len == 2 && basename[0] == '.' && basename[1] == '.')) { /* or ".." */ 137 *directory = true; 138 return 0; 139 } 140 141 /* 142 * For absolute symlinks it is not possible to determinate 143 * if it should point to directory or file. 144 */ 145 if (symname[0] == '/') { 146 cifs_dbg(FYI, 147 "%s: cannot determinate if the symlink target path '%s' " 148 "is directory or not, creating '%s' as file symlink\n", 149 __func__, symname, full_path); 150 return 0; 151 } 152 153 /* 154 * If it was not detected as directory yet and the symlink is relative 155 * then try to resolve the path on the SMB server, check if the path 156 * exists and determinate if it is a directory or not. 157 */ 158 159 full_path_len = strlen(full_path); 160 symname_len = strlen(symname); 161 162 tlink = cifs_sb_tlink(cifs_sb); 163 if (IS_ERR(tlink)) 164 return PTR_ERR(tlink); 165 166 resolved_path = kzalloc(full_path_len + symname_len + 1, GFP_KERNEL); 167 if (!resolved_path) { 168 cifs_put_tlink(tlink); 169 return -ENOMEM; 170 } 171 172 /* 173 * Compose the resolved SMB symlink path from the SMB full path 174 * and Linux target symlink path. 175 */ 176 memcpy(resolved_path, full_path, full_path_len+1); 177 path_sep = strrchr(resolved_path, sep); 178 if (path_sep) 179 path_sep++; 180 else 181 path_sep = resolved_path; 182 memcpy(path_sep, symname, symname_len+1); 183 if (sep == '\\') 184 convert_delimiter(path_sep, sep); 185 186 tcon = tlink_tcon(tlink); 187 oparms = CIFS_OPARMS(cifs_sb, tcon, resolved_path, 188 FILE_READ_ATTRIBUTES, FILE_OPEN, 0, ACL_NO_MODE); 189 oparms.fid = &fid; 190 191 /* Try to open as a directory (NOT_FILE) */ 192 oplock = 0; 193 oparms.create_options = cifs_create_options(cifs_sb, 194 CREATE_NOT_FILE | OPEN_REPARSE_POINT); 195 open_rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); 196 if (open_rc == 0) { 197 /* Successful open means that the target path is definitely a directory. */ 198 *directory = true; 199 tcon->ses->server->ops->close(xid, tcon, &fid); 200 } else if (open_rc == -ENOTDIR) { 201 /* -ENOTDIR means that the target path is definitely a file. */ 202 *directory = false; 203 } else if (open_rc == -ENOENT) { 204 /* -ENOENT means that the target path does not exist. */ 205 cifs_dbg(FYI, 206 "%s: symlink target path '%s' does not exist, " 207 "creating '%s' as file symlink\n", 208 __func__, symname, full_path); 209 } else { 210 /* Try to open as a file (NOT_DIR) */ 211 oplock = 0; 212 oparms.create_options = cifs_create_options(cifs_sb, 213 CREATE_NOT_DIR | OPEN_REPARSE_POINT); 214 open_rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); 215 if (open_rc == 0) { 216 /* Successful open means that the target path is definitely a file. */ 217 *directory = false; 218 tcon->ses->server->ops->close(xid, tcon, &fid); 219 } else if (open_rc == -EISDIR) { 220 /* -EISDIR means that the target path is definitely a directory. */ 221 *directory = true; 222 } else { 223 /* 224 * This code branch is called when we do not have a permission to 225 * open the resolved_path or some other client/process denied 226 * opening the resolved_path. 227 * 228 * TODO: Try to use ops->query_dir_first on the parent directory 229 * of resolved_path, search for basename of resolved_path and 230 * check if the ATTR_DIRECTORY is set in fi.Attributes. In some 231 * case this could work also when opening of the path is denied. 232 */ 233 cifs_dbg(FYI, 234 "%s: cannot determinate if the symlink target path '%s' " 235 "is directory or not, creating '%s' as file symlink\n", 236 __func__, symname, full_path); 237 } 238 } 239 240 kfree(resolved_path); 241 cifs_put_tlink(tlink); 242 return 0; 243 } 244 245 static int nfs_set_reparse_buf(struct reparse_posix_data *buf, 246 mode_t mode, dev_t dev, 247 struct kvec *iov) 248 { 249 u64 type; 250 u16 len, dlen; 251 252 len = sizeof(*buf); 253 254 switch ((type = reparse_mode_nfs_type(mode))) { 255 case NFS_SPECFILE_BLK: 256 case NFS_SPECFILE_CHR: 257 dlen = sizeof(__le64); 258 break; 259 case NFS_SPECFILE_FIFO: 260 case NFS_SPECFILE_SOCK: 261 dlen = 0; 262 break; 263 default: 264 return -EOPNOTSUPP; 265 } 266 267 buf->ReparseTag = cpu_to_le32(IO_REPARSE_TAG_NFS); 268 buf->Reserved = 0; 269 buf->InodeType = cpu_to_le64(type); 270 buf->ReparseDataLength = cpu_to_le16(len + dlen - 271 sizeof(struct reparse_data_buffer)); 272 *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MINOR(dev) << 32) | 273 MAJOR(dev)); 274 iov->iov_base = buf; 275 iov->iov_len = len + dlen; 276 return 0; 277 } 278 279 static int mknod_nfs(unsigned int xid, struct inode *inode, 280 struct dentry *dentry, struct cifs_tcon *tcon, 281 const char *full_path, umode_t mode, dev_t dev) 282 { 283 struct cifs_open_info_data data; 284 struct reparse_posix_data *p; 285 struct inode *new; 286 struct kvec iov; 287 __u8 buf[sizeof(*p) + sizeof(__le64)]; 288 int rc; 289 290 p = (struct reparse_posix_data *)buf; 291 rc = nfs_set_reparse_buf(p, mode, dev, &iov); 292 if (rc) 293 return rc; 294 295 data = (struct cifs_open_info_data) { 296 .reparse_point = true, 297 .reparse = { .tag = IO_REPARSE_TAG_NFS, .posix = p, }, 298 }; 299 300 new = smb2_get_reparse_inode(&data, inode->i_sb, xid, 301 tcon, full_path, false, &iov, NULL); 302 if (!IS_ERR(new)) 303 d_instantiate(dentry, new); 304 else 305 rc = PTR_ERR(new); 306 cifs_free_open_info(&data); 307 return rc; 308 } 309 310 static int wsl_set_reparse_buf(struct reparse_data_buffer *buf, 311 mode_t mode, struct kvec *iov) 312 { 313 u32 tag; 314 315 switch ((tag = reparse_mode_wsl_tag(mode))) { 316 case IO_REPARSE_TAG_LX_BLK: 317 case IO_REPARSE_TAG_LX_CHR: 318 case IO_REPARSE_TAG_LX_FIFO: 319 case IO_REPARSE_TAG_AF_UNIX: 320 break; 321 default: 322 return -EOPNOTSUPP; 323 } 324 325 buf->ReparseTag = cpu_to_le32(tag); 326 buf->Reserved = 0; 327 buf->ReparseDataLength = 0; 328 iov->iov_base = buf; 329 iov->iov_len = sizeof(*buf); 330 return 0; 331 } 332 333 static struct smb2_create_ea_ctx *ea_create_context(u32 dlen, size_t *cc_len) 334 { 335 struct smb2_create_ea_ctx *cc; 336 337 *cc_len = round_up(sizeof(*cc) + dlen, 8); 338 cc = kzalloc(*cc_len, GFP_KERNEL); 339 if (!cc) 340 return ERR_PTR(-ENOMEM); 341 342 cc->ctx.NameOffset = cpu_to_le16(offsetof(struct smb2_create_ea_ctx, 343 name)); 344 cc->ctx.NameLength = cpu_to_le16(4); 345 memcpy(cc->name, SMB2_CREATE_EA_BUFFER, strlen(SMB2_CREATE_EA_BUFFER)); 346 cc->ctx.DataOffset = cpu_to_le16(offsetof(struct smb2_create_ea_ctx, ea)); 347 cc->ctx.DataLength = cpu_to_le32(dlen); 348 return cc; 349 } 350 351 struct wsl_xattr { 352 const char *name; 353 __le64 value; 354 u16 size; 355 u32 next; 356 }; 357 358 static int wsl_set_xattrs(struct inode *inode, umode_t _mode, 359 dev_t _dev, struct kvec *iov) 360 { 361 struct smb2_file_full_ea_info *ea; 362 struct smb2_create_ea_ctx *cc; 363 struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx; 364 __le64 uid = cpu_to_le64(from_kuid(current_user_ns(), ctx->linux_uid)); 365 __le64 gid = cpu_to_le64(from_kgid(current_user_ns(), ctx->linux_gid)); 366 __le64 dev = cpu_to_le64(((u64)MINOR(_dev) << 32) | MAJOR(_dev)); 367 __le64 mode = cpu_to_le64(_mode); 368 struct wsl_xattr xattrs[] = { 369 { .name = SMB2_WSL_XATTR_UID, .value = uid, .size = SMB2_WSL_XATTR_UID_SIZE, }, 370 { .name = SMB2_WSL_XATTR_GID, .value = gid, .size = SMB2_WSL_XATTR_GID_SIZE, }, 371 { .name = SMB2_WSL_XATTR_MODE, .value = mode, .size = SMB2_WSL_XATTR_MODE_SIZE, }, 372 { .name = SMB2_WSL_XATTR_DEV, .value = dev, .size = SMB2_WSL_XATTR_DEV_SIZE, }, 373 }; 374 size_t cc_len; 375 u32 dlen = 0, next = 0; 376 int i, num_xattrs; 377 u8 name_size = SMB2_WSL_XATTR_NAME_LEN + 1; 378 379 memset(iov, 0, sizeof(*iov)); 380 381 /* Exclude $LXDEV xattr for non-device files */ 382 if (!S_ISBLK(_mode) && !S_ISCHR(_mode)) 383 num_xattrs = ARRAY_SIZE(xattrs) - 1; 384 else 385 num_xattrs = ARRAY_SIZE(xattrs); 386 387 for (i = 0; i < num_xattrs; i++) { 388 xattrs[i].next = ALIGN(sizeof(*ea) + name_size + 389 xattrs[i].size, 4); 390 dlen += xattrs[i].next; 391 } 392 393 cc = ea_create_context(dlen, &cc_len); 394 if (IS_ERR(cc)) 395 return PTR_ERR(cc); 396 397 ea = &cc->ea; 398 for (i = 0; i < num_xattrs; i++) { 399 ea = (void *)((u8 *)ea + next); 400 next = xattrs[i].next; 401 ea->next_entry_offset = cpu_to_le32(next); 402 403 ea->ea_name_length = name_size - 1; 404 ea->ea_value_length = cpu_to_le16(xattrs[i].size); 405 memcpy(ea->ea_data, xattrs[i].name, name_size); 406 memcpy(&ea->ea_data[name_size], 407 &xattrs[i].value, xattrs[i].size); 408 } 409 ea->next_entry_offset = 0; 410 411 iov->iov_base = cc; 412 iov->iov_len = cc_len; 413 return 0; 414 } 415 416 static int mknod_wsl(unsigned int xid, struct inode *inode, 417 struct dentry *dentry, struct cifs_tcon *tcon, 418 const char *full_path, umode_t mode, dev_t dev) 419 { 420 struct cifs_open_info_data data; 421 struct reparse_data_buffer buf; 422 struct smb2_create_ea_ctx *cc; 423 struct inode *new; 424 unsigned int len; 425 struct kvec reparse_iov, xattr_iov; 426 int rc; 427 428 rc = wsl_set_reparse_buf(&buf, mode, &reparse_iov); 429 if (rc) 430 return rc; 431 432 rc = wsl_set_xattrs(inode, mode, dev, &xattr_iov); 433 if (rc) 434 return rc; 435 436 data = (struct cifs_open_info_data) { 437 .reparse_point = true, 438 .reparse = { .tag = le32_to_cpu(buf.ReparseTag), .buf = &buf, }, 439 }; 440 441 cc = xattr_iov.iov_base; 442 len = le32_to_cpu(cc->ctx.DataLength); 443 memcpy(data.wsl.eas, &cc->ea, len); 444 data.wsl.eas_len = len; 445 446 new = smb2_get_reparse_inode(&data, inode->i_sb, 447 xid, tcon, full_path, false, 448 &reparse_iov, &xattr_iov); 449 if (!IS_ERR(new)) 450 d_instantiate(dentry, new); 451 else 452 rc = PTR_ERR(new); 453 cifs_free_open_info(&data); 454 kfree(xattr_iov.iov_base); 455 return rc; 456 } 457 458 int smb2_mknod_reparse(unsigned int xid, struct inode *inode, 459 struct dentry *dentry, struct cifs_tcon *tcon, 460 const char *full_path, umode_t mode, dev_t dev) 461 { 462 struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx; 463 int rc = -EOPNOTSUPP; 464 465 switch (ctx->reparse_type) { 466 case CIFS_REPARSE_TYPE_NFS: 467 rc = mknod_nfs(xid, inode, dentry, tcon, full_path, mode, dev); 468 break; 469 case CIFS_REPARSE_TYPE_WSL: 470 rc = mknod_wsl(xid, inode, dentry, tcon, full_path, mode, dev); 471 break; 472 } 473 return rc; 474 } 475 476 /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */ 477 static int parse_reparse_posix(struct reparse_posix_data *buf, 478 struct cifs_sb_info *cifs_sb, 479 struct cifs_open_info_data *data) 480 { 481 unsigned int len; 482 u64 type; 483 484 len = le16_to_cpu(buf->ReparseDataLength); 485 if (len < sizeof(buf->InodeType)) { 486 cifs_dbg(VFS, "srv returned malformed nfs buffer\n"); 487 return -EIO; 488 } 489 490 len -= sizeof(buf->InodeType); 491 492 switch ((type = le64_to_cpu(buf->InodeType))) { 493 case NFS_SPECFILE_LNK: 494 if (len == 0 || (len % 2)) { 495 cifs_dbg(VFS, "srv returned malformed nfs symlink buffer\n"); 496 return -EIO; 497 } 498 /* 499 * Check that buffer does not contain UTF-16 null codepoint 500 * because Linux cannot process symlink with null byte. 501 */ 502 if (UniStrnlen((wchar_t *)buf->DataBuffer, len/2) != len/2) { 503 cifs_dbg(VFS, "srv returned null byte in nfs symlink target location\n"); 504 return -EIO; 505 } 506 data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer, 507 len, true, 508 cifs_sb->local_nls); 509 if (!data->symlink_target) 510 return -ENOMEM; 511 cifs_dbg(FYI, "%s: target path: %s\n", 512 __func__, data->symlink_target); 513 break; 514 case NFS_SPECFILE_CHR: 515 case NFS_SPECFILE_BLK: 516 /* DataBuffer for block and char devices contains two 32-bit numbers */ 517 if (len != 8) { 518 cifs_dbg(VFS, "srv returned malformed nfs buffer for type: 0x%llx\n", type); 519 return -EIO; 520 } 521 break; 522 case NFS_SPECFILE_FIFO: 523 case NFS_SPECFILE_SOCK: 524 /* DataBuffer for fifos and sockets is empty */ 525 if (len != 0) { 526 cifs_dbg(VFS, "srv returned malformed nfs buffer for type: 0x%llx\n", type); 527 return -EIO; 528 } 529 break; 530 default: 531 cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n", 532 __func__, type); 533 return -EOPNOTSUPP; 534 } 535 return 0; 536 } 537 538 int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len, 539 bool unicode, bool relative, 540 const char *full_path, 541 struct cifs_sb_info *cifs_sb) 542 { 543 char sep = CIFS_DIR_SEP(cifs_sb); 544 char *linux_target = NULL; 545 char *smb_target = NULL; 546 int levels; 547 int rc; 548 int i; 549 550 /* Check that length it valid for unicode/non-unicode mode */ 551 if (!len || (unicode && (len % 2))) { 552 cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); 553 rc = -EIO; 554 goto out; 555 } 556 557 /* 558 * Check that buffer does not contain UTF-16 null codepoint in unicode 559 * mode or null byte in non-unicode mode because Linux cannot process 560 * symlink with null byte. 561 */ 562 if ((unicode && UniStrnlen((wchar_t *)buf, len/2) != len/2) || 563 (!unicode && strnlen(buf, len) != len)) { 564 cifs_dbg(VFS, "srv returned null byte in native symlink target location\n"); 565 rc = -EIO; 566 goto out; 567 } 568 569 smb_target = cifs_strndup_from_utf16(buf, len, unicode, cifs_sb->local_nls); 570 if (!smb_target) { 571 rc = -ENOMEM; 572 goto out; 573 } 574 575 if (smb_target[0] == sep && relative) { 576 /* 577 * This is a relative SMB symlink from the top of the share, 578 * which is the top level directory of the Linux mount point. 579 * Linux does not support such relative symlinks, so convert 580 * it to the relative symlink from the current directory. 581 * full_path is the SMB path to the symlink (from which is 582 * extracted current directory) and smb_target is the SMB path 583 * where symlink points, therefore full_path must always be on 584 * the SMB share. 585 */ 586 int smb_target_len = strlen(smb_target)+1; 587 levels = 0; 588 for (i = 1; full_path[i]; i++) { /* i=1 to skip leading sep */ 589 if (full_path[i] == sep) 590 levels++; 591 } 592 linux_target = kmalloc(levels*3 + smb_target_len, GFP_KERNEL); 593 if (!linux_target) { 594 rc = -ENOMEM; 595 goto out; 596 } 597 for (i = 0; i < levels; i++) { 598 linux_target[i*3 + 0] = '.'; 599 linux_target[i*3 + 1] = '.'; 600 linux_target[i*3 + 2] = sep; 601 } 602 memcpy(linux_target + levels*3, smb_target+1, smb_target_len); /* +1 to skip leading sep */ 603 } else { 604 linux_target = smb_target; 605 smb_target = NULL; 606 } 607 608 if (sep == '\\') 609 convert_delimiter(linux_target, '/'); 610 611 rc = 0; 612 *target = linux_target; 613 614 cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, *target); 615 616 out: 617 if (rc != 0) 618 kfree(linux_target); 619 kfree(smb_target); 620 return rc; 621 } 622 623 static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym, 624 u32 plen, bool unicode, 625 struct cifs_sb_info *cifs_sb, 626 const char *full_path, 627 struct cifs_open_info_data *data) 628 { 629 unsigned int len; 630 unsigned int offs; 631 632 /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */ 633 634 offs = le16_to_cpu(sym->SubstituteNameOffset); 635 len = le16_to_cpu(sym->SubstituteNameLength); 636 if (offs + 20 > plen || offs + len + 20 > plen) { 637 cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); 638 return -EIO; 639 } 640 641 return smb2_parse_native_symlink(&data->symlink_target, 642 sym->PathBuffer + offs, 643 len, 644 unicode, 645 le32_to_cpu(sym->Flags) & SYMLINK_FLAG_RELATIVE, 646 full_path, 647 cifs_sb); 648 } 649 650 static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffer *buf, 651 struct cifs_sb_info *cifs_sb, 652 struct cifs_open_info_data *data) 653 { 654 int len = le16_to_cpu(buf->ReparseDataLength); 655 int symname_utf8_len; 656 __le16 *symname_utf16; 657 int symname_utf16_len; 658 659 if (len <= sizeof(buf->Flags)) { 660 cifs_dbg(VFS, "srv returned malformed wsl symlink buffer\n"); 661 return -EIO; 662 } 663 664 /* PathBuffer is in UTF-8 but without trailing null-term byte */ 665 symname_utf8_len = len - sizeof(buf->Flags); 666 /* 667 * Check that buffer does not contain null byte 668 * because Linux cannot process symlink with null byte. 669 */ 670 if (strnlen(buf->PathBuffer, symname_utf8_len) != symname_utf8_len) { 671 cifs_dbg(VFS, "srv returned null byte in wsl symlink target location\n"); 672 return -EIO; 673 } 674 symname_utf16 = kzalloc(symname_utf8_len * 2, GFP_KERNEL); 675 if (!symname_utf16) 676 return -ENOMEM; 677 symname_utf16_len = utf8s_to_utf16s(buf->PathBuffer, symname_utf8_len, 678 UTF16_LITTLE_ENDIAN, 679 symname_utf16, symname_utf8_len * 2); 680 if (symname_utf16_len < 0) { 681 kfree(symname_utf16); 682 return symname_utf16_len; 683 } 684 symname_utf16_len *= 2; /* utf8s_to_utf16s() returns number of u16 items, not byte length */ 685 686 data->symlink_target = cifs_strndup_from_utf16((u8 *)symname_utf16, 687 symname_utf16_len, true, 688 cifs_sb->local_nls); 689 kfree(symname_utf16); 690 if (!data->symlink_target) 691 return -ENOMEM; 692 693 return 0; 694 } 695 696 int parse_reparse_point(struct reparse_data_buffer *buf, 697 u32 plen, struct cifs_sb_info *cifs_sb, 698 const char *full_path, 699 bool unicode, struct cifs_open_info_data *data) 700 { 701 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 702 703 data->reparse.buf = buf; 704 705 /* See MS-FSCC 2.1.2 */ 706 switch (le32_to_cpu(buf->ReparseTag)) { 707 case IO_REPARSE_TAG_NFS: 708 return parse_reparse_posix((struct reparse_posix_data *)buf, 709 cifs_sb, data); 710 case IO_REPARSE_TAG_SYMLINK: 711 return parse_reparse_symlink( 712 (struct reparse_symlink_data_buffer *)buf, 713 plen, unicode, cifs_sb, full_path, data); 714 case IO_REPARSE_TAG_LX_SYMLINK: 715 return parse_reparse_wsl_symlink( 716 (struct reparse_wsl_symlink_data_buffer *)buf, 717 cifs_sb, data); 718 case IO_REPARSE_TAG_AF_UNIX: 719 case IO_REPARSE_TAG_LX_FIFO: 720 case IO_REPARSE_TAG_LX_CHR: 721 case IO_REPARSE_TAG_LX_BLK: 722 if (le16_to_cpu(buf->ReparseDataLength) != 0) { 723 cifs_dbg(VFS, "srv returned malformed buffer for reparse point: 0x%08x\n", 724 le32_to_cpu(buf->ReparseTag)); 725 return -EIO; 726 } 727 break; 728 default: 729 cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n", 730 le32_to_cpu(buf->ReparseTag)); 731 break; 732 } 733 return 0; 734 } 735 736 int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, 737 const char *full_path, 738 struct kvec *rsp_iov, 739 struct cifs_open_info_data *data) 740 { 741 struct reparse_data_buffer *buf; 742 struct smb2_ioctl_rsp *io = rsp_iov->iov_base; 743 u32 plen = le32_to_cpu(io->OutputCount); 744 745 buf = (struct reparse_data_buffer *)((u8 *)io + 746 le32_to_cpu(io->OutputOffset)); 747 return parse_reparse_point(buf, plen, cifs_sb, full_path, true, data); 748 } 749 750 static void wsl_to_fattr(struct cifs_open_info_data *data, 751 struct cifs_sb_info *cifs_sb, 752 u32 tag, struct cifs_fattr *fattr) 753 { 754 struct smb2_file_full_ea_info *ea; 755 u32 next = 0; 756 757 switch (tag) { 758 case IO_REPARSE_TAG_LX_SYMLINK: 759 fattr->cf_mode |= S_IFLNK; 760 break; 761 case IO_REPARSE_TAG_LX_FIFO: 762 fattr->cf_mode |= S_IFIFO; 763 break; 764 case IO_REPARSE_TAG_AF_UNIX: 765 fattr->cf_mode |= S_IFSOCK; 766 break; 767 case IO_REPARSE_TAG_LX_CHR: 768 fattr->cf_mode |= S_IFCHR; 769 break; 770 case IO_REPARSE_TAG_LX_BLK: 771 fattr->cf_mode |= S_IFBLK; 772 break; 773 } 774 775 if (!data->wsl.eas_len) 776 goto out; 777 778 ea = (struct smb2_file_full_ea_info *)data->wsl.eas; 779 do { 780 const char *name; 781 void *v; 782 u8 nlen; 783 784 ea = (void *)((u8 *)ea + next); 785 next = le32_to_cpu(ea->next_entry_offset); 786 if (!le16_to_cpu(ea->ea_value_length)) 787 continue; 788 789 name = ea->ea_data; 790 nlen = ea->ea_name_length; 791 v = (void *)((u8 *)ea->ea_data + ea->ea_name_length + 1); 792 793 if (!strncmp(name, SMB2_WSL_XATTR_UID, nlen)) 794 fattr->cf_uid = wsl_make_kuid(cifs_sb, v); 795 else if (!strncmp(name, SMB2_WSL_XATTR_GID, nlen)) 796 fattr->cf_gid = wsl_make_kgid(cifs_sb, v); 797 else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen)) 798 fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v); 799 else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) 800 fattr->cf_rdev = reparse_mkdev(v); 801 } while (next); 802 out: 803 fattr->cf_dtype = S_DT(fattr->cf_mode); 804 } 805 806 static bool posix_reparse_to_fattr(struct cifs_sb_info *cifs_sb, 807 struct cifs_fattr *fattr, 808 struct cifs_open_info_data *data) 809 { 810 struct reparse_posix_data *buf = data->reparse.posix; 811 812 813 if (buf == NULL) 814 return true; 815 816 if (le16_to_cpu(buf->ReparseDataLength) < sizeof(buf->InodeType)) { 817 WARN_ON_ONCE(1); 818 return false; 819 } 820 821 switch (le64_to_cpu(buf->InodeType)) { 822 case NFS_SPECFILE_CHR: 823 if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8) { 824 WARN_ON_ONCE(1); 825 return false; 826 } 827 fattr->cf_mode |= S_IFCHR; 828 fattr->cf_rdev = reparse_mkdev(buf->DataBuffer); 829 break; 830 case NFS_SPECFILE_BLK: 831 if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8) { 832 WARN_ON_ONCE(1); 833 return false; 834 } 835 fattr->cf_mode |= S_IFBLK; 836 fattr->cf_rdev = reparse_mkdev(buf->DataBuffer); 837 break; 838 case NFS_SPECFILE_FIFO: 839 fattr->cf_mode |= S_IFIFO; 840 break; 841 case NFS_SPECFILE_SOCK: 842 fattr->cf_mode |= S_IFSOCK; 843 break; 844 case NFS_SPECFILE_LNK: 845 fattr->cf_mode |= S_IFLNK; 846 break; 847 default: 848 WARN_ON_ONCE(1); 849 return false; 850 } 851 return true; 852 } 853 854 bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, 855 struct cifs_fattr *fattr, 856 struct cifs_open_info_data *data) 857 { 858 u32 tag = data->reparse.tag; 859 bool ok; 860 861 switch (tag) { 862 case IO_REPARSE_TAG_INTERNAL: 863 if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY)) 864 return false; 865 fallthrough; 866 case IO_REPARSE_TAG_DFS: 867 case IO_REPARSE_TAG_DFSR: 868 case IO_REPARSE_TAG_MOUNT_POINT: 869 /* See cifs_create_junction_fattr() */ 870 fattr->cf_mode = S_IFDIR | 0711; 871 break; 872 case IO_REPARSE_TAG_LX_SYMLINK: 873 case IO_REPARSE_TAG_LX_FIFO: 874 case IO_REPARSE_TAG_AF_UNIX: 875 case IO_REPARSE_TAG_LX_CHR: 876 case IO_REPARSE_TAG_LX_BLK: 877 wsl_to_fattr(data, cifs_sb, tag, fattr); 878 break; 879 case IO_REPARSE_TAG_NFS: 880 ok = posix_reparse_to_fattr(cifs_sb, fattr, data); 881 if (!ok) 882 return false; 883 break; 884 case 0: /* SMB1 symlink */ 885 case IO_REPARSE_TAG_SYMLINK: 886 fattr->cf_mode |= S_IFLNK; 887 break; 888 default: 889 return false; 890 } 891 892 fattr->cf_dtype = S_DT(fattr->cf_mode); 893 return true; 894 } 895