1 // SPDX-License-Identifier: LGPL-2.1
4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
9 #include <linux/stat.h>
10 #include <linux/slab.h>
11 #include <linux/namei.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"
23 * M-F Symlink Functions - Begin
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)
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
38 symlink_hash(unsigned int link_len
, const char *link_str
, u8
*md5_hash
)
41 struct shash_desc
*md5
= NULL
;
43 rc
= cifs_alloc_hash("md5", &md5
);
47 rc
= crypto_shash_digest(md5
, link_str
, link_len
, md5_hash
);
49 cifs_dbg(VFS
, "%s: Could not generate md5 hash\n", __func__
);
55 parse_mf_symlink(const u8
*buf
, unsigned int buf_len
, unsigned int *_link_len
,
59 unsigned int link_len
;
65 if (buf_len
!= CIFS_MF_SYMLINK_FILE_SIZE
)
68 md5_str1
= (const char *)&buf
[CIFS_MF_SYMLINK_MD5_OFFSET
];
69 link_str
= (const char *)&buf
[CIFS_MF_SYMLINK_LINK_OFFSET
];
71 rc
= sscanf(buf
, CIFS_MF_SYMLINK_LEN_FORMAT
, &link_len
);
75 if (link_len
> CIFS_MF_SYMLINK_LINK_MAXLEN
)
78 rc
= symlink_hash(link_len
, link_str
, md5_hash
);
80 cifs_dbg(FYI
, "%s: MD5 hash failure: %d\n", __func__
, rc
);
84 scnprintf(md5_str2
, sizeof(md5_str2
),
85 CIFS_MF_SYMLINK_MD5_FORMAT
,
86 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash
));
88 if (strncmp(md5_str1
, md5_str2
, 17) != 0)
92 *_link_str
= kstrndup(link_str
, link_len
, GFP_KERNEL
);
97 *_link_len
= link_len
;
102 format_mf_symlink(u8
*buf
, unsigned int buf_len
, const char *link_str
)
105 unsigned int link_len
;
109 if (buf_len
!= CIFS_MF_SYMLINK_FILE_SIZE
)
112 link_len
= strlen(link_str
);
114 if (link_len
> CIFS_MF_SYMLINK_LINK_MAXLEN
)
115 return -ENAMETOOLONG
;
117 rc
= symlink_hash(link_len
, link_str
, md5_hash
);
119 cifs_dbg(FYI
, "%s: MD5 hash failure: %d\n", __func__
, rc
);
123 scnprintf(buf
, buf_len
,
124 CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT
,
126 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash
));
128 ofs
= CIFS_MF_SYMLINK_LINK_OFFSET
;
129 memcpy(buf
+ ofs
, link_str
, link_len
);
132 if (ofs
< CIFS_MF_SYMLINK_FILE_SIZE
) {
137 while (ofs
< CIFS_MF_SYMLINK_FILE_SIZE
) {
146 couldbe_mf_symlink(const struct cifs_fattr
*fattr
)
148 if (!S_ISREG(fattr
->cf_mode
))
149 /* it's not a symlink */
152 if (fattr
->cf_eof
!= CIFS_MF_SYMLINK_FILE_SIZE
)
153 /* it's not a symlink */
160 create_mf_symlink(const unsigned int xid
, struct cifs_tcon
*tcon
,
161 struct cifs_sb_info
*cifs_sb
, const char *fromName
,
166 unsigned int bytes_written
= 0;
168 buf
= kmalloc(CIFS_MF_SYMLINK_FILE_SIZE
, GFP_KERNEL
);
172 rc
= format_mf_symlink(buf
, CIFS_MF_SYMLINK_FILE_SIZE
, toName
);
176 if (tcon
->ses
->server
->ops
->create_mf_symlink
)
177 rc
= tcon
->ses
->server
->ops
->create_mf_symlink(xid
, tcon
,
178 cifs_sb
, fromName
, buf
, &bytes_written
);
185 if (bytes_written
!= CIFS_MF_SYMLINK_FILE_SIZE
)
193 check_mf_symlink(unsigned int xid
, struct cifs_tcon
*tcon
,
194 struct cifs_sb_info
*cifs_sb
, struct cifs_fattr
*fattr
,
195 const unsigned char *path
)
199 unsigned int link_len
= 0;
200 unsigned int bytes_read
= 0;
201 char *symlink
= NULL
;
203 if (!couldbe_mf_symlink(fattr
))
204 /* it's not a symlink */
207 buf
= kmalloc(CIFS_MF_SYMLINK_FILE_SIZE
, GFP_KERNEL
);
211 if (tcon
->ses
->server
->ops
->query_mf_symlink
)
212 rc
= tcon
->ses
->server
->ops
->query_mf_symlink(xid
, tcon
,
213 cifs_sb
, path
, buf
, &bytes_read
);
220 if (bytes_read
== 0) /* not a symlink */
223 rc
= parse_mf_symlink(buf
, bytes_read
, &link_len
, &symlink
);
225 /* it's not a symlink */
233 /* it is a symlink */
234 fattr
->cf_eof
= link_len
;
235 fattr
->cf_mode
&= ~S_IFMT
;
236 fattr
->cf_mode
|= S_IFLNK
| S_IRWXU
| S_IRWXG
| S_IRWXO
;
237 fattr
->cf_dtype
= DT_LNK
;
238 fattr
->cf_symlink_target
= symlink
;
244 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
246 * SMB 1.0 Protocol specific functions
250 cifs_query_mf_symlink(unsigned int xid
, struct cifs_tcon
*tcon
,
251 struct cifs_sb_info
*cifs_sb
, const unsigned char *path
,
252 char *pbuf
, unsigned int *pbytes_read
)
257 struct cifs_open_parms oparms
;
258 struct cifs_io_parms io_parms
= {0};
259 int buf_type
= CIFS_NO_BUFFER
;
260 FILE_ALL_INFO file_info
;
262 oparms
= (struct cifs_open_parms
) {
265 .desired_access
= GENERIC_READ
,
266 .create_options
= cifs_create_options(cifs_sb
, CREATE_NOT_DIR
),
267 .disposition
= FILE_OPEN
,
272 rc
= CIFS_open(xid
, &oparms
, &oplock
, &file_info
);
276 if (file_info
.EndOfFile
!= cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE
)) {
278 /* it's not a symlink */
282 io_parms
.netfid
= fid
.netfid
;
283 io_parms
.pid
= current
->tgid
;
284 io_parms
.tcon
= tcon
;
286 io_parms
.length
= CIFS_MF_SYMLINK_FILE_SIZE
;
288 rc
= CIFSSMBRead(xid
, &io_parms
, pbytes_read
, &pbuf
, &buf_type
);
290 CIFSSMBClose(xid
, tcon
, fid
.netfid
);
295 cifs_create_mf_symlink(unsigned int xid
, struct cifs_tcon
*tcon
,
296 struct cifs_sb_info
*cifs_sb
, const unsigned char *path
,
297 char *pbuf
, unsigned int *pbytes_written
)
302 struct cifs_open_parms oparms
;
303 struct cifs_io_parms io_parms
= {0};
305 oparms
= (struct cifs_open_parms
) {
308 .desired_access
= GENERIC_WRITE
,
309 .create_options
= cifs_create_options(cifs_sb
, CREATE_NOT_DIR
),
310 .disposition
= FILE_CREATE
,
315 rc
= CIFS_open(xid
, &oparms
, &oplock
, NULL
);
319 io_parms
.netfid
= fid
.netfid
;
320 io_parms
.pid
= current
->tgid
;
321 io_parms
.tcon
= tcon
;
323 io_parms
.length
= CIFS_MF_SYMLINK_FILE_SIZE
;
325 rc
= CIFSSMBWrite(xid
, &io_parms
, pbytes_written
, pbuf
);
326 CIFSSMBClose(xid
, tcon
, fid
.netfid
);
329 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
332 * SMB 2.1/SMB3 Protocol specific functions
335 smb3_query_mf_symlink(unsigned int xid
, struct cifs_tcon
*tcon
,
336 struct cifs_sb_info
*cifs_sb
, const unsigned char *path
,
337 char *pbuf
, unsigned int *pbytes_read
)
341 struct cifs_open_parms oparms
;
342 struct cifs_io_parms io_parms
= {0};
343 int buf_type
= CIFS_NO_BUFFER
;
345 __u8 oplock
= SMB2_OPLOCK_LEVEL_NONE
;
346 struct smb2_file_all_info
*pfile_info
= NULL
;
348 oparms
= (struct cifs_open_parms
) {
352 .desired_access
= GENERIC_READ
,
353 .create_options
= cifs_create_options(cifs_sb
, CREATE_NOT_DIR
),
354 .disposition
= FILE_OPEN
,
358 utf16_path
= cifs_convert_path_to_utf16(path
, cifs_sb
);
359 if (utf16_path
== NULL
)
362 pfile_info
= kzalloc(sizeof(struct smb2_file_all_info
) + PATH_MAX
* 2,
365 if (pfile_info
== NULL
) {
370 rc
= SMB2_open(xid
, &oparms
, utf16_path
, &oplock
, pfile_info
, NULL
,
373 goto qmf_out_open_fail
;
375 if (pfile_info
->EndOfFile
!= cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE
)) {
376 /* it's not a symlink */
377 rc
= -ENOENT
; /* Is there a better rc to return? */
381 io_parms
.netfid
= fid
.netfid
;
382 io_parms
.pid
= current
->tgid
;
383 io_parms
.tcon
= tcon
;
385 io_parms
.length
= CIFS_MF_SYMLINK_FILE_SIZE
;
386 io_parms
.persistent_fid
= fid
.persistent_fid
;
387 io_parms
.volatile_fid
= fid
.volatile_fid
;
388 rc
= SMB2_read(xid
, &io_parms
, pbytes_read
, &pbuf
, &buf_type
);
390 SMB2_close(xid
, tcon
, fid
.persistent_fid
, fid
.volatile_fid
);
398 smb3_create_mf_symlink(unsigned int xid
, struct cifs_tcon
*tcon
,
399 struct cifs_sb_info
*cifs_sb
, const unsigned char *path
,
400 char *pbuf
, unsigned int *pbytes_written
)
404 struct cifs_open_parms oparms
;
405 struct cifs_io_parms io_parms
= {0};
407 __u8 oplock
= SMB2_OPLOCK_LEVEL_NONE
;
410 cifs_dbg(FYI
, "%s: path: %s\n", __func__
, path
);
412 utf16_path
= cifs_convert_path_to_utf16(path
, cifs_sb
);
416 oparms
= (struct cifs_open_parms
) {
420 .desired_access
= GENERIC_WRITE
,
421 .create_options
= cifs_create_options(cifs_sb
, CREATE_NOT_DIR
),
422 .disposition
= FILE_CREATE
,
427 rc
= SMB2_open(xid
, &oparms
, utf16_path
, &oplock
, NULL
, NULL
,
434 io_parms
.netfid
= fid
.netfid
;
435 io_parms
.pid
= current
->tgid
;
436 io_parms
.tcon
= tcon
;
438 io_parms
.length
= CIFS_MF_SYMLINK_FILE_SIZE
;
439 io_parms
.persistent_fid
= fid
.persistent_fid
;
440 io_parms
.volatile_fid
= fid
.volatile_fid
;
442 /* iov[0] is reserved for smb header */
443 iov
[1].iov_base
= pbuf
;
444 iov
[1].iov_len
= CIFS_MF_SYMLINK_FILE_SIZE
;
446 rc
= SMB2_write(xid
, &io_parms
, pbytes_written
, iov
, 1);
448 /* Make sure we wrote all of the symlink data */
449 if ((rc
== 0) && (*pbytes_written
!= CIFS_MF_SYMLINK_FILE_SIZE
))
452 SMB2_close(xid
, tcon
, fid
.persistent_fid
, fid
.volatile_fid
);
459 * M-F Symlink Functions - End
463 cifs_hardlink(struct dentry
*old_file
, struct inode
*inode
,
464 struct dentry
*direntry
)
468 const char *from_name
, *to_name
;
470 struct cifs_sb_info
*cifs_sb
= CIFS_SB(inode
->i_sb
);
471 struct tcon_link
*tlink
;
472 struct cifs_tcon
*tcon
;
473 struct TCP_Server_Info
*server
;
474 struct cifsInodeInfo
*cifsInode
;
476 if (unlikely(cifs_forced_shutdown(cifs_sb
)))
479 tlink
= cifs_sb_tlink(cifs_sb
);
481 return PTR_ERR(tlink
);
482 tcon
= tlink_tcon(tlink
);
485 page1
= alloc_dentry_path();
486 page2
= alloc_dentry_path();
488 from_name
= build_path_from_dentry(old_file
, page1
);
489 if (IS_ERR(from_name
)) {
490 rc
= PTR_ERR(from_name
);
493 to_name
= build_path_from_dentry(direntry
, page2
);
494 if (IS_ERR(to_name
)) {
495 rc
= PTR_ERR(to_name
);
499 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
501 rc
= CIFSUnixCreateHardLink(xid
, tcon
, from_name
, to_name
,
503 cifs_remap(cifs_sb
));
507 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
508 server
= tcon
->ses
->server
;
509 if (!server
->ops
->create_hardlink
) {
513 rc
= server
->ops
->create_hardlink(xid
, tcon
, old_file
,
514 from_name
, to_name
, cifs_sb
);
515 if ((rc
== -EIO
) || (rc
== -EINVAL
))
519 d_drop(direntry
); /* force new lookup from server of target */
522 * if source file is cached (oplocked) revalidate will not go to server
523 * until the file is closed or oplock broken so update nlinks locally
525 if (d_really_is_positive(old_file
)) {
526 cifsInode
= CIFS_I(d_inode(old_file
));
528 spin_lock(&d_inode(old_file
)->i_lock
);
529 inc_nlink(d_inode(old_file
));
530 spin_unlock(&d_inode(old_file
)->i_lock
);
533 * parent dir timestamps will update from srv within a
534 * second, would it really be worth it to set the parent
535 * dir cifs inode time to zero to force revalidate
536 * (faster) for it too?
540 * if not oplocked will force revalidate to get info on source
541 * file from srv. Note Samba server prior to 4.2 has bug -
542 * not updating src file ctime on hardlinks but Windows servers
548 * Will update parent dir timestamps from srv within a second.
549 * Would it really be worth it to set the parent dir (cifs
550 * inode) time field to zero to force revalidate on parent
551 * directory faster ie
553 * CIFS_I(inode)->time = 0;
558 free_dentry_path(page1
);
559 free_dentry_path(page2
);
561 cifs_put_tlink(tlink
);
566 cifs_symlink(struct mnt_idmap
*idmap
, struct inode
*inode
,
567 struct dentry
*direntry
, const char *symname
)
569 int rc
= -EOPNOTSUPP
;
571 struct cifs_sb_info
*cifs_sb
= CIFS_SB(inode
->i_sb
);
572 struct TCP_Server_Info
*server
;
573 struct tcon_link
*tlink
;
574 struct cifs_tcon
*pTcon
;
575 const char *full_path
;
577 struct inode
*newinode
= NULL
;
579 if (unlikely(cifs_forced_shutdown(cifs_sb
)))
582 page
= alloc_dentry_path();
588 tlink
= cifs_sb_tlink(cifs_sb
);
591 /* BB could be clearer if skipped put_tlink on error here, but harmless */
594 pTcon
= tlink_tcon(tlink
);
595 server
= cifs_pick_channel(pTcon
->ses
);
597 full_path
= build_path_from_dentry(direntry
, page
);
598 if (IS_ERR(full_path
)) {
599 rc
= PTR_ERR(full_path
);
603 cifs_dbg(FYI
, "Full path: %s\n", full_path
);
604 cifs_dbg(FYI
, "symname is %s\n", symname
);
606 /* BB what if DFS and this volume is on different share? BB */
607 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_MF_SYMLINKS
) {
608 rc
= create_mf_symlink(xid
, pTcon
, cifs_sb
, full_path
, symname
);
609 } else if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_UNX_EMUL
) {
610 rc
= __cifs_sfu_make_node(xid
, inode
, direntry
, pTcon
,
611 full_path
, S_IFLNK
, 0, symname
);
612 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
613 } else if (pTcon
->unix_ext
) {
614 rc
= CIFSUnixCreateSymLink(xid
, pTcon
, full_path
, symname
,
616 cifs_remap(cifs_sb
));
617 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
618 } else if (server
->ops
->create_reparse_symlink
) {
619 rc
= server
->ops
->create_reparse_symlink(xid
, inode
, direntry
,
626 if (pTcon
->posix_extensions
) {
627 rc
= smb311_posix_get_inode_info(&newinode
, full_path
,
628 NULL
, inode
->i_sb
, xid
);
629 } else if (pTcon
->unix_ext
) {
630 rc
= cifs_get_inode_info_unix(&newinode
, full_path
,
633 rc
= cifs_get_inode_info(&newinode
, full_path
, NULL
,
634 inode
->i_sb
, xid
, NULL
);
638 cifs_dbg(FYI
, "Create symlink ok, getinodeinfo fail rc = %d\n",
641 d_instantiate(direntry
, newinode
);
645 free_dentry_path(page
);
646 cifs_put_tlink(tlink
);