1 // SPDX-License-Identifier: LGPL-2.1 2 /* 3 * 4 * Copyright (C) International Business Machines Corp., 2002,2008 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 * 7 */ 8 #include <crypto/md5.h> 9 #include <linux/fs.h> 10 #include <linux/stat.h> 11 #include <linux/slab.h> 12 #include <linux/namei.h> 13 #include "cifsfs.h" 14 #include "cifsglob.h" 15 #include "cifsproto.h" 16 #include "cifs_debug.h" 17 #include "cifs_fs_sb.h" 18 #include "cifs_unicode.h" 19 #include "smb2proto.h" 20 #include "cifs_ioctl.h" 21 #include "fs_context.h" 22 #include "reparse.h" 23 24 /* 25 * M-F Symlink Functions - Begin 26 */ 27 28 #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) 29 #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) 30 #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) 31 #define CIFS_MF_SYMLINK_LINK_MAXLEN (1024) 32 #define CIFS_MF_SYMLINK_FILE_SIZE \ 33 (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN) 34 35 #define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n" 36 #define CIFS_MF_SYMLINK_MD5_FORMAT "%16phN\n" 37 #define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) md5_hash 38 39 static int 40 parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len, 41 char **_link_str) 42 { 43 int rc; 44 unsigned int link_len; 45 const char *md5_str1; 46 const char *link_str; 47 u8 md5_hash[16]; 48 char md5_str2[34]; 49 50 if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) 51 return -EINVAL; 52 53 md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET]; 54 link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET]; 55 56 rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len); 57 if (rc != 1) 58 return -EINVAL; 59 60 if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN) 61 return -EINVAL; 62 63 md5(link_str, link_len, md5_hash); 64 65 scnprintf(md5_str2, sizeof(md5_str2), 66 CIFS_MF_SYMLINK_MD5_FORMAT, 67 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash)); 68 69 if (strncmp(md5_str1, md5_str2, 17) != 0) 70 return -EINVAL; 71 72 if (_link_str) { 73 *_link_str = kstrndup(link_str, link_len, GFP_KERNEL); 74 if (!*_link_str) 75 return -ENOMEM; 76 } 77 78 *_link_len = link_len; 79 return 0; 80 } 81 82 static int 83 format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str) 84 { 85 unsigned int link_len; 86 unsigned int ofs; 87 u8 md5_hash[16]; 88 89 if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) 90 return -EINVAL; 91 92 link_len = strlen(link_str); 93 94 if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN) 95 return -ENAMETOOLONG; 96 97 md5(link_str, link_len, md5_hash); 98 99 scnprintf(buf, buf_len, 100 CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT, 101 link_len, 102 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash)); 103 104 ofs = CIFS_MF_SYMLINK_LINK_OFFSET; 105 memcpy(buf + ofs, link_str, link_len); 106 107 ofs += link_len; 108 if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) { 109 buf[ofs] = '\n'; 110 ofs++; 111 } 112 113 while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) { 114 buf[ofs] = ' '; 115 ofs++; 116 } 117 118 return 0; 119 } 120 121 bool 122 couldbe_mf_symlink(const struct cifs_fattr *fattr) 123 { 124 if (!S_ISREG(fattr->cf_mode)) 125 /* it's not a symlink */ 126 return false; 127 128 if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) 129 /* it's not a symlink */ 130 return false; 131 132 return true; 133 } 134 135 static int 136 create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, 137 struct cifs_sb_info *cifs_sb, const char *fromName, 138 const char *toName) 139 { 140 int rc; 141 u8 *buf; 142 unsigned int bytes_written = 0; 143 144 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); 145 if (!buf) 146 return -ENOMEM; 147 148 rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); 149 if (rc) 150 goto out; 151 152 if (tcon->ses->server->ops->create_mf_symlink) 153 rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, 154 cifs_sb, fromName, buf, &bytes_written); 155 else 156 rc = -EOPNOTSUPP; 157 158 if (rc) 159 goto out; 160 161 if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) 162 rc = smb_EIO2(smb_eio_trace_symlink_file_size, 163 bytes_written, CIFS_MF_SYMLINK_FILE_SIZE); 164 out: 165 kfree(buf); 166 return rc; 167 } 168 169 int 170 check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 171 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, 172 const unsigned char *path) 173 { 174 int rc; 175 u8 *buf = NULL; 176 unsigned int link_len = 0; 177 unsigned int bytes_read = 0; 178 char *symlink = NULL; 179 180 if (!couldbe_mf_symlink(fattr)) 181 /* it's not a symlink */ 182 return 0; 183 184 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); 185 if (!buf) 186 return -ENOMEM; 187 188 if (tcon->ses->server->ops->query_mf_symlink) 189 rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, 190 cifs_sb, path, buf, &bytes_read); 191 else 192 rc = -ENOSYS; 193 194 if (rc) 195 goto out; 196 197 if (bytes_read == 0) /* not a symlink */ 198 goto out; 199 200 rc = parse_mf_symlink(buf, bytes_read, &link_len, &symlink); 201 if (rc == -EINVAL) { 202 /* it's not a symlink */ 203 rc = 0; 204 goto out; 205 } 206 207 if (rc != 0) 208 goto out; 209 210 /* it is a symlink */ 211 fattr->cf_eof = link_len; 212 fattr->cf_mode &= ~S_IFMT; 213 fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; 214 fattr->cf_dtype = DT_LNK; 215 fattr->cf_symlink_target = symlink; 216 out: 217 kfree(buf); 218 return rc; 219 } 220 221 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 222 /* 223 * SMB 1.0 Protocol specific functions 224 */ 225 226 int 227 cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 228 struct cifs_sb_info *cifs_sb, const unsigned char *path, 229 char *pbuf, unsigned int *pbytes_read) 230 { 231 int rc; 232 int oplock = 0; 233 struct cifs_fid fid; 234 struct cifs_open_parms oparms; 235 struct cifs_io_parms io_parms = {0}; 236 int buf_type = CIFS_NO_BUFFER; 237 struct cifs_open_info_data query_data; 238 239 oparms = (struct cifs_open_parms) { 240 .tcon = tcon, 241 .cifs_sb = cifs_sb, 242 .desired_access = GENERIC_READ, 243 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), 244 .disposition = FILE_OPEN, 245 .path = path, 246 .fid = &fid, 247 }; 248 249 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &query_data); 250 if (rc) 251 return rc; 252 253 if (query_data.fi.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { 254 rc = -ENOENT; 255 /* it's not a symlink */ 256 goto out; 257 } 258 259 io_parms.netfid = fid.netfid; 260 io_parms.pid = current->tgid; 261 io_parms.tcon = tcon; 262 io_parms.offset = 0; 263 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 264 265 rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); 266 out: 267 CIFSSMBClose(xid, tcon, fid.netfid); 268 return rc; 269 } 270 271 int 272 cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 273 struct cifs_sb_info *cifs_sb, const unsigned char *path, 274 char *pbuf, unsigned int *pbytes_written) 275 { 276 int rc; 277 int oplock = 0; 278 struct cifs_fid fid; 279 struct cifs_open_parms oparms; 280 struct cifs_io_parms io_parms = {0}; 281 282 oparms = (struct cifs_open_parms) { 283 .tcon = tcon, 284 .cifs_sb = cifs_sb, 285 .desired_access = GENERIC_WRITE, 286 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), 287 .disposition = FILE_CREATE, 288 .path = path, 289 .fid = &fid, 290 }; 291 292 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); 293 if (rc) 294 return rc; 295 296 io_parms.netfid = fid.netfid; 297 io_parms.pid = current->tgid; 298 io_parms.tcon = tcon; 299 io_parms.offset = 0; 300 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 301 302 rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf); 303 CIFSSMBClose(xid, tcon, fid.netfid); 304 return rc; 305 } 306 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 307 308 /* 309 * SMB 2.1/SMB3 Protocol specific functions 310 */ 311 int 312 smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 313 struct cifs_sb_info *cifs_sb, const unsigned char *path, 314 char *pbuf, unsigned int *pbytes_read) 315 { 316 int rc; 317 struct cifs_fid fid; 318 struct cifs_open_parms oparms; 319 struct cifs_io_parms io_parms = {0}; 320 int buf_type = CIFS_NO_BUFFER; 321 __le16 *utf16_path; 322 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 323 struct smb2_file_all_info *pfile_info = NULL; 324 325 oparms = (struct cifs_open_parms) { 326 .tcon = tcon, 327 .cifs_sb = cifs_sb, 328 .path = path, 329 .desired_access = GENERIC_READ, 330 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), 331 .disposition = FILE_OPEN, 332 .fid = &fid, 333 }; 334 335 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); 336 if (utf16_path == NULL) 337 return -ENOMEM; 338 339 pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 340 GFP_KERNEL); 341 342 if (pfile_info == NULL) { 343 kfree(utf16_path); 344 return -ENOMEM; 345 } 346 347 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL, 348 NULL, NULL); 349 if (rc) 350 goto qmf_out_open_fail; 351 352 if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { 353 /* it's not a symlink */ 354 rc = -ENOENT; /* Is there a better rc to return? */ 355 goto qmf_out; 356 } 357 358 io_parms.netfid = fid.netfid; 359 io_parms.pid = current->tgid; 360 io_parms.tcon = tcon; 361 io_parms.offset = 0; 362 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 363 io_parms.persistent_fid = fid.persistent_fid; 364 io_parms.volatile_fid = fid.volatile_fid; 365 rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type); 366 qmf_out: 367 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 368 qmf_out_open_fail: 369 kfree(utf16_path); 370 kfree(pfile_info); 371 return rc; 372 } 373 374 int 375 smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 376 struct cifs_sb_info *cifs_sb, const unsigned char *path, 377 char *pbuf, unsigned int *pbytes_written) 378 { 379 int rc; 380 struct cifs_fid fid; 381 struct cifs_open_parms oparms; 382 struct cifs_io_parms io_parms = {0}; 383 __le16 *utf16_path; 384 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 385 struct kvec iov[2]; 386 387 cifs_dbg(FYI, "%s: path: %s\n", __func__, path); 388 389 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); 390 if (!utf16_path) 391 return -ENOMEM; 392 393 oparms = (struct cifs_open_parms) { 394 .tcon = tcon, 395 .cifs_sb = cifs_sb, 396 .path = path, 397 .desired_access = GENERIC_WRITE, 398 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), 399 .disposition = FILE_CREATE, 400 .fid = &fid, 401 .mode = 0644, 402 }; 403 404 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, 405 NULL, NULL); 406 if (rc) { 407 kfree(utf16_path); 408 return rc; 409 } 410 411 io_parms.netfid = fid.netfid; 412 io_parms.pid = current->tgid; 413 io_parms.tcon = tcon; 414 io_parms.offset = 0; 415 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; 416 io_parms.persistent_fid = fid.persistent_fid; 417 io_parms.volatile_fid = fid.volatile_fid; 418 419 /* iov[0] is reserved for smb header */ 420 iov[1].iov_base = pbuf; 421 iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE; 422 423 rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1); 424 425 /* Make sure we wrote all of the symlink data */ 426 if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE)) 427 rc = smb_EIO2(smb_eio_trace_short_symlink_write, 428 *pbytes_written, CIFS_MF_SYMLINK_FILE_SIZE); 429 430 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 431 432 kfree(utf16_path); 433 return rc; 434 } 435 436 /* 437 * M-F Symlink Functions - End 438 */ 439 440 int 441 cifs_hardlink(struct dentry *old_file, struct inode *inode, 442 struct dentry *direntry) 443 { 444 int rc = -EACCES; 445 unsigned int xid; 446 const char *from_name, *to_name; 447 void *page1, *page2; 448 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 449 struct tcon_link *tlink; 450 struct cifs_tcon *tcon; 451 struct TCP_Server_Info *server; 452 struct cifsInodeInfo *cifsInode; 453 454 if (unlikely(cifs_forced_shutdown(cifs_sb))) 455 return smb_EIO(smb_eio_trace_forced_shutdown); 456 457 tlink = cifs_sb_tlink(cifs_sb); 458 if (IS_ERR(tlink)) 459 return PTR_ERR(tlink); 460 tcon = tlink_tcon(tlink); 461 462 xid = get_xid(); 463 page1 = alloc_dentry_path(); 464 page2 = alloc_dentry_path(); 465 466 from_name = build_path_from_dentry(old_file, page1); 467 if (IS_ERR(from_name)) { 468 rc = PTR_ERR(from_name); 469 goto cifs_hl_exit; 470 } 471 to_name = build_path_from_dentry(direntry, page2); 472 if (IS_ERR(to_name)) { 473 rc = PTR_ERR(to_name); 474 goto cifs_hl_exit; 475 } 476 477 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 478 if (tcon->unix_ext) 479 rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name, 480 cifs_sb->local_nls, 481 cifs_remap(cifs_sb)); 482 else { 483 #else 484 { 485 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 486 server = tcon->ses->server; 487 if (!server->ops->create_hardlink) { 488 rc = -ENOSYS; 489 goto cifs_hl_exit; 490 } 491 rc = server->ops->create_hardlink(xid, tcon, old_file, 492 from_name, to_name, cifs_sb); 493 if ((rc == -EIO) || (rc == -EINVAL)) 494 rc = -EOPNOTSUPP; 495 } 496 497 d_drop(direntry); /* force new lookup from server of target */ 498 499 /* 500 * if source file is cached (oplocked) revalidate will not go to server 501 * until the file is closed or oplock broken so update nlinks locally 502 */ 503 if (d_really_is_positive(old_file)) { 504 cifsInode = CIFS_I(d_inode(old_file)); 505 if (rc == 0) { 506 spin_lock(&d_inode(old_file)->i_lock); 507 inc_nlink(d_inode(old_file)); 508 spin_unlock(&d_inode(old_file)->i_lock); 509 510 /* 511 * parent dir timestamps will update from srv within a 512 * second, would it really be worth it to set the parent 513 * dir cifs inode time to zero to force revalidate 514 * (faster) for it too? 515 */ 516 } 517 /* 518 * if not oplocked will force revalidate to get info on source 519 * file from srv. Note Samba server prior to 4.2 has bug - 520 * not updating src file ctime on hardlinks but Windows servers 521 * handle it properly 522 */ 523 cifsInode->time = 0; 524 525 /* 526 * Will update parent dir timestamps from srv within a second. 527 * Would it really be worth it to set the parent dir (cifs 528 * inode) time field to zero to force revalidate on parent 529 * directory faster ie 530 * 531 * CIFS_I(inode)->time = 0; 532 */ 533 } 534 535 cifs_hl_exit: 536 free_dentry_path(page1); 537 free_dentry_path(page2); 538 free_xid(xid); 539 cifs_put_tlink(tlink); 540 return rc; 541 } 542 543 int 544 cifs_symlink(struct mnt_idmap *idmap, struct inode *inode, 545 struct dentry *direntry, const char *symname) 546 { 547 struct cifs_sb_info *cifs_sb = CIFS_SB(inode); 548 struct inode *newinode = NULL; 549 struct tcon_link *tlink; 550 struct cifs_tcon *pTcon; 551 const char *full_path; 552 int rc = -EOPNOTSUPP; 553 unsigned int sbflags; 554 unsigned int xid; 555 void *page; 556 557 if (unlikely(cifs_forced_shutdown(cifs_sb))) 558 return smb_EIO(smb_eio_trace_forced_shutdown); 559 560 page = alloc_dentry_path(); 561 if (!page) 562 return -ENOMEM; 563 564 xid = get_xid(); 565 566 tlink = cifs_sb_tlink(cifs_sb); 567 if (IS_ERR(tlink)) { 568 rc = PTR_ERR(tlink); 569 /* BB could be clearer if skipped put_tlink on error here, but harmless */ 570 goto symlink_exit; 571 } 572 pTcon = tlink_tcon(tlink); 573 574 full_path = build_path_from_dentry(direntry, page); 575 if (IS_ERR(full_path)) { 576 rc = PTR_ERR(full_path); 577 goto symlink_exit; 578 } 579 580 cifs_dbg(FYI, "Full path: %s\n", full_path); 581 cifs_dbg(FYI, "symname is %s\n", symname); 582 583 /* BB what if DFS and this volume is on different share? BB */ 584 sbflags = cifs_sb_flags(cifs_sb); 585 rc = -EOPNOTSUPP; 586 switch (cifs_symlink_type(cifs_sb)) { 587 case CIFS_SYMLINK_TYPE_UNIX: 588 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 589 if (pTcon->unix_ext) { 590 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, 591 symname, 592 cifs_sb->local_nls, 593 cifs_remap(cifs_sb)); 594 } 595 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 596 break; 597 598 case CIFS_SYMLINK_TYPE_MFSYMLINKS: 599 if (sbflags & CIFS_MOUNT_MF_SYMLINKS) { 600 rc = create_mf_symlink(xid, pTcon, cifs_sb, 601 full_path, symname); 602 } 603 break; 604 605 case CIFS_SYMLINK_TYPE_SFU: 606 if (sbflags & CIFS_MOUNT_UNX_EMUL) { 607 rc = __cifs_sfu_make_node(xid, inode, direntry, pTcon, 608 full_path, S_IFLNK, 609 0, symname); 610 } 611 break; 612 613 case CIFS_SYMLINK_TYPE_NATIVE: 614 case CIFS_SYMLINK_TYPE_NFS: 615 case CIFS_SYMLINK_TYPE_WSL: 616 if (CIFS_REPARSE_SUPPORT(pTcon)) { 617 rc = create_reparse_symlink(xid, inode, direntry, pTcon, 618 full_path, symname); 619 goto symlink_exit; 620 } 621 break; 622 default: 623 break; 624 } 625 626 if (rc == 0) { 627 if (pTcon->posix_extensions) { 628 rc = smb311_posix_get_inode_info(&newinode, full_path, 629 NULL, inode->i_sb, xid); 630 } else if (pTcon->unix_ext) { 631 rc = cifs_get_inode_info_unix(&newinode, full_path, 632 inode->i_sb, xid); 633 } else { 634 rc = cifs_get_inode_info(&newinode, full_path, NULL, 635 inode->i_sb, xid, NULL); 636 } 637 638 if (rc != 0) { 639 cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n", 640 rc); 641 } else { 642 d_instantiate(direntry, newinode); 643 } 644 } 645 symlink_exit: 646 free_dentry_path(page); 647 cifs_put_tlink(tlink); 648 free_xid(xid); 649 return rc; 650 } 651