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